diff options
author | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-11 23:25:21 +0000 |
---|---|---|
committer | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-11 23:25:21 +0000 |
commit | 55a356908083c25a2829db1636564c50c57b430f (patch) | |
tree | 1fa448b284205c57f594ca34b175db202af1aec1 /chrome/browser | |
parent | 6149d3e3ba96cc4aac419777094a1e090b0825e9 (diff) | |
download | chromium_src-55a356908083c25a2829db1636564c50c57b430f.zip chromium_src-55a356908083c25a2829db1636564c50c57b430f.tar.gz chromium_src-55a356908083c25a2829db1636564c50c57b430f.tar.bz2 |
Initial work on making extensions work in incognito mode.
This merely adds a way to enable content scripts and browser actions in incognito windows. They still don't work properly because none of the APIs work with incognito tabs.
The way to enable an extension is to add an "incognito" bit in the user prefs file. My plan is to add UI for this later.
BUG=32365
Review URL: http://codereview.chromium.org/567037
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@38852 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
21 files changed, 333 insertions, 78 deletions
diff --git a/chrome/browser/cocoa/extensions/browser_actions_controller.mm b/chrome/browser/cocoa/extensions/browser_actions_controller.mm index cc73d61..c3cd111 100644 --- a/chrome/browser/cocoa/extensions/browser_actions_controller.mm +++ b/chrome/browser/cocoa/extensions/browser_actions_controller.mm @@ -30,6 +30,7 @@ NSString* const kBrowserActionsChangedNotification = @"BrowserActionsChanged"; - (void)removeActionButtonForExtension:(Extension*)extension; - (void)repositionActionButtons; - (int)currentTabId; +- (bool)shouldDisplayBrowserAction:(Extension*)extension; @end // A helper class to proxy extension notifications to the view controller's @@ -139,6 +140,9 @@ class ExtensionsServiceObserverBridge : public NotificationObserver, if (!extension->browser_action()) return; + if (![self shouldDisplayBrowserAction:extension]) + return; + // Show the container if it's the first button. Otherwise it will be shown // already. if ([buttons_ count] == 0) @@ -266,4 +270,10 @@ class ExtensionsServiceObserverBridge : public NotificationObserver, return [buttonOrder_ objectAtIndex:(NSUInteger)index]; } +- (bool)shouldDisplayBrowserAction:(Extension*)extension { + return (!profile_->IsOffTheRecord() || + profile_->GetExtensionsService()-> + IsIncognitoEnabled(extension->id())); +} + @end diff --git a/chrome/browser/extensions/browser_action_apitest.cc b/chrome/browser/extensions/browser_action_apitest.cc index eafa655..a8cd84c 100644 --- a/chrome/browser/extensions/browser_action_apitest.cc +++ b/chrome/browser/extensions/browser_action_apitest.cc @@ -19,7 +19,9 @@ #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension_action.h" +#include "chrome/common/url_constants.h" #include "chrome/test/ui_test_utils.h" static const int kTimeoutMs = 60 * 1000; // 1 minute @@ -44,6 +46,9 @@ class BrowserActionApiTest : public ExtensionApiTest { }; IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, Basic) { + CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableExperimentalExtensionApis); + StartHTTPServer(); ASSERT_TRUE(RunExtensionTest("browser_action/basics")) << message_; Extension* extension = GetSingleLoadedExtension(); @@ -143,6 +148,9 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, TabSpecificBrowserActionState) { } IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, BrowserActionPopup) { + CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableExperimentalExtensionApis); + ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII( "browser_action/popup"))); Extension* extension = GetSingleLoadedExtension(); @@ -176,6 +184,9 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, BrowserActionPopup) { // Test that calling chrome.browserAction.setPopup() can enable and change // a popup. IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, BrowserActionAddPopup) { + CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableExperimentalExtensionApis); + ASSERT_TRUE(RunExtensionTest("browser_action/add_popup")) << message_; Extension* extension = GetSingleLoadedExtension(); ASSERT_TRUE(extension) << message_; @@ -261,3 +272,114 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, BrowserActionRemovePopup) { << "Browser action popup default should not be changed by setting " << "a specific tab id."; } + +IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, IncognitoBasic) { + CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableExperimentalExtensionApis); + + StartHTTPServer(); + + ASSERT_TRUE(RunExtensionTest("browser_action/basics")) << message_; + Extension* extension = GetSingleLoadedExtension(); + ASSERT_TRUE(extension) << message_; + + // Test that there is a browser action in the toolbar. + ASSERT_EQ(1, GetBrowserActionsBar().NumberOfBrowserActions()); + + // Open an incognito window and test that the browser action isn't there by + // default. + Profile* incognito_profile = browser()->profile()->GetOffTheRecordProfile(); + Browser* incognito_browser = Browser::Create(incognito_profile); + + ASSERT_EQ(0, + BrowserActionTestUtil(incognito_browser).NumberOfBrowserActions()); + + // Now enable the extension in incognito mode, and test that the browser + // action shows up. Note that we don't update the existing window at the + // moment, so we just create a new one. + browser()->profile()->GetExtensionsService()->extension_prefs()-> + SetIsIncognitoEnabled(extension->id(), true); + + incognito_browser->CloseWindow(); + incognito_browser = Browser::Create(incognito_profile); + ASSERT_EQ(1, + BrowserActionTestUtil(incognito_browser).NumberOfBrowserActions()); + + // TODO(mpcomplete): simulate a click and have it do the right thing in + // incognito. +} + +// TODO(mpcomplete): enable this when Mac gets dragging support. +#if defined(OS_MACOSX) +IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, DISABLED_IncognitoDragging) { +#else +IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, IncognitoDragging) { +#endif + ExtensionsService* service = browser()->profile()->GetExtensionsService(); + + CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableExperimentalExtensionApis); + + // The tooltips for each respective browser action. + const char kTooltipA[] = "Make this page red"; + const char kTooltipB[] = "grow"; + const char kTooltipC[] = "Test setPopup()"; + ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII( + "browser_action/basics"))); + ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII( + "browser_action/popup"))); + ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII( + "browser_action/add_popup"))); + + // Test that there are 3 browser actions in the toolbar. + ASSERT_EQ(3u, service->extensions()->size()); + ASSERT_EQ(3, GetBrowserActionsBar().NumberOfBrowserActions()); + + // Now enable 2 of the extensions in incognito mode, and test that the browser + // actions show up. + service->extension_prefs()->SetIsIncognitoEnabled( + service->extensions()->at(0)->id(), true); + service->extension_prefs()->SetIsIncognitoEnabled( + service->extensions()->at(2)->id(), true); + + Profile* incognito_profile = browser()->profile()->GetOffTheRecordProfile(); + Browser* incognito_browser = Browser::Create(incognito_profile); + BrowserActionTestUtil incognito_bar(incognito_browser); + + // Navigate just to have a tab in this window, otherwise wonky things happen. + ui_test_utils::OpenURLOffTheRecord(browser()->profile(), + GURL(chrome::kChromeUIExtensionsURL)); + + ASSERT_EQ(2, incognito_bar.NumberOfBrowserActions()); + + // Ensure that the browser actions are in the right order (ABC). + EXPECT_EQ(kTooltipA, GetBrowserActionsBar().GetTooltip(0)); + EXPECT_EQ(kTooltipB, GetBrowserActionsBar().GetTooltip(1)); + EXPECT_EQ(kTooltipC, GetBrowserActionsBar().GetTooltip(2)); + + EXPECT_EQ(kTooltipA, incognito_bar.GetTooltip(0)); + EXPECT_EQ(kTooltipC, incognito_bar.GetTooltip(1)); + + // Now rearrange them and ensure that they are rearranged correctly in both + // regular and incognito mode. + + // ABC -> CAB + service->toolbar_model()->MoveBrowserAction(service->extensions()->at(2), 0); + + EXPECT_EQ(kTooltipC, GetBrowserActionsBar().GetTooltip(0)); + EXPECT_EQ(kTooltipA, GetBrowserActionsBar().GetTooltip(1)); + EXPECT_EQ(kTooltipB, GetBrowserActionsBar().GetTooltip(2)); + + EXPECT_EQ(kTooltipC, incognito_bar.GetTooltip(0)); + EXPECT_EQ(kTooltipA, incognito_bar.GetTooltip(1)); + + // CAB -> CBA + service->toolbar_model()->MoveBrowserAction(service->extensions()->at(1), 1); + + EXPECT_EQ(kTooltipC, GetBrowserActionsBar().GetTooltip(0)); + EXPECT_EQ(kTooltipB, GetBrowserActionsBar().GetTooltip(1)); + EXPECT_EQ(kTooltipA, GetBrowserActionsBar().GetTooltip(2)); + + EXPECT_EQ(kTooltipC, incognito_bar.GetTooltip(0)); + EXPECT_EQ(kTooltipA, incognito_bar.GetTooltip(1)); +} diff --git a/chrome/browser/extensions/browser_action_test_util_views.cc b/chrome/browser/extensions/browser_action_test_util_views.cc index 9af266d..c116f22 100644 --- a/chrome/browser/extensions/browser_action_test_util_views.cc +++ b/chrome/browser/extensions/browser_action_test_util_views.cc @@ -41,7 +41,7 @@ void BrowserActionTestUtil::Press(int index) { std::string BrowserActionTestUtil::GetTooltip(int index) { std::wstring text; - GetContainer(browser_)->GetBrowserActionViewAt(0)->button()-> + GetContainer(browser_)->GetBrowserActionViewAt(index)->button()-> GetTooltipText(0, 0, &text); return WideToUTF8(text); } diff --git a/chrome/browser/extensions/extension_prefs.cc b/chrome/browser/extensions/extension_prefs.cc index 6d92ad2..3aeda24 100644 --- a/chrome/browser/extensions/extension_prefs.cc +++ b/chrome/browser/extensions/extension_prefs.cc @@ -49,6 +49,10 @@ const wchar_t kExtensionToolbar[] = L"extensions.toolbar"; // server's perspective) an extension last included a "ping" parameter during // its update check. const wchar_t kLastPingDay[] = L"lastpingday"; + +// A preference that, if true, will allow this extension to run in incognito +// mode. +const wchar_t kPrefIncognitoEnabled[] = L"incognito"; } //////////////////////////////////////////////////////////////////////////////// @@ -257,6 +261,16 @@ void ExtensionPrefs::SetLastPingDay(const std::string& extension_id, prefs_->ScheduleSavePersistentPrefs(); } +bool ExtensionPrefs::IsIncognitoEnabled(const std::string& extension_id) { + return ReadExtensionPrefBoolean(extension_id, kPrefIncognitoEnabled); +} + +void ExtensionPrefs::SetIsIncognitoEnabled(const std::string& extension_id, + bool enabled) { + UpdateExtensionPref(extension_id, kPrefIncognitoEnabled, + Value::CreateBooleanValue(enabled)); + prefs_->SavePersistentPrefs(); +} void ExtensionPrefs::GetKilledExtensionIds(std::set<std::string>* killed_ids) { const DictionaryValue* dict = prefs_->GetDictionary(kExtensionsPref); diff --git a/chrome/browser/extensions/extension_prefs.h b/chrome/browser/extensions/extension_prefs.h index d8d3694..77f64901 100644 --- a/chrome/browser/extensions/extension_prefs.h +++ b/chrome/browser/extensions/extension_prefs.h @@ -94,6 +94,10 @@ class ExtensionPrefs { // the client's. void SetLastPingDay(const std::string& extension_id, const base::Time& time); + // Returns true if the user enabled this extension to be loaded in incognito + // mode. + bool IsIncognitoEnabled(const std::string& extension_id); + void SetIsIncognitoEnabled(const std::string& extension_id, bool enabled); // Saves ExtensionInfo for each installed extension with the path to the // version directory and the location. Blacklisted extensions won't be saved diff --git a/chrome/browser/extensions/extension_toolbar_model.cc b/chrome/browser/extensions/extension_toolbar_model.cc index 4c9bd39..f243949 100644 --- a/chrome/browser/extensions/extension_toolbar_model.cc +++ b/chrome/browser/extensions/extension_toolbar_model.cc @@ -187,3 +187,28 @@ void ExtensionToolbarModel::UpdatePrefs() { ids.push_back((*iter)->id()); service_->extension_prefs()->SetToolbarOrder(ids); } + +int ExtensionToolbarModel::IncognitoIndexToOriginal(int incognito_index) { + int original_index = 0, i = 0; + for (ExtensionList::iterator iter = begin(); iter != end(); + ++iter, ++original_index) { + if (service_->IsIncognitoEnabled((*iter)->id())) { + if (incognito_index == i) + break; + ++i; + } + } + return original_index; +} + +int ExtensionToolbarModel::OriginalIndexToIncognito(int original_index) { + int incognito_index = 0, i = 0; + for (ExtensionList::iterator iter = begin(); iter != end(); + ++iter, ++i) { + if (original_index == i) + break; + if (service_->IsIncognitoEnabled((*iter)->id())) + ++incognito_index; + } + return incognito_index; +} diff --git a/chrome/browser/extensions/extension_toolbar_model.h b/chrome/browser/extensions/extension_toolbar_model.h index 1718050..a4c7855 100644 --- a/chrome/browser/extensions/extension_toolbar_model.h +++ b/chrome/browser/extensions/extension_toolbar_model.h @@ -50,6 +50,11 @@ class ExtensionToolbarModel : public NotificationObserver { return toolitems_.end(); } + // Utility functions for converting between an index into the list of + // incognito-enabled browser actions, and the list of all browser actions. + int IncognitoIndexToOriginal(int incognito_index); + int OriginalIndexToIncognito(int original_index); + private: // NotificationObserver implementation. virtual void Observe(NotificationType type, diff --git a/chrome/browser/extensions/extension_toolbar_model_unittest.cc b/chrome/browser/extensions/extension_toolbar_model_unittest.cc index 79b9efb..031672e 100644 --- a/chrome/browser/extensions/extension_toolbar_model_unittest.cc +++ b/chrome/browser/extensions/extension_toolbar_model_unittest.cc @@ -7,6 +7,7 @@ #include "chrome/browser/extensions/extension_toolbar_model.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/profile.h" +#include "chrome/common/chrome_switches.h" #include "chrome/test/in_process_browser_test.h" // An InProcessBrowserTest for testing the ExtensionToolbarModel. @@ -65,6 +66,9 @@ class ExtensionToolbarModelTest : public ExtensionBrowserTest, }; IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest, Basic) { + CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableExperimentalExtensionApis); + // Load an extension with no browser action. ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test") .AppendASCII("browser_action") @@ -102,6 +106,9 @@ IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest, Basic) { } IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest, ReorderAndReinsert) { + CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableExperimentalExtensionApis); + // Load an extension with a browser action. FilePath extension_a_path(test_data_dir_.AppendASCII("api_test") .AppendASCII("browser_action") diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc index 7dddfa9..476f640 100644 --- a/chrome/browser/extensions/extensions_service.cc +++ b/chrome/browser/extensions/extensions_service.cc @@ -529,6 +529,16 @@ base::Time ExtensionsService::LastPingDay(const std::string& extension_id) { return extension_prefs_->LastPingDay(extension_id); } +bool ExtensionsService::IsIncognitoEnabled(const std::string& extension_id) { + Extension* extension = GetExtensionById(extension_id, true); + if (!extension) + return false; + + return extension_prefs_->IsIncognitoEnabled(extension_id) && + extension->HasApiPermission(Extension::kExperimentalPermission) && + extension->HasApiPermission(Extension::kIncognitoPermission); +} + void ExtensionsService::CheckForExternalUpdates() { // This installs or updates externally provided extensions. // TODO(aa): Why pass this list into the provider, why not just filter it diff --git a/chrome/browser/extensions/extensions_service.h b/chrome/browser/extensions/extensions_service.h index 5b4d37e..078ac01 100644 --- a/chrome/browser/extensions/extensions_service.h +++ b/chrome/browser/extensions/extensions_service.h @@ -106,6 +106,10 @@ class ExtensionsService const base::Time& time); virtual base::Time LastPingDay(const std::string& extension_id); + // Returns true if this extension can run in an incognito window. The + // decision is based on both user consent and the extension having the right + // permission. + bool IsIncognitoEnabled(const std::string& extension_id); const FilePath& install_directory() const { return install_directory_; } diff --git a/chrome/browser/extensions/incognito_noscript_apitest.cc b/chrome/browser/extensions/incognito_noscript_apitest.cc index fa78e67..1a63d88 100755 --- a/chrome/browser/extensions/incognito_noscript_apitest.cc +++ b/chrome/browser/extensions/incognito_noscript_apitest.cc @@ -6,8 +6,11 @@ #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/extensions/extension_browsertest.h" +#include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/extensions/user_script_master.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/url_constants.h" #include "chrome/test/ui_test_utils.h" #include "net/base/mock_host_resolver.h" @@ -18,28 +21,50 @@ IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, IncognitoNoScript) { // Loads a simple extension which attempts to change the title of every page // that loads to "modified". + CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableExperimentalExtensionApis); FilePath extension_path = test_data_dir_.AppendASCII("api_test") .AppendASCII("incognito_no_script"); ASSERT_TRUE(LoadExtension(extension_path)); // Open incognito window and navigate to test page. - Browser::OpenURLOffTheRecord(browser()->profile(), - GURL("http://www.foo.com:1337/files/extensions/test_file.html")); - Profile* off_the_record_profile = - browser()->profile()->GetOffTheRecordProfile(); - Browser* otr_browser = Browser::Create(off_the_record_profile); - otr_browser->AddTabWithURL( - GURL("http://www.foo.com:1337/files/extensions/test_file.html"), - GURL(), - PageTransition::LINK, - true, - -1, - false, - NULL); - otr_browser->window()->Show(); - ui_test_utils::WaitForNavigationInCurrentTab(otr_browser); + ui_test_utils::OpenURLOffTheRecord(browser()->profile(), + GURL("http://www.example.com:1337/files/extensions/test_file.html")); + Browser* otr_browser = BrowserList::FindBrowserWithType( + browser()->profile()->GetOffTheRecordProfile(), Browser::TYPE_NORMAL); string16 title; ui_test_utils::GetCurrentTabTitle(otr_browser, &title); ASSERT_EQ("Unmodified", UTF16ToASCII(title)); } + +IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, IncognitoYesScript) { + host_resolver()->AddRule("*", "127.0.0.1"); + StartHTTPServer(); + + // Loads a simple extension which attempts to change the title of every page + // that loads to "modified". + CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableExperimentalExtensionApis); + FilePath extension_path = test_data_dir_.AppendASCII("api_test") + .AppendASCII("incognito_no_script"); + ASSERT_TRUE(LoadExtension(extension_path)); + + // Now enable the extension in incognito mode, and ensure that page titles + // are modified. + ExtensionsService* service = browser()->profile()->GetExtensionsService(); + service->extension_prefs()->SetIsIncognitoEnabled( + service->extensions()->at(0)->id(), true); + browser()->profile()->GetUserScriptMaster()->ReloadExtensionForTesting( + service->extensions()->at(0)); + + // Open incognito window and navigate to test page. + ui_test_utils::OpenURLOffTheRecord(browser()->profile(), + GURL("http://www.example.com:1337/files/extensions/test_file.html")); + Browser* otr_browser = BrowserList::FindBrowserWithType( + browser()->profile()->GetOffTheRecordProfile(), Browser::TYPE_NORMAL); + + string16 title; + ui_test_utils::GetCurrentTabTitle(otr_browser, &title); + ASSERT_EQ("modified", UTF16ToASCII(title)); +} diff --git a/chrome/browser/extensions/user_script_master.cc b/chrome/browser/extensions/user_script_master.cc index 3478b68..a7d69f6 100644 --- a/chrome/browser/extensions/user_script_master.cc +++ b/chrome/browser/extensions/user_script_master.cc @@ -16,6 +16,7 @@ #include "base/thread.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/profile.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/notification_service.h" #include "chrome/common/url_constants.h" @@ -333,17 +334,15 @@ void UserScriptMaster::Observe(NotificationType type, StartScan(); break; case NotificationType::EXTENSION_LOADED: { - // TODO(aa): Fix race here. A page could need a content script on startup, - // before the extension has loaded. We need to freeze the renderer in - // that case. - // See: http://code.google.com/p/chromium/issues/detail?id=11547. - // Add any content scripts inside the extension. Extension* extension = Details<Extension>(details).ptr(); + bool incognito_enabled = profile_->GetExtensionsService()-> + IsIncognitoEnabled(extension->id()); const UserScriptList& scripts = extension->content_scripts(); for (UserScriptList::const_iterator iter = scripts.begin(); iter != scripts.end(); ++iter) { lone_scripts_.push_back(*iter); + lone_scripts_.back().set_incognito_enabled(incognito_enabled); } if (extensions_service_ready_) StartScan(); @@ -379,3 +378,14 @@ void UserScriptMaster::StartScan() { script_reloader_->StartScan(user_script_dir_, lone_scripts_); } + +void UserScriptMaster::ReloadExtensionForTesting(Extension* extension) { + bool incognito_enabled = profile_->GetExtensionsService()-> + IsIncognitoEnabled(extension->id()); + for (UserScriptList::iterator iter = lone_scripts_.begin(); + iter != lone_scripts_.end(); ++iter) { + if (iter->extension_id() == extension->id()) + (*iter).set_incognito_enabled(incognito_enabled); + } + StartScan(); +} diff --git a/chrome/browser/extensions/user_script_master.h b/chrome/browser/extensions/user_script_master.h index 0423305..19562f0 100644 --- a/chrome/browser/extensions/user_script_master.h +++ b/chrome/browser/extensions/user_script_master.h @@ -17,6 +17,7 @@ namespace base { class StringPiece; } +class Extension; class Profile; // Manages a segment of shared memory that contains the user scripts the user @@ -46,6 +47,11 @@ class UserScriptMaster : public base::RefCountedThreadSafe<UserScriptMaster>, // Returns the path to the directory user scripts are stored in. FilePath user_script_dir() const { return user_script_dir_; } + // Note: this is only for testing. This will reload the scripts associated + // with the given extension. This is only temporary until we get better + // machinery in place for toggling incognito-enabled extensions. + void ReloadExtensionForTesting(Extension* extension); + protected: friend class base::RefCountedThreadSafe<UserScriptMaster>; diff --git a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc b/chrome/browser/gtk/browser_actions_toolbar_gtk.cc index ef115be..c1921cd 100644 --- a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc +++ b/chrome/browser/gtk/browser_actions_toolbar_gtk.cc @@ -332,6 +332,12 @@ void BrowserActionsToolbarGtk::CreateAllButtons() { void BrowserActionsToolbarGtk::CreateButtonForExtension(Extension* extension, int index) { + if (!ShouldDisplayBrowserAction(extension)) + return; + + if (profile_->IsOffTheRecord()) + index = model_->OriginalIndexToIncognito(index); + RemoveButtonForExtension(extension); linked_ptr<BrowserActionButton> button( new BrowserActionButton(this, extension)); @@ -374,6 +380,14 @@ void BrowserActionsToolbarGtk::UpdateVisibility() { gtk_widget_show(widget()); } +bool BrowserActionsToolbarGtk::ShouldDisplayBrowserAction( + Extension* extension) { + // Only display incognito-enabled extensions while in incognito mode. + return (!profile_->IsOffTheRecord() || + profile_->GetExtensionsService()-> + IsIncognitoEnabled(extension->id())); +} + void BrowserActionsToolbarGtk::HidePopup() { ExtensionPopupGtk* popup = ExtensionPopupGtk::get_current_extension_popup(); if (popup) @@ -402,10 +416,14 @@ void BrowserActionsToolbarGtk::BrowserActionMoved(Extension* extension, BrowserActionButton* button = extension_button_map_[extension->id()].get(); if (!button) { - NOTREACHED(); + if (ShouldDisplayBrowserAction(extension)) + NOTREACHED(); return; } + if (profile_->IsOffTheRecord()) + index = model_->OriginalIndexToIncognito(index); + gtk_box_reorder_child(GTK_BOX(hbox_.get()), button->widget(), index); } @@ -428,6 +446,9 @@ gboolean BrowserActionsToolbarGtk::OnDragMotion(GtkWidget* widget, return FALSE; drop_index_ = x < kButtonSize ? 0 : x / (kButtonSize + kButtonPadding); + if (profile_->IsOffTheRecord()) + drop_index_ = model_->IncognitoIndexToOriginal(drop_index_); + // We will go ahead and reorder the child in order to provide visual feedback // to the user. We don't inform the model that it has moved until the drag // ends. diff --git a/chrome/browser/gtk/browser_actions_toolbar_gtk.h b/chrome/browser/gtk/browser_actions_toolbar_gtk.h index 39daf78..1356320 100644 --- a/chrome/browser/gtk/browser_actions_toolbar_gtk.h +++ b/chrome/browser/gtk/browser_actions_toolbar_gtk.h @@ -69,6 +69,11 @@ class BrowserActionsToolbarGtk : public ExtensionToolbarModel::Observer { // Hide the extension popup, if any. void HidePopup(); + // Returns true if this extension should be shown in this toolbar. This can + // return false if we are in an incognito window and the extension is disabled + // for incognito. + bool ShouldDisplayBrowserAction(Extension* extension); + // ExtensionToolbarModel::Observer implementation. virtual void BrowserActionAdded(Extension* extension, int index); virtual void BrowserActionRemoved(Extension* extension); diff --git a/chrome/browser/net/chrome_url_request_context.cc b/chrome/browser/net/chrome_url_request_context.cc index e206121..3faa8d3 100644 --- a/chrome/browser/net/chrome_url_request_context.cc +++ b/chrome/browser/net/chrome_url_request_context.cc @@ -283,32 +283,6 @@ ChromeURLRequestContext* FactoryForOffTheRecord::Create() { return context; } -// Factory that creates the ChromeURLRequestContext for extensions in incognito -// mode. -class FactoryForOffTheRecordExtensions - : public ChromeURLRequestContextFactory { - public: - explicit FactoryForOffTheRecordExtensions(Profile* profile) - : ChromeURLRequestContextFactory(profile) {} - - virtual ChromeURLRequestContext* Create(); -}; - -ChromeURLRequestContext* FactoryForOffTheRecordExtensions::Create() { - ChromeURLRequestContext* context = new ChromeURLRequestContext; - ApplyProfileParametersToContext(context); - - net::CookieMonster* cookie_monster = new net::CookieMonster(NULL); - - // Enable cookies for extension URLs only. - const char* schemes[] = {chrome::kExtensionScheme}; - cookie_monster->SetCookieableSchemes(schemes, 1); - context->set_cookie_store(cookie_monster); - // No dynamic cookie policy for extensions. - - return context; -} - // Factory that creates the ChromeURLRequestContext for media. class FactoryForMedia : public ChromeURLRequestContextFactory { public: @@ -501,16 +475,6 @@ ChromeURLRequestContextGetter::CreateOffTheRecord(Profile* profile) { profile, new FactoryForOffTheRecord(profile)); } -// static -ChromeURLRequestContextGetter* -ChromeURLRequestContextGetter::CreateOffTheRecordForExtensions( - Profile* profile) { - DCHECK(profile->IsOffTheRecord()); - return new ChromeURLRequestContextGetter( - profile, - new FactoryForOffTheRecordExtensions(profile)); -} - void ChromeURLRequestContextGetter::CleanupOnUIThread() { CheckCurrentlyOnMainThread(); diff --git a/chrome/browser/net/chrome_url_request_context.h b/chrome/browser/net/chrome_url_request_context.h index 99aed21..df9b64a 100644 --- a/chrome/browser/net/chrome_url_request_context.h +++ b/chrome/browser/net/chrome_url_request_context.h @@ -280,10 +280,6 @@ class ChromeURLRequestContextGetter : public URLRequestContextGetter, // called on the UI thread. static ChromeURLRequestContextGetter* CreateOffTheRecord(Profile* profile); - // Create an instance of request context for OTR profile for extensions. - static ChromeURLRequestContextGetter* CreateOffTheRecordForExtensions( - Profile* profile); - // Clean up UI thread resources. This is expected to get called on the UI // thread before the instance is deleted on the IO thread. void CleanupOnUIThread(); diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc index a1594b2..a83ad4a 100644 --- a/chrome/browser/profile.cc +++ b/chrome/browser/profile.cc @@ -196,7 +196,6 @@ class OffTheRecordProfileImpl : public Profile, public: explicit OffTheRecordProfileImpl(Profile* real_profile) : profile_(real_profile), - extensions_request_context_(NULL), start_time_(Time::Now()) { request_context_ = ChromeURLRequestContextGetter::CreateOffTheRecord(this); @@ -209,7 +208,6 @@ class OffTheRecordProfileImpl : public Profile, virtual ~OffTheRecordProfileImpl() { CleanupRequestContext(request_context_); - CleanupRequestContext(extensions_request_context_); } virtual ProfileId GetRuntimeId() { @@ -248,23 +246,25 @@ class OffTheRecordProfileImpl : public Profile, } virtual ExtensionsService* GetExtensionsService() { - return NULL; + return GetOriginalProfile()->GetExtensionsService(); } virtual UserScriptMaster* GetUserScriptMaster() { - return NULL; + return GetOriginalProfile()->GetUserScriptMaster(); } virtual ExtensionDevToolsManager* GetExtensionDevToolsManager() { + // TODO(mpcomplete): figure out whether we should return the original + // profile's version. return NULL; } virtual ExtensionProcessManager* GetExtensionProcessManager() { - return NULL; + return GetOriginalProfile()->GetExtensionProcessManager(); } virtual ExtensionMessageService* GetExtensionMessageService() { - return NULL; + return GetOriginalProfile()->GetExtensionMessageService(); } virtual SSLHostState* GetSSLHostState() { @@ -389,12 +389,7 @@ class OffTheRecordProfileImpl : public Profile, } URLRequestContextGetter* GetRequestContextForExtensions() { - if (!extensions_request_context_) { - extensions_request_context_ = - ChromeURLRequestContextGetter::CreateOffTheRecordForExtensions(this); - } - - return extensions_request_context_; + return GetOriginalProfile()->GetRequestContextForExtensions(); } virtual net::SSLConfigService* GetSSLConfigService() { @@ -527,8 +522,6 @@ class OffTheRecordProfileImpl : public Profile, // The context to use for requests made from this OTR session. scoped_refptr<ChromeURLRequestContextGetter> request_context_; - scoped_refptr<ChromeURLRequestContextGetter> extensions_request_context_; - // The download manager that only stores downloaded items in memory. scoped_refptr<DownloadManager> download_manager_; diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc index f567b99..1822c07 100644 --- a/chrome/browser/renderer_host/browser_render_process_host.cc +++ b/chrome/browser/renderer_host/browser_render_process_host.cc @@ -622,7 +622,8 @@ void BrowserRenderProcessHost::SendUserScriptsUpdate( } if (base::SharedMemory::IsHandleValid(handle_for_process)) { - Send(new ViewMsg_UserScripts_UpdatedScripts(handle_for_process)); + Send(new ViewMsg_UserScripts_UpdatedScripts(handle_for_process, + profile()->IsOffTheRecord())); } } diff --git a/chrome/browser/views/browser_actions_container.cc b/chrome/browser/views/browser_actions_container.cc index d089a40..5a1ae90 100644 --- a/chrome/browser/views/browser_actions_container.cc +++ b/chrome/browser/views/browser_actions_container.cc @@ -450,6 +450,9 @@ void BrowserActionsContainer::CreateBrowserActionViews() { DCHECK(browser_action_views_.empty()); for (ExtensionList::iterator iter = model_->begin(); iter != model_->end(); ++iter) { + if (!ShouldDisplayBrowserAction(*iter)) + continue; + BrowserActionView* view = new BrowserActionView(*iter, this); browser_action_views_.push_back(view); AddChildView(view); @@ -673,6 +676,7 @@ void BrowserActionsContainer::ViewHierarchyChanged(bool is_add, bool BrowserActionsContainer::GetDropFormats( int* formats, std::set<OSExchangeData::CustomFormat>* custom_formats) { custom_formats->insert(BrowserActionDragData::GetBrowserActionCustomFormat()); + return true; } @@ -771,6 +775,9 @@ int BrowserActionsContainer::OnPerformDrop( if (i > data.index()) --i; + if (profile_->IsOffTheRecord()) + i = model_->IncognitoIndexToOriginal(i); + model_->MoveBrowserAction(dragging, i); OnDragExited(); // Perform clean up after dragging. @@ -933,6 +940,12 @@ void BrowserActionsContainer::BrowserActionAdded(Extension* extension, CloseMenus(); + if (!ShouldDisplayBrowserAction(extension)) + return; + + if (profile_->IsOffTheRecord()) + index = model_->OriginalIndexToIncognito(index); + // Before we change anything, determine the number of visible browser actions. size_t visible_actions = VisibleBrowserActions(); @@ -1011,6 +1024,12 @@ void BrowserActionsContainer::BrowserActionRemoved(Extension* extension) { void BrowserActionsContainer::BrowserActionMoved(Extension* extension, int index) { + if (!ShouldDisplayBrowserAction(extension)) + return; + + if (profile_->IsOffTheRecord()) + index = model_->OriginalIndexToIncognito(index); + DCHECK(index >= 0 && index < static_cast<int>(browser_action_views_.size())); DeleteBrowserActionViews(); @@ -1104,3 +1123,10 @@ void BrowserActionsContainer::NotifyMenuDeleted( DCHECK(controller == overflow_menu_); overflow_menu_ = NULL; } + +bool BrowserActionsContainer::ShouldDisplayBrowserAction(Extension* extension) { + // Only display incognito-enabled extensions while in incognito mode. + return (!profile_->IsOffTheRecord() || + profile_->GetExtensionsService()-> + IsIncognitoEnabled(extension->id())); +} diff --git a/chrome/browser/views/browser_actions_container.h b/chrome/browser/views/browser_actions_container.h index a7a5b59ac..1ace12d 100644 --- a/chrome/browser/views/browser_actions_container.h +++ b/chrome/browser/views/browser_actions_container.h @@ -399,7 +399,14 @@ class BrowserActionsContainer // all the padding that we normally show if there are icons. int ContainerMinSize() const; - // The vector of browser actions (icons/image buttons for each action). + // Returns true if this extension should be shown in this toolbar. This can + // return false if we are in an incognito window and the extension is disabled + // for incognito. + bool ShouldDisplayBrowserAction(Extension* extension); + + // The vector of browser actions (icons/image buttons for each action). Note + // that not every BrowserAction in the ToolbarModel will necessarily be in + // this collection. Some extensions may be disabled in incognito windows. BrowserActionViews browser_action_views_; NotificationRegistrar registrar_; |