summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/automation/automation_provider_win.cc2
-rw-r--r--chrome/browser/browser.cc15
-rw-r--r--chrome/browser/cocoa/extensions/extension_popup_controller_unittest.mm2
-rw-r--r--chrome/browser/dom_ui/dom_ui_factory.cc3
-rw-r--r--chrome/browser/extensions/extension_accessibility_api.cc2
-rw-r--r--chrome/browser/extensions/extension_apitest.cc8
-rw-r--r--chrome/browser/extensions/extension_apitest.h5
-rw-r--r--chrome/browser/extensions/extension_bookmark_manager_api.cc2
-rw-r--r--chrome/browser/extensions/extension_bookmarks_module.cc2
-rw-r--r--chrome/browser/extensions/extension_browser_event_router.cc2
-rw-r--r--chrome/browser/extensions/extension_cookies_api.cc6
-rw-r--r--chrome/browser/extensions/extension_cookies_helpers.cc6
-rw-r--r--chrome/browser/extensions/extension_cookies_unittest.cc6
-rw-r--r--chrome/browser/extensions/extension_devtools_bridge.cc4
-rw-r--r--chrome/browser/extensions/extension_function.h5
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.cc25
-rw-r--r--chrome/browser/extensions/extension_history_api.cc2
-rw-r--r--chrome/browser/extensions/extension_idle_api.cc5
-rw-r--r--chrome/browser/extensions/extension_incognito_apitest.cc25
-rw-r--r--chrome/browser/extensions/extension_management_api.cc2
-rw-r--r--chrome/browser/extensions/extension_menu_manager.cc3
-rw-r--r--chrome/browser/extensions/extension_menu_manager_unittest.cc8
-rw-r--r--chrome/browser/extensions/extension_message_service.cc30
-rw-r--r--chrome/browser/extensions/extension_message_service.h4
-rw-r--r--chrome/browser/extensions/extension_messages_apitest.cc8
-rw-r--r--chrome/browser/extensions/extension_omnibox_api.cc12
-rw-r--r--chrome/browser/extensions/extension_popup_api.cc5
-rw-r--r--chrome/browser/extensions/extension_process_manager.cc168
-rw-r--r--chrome/browser/extensions/extension_process_manager.h39
-rw-r--r--chrome/browser/extensions/extension_process_manager_unittest.cc4
-rw-r--r--chrome/browser/extensions/extension_protocols.cc3
-rw-r--r--chrome/browser/extensions/extension_sidebar_api.cc3
-rw-r--r--chrome/browser/extensions/extension_ui_unittest.cc4
-rw-r--r--chrome/browser/extensions/extensions_service.cc11
-rw-r--r--chrome/browser/extensions/extensions_ui.cc48
-rw-r--r--chrome/browser/extensions/extensions_ui.h12
-rw-r--r--chrome/browser/net/chrome_url_request_context.cc42
-rw-r--r--chrome/browser/net/chrome_url_request_context.h19
-rw-r--r--chrome/browser/profile.cc18
-rw-r--r--chrome/browser/profile_impl.cc32
-rw-r--r--chrome/browser/resources/extensions_ui.html20
-rw-r--r--chrome/browser/task_manager_resource_providers.cc30
-rw-r--r--chrome/browser/views/location_bar/icon_label_bubble_view.cc7
-rw-r--r--chrome/browser/views/location_bar/icon_label_bubble_view.h3
-rw-r--r--chrome/browser/views/location_bar/location_bar_view.cc3
-rw-r--r--chrome/browser/views/location_bar/location_bar_view.h3
46 files changed, 494 insertions, 174 deletions
diff --git a/chrome/browser/automation/automation_provider_win.cc b/chrome/browser/automation/automation_provider_win.cc
index 23e8e3d..41994e8 100644
--- a/chrome/browser/automation/automation_provider_win.cc
+++ b/chrome/browser/automation/automation_provider_win.cc
@@ -487,7 +487,7 @@ bool AutomationProvider::InterceptBrowserEventMessageFromExternalHost(
if (profile()->GetExtensionMessageService()) {
profile()->GetExtensionMessageService()->DispatchEventToRenderers(
- event_name, json_args, profile()->IsOffTheRecord(), GURL());
+ event_name, json_args, profile(), GURL());
}
return true;
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc
index ebcf1da..85cf378 100644
--- a/chrome/browser/browser.cc
+++ b/chrome/browser/browser.cc
@@ -3052,13 +3052,14 @@ void Browser::Observe(NotificationType type,
case NotificationType::EXTENSION_UPDATE_DISABLED: {
// Show the UI if the extension was disabled for escalated permissions.
Profile* profile = Source<Profile>(source).ptr();
- DCHECK_EQ(profile_, profile);
- ExtensionsService* service = profile->GetExtensionsService();
- DCHECK(service);
- Extension* extension = Details<Extension>(details).ptr();
- if (service->extension_prefs()->DidExtensionEscalatePermissions(
- extension->id()))
- ShowExtensionDisabledUI(service, profile_, extension);
+ if (profile_->IsSameProfile(profile)) {
+ ExtensionsService* service = profile->GetExtensionsService();
+ DCHECK(service);
+ Extension* extension = Details<Extension>(details).ptr();
+ if (service->extension_prefs()->DidExtensionEscalatePermissions(
+ extension->id()))
+ ShowExtensionDisabledUI(service, profile_, extension);
+ }
break;
}
diff --git a/chrome/browser/cocoa/extensions/extension_popup_controller_unittest.mm b/chrome/browser/cocoa/extensions/extension_popup_controller_unittest.mm
index 235d85b..110f719 100644
--- a/chrome/browser/cocoa/extensions/extension_popup_controller_unittest.mm
+++ b/chrome/browser/cocoa/extensions/extension_popup_controller_unittest.mm
@@ -24,7 +24,7 @@ class ExtensionTestingProfile : public TestingProfile {
DCHECK(!GetExtensionProcessManager());
DCHECK(!GetExtensionsService());
- manager_.reset(new ExtensionProcessManager(this));
+ manager_.reset(ExtensionProcessManager::Create(this));
service_ = new ExtensionsService(this,
CommandLine::ForCurrentProcess(),
GetPrefs(),
diff --git a/chrome/browser/dom_ui/dom_ui_factory.cc b/chrome/browser/dom_ui/dom_ui_factory.cc
index 96f8b8a..524059b 100644
--- a/chrome/browser/dom_ui/dom_ui_factory.cc
+++ b/chrome/browser/dom_ui/dom_ui_factory.cc
@@ -59,8 +59,7 @@ DOMUI* NewDOMUI<ExtensionDOMUI>(TabContents* contents, const GURL& url) {
// within a single process.
ExtensionsService* service = contents->profile()->GetExtensionsService();
if (service &&
- service->ExtensionBindingsAllowed(url) &&
- !contents->profile()->IsOffTheRecord()) {
+ service->ExtensionBindingsAllowed(url)) {
return new ExtensionDOMUI(contents, url);
}
return NULL;
diff --git a/chrome/browser/extensions/extension_accessibility_api.cc b/chrome/browser/extensions/extension_accessibility_api.cc
index 760869a..bf310f2 100644
--- a/chrome/browser/extensions/extension_accessibility_api.cc
+++ b/chrome/browser/extensions/extension_accessibility_api.cc
@@ -177,7 +177,7 @@ void ExtensionAccessibilityEventRouter::DispatchEvent(
const std::string& json_args) {
if (enabled_ && profile && profile->GetExtensionMessageService()) {
profile->GetExtensionMessageService()->DispatchEventToRenderers(
- event_name, json_args, profile->IsOffTheRecord(), GURL());
+ event_name, json_args, profile, GURL());
}
}
diff --git a/chrome/browser/extensions/extension_apitest.cc b/chrome/browser/extensions/extension_apitest.cc
index ba4da59..c5e1f54 100644
--- a/chrome/browser/extensions/extension_apitest.cc
+++ b/chrome/browser/extensions/extension_apitest.cc
@@ -11,7 +11,8 @@
#include "chrome/common/notification_registrar.h"
#include "chrome/test/ui_test_utils.h"
-ExtensionApiTest::ResultCatcher::ResultCatcher() {
+ExtensionApiTest::ResultCatcher::ResultCatcher()
+ : profile_restriction_(NULL) {
registrar_.Add(this, NotificationType::EXTENSION_TEST_PASSED,
NotificationService::AllSources());
registrar_.Add(this, NotificationType::EXTENSION_TEST_FAILED,
@@ -44,6 +45,11 @@ bool ExtensionApiTest::ResultCatcher::GetNextResult() {
void ExtensionApiTest::ResultCatcher::Observe(
NotificationType type, const NotificationSource& source,
const NotificationDetails& details) {
+ if (profile_restriction_ &&
+ Source<Profile>(source).ptr() != profile_restriction_) {
+ return;
+ }
+
switch (type.value) {
case NotificationType::EXTENSION_TEST_PASSED:
std::cout << "Got EXTENSION_TEST_PASSED notification.\n";
diff --git a/chrome/browser/extensions/extension_apitest.h b/chrome/browser/extensions/extension_apitest.h
index 3e2c13c..1c20bab 100644
--- a/chrome/browser/extensions/extension_apitest.h
+++ b/chrome/browser/extensions/extension_apitest.h
@@ -39,6 +39,8 @@ class ExtensionApiTest : public ExtensionBrowserTest {
// succeeded or failed. Returns true if the test succeeded, false otherwise.
bool GetNextResult();
+ void RestrictToProfile(Profile* profile) { profile_restriction_ = profile; }
+
const std::string& message() { return message_; }
private:
@@ -54,6 +56,9 @@ class ExtensionApiTest : public ExtensionBrowserTest {
// If it failed, what was the error message?
std::deque<std::string> messages_;
std::string message_;
+
+ // If non-NULL, we will listen to events from this profile only.
+ Profile* profile_restriction_;
};
// Load |extension_name| and wait for pass / fail notification.
diff --git a/chrome/browser/extensions/extension_bookmark_manager_api.cc b/chrome/browser/extensions/extension_bookmark_manager_api.cc
index 8e6df4d..0b0dc0f 100644
--- a/chrome/browser/extensions/extension_bookmark_manager_api.cc
+++ b/chrome/browser/extensions/extension_bookmark_manager_api.cc
@@ -161,7 +161,7 @@ void ExtensionBookmarkManagerEventRouter::DispatchEvent(const char* event_name,
std::string json_args;
base::JSONWriter::Write(args, false, &json_args);
profile_->GetExtensionMessageService()->DispatchEventToRenderers(
- event_name, json_args, profile_->IsOffTheRecord(), GURL());
+ event_name, json_args, profile_, GURL());
}
void ExtensionBookmarkManagerEventRouter::DispatchDragEvent(
diff --git a/chrome/browser/extensions/extension_bookmarks_module.cc b/chrome/browser/extensions/extension_bookmarks_module.cc
index 3f3e8c9..4044bfc 100644
--- a/chrome/browser/extensions/extension_bookmarks_module.cc
+++ b/chrome/browser/extensions/extension_bookmarks_module.cc
@@ -97,7 +97,7 @@ void ExtensionBookmarkEventRouter::DispatchEvent(Profile *profile,
const std::string json_args) {
if (profile->GetExtensionMessageService()) {
profile->GetExtensionMessageService()->DispatchEventToRenderers(
- event_name, json_args, profile->IsOffTheRecord(), GURL());
+ event_name, json_args, profile, GURL());
}
}
diff --git a/chrome/browser/extensions/extension_browser_event_router.cc b/chrome/browser/extensions/extension_browser_event_router.cc
index dedcc80..80dfa69 100644
--- a/chrome/browser/extensions/extension_browser_event_router.cc
+++ b/chrome/browser/extensions/extension_browser_event_router.cc
@@ -68,7 +68,7 @@ static void DispatchEvent(Profile* profile,
const std::string json_args) {
if (profile->GetExtensionMessageService()) {
profile->GetExtensionMessageService()->DispatchEventToRenderers(
- event_name, json_args, profile->IsOffTheRecord(), GURL());
+ event_name, json_args, profile, GURL());
}
}
diff --git a/chrome/browser/extensions/extension_cookies_api.cc b/chrome/browser/extensions/extension_cookies_api.cc
index f50d475..5a2d456 100644
--- a/chrome/browser/extensions/extension_cookies_api.cc
+++ b/chrome/browser/extensions/extension_cookies_api.cc
@@ -76,7 +76,7 @@ void ExtensionCookiesEventRouter::DispatchEvent(Profile* profile,
GURL& cookie_domain) {
if (profile && profile->GetExtensionMessageService()) {
profile->GetExtensionMessageService()->DispatchEventToRenderers(
- event_name, json_args, profile->IsOffTheRecord(), cookie_domain);
+ event_name, json_args, profile, cookie_domain);
}
}
@@ -405,7 +405,7 @@ bool RemoveCookieFunction::RunImpl() {
}
bool GetAllCookieStoresFunction::RunImpl() {
- Profile* original_profile = profile()->GetOriginalProfile();
+ Profile* original_profile = profile();
DCHECK(original_profile);
scoped_ptr<ListValue> original_tab_ids(new ListValue());
Profile* incognito_profile = NULL;
@@ -415,6 +415,8 @@ bool GetAllCookieStoresFunction::RunImpl() {
if (incognito_profile)
incognito_tab_ids.reset(new ListValue());
}
+ DCHECK(original_profile != incognito_profile);
+
// Iterate through all browser instances, and for each browser,
// add its tab IDs to either the regular or incognito tab ID list depending
// whether the browser is regular or incognito.
diff --git a/chrome/browser/extensions/extension_cookies_helpers.cc b/chrome/browser/extensions/extension_cookies_helpers.cc
index 2aedb5f..52368e9 100644
--- a/chrome/browser/extensions/extension_cookies_helpers.cc
+++ b/chrome/browser/extensions/extension_cookies_helpers.cc
@@ -27,9 +27,11 @@ Profile* ChooseProfileFromStoreId(const std::string& store_id,
Profile* profile,
bool include_incognito) {
DCHECK(profile);
- if (store_id == kOriginalProfileStoreId)
+ bool allow_original = !profile->IsOffTheRecord();
+ bool allow_incognito = profile->IsOffTheRecord() || include_incognito;
+ if (store_id == kOriginalProfileStoreId && allow_original)
return profile->GetOriginalProfile();
- if (store_id == kOffTheRecordProfileStoreId && include_incognito)
+ if (store_id == kOffTheRecordProfileStoreId && allow_incognito)
return profile->GetOffTheRecordProfile();
return NULL;
}
diff --git a/chrome/browser/extensions/extension_cookies_unittest.cc b/chrome/browser/extensions/extension_cookies_unittest.cc
index 0abbe7e..ec9084a 100644
--- a/chrome/browser/extensions/extension_cookies_unittest.cc
+++ b/chrome/browser/extensions/extension_cookies_unittest.cc
@@ -83,16 +83,16 @@ TEST_F(ExtensionCookiesTest, StoreIdProfileConversion) {
EXPECT_EQ(std::string("1"),
extension_cookies_helpers::GetStoreIdFromProfile(&otrProfile));
- EXPECT_EQ(&profile,
+ EXPECT_EQ(NULL,
extension_cookies_helpers::ChooseProfileFromStoreId(
"0", &otrProfile, true));
- EXPECT_EQ(&profile,
+ EXPECT_EQ(NULL,
extension_cookies_helpers::ChooseProfileFromStoreId(
"0", &otrProfile, false));
EXPECT_EQ(&otrProfile,
extension_cookies_helpers::ChooseProfileFromStoreId(
"1", &otrProfile, true));
- EXPECT_EQ(NULL,
+ EXPECT_EQ(&otrProfile,
extension_cookies_helpers::ChooseProfileFromStoreId(
"1", &otrProfile, false));
}
diff --git a/chrome/browser/extensions/extension_devtools_bridge.cc b/chrome/browser/extensions/extension_devtools_bridge.cc
index 71d795b..01a0aef 100644
--- a/chrome/browser/extensions/extension_devtools_bridge.cc
+++ b/chrome/browser/extensions/extension_devtools_bridge.cc
@@ -65,7 +65,7 @@ void ExtensionDevToolsBridge::InspectedTabClosing() {
// event in extensions.
std::string json("[{}]");
profile_->GetExtensionMessageService()->DispatchEventToRenderers(
- on_tab_close_event_name_, json, profile_->IsOffTheRecord(), GURL());
+ on_tab_close_event_name_, json, profile_, GURL());
// This may result in this object being destroyed.
extension_devtools_manager_->BridgeClosingForTab(tab_id_);
@@ -83,6 +83,6 @@ void ExtensionDevToolsBridge::OnDispatchToAPU(const std::string& data) {
std::string json = StringPrintf("[%s]", data.c_str());
profile_->GetExtensionMessageService()->DispatchEventToRenderers(
- on_page_event_name_, json, profile_->IsOffTheRecord(), GURL());
+ on_page_event_name_, json, profile_, GURL());
}
diff --git a/chrome/browser/extensions/extension_function.h b/chrome/browser/extensions/extension_function.h
index 51f25fe..b48d0a9 100644
--- a/chrome/browser/extensions/extension_function.h
+++ b/chrome/browser/extensions/extension_function.h
@@ -149,7 +149,10 @@ class ExtensionFunction : public base::RefCountedThreadSafe<ExtensionFunction> {
// of this call.
bool has_callback_;
- // True if this callback should include information from incognito contexts.
+ // True if this callback should include information from incognito contexts
+ // even if our profile_ is non-incognito. Note that in the case of a "split"
+ // mode extension, this will always be false, and we will limit access to
+ // data from within the same profile_ (either incognito or not).
bool include_incognito_;
// True if the call was made in response of user gesture.
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index a8253cf..fd4ba5f 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -391,7 +391,7 @@ ExtensionFunctionDispatcher::ExtensionFunctionDispatcher(
render_view_host->Send(new ViewMsg_Extension_SetHostPermissions(
extension->url(), extension->host_permissions()));
render_view_host->Send(new ViewMsg_Extension_ExtensionSetIncognitoEnabled(
- extension->id(), incognito_enabled));
+ extension->id(), incognito_enabled, extension->incognito_split_mode()));
NotificationService::current()->Notify(
NotificationType::EXTENSION_FUNCTION_DISPATCHER_CREATED,
@@ -412,20 +412,16 @@ Browser* ExtensionFunctionDispatcher::GetCurrentBrowser(
bool include_incognito) {
Browser* browser = delegate_->GetBrowser();
- // If the delegate has an associated browser and that browser is in the right
- // incognito state, we can return it.
- if (browser) {
- if (include_incognito || !browser->profile()->IsOffTheRecord())
- return browser;
- }
+ // If the delegate has an associated browser, that is always the right answer.
+ if (browser)
+ return browser;
- // Otherwise, try to default to a reasonable browser.
+ // Otherwise, try to default to a reasonable browser. If |include_incognito|
+ // is true, we will also search browsers in the incognito version of this
+ // profile. Note that the profile may already be incognito, in which case
+ // we will search the incognito version only, regardless of the value of
+ // |include_incognito|.
Profile* profile = render_view_host()->process()->profile();
-
- // Make sure we don't return an incognito browser without proper access.
- if (!include_incognito)
- profile = profile->GetOriginalProfile();
-
browser = BrowserList::FindBrowserWithType(profile, Browser::TYPE_NORMAL,
include_incognito);
@@ -454,7 +450,8 @@ void ExtensionFunctionDispatcher::HandleRequest(
DCHECK(service);
Extension* extension = service->GetExtensionById(extension_id(), false);
DCHECK(extension);
- function->set_include_incognito(service->IsIncognitoEnabled(extension));
+ function->set_include_incognito(service->IsIncognitoEnabled(extension) &&
+ !extension->incognito_split_mode());
std::string permission_name = function->name();
size_t separator = permission_name.find_first_of("./");
diff --git a/chrome/browser/extensions/extension_history_api.cc b/chrome/browser/extensions/extension_history_api.cc
index 3df0509..82be3dc 100644
--- a/chrome/browser/extensions/extension_history_api.cc
+++ b/chrome/browser/extensions/extension_history_api.cc
@@ -143,7 +143,7 @@ void ExtensionHistoryEventRouter::DispatchEvent(Profile* profile,
const std::string& json_args) {
if (profile && profile->GetExtensionMessageService()) {
profile->GetExtensionMessageService()->DispatchEventToRenderers(
- event_name, json_args, profile->IsOffTheRecord(), GURL());
+ event_name, json_args, profile, GURL());
}
}
diff --git a/chrome/browser/extensions/extension_idle_api.cc b/chrome/browser/extensions/extension_idle_api.cc
index 104cc8b..0de5032 100644
--- a/chrome/browser/extensions/extension_idle_api.cc
+++ b/chrome/browser/extensions/extension_idle_api.cc
@@ -153,8 +153,5 @@ void ExtensionIdleEventRouter::OnIdleStateChange(Profile* profile,
base::JSONWriter::Write(&args, false, &json_args);
profile->GetExtensionMessageService()->DispatchEventToRenderers(
- keys::kOnStateChanged,
- json_args,
- profile->IsOffTheRecord(),
- GURL());
+ keys::kOnStateChanged, json_args, profile, GURL());
}
diff --git a/chrome/browser/extensions/extension_incognito_apitest.cc b/chrome/browser/extensions/extension_incognito_apitest.cc
index dd0abd4..41ddb99 100644
--- a/chrome/browser/extensions/extension_incognito_apitest.cc
+++ b/chrome/browser/extensions/extension_incognito_apitest.cc
@@ -95,6 +95,31 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Incognito) {
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
+// Tests that the APIs in an incognito-enabled split-mode extension work
+// properly.
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, IncognitoSplitMode) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(test_server()->Start());
+
+ // We need 2 ResultCatchers because we'll be running the same test in both
+ // regular and incognito mode.
+ ResultCatcher catcher;
+ catcher.RestrictToProfile(browser()->profile());
+ ResultCatcher catcher_incognito;
+ catcher_incognito.RestrictToProfile(
+ browser()->profile()->GetOffTheRecordProfile());
+
+ // 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"));
+
+ ASSERT_TRUE(LoadExtensionIncognito(test_data_dir_
+ .AppendASCII("incognito").AppendASCII("split")));
+
+ EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
+ EXPECT_TRUE(catcher_incognito.GetNextResult()) << catcher.message();
+}
+
// Tests that the APIs in an incognito-disabled extension don't see incognito
// events or callbacks.
// Hangy, http://crbug.com/53869.
diff --git a/chrome/browser/extensions/extension_management_api.cc b/chrome/browser/extensions/extension_management_api.cc
index 4b581b2..ba5eab3 100644
--- a/chrome/browser/extensions/extension_management_api.cc
+++ b/chrome/browser/extensions/extension_management_api.cc
@@ -200,6 +200,6 @@ void ExtensionManagementEventRouter::Observe(
profile->GetExtensionMessageService();
message_service->DispatchEventToRenderers(event_name,
args_json,
- profile->IsOffTheRecord(),
+ profile,
GURL());
}
diff --git a/chrome/browser/extensions/extension_menu_manager.cc b/chrome/browser/extensions/extension_menu_manager.cc
index 77c3408..e4bda71 100644
--- a/chrome/browser/extensions/extension_menu_manager.cc
+++ b/chrome/browser/extensions/extension_menu_manager.cc
@@ -441,8 +441,7 @@ void ExtensionMenuManager::ExecuteCommand(
std::string json_args;
base::JSONWriter::Write(&args, false, &json_args);
std::string event_name = "contextMenus/" + item->extension_id();
- service->DispatchEventToRenderers(event_name, json_args,
- profile->IsOffTheRecord(), GURL());
+ service->DispatchEventToRenderers(event_name, json_args, profile, GURL());
}
void ExtensionMenuManager::Observe(NotificationType type,
diff --git a/chrome/browser/extensions/extension_menu_manager_unittest.cc b/chrome/browser/extensions/extension_menu_manager_unittest.cc
index f074b4a..e3a61a1 100644
--- a/chrome/browser/extensions/extension_menu_manager_unittest.cc
+++ b/chrome/browser/extensions/extension_menu_manager_unittest.cc
@@ -338,7 +338,7 @@ class MockExtensionMessageService : public ExtensionMessageService {
MOCK_METHOD4(DispatchEventToRenderers, void(const std::string& event_name,
const std::string& event_args,
- bool has_incognito_data,
+ Profile* source_profile,
const GURL& event_url));
private:
@@ -413,17 +413,13 @@ TEST_F(ExtensionMenuManagerTest, ExecuteCommand) {
.Times(1)
.WillOnce(Return(mock_message_service.get()));
- EXPECT_CALL(profile, IsOffTheRecord())
- .Times(AtLeast(1))
- .WillRepeatedly(Return(false));
-
// Use the magic of googlemock to save a parameter to our mock's
// DispatchEventToRenderers method into event_args.
std::string event_args;
std::string expected_event_name = "contextMenus/" + item->extension_id();
EXPECT_CALL(*mock_message_service.get(),
DispatchEventToRenderers(expected_event_name, _,
- profile.IsOffTheRecord(),
+ &profile,
GURL()))
.Times(1)
.WillOnce(SaveArg<1>(&event_args));
diff --git a/chrome/browser/extensions/extension_message_service.cc b/chrome/browser/extensions/extension_message_service.cc
index 9775551..2fb59c3 100644
--- a/chrome/browser/extensions/extension_message_service.cc
+++ b/chrome/browser/extensions/extension_message_service.cc
@@ -204,15 +204,15 @@ void ExtensionMessageService::OpenChannelToExtension(
const std::string& source_extension_id,
const std::string& target_extension_id,
const std::string& channel_name) {
- if (!profile_)
- return;
-
RenderProcessHost* source = RenderProcessHost::FromID(source_process_id);
if (!source)
return;
+ // Note: we use the source's profile here. If the source is an incognito
+ // process, we will use the incognito EPM to find the right extension process,
+ // which depends on whether the extension uses spanning or split mode.
MessagePort receiver(
- profile_->GetExtensionProcessManager()->GetExtensionProcess(
+ source->profile()->GetExtensionProcessManager()->GetExtensionProcess(
target_extension_id),
MSG_ROUTING_CONTROL);
TabContents* source_contents = tab_util::GetTabContentsByID(
@@ -321,8 +321,7 @@ int ExtensionMessageService::OpenSpecialChannelToExtension(
AllocatePortIdPair(&port1_id, &port2_id);
MessagePort receiver(
- profile_->GetExtensionProcessManager()->
- GetExtensionProcess(extension_id),
+ profile_->GetExtensionProcessManager()->GetExtensionProcess(extension_id),
MSG_ROUTING_CONTROL);
if (!OpenChannelImpl(source, tab_json, receiver, port2_id,
extension_id, extension_id, channel_name))
@@ -393,7 +392,13 @@ void ExtensionMessageService::PostMessageFromRenderer(
void ExtensionMessageService::DispatchEventToRenderers(
const std::string& event_name, const std::string& event_args,
- bool has_incognito_data, const GURL& event_url) {
+ Profile* source_profile, const GURL& event_url) {
+ if (!profile_)
+ return;
+
+ // We don't expect to get events from a completely different profile.
+ DCHECK(!source_profile || profile_->IsSameProfile(source_profile));
+
ListenerMap::iterator it = listeners_.find(event_name);
if (it == listeners_.end())
return;
@@ -411,17 +416,20 @@ void ExtensionMessageService::DispatchEventToRenderers(
continue;
}
- DispatchEvent(
- renderer, event_name, event_args, has_incognito_data, event_url);
+ // Is this event from a different profile than the renderer (ie, an
+ // incognito tab event sent to a normal process, or vice versa).
+ bool cross_profile =
+ source_profile && renderer->profile() != source_profile;
+ DispatchEvent(renderer, event_name, event_args, cross_profile, event_url);
}
}
void ExtensionMessageService::DispatchEventToExtension(
const std::string& extension_id,
const std::string& event_name, const std::string& event_args,
- bool has_incognito_data, const GURL& event_url) {
+ Profile* source_profile, const GURL& event_url) {
DispatchEventToRenderers(GetPerExtensionEventName(event_name, extension_id),
- event_args, has_incognito_data, event_url);
+ event_args, source_profile, event_url);
}
void ExtensionMessageService::Observe(NotificationType type,
diff --git a/chrome/browser/extensions/extension_message_service.h b/chrome/browser/extensions/extension_message_service.h
index e18140b..9d8c038 100644
--- a/chrome/browser/extensions/extension_message_service.h
+++ b/chrome/browser/extensions/extension_message_service.h
@@ -87,14 +87,14 @@ class ExtensionMessageService
// event is only sent to extension with host permissions for this url.
virtual void DispatchEventToRenderers(
const std::string& event_name, const std::string& event_args,
- bool has_incognito_data, const GURL& event_url);
+ Profile* source_profile, const GURL& event_url);
// Same as above, except use the extension-specific naming scheme for the
// event. This is used by events that are per-extension.
void DispatchEventToExtension(
const std::string& extension_id,
const std::string& event_name, const std::string& event_args,
- bool has_incognito_data, const GURL& event_url);
+ Profile* source_profile, const GURL& event_url);
// Given an extension's ID, opens a channel between the given renderer "port"
// and every listening context owned by that extension. |channel_name| is
diff --git a/chrome/browser/extensions/extension_messages_apitest.cc b/chrome/browser/extensions/extension_messages_apitest.cc
index 9a393c6..533b840 100644
--- a/chrome/browser/extensions/extension_messages_apitest.cc
+++ b/chrome/browser/extensions/extension_messages_apitest.cc
@@ -28,19 +28,19 @@ class MessageSender : public NotificationObserver {
// from the origin http://b.com/ are supposed to arrive.
message_service->DispatchEventToRenderers("test.onMessage",
"[{\"lastMessage\":false,\"data\":\"no restriction\"}]",
- Source<Profile>(source).ptr()->IsOffTheRecord(),
+ Source<Profile>(source).ptr(),
GURL());
message_service->DispatchEventToRenderers("test.onMessage",
"[{\"lastMessage\":false,\"data\":\"http://a.com/\"}]",
- Source<Profile>(source).ptr()->IsOffTheRecord(),
+ Source<Profile>(source).ptr(),
GURL("http://a.com/"));
message_service->DispatchEventToRenderers("test.onMessage",
"[{\"lastMessage\":false,\"data\":\"http://b.com/\"}]",
- Source<Profile>(source).ptr()->IsOffTheRecord(),
+ Source<Profile>(source).ptr(),
GURL("http://b.com/"));
message_service->DispatchEventToRenderers("test.onMessage",
"[{\"lastMessage\":true,\"data\":\"last message\"}]",
- Source<Profile>(source).ptr()->IsOffTheRecord(),
+ Source<Profile>(source).ptr(),
GURL());
}
diff --git a/chrome/browser/extensions/extension_omnibox_api.cc b/chrome/browser/extensions/extension_omnibox_api.cc
index 89ed86c..26c91bb 100644
--- a/chrome/browser/extensions/extension_omnibox_api.cc
+++ b/chrome/browser/extensions/extension_omnibox_api.cc
@@ -36,8 +36,7 @@ const char kDescriptionStylesOffset[] = "offset";
void ExtensionOmniboxEventRouter::OnInputStarted(
Profile* profile, const std::string& extension_id) {
profile->GetExtensionMessageService()->DispatchEventToExtension(
- extension_id, events::kOnInputStarted, "[]", profile->IsOffTheRecord(),
- GURL());
+ extension_id, events::kOnInputStarted, "[]", profile, GURL());
}
// static
@@ -56,8 +55,7 @@ bool ExtensionOmniboxEventRouter::OnInputChanged(
base::JSONWriter::Write(&args, false, &json_args);
profile->GetExtensionMessageService()->DispatchEventToExtension(
- extension_id, events::kOnInputChanged, json_args,
- profile->IsOffTheRecord(), GURL());
+ extension_id, events::kOnInputChanged, json_args, profile, GURL());
return true;
}
@@ -73,8 +71,7 @@ void ExtensionOmniboxEventRouter::OnInputEntered(
base::JSONWriter::Write(&args, false, &json_args);
profile->GetExtensionMessageService()->DispatchEventToExtension(
- extension_id, events::kOnInputEntered, json_args,
- profile->IsOffTheRecord(), GURL());
+ extension_id, events::kOnInputEntered, json_args, profile, GURL());
NotificationService::current()->Notify(
NotificationType::EXTENSION_OMNIBOX_INPUT_ENTERED,
@@ -85,8 +82,7 @@ void ExtensionOmniboxEventRouter::OnInputEntered(
void ExtensionOmniboxEventRouter::OnInputCancelled(
Profile* profile, const std::string& extension_id) {
profile->GetExtensionMessageService()->DispatchEventToExtension(
- extension_id, events::kOnInputCancelled, "[]", profile->IsOffTheRecord(),
- GURL());
+ extension_id, events::kOnInputCancelled, "[]", profile, GURL());
}
bool OmniboxSendSuggestionsFunction::RunImpl() {
diff --git a/chrome/browser/extensions/extension_popup_api.cc b/chrome/browser/extensions/extension_popup_api.cc
index e6c559b..7fc8f1b 100644
--- a/chrome/browser/extensions/extension_popup_api.cc
+++ b/chrome/browser/extensions/extension_popup_api.cc
@@ -498,8 +498,5 @@ void PopupEventRouter::OnPopupClosed(Profile* profile,
routing_id);
profile->GetExtensionMessageService()->DispatchEventToRenderers(
- full_event_name,
- base::JSONWriter::kEmptyArray,
- profile->IsOffTheRecord(),
- GURL());
+ full_event_name, base::JSONWriter::kEmptyArray, profile, GURL());
}
diff --git a/chrome/browser/extensions/extension_process_manager.cc b/chrome/browser/extensions/extension_process_manager.cc
index 49205cd..1fff690 100644
--- a/chrome/browser/extensions/extension_process_manager.cc
+++ b/chrome/browser/extensions/extension_process_manager.cc
@@ -21,6 +21,37 @@
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "chrome/common/render_messages.h"
+#include "chrome/common/url_constants.h"
+
+namespace {
+
+// Incognito profiles use this process manager. It is mostly a shim that decides
+// whether to fall back on the original profile's ExtensionProcessManager based
+// on whether a given extension uses "split" or "spanning" incognito behavior.
+class IncognitoExtensionProcessManager : public ExtensionProcessManager {
+ public:
+ explicit IncognitoExtensionProcessManager(Profile* profile);
+ virtual ~IncognitoExtensionProcessManager() {}
+ virtual ExtensionHost* CreateView(Extension* extension,
+ const GURL& url,
+ Browser* browser,
+ ViewType::Type view_type);
+ virtual void CreateBackgroundHost(Extension* extension, const GURL& url);
+ virtual SiteInstance* GetSiteInstanceForURL(const GURL& url);
+ virtual RenderProcessHost* GetExtensionProcess(const GURL& url);
+
+ private:
+ // NotificationObserver:
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ // Returns the extension for an URL, which can either be a chrome-extension
+ // URL or a web app URL.
+ Extension* GetExtensionOrAppByURL(const GURL& url);
+
+ ExtensionProcessManager* original_manager_;
+};
static void CreateBackgroundHost(
ExtensionProcessManager* manager, Extension* extension) {
@@ -37,6 +68,19 @@ static void CreateBackgroundHosts(
}
}
+} // namespace
+
+//
+// ExtensionProcessManager
+//
+
+// static
+ExtensionProcessManager* ExtensionProcessManager::Create(Profile* profile) {
+ return (profile->IsOffTheRecord()) ?
+ new IncognitoExtensionProcessManager(profile) :
+ new ExtensionProcessManager(profile);
+}
+
ExtensionProcessManager::ExtensionProcessManager(Profile* profile)
: browsing_instance_(new BrowsingInstance(profile)) {
registrar_.Add(this, NotificationType::EXTENSIONS_READY,
@@ -85,7 +129,7 @@ ExtensionHost* ExtensionProcessManager::CreateView(const GURL& url,
// A NULL browser may only be given for pop-up views.
DCHECK(browser || (!browser && view_type == ViewType::EXTENSION_POPUP));
ExtensionsService* service =
- browsing_instance_->profile()->GetExtensionsService();
+ browsing_instance_->profile()->GetExtensionsService();
if (service) {
Extension* extension = service->GetExtensionByURL(url);
if (extension)
@@ -116,8 +160,12 @@ ExtensionHost* ExtensionProcessManager::CreateInfobar(const GURL& url,
return CreateView(url, browser, ViewType::EXTENSION_INFOBAR);
}
-ExtensionHost* ExtensionProcessManager::CreateBackgroundHost(
+void ExtensionProcessManager::CreateBackgroundHost(
Extension* extension, const GURL& url) {
+ // Don't create multiple background hosts for an extension.
+ if (GetBackgroundHostForExtension(extension))
+ return;
+
ExtensionHost* host =
#if defined(OS_MACOSX)
new ExtensionHostMac(extension, GetSiteInstanceForURL(url), url,
@@ -129,16 +177,19 @@ ExtensionHost* ExtensionProcessManager::CreateBackgroundHost(
host->CreateRenderViewSoon(NULL); // create a RenderViewHost with no view
OnExtensionHostCreated(host, true);
- return host;
}
void ExtensionProcessManager::OpenOptionsPage(Extension* extension,
Browser* browser) {
DCHECK(!extension->options_url().is_empty());
- // We can't open extensions URLs in incognito windows.
- if (!browser || browser->profile()->IsOffTheRecord())
- browser = Browser::GetOrCreateTabbedBrowser(browsing_instance_->profile());
+ // We can't open extensions URLs in incognito windows, unless the extension
+ // uses "split" incognito mode.
+ if (!browser || (browser->profile()->IsOffTheRecord() &&
+ !extension->incognito_split_mode())) {
+ browser = Browser::GetOrCreateTabbedBrowser(
+ browsing_instance_->profile()->GetOriginalProfile());
+ }
browser->OpenURL(extension->options_url(), GURL(), SINGLETON_TAB,
PageTransition::LINK);
@@ -159,6 +210,8 @@ ExtensionHost* ExtensionProcessManager::GetBackgroundHostForExtension(
void ExtensionProcessManager::RegisterExtensionProcess(
const std::string& extension_id, int process_id) {
+ // TODO(mpcomplete): This is the only place we actually read process_ids_.
+ // Is it necessary?
ProcessIDMap::const_iterator it = process_ids_.find(extension_id);
if (it != process_ids_.end() && (*it).second == process_id)
return;
@@ -197,7 +250,7 @@ RenderProcessHost* ExtensionProcessManager::GetExtensionProcess(
if (!browsing_instance_->HasSiteInstance(url))
return NULL;
scoped_refptr<SiteInstance> site =
- browsing_instance_->GetSiteInstanceForURL(url);
+ browsing_instance_->GetSiteInstanceForURL(url);
if (site->HasProcess())
return site->GetProcess();
return NULL;
@@ -205,13 +258,8 @@ RenderProcessHost* ExtensionProcessManager::GetExtensionProcess(
RenderProcessHost* ExtensionProcessManager::GetExtensionProcess(
const std::string& extension_id) {
- ProcessIDMap::const_iterator it = process_ids_.find(extension_id);
- if (it == process_ids_.end())
- return NULL;
-
- RenderProcessHost* rph = RenderProcessHost::FromID(it->second);
- DCHECK(rph) << "We should have unregistered this host.";
- return rph;
+ return GetExtensionProcess(
+ Extension::GetBaseURLFromExtensionId(extension_id));
}
SiteInstance* ExtensionProcessManager::GetSiteInstanceForURL(const GURL& url) {
@@ -285,6 +333,8 @@ void ExtensionProcessManager::Observe(NotificationType type,
void ExtensionProcessManager::OnExtensionHostCreated(ExtensionHost* host,
bool is_background) {
+ DCHECK_EQ(browsing_instance_->profile(), host->profile());
+
all_hosts_.insert(host);
if (is_background)
background_hosts_.insert(host);
@@ -301,3 +351,93 @@ void ExtensionProcessManager::CloseBackgroundHosts() {
delete *current;
}
}
+
+//
+// IncognitoExtensionProcessManager
+//
+
+IncognitoExtensionProcessManager::IncognitoExtensionProcessManager(
+ Profile* profile)
+ : ExtensionProcessManager(profile),
+ original_manager_(profile->GetOriginalProfile()->
+ GetExtensionProcessManager()) {
+ DCHECK(profile->IsOffTheRecord());
+
+ registrar_.Add(this, NotificationType::BROWSER_WINDOW_READY,
+ NotificationService::AllSources());
+}
+
+ExtensionHost* IncognitoExtensionProcessManager::CreateView(
+ Extension* extension,
+ const GURL& url,
+ Browser* browser,
+ ViewType::Type view_type) {
+ if (extension->incognito_split_mode()) {
+ return ExtensionProcessManager::CreateView(extension, url,
+ browser, view_type);
+ } else {
+ return original_manager_->CreateView(extension, url, browser, view_type);
+ }
+}
+
+void IncognitoExtensionProcessManager::CreateBackgroundHost(
+ Extension* extension, const GURL& url) {
+ if (extension->incognito_split_mode()) {
+ ExtensionProcessManager::CreateBackgroundHost(extension, url);
+ } else {
+ // Do nothing. If an extension is spanning, then its original-profile
+ // background page is shared with incognito, so we don't create another.
+ }
+}
+
+SiteInstance* IncognitoExtensionProcessManager::GetSiteInstanceForURL(
+ const GURL& url) {
+ Extension* extension = GetExtensionOrAppByURL(url);
+ if (!extension || extension->incognito_split_mode()) {
+ return ExtensionProcessManager::GetSiteInstanceForURL(url);
+ } else {
+ return original_manager_->GetSiteInstanceForURL(url);
+ }
+}
+
+RenderProcessHost* IncognitoExtensionProcessManager::GetExtensionProcess(
+ const GURL& url) {
+ Extension* extension = GetExtensionOrAppByURL(url);
+ if (!extension || extension->incognito_split_mode()) {
+ return ExtensionProcessManager::GetExtensionProcess(url);
+ } else {
+ return original_manager_->GetExtensionProcess(url);
+ }
+}
+
+Extension* IncognitoExtensionProcessManager::GetExtensionOrAppByURL(
+ const GURL& url) {
+ ExtensionsService* service =
+ browsing_instance_->profile()->GetExtensionsService();
+ return (url.SchemeIs(chrome::kExtensionScheme)) ?
+ service->GetExtensionByURL(url) : service->GetExtensionByWebExtent(url);
+}
+
+void IncognitoExtensionProcessManager::Observe(
+ NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ switch (type.value) {
+ case NotificationType::BROWSER_WINDOW_READY: {
+ // We want to spawn our background hosts as soon as the user opens an
+ // incognito window. Watch for new browsers and create the hosts if
+ // it matches our profile.
+ Browser* browser = Source<Browser>(source).ptr();
+ if (browser->profile() == browsing_instance_->profile()) {
+ ExtensionsService* service =
+ browsing_instance_->profile()->GetExtensionsService();
+ if (service && service->is_ready())
+ CreateBackgroundHosts(this, service->extensions());
+ }
+ break;
+ }
+ default:
+ ExtensionProcessManager::Observe(type, source, details);
+ break;
+ }
+}
diff --git a/chrome/browser/extensions/extension_process_manager.h b/chrome/browser/extensions/extension_process_manager.h
index 5f71806..d284275 100644
--- a/chrome/browser/extensions/extension_process_manager.h
+++ b/chrome/browser/extensions/extension_process_manager.h
@@ -24,17 +24,18 @@ class Profile;
class RenderProcessHost;
class SiteInstance;
-// Manages dynamic state of running Chromium extensions. There is one instance
-// of this class per Profile (including OTR).
+// Manages dynamic state of running Chromium extensions. There is one instance
+// of this class per Profile. OTR Profiles have a separate instance that keeps
+// track of split-mode extensions only.
class ExtensionProcessManager : public NotificationObserver {
public:
- explicit ExtensionProcessManager(Profile* profile);
- ~ExtensionProcessManager();
+ static ExtensionProcessManager* Create(Profile* profile);
+ virtual ~ExtensionProcessManager();
// Creates a new ExtensionHost with its associated view, grouping it in the
// appropriate SiteInstance (and therefore process) based on the URL and
// profile.
- ExtensionHost* CreateView(Extension* extension,
+ virtual ExtensionHost* CreateView(Extension* extension,
const GURL& url,
Browser* browser,
ViewType::Type view_type);
@@ -51,19 +52,19 @@ class ExtensionProcessManager : public NotificationObserver {
ExtensionHost* CreateInfobar(const GURL& url,
Browser* browser);
- // Creates a new UI-less extension instance. Like CreateView, but not
- // displayed anywhere.
- ExtensionHost* CreateBackgroundHost(Extension* extension, const GURL& url);
-
// Open the extension's options page.
void OpenOptionsPage(Extension* extension, Browser* browser);
+ // Creates a new UI-less extension instance. Like CreateView, but not
+ // displayed anywhere.
+ virtual void CreateBackgroundHost(Extension* extension, const GURL& url);
+
// Gets the ExtensionHost for the background page for an extension, or NULL if
// the extension isn't running or doesn't have a background page.
ExtensionHost* GetBackgroundHostForExtension(Extension* extension);
// Returns the SiteInstance that the given URL belongs to.
- SiteInstance* GetSiteInstanceForURL(const GURL& url);
+ virtual SiteInstance* GetSiteInstanceForURL(const GURL& url);
// Registers an extension process by |extension_id| and specifying which
// |process_id| it belongs to.
@@ -74,33 +75,33 @@ class ExtensionProcessManager : public NotificationObserver {
void UnregisterExtensionProcess(int process_id);
// Returns the extension process that |url| is associated with if it exists.
- RenderProcessHost* GetExtensionProcess(const GURL& url);
+ virtual RenderProcessHost* GetExtensionProcess(const GURL& url);
// Returns the process that the extension with the given ID is running in.
- // NOTE: This does not currently handle app processes with no
- // ExtensionFunctionDispatcher objects.
RenderProcessHost* GetExtensionProcess(const std::string& extension_id);
// Returns true if |host| is managed by this process manager.
bool HasExtensionHost(ExtensionHost* host) const;
- // NotificationObserver:
- virtual void Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details);
-
typedef std::set<ExtensionHost*> ExtensionHostSet;
typedef ExtensionHostSet::const_iterator const_iterator;
const_iterator begin() const { return all_hosts_.begin(); }
const_iterator end() const { return all_hosts_.end(); }
- private:
+ protected:
+ explicit ExtensionProcessManager(Profile* profile);
+
// Called just after |host| is created so it can be registered in our lists.
void OnExtensionHostCreated(ExtensionHost* host, bool is_background);
// Called on browser shutdown to close our extension hosts.
void CloseBackgroundHosts();
+ // NotificationObserver:
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
NotificationRegistrar registrar_;
// The set of all ExtensionHosts managed by this process manager.
diff --git a/chrome/browser/extensions/extension_process_manager_unittest.cc b/chrome/browser/extensions/extension_process_manager_unittest.cc
index cf2d5d9..f73c0b0 100644
--- a/chrome/browser/extensions/extension_process_manager_unittest.cc
+++ b/chrome/browser/extensions/extension_process_manager_unittest.cc
@@ -33,11 +33,11 @@ TEST_F(ExtensionProcessManagerTest, ProcessGrouping) {
// functionality. This means we can get away with a NULL UserScriptMaster.
TestingProfile profile1;
scoped_ptr<ExtensionProcessManager> manager1(
- new ExtensionProcessManager(&profile1));
+ ExtensionProcessManager::Create(&profile1));
TestingProfile profile2;
scoped_ptr<ExtensionProcessManager> manager2(
- new ExtensionProcessManager(&profile2));
+ ExtensionProcessManager::Create(&profile2));
// Extensions with common origins ("scheme://id/") should be grouped in the
// same SiteInstance.
diff --git a/chrome/browser/extensions/extension_protocols.cc b/chrome/browser/extensions/extension_protocols.cc
index 30f7b37..f281c74 100644
--- a/chrome/browser/extensions/extension_protocols.cc
+++ b/chrome/browser/extensions/extension_protocols.cc
@@ -99,7 +99,8 @@ bool AllowExtensionResourceLoad(URLRequest* request,
// This is because an extension must run in a single process, and an
// incognito tab prevents that.
if (context->is_off_the_record() &&
- info->resource_type() == ResourceType::MAIN_FRAME) {
+ info->resource_type() == ResourceType::MAIN_FRAME &&
+ !context->ExtensionCanLoadInIncognito(request->url().host())) {
LOG(ERROR) << "Denying load of " << request->url().spec() << " from "
<< "incognito tab.";
return false;
diff --git a/chrome/browser/extensions/extension_sidebar_api.cc b/chrome/browser/extensions/extension_sidebar_api.cc
index e5f693e..d63f632 100644
--- a/chrome/browser/extensions/extension_sidebar_api.cc
+++ b/chrome/browser/extensions/extension_sidebar_api.cc
@@ -90,8 +90,7 @@ void ExtensionSidebarEventRouter::OnStateChanged(
const std::string& extension_id(content_id);
profile->GetExtensionMessageService()->DispatchEventToExtension(
- extension_id, kOnStateChanged, json_args,
- profile->IsOffTheRecord(), GURL());
+ extension_id, kOnStateChanged, json_args, profile, GURL());
}
diff --git a/chrome/browser/extensions/extension_ui_unittest.cc b/chrome/browser/extensions/extension_ui_unittest.cc
index f4075b6..6df1ac7 100644
--- a/chrome/browser/extensions/extension_ui_unittest.cc
+++ b/chrome/browser/extensions/extension_ui_unittest.cc
@@ -72,10 +72,10 @@ TEST(ExtensionUITest, GenerateExtensionsJSONData) {
std::vector<ExtensionPage> pages;
pages.push_back(ExtensionPage(
GURL("chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/bar.html"),
- 42, 88));
+ 42, 88, false));
pages.push_back(ExtensionPage(
GURL("chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/dog.html"),
- 0, 0));
+ 0, 0, false));
expected_output_path = data_test_dir_path.AppendASCII("extensions")
.AppendASCII("ui")
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc
index 362ef22..7ba0f42 100644
--- a/chrome/browser/extensions/extensions_service.cc
+++ b/chrome/browser/extensions/extensions_service.cc
@@ -204,7 +204,7 @@ ExtensionsService::ExtensionsService(Profile* profile,
registrar_.Add(this, NotificationType::EXTENSION_HOST_DID_STOP_LOADING,
NotificationService::AllSources());
registrar_.Add(this, NotificationType::EXTENSION_PROCESS_TERMINATED,
- Source<Profile>(profile_));
+ NotificationService::AllSources());
prefs->AddPrefObserver(prefs::kExtensionInstallAllowList, this);
prefs->AddPrefObserver(prefs::kExtensionInstallDenyList, this);
@@ -1368,7 +1368,8 @@ void ExtensionsService::Observe(NotificationType type,
}
case NotificationType::EXTENSION_PROCESS_TERMINATED: {
- DCHECK_EQ(profile_, Source<Profile>(source).ptr());
+ if (profile_ != Source<Profile>(source).ptr()->GetOriginalProfile())
+ break;
ExtensionHost* host = Details<ExtensionHost>(details).ptr();
@@ -1387,7 +1388,11 @@ void ExtensionsService::Observe(NotificationType type,
// Unload the entire extension. We want it to be in a consistent state:
// either fully working or not loaded at all, but never half-crashed.
- UnloadExtension(host->extension()->id());
+ // We do it in a PostTask so that other handlers of this notification will
+ // still have access to the Extension and ExtensionHost.
+ MessageLoop::current()->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &ExtensionsService::UnloadExtension,
+ host->extension()->id()));
break;
}
diff --git a/chrome/browser/extensions/extensions_ui.cc b/chrome/browser/extensions/extensions_ui.cc
index 08f2af3..d335cde 100644
--- a/chrome/browser/extensions/extensions_ui.cc
+++ b/chrome/browser/extensions/extensions_ui.cc
@@ -15,6 +15,7 @@
#include "base/thread.h"
#include "base/version.h"
#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/debugger/devtools_manager.h"
#include "chrome/browser/debugger/devtools_toggle_action.h"
@@ -115,6 +116,8 @@ void ExtensionsUIHTMLSource::StartDataRequest(const std::string& path,
l10n_util::GetStringUTF16(IDS_EXTENSIONS_DISABLED_EXTENSION));
localized_strings.SetString("inDevelopment",
l10n_util::GetStringUTF16(IDS_EXTENSIONS_IN_DEVELOPMENT));
+ localized_strings.SetString("viewIncognito",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_VIEW_INCOGNITO));
localized_strings.SetString("extensionId",
l10n_util::GetStringUTF16(IDS_EXTENSIONS_ID));
localized_strings.SetString("extensionVersion",
@@ -317,18 +320,14 @@ void ExtensionsDOMHandler::HandleRequestExtensionsData(const ListValue* args) {
std::vector<ExtensionResource>* extension_icons =
new std::vector<ExtensionResource>();
- ExtensionProcessManager* process_manager =
- extensions_service_->profile()->GetExtensionProcessManager();
const ExtensionList* extensions = extensions_service_->extensions();
for (ExtensionList::const_iterator extension = extensions->begin();
extension != extensions->end(); ++extension) {
if (ShouldShowExtension(*extension)) {
- RenderProcessHost* process =
- process_manager->GetExtensionProcess((*extension)->url());
extensions_list->Append(CreateExtensionDetailValue(
extensions_service_.get(),
*extension,
- GetActivePagesForExtension(process, *extension),
+ GetActivePagesForExtension(*extension),
true)); // enabled
extension_icons->push_back(PickExtensionIcon(*extension));
}
@@ -337,12 +336,10 @@ void ExtensionsDOMHandler::HandleRequestExtensionsData(const ListValue* args) {
for (ExtensionList::const_iterator extension = extensions->begin();
extension != extensions->end(); ++extension) {
if (ShouldShowExtension(*extension)) {
- RenderProcessHost* process =
- process_manager->GetExtensionProcess((*extension)->url());
extensions_list->Append(CreateExtensionDetailValue(
extensions_service_.get(),
*extension,
- GetActivePagesForExtension(process, *extension),
+ GetActivePagesForExtension(*extension),
false)); // enabled
extension_icons->push_back(PickExtensionIcon(*extension));
}
@@ -836,6 +833,7 @@ DictionaryValue* ExtensionsDOMHandler::CreateExtensionDetailValue(
}
view_value->SetInteger("renderViewId", iter->render_view_id);
view_value->SetInteger("renderProcessId", iter->render_process_id);
+ view_value->SetBoolean("incognito", iter->incognito);
views->Append(view_value);
}
extension_data->Set("views", views);
@@ -847,11 +845,36 @@ DictionaryValue* ExtensionsDOMHandler::CreateExtensionDetailValue(
}
std::vector<ExtensionPage> ExtensionsDOMHandler::GetActivePagesForExtension(
- RenderProcessHost* process,
Extension* extension) {
std::vector<ExtensionPage> result;
+
+ // Get the extension process's active views.
+ ExtensionProcessManager* process_manager =
+ extensions_service_->profile()->GetExtensionProcessManager();
+ GetActivePagesForExtensionProcess(
+ process_manager->GetExtensionProcess(extension->url()),
+ extension, &result);
+
+ // Repeat for the incognito process, if applicable.
+ if (extensions_service_->profile()->HasOffTheRecordProfile() &&
+ extension->incognito_split_mode()) {
+ ExtensionProcessManager* process_manager =
+ extensions_service_->profile()->GetOffTheRecordProfile()->
+ GetExtensionProcessManager();
+ GetActivePagesForExtensionProcess(
+ process_manager->GetExtensionProcess(extension->url()),
+ extension, &result);
+ }
+
+ return result;
+}
+
+void ExtensionsDOMHandler::GetActivePagesForExtensionProcess(
+ RenderProcessHost* process,
+ Extension* extension,
+ std::vector<ExtensionPage> *result) {
if (!process)
- return result;
+ return;
RenderProcessHost::listeners_iterator iter = process->ListenersIterator();
for (; !iter.IsAtEnd(); iter.Advance()) {
@@ -873,10 +896,9 @@ std::vector<ExtensionPage> ExtensionsDOMHandler::GetActivePagesForExtension(
continue;
}
- result.push_back(ExtensionPage(url, process->id(), host->routing_id()));
+ result->push_back(ExtensionPage(url, process->id(), host->routing_id(),
+ process->profile()->IsOffTheRecord()));
}
-
- return result;
}
ExtensionsDOMHandler::~ExtensionsDOMHandler() {
diff --git a/chrome/browser/extensions/extensions_ui.h b/chrome/browser/extensions/extensions_ui.h
index fb186fc..0d961a1 100644
--- a/chrome/browser/extensions/extensions_ui.h
+++ b/chrome/browser/extensions/extensions_ui.h
@@ -32,12 +32,14 @@ class UserScript;
// Information about a page running in an extension, for example a toolstrip,
// a background page, or a tab contents.
struct ExtensionPage {
- ExtensionPage(const GURL& url, int render_process_id, int render_view_id)
+ ExtensionPage(const GURL& url, int render_process_id, int render_view_id,
+ bool incognito)
: url(url), render_process_id(render_process_id),
- render_view_id(render_view_id) {}
+ render_view_id(render_view_id), incognito(incognito) {}
GURL url;
int render_process_id;
int render_view_id;
+ bool incognito;
};
class ExtensionsUIHTMLSource : public ChromeURLDataManager::DataSource {
@@ -196,9 +198,11 @@ class ExtensionsDOMHandler
const NotificationDetails& details);
// Helper that lists the current active html pages for an extension.
- std::vector<ExtensionPage> GetActivePagesForExtension(
+ std::vector<ExtensionPage> GetActivePagesForExtension(Extension* extension);
+ void GetActivePagesForExtensionProcess(
RenderProcessHost* process,
- Extension* extension);
+ Extension* extension,
+ std::vector<ExtensionPage> *result);
// Returns the best icon to display in the UI for an extension, or an empty
// ExtensionResource if no good icon exists.
diff --git a/chrome/browser/net/chrome_url_request_context.cc b/chrome/browser/net/chrome_url_request_context.cc
index c4104a5..f14958f 100644
--- a/chrome/browser/net/chrome_url_request_context.cc
+++ b/chrome/browser/net/chrome_url_request_context.cc
@@ -325,15 +325,18 @@ ChromeURLRequestContext* FactoryForOriginal::Create() {
// Factory that creates the ChromeURLRequestContext for extensions.
class FactoryForExtensions : public ChromeURLRequestContextFactory {
public:
- FactoryForExtensions(Profile* profile, const FilePath& cookie_store_path)
+ FactoryForExtensions(Profile* profile, const FilePath& cookie_store_path,
+ bool incognito)
: ChromeURLRequestContextFactory(profile),
- cookie_store_path_(cookie_store_path) {
+ cookie_store_path_(cookie_store_path),
+ incognito_(incognito) {
}
virtual ChromeURLRequestContext* Create();
private:
FilePath cookie_store_path_;
+ bool incognito_;
};
ChromeURLRequestContext* FactoryForExtensions::Create() {
@@ -342,11 +345,14 @@ ChromeURLRequestContext* FactoryForExtensions::Create() {
IOThread::Globals* io_thread_globals = io_thread()->globals();
- // All we care about for extensions is the cookie store.
- DCHECK(!cookie_store_path_.empty());
+ // All we care about for extensions is the cookie store. For incognito, we
+ // use a non-persistent cookie store.
+ scoped_refptr<SQLitePersistentCookieStore> cookie_db = NULL;
+ if (!incognito_) {
+ DCHECK(!cookie_store_path_.empty());
+ cookie_db = new SQLitePersistentCookieStore(cookie_store_path_);
+ }
- scoped_refptr<SQLitePersistentCookieStore> cookie_db =
- new SQLitePersistentCookieStore(cookie_store_path_);
net::CookieMonster* cookie_monster =
new net::CookieMonster(cookie_db.get(), NULL);
@@ -624,7 +630,7 @@ ChromeURLRequestContextGetter::CreateOriginalForExtensions(
DCHECK(!profile->IsOffTheRecord());
return new ChromeURLRequestContextGetter(
profile,
- new FactoryForExtensions(profile, cookie_store_path));
+ new FactoryForExtensions(profile, cookie_store_path, false));
}
// static
@@ -635,6 +641,15 @@ ChromeURLRequestContextGetter::CreateOffTheRecord(Profile* profile) {
profile, new FactoryForOffTheRecord(profile));
}
+// static
+ChromeURLRequestContextGetter*
+ChromeURLRequestContextGetter::CreateOffTheRecordForExtensions(
+ Profile* profile) {
+ DCHECK(profile->IsOffTheRecord());
+ return new ChromeURLRequestContextGetter(
+ profile, new FactoryForExtensions(profile, FilePath(), true));
+}
+
void ChromeURLRequestContextGetter::CleanupOnUIThread() {
CheckCurrentlyOnMainThread();
@@ -798,6 +813,13 @@ bool ChromeURLRequestContext::ExtensionHasWebExtent(const std::string& id) {
return iter != extension_info_.end() && !iter->second->extent.is_empty();
}
+bool ChromeURLRequestContext::ExtensionCanLoadInIncognito(
+ const std::string& id) {
+ ExtensionInfoMap::iterator iter = extension_info_.find(id);
+ // Only split-mode extensions can load in incognito profiles.
+ return iter != extension_info_.end() && iter->second->incognito_split_mode;
+}
+
std::string ChromeURLRequestContext::GetDefaultLocaleForExtension(
const std::string& id) {
ExtensionInfoMap::iterator iter = extension_info_.find(id);
@@ -852,14 +874,11 @@ const std::string& ChromeURLRequestContext::GetUserAgent(
void ChromeURLRequestContext::OnNewExtensions(const std::string& id,
ExtensionInfo* info) {
- if (!is_off_the_record_)
- extension_info_[id] = linked_ptr<ExtensionInfo>(info);
+ extension_info_[id] = linked_ptr<ExtensionInfo>(info);
}
void ChromeURLRequestContext::OnUnloadedExtension(const std::string& id) {
CheckCurrentlyOnIOThread();
- if (is_off_the_record_)
- return;
ExtensionInfoMap::iterator iter = extension_info_.find(id);
if (iter != extension_info_.end()) {
extension_info_.erase(iter);
@@ -976,6 +995,7 @@ ChromeURLRequestContextFactory::ChromeURLRequestContextFactory(Profile* profile)
(*iter)->name(),
(*iter)->path(),
(*iter)->default_locale(),
+ (*iter)->incognito_split_mode(),
(*iter)->web_extent(),
(*iter)->GetEffectiveHostPermissions(),
(*iter)->api_permissions()));
diff --git a/chrome/browser/net/chrome_url_request_context.h b/chrome/browser/net/chrome_url_request_context.h
index 2638d46..97997e3 100644
--- a/chrome/browser/net/chrome_url_request_context.h
+++ b/chrome/browser/net/chrome_url_request_context.h
@@ -51,12 +51,17 @@ class ChromeURLRequestContext : public URLRequestContext {
// could be immutable and ref-counted so that we could use them directly from
// both threads. There is only a small amount of mutable state in Extension.
struct ExtensionInfo {
- ExtensionInfo(const std::string& name, const FilePath& path,
+ ExtensionInfo(const std::string& name,
+ const FilePath& path,
const std::string& default_locale,
+ bool incognito_split_mode,
const ExtensionExtent& extent,
const ExtensionExtent& effective_host_permissions,
const std::vector<std::string>& api_permissions)
- : name(name), path(path), default_locale(default_locale),
+ : name(name),
+ path(path),
+ default_locale(default_locale),
+ incognito_split_mode(incognito_split_mode),
extent(extent),
effective_host_permissions(effective_host_permissions),
api_permissions(api_permissions) {
@@ -64,6 +69,7 @@ class ChromeURLRequestContext : public URLRequestContext {
const std::string name;
const FilePath path;
const std::string default_locale;
+ const bool incognito_split_mode;
const ExtensionExtent extent;
const ExtensionExtent effective_host_permissions;
std::vector<std::string> api_permissions;
@@ -84,6 +90,10 @@ class ChromeURLRequestContext : public URLRequestContext {
// extent.
bool ExtensionHasWebExtent(const std::string& id);
+ // Returns true if the specified extension exists and can load in incognito
+ // contexts.
+ bool ExtensionCanLoadInIncognito(const std::string& id);
+
// Returns an empty string if the extension with |id| doesn't have a default
// locale.
std::string GetDefaultLocaleForExtension(const std::string& id);
@@ -312,6 +322,11 @@ class ChromeURLRequestContextGetter : public URLRequestContextGetter,
// called on the UI thread.
static ChromeURLRequestContextGetter* CreateOffTheRecord(Profile* profile);
+ // Create an instance for an OTR profile for extensions. This is expected
+ // to get called on UI thread.
+ 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 2f1641e..5c3669c 100644
--- a/chrome/browser/profile.cc
+++ b/chrome/browser/profile.cc
@@ -18,6 +18,8 @@
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/file_system/file_system_host_context.h"
+#include "chrome/browser/extensions/extension_message_service.h"
+#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/find_bar_state.h"
#include "chrome/browser/in_process_webkit/webkit_context.h"
#include "chrome/browser/net/chrome_url_request_context.h"
@@ -119,6 +121,7 @@ class OffTheRecordProfileImpl : public Profile,
: profile_(real_profile),
start_time_(Time::Now()) {
request_context_ = ChromeURLRequestContextGetter::CreateOffTheRecord(this);
+ extension_process_manager_.reset(ExtensionProcessManager::Create(this));
// Register for browser close notifications so we can detect when the last
// off-the-record window is closed, in which case we can clean our states
@@ -134,6 +137,7 @@ class OffTheRecordProfileImpl : public Profile,
Source<Profile>(this),
NotificationService::NoDetails());
CleanupRequestContext(request_context_);
+ CleanupRequestContext(extensions_request_context_);
// Clean up all DB files/directories
ChromeThread::PostTask(
@@ -220,7 +224,7 @@ class OffTheRecordProfileImpl : public Profile,
}
virtual ExtensionProcessManager* GetExtensionProcessManager() {
- return GetOriginalProfile()->GetExtensionProcessManager();
+ return extension_process_manager_.get();
}
virtual ExtensionMessageService* GetExtensionMessageService() {
@@ -357,7 +361,12 @@ class OffTheRecordProfileImpl : public Profile,
}
URLRequestContextGetter* GetRequestContextForExtensions() {
- return GetOriginalProfile()->GetRequestContextForExtensions();
+ if (!extensions_request_context_) {
+ extensions_request_context_ =
+ ChromeURLRequestContextGetter::CreateOffTheRecordForExtensions(this);
+ }
+
+ return extensions_request_context_;
}
virtual net::SSLConfigService* GetSSLConfigService() {
@@ -543,9 +552,14 @@ class OffTheRecordProfileImpl : public Profile,
// The real underlying profile.
Profile* profile_;
+ scoped_ptr<ExtensionProcessManager> extension_process_manager_;
+
// The context to use for requests made from this OTR session.
scoped_refptr<ChromeURLRequestContextGetter> request_context_;
+ // The context to use for requests made by an extension while in OTR mode.
+ 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/profile_impl.cc b/chrome/browser/profile_impl.cc
index e81cef4..6a7cb51 100644
--- a/chrome/browser/profile_impl.cc
+++ b/chrome/browser/profile_impl.cc
@@ -172,6 +172,7 @@ void PostExtensionLoadedToContextGetter(ChromeURLRequestContextGetter* getter,
extension->name(),
extension->path(),
extension->default_locale(),
+ extension->incognito_split_mode(),
extension->web_extent(),
extension->GetEffectiveHostPermissions(),
extension->api_permissions())));
@@ -369,7 +370,7 @@ void ProfileImpl::InitExtensions() {
extension_devtools_manager_ = new ExtensionDevToolsManager(this);
}
- extension_process_manager_.reset(new ExtensionProcessManager(this));
+ extension_process_manager_.reset(ExtensionProcessManager::Create(this));
extension_message_service_ = new ExtensionMessageService(this);
ExtensionErrorReporter::Init(true); // allow noisy errors.
@@ -737,6 +738,9 @@ URLRequestContextGetter* ProfileImpl::GetRequestContextForExtensions() {
return extensions_request_context_;
}
+// TODO(mpcomplete): This is lame. 5+ copies of the extension data on the IO
+// thread. We should have 1 shared data object that all the contexts get access
+// to. Fix by M8.
void ProfileImpl::RegisterExtensionWithRequestContexts(
Extension* extension) {
// Notify the default, extension and media contexts on the IO thread.
@@ -751,6 +755,19 @@ void ProfileImpl::RegisterExtensionWithRequestContexts(
static_cast<ChromeURLRequestContextGetter*>(
GetRequestContextForMedia()),
extension);
+
+ // Ditto for OTR if it's active, except for the media context which is the
+ // same as the regular context.
+ if (off_the_record_profile_.get()) {
+ PostExtensionLoadedToContextGetter(
+ static_cast<ChromeURLRequestContextGetter*>(
+ off_the_record_profile_->GetRequestContext()),
+ extension);
+ PostExtensionLoadedToContextGetter(
+ static_cast<ChromeURLRequestContextGetter*>(
+ off_the_record_profile_->GetRequestContextForExtensions()),
+ extension);
+ }
}
void ProfileImpl::UnregisterExtensionWithRequestContexts(
@@ -767,6 +784,19 @@ void ProfileImpl::UnregisterExtensionWithRequestContexts(
static_cast<ChromeURLRequestContextGetter*>(
GetRequestContextForMedia()),
extension);
+
+ // Ditto for OTR if it's active, except for the media context which is the
+ // same as the regular context.
+ if (off_the_record_profile_.get()) {
+ PostExtensionUnloadedToContextGetter(
+ static_cast<ChromeURLRequestContextGetter*>(
+ off_the_record_profile_->GetRequestContext()),
+ extension);
+ PostExtensionUnloadedToContextGetter(
+ static_cast<ChromeURLRequestContextGetter*>(
+ off_the_record_profile_->GetRequestContextForExtensions()),
+ extension);
+ }
}
net::SSLConfigService* ProfileImpl::GetSSLConfigService() {
diff --git a/chrome/browser/resources/extensions_ui.html b/chrome/browser/resources/extensions_ui.html
index 5e9b020..a5671a424 100644
--- a/chrome/browser/resources/extensions_ui.html
+++ b/chrome/browser/resources/extensions_ui.html
@@ -378,12 +378,14 @@ var extensionDataFormat = {
{
'path': 'toolstrip.html',
'renderViewId': 1,
- 'renderProcessId': 1
+ 'renderProcessId': 1,
+ 'incognito': false
},
{
'path': 'background.html',
'renderViewId': 2,
- 'renderProcessId': 1
+ 'renderProcessId': 1,
+ 'incognito': false
}
]
},
@@ -415,7 +417,8 @@ var extensionDataFormat = {
{
'path': 'foo/bar/toolstrip.html',
'renderViewId': 3,
- 'renderProcessId': 1
+ 'renderProcessId': 1,
+ 'incognito': false
}
],
"hasPopupAction": false
@@ -856,10 +859,13 @@ document.addEventListener('DOMContentLoaded', requestExtensionsData);
</span>
<ul class="extension-views">
<li jsselect="views">
- <a jsvalues=".extensionView:$this" href="#"
- onclick="sendInspectMessage(this.extensionView); return false;">
- <span jscontent="path"></span>
- </a>
+ <span jsvalues=".extensionView:$this">
+ <a jsvalues=".extensionView:$this" href="#"
+ onclick="sendInspectMessage(this.extensionView); return false;">
+ <span jscontent="path"></span></a>
+ <span jsdisplay="incognito"
+ i18n-content="viewIncognito">(INCOGNITO)</span>
+ </span>
</li>
<li i18n-content="inspectPopupsInstructions"
class="inspectPopupNote" jsdisplay="hasPopupAction">
diff --git a/chrome/browser/task_manager_resource_providers.cc b/chrome/browser/task_manager_resource_providers.cc
index 2b41233..1207462 100644
--- a/chrome/browser/task_manager_resource_providers.cc
+++ b/chrome/browser/task_manager_resource_providers.cc
@@ -529,8 +529,16 @@ TaskManagerExtensionProcessResource::TaskManagerExtensionProcessResource(
pid_ = base::GetProcId(process_handle_);
std::wstring extension_name(UTF8ToWide(GetExtension()->name()));
DCHECK(!extension_name.empty());
- title_ = l10n_util::GetStringF(IDS_TASK_MANAGER_EXTENSION_PREFIX,
- extension_name);
+
+ int message_id =
+ GetExtension()->is_app() ?
+ (extension_host_->profile()->IsOffTheRecord() ?
+ IDS_TASK_MANAGER_APP_INCOGNITO_PREFIX :
+ IDS_TASK_MANAGER_APP_PREFIX) :
+ (extension_host_->profile()->IsOffTheRecord() ?
+ IDS_TASK_MANAGER_EXTENSION_INCOGNITO_PREFIX :
+ IDS_TASK_MANAGER_EXTENSION_PREFIX);
+ title_ = l10n_util::GetStringF(message_id, extension_name);
}
TaskManagerExtensionProcessResource::~TaskManagerExtensionProcessResource() {
@@ -586,13 +594,25 @@ void TaskManagerExtensionProcessResourceProvider::StartUpdating() {
ProfileManager* profile_manager = g_browser_process->profile_manager();
for (ProfileManager::const_iterator it = profile_manager->begin();
it != profile_manager->end(); ++it) {
+ ExtensionProcessManager* process_manager =
+ (*it)->GetExtensionProcessManager();
+ if (process_manager) {
+ ExtensionProcessManager::const_iterator jt;
+ for (jt = process_manager->begin(); jt != process_manager->end(); ++jt)
+ AddToTaskManager(*jt);
+ }
+
+ // If we have an incognito profile active, include the split-mode incognito
+ // extensions.
+ if (BrowserList::IsOffTheRecordSessionActive()) {
ExtensionProcessManager* process_manager =
- (*it)->GetExtensionProcessManager();
- if (!process_manager)
- continue;
+ (*it)->GetOffTheRecordProfile()->GetExtensionProcessManager();
+ if (process_manager) {
ExtensionProcessManager::const_iterator jt;
for (jt = process_manager->begin(); jt != process_manager->end(); ++jt)
AddToTaskManager(*jt);
+ }
+ }
}
// Register for notifications about extension process changes.
diff --git a/chrome/browser/views/location_bar/icon_label_bubble_view.cc b/chrome/browser/views/location_bar/icon_label_bubble_view.cc
index 0f7059b..1e0159b 100644
--- a/chrome/browser/views/location_bar/icon_label_bubble_view.cc
+++ b/chrome/browser/views/location_bar/icon_label_bubble_view.cc
@@ -20,7 +20,8 @@ static const int kLabelPadding = 5;
IconLabelBubbleView::IconLabelBubbleView(const int background_images[],
int contained_image,
const SkColor& color)
- : background_painter_(background_images) {
+ : background_painter_(background_images),
+ item_padding_(LocationBarView::kItemPadding) {
image_ = new views::ImageView();
AddChildView(image_);
image_->SetImage(
@@ -60,7 +61,7 @@ void IconLabelBubbleView::Layout() {
height());
const int label_height = label_->GetPreferredSize().height();
label_->SetBounds(image_->x() + image_->width() +
- LocationBarView::kItemPadding, (height() - label_height) / 2,
+ item_padding_ , (height() - label_height) / 2,
width() - GetNonLabelWidth(), label_height);
}
@@ -74,5 +75,5 @@ gfx::Size IconLabelBubbleView::GetNonLabelSize() {
int IconLabelBubbleView::GetNonLabelWidth() {
return kBubbleOuterPadding + image_->GetPreferredSize().width() +
- LocationBarView::kItemPadding + kBubbleOuterPadding;
+ item_padding_ + kBubbleOuterPadding;
}
diff --git a/chrome/browser/views/location_bar/icon_label_bubble_view.h b/chrome/browser/views/location_bar/icon_label_bubble_view.h
index de252dd..d2e4b78 100644
--- a/chrome/browser/views/location_bar/icon_label_bubble_view.h
+++ b/chrome/browser/views/location_bar/icon_label_bubble_view.h
@@ -36,6 +36,7 @@ class IconLabelBubbleView : public views::View {
void SetFont(const gfx::Font& font);
void SetLabel(const std::wstring& label);
void SetImage(const SkBitmap& bitmap);
+ void SetItemPadding(int padding) { item_padding_ = padding; }
virtual void Paint(gfx::Canvas* canvas);
virtual gfx::Size GetPreferredSize();
@@ -55,6 +56,8 @@ class IconLabelBubbleView : public views::View {
views::ImageView* image_;
views::Label* label_;
+ int item_padding_;
+
DISALLOW_IMPLICIT_CONSTRUCTORS(IconLabelBubbleView);
};
diff --git a/chrome/browser/views/location_bar/location_bar_view.cc b/chrome/browser/views/location_bar/location_bar_view.cc
index fdfdacc..c3ef4c0 100644
--- a/chrome/browser/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/views/location_bar/location_bar_view.cc
@@ -48,6 +48,7 @@ using views::View;
const int LocationBarView::kNormalHorizontalEdgeThickness = 1;
const int LocationBarView::kVerticalEdgeThickness = 2;
const int LocationBarView::kItemPadding = 3;
+const int LocationBarView::kExtensionItemPadding = 5;
const int LocationBarView::kEdgeItemPadding = kItemPadding;
const int LocationBarView::kBubblePadding = 1;
const char LocationBarView::kViewClassName[] =
@@ -490,9 +491,11 @@ void LocationBarView::Layout() {
const SkBitmap& bitmap = profile_->GetExtensionsService()->
GetOmniboxIcon(template_url->GetExtensionId());
selected_keyword_view_->SetImage(bitmap);
+ selected_keyword_view_->SetItemPadding(kExtensionItemPadding);
} else {
selected_keyword_view_->SetImage(*ResourceBundle::GetSharedInstance().
GetBitmapNamed(IDR_OMNIBOX_SEARCH));
+ selected_keyword_view_->SetItemPadding(kItemPadding);
}
}
} else if (show_keyword_hint) {
diff --git a/chrome/browser/views/location_bar/location_bar_view.h b/chrome/browser/views/location_bar/location_bar_view.h
index ebace6b..281fee7 100644
--- a/chrome/browser/views/location_bar/location_bar_view.h
+++ b/chrome/browser/views/location_bar/location_bar_view.h
@@ -231,6 +231,9 @@ class LocationBarView : public LocationBar,
static const int kVerticalEdgeThickness;
// Space between items in the location bar.
static const int kItemPadding;
+ // Space between items in the location bar when an extension keyword is
+ // showing.
+ static const int kExtensionItemPadding;
// Space between the edges and the items next to them.
static const int kEdgeItemPadding;
// Space between the edge and a bubble.