diff options
author | rdevlin.cronin <rdevlin.cronin@chromium.org> | 2015-04-03 13:19:40 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-03 20:20:20 +0000 |
commit | 6ae04a013f6040f5d38e6cf04f6da224f21b77f9 (patch) | |
tree | 427696998b1fd65a9549ab695f30e58f9365c960 | |
parent | 11d52caf494dea19e0feb6184858b9ec24bdb46c (diff) | |
download | chromium_src-6ae04a013f6040f5d38e6cf04f6da224f21b77f9.zip chromium_src-6ae04a013f6040f5d38e6cf04f6da224f21b77f9.tar.gz chromium_src-6ae04a013f6040f5d38e6cf04f6da224f21b77f9.tar.bz2 |
Reland: [Extensions] Change ProcessManager to use RenderFrameHosts
(Reland of https://codereview.chromium.org/1037263004)
RenderViewHosts are going to go away, and things using them are blocking
OOPIs. Make ProcessManager use RenderFrameHosts.
Additionally, this takes out ~130 lines of code.
BUG=466373
(TBRing other reviewers from original patch, since no code there changed)
TBR=avi@chromium.org
TBR=asargent@chromium.org
TBR=atwilson@chromium.org
TBR=jamescook@chromium.org
TBR=dgozman@chromium.org
TBR=nick@chromium.org
Review URL: https://codereview.chromium.org/1056463005
Cr-Commit-Position: refs/heads/master@{#323803}
35 files changed, 608 insertions, 827 deletions
diff --git a/chrome/browser/apps/window_controls_browsertest.cc b/chrome/browser/apps/window_controls_browsertest.cc index 6d4b76a..33cad92 100644 --- a/chrome/browser/apps/window_controls_browsertest.cc +++ b/chrome/browser/apps/window_controls_browsertest.cc @@ -27,27 +27,19 @@ content::WebContents* WindowControlsTest::GetWebContentsForExtensionWindow( // Lookup render view host for background page. const extensions::ExtensionHost* extension_host = process_manager->GetBackgroundHostForExtension(extension->id()); - content::RenderViewHost* background_view_host = - extension_host->render_view_host(); - - // Go through all active views, looking for the first window of the extension - const extensions::ProcessManager::ViewSet all_views = - process_manager->GetAllViews(); - extensions::ProcessManager::ViewSet::const_iterator it = all_views.begin(); - for (; it != all_views.end(); ++it) { - content::RenderViewHost* host = *it; + // Go through all active views, looking for the first window of the extension. + for (content::RenderFrameHost* host : process_manager->GetAllFrames()) { // Filter out views not part of this extension - if (process_manager->GetExtensionForRenderViewHost(host) == extension) { + if (process_manager->GetExtensionForRenderFrameHost(host) == extension) { // Filter out the background page view - if (host != background_view_host) { - content::WebContents* web_contents = - content::WebContents::FromRenderViewHost(host); + content::WebContents* web_contents = + content::WebContents::FromRenderFrameHost(host); + if (web_contents != extension_host->web_contents()) return web_contents; - } } } - return NULL; + return nullptr; } IN_PROC_BROWSER_TEST_F(WindowControlsTest, CloseControlWorks) { diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc index df92be6..db9eb50 100644 --- a/chrome/browser/devtools/devtools_sanity_browsertest.cc +++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc @@ -363,11 +363,11 @@ class DevToolsExtensionTest : public DevToolsSanityTest, extensions::ProcessManager* manager = extensions::ProcessManager::Get(browser()->profile()); - extensions::ProcessManager::ViewSet all_views = manager->GetAllViews(); - for (extensions::ProcessManager::ViewSet::const_iterator iter = - all_views.begin(); - iter != all_views.end();) { - if (!(*iter)->IsLoading()) + extensions::ProcessManager::FrameSet all_frames = manager->GetAllFrames(); + for (extensions::ProcessManager::FrameSet::const_iterator iter = + all_frames.begin(); + iter != all_frames.end();) { + if (!content::WebContents::FromRenderFrameHost(*iter)->IsLoading()) ++iter; else content::RunMessageLoop(); diff --git a/chrome/browser/extensions/active_tab_permission_granter.cc b/chrome/browser/extensions/active_tab_permission_granter.cc index 32cbd69..cce3f3f 100644 --- a/chrome/browser/extensions/active_tab_permission_granter.cc +++ b/chrome/browser/extensions/active_tab_permission_granter.cc @@ -8,8 +8,8 @@ #include "chrome/browser/profiles/profile.h" #include "content/public/browser/navigation_details.h" #include "content/public/browser/navigation_entry.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" -#include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/process_manager.h" @@ -45,19 +45,19 @@ IPC::Message* CreateClearMessage(const std::vector<std::string>& ids, } // Sends a message exactly once to each render process host owning one of the -// given |view_hosts| and |tab_process|. If |tab_process| doesn't own any of the -// |view_hosts|, it will not be signaled to update its origin whitelist. +// given |frame_hosts| and |tab_process|. If |tab_process| doesn't own any of +// the |frame_hosts|, it will not be signaled to update its origin whitelist. void SendMessageToProcesses( - const std::set<content::RenderViewHost*>& view_hosts, + const std::set<content::RenderFrameHost*>& frame_hosts, content::RenderProcessHost* tab_process, const CreateMessageFunction& create_message) { std::set<content::RenderProcessHost*> sent_to_hosts; - for (content::RenderViewHost* view_host : view_hosts) { - content::RenderProcessHost* process_host = view_host->GetProcess(); + for (content::RenderFrameHost* frame_host : frame_hosts) { + content::RenderProcessHost* process_host = frame_host->GetProcess(); if (sent_to_hosts.count(process_host) == 0) { // Extension processes have to update the origin whitelists. process_host->Send(create_message.Run(true)); - sent_to_hosts.insert(view_host->GetProcess()); + sent_to_hosts.insert(frame_host->GetProcess()); } } // If the tab wasn't one of those processes already updated (it likely @@ -121,7 +121,7 @@ void ActiveTabPermissionGranter::GrantIfRequested(const Extension* extension) { tab_id_); SendMessageToProcesses( ProcessManager::Get(web_contents()->GetBrowserContext())-> - GetRenderViewHostsForExtension(extension->id()), + GetRenderFrameHostsForExtension(extension->id()), web_contents()->GetRenderProcessHost(), update_message); @@ -180,21 +180,22 @@ void ActiveTabPermissionGranter::ClearActiveExtensionsAndNotify() { if (granted_extensions_.is_empty()) return; - std::set<content::RenderViewHost*> view_hosts; + std::set<content::RenderFrameHost*> frame_hosts; std::vector<std::string> extension_ids; ProcessManager* process_manager = ProcessManager::Get(web_contents()->GetBrowserContext()); for (const scoped_refptr<const Extension>& extension : granted_extensions_) { extension->permissions_data()->ClearTabSpecificPermissions(tab_id_); extension_ids.push_back(extension->id()); - std::set<content::RenderViewHost*> extension_view_hosts = - process_manager->GetRenderViewHostsForExtension(extension->id()); - view_hosts.insert(extension_view_hosts.begin(), extension_view_hosts.end()); + std::set<content::RenderFrameHost*> extension_frame_hosts = + process_manager->GetRenderFrameHostsForExtension(extension->id()); + frame_hosts.insert(extension_frame_hosts.begin(), + extension_frame_hosts.end()); } CreateMessageFunction clear_message = base::Bind(&CreateClearMessage, extension_ids, tab_id_); - SendMessageToProcesses(view_hosts, + SendMessageToProcesses(frame_hosts, web_contents()->GetRenderProcessHost(), clear_message); diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc index 946ec7a..b48788b 100644 --- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc +++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc @@ -138,13 +138,6 @@ GURL ToDataURL(const base::FilePath& path, developer_private::ItemType type) { return GetImageURLFromData(contents); } -std::string GetExtensionID(const content::RenderViewHost* render_view_host) { - if (!render_view_host->GetSiteInstance()) - return std::string(); - - return render_view_host->GetSiteInstance()->GetSiteURL().host(); -} - void BroadcastItemStateChanged(content::BrowserContext* browser_context, developer::EventType event_type, const std::string& item_id) { @@ -210,22 +203,16 @@ DeveloperPrivateAPI::DeveloperPrivateAPI(content::BrowserContext* context) } DeveloperPrivateEventRouter::DeveloperPrivateEventRouter(Profile* profile) - : extension_registry_observer_(this), profile_(profile) { - registrar_.Add(this, - extensions::NOTIFICATION_EXTENSION_VIEW_REGISTERED, - content::Source<Profile>(profile_)); - registrar_.Add(this, - extensions::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED, - content::Source<Profile>(profile_)); - - // TODO(limasdf): Use scoped_observer instead. - ErrorConsole::Get(profile)->AddObserver(this); - + : extension_registry_observer_(this), + error_console_observer_(this), + process_manager_observer_(this), + profile_(profile) { extension_registry_observer_.Add(ExtensionRegistry::Get(profile_)); + error_console_observer_.Add(ErrorConsole::Get(profile)); + process_manager_observer_.Add(ProcessManager::Get(profile)); } DeveloperPrivateEventRouter::~DeveloperPrivateEventRouter() { - ErrorConsole::Get(profile_)->RemoveObserver(this); } void DeveloperPrivateEventRouter::AddExtensionId( @@ -238,36 +225,6 @@ void DeveloperPrivateEventRouter::RemoveExtensionId( extension_ids_.erase(extension_id); } -void DeveloperPrivateEventRouter::Observe( - int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - Profile* profile = content::Source<Profile>(source).ptr(); - CHECK(profile); - CHECK(profile_->IsSameProfile(profile)); - developer::EventData event_data; - - switch (type) { - case extensions::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED: { - event_data.event_type = developer::EVENT_TYPE_VIEW_UNREGISTERED; - event_data.item_id = GetExtensionID( - content::Details<const content::RenderViewHost>(details).ptr()); - break; - } - case extensions::NOTIFICATION_EXTENSION_VIEW_REGISTERED: { - event_data.event_type = developer::EVENT_TYPE_VIEW_REGISTERED; - event_data.item_id = GetExtensionID( - content::Details<const content::RenderViewHost>(details).ptr()); - break; - } - default: - NOTREACHED(); - return; - } - - BroadcastItemStateChanged(profile, event_data.event_type, event_data.item_id); -} - void DeveloperPrivateEventRouter::OnExtensionLoaded( content::BrowserContext* browser_context, const Extension* extension) { @@ -316,6 +273,20 @@ void DeveloperPrivateEventRouter::OnErrorAdded(const ExtensionError* error) { profile_, developer::EVENT_TYPE_ERROR_ADDED, error->extension_id()); } +void DeveloperPrivateEventRouter::OnExtensionFrameRegistered( + const std::string& extension_id, + content::RenderFrameHost* render_frame_host) { + BroadcastItemStateChanged( + profile_, developer::EVENT_TYPE_VIEW_REGISTERED, extension_id); +} + +void DeveloperPrivateEventRouter::OnExtensionFrameUnregistered( + const std::string& extension_id, + content::RenderFrameHost* render_frame_host) { + BroadcastItemStateChanged( + profile_, developer::EVENT_TYPE_VIEW_UNREGISTERED, extension_id); +} + void DeveloperPrivateAPI::SetLastUnpackedDirectory(const base::FilePath& path) { last_unpacked_directory_ = path; } diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.h b/chrome/browser/extensions/api/developer_private/developer_private_api.h index 707bc8d..8126d77 100644 --- a/chrome/browser/extensions/api/developer_private/developer_private_api.h +++ b/chrome/browser/extensions/api/developer_private/developer_private_api.h @@ -15,12 +15,10 @@ #include "chrome/browser/extensions/error_console/error_console.h" #include "chrome/browser/extensions/extension_uninstall_dialog.h" #include "chrome/browser/extensions/pack_extension_job.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" -#include "content/public/browser/render_view_host.h" #include "extensions/browser/browser_context_keyed_api_factory.h" #include "extensions/browser/event_router.h" #include "extensions/browser/extension_registry_observer.h" +#include "extensions/browser/process_manager_observer.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_operation.h" #include "ui/shell_dialogs/select_file_dialog.h" @@ -33,6 +31,7 @@ class ExtensionError; class ExtensionRegistry; class ExtensionSystem; class ManagementPolicy; +class ProcessManager; class RequirementsChecker; namespace api { @@ -61,9 +60,9 @@ typedef std::vector<linked_ptr<developer::ProjectInfo> > ProjectInfoList; typedef std::vector<linked_ptr<developer::ItemInspectView> > ItemInspectViewList; -class DeveloperPrivateEventRouter : public content::NotificationObserver, - public ExtensionRegistryObserver, - public ErrorConsole::Observer { +class DeveloperPrivateEventRouter : public ExtensionRegistryObserver, + public ErrorConsole::Observer, + public ProcessManagerObserver { public: explicit DeveloperPrivateEventRouter(Profile* profile); ~DeveloperPrivateEventRouter() override; @@ -73,12 +72,7 @@ class DeveloperPrivateEventRouter : public content::NotificationObserver, void RemoveExtensionId(const std::string& extension_id); private: - // content::NotificationObserver implementation. - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; - - // ExtensionRegistryObserver implementation. + // ExtensionRegistryObserver: void OnExtensionLoaded(content::BrowserContext* browser_context, const Extension* extension) override; void OnExtensionUnloaded(content::BrowserContext* browser_context, @@ -93,14 +87,22 @@ class DeveloperPrivateEventRouter : public content::NotificationObserver, const Extension* extension, extensions::UninstallReason reason) override; - // ErrorConsole::Observer implementation. + // ErrorConsole::Observer: void OnErrorAdded(const ExtensionError* error) override; - content::NotificationRegistrar registrar_; + // ProcessManagerObserver: + void OnExtensionFrameRegistered( + const std::string& extension_id, + content::RenderFrameHost* render_frame_host) override; + void OnExtensionFrameUnregistered( + const std::string& extension_id, + content::RenderFrameHost* render_frame_host) override; - ScopedObserver<extensions::ExtensionRegistry, - extensions::ExtensionRegistryObserver> + ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> extension_registry_observer_; + ScopedObserver<ErrorConsole, ErrorConsole::Observer> error_console_observer_; + ScopedObserver<ProcessManager, ProcessManagerObserver> + process_manager_observer_; Profile* profile_; diff --git a/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc b/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc index 6bbccf2..431d4ab 100644 --- a/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc +++ b/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc @@ -6,6 +6,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/common/extensions/api/developer_private.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" @@ -105,7 +106,7 @@ void InspectableViewsFinder::GetViewsForExtensionForProfile( // Get the extension process's active views. GetViewsForExtensionProcess( extension, - process_manager->GetRenderViewHostsForExtension(extension.id()), + process_manager->GetRenderFrameHostsForExtension(extension.id()), is_incognito, result); // Get app window views, if not incognito. @@ -126,14 +127,14 @@ void InspectableViewsFinder::GetViewsForExtensionForProfile( void InspectableViewsFinder::GetViewsForExtensionProcess( const Extension& extension, - const std::set<content::RenderViewHost*>& views, + const std::set<content::RenderFrameHost*>& hosts, bool is_incognito, ViewList* result) { - for (const content::RenderViewHost* host : views) { + for (content::RenderFrameHost* host : hosts) { content::WebContents* web_contents = - content::WebContents::FromRenderViewHost(host); + content::WebContents::FromRenderFrameHost(host); ViewType host_type = GetViewType(web_contents); - if (host == deleting_rvh_ || + if (host->GetRenderViewHost() == deleting_rvh_ || host_type == VIEW_TYPE_EXTENSION_POPUP || host_type == VIEW_TYPE_EXTENSION_DIALOG) { continue; @@ -144,7 +145,7 @@ void InspectableViewsFinder::GetViewsForExtensionProcess( result->push_back(ConstructView( url, process->GetID(), - host->GetRoutingID(), + host->GetRenderViewHost()->GetRoutingID(), is_incognito, host_type)); } diff --git a/chrome/browser/extensions/api/developer_private/inspectable_views_finder.h b/chrome/browser/extensions/api/developer_private/inspectable_views_finder.h index 3cb50dd..70b5ea1 100644 --- a/chrome/browser/extensions/api/developer_private/inspectable_views_finder.h +++ b/chrome/browser/extensions/api/developer_private/inspectable_views_finder.h @@ -16,6 +16,7 @@ class Profile; class GURL; namespace content { +class RenderFrameHost; class RenderViewHost; } @@ -63,7 +64,7 @@ class InspectableViewsFinder { // Returns all inspectable views for the extension process. void GetViewsForExtensionProcess( const Extension& extension, - const std::set<content::RenderViewHost*>& views, + const std::set<content::RenderFrameHost*>& frames, bool is_incognito, ViewList* result); diff --git a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc index f1db11c..91b7186 100644 --- a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc +++ b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc @@ -259,11 +259,8 @@ ChromeContentBrowserClientExtensionsPart::ShouldTryToUseExistingProcessHost( GetLoadedProfiles(); for (size_t i = 0; i < profiles.size(); ++i) { ProcessManager* epm = ProcessManager::Get(profiles[i]); - for (ProcessManager::const_iterator iter = epm->background_hosts().begin(); - iter != epm->background_hosts().end(); ++iter) { - const ExtensionHost* host = *iter; + for (extensions::ExtensionHost* host : epm->background_hosts()) process_ids.insert(host->render_process_host()->GetID()); - } } return (process_ids.size() > diff --git a/chrome/browser/extensions/chrome_process_manager_delegate.cc b/chrome/browser/extensions/chrome_process_manager_delegate.cc index e0d9875..e3d1354 100644 --- a/chrome/browser/extensions/chrome_process_manager_delegate.cc +++ b/chrome/browser/extensions/chrome_process_manager_delegate.cc @@ -113,7 +113,7 @@ void ChromeProcessManagerDelegate::OnBrowserWindowReady(Browser* browser) { // a related incognito profile or other regular profiles. ProcessManager* manager = ProcessManager::Get(profile); DCHECK(manager); - DCHECK_EQ(profile, manager->GetBrowserContext()); + DCHECK_EQ(profile, manager->browser_context()); manager->MaybeCreateStartupBackgroundHosts(); // For incognito profiles also inform the original profile's process manager @@ -124,7 +124,7 @@ void ChromeProcessManagerDelegate::OnBrowserWindowReady(Browser* browser) { Profile* original_profile = profile->GetOriginalProfile(); ProcessManager* original_manager = ProcessManager::Get(original_profile); DCHECK(original_manager); - DCHECK_EQ(original_profile, original_manager->GetBrowserContext()); + DCHECK_EQ(original_profile, original_manager->browser_context()); original_manager->MaybeCreateStartupBackgroundHosts(); } } diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc index 2243400..777ad82 100644 --- a/chrome/browser/extensions/extension_browsertest.cc +++ b/chrome/browser/extensions/extension_browsertest.cc @@ -637,22 +637,17 @@ extensions::ExtensionHost* ExtensionBrowserTest::FindHostWithPath( extensions::ProcessManager* manager, const std::string& path, int expected_hosts) { - extensions::ExtensionHost* host = NULL; + extensions::ExtensionHost* result_host = nullptr; int num_hosts = 0; - extensions::ProcessManager::ExtensionHostSet background_hosts = - manager->background_hosts(); - for (extensions::ProcessManager::const_iterator iter = - background_hosts.begin(); - iter != background_hosts.end(); - ++iter) { - if ((*iter)->GetURL().path() == path) { - EXPECT_FALSE(host); - host = *iter; + for (extensions::ExtensionHost* host : manager->background_hosts()) { + if (host->GetURL().path() == path) { + EXPECT_FALSE(result_host); + result_host = host; } num_hosts++; } EXPECT_EQ(expected_hosts, num_hosts); - return host; + return result_host; } std::string ExtensionBrowserTest::ExecuteScriptInBackgroundPage( diff --git a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc index 9a40df8..079c2c1 100644 --- a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc +++ b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc @@ -93,11 +93,11 @@ class ExtensionCrashRecoveryTestBase : public ExtensionBrowserTest { extensions::ExtensionHost* extension_host = GetProcessManager()-> GetBackgroundHostForExtension(extension_id); ASSERT_TRUE(extension_host); - extensions::ProcessManager::ViewSet all_views = - GetProcessManager()->GetAllViews(); - extensions::ProcessManager::ViewSet::const_iterator it = - all_views.find(extension_host->host_contents()->GetRenderViewHost()); - ASSERT_FALSE(it == all_views.end()); + extensions::ProcessManager::FrameSet frames = + GetProcessManager()->GetAllFrames(); + ASSERT_NE(frames.end(), + frames.find(extension_host->host_contents()->GetMainFrame())); + ASSERT_FALSE(GetProcessManager()->GetAllFrames().empty()); ASSERT_TRUE(extension_host->IsRenderViewLive()); extensions::ProcessMap* process_map = extensions::ProcessMap::Get(browser()->profile()); diff --git a/chrome/browser/extensions/extension_test_notification_observer.cc b/chrome/browser/extensions/extension_test_notification_observer.cc index 403e6b9..da99e29 100644 --- a/chrome/browser/extensions/extension_test_notification_observer.cc +++ b/chrome/browser/extensions/extension_test_notification_observer.cc @@ -35,13 +35,11 @@ bool HasPageActionVisibilityReachedTarget( target_visible_page_action_count; } -bool HaveAllExtensionRenderViewHostsFinishedLoading( +bool HaveAllExtensionRenderFrameHostsFinishedLoading( extensions::ProcessManager* manager) { - extensions::ProcessManager::ViewSet all_views = manager->GetAllViews(); - for (extensions::ProcessManager::ViewSet::const_iterator iter = - all_views.begin(); - iter != all_views.end(); ++iter) { - if ((*iter)->IsLoading()) + extensions::ProcessManager::FrameSet all_views = manager->GetAllFrames(); + for (content::RenderFrameHost* host : manager->GetAllFrames()) { + if (content::WebContents::FromRenderFrameHost(host)->IsLoading()) return false; } return true; @@ -150,7 +148,7 @@ bool ExtensionTestNotificationObserver::WaitForExtensionViewsToLoad() { notification_set.Add(content::NOTIFICATION_WEB_CONTENTS_DESTROYED); notification_set.Add(content::NOTIFICATION_LOAD_STOP); WaitForCondition( - base::Bind(&HaveAllExtensionRenderViewHostsFinishedLoading, manager), + base::Bind(&HaveAllExtensionRenderFrameHostsFinishedLoading, manager), ¬ification_set); return true; } diff --git a/chrome/browser/extensions/extension_util.cc b/chrome/browser/extensions/extension_util.cc index 4c3bb79..3491419 100644 --- a/chrome/browser/extensions/extension_util.cc +++ b/chrome/browser/extensions/extension_util.cc @@ -315,7 +315,7 @@ bool IsExtensionIdle(const std::string& extension_id, if (site_instance && site_instance->HasProcess()) return false; - if (!process_manager->GetRenderViewHostsForExtension(id).empty()) + if (!process_manager->GetRenderFrameHostsForExtension(id).empty()) return false; } return true; diff --git a/chrome/browser/extensions/gtalk_extension_browsertest.cc b/chrome/browser/extensions/gtalk_extension_browsertest.cc deleted file mode 100644 index 7d5a6d7..0000000 --- a/chrome/browser/extensions/gtalk_extension_browsertest.cc +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2013 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 "base/bind.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/extensions/extension_browsertest.h" -#include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_commands.h" -#include "content/public/browser/render_process_host.h" -#include "content/public/browser/render_view_host.h" -#include "content/public/browser/web_contents.h" -#include "content/public/common/url_constants.h" -#include "content/public/test/browser_test_utils.h" -#include "extensions/browser/extension_host.h" -#include "extensions/browser/extension_system.h" -#include "extensions/browser/process_manager.h" -#include "extensions/common/constants.h" - -using content::RenderViewHost; -using content::WebContents; -using extensions::Extension; - -class GtalkExtensionTest : public ExtensionBrowserTest { - protected: - extensions::ProcessManager* GetProcessManager() { - return extensions::ExtensionSystem::Get(browser()->profile())-> - process_manager(); - } - - void InstallGtalkExtension(const std::string& version) { - const Extension* extension = InstallExtensionWithUIAutoConfirm( - test_data_dir_.AppendASCII("gtalk").AppendASCII(version + ".crx"), - 1, browser()); - installed_extension_id_ = extension->id(); - } - - const std::string& GetInstalledExtensionId() { - return installed_extension_id_; - } - - RenderViewHost* GetViewer() { - std::vector<RenderViewHost*> views = GetMatchingViews(GetViewerUrl()); - EXPECT_EQ(1U, views.size()); - if (views.empty()) - return NULL; - return views.front(); - } - - std::string GetViewerUrl() { - return std::string(extensions::kExtensionScheme) + - url::kStandardSchemeSeparator + GetInstalledExtensionId() + - "/viewer.html"; - } - - std::vector<RenderViewHost*> GetMatchingViews(const std::string& url_query) { - extensions::ProcessManager* manager = GetProcessManager(); - extensions::ProcessManager::ViewSet all_views = manager->GetAllViews(); - std::vector<RenderViewHost*> matching_views; - for (extensions::ProcessManager::ViewSet::const_iterator iter = - all_views.begin(); iter != all_views.end(); ++iter) { - WebContents* web_contents = WebContents::FromRenderViewHost(*iter); - std::string url = web_contents->GetURL().spec(); - if (url.find(url_query) != std::string::npos) - matching_views.push_back(*iter); - } - return matching_views; - } - - std::string ReadCurrentVersion() { - std::string response; - EXPECT_TRUE(base::ReadFileToString( - test_data_dir_.AppendASCII("gtalk").AppendASCII("current_version"), - &response)); - return response; - } - - private: - std::string installed_extension_id_; -}; - -IN_PROC_BROWSER_TEST_F(GtalkExtensionTest, InstallCurrent) { - content::WindowedNotificationObserver panel_loaded( - extensions::NOTIFICATION_EXTENSION_VIEW_REGISTERED, - content::NotificationService::AllSources()); - InstallGtalkExtension(ReadCurrentVersion()); - panel_loaded.Wait(); - ASSERT_TRUE(GetViewer()); -} diff --git a/chrome/browser/extensions/process_management_browsertest.cc b/chrome/browser/extensions/process_management_browsertest.cc index 3515540..67ef9e8 100644 --- a/chrome/browser/extensions/process_management_browsertest.cc +++ b/chrome/browser/extensions/process_management_browsertest.cc @@ -226,11 +226,8 @@ IN_PROC_BROWSER_TEST_F(ProcessManagementTest, MAYBE_ExtensionProcessBalancing) { std::set<int> process_ids; Profile* profile = browser()->profile(); extensions::ProcessManager* epm = extensions::ProcessManager::Get(profile); - for (extensions::ProcessManager::const_iterator iter = - epm->background_hosts().begin(); - iter != epm->background_hosts().end(); ++iter) { - process_ids.insert((*iter)->render_process_host()->GetID()); - } + for (extensions::ExtensionHost* host : epm->background_hosts()) + process_ids.insert(host->render_process_host()->GetID()); // We've loaded 5 extensions with background pages, 1 extension without // background page, and one isolated app. We expect only 2 unique processes diff --git a/chrome/browser/extensions/process_manager_browsertest.cc b/chrome/browser/extensions/process_manager_browsertest.cc index 5bbc2aa..c8a8e00 100644 --- a/chrome/browser/extensions/process_manager_browsertest.cc +++ b/chrome/browser/extensions/process_manager_browsertest.cc @@ -30,7 +30,7 @@ IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, // We start with no background hosts. ASSERT_EQ(0u, pm->background_hosts().size()); - ASSERT_EQ(0u, pm->GetAllViews().size()); + ASSERT_EQ(0u, pm->GetAllFrames().size()); // Load an extension with a background page. scoped_refptr<const Extension> extension = @@ -41,10 +41,10 @@ IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, // Process manager gains a background host. EXPECT_EQ(1u, pm->background_hosts().size()); - EXPECT_EQ(1u, pm->GetAllViews().size()); + EXPECT_EQ(1u, pm->GetAllFrames().size()); EXPECT_TRUE(pm->GetBackgroundHostForExtension(extension->id())); EXPECT_TRUE(pm->GetSiteInstanceForURL(extension->url())); - EXPECT_EQ(1u, pm->GetRenderViewHostsForExtension(extension->id()).size()); + EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension->id()).size()); EXPECT_FALSE(pm->IsBackgroundHostClosing(extension->id())); EXPECT_EQ(0, pm->GetLazyKeepaliveCount(extension.get())); @@ -53,10 +53,10 @@ IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, // Background host disappears. EXPECT_EQ(0u, pm->background_hosts().size()); - EXPECT_EQ(0u, pm->GetAllViews().size()); + EXPECT_EQ(0u, pm->GetAllFrames().size()); EXPECT_FALSE(pm->GetBackgroundHostForExtension(extension->id())); EXPECT_TRUE(pm->GetSiteInstanceForURL(extension->url())); - EXPECT_EQ(0u, pm->GetRenderViewHostsForExtension(extension->id()).size()); + EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension->id()).size()); EXPECT_FALSE(pm->IsBackgroundHostClosing(extension->id())); EXPECT_EQ(0, pm->GetLazyKeepaliveCount(extension.get())); } @@ -79,9 +79,9 @@ IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, // No background host was added. EXPECT_EQ(0u, pm->background_hosts().size()); - EXPECT_EQ(0u, pm->GetAllViews().size()); + EXPECT_EQ(0u, pm->GetAllFrames().size()); EXPECT_FALSE(pm->GetBackgroundHostForExtension(popup->id())); - EXPECT_EQ(0u, pm->GetRenderViewHostsForExtension(popup->id()).size()); + EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(popup->id()).size()); EXPECT_TRUE(pm->GetSiteInstanceForURL(popup->url())); EXPECT_FALSE(pm->IsBackgroundHostClosing(popup->id())); EXPECT_EQ(0, pm->GetLazyKeepaliveCount(popup.get())); @@ -98,9 +98,9 @@ IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, // We now have a view, but still no background hosts. EXPECT_EQ(0u, pm->background_hosts().size()); - EXPECT_EQ(1u, pm->GetAllViews().size()); + EXPECT_EQ(1u, pm->GetAllFrames().size()); EXPECT_FALSE(pm->GetBackgroundHostForExtension(popup->id())); - EXPECT_EQ(1u, pm->GetRenderViewHostsForExtension(popup->id()).size()); + EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(popup->id()).size()); EXPECT_TRUE(pm->GetSiteInstanceForURL(popup->url())); EXPECT_FALSE(pm->IsBackgroundHostClosing(popup->id())); EXPECT_EQ(0, pm->GetLazyKeepaliveCount(popup.get())); @@ -114,7 +114,7 @@ IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, HttpHostMatchingExtensionId) { // We start with no background hosts. ASSERT_EQ(0u, pm->background_hosts().size()); - ASSERT_EQ(0u, pm->GetAllViews().size()); + ASSERT_EQ(0u, pm->GetAllFrames().size()); // Load an extension with a background page. scoped_refptr<const Extension> extension = @@ -144,13 +144,12 @@ IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, HttpHostMatchingExtensionId) { content::WebContents* tab_web_contents = browser()->tab_strip_model()->GetActiveWebContents(); EXPECT_EQ(url, tab_web_contents->GetVisibleURL()); - EXPECT_TRUE(NULL == pm->GetExtensionForRenderViewHost( - tab_web_contents->GetRenderViewHost())) + EXPECT_FALSE(pm->GetExtensionForWebContents(tab_web_contents)) << "Non-extension content must not have an associated extension"; - ASSERT_EQ(1u, pm->GetRenderViewHostsForExtension(extension->id()).size()); + ASSERT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension->id()).size()); content::WebContents* extension_web_contents = - content::WebContents::FromRenderViewHost( - *pm->GetRenderViewHostsForExtension(extension->id()).begin()); + content::WebContents::FromRenderFrameHost( + *pm->GetRenderFrameHostsForExtension(extension->id()).begin()); EXPECT_TRUE(extension_web_contents->GetSiteInstance() != tab_web_contents->GetSiteInstance()); EXPECT_TRUE(pm->GetSiteInstanceForURL(extension->url()) != diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc index 902e514..05c0694 100644 --- a/chrome/browser/policy/policy_browsertest.cc +++ b/chrome/browser/policy/policy_browsertest.cc @@ -1802,23 +1802,23 @@ IN_PROC_BROWSER_TEST_F(PolicyTest, ExtensionInstallForcelist) { // have been loaded. extensions::ProcessManager* manager = extensions::ProcessManager::Get(browser()->profile()); - extensions::ProcessManager::ViewSet all_views = manager->GetAllViews(); - for (extensions::ProcessManager::ViewSet::const_iterator iter = - all_views.begin(); - iter != all_views.end();) { - if (!(*iter)->IsLoading()) { + extensions::ProcessManager::FrameSet all_frames = manager->GetAllFrames(); + for (extensions::ProcessManager::FrameSet::const_iterator iter = + all_frames.begin(); + iter != all_frames.end();) { + content::WebContents* web_contents = + content::WebContents::FromRenderFrameHost(*iter); + ASSERT_TRUE(web_contents); + if (!web_contents->IsLoading()) { ++iter; } else { - content::WebContents* web_contents = - content::WebContents::FromRenderViewHost(*iter); - ASSERT_TRUE(web_contents); WebContentsLoadedOrDestroyedWatcher(web_contents).Wait(); // Test activity may have modified the set of extension processes during // message processing, so re-start the iteration to catch added/removed // processes. - all_views = manager->GetAllViews(); - iter = all_views.begin(); + all_frames = manager->GetAllFrames(); + iter = all_frames.begin(); } } diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index b6d877e..6946015 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc @@ -633,8 +633,7 @@ void RenderViewContextMenu::AppendPrintPreviewItems() { const Extension* RenderViewContextMenu::GetExtension() const { return extensions::ProcessManager::Get(browser_context_) - ->GetExtensionForRenderViewHost( - source_web_contents_->GetRenderViewHost()); + ->GetExtensionForWebContents(source_web_contents_); } void RenderViewContextMenu::AppendDeveloperItems() { diff --git a/chrome/browser/task_manager/extension_information.cc b/chrome/browser/task_manager/extension_information.cc index 6dcf014..df1f0e3 100644 --- a/chrome/browser/task_manager/extension_information.cc +++ b/chrome/browser/task_manager/extension_information.cc @@ -31,7 +31,7 @@ namespace { const Extension* GetExtensionForWebContents(WebContents* web_contents) { return extensions::ProcessManager::Get(web_contents->GetBrowserContext()) - ->GetExtensionForRenderViewHost(web_contents->GetRenderViewHost()); + ->GetExtensionForWebContents(web_contents); } } // namespace @@ -124,11 +124,10 @@ void ExtensionInformation::GetAll(const NewWebContentsCallback& callback) { } for (size_t i = 0; i < profiles.size(); ++i) { - const extensions::ProcessManager::ViewSet all_views = - extensions::ProcessManager::Get(profiles[i])->GetAllViews(); - extensions::ProcessManager::ViewSet::const_iterator jt = all_views.begin(); - for (; jt != all_views.end(); ++jt) { - WebContents* web_contents = WebContents::FromRenderViewHost(*jt); + const extensions::ProcessManager::FrameSet all_frames = + extensions::ProcessManager::Get(profiles[i])->GetAllFrames(); + for (content::RenderFrameHost* host : all_frames) { + WebContents* web_contents = WebContents::FromRenderFrameHost(host); if (CheckOwnership(web_contents)) callback.Run(web_contents); } diff --git a/chrome/browser/ui/ash/media_delegate_chromeos.cc b/chrome/browser/ui/ash/media_delegate_chromeos.cc index 53cc92f..3ea4aa4 100644 --- a/chrome/browser/ui/ash/media_delegate_chromeos.cc +++ b/chrome/browser/ui/ash/media_delegate_chromeos.cc @@ -76,15 +76,11 @@ void GetExtensionMediaCaptureState( const MediaStreamCaptureIndicator* indicator, content::BrowserContext* context, int* media_state_out) { - const extensions::ProcessManager::ViewSet view_set = - extensions::ProcessManager::Get(context)->GetAllViews(); - for (extensions::ProcessManager::ViewSet::const_iterator iter = - view_set.begin(); - iter != view_set.end(); - ++iter) { + for (content::RenderFrameHost* host : + extensions::ProcessManager::Get(context)->GetAllFrames()) { content::WebContents* web_contents = - content::WebContents::FromRenderViewHost(*iter); - // RVH may not have web contents. + content::WebContents::FromRenderFrameHost(host); + // RFH may not have web contents. if (!web_contents) continue; GetMediaCaptureState(indicator, web_contents, media_state_out); diff --git a/chrome/test/data/extensions/gtalk/1.2013.0404.1.crx b/chrome/test/data/extensions/gtalk/1.2013.0404.1.crx Binary files differdeleted file mode 100644 index f6fdac4..0000000 --- a/chrome/test/data/extensions/gtalk/1.2013.0404.1.crx +++ /dev/null diff --git a/chrome/test/data/extensions/gtalk/1.2013.0417.1.crx b/chrome/test/data/extensions/gtalk/1.2013.0417.1.crx Binary files differdeleted file mode 100644 index d27b706..0000000 --- a/chrome/test/data/extensions/gtalk/1.2013.0417.1.crx +++ /dev/null diff --git a/chrome/test/data/extensions/gtalk/current_version b/chrome/test/data/extensions/gtalk/current_version deleted file mode 100644 index 16b978e..0000000 --- a/chrome/test/data/extensions/gtalk/current_version +++ /dev/null @@ -1 +0,0 @@ -1.2013.0404.1
\ No newline at end of file diff --git a/chrome/test/data/extensions/gtalk/rc_version b/chrome/test/data/extensions/gtalk/rc_version deleted file mode 100644 index 34ebd5f..0000000 --- a/chrome/test/data/extensions/gtalk/rc_version +++ /dev/null @@ -1 +0,0 @@ -1.2013.0417.1
\ No newline at end of file diff --git a/components/renderer_context_menu/context_menu_content_type.cc b/components/renderer_context_menu/context_menu_content_type.cc index 60ed1df..6687891 100644 --- a/components/renderer_context_menu/context_menu_content_type.cc +++ b/components/renderer_context_menu/context_menu_content_type.cc @@ -52,8 +52,8 @@ ContextMenuContentType::~ContextMenuContentType() { const Extension* ContextMenuContentType::GetExtension() const { ProcessManager* process_manager = ProcessManager::Get(source_web_contents_->GetBrowserContext()); - return process_manager->GetExtensionForRenderViewHost( - source_web_contents_->GetRenderViewHost()); + return process_manager->GetExtensionForWebContents( + source_web_contents_); } #endif diff --git a/extensions/browser/app_window/app_window.cc b/extensions/browser/app_window/app_window.cc index 0689b13..fc56bae 100644 --- a/extensions/browser/app_window/app_window.cc +++ b/extensions/browser/app_window/app_window.cc @@ -253,6 +253,7 @@ void AppWindow::Init(const GURL& url, app_window_contents_->Initialize(browser_context(), url); content::WebContentsObserver::Observe(web_contents()); + SetViewType(web_contents(), VIEW_TYPE_APP_WINDOW); app_delegate_->InitWebContents(web_contents()); WebContentsModalDialogManager::CreateForWebContents(web_contents()); @@ -260,7 +261,6 @@ void AppWindow::Init(const GURL& url, web_contents()->SetDelegate(this); WebContentsModalDialogManager::FromWebContents(web_contents()) ->SetDelegate(this); - SetViewType(web_contents(), VIEW_TYPE_APP_WINDOW); // Initialize the window CreateParams new_params = LoadDefaults(params); diff --git a/extensions/browser/extension_web_contents_observer.cc b/extensions/browser/extension_web_contents_observer.cc index 020cc32..dd0a628 100644 --- a/extensions/browser/extension_web_contents_observer.cc +++ b/extensions/browser/extension_web_contents_observer.cc @@ -5,6 +5,7 @@ #include "extensions/browser/extension_web_contents_observer.h" #include "content/public/browser/child_process_security_policy.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/site_instance.h" @@ -13,6 +14,7 @@ #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/mojo/service_registration.h" +#include "extensions/browser/process_manager.h" #include "extensions/browser/view_type_utils.h" #include "extensions/common/constants.h" #include "extensions/common/extension_messages.h" @@ -24,9 +26,13 @@ ExtensionWebContentsObserver::ExtensionWebContentsObserver( : content::WebContentsObserver(web_contents), browser_context_(web_contents->GetBrowserContext()) { NotifyRenderViewType(web_contents->GetRenderViewHost()); + content::RenderFrameHost* host = web_contents->GetMainFrame(); + if (host) + RenderFrameHostChanged(nullptr, host); } -ExtensionWebContentsObserver::~ExtensionWebContentsObserver() {} +ExtensionWebContentsObserver::~ExtensionWebContentsObserver() { +} void ExtensionWebContentsObserver::RenderViewCreated( content::RenderViewHost* render_view_host) { @@ -95,6 +101,26 @@ void ExtensionWebContentsObserver::RenderFrameCreated( RegisterCoreExtensionServices(render_frame_host); } +void ExtensionWebContentsObserver::FrameDeleted( + content::RenderFrameHost* render_frame_host) { + ProcessManager::Get(browser_context_)->UnregisterRenderFrameHost( + render_frame_host); +} + +void ExtensionWebContentsObserver::RenderFrameHostChanged( + content::RenderFrameHost* old_host, + content::RenderFrameHost* new_host) { + ProcessManager* process_manager = ProcessManager::Get(browser_context_); + if (old_host) + process_manager->UnregisterRenderFrameHost(old_host); + + const Extension* extension = GetExtension(new_host->GetRenderViewHost()); + if (extension) { + process_manager->RegisterRenderFrameHost( + web_contents(), new_host, extension); + } +} + void ExtensionWebContentsObserver::NotifyRenderViewType( content::RenderViewHost* render_view_host) { if (render_view_host) { diff --git a/extensions/browser/extension_web_contents_observer.h b/extensions/browser/extension_web_contents_observer.h index cd48560..993a8fe 100644 --- a/extensions/browser/extension_web_contents_observer.h +++ b/extensions/browser/extension_web_contents_observer.h @@ -42,6 +42,13 @@ class ExtensionWebContentsObserver : public content::WebContentsObserver { void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override; + // Per the documentation in WebContentsObserver, these two methods are + // appropriate to track the set of current RenderFrameHosts. + // NOTE: FrameDeleted() != RenderFrameDeleted(). + void FrameDeleted(content::RenderFrameHost* render_frame_host) override; + void RenderFrameHostChanged(content::RenderFrameHost* old_host, + content::RenderFrameHost* new_host) override; + // Returns the extension or app associated with a render view host. Returns // NULL if the render view host is not for a valid extension. const Extension* GetExtension(content::RenderViewHost* render_view_host); diff --git a/extensions/browser/guest_view/guest_view_base.cc b/extensions/browser/guest_view/guest_view_base.cc index 899037d..bbbc5cc 100644 --- a/extensions/browser/guest_view/guest_view_base.cc +++ b/extensions/browser/guest_view/guest_view_base.cc @@ -202,8 +202,7 @@ void GuestViewBase::Init(const base::DictionaryValue& create_params, const Extension* owner_extension = ProcessManager::Get(owner_web_contents()->GetBrowserContext())-> - GetExtensionForRenderViewHost( - owner_web_contents()->GetRenderViewHost()); + GetExtensionForWebContents(owner_web_contents()); owner_extension_id_ = owner_extension ? owner_extension->id() : std::string(); // Ok for |owner_extension| to be nullptr, the embedder might be WebUI. diff --git a/extensions/browser/notification_types.h b/extensions/browser/notification_types.h index a5908ed..031cb0c 100644 --- a/extensions/browser/notification_types.h +++ b/extensions/browser/notification_types.h @@ -157,14 +157,6 @@ enum NotificationType { // associated window. NOTIFICATION_EXTENSION_COMMAND_PAGE_ACTION_MAC, - // A new extension RenderViewHost has been registered. The details are - // the RenderViewHost*. - NOTIFICATION_EXTENSION_VIEW_REGISTERED, - - // An extension RenderViewHost has been unregistered. The details are - // the RenderViewHost*. - NOTIFICATION_EXTENSION_VIEW_UNREGISTERED, - // Sent by an extension to notify the browser about the results of a unit // test. NOTIFICATION_EXTENSION_TEST_PASSED, diff --git a/extensions/browser/process_manager.cc b/extensions/browser/process_manager.cc index 5ba41c4..47f7b19 100644 --- a/extensions/browser/process_manager.cc +++ b/extensions/browser/process_manager.cc @@ -5,16 +5,12 @@ #include "extensions/browser/process_manager.h" #include "base/bind.h" -#include "base/command_line.h" -#include "base/lazy_instance.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" #include "base/metrics/histogram_macros.h" #include "base/stl_util.h" -#include "base/strings/string_number_conversions.h" #include "base/time/time.h" #include "content/public/browser/browser_context.h" -#include "content/public/browser/browser_thread.h" #include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/render_frame_host.h" @@ -22,10 +18,6 @@ #include "content/public/browser/render_view_host.h" #include "content/public/browser/site_instance.h" #include "content/public/browser/web_contents.h" -#include "content/public/browser/web_contents_delegate.h" -#include "content/public/browser/web_contents_observer.h" -#include "content/public/browser/web_contents_user_data.h" -#include "content/public/common/renderer_preferences.h" #include "content/public/common/url_constants.h" #include "extensions/browser/extension_host.h" #include "extensions/browser/extension_registry.h" @@ -44,15 +36,6 @@ #include "extensions/common/one_shot_event.h" using content::BrowserContext; -using content::RenderViewHost; -using content::SiteInstance; -using content::WebContents; - -namespace extensions { -class RenderViewHostDestructionObserver; -} -DEFINE_WEB_CONTENTS_USER_DATA_KEY( - extensions::RenderViewHostDestructionObserver); namespace extensions { @@ -68,13 +51,13 @@ unsigned g_event_page_idle_time_msec = 10000; // sending a Suspend message. unsigned g_event_page_suspending_time_msec = 5000; -std::string GetExtensionID(RenderViewHost* render_view_host) { - // This works for both apps and extensions because the site has been - // normalized to the extension URL for hosted apps. - content::SiteInstance* site_instance = render_view_host->GetSiteInstance(); +std::string GetExtensionIdForSiteInstance( + content::SiteInstance* site_instance) { if (!site_instance) return std::string(); + // This works for both apps and extensions because the site has been + // normalized to the extension URL for hosted apps. const GURL& site_url = site_instance->GetSiteURL(); if (!site_url.SchemeIs(kExtensionScheme) && @@ -84,33 +67,23 @@ std::string GetExtensionID(RenderViewHost* render_view_host) { return site_url.host(); } -std::string GetExtensionIDFromFrame( - content::RenderFrameHost* render_frame_host) { - // This works for both apps and extensions because the site has been - // normalized to the extension URL for apps. - if (!render_frame_host->GetSiteInstance()) - return std::string(); - - return render_frame_host->GetSiteInstance()->GetSiteURL().host(); +std::string GetExtensionID(content::RenderFrameHost* render_frame_host) { + CHECK(render_frame_host); + return GetExtensionIdForSiteInstance(render_frame_host->GetSiteInstance()); } bool IsFrameInExtensionHost(ExtensionHost* extension_host, content::RenderFrameHost* render_frame_host) { - return WebContents::FromRenderFrameHost(render_frame_host) == + return content::WebContents::FromRenderFrameHost(render_frame_host) == extension_host->host_contents(); } -void OnRenderViewHostUnregistered(BrowserContext* context, - RenderViewHost* render_view_host) { - content::NotificationService::current()->Notify( - extensions::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED, - content::Source<BrowserContext>(context), - content::Details<RenderViewHost>(render_view_host)); -} - // Incognito profiles use this process manager. It is mostly a shim that decides // whether to fall back on the original profile's ProcessManager based // on whether a given extension uses "split" or "spanning" incognito behavior. +// TODO(devlin): Given how little this does and the amount of cruft it adds to +// the .h file (in the form of protected members), we should consider just +// moving the incognito logic into the base class. class IncognitoProcessManager : public ProcessManager { public: IncognitoProcessManager(BrowserContext* incognito_context, @@ -119,7 +92,8 @@ class IncognitoProcessManager : public ProcessManager { ~IncognitoProcessManager() override {} bool CreateBackgroundHost(const Extension* extension, const GURL& url) override; - scoped_refptr<SiteInstance> GetSiteInstanceForURL(const GURL& url) override; + scoped_refptr<content::SiteInstance> GetSiteInstanceForURL(const GURL& url) + override; private: DISALLOW_COPY_AND_ASSIGN(IncognitoProcessManager); @@ -135,31 +109,6 @@ static void CreateBackgroundHostForExtensionLoad( } // namespace -class RenderViewHostDestructionObserver - : public content::WebContentsObserver, - public content::WebContentsUserData<RenderViewHostDestructionObserver> { - public: - ~RenderViewHostDestructionObserver() override {} - - private: - explicit RenderViewHostDestructionObserver(WebContents* web_contents) - : WebContentsObserver(web_contents) { - BrowserContext* context = web_contents->GetBrowserContext(); - process_manager_ = ProcessManager::Get(context); - } - - friend class content::WebContentsUserData<RenderViewHostDestructionObserver>; - - // content::WebContentsObserver overrides. - void RenderViewDeleted(RenderViewHost* render_view_host) override { - process_manager_->UnregisterRenderViewHost(render_view_host); - } - - ProcessManager* process_manager_; - - DISALLOW_COPY_AND_ASSIGN(RenderViewHostDestructionObserver); -}; - struct ProcessManager::BackgroundPageData { // The count of things keeping the lazy background page alive. int lazy_keepalive_count; @@ -192,15 +141,15 @@ struct ProcessManager::BackgroundPageData { close_sequence_id(0) {} }; -// Data of a RenderViewHost associated with an extension. -struct ProcessManager::ExtensionRenderViewData { +// Data of a RenderFrameHost associated with an extension. +struct ProcessManager::ExtensionRenderFrameData { // The type of the view. extensions::ViewType view_type; // Whether the view is keeping the lazy background page alive or not. bool has_keepalive; - ExtensionRenderViewData() + ExtensionRenderFrameData() : view_type(VIEW_TYPE_INVALID), has_keepalive(false) {} // Returns whether the view can keep the lazy background page alive or not. @@ -279,30 +228,31 @@ ProcessManager* ProcessManager::CreateIncognitoForTesting( ProcessManager::ProcessManager(BrowserContext* context, BrowserContext* original_context, ExtensionRegistry* extension_registry) - : site_instance_(SiteInstance::Create(context)), - extension_registry_(extension_registry), + : extension_registry_(extension_registry), + site_instance_(content::SiteInstance::Create(context)), + browser_context_(context), startup_background_hosts_created_(false), - devtools_callback_(base::Bind(&ProcessManager::OnDevToolsStateChanged, - base::Unretained(this))), last_background_close_sequence_id_(0), weak_ptr_factory_(this) { // ExtensionRegistry is shared between incognito and regular contexts. DCHECK_EQ(original_context, extension_registry_->browser_context()); extension_registry_->AddObserver(this); - registrar_.Add(this, + + if (!context->IsOffTheRecord()) { + // Only the original profile needs to listen for ready to create background + // pages for all spanning extensions. + registrar_.Add(this, extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED, content::Source<BrowserContext>(original_context)); + } registrar_.Add(this, extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED, content::Source<BrowserContext>(context)); registrar_.Add(this, extensions::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, content::Source<BrowserContext>(context)); - registrar_.Add(this, content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, - content::NotificationService::AllSources()); - registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED, - content::NotificationService::AllSources()); - + devtools_callback_ = base::Bind(&ProcessManager::OnDevToolsStateChanged, + weak_ptr_factory_.GetWeakPtr()); content::DevToolsAgentHost::AddAgentStateCallback(devtools_callback_); OnKeepaliveImpulseCheck(); @@ -315,13 +265,68 @@ ProcessManager::~ProcessManager() { content::DevToolsAgentHost::RemoveAgentStateCallback(devtools_callback_); } -const ProcessManager::ViewSet ProcessManager::GetAllViews() const { - ViewSet result; - for (ExtensionRenderViews::const_iterator iter = - all_extension_views_.begin(); - iter != all_extension_views_.end(); ++iter) { - result.insert(iter->first); +void ProcessManager::RegisterRenderFrameHost( + content::WebContents* web_contents, + content::RenderFrameHost* render_frame_host, + const Extension* extension) { + ExtensionRenderFrameData* data = &all_extension_frames_[render_frame_host]; + data->view_type = GetViewType(web_contents); + + // Keep the lazy background page alive as long as any non-background-page + // extension views are visible. Keepalive count balanced in + // UnregisterRenderFrame. + AcquireLazyKeepaliveCountForFrame(render_frame_host); + + FOR_EACH_OBSERVER(ProcessManagerObserver, + observer_list_, + OnExtensionFrameRegistered(extension->id(), + render_frame_host)); +} + +void ProcessManager::UnregisterRenderFrameHost( + content::RenderFrameHost* render_frame_host) { + ExtensionRenderFrames::iterator frame = + all_extension_frames_.find(render_frame_host); + + if (frame != all_extension_frames_.end()) { + std::string extension_id = GetExtensionID(render_frame_host); + // Keepalive count, balanced in RegisterRenderFrame. + ReleaseLazyKeepaliveCountForFrame(render_frame_host); + all_extension_frames_.erase(frame); + + FOR_EACH_OBSERVER(ProcessManagerObserver, + observer_list_, + OnExtensionFrameUnregistered(extension_id, + render_frame_host)); + } +} + +scoped_refptr<content::SiteInstance> ProcessManager::GetSiteInstanceForURL( + const GURL& url) { + return make_scoped_refptr(site_instance_->GetRelatedSiteInstance(url)); +} + +const ProcessManager::FrameSet ProcessManager::GetAllFrames() const { + FrameSet result; + for (const auto& key_value : all_extension_frames_) + result.insert(key_value.first); + return result; +} + +ProcessManager::FrameSet ProcessManager::GetRenderFrameHostsForExtension( + const std::string& extension_id) { + FrameSet result; + scoped_refptr<content::SiteInstance> site_instance(GetSiteInstanceForURL( + Extension::GetBaseURLFromExtensionId(extension_id))); + if (!site_instance.get()) + return result; + + // Gather up all the frames for that site. + for (const auto& key_value : all_extension_frames_) { + if (key_value.first->GetSiteInstance() == site_instance) + result.insert(key_value.first); } + return result; } @@ -343,7 +348,7 @@ bool ProcessManager::CreateBackgroundHost(const Extension* extension, // Don't create hosts if the embedder doesn't allow it. ProcessManagerDelegate* delegate = ExtensionsBrowserClient::Get()->GetProcessManagerDelegate(); - if (delegate && !delegate->IsBackgroundPageAllowed(GetBrowserContext())) + if (delegate && !delegate->IsBackgroundPageAllowed(browser_context_)) return false; // Don't create multiple background hosts for an extension. @@ -358,113 +363,47 @@ bool ProcessManager::CreateBackgroundHost(const Extension* extension, return true; } -ExtensionHost* ProcessManager::GetBackgroundHostForExtension( - const std::string& extension_id) { - for (ExtensionHostSet::iterator iter = background_hosts_.begin(); - iter != background_hosts_.end(); ++iter) { - ExtensionHost* host = *iter; - if (host->extension_id() == extension_id) - return host; - } - return NULL; -} - -std::set<RenderViewHost*> ProcessManager::GetRenderViewHostsForExtension( - const std::string& extension_id) { - std::set<RenderViewHost*> result; - - scoped_refptr<SiteInstance> site_instance(GetSiteInstanceForURL( - Extension::GetBaseURLFromExtensionId(extension_id))); - if (!site_instance.get()) - return result; - - // Gather up all the views for that site. - for (ExtensionRenderViews::iterator view = all_extension_views_.begin(); - view != all_extension_views_.end(); ++view) { - if (view->first->GetSiteInstance() == site_instance) - result.insert(view->first); - } - - return result; -} - -const Extension* ProcessManager::GetExtensionForRenderViewHost( - RenderViewHost* render_view_host) { - if (!render_view_host->GetSiteInstance()) - return NULL; - - return extension_registry_->enabled_extensions().GetByID( - GetExtensionID(render_view_host)); -} - -void ProcessManager::AcquireLazyKeepaliveCountForView( - content::RenderViewHost* render_view_host) { - auto it = all_extension_views_.find(render_view_host); - if (it == all_extension_views_.end()) +void ProcessManager::MaybeCreateStartupBackgroundHosts() { + if (startup_background_hosts_created_) return; - ExtensionRenderViewData* data = &it->second; - if (data->CanKeepalive() && !data->has_keepalive) { - const Extension* extension = - GetExtensionForRenderViewHost(render_view_host); - if (extension) { - IncrementLazyKeepaliveCount(extension); - data->has_keepalive = true; - } - } -} - -void ProcessManager::ReleaseLazyKeepaliveCountForView( - content::RenderViewHost* render_view_host) { - auto it = all_extension_views_.find(render_view_host); - if (it == all_extension_views_.end()) + // The embedder might disallow background pages entirely. + ProcessManagerDelegate* delegate = + ExtensionsBrowserClient::Get()->GetProcessManagerDelegate(); + if (delegate && !delegate->IsBackgroundPageAllowed(browser_context_)) return; - ExtensionRenderViewData* data = &it->second; - if (data->CanKeepalive() && data->has_keepalive) { - const Extension* extension = - GetExtensionForRenderViewHost(render_view_host); - if (extension) { - DecrementLazyKeepaliveCount(extension); - data->has_keepalive = false; - } - } -} - -void ProcessManager::UnregisterRenderViewHost( - RenderViewHost* render_view_host) { - ExtensionRenderViews::iterator view = - all_extension_views_.find(render_view_host); - if (view == all_extension_views_.end()) + // The embedder might want to defer background page loading. For example, + // Chrome defers background page loading when it is launched to show the app + // list, then triggers a load later when a browser window opens. + if (delegate && + delegate->DeferCreatingStartupBackgroundHosts(browser_context_)) return; - OnRenderViewHostUnregistered(GetBrowserContext(), render_view_host); - - // Keepalive count, balanced in RegisterRenderViewHost. - ReleaseLazyKeepaliveCountForView(render_view_host); - all_extension_views_.erase(view); -} - -bool ProcessManager::RegisterRenderViewHost(RenderViewHost* render_view_host) { - const Extension* extension = GetExtensionForRenderViewHost( - render_view_host); - if (!extension) - return false; - - WebContents* web_contents = WebContents::FromRenderViewHost(render_view_host); - ExtensionRenderViewData* data = &all_extension_views_[render_view_host]; - data->view_type = GetViewType(web_contents); + CreateStartupBackgroundHosts(); + startup_background_hosts_created_ = true; - // Keep the lazy background page alive as long as any non-background-page - // extension views are visible. Keepalive count balanced in - // UnregisterRenderViewHost. - AcquireLazyKeepaliveCountForView(render_view_host); - return true; + // Background pages should only be loaded once. To prevent any further loads + // occurring, we remove the notification listeners. + BrowserContext* original_context = + ExtensionsBrowserClient::Get()->GetOriginalContext(browser_context_); + if (registrar_.IsRegistered( + this, + extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED, + content::Source<BrowserContext>(original_context))) { + registrar_.Remove(this, + extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED, + content::Source<BrowserContext>(original_context)); + } } -scoped_refptr<SiteInstance> ProcessManager::GetSiteInstanceForURL( - const GURL& url) { - return make_scoped_refptr(site_instance_->GetRelatedSiteInstance(url)); +ExtensionHost* ProcessManager::GetBackgroundHostForExtension( + const std::string& extension_id) { + for (ExtensionHost* host : background_hosts_) { + if (host->extension_id() == extension_id) + return host; + } + return nullptr; } bool ProcessManager::IsBackgroundHostClosing(const std::string& extension_id) { @@ -472,6 +411,20 @@ bool ProcessManager::IsBackgroundHostClosing(const std::string& extension_id) { return (host && background_page_data_[extension_id].is_closing); } +const Extension* ProcessManager::GetExtensionForRenderFrameHost( + content::RenderFrameHost* render_frame_host) { + return extension_registry_->enabled_extensions().GetByID( + GetExtensionID(render_frame_host)); +} + +const Extension* ProcessManager::GetExtensionForWebContents( + content::WebContents* web_contents) { + if (!web_contents->GetSiteInstance()) + return nullptr; + return extension_registry_->enabled_extensions().GetByID( + GetExtensionIdForSiteInstance(web_contents->GetSiteInstance())); +} + int ProcessManager::GetLazyKeepaliveCount(const Extension* extension) { if (!BackgroundInfo::HasLazyBackgroundPage(extension)) return 0; @@ -480,41 +433,16 @@ int ProcessManager::GetLazyKeepaliveCount(const Extension* extension) { } void ProcessManager::IncrementLazyKeepaliveCount(const Extension* extension) { - if (!BackgroundInfo::HasLazyBackgroundPage(extension)) - return; - - int& count = background_page_data_[extension->id()].lazy_keepalive_count; - if (++count == 1) - OnLazyBackgroundPageActive(extension->id()); + if (BackgroundInfo::HasLazyBackgroundPage(extension)) { + int& count = background_page_data_[extension->id()].lazy_keepalive_count; + if (++count == 1) + OnLazyBackgroundPageActive(extension->id()); + } } void ProcessManager::DecrementLazyKeepaliveCount(const Extension* extension) { - if (!BackgroundInfo::HasLazyBackgroundPage(extension)) - return; - DecrementLazyKeepaliveCount(extension->id()); -} - -void ProcessManager::DecrementLazyKeepaliveCount( - const std::string& extension_id) { - int& count = background_page_data_[extension_id].lazy_keepalive_count; - DCHECK(count > 0 || - !extension_registry_->enabled_extensions().Contains(extension_id)); - - // If we reach a zero keepalive count when the lazy background page is about - // to be closed, incrementing close_sequence_id will cancel the close - // sequence and cause the background page to linger. So check is_closing - // before initiating another close sequence. - if (--count == 0 && !background_page_data_[extension_id].is_closing) { - background_page_data_[extension_id].close_sequence_id = - ++last_background_close_sequence_id_; - base::MessageLoop::current()->PostDelayedTask( - FROM_HERE, - base::Bind(&ProcessManager::OnLazyBackgroundPageIdle, - weak_ptr_factory_.GetWeakPtr(), - extension_id, - last_background_close_sequence_id_), - base::TimeDelta::FromMilliseconds(g_event_page_idle_time_msec)); - } + if (BackgroundInfo::HasLazyBackgroundPage(extension)) + DecrementLazyKeepaliveCount(extension->id()); } // This implementation layers on top of the keepalive count. An impulse sets @@ -563,73 +491,12 @@ void ProcessManager::OnKeepaliveFromPlugin(int render_process_id, ProcessManager::Get(browser_context)->KeepaliveImpulse(extension); } -// DecrementLazyKeepaliveCount is called when no calls to KeepaliveImpulse -// have been made for at least g_event_page_idle_time_msec. In the best case an -// impulse was made just before being cleared, and the decrement will occur -// g_event_page_idle_time_msec later, causing a 2 * g_event_page_idle_time_msec -// total time for extension to be shut down based on impulses. Worst case is -// an impulse just after a clear, adding one check cycle and resulting in 3x -// total time. -void ProcessManager::OnKeepaliveImpulseCheck() { - for (BackgroundPageDataMap::iterator i = background_page_data_.begin(); - i != background_page_data_.end(); - ++i) { - if (i->second.previous_keepalive_impulse && !i->second.keepalive_impulse) { - DecrementLazyKeepaliveCount(i->first); - if (!keepalive_impulse_decrement_callback_for_testing_.is_null()) { - ImpulseCallbackForTesting callback_may_clear_callbacks_reentrantly = - keepalive_impulse_decrement_callback_for_testing_; - callback_may_clear_callbacks_reentrantly.Run(i->first); - } - } - - i->second.previous_keepalive_impulse = i->second.keepalive_impulse; - i->second.keepalive_impulse = false; - } - - // OnKeepaliveImpulseCheck() is always called in constructor, but in unit - // tests there will be no message loop. In that event don't schedule tasks. - if (base::MessageLoop::current()) { - base::MessageLoop::current()->PostDelayedTask( - FROM_HERE, - base::Bind(&ProcessManager::OnKeepaliveImpulseCheck, - weak_ptr_factory_.GetWeakPtr()), - base::TimeDelta::FromMilliseconds(g_event_page_idle_time_msec)); - } -} - -void ProcessManager::OnLazyBackgroundPageIdle(const std::string& extension_id, - uint64 sequence_id) { - ExtensionHost* host = GetBackgroundHostForExtension(extension_id); - if (host && !background_page_data_[extension_id].is_closing && - sequence_id == background_page_data_[extension_id].close_sequence_id) { - // Tell the renderer we are about to close. This is a simple ping that the - // renderer will respond to. The purpose is to control sequencing: if the - // extension remains idle until the renderer responds with an ACK, then we - // know that the extension process is ready to shut down. If our - // close_sequence_id has already changed, then we would ignore the - // ShouldSuspendAck, so we don't send the ping. - host->render_view_host()->Send(new ExtensionMsg_ShouldSuspend( - extension_id, sequence_id)); - } -} - -void ProcessManager::OnLazyBackgroundPageActive( - const std::string& extension_id) { - if (!background_page_data_[extension_id].is_closing) { - // Cancel the current close sequence by changing the close_sequence_id, - // which causes us to ignore the next ShouldSuspendAck. - background_page_data_[extension_id].close_sequence_id = - ++last_background_close_sequence_id_; - } -} - void ProcessManager::OnShouldSuspendAck(const std::string& extension_id, uint64 sequence_id) { ExtensionHost* host = GetBackgroundHostForExtension(extension_id); if (host && sequence_id == background_page_data_[extension_id].close_sequence_id) { - host->render_view_host()->Send(new ExtensionMsg_Suspend(extension_id)); + host->render_process_host()->Send(new ExtensionMsg_Suspend(extension_id)); } } @@ -645,40 +512,11 @@ void ProcessManager::OnSuspendAck(const std::string& extension_id) { base::TimeDelta::FromMilliseconds(g_event_page_suspending_time_msec)); } -void ProcessManager::CloseLazyBackgroundPageNow(const std::string& extension_id, - uint64 sequence_id) { - ExtensionHost* host = GetBackgroundHostForExtension(extension_id); - if (host && - sequence_id == background_page_data_[extension_id].close_sequence_id) { - // Close remaining views. - std::vector<RenderViewHost*> views_to_close; - for (const auto& view : all_extension_views_) { - if (view.second.CanKeepalive() && - GetExtensionID(view.first) == extension_id) { - DCHECK(!view.second.has_keepalive); - views_to_close.push_back(view.first); - } - } - for (auto view : views_to_close) { - view->ClosePage(); - // RenderViewHost::ClosePage() may result in calling - // UnregisterRenderViewHost() asynchronously and may cause race conditions - // when the background page is reloaded. - // To avoid this, unregister the view now. - UnregisterRenderViewHost(view); - } - - ExtensionHost* host = GetBackgroundHostForExtension(extension_id); - if (host) - CloseBackgroundHost(host); - } -} - void ProcessManager::OnNetworkRequestStarted( content::RenderFrameHost* render_frame_host, uint64 request_id) { ExtensionHost* host = GetBackgroundHostForExtension( - GetExtensionIDFromFrame(render_frame_host)); + GetExtensionID(render_frame_host)); if (host && IsFrameInExtensionHost(host, render_frame_host)) { IncrementLazyKeepaliveCount(host->extension()); host->OnNetworkRequestStarted(request_id); @@ -689,7 +527,7 @@ void ProcessManager::OnNetworkRequestDone( content::RenderFrameHost* render_frame_host, uint64 request_id) { ExtensionHost* host = GetBackgroundHostForExtension( - GetExtensionIDFromFrame(render_frame_host)); + GetExtensionID(render_frame_host)); if (host && IsFrameInExtensionHost(host, render_frame_host)) { host->OnNetworkRequestDone(request_id); DecrementLazyKeepaliveCount(host->extension()); @@ -701,7 +539,7 @@ void ProcessManager::CancelSuspend(const Extension* extension) { ExtensionHost* host = GetBackgroundHostForExtension(extension->id()); if (host && is_closing) { is_closing = false; - host->render_view_host()->Send( + host->render_process_host()->Send( new ExtensionMsg_CancelSuspend(extension->id())); // This increment / decrement is to simulate an instantaneous event. This // has the effect of invalidating close_sequence_id, preventing any in @@ -716,10 +554,6 @@ void ProcessManager::CloseBackgroundHosts() { STLDeleteElements(&background_hosts_); } -content::BrowserContext* ProcessManager::GetBrowserContext() const { - return site_instance_->GetBrowserContext(); -} - void ProcessManager::SetKeepaliveImpulseCallbackForTesting( const ImpulseCallbackForTesting& callback) { keepalive_impulse_callback_for_testing_ = callback; @@ -742,6 +576,9 @@ void ProcessManager::SetEventPageSuspendingTimeForTesting( g_event_page_suspending_time_msec = suspending_time_msec; } +//////////////////////////////////////////////////////////////////////////////// +// Private + void ProcessManager::Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) { @@ -754,7 +591,6 @@ void ProcessManager::Observe(int type, MaybeCreateStartupBackgroundHosts(); break; } - case extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED: { ExtensionHost* host = content::Details<ExtensionHost>(details).ptr(); if (background_hosts_.erase(host)) { @@ -764,7 +600,6 @@ void ProcessManager::Observe(int type, } break; } - case extensions::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE: { ExtensionHost* host = content::Details<ExtensionHost>(details).ptr(); if (host->extension_host_type() == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { @@ -772,49 +607,6 @@ void ProcessManager::Observe(int type, } break; } - - case content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED: { - // We get this notification both for new WebContents and when one - // has its RenderViewHost replaced (e.g. when a user does a cross-site - // navigation away from an extension URL). For the replaced case, we must - // unregister the old RVH so it doesn't count as an active view that would - // keep the event page alive. - WebContents* contents = content::Source<WebContents>(source).ptr(); - if (contents->GetBrowserContext() != GetBrowserContext()) - break; - - typedef std::pair<RenderViewHost*, RenderViewHost*> RVHPair; - RVHPair* switched_details = content::Details<RVHPair>(details).ptr(); - if (switched_details->first) - UnregisterRenderViewHost(switched_details->first); - - // The above will unregister a RVH when it gets swapped out with a new - // one. However we need to watch the WebContents to know when a RVH is - // deleted because the WebContents has gone away. - if (RegisterRenderViewHost(switched_details->second)) { - RenderViewHostDestructionObserver::CreateForWebContents(contents); - } - break; - } - - case content::NOTIFICATION_WEB_CONTENTS_CONNECTED: { - WebContents* contents = content::Source<WebContents>(source).ptr(); - if (contents->GetBrowserContext() != GetBrowserContext()) - break; - const Extension* extension = GetExtensionForRenderViewHost( - contents->GetRenderViewHost()); - if (!extension) - return; - - // RegisterRenderViewHost is called too early (before the process is - // available), so we need to wait until now to notify. - content::NotificationService::current()->Notify( - extensions::NOTIFICATION_EXTENSION_VIEW_REGISTERED, - content::Source<BrowserContext>(GetBrowserContext()), - content::Details<RenderViewHost>(contents->GetRenderViewHost())); - break; - } - default: NOTREACHED(); } @@ -833,84 +625,24 @@ void ProcessManager::OnExtensionUnloaded( const Extension* extension, UnloadedExtensionInfo::Reason reason) { ExtensionHost* host = GetBackgroundHostForExtension(extension->id()); - if (host != NULL) + if (host != nullptr) CloseBackgroundHost(host); UnregisterExtension(extension->id()); } -void ProcessManager::OnDevToolsStateChanged( - content::DevToolsAgentHost* agent_host, - bool attached) { - WebContents* web_contents = agent_host->GetWebContents(); - // Ignore unrelated notifications. - if (!web_contents || web_contents->GetBrowserContext() != GetBrowserContext()) - return; - if (GetViewType(web_contents) != VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) - return; - const Extension* extension = - GetExtensionForRenderViewHost(web_contents->GetRenderViewHost()); - if (!extension) - return; - if (attached) { - // Keep the lazy background page alive while it's being inspected. - CancelSuspend(extension); - IncrementLazyKeepaliveCount(extension); - } else { - DecrementLazyKeepaliveCount(extension); - } -} - -void ProcessManager::MaybeCreateStartupBackgroundHosts() { - if (startup_background_hosts_created_) - return; - - // The embedder might disallow background pages entirely. - ProcessManagerDelegate* delegate = - ExtensionsBrowserClient::Get()->GetProcessManagerDelegate(); - if (delegate && !delegate->IsBackgroundPageAllowed(GetBrowserContext())) - return; - - // The embedder might want to defer background page loading. For example, - // Chrome defers background page loading when it is launched to show the app - // list, then triggers a load later when a browser window opens. - if (delegate && - delegate->DeferCreatingStartupBackgroundHosts(GetBrowserContext())) - return; - - CreateStartupBackgroundHosts(); - startup_background_hosts_created_ = true; - - // Background pages should only be loaded once. To prevent any further loads - // occurring, we remove the notification listeners. - BrowserContext* original_context = - ExtensionsBrowserClient::Get()->GetOriginalContext(GetBrowserContext()); - if (registrar_.IsRegistered( - this, - extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED, - content::Source<BrowserContext>(original_context))) { - registrar_.Remove(this, - extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED, - content::Source<BrowserContext>(original_context)); - } -} - void ProcessManager::CreateStartupBackgroundHosts() { DCHECK(!startup_background_hosts_created_); - const ExtensionSet& enabled_extensions = - extension_registry_->enabled_extensions(); - for (ExtensionSet::const_iterator extension = enabled_extensions.begin(); - extension != enabled_extensions.end(); - ++extension) { - CreateBackgroundHostForExtensionLoad(this, extension->get()); - + for (const scoped_refptr<const Extension>& extension : + extension_registry_->enabled_extensions()) { + CreateBackgroundHostForExtensionLoad(this, extension.get()); FOR_EACH_OBSERVER(ProcessManagerObserver, observer_list_, - OnBackgroundHostStartup(extension->get())); + OnBackgroundHostStartup(extension.get())); } } void ProcessManager::OnBackgroundHostCreated(ExtensionHost* host) { - DCHECK_EQ(GetBrowserContext(), host->browser_context()); + DCHECK_EQ(browser_context_, host->browser_context()); background_hosts_.insert(host); if (BackgroundInfo::HasLazyBackgroundPage(host->extension())) { @@ -928,8 +660,7 @@ void ProcessManager::OnBackgroundHostCreated(ExtensionHost* host) { void ProcessManager::CloseBackgroundHost(ExtensionHost* host) { ExtensionId extension_id = host->extension_id(); - CHECK(host->extension_host_type() == - VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); + CHECK(host->extension_host_type() == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE); delete host; // |host| should deregister itself from our structures. CHECK(background_hosts_.find(host) == background_hosts_.end()); @@ -939,18 +670,192 @@ void ProcessManager::CloseBackgroundHost(ExtensionHost* host) { OnBackgroundHostClose(extension_id)); } +void ProcessManager::AcquireLazyKeepaliveCountForFrame( + content::RenderFrameHost* render_frame_host) { + ExtensionRenderFrames::iterator it = + all_extension_frames_.find(render_frame_host); + if (it == all_extension_frames_.end()) + return; + + ExtensionRenderFrameData& data = it->second; + if (data.CanKeepalive() && !data.has_keepalive) { + const Extension* extension = + GetExtensionForRenderFrameHost(render_frame_host); + if (extension) { + IncrementLazyKeepaliveCount(extension); + data.has_keepalive = true; + } + } +} + +void ProcessManager::ReleaseLazyKeepaliveCountForFrame( + content::RenderFrameHost* render_frame_host) { + ExtensionRenderFrames::iterator iter = + all_extension_frames_.find(render_frame_host); + if (iter == all_extension_frames_.end()) + return; + + ExtensionRenderFrameData& data = iter->second; + if (data.CanKeepalive() && data.has_keepalive) { + const Extension* extension = + GetExtensionForRenderFrameHost(render_frame_host); + if (extension) { + DecrementLazyKeepaliveCount(extension); + data.has_keepalive = false; + } + } +} + +void ProcessManager::DecrementLazyKeepaliveCount( + const std::string& extension_id) { + int& count = background_page_data_[extension_id].lazy_keepalive_count; + DCHECK(count > 0 || + !extension_registry_->enabled_extensions().Contains(extension_id)); + + // If we reach a zero keepalive count when the lazy background page is about + // to be closed, incrementing close_sequence_id will cancel the close + // sequence and cause the background page to linger. So check is_closing + // before initiating another close sequence. + if (--count == 0 && !background_page_data_[extension_id].is_closing) { + background_page_data_[extension_id].close_sequence_id = + ++last_background_close_sequence_id_; + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::Bind(&ProcessManager::OnLazyBackgroundPageIdle, + weak_ptr_factory_.GetWeakPtr(), + extension_id, + last_background_close_sequence_id_), + base::TimeDelta::FromMilliseconds(g_event_page_idle_time_msec)); + } +} + +// DecrementLazyKeepaliveCount is called when no calls to KeepaliveImpulse +// have been made for at least g_event_page_idle_time_msec. In the best case an +// impulse was made just before being cleared, and the decrement will occur +// g_event_page_idle_time_msec later, causing a 2 * g_event_page_idle_time_msec +// total time for extension to be shut down based on impulses. Worst case is +// an impulse just after a clear, adding one check cycle and resulting in 3x +// total time. +void ProcessManager::OnKeepaliveImpulseCheck() { + for (BackgroundPageDataMap::iterator i = background_page_data_.begin(); + i != background_page_data_.end(); + ++i) { + if (i->second.previous_keepalive_impulse && !i->second.keepalive_impulse) { + DecrementLazyKeepaliveCount(i->first); + if (!keepalive_impulse_decrement_callback_for_testing_.is_null()) { + ImpulseCallbackForTesting callback_may_clear_callbacks_reentrantly = + keepalive_impulse_decrement_callback_for_testing_; + callback_may_clear_callbacks_reentrantly.Run(i->first); + } + } + + i->second.previous_keepalive_impulse = i->second.keepalive_impulse; + i->second.keepalive_impulse = false; + } + + // OnKeepaliveImpulseCheck() is always called in constructor, but in unit + // tests there will be no message loop. In that event don't schedule tasks. + if (base::MessageLoop::current()) { + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::Bind(&ProcessManager::OnKeepaliveImpulseCheck, + weak_ptr_factory_.GetWeakPtr()), + base::TimeDelta::FromMilliseconds(g_event_page_idle_time_msec)); + } +} + +void ProcessManager::OnLazyBackgroundPageIdle(const std::string& extension_id, + uint64 sequence_id) { + ExtensionHost* host = GetBackgroundHostForExtension(extension_id); + if (host && !background_page_data_[extension_id].is_closing && + sequence_id == background_page_data_[extension_id].close_sequence_id) { + // Tell the renderer we are about to close. This is a simple ping that the + // renderer will respond to. The purpose is to control sequencing: if the + // extension remains idle until the renderer responds with an ACK, then we + // know that the extension process is ready to shut down. If our + // close_sequence_id has already changed, then we would ignore the + // ShouldSuspendAck, so we don't send the ping. + host->render_process_host()->Send(new ExtensionMsg_ShouldSuspend( + extension_id, sequence_id)); + } +} + +void ProcessManager::OnLazyBackgroundPageActive( + const std::string& extension_id) { + if (!background_page_data_[extension_id].is_closing) { + // Cancel the current close sequence by changing the close_sequence_id, + // which causes us to ignore the next ShouldSuspendAck. + background_page_data_[extension_id].close_sequence_id = + ++last_background_close_sequence_id_; + } +} + +void ProcessManager::CloseLazyBackgroundPageNow(const std::string& extension_id, + uint64 sequence_id) { + ExtensionHost* host = GetBackgroundHostForExtension(extension_id); + if (host && + sequence_id == background_page_data_[extension_id].close_sequence_id) { + // Close remaining views. + std::vector<content::RenderFrameHost*> frames_to_close; + for (const auto& key_value : all_extension_frames_) { + if (key_value.second.CanKeepalive() && + GetExtensionID(key_value.first) == extension_id) { + DCHECK(!key_value.second.has_keepalive); + frames_to_close.push_back(key_value.first); + } + } + for (content::RenderFrameHost* frame : frames_to_close) { + frame->GetRenderViewHost()->ClosePage(); + // RenderViewHost::ClosePage() may result in calling + // UnregisterRenderViewHost() asynchronously and may cause race conditions + // when the background page is reloaded. + // To avoid this, unregister the view now. + UnregisterRenderFrameHost(frame); + } + + ExtensionHost* host = GetBackgroundHostForExtension(extension_id); + if (host) + CloseBackgroundHost(host); + } +} + +void ProcessManager::OnDevToolsStateChanged( + content::DevToolsAgentHost* agent_host, + bool attached) { + content::WebContents* web_contents = agent_host->GetWebContents(); + // Ignore unrelated notifications. + if (!web_contents || web_contents->GetBrowserContext() != browser_context_) + return; + if (GetViewType(web_contents) != VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) + return; + const Extension* extension = + extension_registry_->enabled_extensions().GetByID( + GetExtensionIdForSiteInstance(web_contents->GetSiteInstance())); + if (!extension) + return; + if (attached) { + // Keep the lazy background page alive while it's being inspected. + CancelSuspend(extension); + IncrementLazyKeepaliveCount(extension); + } else { + DecrementLazyKeepaliveCount(extension); + } +} + void ProcessManager::UnregisterExtension(const std::string& extension_id) { // The lazy_keepalive_count may be greater than zero at this point because - // RenderViewHosts are still alive. During extension reloading, they will + // RenderFrameHosts are still alive. During extension reloading, they will // decrement the lazy_keepalive_count to negative for the new extension // instance when they are destroyed. Since we are erasing the background page - // data for the unloaded extension, unregister the RenderViewHosts too. - BrowserContext* context = GetBrowserContext(); - for (ExtensionRenderViews::iterator it = all_extension_views_.begin(); - it != all_extension_views_.end(); ) { - if (GetExtensionID(it->first) == extension_id) { - OnRenderViewHostUnregistered(context, it->first); - all_extension_views_.erase(it++); + // data for the unloaded extension, unregister the RenderFrameHosts too. + for (ExtensionRenderFrames::iterator it = all_extension_frames_.begin(); + it != all_extension_frames_.end(); ) { + content::RenderFrameHost* host = it->first; + if (GetExtensionID(host) == extension_id) { + all_extension_frames_.erase(it++); + FOR_EACH_OBSERVER(ProcessManagerObserver, + observer_list_, + OnExtensionFrameUnregistered(extension_id, host)); } else { ++it; } @@ -965,14 +870,13 @@ void ProcessManager::ClearBackgroundPageData(const std::string& extension_id) { // Re-register all RenderViews for this extension. We do this to restore // the lazy_keepalive_count (if any) to properly reflect the number of open // views. - for (ExtensionRenderViews::const_iterator it = all_extension_views_.begin(); - it != all_extension_views_.end(); ++it) { - RenderViewHost* view = it->first; - const ExtensionRenderViewData& data = it->second; + for (const auto& key_value : all_extension_frames_) { // Do not increment the count when |has_keepalive| is false // (i.e. ReleaseLazyKeepaliveCountForView() was called). - if (GetExtensionID(view) == extension_id && data.has_keepalive) { - const Extension* extension = GetExtensionForRenderViewHost(view); + if (GetExtensionID(key_value.first) == extension_id && + key_value.second.has_keepalive) { + const Extension* extension = + GetExtensionForRenderFrameHost(key_value.first); if (extension) IncrementLazyKeepaliveCount(extension); } @@ -989,21 +893,13 @@ IncognitoProcessManager::IncognitoProcessManager( ExtensionRegistry* extension_registry) : ProcessManager(incognito_context, original_context, extension_registry) { DCHECK(incognito_context->IsOffTheRecord()); - - // The original profile will have its own ProcessManager to - // load the background pages of the spanning extensions. This process - // manager need only worry about the split mode extensions, which is handled - // in the NOTIFICATION_BROWSER_WINDOW_READY notification handler. - registrar_.Remove(this, - extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED, - content::Source<BrowserContext>(original_context)); } bool IncognitoProcessManager::CreateBackgroundHost(const Extension* extension, const GURL& url) { if (IncognitoInfo::IsSplitMode(extension)) { if (ExtensionsBrowserClient::Get()->IsExtensionIncognitoEnabled( - extension->id(), GetBrowserContext())) + extension->id(), browser_context())) return ProcessManager::CreateBackgroundHost(extension, url); } else { // Do nothing. If an extension is spanning, then its original-profile @@ -1012,13 +908,13 @@ bool IncognitoProcessManager::CreateBackgroundHost(const Extension* extension, return false; } -scoped_refptr<SiteInstance> IncognitoProcessManager::GetSiteInstanceForURL( - const GURL& url) { +scoped_refptr<content::SiteInstance> +IncognitoProcessManager::GetSiteInstanceForURL(const GURL& url) { const Extension* extension = extension_registry_->enabled_extensions().GetExtensionOrAppByURL(url); if (extension && !IncognitoInfo::IsSplitMode(extension)) { BrowserContext* original_context = - ExtensionsBrowserClient::Get()->GetOriginalContext(GetBrowserContext()); + ExtensionsBrowserClient::Get()->GetOriginalContext(browser_context()); return ProcessManager::Get(original_context)->GetSiteInstanceForURL(url); } diff --git a/extensions/browser/process_manager.h b/extensions/browser/process_manager.h index d897d29..de23f1e 100644 --- a/extensions/browser/process_manager.h +++ b/extensions/browser/process_manager.h @@ -14,11 +14,11 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" -#include "base/time/time.h" #include "components/keyed_service/core/keyed_service.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "extensions/browser/extension_registry_observer.h" +#include "extensions/common/extension.h" #include "extensions/common/view_type.h" class GURL; @@ -26,9 +26,9 @@ class GURL; namespace content { class BrowserContext; class DevToolsAgentHost; -class RenderViewHost; class RenderFrameHost; class SiteInstance; +class WebContents; }; namespace extensions { @@ -36,7 +36,6 @@ namespace extensions { class Extension; class ExtensionHost; class ExtensionRegistry; -class ProcessManagerDelegate; class ProcessManagerObserver; // Manages dynamic state of running Chromium extensions. There is one instance @@ -46,20 +45,30 @@ class ProcessManager : public KeyedService, public content::NotificationObserver, public ExtensionRegistryObserver { public: - typedef std::set<extensions::ExtensionHost*> ExtensionHostSet; - typedef ExtensionHostSet::const_iterator const_iterator; + using ExtensionHostSet = std::set<extensions::ExtensionHost*>; static ProcessManager* Get(content::BrowserContext* context); ~ProcessManager() override; - const ExtensionHostSet& background_hosts() const { - return background_hosts_; - } + void RegisterRenderFrameHost(content::WebContents* web_contents, + content::RenderFrameHost* render_frame_host, + const Extension* extension); + void UnregisterRenderFrameHost(content::RenderFrameHost* render_frame_host); - typedef std::set<content::RenderViewHost*> ViewSet; - const ViewSet GetAllViews() const; + // 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 scoped_refptr<content::SiteInstance> GetSiteInstanceForURL( + const GURL& url); + + using FrameSet = std::set<content::RenderFrameHost*>; + const FrameSet GetAllFrames() const; + + // Returns all RenderFrameHosts that are registered for the specified + // extension. + ProcessManager::FrameSet GetRenderFrameHostsForExtension( + const std::string& extension_id); - // The typical observer interface. void AddObserver(ProcessManagerObserver* observer); void RemoveObserver(ProcessManagerObserver* observer); @@ -70,43 +79,25 @@ class ProcessManager : public KeyedService, virtual bool CreateBackgroundHost(const Extension* extension, const GURL& url); - // Gets the ExtensionHost for the background page for an extension, or NULL if + // Creates background hosts if the embedder is ready and they are not already + // loaded. + void MaybeCreateStartupBackgroundHosts(); + + // 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(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 scoped_refptr<content::SiteInstance> GetSiteInstanceForURL( - const GURL& url); - - // If the view isn't keeping the lazy background page alive, increments the - // keepalive count to do so. - void AcquireLazyKeepaliveCountForView( - content::RenderViewHost* render_view_host); - - // If the view is keeping the lazy background page alive, decrements the - // keepalive count to stop doing it. - void ReleaseLazyKeepaliveCountForView( - content::RenderViewHost* render_view_host); - - // Unregisters a RenderViewHost as hosting any extension. - void UnregisterRenderViewHost(content::RenderViewHost* render_view_host); - - // Returns all RenderViewHosts that are registered for the specified - // extension. - std::set<content::RenderViewHost*> GetRenderViewHostsForExtension( - const std::string& extension_id); - - // Returns the extension associated with the specified RenderViewHost, or - // NULL. - const Extension* GetExtensionForRenderViewHost( - content::RenderViewHost* render_view_host); - // Returns true if the (lazy) background host for the given extension has // already been sent the unload event and is shutting down. bool IsBackgroundHostClosing(const std::string& extension_id); + // Returns the extension associated with the specified RenderFrameHost/ + // WebContents, or null. + const Extension* GetExtensionForRenderFrameHost( + content::RenderFrameHost* render_frame_host); + const Extension* GetExtensionForWebContents( + content::WebContents* web_contents); + // Getter and setter for the lazy background page's keepalive count. This is // the count of how many outstanding "things" are keeping the page alive. // When this reaches 0, we will begin the process of shutting down the page. @@ -143,20 +134,12 @@ class ProcessManager : public KeyedService, // onSuspendCanceled() event to it. void CancelSuspend(const Extension* extension); - // Creates background hosts if the embedder is ready and they are not already - // loaded. - void MaybeCreateStartupBackgroundHosts(); - // Called on shutdown to close our extension hosts. void CloseBackgroundHosts(); - // Gets the BrowserContext associated with site_instance_ and all other - // related SiteInstances. - content::BrowserContext* GetBrowserContext() const; - // Sets callbacks for testing keepalive impulse behavior. - typedef base::Callback<void(const std::string& extension_id)> - ImpulseCallbackForTesting; + using ImpulseCallbackForTesting = + base::Callback<void(const std::string& extension_id)>; void SetKeepaliveImpulseCallbackForTesting( const ImpulseCallbackForTesting& callback); void SetKeepaliveImpulseDecrementCallbackForTesting( @@ -184,6 +167,12 @@ class ProcessManager : public KeyedService, content::BrowserContext* original_context, ExtensionRegistry* registry); + content::BrowserContext* browser_context() const { return browser_context_; } + + const ExtensionHostSet& background_hosts() const { + return background_hosts_; + } + bool startup_background_hosts_created_for_test() const { return startup_background_hosts_created_; } @@ -191,13 +180,20 @@ class ProcessManager : public KeyedService, protected: static ProcessManager* Create(content::BrowserContext* context); - // |context| is incognito pass the master context as |original_context|. + // |context| is incognito pass the master context as |original_context|. // Otherwise pass the same context for both. Pass the ExtensionRegistry for // |context| as |registry|, or override it for testing. ProcessManager(content::BrowserContext* context, content::BrowserContext* original_context, ExtensionRegistry* registry); + // Not owned. Also used by IncognitoProcessManager. + ExtensionRegistry* extension_registry_; + + private: + friend class ProcessManagerFactory; + friend class ProcessManagerTest; + // content::NotificationObserver: void Observe(int type, const content::NotificationSource& source, @@ -210,30 +206,12 @@ class ProcessManager : public KeyedService, const Extension* extension, UnloadedExtensionInfo::Reason reason) override; - content::NotificationRegistrar registrar_; - - // The set of ExtensionHosts running viewless background extensions. - ExtensionHostSet background_hosts_; - - // A SiteInstance related to the SiteInstance for all extensions in - // this profile. We create it in such a way that a new - // browsing instance is created. This controls process grouping. - scoped_refptr<content::SiteInstance> site_instance_; - - // Not owned. Also used by IncognitoProcessManager. - ExtensionRegistry* extension_registry_; - - private: - friend class ProcessManagerFactory; - friend class ProcessManagerTest; - // Extra information we keep for each extension's background page. struct BackgroundPageData; - struct ExtensionRenderViewData; - typedef std::string ExtensionId; - typedef std::map<ExtensionId, BackgroundPageData> BackgroundPageDataMap; - typedef std::map<content::RenderViewHost*, ExtensionRenderViewData> - ExtensionRenderViews; + struct ExtensionRenderFrameData; + using BackgroundPageDataMap = std::map<ExtensionId, BackgroundPageData>; + using ExtensionRenderFrames = + std::map<content::RenderFrameHost*, ExtensionRenderFrameData>; // Load all background pages once the profile data is ready and the pages // should be loaded. @@ -245,6 +223,16 @@ class ProcessManager : public KeyedService, // Close the given |host| iff it's a background page. void CloseBackgroundHost(ExtensionHost* host); + // If the frame isn't keeping the lazy background page alive, increments the + // keepalive count to do so. + void AcquireLazyKeepaliveCountForFrame( + content::RenderFrameHost* render_frame_host); + + // If the frame is keeping the lazy background page alive, decrements the + // keepalive count to stop doing it. + void ReleaseLazyKeepaliveCountForFrame( + content::RenderFrameHost* render_frame_host); + // Internal implementation of DecrementLazyKeepaliveCount with an // |extension_id| known to have a lazy background page. void DecrementLazyKeepaliveCount(const std::string& extension_id); @@ -260,25 +248,32 @@ class ProcessManager : public KeyedService, void CloseLazyBackgroundPageNow(const std::string& extension_id, uint64 sequence_id); - // Potentially registers a RenderViewHost, if it is associated with an - // extension. Does nothing if this is not an extension renderer. - // Returns true, if render_view_host was registered (it is associated - // with an extension). - bool RegisterRenderViewHost(content::RenderViewHost* render_view_host); + void OnDevToolsStateChanged(content::DevToolsAgentHost*, bool attached); - // Unregister RenderViewHosts and clear background page data for an extension + // Unregister RenderFrameHosts and clear background page data for an extension // which has been unloaded. void UnregisterExtension(const std::string& extension_id); // Clears background page data for this extension. void ClearBackgroundPageData(const std::string& extension_id); - void OnDevToolsStateChanged(content::DevToolsAgentHost*, bool attached); + content::NotificationRegistrar registrar_; + + // The set of ExtensionHosts running viewless background extensions. + ExtensionHostSet background_hosts_; + + // A SiteInstance related to the SiteInstance for all extensions in + // this profile. We create it in such a way that a new + // browsing instance is created. This controls process grouping. + scoped_refptr<content::SiteInstance> site_instance_; + + // The browser context associated with the |site_instance_|. + content::BrowserContext* browser_context_; - // Contains all active extension-related RenderViewHost instances for all + // Contains all active extension-related RenderFrameHost instances for all // extensions. We also keep a cache of the host's view type, because that // information is not accessible at registration/deregistration time. - ExtensionRenderViews all_extension_views_; + ExtensionRenderFrames all_extension_frames_; BackgroundPageDataMap background_page_data_; diff --git a/extensions/browser/process_manager_observer.h b/extensions/browser/process_manager_observer.h index 4b0dfd6..37054ac 100644 --- a/extensions/browser/process_manager_observer.h +++ b/extensions/browser/process_manager_observer.h @@ -7,6 +7,10 @@ #include <string> +namespace content { +class RenderFrameHost; +} + namespace extensions { class Extension; @@ -21,6 +25,14 @@ class ProcessManagerObserver { // Called immediately after the extension background host is destroyed. virtual void OnBackgroundHostClose(const std::string& extension_id) {} + + virtual void OnExtensionFrameRegistered( + const std::string& extension_id, + content::RenderFrameHost* render_frame_host) {} + + virtual void OnExtensionFrameUnregistered( + const std::string& extension_id, + content::RenderFrameHost* render_frame_host) {} }; } // namespace extensions diff --git a/extensions/browser/process_manager_unittest.cc b/extensions/browser/process_manager_unittest.cc index 47ff500..34b74a9 100644 --- a/extensions/browser/process_manager_unittest.cc +++ b/extensions/browser/process_manager_unittest.cc @@ -103,7 +103,7 @@ TEST_F(ProcessManagerTest, ExtensionNotificationRegistration) { scoped_ptr<ProcessManager> manager1(ProcessManager::CreateForTesting( original_context(), extension_registry())); - EXPECT_EQ(original_context(), manager1->GetBrowserContext()); + EXPECT_EQ(original_context(), manager1->browser_context()); EXPECT_EQ(0u, manager1->background_hosts().size()); // It observes other notifications from this context. @@ -120,7 +120,7 @@ TEST_F(ProcessManagerTest, ExtensionNotificationRegistration) { original_context(), extension_registry())); - EXPECT_EQ(incognito_context(), manager2->GetBrowserContext()); + EXPECT_EQ(incognito_context(), manager2->browser_context()); EXPECT_EQ(0u, manager2->background_hosts().size()); // Some notifications are observed for the incognito context. diff --git a/extensions/components/javascript_dialog_extensions_client/javascript_dialog_extension_client_impl.cc b/extensions/components/javascript_dialog_extensions_client/javascript_dialog_extension_client_impl.cc index f50b4e9..6874a3a 100644 --- a/extensions/components/javascript_dialog_extensions_client/javascript_dialog_extension_client_impl.cc +++ b/extensions/components/javascript_dialog_extensions_client/javascript_dialog_extension_client_impl.cc @@ -26,8 +26,8 @@ extensions::ProcessManager* GetProcessManager( // associated extension (or extensions are not supported). const Extension* GetExtensionForWebContents( content::WebContents* web_contents) { - extensions::ProcessManager* pm = GetProcessManager(web_contents); - return pm->GetExtensionForRenderViewHost(web_contents->GetRenderViewHost()); + return GetProcessManager(web_contents)->GetExtensionForWebContents( + web_contents); } class JavaScriptDialogExtensionsClientImpl |