#include "extensions/browser/extensions_browser_client.h"
#include "extensions/browser/notification_types.h"
#include "extensions/browser/process_manager_delegate.h"
+#include "extensions/browser/process_manager_factory.h"
#include "extensions/browser/process_manager_observer.h"
#include "extensions/browser/view_type_utils.h"
#include "extensions/common/constants.h"
public:
IncognitoProcessManager(BrowserContext* incognito_context,
BrowserContext* original_context,
- ProcessManager* original_manager,
ExtensionRegistry* extension_registry);
- virtual ~IncognitoProcessManager() {}
- virtual bool CreateBackgroundHost(const Extension* extension,
- const GURL& url) OVERRIDE;
- virtual SiteInstance* GetSiteInstanceForURL(const GURL& url) OVERRIDE;
+ ~IncognitoProcessManager() override {}
+ bool CreateBackgroundHost(const Extension* extension,
+ const GURL& url) override;
+ SiteInstance* GetSiteInstanceForURL(const GURL& url) override;
private:
- ProcessManager* original_manager_;
-
DISALLOW_COPY_AND_ASSIGN(IncognitoProcessManager);
};
: public content::WebContentsObserver,
public content::WebContentsUserData<RenderViewHostDestructionObserver> {
public:
- virtual ~RenderViewHostDestructionObserver() {}
+ ~RenderViewHostDestructionObserver() override {}
private:
explicit RenderViewHostDestructionObserver(WebContents* web_contents)
: WebContentsObserver(web_contents) {
BrowserContext* context = web_contents->GetBrowserContext();
- process_manager_ = ExtensionSystem::Get(context)->process_manager();
+ process_manager_ = ProcessManager::Get(context);
}
friend class content::WebContentsUserData<RenderViewHostDestructionObserver>;
// content::WebContentsObserver overrides.
- virtual void RenderViewDeleted(RenderViewHost* render_view_host) OVERRIDE {
+ void RenderViewDeleted(RenderViewHost* render_view_host) override {
process_manager_->UnregisterRenderViewHost(render_view_host);
}
close_sequence_id(0) {}
};
+// Data of a RenderViewHost associated with an extension.
+struct ProcessManager::ExtensionRenderViewData {
+ // 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()
+ : view_type(VIEW_TYPE_INVALID), has_keepalive(false) {}
+
+ // Returns whether the view can keep the lazy background page alive or not.
+ bool CanKeepalive() const {
+ switch (view_type) {
+ case VIEW_TYPE_APP_WINDOW:
+ case VIEW_TYPE_BACKGROUND_CONTENTS:
+ case VIEW_TYPE_EXTENSION_DIALOG:
+ case VIEW_TYPE_EXTENSION_INFOBAR:
+ case VIEW_TYPE_EXTENSION_POPUP:
+ case VIEW_TYPE_LAUNCHER_PAGE:
+ case VIEW_TYPE_PANEL:
+ case VIEW_TYPE_TAB_CONTENTS:
+ case VIEW_TYPE_VIRTUAL_KEYBOARD:
+ return true;
+
+ case VIEW_TYPE_INVALID:
+ case VIEW_TYPE_EXTENSION_BACKGROUND_PAGE:
+ return false;
+ }
+ NOTREACHED();
+ return false;
+ }
+};
+
//
// ProcessManager
//
// static
+ProcessManager* ProcessManager::Get(BrowserContext* context) {
+ return ProcessManagerFactory::GetForBrowserContext(context);
+}
+
+// static
ProcessManager* ProcessManager::Create(BrowserContext* context) {
ExtensionRegistry* extension_registry = ExtensionRegistry::Get(context);
ExtensionsBrowserClient* client = ExtensionsBrowserClient::Get();
if (context->IsOffTheRecord()) {
BrowserContext* original_context = client->GetOriginalContext(context);
- ProcessManager* original_manager =
- ExtensionSystem::Get(original_context)->process_manager();
return new IncognitoProcessManager(
- context, original_context, original_manager, extension_registry);
+ context, original_context, extension_registry);
}
return new ProcessManager(context, context, extension_registry);
ProcessManager* ProcessManager::CreateIncognitoForTesting(
BrowserContext* incognito_context,
BrowserContext* original_context,
- ProcessManager* original_manager,
ExtensionRegistry* extension_registry) {
DCHECK(incognito_context->IsOffTheRecord());
DCHECK(!original_context->IsOffTheRecord());
return new IncognitoProcessManager(incognito_context,
original_context,
- original_manager,
extension_registry);
}
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())
+ 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())
+ 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 =
return;
OnRenderViewHostUnregistered(GetBrowserContext(), render_view_host);
- ViewType view_type = view->second;
- all_extension_views_.erase(view);
// Keepalive count, balanced in RegisterRenderViewHost.
- if (view_type != VIEW_TYPE_INVALID &&
- view_type != VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
- const Extension* extension = GetExtensionForRenderViewHost(
- render_view_host);
- if (extension)
- DecrementLazyKeepaliveCount(extension);
- }
+ ReleaseLazyKeepaliveCountForView(render_view_host);
+ all_extension_views_.erase(view);
}
bool ProcessManager::RegisterRenderViewHost(RenderViewHost* render_view_host) {
return false;
WebContents* web_contents = WebContents::FromRenderViewHost(render_view_host);
- all_extension_views_[render_view_host] = GetViewType(web_contents);
+ ExtensionRenderViewData* data = &all_extension_views_[render_view_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
// UnregisterRenderViewHost.
- IncrementLazyKeepaliveCountForView(render_view_host);
+ AcquireLazyKeepaliveCountForView(render_view_host);
return true;
}
}
}
-void ProcessManager::IncrementLazyKeepaliveCountForView(
- RenderViewHost* render_view_host) {
- WebContents* web_contents =
- WebContents::FromRenderViewHost(render_view_host);
- ViewType view_type = GetViewType(web_contents);
- if (view_type != VIEW_TYPE_INVALID &&
- view_type != VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
- const Extension* extension = GetExtensionForRenderViewHost(
- render_view_host);
- if (extension)
- IncrementLazyKeepaliveCount(extension);
- }
-}
-
// This implementation layers on top of the keepalive count. An impulse sets
// a per extension flag. On a regular interval that flag is checked. Changes
// from the flag not being set to set cause an IncrementLazyKeepaliveCount.
if (!extension)
return;
- ProcessManager* pm = ExtensionSystem::Get(browser_context)->process_manager();
- if (!pm)
- return;
-
- pm->KeepaliveImpulse(extension);
+ ProcessManager::Get(browser_context)->KeepaliveImpulse(extension);
}
// DecrementLazyKeepaliveCount is called when no calls to KeepaliveImpulse
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::CloseBackgroundHost(ExtensionHost* host) {
+ ExtensionId extension_id = host->extension_id();
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());
+
+ FOR_EACH_OBSERVER(ProcessManagerObserver,
+ observer_list_,
+ OnBackgroundHostClose(extension_id));
}
void ProcessManager::UnregisterExtension(const std::string& extension_id) {
// views.
for (ExtensionRenderViews::const_iterator it = all_extension_views_.begin();
it != all_extension_views_.end(); ++it) {
- if (GetExtensionID(it->first) == extension_id)
- IncrementLazyKeepaliveCountForView(it->first);
+ RenderViewHost* view = it->first;
+ const ExtensionRenderViewData& data = it->second;
+ // 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 (extension)
+ IncrementLazyKeepaliveCount(extension);
+ }
}
}
IncognitoProcessManager::IncognitoProcessManager(
BrowserContext* incognito_context,
BrowserContext* original_context,
- ProcessManager* original_manager,
ExtensionRegistry* extension_registry)
- : ProcessManager(incognito_context, original_context, extension_registry),
- original_manager_(original_manager) {
+ : ProcessManager(incognito_context, original_context, extension_registry) {
DCHECK(incognito_context->IsOffTheRecord());
// The original profile will have its own ProcessManager to
SiteInstance* IncognitoProcessManager::GetSiteInstanceForURL(const GURL& url) {
const Extension* extension =
extension_registry_->enabled_extensions().GetExtensionOrAppByURL(url);
- if (extension && !IncognitoInfo::IsSplitMode(extension))
- return original_manager_->GetSiteInstanceForURL(url);
+ if (extension && !IncognitoInfo::IsSplitMode(extension)) {
+ BrowserContext* original_context =
+ ExtensionsBrowserClient::Get()->GetOriginalContext(GetBrowserContext());
+ return ProcessManager::Get(original_context)->GetSiteInstanceForURL(url);
+ }
return ProcessManager::GetSiteInstanceForURL(url);
}