1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/process_manager.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/public/browser/browser_context.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/devtools_agent_host.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/render_frame_host.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/site_instance.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents_delegate.h"
268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "content/public/browser/web_contents_observer.h"
278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "content/public/browser/web_contents_user_data.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/renderer_preferences.h"
29c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "content/public/common/url_constants.h"
3023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/browser/extension_host.h"
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_registry.h"
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/extensions_browser_client.h"
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/notification_types.h"
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/process_manager_delegate.h"
364ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch#include "extensions/browser/process_manager_observer.h"
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "extensions/browser/view_type_utils.h"
38c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/constants.h"
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/common/extension_messages.h"
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/manifest_handlers/background_info.h"
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/manifest_handlers/incognito_info.h"
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/common/one_shot_event.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using content::BrowserContext;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderViewHost;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::SiteInstance;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace extensions {
518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)class RenderViewHostDestructionObserver;
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)DEFINE_WEB_CONTENTS_USER_DATA_KEY(
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    extensions::RenderViewHostDestructionObserver);
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace extensions {
578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// The time to delay between an extension becoming idle and
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// sending a ShouldSuspend message.
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Note: Must be sufficiently larger (e.g. 2x) than
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// kKeepaliveThrottleIntervalInSeconds in ppapi/proxy/plugin_globals.
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciunsigned g_event_page_idle_time_msec = 10000;
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// The time to delay between sending a ShouldSuspend message and
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// sending a Suspend message.
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciunsigned g_event_page_suspending_time_msec = 5000;
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetExtensionID(RenderViewHost* render_view_host) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This works for both apps and extensions because the site has been
72c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // normalized to the extension URL for hosted apps.
73c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  content::SiteInstance* site_instance = render_view_host->GetSiteInstance();
74c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!site_instance)
75c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return std::string();
76c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const GURL& site_url = site_instance->GetSiteURL();
78c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
79c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!site_url.SchemeIs(kExtensionScheme) &&
80c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      !site_url.SchemeIs(content::kGuestScheme))
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return std::string();
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
83c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return site_url.host();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string GetExtensionIDFromFrame(
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    content::RenderFrameHost* render_frame_host) {
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // This works for both apps and extensions because the site has been
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // normalized to the extension URL for apps.
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!render_frame_host->GetSiteInstance())
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return std::string();
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return render_frame_host->GetSiteInstance()->GetSiteURL().host();
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool IsFrameInExtensionHost(ExtensionHost* extension_host,
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            content::RenderFrameHost* render_frame_host) {
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return WebContents::FromRenderFrameHost(render_frame_host) ==
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      extension_host->host_contents();
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void OnRenderViewHostUnregistered(BrowserContext* context,
10368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                  RenderViewHost* render_view_host) {
10468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  content::NotificationService::current()->Notify(
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      extensions::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED,
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      content::Source<BrowserContext>(context),
10768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      content::Details<RenderViewHost>(render_view_host));
10868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
10968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Incognito profiles use this process manager. It is mostly a shim that decides
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// whether to fall back on the original profile's ProcessManager based
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on whether a given extension uses "split" or "spanning" incognito behavior.
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class IncognitoProcessManager : public ProcessManager {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  IncognitoProcessManager(BrowserContext* incognito_context,
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                          BrowserContext* original_context,
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          ProcessManager* original_manager,
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          ExtensionRegistry* extension_registry);
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual ~IncognitoProcessManager() {}
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual bool CreateBackgroundHost(const Extension* extension,
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                    const GURL& url) OVERRIDE;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual SiteInstance* GetSiteInstanceForURL(const GURL& url) OVERRIDE;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ProcessManager* original_manager_;
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(IncognitoProcessManager);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void CreateBackgroundHostForExtensionLoad(
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ProcessManager* manager, const Extension* extension) {
132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << "CreateBackgroundHostForExtensionLoad";
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (BackgroundInfo::HasPersistentBackgroundPage(extension))
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    manager->CreateBackgroundHost(extension,
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  BackgroundInfo::GetBackgroundURL(extension));
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)class RenderViewHostDestructionObserver
1418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    : public content::WebContentsObserver,
1428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      public content::WebContentsUserData<RenderViewHostDestructionObserver> {
1438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) public:
1448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  virtual ~RenderViewHostDestructionObserver() {}
1458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) private:
1478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  explicit RenderViewHostDestructionObserver(WebContents* web_contents)
1488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      : WebContentsObserver(web_contents) {
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    BrowserContext* context = web_contents->GetBrowserContext();
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    process_manager_ = ExtensionSystem::Get(context)->process_manager();
1518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
1528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  friend class content::WebContentsUserData<RenderViewHostDestructionObserver>;
1548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // content::WebContentsObserver overrides.
1568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  virtual void RenderViewDeleted(RenderViewHost* render_view_host) OVERRIDE {
1578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    process_manager_->UnregisterRenderViewHost(render_view_host);
1588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
1598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ProcessManager* process_manager_;
1618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(RenderViewHostDestructionObserver);
1638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)};
1648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)struct ProcessManager::BackgroundPageData {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The count of things keeping the lazy background page alive.
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int lazy_keepalive_count;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Tracks if an impulse event has occured since the last polling check.
170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool keepalive_impulse;
171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool previous_keepalive_impulse;
172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // True if the page responded to the ShouldSuspend message and is currently
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // dispatching the suspend event. During this time any events that arrive will
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // cancel the suspend process and an onSuspendCanceled event will be
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // dispatched to the page.
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_closing;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Stores the value of the incremented
180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // ProcessManager::last_background_close_sequence_id_ whenever the extension
181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // is active. A copy of the ID is also passed in the callbacks and IPC
182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // messages leading up to CloseLazyBackgroundPageNow. The process is aborted
183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // if the IDs ever differ due to new activity.
184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint64 close_sequence_id;
185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Keeps track of when this page was last suspended. Used for perf metrics.
1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  linked_ptr<base::ElapsedTimer> since_suspended;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BackgroundPageData()
190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      : lazy_keepalive_count(0),
191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        keepalive_impulse(false),
192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        previous_keepalive_impulse(false),
193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        is_closing(false),
194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        close_sequence_id(0) {}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// ProcessManager
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ProcessManager* ProcessManager::Create(BrowserContext* context) {
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ExtensionRegistry* extension_registry = ExtensionRegistry::Get(context);
204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ExtensionsBrowserClient* client = ExtensionsBrowserClient::Get();
205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (client->IsGuestSession(context)) {
206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // In the guest session, there is a single off-the-record context.  Unlike
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // a regular incognito mode, background pages of extensions must be
208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // created regardless of whether extensions use "spanning" or "split"
209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // incognito behavior.
210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    BrowserContext* original_context = client->GetOriginalContext(context);
2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return new ProcessManager(context, original_context, extension_registry);
212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (context->IsOffTheRecord()) {
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    BrowserContext* original_context = client->GetOriginalContext(context);
216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ProcessManager* original_manager =
217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        ExtensionSystem::Get(original_context)->process_manager();
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return new IncognitoProcessManager(
2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        context, original_context, original_manager, extension_registry);
220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return new ProcessManager(context, context, extension_registry);
2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// static
2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ProcessManager* ProcessManager::CreateForTesting(
2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    BrowserContext* context,
2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ExtensionRegistry* extension_registry) {
2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(!context->IsOffTheRecord());
2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return new ProcessManager(context, context, extension_registry);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// static
234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ProcessManager* ProcessManager::CreateIncognitoForTesting(
235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    BrowserContext* incognito_context,
236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    BrowserContext* original_context,
2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ProcessManager* original_manager,
2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ExtensionRegistry* extension_registry) {
239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(incognito_context->IsOffTheRecord());
240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(!original_context->IsOffTheRecord());
2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return new IncognitoProcessManager(incognito_context,
2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     original_context,
2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     original_manager,
2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     extension_registry);
245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ProcessManager::ProcessManager(BrowserContext* context,
2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               BrowserContext* original_context,
2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               ExtensionRegistry* extension_registry)
250116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    : site_instance_(SiteInstance::Create(context)),
2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      extension_registry_(extension_registry),
252116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      startup_background_hosts_created_(false),
253116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      devtools_callback_(base::Bind(&ProcessManager::OnDevToolsStateChanged,
254116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                    base::Unretained(this))),
255116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      last_background_close_sequence_id_(0),
256116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      weak_ptr_factory_(this) {
2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // ExtensionRegistry is shared between incognito and regular contexts.
2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_EQ(original_context, extension_registry_->browser_context());
2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  registrar_.Add(this,
2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED,
261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 content::Source<BrowserContext>(original_context));
2620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  registrar_.Add(this,
2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 content::Source<BrowserContext>(original_context));
2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  registrar_.Add(this,
2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 content::Source<BrowserContext>(original_context));
2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  registrar_.Add(this,
2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED,
270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 content::Source<BrowserContext>(context));
2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  registrar_.Add(this,
2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 extensions::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE,
273f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 content::Source<BrowserContext>(context));
2744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 content::NotificationService::AllSources());
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 content::NotificationService::AllSources());
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  content::DevToolsAgentHost::AddAgentStateCallback(devtools_callback_);
280a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
281a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  OnKeepaliveImpulseCheck();
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ProcessManager::~ProcessManager() {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseBackgroundHosts();
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(background_hosts_.empty());
28703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  content::DevToolsAgentHost::RemoveAgentStateCallback(devtools_callback_);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const ProcessManager::ViewSet ProcessManager::GetAllViews() const {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ViewSet result;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ExtensionRenderViews::const_iterator iter =
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           all_extension_views_.begin();
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != all_extension_views_.end(); ++iter) {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.insert(iter->first);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3004ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochvoid ProcessManager::AddObserver(ProcessManagerObserver* observer) {
3014ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  observer_list_.AddObserver(observer);
3024ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch}
3034ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
3044ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochvoid ProcessManager::RemoveObserver(ProcessManagerObserver* observer) {
3054ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch  observer_list_.RemoveObserver(observer);
3064ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch}
3074ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ProcessManager::CreateBackgroundHost(const Extension* extension,
309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          const GURL& url) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Hosted apps are taken care of from BackgroundContentsService. Ignore them
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // here.
3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (extension->is_hosted_app())
3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Don't create hosts if the embedder doesn't allow it.
3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ProcessManagerDelegate* delegate =
3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ExtensionsBrowserClient::Get()->GetProcessManagerDelegate();
3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (delegate && !delegate->IsBackgroundPageAllowed(GetBrowserContext()))
319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't create multiple background hosts for an extension.
322a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (GetBackgroundHostForExtension(extension->id()))
323a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return true;  // TODO(kalman): return false here? It might break things...
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionHost* host =
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ExtensionHost(extension, GetSiteInstanceForURL(url), url,
327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  host->CreateRenderViewSoon();
329f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OnBackgroundHostCreated(host);
330a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return true;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
333f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ExtensionHost* ProcessManager::GetBackgroundHostForExtension(
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id) {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ExtensionHostSet::iterator iter = background_hosts_.begin();
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != background_hosts_.end(); ++iter) {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionHost* host = *iter;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (host->extension_id() == extension_id)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return host;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
344f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)std::set<RenderViewHost*> ProcessManager::GetRenderViewHostsForExtension(
345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& extension_id) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<RenderViewHost*> result;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SiteInstance* site_instance = GetSiteInstanceForURL(
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Extension::GetBaseURLFromExtensionId(extension_id));
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!site_instance)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Gather up all the views for that site.
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ExtensionRenderViews::iterator view = all_extension_views_.begin();
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       view != all_extension_views_.end(); ++view) {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (view->first->GetSiteInstance() == site_instance)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result.insert(view->first);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const Extension* ProcessManager::GetExtensionForRenderViewHost(
3644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    RenderViewHost* render_view_host) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!render_view_host->GetSiteInstance())
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return extension_registry_->enabled_extensions().GetByID(
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GetExtensionID(render_view_host));
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ProcessManager::UnregisterRenderViewHost(
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RenderViewHost* render_view_host) {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionRenderViews::iterator view =
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      all_extension_views_.find(render_view_host);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (view == all_extension_views_.end())
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
379f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OnRenderViewHostUnregistered(GetBrowserContext(), render_view_host);
380f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ViewType view_type = view->second;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  all_extension_views_.erase(view);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Keepalive count, balanced in RegisterRenderViewHost.
384f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (view_type != VIEW_TYPE_INVALID &&
385f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      view_type != VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Extension* extension = GetExtensionForRenderViewHost(
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        render_view_host);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extension)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DecrementLazyKeepaliveCount(extension);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ProcessManager::RegisterRenderViewHost(RenderViewHost* render_view_host) {
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const Extension* extension = GetExtensionForRenderViewHost(
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      render_view_host);
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!extension)
3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebContents* web_contents = WebContents::FromRenderViewHost(render_view_host);
400f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  all_extension_views_[render_view_host] = GetViewType(web_contents);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Keep the lazy background page alive as long as any non-background-page
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // extension views are visible. Keepalive count balanced in
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // UnregisterRenderViewHost.
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IncrementLazyKeepaliveCountForView(render_view_host);
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
409f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SiteInstance* ProcessManager::GetSiteInstanceForURL(const GURL& url) {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return site_instance_->GetRelatedSiteInstance(url);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
413f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool ProcessManager::IsBackgroundHostClosing(const std::string& extension_id) {
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionHost* host = GetBackgroundHostForExtension(extension_id);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (host && background_page_data_[extension_id].is_closing);
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
418f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)int ProcessManager::GetLazyKeepaliveCount(const Extension* extension) {
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!BackgroundInfo::HasLazyBackgroundPage(extension))
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return background_page_data_[extension->id()].lazy_keepalive_count;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ProcessManager::IncrementLazyKeepaliveCount(const Extension* extension) {
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!BackgroundInfo::HasLazyBackgroundPage(extension))
427a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int& count = background_page_data_[extension->id()].lazy_keepalive_count;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (++count == 1)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnLazyBackgroundPageActive(extension->id());
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
434a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ProcessManager::DecrementLazyKeepaliveCount(const Extension* extension) {
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!BackgroundInfo::HasLazyBackgroundPage(extension))
436a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
437a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DecrementLazyKeepaliveCount(extension->id());
438a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
440a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ProcessManager::DecrementLazyKeepaliveCount(
441a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const std::string& extension_id) {
442a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  int& count = background_page_data_[extension_id].lazy_keepalive_count;
443cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(count > 0 ||
4445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)         !extension_registry_->enabled_extensions().Contains(extension_id));
4454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // If we reach a zero keepalive count when the lazy background page is about
4474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // to be closed, incrementing close_sequence_id will cancel the close
4484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // sequence and cause the background page to linger. So check is_closing
4494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // before initiating another close sequence.
450a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (--count == 0 && !background_page_data_[extension_id].is_closing) {
451116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    background_page_data_[extension_id].close_sequence_id =
452116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        ++last_background_close_sequence_id_;
45390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
455f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        base::Bind(&ProcessManager::OnLazyBackgroundPageIdle,
456116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   weak_ptr_factory_.GetWeakPtr(),
457116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   extension_id,
458116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                   last_background_close_sequence_id_),
4591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        base::TimeDelta::FromMilliseconds(g_event_page_idle_time_msec));
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
463f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ProcessManager::IncrementLazyKeepaliveCountForView(
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RenderViewHost* render_view_host) {
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebContents* web_contents =
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebContents::FromRenderViewHost(render_view_host);
467f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ViewType view_type = GetViewType(web_contents);
468f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (view_type != VIEW_TYPE_INVALID &&
469f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      view_type != VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Extension* extension = GetExtensionForRenderViewHost(
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        render_view_host);
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (extension)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IncrementLazyKeepaliveCount(extension);
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
477a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// This implementation layers on top of the keepalive count. An impulse sets
478a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// a per extension flag. On a regular interval that flag is checked. Changes
479a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// from the flag not being set to set cause an IncrementLazyKeepaliveCount.
480a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ProcessManager::KeepaliveImpulse(const Extension* extension) {
481a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!BackgroundInfo::HasLazyBackgroundPage(extension))
482a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
483a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
484a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  BackgroundPageData& bd = background_page_data_[extension->id()];
485a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
486a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!bd.keepalive_impulse) {
487a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    bd.keepalive_impulse = true;
488a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (!bd.previous_keepalive_impulse) {
489a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      IncrementLazyKeepaliveCount(extension);
490a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
491a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!keepalive_impulse_callback_for_testing_.is_null()) {
4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ImpulseCallbackForTesting callback_may_clear_callbacks_reentrantly =
4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      keepalive_impulse_callback_for_testing_;
4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callback_may_clear_callbacks_reentrantly.Run(extension->id());
4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
498a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
499a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
50003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// static
50103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void ProcessManager::OnKeepaliveFromPlugin(int render_process_id,
50203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                           int render_frame_id,
50303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                           const std::string& extension_id) {
50403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  content::RenderFrameHost* render_frame_host =
50503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      content::RenderFrameHost::FromID(render_process_id, render_frame_id);
50603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!render_frame_host)
50703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return;
50803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
50903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  content::SiteInstance* site_instance = render_frame_host->GetSiteInstance();
51003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!site_instance)
51103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return;
51203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
51303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  BrowserContext* browser_context = site_instance->GetBrowserContext();
51403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const Extension* extension =
51503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      ExtensionRegistry::Get(browser_context)->enabled_extensions().GetByID(
51603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          extension_id);
51703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!extension)
51803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return;
51903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
52003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ProcessManager* pm = ExtensionSystem::Get(browser_context)->process_manager();
52103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!pm)
52203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return;
52303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
52403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  pm->KeepaliveImpulse(extension);
52503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
52603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
527a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// DecrementLazyKeepaliveCount is called when no calls to KeepaliveImpulse
5281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// have been made for at least g_event_page_idle_time_msec. In the best case an
529a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// impulse was made just before being cleared, and the decrement will occur
5301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// g_event_page_idle_time_msec later, causing a 2 * g_event_page_idle_time_msec
5311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// total time for extension to be shut down based on impulses. Worst case is
5321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// an impulse just after a clear, adding one check cycle and resulting in 3x
5331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// total time.
534a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ProcessManager::OnKeepaliveImpulseCheck() {
535a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (BackgroundPageDataMap::iterator i = background_page_data_.begin();
536a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       i != background_page_data_.end();
537a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       ++i) {
5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (i->second.previous_keepalive_impulse && !i->second.keepalive_impulse) {
539a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      DecrementLazyKeepaliveCount(i->first);
5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (!keepalive_impulse_decrement_callback_for_testing_.is_null()) {
5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ImpulseCallbackForTesting callback_may_clear_callbacks_reentrantly =
5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          keepalive_impulse_decrement_callback_for_testing_;
5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        callback_may_clear_callbacks_reentrantly.Run(i->first);
5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
546a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
547a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    i->second.previous_keepalive_impulse = i->second.keepalive_impulse;
548a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    i->second.keepalive_impulse = false;
549a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
550a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
551a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // OnKeepaliveImpulseCheck() is always called in constructor, but in unit
552a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // tests there will be no message loop. In that event don't schedule tasks.
553a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (base::MessageLoop::current()) {
554a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
555a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        FROM_HERE,
556a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        base::Bind(&ProcessManager::OnKeepaliveImpulseCheck,
557a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
5581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        base::TimeDelta::FromMilliseconds(g_event_page_idle_time_msec));
559a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
560a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
561a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
562f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ProcessManager::OnLazyBackgroundPageIdle(const std::string& extension_id,
563116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                              uint64 sequence_id) {
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionHost* host = GetBackgroundHostForExtension(extension_id);
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host && !background_page_data_[extension_id].is_closing &&
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sequence_id == background_page_data_[extension_id].close_sequence_id) {
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Tell the renderer we are about to close. This is a simple ping that the
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // renderer will respond to. The purpose is to control sequencing: if the
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // extension remains idle until the renderer responds with an ACK, then we
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // know that the extension process is ready to shut down. If our
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // close_sequence_id has already changed, then we would ignore the
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // ShouldSuspendAck, so we don't send the ping.
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    host->render_view_host()->Send(new ExtensionMsg_ShouldSuspend(
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extension_id, sequence_id));
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
578f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ProcessManager::OnLazyBackgroundPageActive(
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& extension_id) {
580116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!background_page_data_[extension_id].is_closing) {
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Cancel the current close sequence by changing the close_sequence_id,
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // which causes us to ignore the next ShouldSuspendAck.
583116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    background_page_data_[extension_id].close_sequence_id =
584116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        ++last_background_close_sequence_id_;
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
588f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ProcessManager::OnShouldSuspendAck(const std::string& extension_id,
589116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                        uint64 sequence_id) {
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionHost* host = GetBackgroundHostForExtension(extension_id);
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host &&
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sequence_id == background_page_data_[extension_id].close_sequence_id) {
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    host->render_view_host()->Send(new ExtensionMsg_Suspend(extension_id));
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
597f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ProcessManager::OnSuspendAck(const std::string& extension_id) {
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  background_page_data_[extension_id].is_closing = true;
599116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  uint64 sequence_id = background_page_data_[extension_id].close_sequence_id;
60090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->PostDelayedTask(
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
602f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::Bind(&ProcessManager::CloseLazyBackgroundPageNow,
6031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 weak_ptr_factory_.GetWeakPtr(),
6041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 extension_id,
6051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 sequence_id),
6061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::TimeDelta::FromMilliseconds(g_event_page_suspending_time_msec));
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
609f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ProcessManager::CloseLazyBackgroundPageNow(const std::string& extension_id,
610116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                uint64 sequence_id) {
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionHost* host = GetBackgroundHostForExtension(extension_id);
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host &&
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sequence_id == background_page_data_[extension_id].close_sequence_id) {
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionHost* host = GetBackgroundHostForExtension(extension_id);
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (host)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CloseBackgroundHost(host);
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ProcessManager::OnNetworkRequestStarted(
6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    content::RenderFrameHost* render_frame_host) {
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionHost* host = GetBackgroundHostForExtension(
6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GetExtensionIDFromFrame(render_frame_host));
6245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (host && IsFrameInExtensionHost(host, render_frame_host))
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IncrementLazyKeepaliveCount(host->extension());
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ProcessManager::OnNetworkRequestDone(
6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    content::RenderFrameHost* render_frame_host) {
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionHost* host = GetBackgroundHostForExtension(
6315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GetExtensionIDFromFrame(render_frame_host));
6325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (host && IsFrameInExtensionHost(host, render_frame_host))
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DecrementLazyKeepaliveCount(host->extension());
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
636f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ProcessManager::CancelSuspend(const Extension* extension) {
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool& is_closing = background_page_data_[extension->id()].is_closing;
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionHost* host = GetBackgroundHostForExtension(extension->id());
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host && is_closing) {
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_closing = false;
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host->render_view_host()->Send(
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        new ExtensionMsg_CancelSuspend(extension->id()));
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This increment / decrement is to simulate an instantaneous event. This
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // has the effect of invalidating close_sequence_id, preventing any in
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // progress closes from completing and starting a new close process if
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // necessary.
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IncrementLazyKeepaliveCount(extension);
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DecrementLazyKeepaliveCount(extension);
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ProcessManager::CloseBackgroundHosts() {
6535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (ExtensionHostSet::iterator iter = background_hosts_.begin();
6545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       iter != background_hosts_.end();) {
6555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ExtensionHostSet::iterator current = iter++;
6565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    delete *current;
6575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
658f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
660f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)content::BrowserContext* ProcessManager::GetBrowserContext() const {
661f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return site_instance_->GetBrowserContext();
662f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
663f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
6645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ProcessManager::SetKeepaliveImpulseCallbackForTesting(
6655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ImpulseCallbackForTesting& callback) {
6665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  keepalive_impulse_callback_for_testing_ = callback;
6675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
6685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ProcessManager::SetKeepaliveImpulseDecrementCallbackForTesting(
6705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ImpulseCallbackForTesting& callback) {
6715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  keepalive_impulse_decrement_callback_for_testing_ = callback;
6725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
6735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static
6751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ProcessManager::SetEventPageIdleTimeForTesting(unsigned idle_time_msec) {
6761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CHECK_GT(idle_time_msec, 0u);  // OnKeepaliveImpulseCheck requires non zero.
6771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  g_event_page_idle_time_msec = idle_time_msec;
6781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
6791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static
6811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ProcessManager::SetEventPageSuspendingTimeForTesting(
6821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    unsigned suspending_time_msec) {
6831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  g_event_page_suspending_time_msec = suspending_time_msec;
6841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
6851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
686f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ProcessManager::Observe(int type,
687f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                             const content::NotificationSource& source,
688f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                             const content::NotificationDetails& details) {
689f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  switch (type) {
6905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED: {
6915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // TODO(jamescook): Convert this to use ExtensionSystem::ready() instead
6925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // of a notification.
6935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      MaybeCreateStartupBackgroundHosts();
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED: {
698f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      BrowserContext* context = content::Source<BrowserContext>(source).ptr();
6995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExtensionSystem* system = ExtensionSystem::Get(context);
7005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (system->ready().is_signaled()) {
7015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // The extension system is ready, so create the background host.
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const Extension* extension =
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            content::Details<const Extension>(details).ptr();
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateBackgroundHostForExtensionLoad(this, extension);
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: {
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Extension* extension =
711f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          content::Details<UnloadedExtensionInfo>(details)->extension;
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (ExtensionHostSet::iterator iter = background_hosts_.begin();
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           iter != background_hosts_.end(); ++iter) {
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ExtensionHost* host = *iter;
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (host->extension_id() == extension->id()) {
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CloseBackgroundHost(host);
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
72068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      UnregisterExtension(extension->id());
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED: {
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ExtensionHost* host = content::Details<ExtensionHost>(details).ptr();
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (background_hosts_.erase(host)) {
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ClearBackgroundPageData(host->extension()->id());
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        background_page_data_[host->extension()->id()].since_suspended.reset(
7294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            new base::ElapsedTimer());
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case extensions::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE: {
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ExtensionHost* host = content::Details<ExtensionHost>(details).ptr();
736f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (host->extension_host_type() == VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CloseBackgroundHost(host);
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    case content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED: {
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // We get this notification both for new WebContents and when one
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // has its RenderViewHost replaced (e.g. when a user does a cross-site
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // navigation away from an extension URL). For the replaced case, we must
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // unregister the old RVH so it doesn't count as an active view that would
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // keep the event page alive.
7484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      WebContents* contents = content::Source<WebContents>(source).ptr();
749f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (contents->GetBrowserContext() != GetBrowserContext())
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      typedef std::pair<RenderViewHost*, RenderViewHost*> RVHPair;
7534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      RVHPair* switched_details = content::Details<RVHPair>(details).ptr();
7544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (switched_details->first)
7554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        UnregisterRenderViewHost(switched_details->first);
7568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      // The above will unregister a RVH when it gets swapped out with a new
7588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      // one. However we need to watch the WebContents to know when a RVH is
7598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      // deleted because the WebContents has gone away.
7605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (RegisterRenderViewHost(switched_details->second)) {
7615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        RenderViewHostDestructionObserver::CreateForWebContents(contents);
7625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case content::NOTIFICATION_WEB_CONTENTS_CONNECTED: {
7674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      WebContents* contents = content::Source<WebContents>(source).ptr();
768f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (contents->GetBrowserContext() != GetBrowserContext())
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const Extension* extension = GetExtensionForRenderViewHost(
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          contents->GetRenderViewHost());
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!extension)
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return;
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // RegisterRenderViewHost is called too early (before the process is
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // available), so we need to wait until now to notify.
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::NotificationService::current()->Notify(
7785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          extensions::NOTIFICATION_EXTENSION_VIEW_REGISTERED,
779f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          content::Source<BrowserContext>(GetBrowserContext()),
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          content::Details<RenderViewHost>(contents->GetRenderViewHost()));
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
789f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ProcessManager::OnDevToolsStateChanged(
790f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    content::DevToolsAgentHost* agent_host,
791f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool attached) {
7926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  WebContents* web_contents = agent_host->GetWebContents();
793c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Ignore unrelated notifications.
7946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!web_contents || web_contents->GetBrowserContext() != GetBrowserContext())
795c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
7966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (GetViewType(web_contents) != VIEW_TYPE_EXTENSION_BACKGROUND_PAGE)
797c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
7986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const Extension* extension =
7996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      GetExtensionForRenderViewHost(web_contents->GetRenderViewHost());
800c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!extension)
801c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
802c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (attached) {
803c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Keep the lazy background page alive while it's being inspected.
804c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CancelSuspend(extension);
805c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    IncrementLazyKeepaliveCount(extension);
806c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
807c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DecrementLazyKeepaliveCount(extension);
808c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
809c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
810c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
8115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ProcessManager::MaybeCreateStartupBackgroundHosts() {
8125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (startup_background_hosts_created_)
813f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
814f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
8155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // The embedder might disallow background pages entirely.
8165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ProcessManagerDelegate* delegate =
8175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ExtensionsBrowserClient::Get()->GetProcessManagerDelegate();
8185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (delegate && !delegate->IsBackgroundPageAllowed(GetBrowserContext()))
8195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // The embedder might want to defer background page loading. For example,
8225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Chrome defers background page loading when it is launched to show the app
8235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // list, then triggers a load later when a browser window opens.
8245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (delegate &&
8255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      delegate->DeferCreatingStartupBackgroundHosts(GetBrowserContext()))
8265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
8275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CreateStartupBackgroundHosts();
829f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  startup_background_hosts_created_ = true;
8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Background pages should only be loaded once. To prevent any further loads
832b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // occurring, we remove the notification listeners.
833f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  BrowserContext* original_context =
834f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ExtensionsBrowserClient::Get()->GetOriginalContext(GetBrowserContext());
835f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (registrar_.IsRegistered(
836f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          this,
8375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED,
838f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          content::Source<BrowserContext>(original_context))) {
839f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    registrar_.Remove(this,
8405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED,
841f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                      content::Source<BrowserContext>(original_context));
842f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
8435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
8445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ProcessManager::CreateStartupBackgroundHosts() {
8465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(!startup_background_hosts_created_);
8475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const ExtensionSet& enabled_extensions =
8485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      extension_registry_->enabled_extensions();
8495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (ExtensionSet::const_iterator extension = enabled_extensions.begin();
8505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       extension != enabled_extensions.end();
8515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       ++extension) {
8525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    CreateBackgroundHostForExtensionLoad(this, extension->get());
8535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    FOR_EACH_OBSERVER(ProcessManagerObserver,
8555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      observer_list_,
8561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                      OnBackgroundHostStartup(extension->get()));
857f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
858f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
859f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
860f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ProcessManager::OnBackgroundHostCreated(ExtensionHost* host) {
861f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK_EQ(GetBrowserContext(), host->browser_context());
862f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  background_hosts_.insert(host);
863f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
864f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (BackgroundInfo::HasLazyBackgroundPage(host->extension())) {
865f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    linked_ptr<base::ElapsedTimer> since_suspended(
866f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        background_page_data_[host->extension()->id()].
867f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            since_suspended.release());
868f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (since_suspended.get()) {
869f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      UMA_HISTOGRAM_LONG_TIMES("Extensions.EventPageIdleTime",
870f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                               since_suspended->Elapsed());
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ProcessManager::CloseBackgroundHost(ExtensionHost* host) {
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(host->extension_host_type() ==
877f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        VIEW_TYPE_EXTENSION_BACKGROUND_PAGE);
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete host;
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |host| should deregister itself from our structures.
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(background_hosts_.find(host) == background_hosts_.end());
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
883f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ProcessManager::UnregisterExtension(const std::string& extension_id) {
88468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // The lazy_keepalive_count may be greater than zero at this point because
88568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // RenderViewHosts are still alive. During extension reloading, they will
88668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // decrement the lazy_keepalive_count to negative for the new extension
88768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // instance when they are destroyed. Since we are erasing the background page
88868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // data for the unloaded extension, unregister the RenderViewHosts too.
889f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  BrowserContext* context = GetBrowserContext();
89068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (ExtensionRenderViews::iterator it = all_extension_views_.begin();
89168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)       it != all_extension_views_.end(); ) {
89268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (GetExtensionID(it->first) == extension_id) {
893f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      OnRenderViewHostUnregistered(context, it->first);
89468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      all_extension_views_.erase(it++);
89568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    } else {
89668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ++it;
89768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
89868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
89968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
90068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  background_page_data_.erase(extension_id);
90168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
90268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
903f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ProcessManager::ClearBackgroundPageData(const std::string& extension_id) {
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  background_page_data_.erase(extension_id);
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Re-register all RenderViews for this extension. We do this to restore
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the lazy_keepalive_count (if any) to properly reflect the number of open
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // views.
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ExtensionRenderViews::const_iterator it = all_extension_views_.begin();
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != all_extension_views_.end(); ++it) {
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (GetExtensionID(it->first) == extension_id)
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IncrementLazyKeepaliveCountForView(it->first);
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
917f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// IncognitoProcessManager
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
920f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)IncognitoProcessManager::IncognitoProcessManager(
921f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    BrowserContext* incognito_context,
922a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    BrowserContext* original_context,
9235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ProcessManager* original_manager,
9245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ExtensionRegistry* extension_registry)
9255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : ProcessManager(incognito_context, original_context, extension_registry),
926a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      original_manager_(original_manager) {
927f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(incognito_context->IsOffTheRecord());
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
929f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // The original profile will have its own ProcessManager to
9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // load the background pages of the spanning extensions. This process
9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // manager need only worry about the split mode extensions, which is handled
9322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // in the NOTIFICATION_BROWSER_WINDOW_READY notification handler.
9335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  registrar_.Remove(this,
9345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED,
935f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                    content::Source<BrowserContext>(original_context));
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
938a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool IncognitoProcessManager::CreateBackgroundHost(const Extension* extension,
939a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                   const GURL& url) {
940f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (IncognitoInfo::IsSplitMode(extension)) {
9415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (ExtensionsBrowserClient::Get()->IsExtensionIncognitoEnabled(
9425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            extension->id(), GetBrowserContext()))
943f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return ProcessManager::CreateBackgroundHost(extension, url);
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Do nothing. If an extension is spanning, then its original-profile
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // background page is shared with incognito, so we don't create another.
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
948a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return false;
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
951f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SiteInstance* IncognitoProcessManager::GetSiteInstanceForURL(const GURL& url) {
9525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const Extension* extension =
9535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      extension_registry_->enabled_extensions().GetExtensionOrAppByURL(url);
9545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (extension && !IncognitoInfo::IsSplitMode(extension))
9555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return original_manager_->GetSiteInstanceForURL(url);
9565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
957f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return ProcessManager::GetSiteInstanceForURL(url);
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
960f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace extensions
961