Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / extensions / browser / process_manager.cc
index 1b6a45a..5e2e3aa 100644 (file)
@@ -33,6 +33,7 @@
 #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"
@@ -114,16 +115,13 @@ class IncognitoProcessManager : public ProcessManager {
  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);
 };
 
@@ -141,19 +139,19 @@ class RenderViewHostDestructionObserver
     : 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);
   }
 
@@ -194,11 +192,50 @@ struct ProcessManager::BackgroundPageData {
         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();
@@ -213,10 +250,8 @@ ProcessManager* ProcessManager::Create(BrowserContext* context) {
 
   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);
@@ -234,13 +269,11 @@ ProcessManager* ProcessManager::CreateForTesting(
 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);
 }
 
@@ -369,6 +402,40 @@ const Extension* ProcessManager::GetExtensionForRenderViewHost(
       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 =
@@ -377,17 +444,10 @@ void ProcessManager::UnregisterRenderViewHost(
     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) {
@@ -397,12 +457,13 @@ 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;
 }
 
@@ -460,20 +521,6 @@ void ProcessManager::DecrementLazyKeepaliveCount(
   }
 }
 
-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.
@@ -517,11 +564,7 @@ void ProcessManager::OnKeepaliveFromPlugin(int render_process_id,
   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
@@ -611,6 +654,24 @@ void ProcessManager::CloseLazyBackgroundPageNow(const std::string& extension_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);
@@ -873,11 +934,16 @@ 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);
   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) {
@@ -908,8 +974,15 @@ void ProcessManager::ClearBackgroundPageData(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);
+    }
   }
 }
 
@@ -920,10 +993,8 @@ void ProcessManager::ClearBackgroundPageData(const std::string& extension_id) {
 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
@@ -951,8 +1022,11 @@ bool IncognitoProcessManager::CreateBackgroundHost(const Extension* extension,
 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);
 }