diff options
author | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-09 06:45:46 +0000 |
---|---|---|
committer | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-09 06:45:46 +0000 |
commit | 6f37144dd7bbeded7d56dc37952342fa09e5a7bc (patch) | |
tree | 313f077bdd22d3e361d066753f7672ec77006d0c | |
parent | 5790d92e12c225bfe1683c81cf223dcf64302d1d (diff) | |
download | chromium_src-6f37144dd7bbeded7d56dc37952342fa09e5a7bc.zip chromium_src-6f37144dd7bbeded7d56dc37952342fa09e5a7bc.tar.gz chromium_src-6f37144dd7bbeded7d56dc37952342fa09e5a7bc.tar.bz2 |
Extract a ProcessMap class from ExtensionProcessManager. This is a dumb data class that can be used on both the IO and UI threads to test extension/process associations.
BUG=95111,102617
TEST=Already covered by tests
Review URL: http://codereview.chromium.org/8387061
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@109194 0039d316-1c4b-4281-b951-d872f2087c98
34 files changed, 508 insertions, 420 deletions
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 946d7dd..365b2b2 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc @@ -193,16 +193,19 @@ RenderProcessHostPrivilege GetPrivilegeRequiredByUrl( RenderProcessHostPrivilege GetProcessPrivilege( RenderProcessHost* process_host, - ExtensionProcessManager* extension_process_manager) { - if (!extension_process_manager->IsExtensionProcess(process_host->id())) + extensions::ProcessMap* process_map, + ExtensionService* service) { + // TODO(aa): It seems like hosted apps should be grouped separately from + // extensions: crbug.com/102533. + std::set<std::string> extension_ids = + process_map->GetExtensionsInProcess(process_host->id()); + if (extension_ids.empty()) return PRIV_NORMAL; - std::set<const Extension*> extensions_for_process( - extension_process_manager->GetExtensionsForProcess(process_host->id())); - for (std::set<const Extension*>::iterator iter = - extensions_for_process.begin(); - iter != extensions_for_process.end(); ++iter) { - if ((*iter)->is_storage_isolated()) + for (std::set<std::string>::iterator iter = extension_ids.begin(); + iter != extension_ids.end(); ++iter) { + const Extension* extension = service->GetExtensionById(*iter, false); + if (extension && extension->is_storage_isolated()) return PRIV_ISOLATED; } @@ -396,13 +399,12 @@ bool ChromeContentBrowserClient::IsSuitableHost( const GURL& site_url) { Profile* profile = Profile::FromBrowserContext(process_host->browser_context()); - ExtensionProcessManager* extension_process_manager = - profile->GetExtensionProcessManager(); ExtensionService* service = profile->GetExtensionService(); + extensions::ProcessMap* process_map = service->process_map(); // These may be NULL during tests. In that case, just assume any site can // share any host. - if (!extension_process_manager || !service) + if (!service || !process_map) return true; // Experimental: @@ -415,10 +417,65 @@ bool ChromeContentBrowserClient::IsSuitableHost( if (command_line.HasSwitch(switches::kEnableStrictSiteIsolation)) return false; - return GetProcessPrivilege(process_host, extension_process_manager) == + return GetProcessPrivilege(process_host, process_map, service) == GetPrivilegeRequiredByUrl(site_url, service); } +void ChromeContentBrowserClient::SiteInstanceGotProcess( + SiteInstance* site_instance) { + CHECK(site_instance->HasProcess()); + + Profile* profile = Profile::FromBrowserContext( + site_instance->browsing_instance()->browser_context()); + ExtensionService* service = profile->GetExtensionService(); + if (!service) + return; + + const Extension* extension = + service->GetExtensionByURL(site_instance->site()); + if (!extension) + extension = service->GetExtensionByWebExtent(site_instance->site()); + if (!extension) + return; + + service->process_map()->Insert( + extension->id(), site_instance->GetProcess()->id()); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&ExtensionInfoMap::RegisterExtensionProcess, + profile->GetExtensionInfoMap(), + extension->id(), + site_instance->GetProcess()->id())); +} + +void ChromeContentBrowserClient::SiteInstanceDeleting( + SiteInstance* site_instance) { + if (!site_instance->HasProcess()) + return; + + Profile* profile = Profile::FromBrowserContext( + site_instance->browsing_instance()->browser_context()); + ExtensionService* service = profile->GetExtensionService(); + if (!service) + return; + + const Extension* extension = + service->GetExtensionByURL(site_instance->site()); + if (!extension) + extension = service->GetExtensionByWebExtent(site_instance->site()); + if (!extension) + return; + + service->process_map()->Remove( + extension->id(), site_instance->GetProcess()->id()); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&ExtensionInfoMap::UnregisterExtensionProcess, + profile->GetExtensionInfoMap(), + extension->id(), + site_instance->GetProcess()->id())); +} + bool ChromeContentBrowserClient::ShouldSwapProcessesForNavigation( const GURL& current_url, const GURL& new_url) { @@ -483,13 +540,10 @@ void ChromeContentBrowserClient::AppendExtraCommandLineSwitches( RenderProcessHost* process = RenderProcessHost::FromID(child_process_id); Profile* profile = Profile::FromBrowserContext(process->browser_context()); - - ExtensionProcessManager* extension_process_manager = - profile->GetExtensionProcessManager(); - if (extension_process_manager->IsExtensionProcess( - process->id())) { + extensions::ProcessMap* process_map = + profile->GetExtensionService()->process_map(); + if (process_map && process_map->Contains(process->id())) command_line->AppendSwitch(switches::kExtensionProcess); - } PrefService* prefs = profile->GetPrefs(); // Currently this pref is only registered if applied via a policy. diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index f978af8..14aba9d 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h @@ -35,6 +35,8 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient { virtual bool IsURLSameAsAnySiteInstance(const GURL& url) OVERRIDE; virtual bool IsSuitableHost(RenderProcessHost* process_host, const GURL& url) OVERRIDE; + virtual void SiteInstanceGotProcess(SiteInstance* site_instance) OVERRIDE; + virtual void SiteInstanceDeleting(SiteInstance* site_instance) OVERRIDE; virtual bool ShouldSwapProcessesForNavigation(const GURL& current_url, const GURL& new_url) OVERRIDE; virtual std::string GetCanonicalEncodingNameByAliasName( diff --git a/chrome/browser/extensions/app_process_apitest.cc b/chrome/browser/extensions/app_process_apitest.cc index 6872c1e..75f57b5 100644 --- a/chrome/browser/extensions/app_process_apitest.cc +++ b/chrome/browser/extensions/app_process_apitest.cc @@ -5,7 +5,8 @@ #include "base/utf_string_conversions.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_host.h" -#include "chrome/browser/extensions/extension_process_manager.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/process_map.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_list.h" @@ -84,8 +85,8 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, AppProcess) { CommandLine::ForCurrentProcess()->AppendSwitch( switches::kDisablePopupBlocking); - ExtensionProcessManager* extension_process_manager = - browser()->profile()->GetExtensionProcessManager(); + extensions::ProcessMap* process_map = + browser()->profile()->GetExtensionService()->process_map(); host_resolver()->AddRule("*", "127.0.0.1"); ASSERT_TRUE(test_server()->Start()); @@ -103,7 +104,7 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, AppProcess) { ui_test_utils::NavigateToURLWithDisposition( browser(), base_url.Resolve("path1/empty.html"), NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); - EXPECT_TRUE(extension_process_manager->IsExtensionProcess( + EXPECT_TRUE(process_map->Contains( browser()->GetTabContentsAt(1)->render_view_host()->process()->id())); EXPECT_FALSE(browser()->GetTabContentsAt(1)->web_ui()); LOG(INFO) << "Nav 1."; @@ -111,7 +112,7 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, AppProcess) { ui_test_utils::NavigateToURLWithDisposition( browser(), base_url.Resolve("path2/empty.html"), NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); - EXPECT_TRUE(extension_process_manager->IsExtensionProcess( + EXPECT_TRUE(process_map->Contains( browser()->GetTabContentsAt(2)->render_view_host()->process()->id())); EXPECT_FALSE(browser()->GetTabContentsAt(2)->web_ui()); LOG(INFO) << "Nav 2."; @@ -124,7 +125,7 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, AppProcess) { LOG(INFO) << "New tab."; ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path3/empty.html")); LOG(INFO) << "Nav 3."; - EXPECT_FALSE(extension_process_manager->IsExtensionProcess( + EXPECT_FALSE(process_map->Contains( browser()->GetTabContentsAt(3)->render_view_host()->process()->id())); EXPECT_FALSE(browser()->GetTabContentsAt(3)->web_ui()); @@ -196,8 +197,8 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, AppProcessInstances) { CommandLine::ForCurrentProcess()->AppendSwitch( switches::kDisablePopupBlocking); - ExtensionProcessManager* extension_process_manager = - browser()->profile()->GetExtensionProcessManager(); + extensions::ProcessMap* process_map = + browser()->profile()->GetExtensionService()->process_map(); host_resolver()->AddRule("*", "127.0.0.1"); ASSERT_TRUE(test_server()->Start()); @@ -215,7 +216,7 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, AppProcessInstances) { browser(), base_url.Resolve("path1/empty.html"), NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); LOG(INFO) << "Nav 1."; - EXPECT_TRUE(extension_process_manager->IsExtensionProcess( + EXPECT_TRUE(process_map->Contains( browser()->GetTabContentsAt(1)->render_view_host()->process()->id())); EXPECT_FALSE(browser()->GetTabContentsAt(1)->web_ui()); @@ -227,7 +228,7 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, AppProcessInstances) { LOG(INFO) << "New tab."; ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path2/empty.html")); LOG(INFO) << "Nav 2."; - EXPECT_TRUE(extension_process_manager->IsExtensionProcess( + EXPECT_TRUE(process_map->Contains( browser()->GetTabContentsAt(2)->render_view_host()->process()->id())); EXPECT_FALSE(browser()->GetTabContentsAt(2)->web_ui()); @@ -293,8 +294,8 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, DISABLED_ReloadIntoAppProcess) { CommandLine::ForCurrentProcess()->AppendSwitch( switches::kDisablePopupBlocking); - ExtensionProcessManager* extension_process_manager = - browser()->profile()->GetExtensionProcessManager(); + extensions::ProcessMap* process_map = + browser()->profile()->GetExtensionService()->process_map(); host_resolver()->AddRule("*", "127.0.0.1"); ASSERT_TRUE(test_server()->Start()); @@ -306,7 +307,7 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, DISABLED_ReloadIntoAppProcess) { // Load an app URL before loading the app. ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path1/empty.html")); TabContents* contents = browser()->GetTabContentsAt(0); - EXPECT_FALSE(extension_process_manager->IsExtensionProcess( + EXPECT_FALSE(process_map->Contains( contents->render_view_host()->process()->id())); // Load app and navigate to the page. @@ -314,13 +315,13 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, DISABLED_ReloadIntoAppProcess) { LoadExtension(test_data_dir_.AppendASCII("app_process")); ASSERT_TRUE(app); ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path1/empty.html")); - EXPECT_TRUE(extension_process_manager->IsExtensionProcess( + EXPECT_TRUE(process_map->Contains( contents->render_view_host()->process()->id())); // Disable app and navigate to the page. DisableExtension(app->id()); ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path1/empty.html")); - EXPECT_FALSE(extension_process_manager->IsExtensionProcess( + EXPECT_FALSE(process_map->Contains( contents->render_view_host()->process()->id())); // Enable app and reload the page. @@ -331,7 +332,7 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, DISABLED_ReloadIntoAppProcess) { &browser()->GetSelectedTabContentsWrapper()->controller())); browser()->Reload(CURRENT_TAB); reload_observer.Wait(); - EXPECT_TRUE(extension_process_manager->IsExtensionProcess( + EXPECT_TRUE(process_map->Contains( contents->render_view_host()->process()->id())); // Disable app and reload the page. @@ -342,7 +343,7 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, DISABLED_ReloadIntoAppProcess) { &browser()->GetSelectedTabContentsWrapper()->controller())); browser()->Reload(CURRENT_TAB); reload_observer2.Wait(); - EXPECT_FALSE(extension_process_manager->IsExtensionProcess( + EXPECT_FALSE(process_map->Contains( contents->render_view_host()->process()->id())); // Enable app and reload via JavaScript. @@ -354,7 +355,7 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, DISABLED_ReloadIntoAppProcess) { ASSERT_TRUE(ui_test_utils::ExecuteJavaScript(contents->render_view_host(), L"", L"location.reload();")); js_reload_observer.Wait(); - EXPECT_TRUE(extension_process_manager->IsExtensionProcess( + EXPECT_TRUE(process_map->Contains( contents->render_view_host()->process()->id())); // Disable app and reload via JavaScript. @@ -366,7 +367,7 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, DISABLED_ReloadIntoAppProcess) { ASSERT_TRUE(ui_test_utils::ExecuteJavaScript(contents->render_view_host(), L"", L"location.reload();")); js_reload_observer2.Wait(); - EXPECT_FALSE(extension_process_manager->IsExtensionProcess( + EXPECT_FALSE(process_map->Contains( contents->render_view_host()->process()->id())); } @@ -379,8 +380,8 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, OpenAppFromIframe) { CommandLine::ForCurrentProcess()->AppendSwitch( switches::kDisablePopupBlocking); - ExtensionProcessManager* extension_process_manager = - browser()->profile()->GetExtensionProcessManager(); + extensions::ProcessMap* process_map = + browser()->profile()->GetExtensionService()->process_map(); host_resolver()->AddRule("*", "127.0.0.1"); ASSERT_TRUE(test_server()->Start()); @@ -397,7 +398,7 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, OpenAppFromIframe) { CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION | ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER); - EXPECT_FALSE(extension_process_manager->IsExtensionProcess( + EXPECT_FALSE(process_map->Contains( browser()->GetTabContentsAt(0)->render_view_host()->process()->id())); // Wait for popup window to appear. @@ -419,7 +420,7 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, OpenAppFromIframe) { } // Popup window should be in the app's process. - EXPECT_TRUE(extension_process_manager->IsExtensionProcess( + EXPECT_TRUE(process_map->Contains( last_active_browser->GetTabContentsAt(0)->render_view_host()->process()-> id())); } @@ -435,8 +436,8 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, OpenWebPopupFromWebIframe) { CommandLine::ForCurrentProcess()->AppendSwitch( switches::kDisablePopupBlocking); - ExtensionProcessManager* extension_process_manager = - browser()->profile()->GetExtensionProcessManager(); + extensions::ProcessMap* process_map = + browser()->profile()->GetExtensionService()->process_map(); host_resolver()->AddRule("*", "127.0.0.1"); ASSERT_TRUE(test_server()->Start()); @@ -458,8 +459,7 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, OpenWebPopupFromWebIframe) { ui_test_utils::BROWSER_TEST_WAIT_FOR_BROWSER); RenderProcessHost* process = browser()->GetTabContentsAt(0)->render_view_host()->process(); - EXPECT_TRUE(extension_process_manager->IsExtensionProcess( - process->id())); + EXPECT_TRUE(process_map->Contains(process->id())); // Wait for popup window to appear. The new Browser may not have been // added with SetLastActive, in which case we need to show it first. @@ -485,8 +485,9 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, OpenWebPopupFromWebIframe) { } IN_PROC_BROWSER_TEST_F(AppApiTest, ReloadAppAfterCrash) { - ExtensionProcessManager* extension_process_manager = - browser()->profile()->GetExtensionProcessManager(); + extensions::ProcessMap* process_map = + browser()->profile()->GetExtensionService()->process_map(); + host_resolver()->AddRule("*", "127.0.0.1"); ASSERT_TRUE(test_server()->Start()); @@ -497,7 +498,7 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, ReloadAppAfterCrash) { // Load the app, chrome.app.isInstalled should be true. ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path1/empty.html")); TabContents* contents = browser()->GetTabContentsAt(0); - EXPECT_TRUE(extension_process_manager->IsExtensionProcess( + EXPECT_TRUE(process_map->Contains( contents->render_view_host()->process()->id())); bool is_installed = false; ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( diff --git a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc index ee1bec2..98f63f5 100644 --- a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc +++ b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc @@ -90,8 +90,10 @@ class ExtensionCrashRecoveryTest : public ExtensionBrowserTest { ASSERT_TRUE(extension_host); ASSERT_TRUE(GetExtensionProcessManager()->HasExtensionHost(extension_host)); ASSERT_TRUE(extension_host->IsRenderViewLive()); - ASSERT_EQ(extension_host->render_view_host()->process(), - GetExtensionProcessManager()->GetExtensionProcess(extension->id())); + extensions::ProcessMap* process_map = + browser()->profile()->GetExtensionService()->process_map(); + ASSERT_TRUE(process_map->Contains( + extension->id(), extension_host->render_view_host()->process()->id())); } void LoadTestExtension() { diff --git a/chrome/browser/extensions/extension_event_router.cc b/chrome/browser/extensions/extension_event_router.cc index 963477f..01b7c1b 100644 --- a/chrome/browser/extensions/extension_event_router.cc +++ b/chrome/browser/extensions/extension_event_router.cc @@ -15,6 +15,7 @@ #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_tabs_module.h" #include "chrome/browser/extensions/extension_webrequest_api.h" +#include "chrome/browser/extensions/process_map.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension.h" @@ -29,7 +30,7 @@ namespace { const char kDispatchEvent[] = "Event.dispatchJSON"; -static void NotifyEventListenerRemovedOnIOThread( +void NotifyEventListenerRemovedOnIOThread( void* profile, const std::string& extension_id, const std::string& sub_event_name) { @@ -257,16 +258,6 @@ void ExtensionEventRouter::DispatchEventImpl( // Send the event only to renderers that are listening for it. for (std::set<EventListener>::iterator listener = listeners.begin(); listener != listeners.end(); ++listener) { - Profile* listener_profile = Profile::FromBrowserContext( - listener->process->browser_context()); - ExtensionProcessManager* extension_process_manager = - listener_profile->GetExtensionProcessManager(); - if (!extension_process_manager->AreBindingsEnabledForProcess( - listener->process->id())) { - // Don't send browser-level events to unprivileged processes. - continue; - } - if (!event->extension_id.empty() && event->extension_id != listener->extension_id) continue; @@ -279,6 +270,13 @@ void ExtensionEventRouter::DispatchEventImpl( if (!extension) continue; + Profile* listener_profile = Profile::FromBrowserContext( + listener->process->browser_context()); + extensions::ProcessMap* process_map = + listener_profile->GetExtensionService()->process_map(); + if (!process_map->Contains(extension->id(), listener->process->id())) + continue; + // 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_incognito = event->restrict_to_profile && diff --git a/chrome/browser/extensions/extension_file_browser_private_api.cc b/chrome/browser/extensions/extension_file_browser_private_api.cc index f0af322..ee540d0 100644 --- a/chrome/browser/extensions/extension_file_browser_private_api.cc +++ b/chrome/browser/extensions/extension_file_browser_private_api.cc @@ -21,6 +21,7 @@ #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/browser/extensions/file_manager_util.h" +#include "chrome/browser/extensions/process_map.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/prefs/scoped_user_pref_update.h" #include "chrome/browser/profiles/profile.h" @@ -633,12 +634,17 @@ class ExecuteTasksFileSystemCallbackDispatcher const std::string task_id, const std::vector<GURL>& file_urls) : function_(function), + process_id_(0), profile_(profile), source_url_(source_url), extension_(extension), task_id_(task_id), origin_file_urls_(file_urls) { DCHECK(function_); + if (function_->render_view_host() && + function_->render_view_host()->process()) { + process_id_ = function_->render_view_host()->process()->id(); + } } // fileapi::FileSystemCallbackDispatcher overrides. @@ -708,10 +714,13 @@ class ExecuteTasksFileSystemCallbackDispatcher // Checks legitimacy of file url and grants file RO access permissions from // handler (target) extension and its renderer process. bool SetupFileAccessPermissions(const GURL& origin_file_url, - GURL* target_file_url, FilePath* file_path, bool* is_directory) { + GURL* target_file_url, FilePath* file_path, bool* is_directory) { if (!extension_.get()) return false; + if (process_id_ == 0) + return false; + GURL file_origin_url; FilePath virtual_path; fileapi::FileSystemType type; @@ -776,19 +785,13 @@ class ExecuteTasksFileSystemCallbackDispatcher // TODO(zelidrag): Add explicit R/W + R/O permissions for non-component // extensions. - // Get target extension's process. - RenderProcessHost* target_host = - profile_->GetExtensionProcessManager()->GetExtensionProcess( - target_extension_id); - if (!target_host) - return false; - // Grant R/O access permission to non-component extension and R/W to // component extensions. ChildProcessSecurityPolicy::GetInstance()->GrantPermissionsForFile( - target_host->id(), final_file_path, + process_id_, + final_file_path, extension_->location() != Extension::COMPONENT ? - kReadOnlyFilePermissions : kReadWriteFilePermissions); + kReadOnlyFilePermissions : kReadWriteFilePermissions); // Grant access to this particular file to target extension. This will // ensure that the target extension can access only this FS entry and @@ -809,6 +812,7 @@ class ExecuteTasksFileSystemCallbackDispatcher } ExecuteTasksFileBrowserFunction* function_; + int process_id_; Profile* profile_; // Extension source URL. GURL source_url_; diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc index 068ae7a..4d0c94b 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.cc +++ b/chrome/browser/extensions/extension_function_dispatcher.cc @@ -527,17 +527,10 @@ void ExtensionFunctionDispatcher::DispatchOnIOThread( const Extension* extension = extension_info_map->extensions().GetByURL(params.source_url); - if (!extension_info_map->IsExtensionInProcess(extension->id(), - render_process_id)) { - // TODO(aa): Allow content scripts access to low-threat extension APIs. - // See: crbug.com/80308. - LOG(ERROR) << "Extension API called from non-extension process."; - SendAccessDenied(ipc_sender, routing_id, params.request_id); - return; - } - - scoped_refptr<ExtensionFunction> function(CreateExtensionFunction( - params, extension, profile, ipc_sender, routing_id)); + scoped_refptr<ExtensionFunction> function( + CreateExtensionFunction(params, extension, render_process_id, + extension_info_map->process_map(), profile, + ipc_sender, routing_id)); if (!function) return; @@ -600,27 +593,9 @@ void ExtensionFunctionDispatcher::Dispatch( const ExtensionHostMsg_Request_Params& params, RenderViewHost* render_view_host) { ExtensionService* service = profile()->GetExtensionService(); - ExtensionProcessManager* extension_process_manager = - profile()->GetExtensionProcessManager(); - if (!service || !extension_process_manager) - return; - - if (!service->ExtensionBindingsAllowed(params.source_url)) { - LOG(ERROR) << "Extension bindings not allowed for URL: " - << params.source_url.spec(); - SendAccessDenied(render_view_host, render_view_host->routing_id(), - params.request_id); + extensions::ProcessMap* process_map = service->process_map(); + if (!service || !process_map) return; - } - if (!extension_process_manager->AreBindingsEnabledForProcess( - render_view_host->process()->id())) { - // TODO(aa): Allow content scripts access to low-threat extension APIs. - // See: crbug.com/80308. - LOG(ERROR) << "Extension API called from non-extension process."; - SendAccessDenied(render_view_host, render_view_host->routing_id(), - params.request_id); - return; - } // TODO(aa): When we allow content scripts to call extension APIs, we will // have to pass the extension ID explicitly here, not use the source URL. @@ -629,7 +604,10 @@ void ExtensionFunctionDispatcher::Dispatch( extension = service->GetExtensionByWebExtent(params.source_url); scoped_refptr<ExtensionFunction> function( - CreateExtensionFunction(params, extension, profile(), render_view_host, + CreateExtensionFunction(params, extension, + render_view_host->process()->id(), + *(service->process_map()), + profile(), render_view_host, render_view_host->routing_id())); if (!function) return; @@ -661,12 +639,21 @@ void ExtensionFunctionDispatcher::Dispatch( ExtensionFunction* ExtensionFunctionDispatcher::CreateExtensionFunction( const ExtensionHostMsg_Request_Params& params, const Extension* extension, + int requesting_process_id, + const extensions::ProcessMap& process_map, void* profile, IPC::Message::Sender* ipc_sender, int routing_id) { if (!extension) { - LOG(ERROR) << "Extension does not exist for URL: " - << params.source_url.spec(); + LOG(ERROR) << "Specified extension does not exist."; + SendAccessDenied(ipc_sender, routing_id, params.request_id); + return NULL; + } + + if (!process_map.Contains(extension->id(), requesting_process_id)) { + LOG(ERROR) << "Extension API called from incorrect process " + << requesting_process_id + << " from URL " << params.source_url.spec(); SendAccessDenied(ipc_sender, routing_id, params.request_id); return NULL; } diff --git a/chrome/browser/extensions/extension_function_dispatcher.h b/chrome/browser/extensions/extension_function_dispatcher.h index a45efc4c..fd4c7da 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.h +++ b/chrome/browser/extensions/extension_function_dispatcher.h @@ -24,6 +24,10 @@ class RenderViewHost; class TabContents; struct ExtensionHostMsg_Request_Params; +namespace extensions { +class ProcessMap; +} + // A factory function for creating new ExtensionFunction instances. typedef ExtensionFunction* (*ExtensionFunctionFactory)(); @@ -117,6 +121,8 @@ class ExtensionFunctionDispatcher static ExtensionFunction* CreateExtensionFunction( const ExtensionHostMsg_Request_Params& params, const Extension* extension, + int requesting_process_id, + const extensions::ProcessMap& process_map, void* profile, IPC::Message::Sender* ipc_sender, int routing_id); diff --git a/chrome/browser/extensions/extension_info_map.cc b/chrome/browser/extensions/extension_info_map.cc index ed3fd7d..01ee98b 100644 --- a/chrome/browser/extensions/extension_info_map.cc +++ b/chrome/browser/extensions/extension_info_map.cc @@ -44,6 +44,10 @@ ExtensionInfoMap::ExtensionInfoMap() { ExtensionInfoMap::~ExtensionInfoMap() { } +const extensions::ProcessMap& ExtensionInfoMap::process_map() const { + return process_map_; +} + void ExtensionInfoMap::AddExtension(const Extension* extension, base::Time install_time, bool incognito_enabled) { @@ -102,29 +106,23 @@ bool ExtensionInfoMap::CanCrossIncognito(const Extension* extension) { void ExtensionInfoMap::RegisterExtensionProcess(const std::string& extension_id, int process_id) { - DCHECK(!IsExtensionInProcess(extension_id, process_id)); - extension_process_ids_.insert( - ExtensionProcessIDMap::value_type(extension_id, process_id)); + if (!process_map_.Insert(extension_id, process_id)) { + NOTREACHED() << "Duplicate extension process registration for: " + << extension_id << "," << process_id << "."; + } } void ExtensionInfoMap::UnregisterExtensionProcess( const std::string& extension_id, int process_id) { - ExtensionProcessIDMap::iterator iter = - std::find(extension_process_ids_.begin(), - extension_process_ids_.end(), - ExtensionProcessIDMap::value_type(extension_id, process_id)); - if (iter != extension_process_ids_.end()) - extension_process_ids_.erase(iter); + if (!process_map_.Remove(extension_id, process_id)) { + NOTREACHED() << "Unknown extension process registration for: " + << extension_id << "," << process_id << "."; + } } -bool ExtensionInfoMap::IsExtensionInProcess( - const std::string& extension_id, int process_id) const { - return std::find( - extension_process_ids_.begin(), - extension_process_ids_.end(), - ExtensionProcessIDMap::value_type(extension_id, process_id)) != - extension_process_ids_.end(); +void ExtensionInfoMap::UnregisterAllExtensionsInProcess(int process_id) { + process_map_.Remove(process_id); } bool ExtensionInfoMap::SecurityOriginHasAPIPermission( @@ -133,13 +131,13 @@ bool ExtensionInfoMap::SecurityOriginHasAPIPermission( if (origin.SchemeIs(chrome::kExtensionScheme)) { const std::string& id = origin.host(); return extensions_.GetByID(id)->HasAPIPermission(permission) && - IsExtensionInProcess(id, process_id); + process_map_.Contains(id, process_id); } ExtensionSet::ExtensionMap::const_iterator i = extensions_.begin(); for (; i != extensions_.end(); ++i) { if (i->second->web_extent().MatchesSecurityOrigin(origin) && - IsExtensionInProcess(i->first, process_id) && + process_map_.Contains(i->first, process_id) && i->second->HasAPIPermission(permission)) { return true; } diff --git a/chrome/browser/extensions/extension_info_map.h b/chrome/browser/extensions/extension_info_map.h index 6aaf6b0..e8f1afa 100644 --- a/chrome/browser/extensions/extension_info_map.h +++ b/chrome/browser/extensions/extension_info_map.h @@ -6,13 +6,13 @@ #define CHROME_BROWSER_EXTENSIONS_EXTENSION_INFO_MAP_H_ #pragma once -#include <map> #include <string> #include "base/basictypes.h" #include "base/time.h" #include "base/memory/ref_counted.h" #include "chrome/browser/extensions/extensions_quota_service.h" +#include "chrome/browser/extensions/process_map.h" #include "chrome/common/extensions/extension_constants.h" #include "chrome/common/extensions/extension_set.h" @@ -31,6 +31,8 @@ class ExtensionInfoMap : public base::RefCountedThreadSafe<ExtensionInfoMap> { return disabled_extensions_; } + const extensions::ProcessMap& process_map() const; + // Callback for when new extensions are loaded. void AddExtension(const Extension* extension, base::Time install_time, @@ -51,21 +53,14 @@ class ExtensionInfoMap : public base::RefCountedThreadSafe<ExtensionInfoMap> { // sub-profile (incognito to original profile, or vice versa). bool CanCrossIncognito(const Extension* extension); - // Record that |extension_id| is running in |process_id|. We normally have - // this information in ExtensionProcessManager on the UI thread, but we also - // sometimes need it on the IO thread. Note that this can be any of - // (extension, packaged app, hosted app). + // Adds an entry to process_map_. void RegisterExtensionProcess(const std::string& extension_id, int process_id); - // Remove any record of |extension_id| created with RegisterExtensionProcess. - // If |extension_id| is unknown, we ignore it. + // Removes an entry from process_map_. void UnregisterExtensionProcess(const std::string& extension_id, int process_id); - - // Returns true if |extension_id| is running in |process_id|.. - bool IsExtensionInProcess(const std::string& extension_id, - int process_id) const; + void UnregisterAllExtensionsInProcess(int process_id); // Returns true if there is exists an extension with the same origin as // |origin| in |process_id| with |permission|. @@ -87,11 +82,11 @@ class ExtensionInfoMap : public base::RefCountedThreadSafe<ExtensionInfoMap> { // Extra data associated with enabled extensions. ExtraDataMap extra_data_; - typedef std::multimap<std::string, int> ExtensionProcessIDMap; - ExtensionProcessIDMap extension_process_ids_; - // Used by dispatchers to limit API quota for individual extensions. ExtensionsQuotaService quota_service_; + + // Assignment of extensions to processes. + extensions::ProcessMap process_map_; }; #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_INFO_MAP_H_ diff --git a/chrome/browser/extensions/extension_message_service.cc b/chrome/browser/extensions/extension_message_service.cc index f1febd7..d89b6e6 100644 --- a/chrome/browser/extensions/extension_message_service.cc +++ b/chrome/browser/extensions/extension_message_service.cc @@ -10,6 +10,7 @@ #include "base/values.h" #include "chrome/browser/extensions/extension_process_manager.h" #include "chrome/browser/extensions/extension_tab_util.h" +#include "chrome/browser/extensions/process_map.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/tab_contents/tab_util.h" #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" @@ -93,6 +94,18 @@ static void DispatchOnMessage(const ExtensionMessageService::MessagePort& port, port.routing_id, target_port_id, message)); } +static RenderProcessHost* GetExtensionProcess(Profile* profile, + const std::string& extension_id) { + SiteInstance* site_instance = + profile->GetExtensionProcessManager()->GetSiteInstanceForURL( + Extension::GetBaseURLFromExtensionId(extension_id)); + + if (!site_instance->HasProcess()) + return NULL; + + return site_instance->GetProcess(); +} + } // namespace // static @@ -149,8 +162,7 @@ void ExtensionMessageService::OpenChannelToExtension( // 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( - target_extension_id), + GetExtensionProcess(profile, target_extension_id), MSG_ROUTING_CONTROL); TabContents* source_contents = tab_util::GetTabContentsByID( source_process_id, source_routing_id); @@ -258,7 +270,7 @@ int ExtensionMessageService::OpenSpecialChannelToExtension( AllocatePortIdPair(&port1_id, &port2_id); MessagePort receiver( - profile_->GetExtensionProcessManager()->GetExtensionProcess(extension_id), + GetExtensionProcess(profile_, extension_id), MSG_ROUTING_CONTROL); if (!OpenChannelImpl(source, tab_json, receiver, port2_id, extension_id, extension_id, channel_name)) diff --git a/chrome/browser/extensions/extension_process_manager.cc b/chrome/browser/extensions/extension_process_manager.cc index cf9b70b..2fa8461 100644 --- a/chrome/browser/extensions/extension_process_manager.cc +++ b/chrome/browser/extensions/extension_process_manager.cc @@ -47,8 +47,6 @@ class IncognitoExtensionProcessManager : public ExtensionProcessManager { virtual void CreateBackgroundHost(const Extension* extension, const GURL& url); virtual SiteInstance* GetSiteInstanceForURL(const GURL& url); - virtual RenderProcessHost* GetExtensionProcess(const GURL& url); - virtual const Extension* GetExtensionForSiteInstance(int site_instance_id); private: // content::NotificationObserver: @@ -109,10 +107,6 @@ ExtensionProcessManager::ExtensionProcessManager(Profile* profile) content::Source<Profile>(profile)); registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, content::Source<Profile>(profile)); - // We can listen to everything for SITE_INSTANCE_DELETED because we check the - // |site_instance_id| in UnregisterExtensionSiteInstance. - registrar_.Add(this, content::NOTIFICATION_SITE_INSTANCE_DELETED, - content::NotificationService::AllBrowserContextsAndSources()); registrar_.Add(this, content::NOTIFICATION_APP_TERMINATING, content::NotificationService::AllSources()); } @@ -265,7 +259,6 @@ void ExtensionProcessManager::RegisterRenderViewHost( RenderViewHost* render_view_host, const Extension* extension) { all_extension_views_.insert(render_view_host); - RegisterExtensionSiteInstance(render_view_host->site_instance(), extension); } void ExtensionProcessManager::UnregisterRenderViewHost( @@ -273,155 +266,6 @@ void ExtensionProcessManager::UnregisterRenderViewHost( all_extension_views_.erase(render_view_host); } -void ExtensionProcessManager::RegisterExtensionSiteInstance( - SiteInstance* site_instance, - const Extension* extension) { - if (!site_instance->HasProcess()) { - NOTREACHED(); - return; - } - - int site_instance_id = site_instance->id(); - int render_process_id = site_instance->GetProcess()->id(); - if (process_ids_[render_process_id].insert(site_instance_id).second) { - // Register process hosting extensions that have access to extension - // bindings with the ExtensionInfoMap on the IO thread. - Profile* profile = - Profile::FromBrowserContext(browsing_instance_->browser_context()); - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&ExtensionInfoMap::RegisterExtensionProcess, - profile->GetExtensionInfoMap(), - extension->id(), - render_process_id)); - } - - SiteInstanceIDMap::const_iterator it = extension_ids_.find(site_instance_id); - if (it != extension_ids_.end() && (*it).second == extension->id()) - return; - - // SiteInstance ids should get removed from the map before the extension ids - // get used for a new SiteInstance. - DCHECK(it == extension_ids_.end()); - extension_ids_[site_instance_id] = extension->id(); -} - -void ExtensionProcessManager::UnregisterExtensionSiteInstance( - SiteInstance* site_instance) { - int site_instance_id = site_instance->id(); - std::string extension_id = extension_ids_[site_instance_id]; - if (!extension_id.empty()) - extension_ids_.erase(site_instance_id); - - int render_process_id = ClearSiteInstanceID(site_instance_id); - if (render_process_id == -1) - return; - - Profile* profile = Profile::FromBrowserContext( - browsing_instance_->browser_context()); - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&ExtensionInfoMap::UnregisterExtensionProcess, - profile->GetExtensionInfoMap(), - extension_id, - render_process_id)); -} - -int ExtensionProcessManager::ClearSiteInstanceID(int site_instance_id) { - for (ProcessIDMap::iterator i = process_ids_.begin(); - i != process_ids_.end(); ++i) { - SiteInstanceIDSet& site_instance_id_set = i->second; - for (SiteInstanceIDSet::iterator j = site_instance_id_set.begin(); - j != site_instance_id_set.end(); ++j) { - if (*j == site_instance_id) { - int render_process_id = i->first; - site_instance_id_set.erase(j); - if (site_instance_id_set.empty()) - process_ids_.erase(i); - return render_process_id; - } - } - } - return -1; -} - -bool ExtensionProcessManager::IsExtensionProcess(int render_process_id) { - return process_ids_.find(render_process_id) != process_ids_.end(); -} - -bool ExtensionProcessManager::AreBindingsEnabledForProcess( - int render_process_id) { - // Must behave logically the same as AreBindingsEnabledForProcess() in - // extension_info_map.cc. - ProcessIDMap::iterator it = process_ids_.find(render_process_id); - if (it == process_ids_.end()) - return false; - - Profile* profile = - Profile::FromBrowserContext(browsing_instance_->browser_context()); - ExtensionService* service = profile->GetExtensionService(); - for (std::set<int>::iterator site_instance_id = it->second.begin(); - site_instance_id != it->second.end(); ++site_instance_id) { - const Extension* extension = - GetExtensionForSiteInstance(*site_instance_id); - if (extension == NULL) - continue; - if (service->ExtensionBindingsAllowed(extension->url())) - return true; - } - return false; -} - -RenderProcessHost* ExtensionProcessManager::GetExtensionProcess( - const GURL& url) { - if (!browsing_instance_->HasSiteInstance(url)) - return NULL; - scoped_refptr<SiteInstance> site( - browsing_instance_->GetSiteInstanceForURL(url)); - if (site->HasProcess()) - return site->GetProcess(); - return NULL; -} - -RenderProcessHost* ExtensionProcessManager::GetExtensionProcess( - const std::string& extension_id) { - return GetExtensionProcess( - Extension::GetBaseURLFromExtensionId(extension_id)); -} - -const Extension* ExtensionProcessManager::GetExtensionForSiteInstance( - int site_instance_id) { - SiteInstanceIDMap::const_iterator it = extension_ids_.find(site_instance_id); - if (it != extension_ids_.end()) { - // Look up the extension by ID, including disabled extensions in case - // this gets called while an old process is still around. - Profile* profile = - Profile::FromBrowserContext(browsing_instance_->browser_context()); - ExtensionService* service = profile->GetExtensionService(); - return service->GetExtensionById(it->second, false); - } - - return NULL; -} - -std::set<const Extension*> ExtensionProcessManager::GetExtensionsForProcess( - int process_id) { - std::set<const Extension*> result; - - ProcessIDMap::iterator site_id_set = process_ids_.find(process_id); - if (site_id_set == process_ids_.end()) - return result; - - for (std::set<int>::iterator site_id = site_id_set->second.begin(); - site_id != site_id_set->second.end(); ++site_id) { - const Extension* extension = GetExtensionForSiteInstance(*site_id); - if (extension) - result.insert(extension); - } - - return result; -} - SiteInstance* ExtensionProcessManager::GetSiteInstanceForURL(const GURL& url) { return browsing_instance_->GetSiteInstanceForURL(url); } @@ -499,12 +343,6 @@ void ExtensionProcessManager::Observe( break; } - case content::NOTIFICATION_SITE_INSTANCE_DELETED: { - SiteInstance* site_instance = content::Source<SiteInstance>(source).ptr(); - UnregisterExtensionSiteInstance(site_instance); - break; - } - case chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE: { ExtensionHost* host = content::Details<ExtensionHost>(details).ptr(); if (host->extension_host_type() == @@ -609,27 +447,6 @@ SiteInstance* IncognitoExtensionProcessManager::GetSiteInstanceForURL( } } -RenderProcessHost* IncognitoExtensionProcessManager::GetExtensionProcess( - const GURL& url) { - const Extension* extension = GetExtensionOrAppByURL(url); - if (!extension || extension->incognito_split_mode()) { - return ExtensionProcessManager::GetExtensionProcess(url); - } else { - return original_manager_->GetExtensionProcess(url); - } -} - -const Extension* IncognitoExtensionProcessManager::GetExtensionForSiteInstance( - int site_instance_id) { - const Extension* extension = - ExtensionProcessManager::GetExtensionForSiteInstance(site_instance_id); - if (extension && extension->incognito_split_mode()) { - return extension; - } else { - return original_manager_->GetExtensionForSiteInstance(site_instance_id); - } -} - const Extension* IncognitoExtensionProcessManager::GetExtensionOrAppByURL( const GURL& url) { Profile* profile = diff --git a/chrome/browser/extensions/extension_process_manager.h b/chrome/browser/extensions/extension_process_manager.h index 476c053..3ee2a4f 100644 --- a/chrome/browser/extensions/extension_process_manager.h +++ b/chrome/browser/extensions/extension_process_manager.h @@ -68,6 +68,8 @@ class ExtensionProcessManager : public content::NotificationObserver { ExtensionHost* GetBackgroundHostForExtension(const std::string& extension_id); // Returns the SiteInstance that the given URL belongs to. + // TODO(aa): This only returns correct results for extensions and packaged + // apps, not hosted apps. virtual SiteInstance* GetSiteInstanceForURL(const GURL& url); // Registers a RenderViewHost as hosting a given extension. @@ -82,28 +84,6 @@ class ExtensionProcessManager : public content::NotificationObserver { std::set<RenderViewHost*> GetRenderViewHostsForExtension( const std::string& extension_id); - // True if this process host is hosting an extension. - bool IsExtensionProcess(int render_process_id); - - // True if this process host is hosting an extension with extension bindings - // enabled. - bool AreBindingsEnabledForProcess(int render_process_id); - - // Returns the extension process that |url| is associated with if it exists. - // This is not valid for hosted apps without the background permission, since - // such apps may have multiple processes. - virtual RenderProcessHost* GetExtensionProcess(const GURL& url); - - // Returns the process that the extension with the given ID is running in. - RenderProcessHost* GetExtensionProcess(const std::string& extension_id); - - // Returns the Extension associated with the given SiteInstance id, if any. - virtual const Extension* GetExtensionForSiteInstance(int site_instance_id); - - // Returns the set of extensions for the specified process. If the process is - // not an extension process, or contains no extensions, returns an empty set. - std::set<const Extension*> GetExtensionsForProcess(int process_id); - // Returns true if |host| is managed by this process manager. bool HasExtensionHost(ExtensionHost* host) const; @@ -142,23 +122,7 @@ class ExtensionProcessManager : public content::NotificationObserver { // controls process grouping. scoped_refptr<BrowsingInstance> browsing_instance_; - // A map of site instance ID to the ID of the extension it hosts. - typedef std::map<int, std::string> SiteInstanceIDMap; - SiteInstanceIDMap extension_ids_; - - // A map of process ID to site instance ID of the site instances it hosts. - typedef std::set<int> SiteInstanceIDSet; - typedef std::map<int, SiteInstanceIDSet> ProcessIDMap; - ProcessIDMap process_ids_; - private: - // Registers a site instance as hosting a given extension. - void RegisterExtensionSiteInstance(SiteInstance* site_instance, - const Extension* extension); - - // Unregisters the extension associated with |site_instance|. - void UnregisterExtensionSiteInstance(SiteInstance* site_instance); - // Contains all extension-related RenderViewHost instances for all extensions. typedef std::set<RenderViewHost*> RenderViewHostSet; RenderViewHostSet all_extension_views_; @@ -169,10 +133,6 @@ class ExtensionProcessManager : public content::NotificationObserver { // Excludes background page. bool HasVisibleViews(const std::string& extension_id); - // Clears the mapping for the specified site instance. Returns the process the - // site was mapped to, or -1 if it wasn't found. - int ClearSiteInstanceID(int site_instance_id); - DISALLOW_COPY_AND_ASSIGN(ExtensionProcessManager); }; diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index b2d09b6..a42fe0f 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc @@ -2339,6 +2339,13 @@ void ExtensionService::Observe(int type, break; installed_app_hosts_.erase(process->id()); + + process_map_.Remove(process->id()); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&ExtensionInfoMap::UnregisterAllExtensionsInProcess, + profile_->GetExtensionInfoMap(), + process->id())); break; } case chrome::NOTIFICATION_PREF_CHANGED: { diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h index 47cc52d..60da15b 100644 --- a/chrome/browser/extensions/extension_service.h +++ b/chrome/browser/extensions/extension_service.h @@ -33,6 +33,7 @@ #include "chrome/browser/extensions/extensions_quota_service.h" #include "chrome/browser/extensions/external_extension_provider_interface.h" #include "chrome/browser/extensions/pending_extension_manager.h" +#include "chrome/browser/extensions/process_map.h" #include "chrome/browser/extensions/sandboxed_extension_unpacker.h" #include "chrome/browser/prefs/pref_change_registrar.h" #include "chrome/browser/sync/api/sync_change.h" @@ -186,6 +187,8 @@ class ExtensionService AppsPromo* apps_promo() { return &apps_promo_; } + extensions::ProcessMap* process_map() { return &process_map_; } + // Whether this extension can run in an incognito window. virtual bool IsIncognitoEnabled(const std::string& extension_id) const; virtual void SetIsIncognitoEnabled(const std::string& extension_id, @@ -788,6 +791,8 @@ class ExtensionService // Contains an entry for each warning that shall be currently shown. ExtensionWarningSet extension_warnings_; + extensions::ProcessMap process_map_; + FRIEND_TEST_ALL_PREFIXES(ExtensionServiceTest, InstallAppsWithUnlimtedStorage); FRIEND_TEST_ALL_PREFIXES(ExtensionServiceTest, diff --git a/chrome/browser/extensions/extension_tab_helper.cc b/chrome/browser/extensions/extension_tab_helper.cc index d597396..7aa3ce5 100644 --- a/chrome/browser/extensions/extension_tab_helper.cc +++ b/chrome/browser/extensions/extension_tab_helper.cc @@ -168,19 +168,16 @@ void ExtensionTabHelper::OnGetAppNotifyChannel( Profile* profile = Profile::FromBrowserContext(tab_contents()->browser_context()); ExtensionService* extension_service = profile->GetExtensionService(); - ExtensionProcessManager* process_manager = - profile->GetExtensionProcessManager(); + extensions::ProcessMap* process_map = extension_service->process_map(); RenderProcessHost* process = tab_contents_wrapper()->render_view_host()->process(); const Extension* extension = extension_service->GetInstalledApp(requestor_url); bool allowed = extension && - extension->is_app() && extension->HasAPIPermission( ExtensionAPIPermission::kExperimental) && - (extension->is_hosted_app() || - process_manager->GetExtensionProcess(requestor_url) == process); + process_map->Contains(extension->id(), process->id()); if (!allowed) { AppNotifyChannelSetupComplete("", "permission_error", return_route_id, callback_id); diff --git a/chrome/browser/extensions/process_map.cc b/chrome/browser/extensions/process_map.cc new file mode 100644 index 0000000..fa12f6c --- /dev/null +++ b/chrome/browser/extensions/process_map.cc @@ -0,0 +1,89 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/process_map.h" + +namespace extensions { + +// Item +ProcessMap::Item::Item() { +} + +ProcessMap::Item::Item(const ProcessMap::Item& other) + : extension_id(other.extension_id), process_id(other.process_id) { +} + +ProcessMap::Item::Item(const std::string& extension_id, int process_id) + : extension_id(extension_id), process_id(process_id) { +} + +ProcessMap::Item::~Item() { +} + +bool ProcessMap::Item::operator<(const ProcessMap::Item& other) const { + if (extension_id < other.extension_id) + return true; + + if (extension_id == other.extension_id && + process_id < other.process_id) { + return true; + } + + return false; +} + + +// ProcessMap +ProcessMap::ProcessMap() { +} + +ProcessMap::~ProcessMap() { +} + +bool ProcessMap::Insert(const std::string& extension_id, int process_id) { + return items_.insert(Item(extension_id, process_id)).second; +} + +bool ProcessMap::Remove(const std::string& extension_id, int process_id) { + return items_.erase(Item(extension_id, process_id)) > 0; +} + +int ProcessMap::Remove(int process_id) { + int result = 0; + for (ItemSet::const_iterator iter = items_.begin(); iter != items_.end(); ) { + if (iter->process_id == process_id) { + items_.erase(iter++); + ++result; + } else { + ++iter; + } + } + return result; +} + +bool ProcessMap::Contains(const std::string& extension_id, + int process_id) const { + return items_.find(Item(extension_id, process_id)) != items_.end(); +} + +bool ProcessMap::Contains(int process_id) const { + for (ItemSet::const_iterator iter = items_.begin(); iter != items_.end(); + ++iter) { + if (iter->process_id == process_id) + return true; + } + return false; +} + +std::set<std::string> ProcessMap::GetExtensionsInProcess(int process_id) const { + std::set<std::string> result; + for (ItemSet::const_iterator iter = items_.begin(); iter != items_.end(); + ++iter) { + if (iter->process_id == process_id) + result.insert(iter->extension_id); + } + return result; +} + +} // extensions diff --git a/chrome/browser/extensions/process_map.h b/chrome/browser/extensions/process_map.h new file mode 100644 index 0000000..9d43505 --- /dev/null +++ b/chrome/browser/extensions/process_map.h @@ -0,0 +1,73 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_PROCESS_MAP_H_ +#define CHROME_BROWSER_EXTENSIONS_PROCESS_MAP_H_ +#pragma once + +#include <set> +#include <string> + +#include "base/basictypes.h" + +namespace extensions { + +// Contains information about which extensions are assigned to which processes. +// +// The relationship between extensions and processes is complex: +// - Extensions can be either "split" mode or "spanning" mode. +// - In spanning mode, extensions share a single process between all incognito +// and normal windows. This was the original mode for extensions. +// - In split mode, extensions have separate processes in incognito windows. +// - There are also hosted apps, which are a kind of extensions, and those +// usually have a process model similar to normal web sites: multiple +// processes per-profile. +// +// In general, we seem to play with the process model of extensions a lot, so +// it is safest to assume it is many-to-many in most places in the codebase. +// +// Note that because of content scripts, frames, and other edge cases in +// Chrome's process isolation, extension code can still end up running outside +// an assigned process. +// +// But we only allow high-privilege operations to be performed by an extension +// when it is running in an assigned process. +class ProcessMap { + public: + ProcessMap(); + ~ProcessMap(); + + size_t size() const { return items_.size(); } + + bool Insert(const std::string& extension_id, int process_id); + bool Remove(const std::string& extension_id, int process_id); + int Remove(int process_id); + bool Contains(const std::string& extension_id, int process_id) const; + bool Contains(int process_id) const; + + std::set<std::string> GetExtensionsInProcess(int process_id) const; + + private: + struct Item { + Item(); + Item(const Item& other); + Item(const std::string& extension_id, int process_id); + ~Item(); + + // Required for set membership. + bool operator<(const Item& other) const; + + std::string extension_id; + int process_id; + }; + + typedef std::set<Item> ItemSet; + std::set<Item> items_; + + DISALLOW_COPY_AND_ASSIGN(ProcessMap); +}; + +} // extensions + +#endif // CHROME_BROWSER_EXTENSIONS_PROCESS_MAP_H_ diff --git a/chrome/browser/extensions/process_map_unittest.cc b/chrome/browser/extensions/process_map_unittest.cc new file mode 100644 index 0000000..40b3e595 --- /dev/null +++ b/chrome/browser/extensions/process_map_unittest.cc @@ -0,0 +1,52 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/process_map.h" + +#include "testing/gtest/include/gtest/gtest.h" + +using extensions::ProcessMap; + +TEST(ExtensionProcessMapTest, Test) { + ProcessMap map; + + // Test behavior when empty. + EXPECT_FALSE(map.Contains("a", 1)); + EXPECT_FALSE(map.Remove("a", 1)); + EXPECT_EQ(0u, map.size()); + + // Test insertion and behavior with one item. + EXPECT_TRUE(map.Insert("a", 1)); + EXPECT_TRUE(map.Contains("a", 1)); + EXPECT_FALSE(map.Contains("a", 2)); + EXPECT_FALSE(map.Contains("b", 1)); + EXPECT_EQ(1u, map.size()); + + // Test inserting a duplicate item. + EXPECT_FALSE(map.Insert("a", 1)); + EXPECT_TRUE(map.Contains("a", 1)); + EXPECT_EQ(1u, map.size()); + + // Insert some more items. + EXPECT_TRUE(map.Insert("a", 2)); + EXPECT_TRUE(map.Insert("b", 1)); + EXPECT_TRUE(map.Insert("b", 2)); + EXPECT_EQ(4u, map.size()); + + EXPECT_TRUE(map.Contains("a", 1)); + EXPECT_TRUE(map.Contains("a", 2)); + EXPECT_TRUE(map.Contains("b", 1)); + EXPECT_TRUE(map.Contains("b", 2)); + EXPECT_FALSE(map.Contains("a", 3)); + + // Test removal. + EXPECT_TRUE(map.Remove("a", 1)); + EXPECT_FALSE(map.Remove("a", 1)); + EXPECT_EQ(3u, map.size()); + + EXPECT_EQ(2, map.Remove(2)); + EXPECT_EQ(1u, map.size()); + EXPECT_EQ(0, map.Remove(2)); + EXPECT_EQ(1u, map.size()); +} diff --git a/chrome/browser/geolocation/chrome_geolocation_permission_context.cc b/chrome/browser/geolocation/chrome_geolocation_permission_context.cc index b160c38..0328da9 100644 --- a/chrome/browser/geolocation/chrome_geolocation_permission_context.cc +++ b/chrome/browser/geolocation/chrome_geolocation_permission_context.cc @@ -530,18 +530,11 @@ void ChromeGeolocationPermissionContext::RequestGeolocationPermission( if (!ext) ext = extensions->GetExtensionByWebExtent(requesting_frame); if (ext && ext->HasAPIPermission(ExtensionAPIPermission::kGeolocation)) { - // Make sure this matches the current extension. - RenderViewHost* rvh = RenderViewHost::FromID(render_process_id, - render_view_id); - if (rvh && rvh->site_instance()) { - ExtensionProcessManager* epm = profile_->GetExtensionProcessManager(); - const Extension* current_ext = epm->GetExtensionForSiteInstance( - rvh->site_instance()->id()); - if (ext == current_ext) { - NotifyPermissionSet(render_process_id, render_view_id, bridge_id, - requesting_frame, true); - return; - } + // Make sure the extension is in the calling process. + if (extensions->process_map()->Contains(ext->id(), render_process_id)) { + NotifyPermissionSet(render_process_id, render_view_id, bridge_id, + requesting_frame, true); + return; } } } diff --git a/chrome/browser/memory_details.cc b/chrome/browser/memory_details.cc index 138a51d..3f5cb15 100644 --- a/chrome/browser/memory_details.cc +++ b/chrome/browser/memory_details.cc @@ -144,8 +144,8 @@ void MemoryDetails::CollectChildInfoOnUIThread() { Profile* profile = Profile::FromBrowserContext(render_process_host->browser_context()); ExtensionService* extension_service = profile->GetExtensionService(); - ExtensionProcessManager* extension_process_manager = - profile->GetExtensionProcessManager(); + extensions::ProcessMap* extension_process_map = + extension_service->process_map(); // The RenderProcessHost may host multiple TabContents. Any // of them which contain diagnostics information make the whole @@ -175,14 +175,25 @@ void MemoryDetails::CollectChildInfoOnUIThread() { process.renderer_type = ChildProcessInfo::RENDERER_DEVTOOLS; else process.renderer_type = ChildProcessInfo::RENDERER_CHROME; - } else if (extension_process_manager->AreBindingsEnabledForProcess( - host->process()->id())) { - process.renderer_type = ChildProcessInfo::RENDERER_EXTENSION; + } else if (extension_process_map->Contains(host->process()->id())) { + // For our purposes, don't count processes containing only hosted apps + // as extension processes. See also: crbug.com/102533. + std::set<std::string> extension_ids = + extension_process_map->GetExtensionsInProcess( + host->process()->id()); + for (std::set<std::string>::iterator iter = extension_ids.begin(); + iter != extension_ids.end(); ++iter) { + const Extension* extension = + extension_service->GetExtensionById(*iter, false); + if (extension && !extension->is_hosted_app()) { + process.renderer_type = ChildProcessInfo::RENDERER_EXTENSION; + break; + } + } } TabContents* contents = host_delegate->GetAsTabContents(); if (!contents) { - if (extension_process_manager->IsExtensionProcess( - host->process()->id())) { + if (extension_process_map->Contains(host->process()->id())) { const Extension* extension = extension_service->GetExtensionByURL(url); if (extension) { diff --git a/chrome/browser/metrics/metrics_service.cc b/chrome/browser/metrics/metrics_service.cc index 7f2db89..9a299da 100644 --- a/chrome/browser/metrics/metrics_service.cc +++ b/chrome/browser/metrics/metrics_service.cc @@ -156,7 +156,8 @@ #include "base/values.h" #include "chrome/browser/bookmarks/bookmark_model.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/extensions/extension_process_manager.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/process_map.h" #include "chrome/browser/memory_details.h" #include "chrome/browser/metrics/histogram_synchronizer.h" #include "chrome/browser/metrics/metrics_log.h" @@ -1243,11 +1244,9 @@ void MetricsService::LogRendererCrash(RenderProcessHost* host, base::TerminationStatus status, bool was_alive) { Profile* profile = Profile::FromBrowserContext(host->browser_context()); - ExtensionProcessManager* extension_process_manager = - profile->GetExtensionProcessManager(); - bool was_extension_process = extension_process_manager ? - extension_process_manager->IsExtensionProcess(host->id()) : - false; + ExtensionService* service = profile->GetExtensionService(); + bool was_extension_process = + service && service->process_map()->Contains(host->id()); if (status == base::TERMINATION_STATUS_PROCESS_CRASHED || status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) { if (was_extension_process) diff --git a/chrome/browser/profiles/profile.h b/chrome/browser/profiles/profile.h index 0d32bd0..0e3df82 100644 --- a/chrome/browser/profiles/profile.h +++ b/chrome/browser/profiles/profile.h @@ -217,6 +217,10 @@ class Profile : public content::BrowserContext { // Return the incognito version of this profile. The returned pointer // is owned by the receiving profile. If the receiving profile is off the // record, the same profile is returned. + // + // WARNING: This will create the OffTheRecord profile if it doesn't already + // exist. If this isn't what you want, you need to check + // HasOffTheRecordProfile() first. virtual Profile* GetOffTheRecordProfile() = 0; // Destroys the incognito profile. diff --git a/chrome/browser/tab_contents/render_view_host_delegate_helper.cc b/chrome/browser/tab_contents/render_view_host_delegate_helper.cc index 96c841c..28f4eda 100644 --- a/chrome/browser/tab_contents/render_view_host_delegate_helper.cc +++ b/chrome/browser/tab_contents/render_view_host_delegate_helper.cc @@ -16,6 +16,7 @@ #include "chrome/browser/extensions/extension_process_manager.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_webkit_preferences.h" +#include "chrome/browser/extensions/process_map.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/prefs/scoped_user_pref_update.h" #include "chrome/browser/prerender/prerender_manager.h" @@ -114,11 +115,11 @@ RenderViewHostDelegateViewHelper::MaybeCreateBackgroundContents( return NULL; // Ensure that we're trying to open this from the extension's process. - ExtensionProcessManager* process_manager = - profile->GetExtensionProcessManager(); - if (!site->GetProcess() || !process_manager || - site->GetProcess() != process_manager->GetExtensionProcess(opener_url)) + extensions::ProcessMap* process_map = extensions_service->process_map(); + if (!site->GetProcess() || + !process_map->Contains(extension->id(), site->GetProcess()->id())) { return NULL; + } // Only allow a single background contents per app. If one already exists, // close it (even if it was specified in the manifest). @@ -542,12 +543,10 @@ WebPreferences RenderViewHostDelegateHelper::GetWebkitPrefs( web_prefs.is_online = !net::NetworkChangeNotifier::IsOffline(); - ExtensionProcessManager* extension_process_manager = - profile->GetExtensionProcessManager(); - if (extension_process_manager) { + ExtensionService* service = profile->GetExtensionService(); + if (service) { const Extension* extension = - extension_process_manager->GetExtensionForSiteInstance( - rvh->site_instance()->id()); + service->GetExtensionByURL(rvh->site_instance()->site()); extension_webkit_preferences::SetPreferences(&web_prefs, extension); } diff --git a/chrome/browser/task_manager/task_manager_resource_providers.cc b/chrome/browser/task_manager/task_manager_resource_providers.cc index fb2f2ed..7094b64 100644 --- a/chrome/browser/task_manager/task_manager_resource_providers.cc +++ b/chrome/browser/task_manager/task_manager_resource_providers.cc @@ -267,13 +267,11 @@ string16 TaskManagerTabContentsResource::GetTitle() const { // Only classify as an app if the URL is an app and the tab is hosting an // extension process. (It's possible to be showing the URL from before it // was installed as an app.) - ExtensionService* extensions_service = + ExtensionService* extension_service = tab_contents_->profile()->GetExtensionService(); - ExtensionProcessManager* extension_process_manager = - tab_contents_->profile()->GetExtensionProcessManager(); - bool is_app = extensions_service->IsInstalledApp(url) && - extension_process_manager->IsExtensionProcess( - contents->GetRenderProcessHost()->id()); + extensions::ProcessMap* process_map = extension_service->process_map(); + bool is_app = extension_service->IsInstalledApp(url) && + process_map->Contains(contents->GetRenderProcessHost()->id()); int message_id = GetMessagePrefixID( is_app, @@ -306,9 +304,9 @@ TabContentsWrapper* TaskManagerTabContentsResource::GetTabContents() const { const Extension* TaskManagerTabContentsResource::GetExtension() const { if (HostsExtension()) { - ExtensionService* extensions_service = + ExtensionService* extension_service = tab_contents_->profile()->GetExtensionService(); - return extensions_service->GetExtensionByURL( + return extension_service->GetExtensionByURL( tab_contents_->tab_contents()->GetURL()); } diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 569a004..53e86cb 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1250,6 +1250,8 @@ 'browser/extensions/pending_extension_info.h', 'browser/extensions/pending_extension_manager.cc', 'browser/extensions/pending_extension_manager.h', + 'browser/extensions/process_map.cc', + 'browser/extensions/process_map.h', 'browser/extensions/sandboxed_extension_unpacker.cc', 'browser/extensions/sandboxed_extension_unpacker.h', 'browser/extensions/speech_input/extension_speech_input_api.cc', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 939dfa6..a292bd8 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1367,6 +1367,7 @@ 'browser/extensions/in_memory_extension_settings_storage_unittest.cc', 'browser/extensions/key_identifier_conversion_views_unittest.cc', 'browser/extensions/network_delay_listener_unittest.cc', + 'browser/extensions/process_map_unittest.cc', 'browser/extensions/sandboxed_extension_unpacker_unittest.cc', 'browser/extensions/user_script_listener_unittest.cc', 'browser/extensions/user_script_master_unittest.cc', diff --git a/content/browser/mock_content_browser_client.cc b/content/browser/mock_content_browser_client.cc index ed558df..98b8ecd 100644 --- a/content/browser/mock_content_browser_client.cc +++ b/content/browser/mock_content_browser_client.cc @@ -79,6 +79,14 @@ bool MockContentBrowserClient::IsSuitableHost( return true; } +void MockContentBrowserClient::SiteInstanceGotProcess( + SiteInstance* site_instance) { +} + +void MockContentBrowserClient::SiteInstanceDeleting( + SiteInstance* site_instance) { +} + bool MockContentBrowserClient::ShouldSwapProcessesForNavigation( const GURL& current_url, const GURL& new_url) { diff --git a/content/browser/mock_content_browser_client.h b/content/browser/mock_content_browser_client.h index 79e700c..23d53b1 100644 --- a/content/browser/mock_content_browser_client.h +++ b/content/browser/mock_content_browser_client.h @@ -42,6 +42,8 @@ class MockContentBrowserClient : public ContentBrowserClient { virtual bool IsURLSameAsAnySiteInstance(const GURL& url) OVERRIDE; virtual bool IsSuitableHost(RenderProcessHost* process_host, const GURL& site_url) OVERRIDE; + virtual void SiteInstanceGotProcess(SiteInstance* site_instance) OVERRIDE; + virtual void SiteInstanceDeleting(SiteInstance* site_instance) OVERRIDE; virtual bool ShouldSwapProcessesForNavigation(const GURL& current_url, const GURL& new_url) OVERRIDE; virtual std::string GetCanonicalEncodingNameByAliasName( diff --git a/content/browser/site_instance.cc b/content/browser/site_instance.cc index ad79d74..d41f49b 100644 --- a/content/browser/site_instance.cc +++ b/content/browser/site_instance.cc @@ -42,10 +42,7 @@ SiteInstance::SiteInstance(BrowsingInstance* browsing_instance) } SiteInstance::~SiteInstance() { - content::NotificationService::current()->Notify( - content::NOTIFICATION_SITE_INSTANCE_DELETED, - content::Source<SiteInstance>(this), - content::NotificationService::NoDetails()); + content::GetContentClient()->browser()->SiteInstanceDeleting(this); // Now that no one is referencing us, we can safely remove ourselves from // the BrowsingInstance. Any future visits to a page from this site @@ -84,6 +81,8 @@ RenderProcessHost* SiteInstance::GetProcess() { } } + content::GetContentClient()->browser()->SiteInstanceGotProcess(this); + // Make sure the process starts at the right max_page_id process_->UpdateMaxPageID(max_page_id_); } diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index a404112..727e6c9 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h @@ -29,6 +29,7 @@ class RenderViewHost; class RenderWidgetHost; class RenderWidgetHostView; class ResourceDispatcherHost; +class SiteInstance; class SSLCertErrorHandler; class SSLClientAuthHandler; class SkBitmap; @@ -145,6 +146,12 @@ class ContentBrowserClient { virtual bool IsSuitableHost(RenderProcessHost* process_host, const GURL& site_url) = 0; + // Called when a site instance is first associated with a process. + virtual void SiteInstanceGotProcess(SiteInstance* site_instance) = 0; + + // Called from a site instance's destructor. + virtual void SiteInstanceDeleting(SiteInstance* site_instance) = 0; + // Returns true if for the navigation from |current_url| to |new_url|, // processes should be swapped (even if we are in a process model that // doesn't usually swap). diff --git a/content/public/browser/notification_types.h b/content/public/browser/notification_types.h index c0e465d..1d6e503 100644 --- a/content/public/browser/notification_types.h +++ b/content/public/browser/notification_types.h @@ -356,10 +356,6 @@ enum NotificationType { // the new state is "visible." NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED, - // Sent from ~SiteInstance. The source is the SiteInstance, and the details - // are unused. - NOTIFICATION_SITE_INSTANCE_DELETED, - // The focused element inside a page has changed. The source is the // TabContents containing the render view host for the page. The details is // a Details<const bool> that indicates whether or not an editable node was diff --git a/content/shell/shell_content_browser_client.cc b/content/shell/shell_content_browser_client.cc index 1379e82..2a31c9a 100644 --- a/content/shell/shell_content_browser_client.cc +++ b/content/shell/shell_content_browser_client.cc @@ -93,6 +93,14 @@ bool ShellContentBrowserClient::IsSuitableHost( return true; } +void ShellContentBrowserClient::SiteInstanceGotProcess( + SiteInstance* site_instance) { +} + +void ShellContentBrowserClient::SiteInstanceDeleting( + SiteInstance* site_instance) { +} + bool ShellContentBrowserClient::ShouldSwapProcessesForNavigation( const GURL& current_url, const GURL& new_url) { diff --git a/content/shell/shell_content_browser_client.h b/content/shell/shell_content_browser_client.h index 2e44aa9..e8aa52f 100644 --- a/content/shell/shell_content_browser_client.h +++ b/content/shell/shell_content_browser_client.h @@ -54,6 +54,8 @@ class ShellContentBrowserClient : public ContentBrowserClient virtual bool IsURLSameAsAnySiteInstance(const GURL& url) OVERRIDE; virtual bool IsSuitableHost(RenderProcessHost* process_host, const GURL& site_url) OVERRIDE; + virtual void SiteInstanceGotProcess(SiteInstance* site_instance) OVERRIDE; + virtual void SiteInstanceDeleting(SiteInstance* site_instance) OVERRIDE; virtual bool ShouldSwapProcessesForNavigation(const GURL& current_url, const GURL& new_url) OVERRIDE; |