Index: chrome/browser/chromeos/power/renderer_freezer.cc |
diff --git a/chrome/browser/chromeos/power/renderer_freezer.cc b/chrome/browser/chromeos/power/renderer_freezer.cc |
index 6548c9d5c7416fe7e448b3866708ea06c1b9fb43..1aaa79a75293dc5590e924c1c0aa189f970a0c29 100644 |
--- a/chrome/browser/chromeos/power/renderer_freezer.cc |
+++ b/chrome/browser/chromeos/power/renderer_freezer.cc |
@@ -4,24 +4,10 @@ |
#include "chrome/browser/chromeos/power/renderer_freezer.h" |
-#include <string> |
- |
#include "base/bind.h" |
#include "base/logging.h" |
#include "base/message_loop/message_loop.h" |
-#include "base/process/process_handle.h" |
#include "chromeos/dbus/dbus_thread_manager.h" |
-#include "content/public/browser/notification_details.h" |
-#include "content/public/browser/notification_service.h" |
-#include "content/public/browser/notification_source.h" |
-#include "content/public/browser/notification_types.h" |
-#include "content/public/browser/render_process_host.h" |
-#include "extensions/browser/extension_registry.h" |
-#include "extensions/browser/notification_types.h" |
-#include "extensions/browser/process_map.h" |
-#include "extensions/common/extension.h" |
-#include "extensions/common/permissions/api_permission.h" |
-#include "extensions/common/permissions/permissions_data.h" |
namespace chromeos { |
@@ -29,33 +15,36 @@ |
: frozen_(false), |
delegate_(delegate.Pass()), |
weak_factory_(this) { |
- if (delegate_->CanFreezeRenderers()) { |
- DBusThreadManager::Get() |
- ->GetPowerManagerClient() |
- ->SetRenderProcessManagerDelegate(weak_factory_.GetWeakPtr()); |
- |
- registrar_.Add( |
- this, |
- content::NOTIFICATION_RENDERER_PROCESS_CREATED, |
- content::NotificationService::AllBrowserContextsAndSources()); |
- } |
+ if (delegate_->CanFreezeRenderers()) |
+ DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(this); |
} |
RendererFreezer::~RendererFreezer() { |
- for (int rph_id : gcm_extension_processes_) { |
- content::RenderProcessHost* host = |
- content::RenderProcessHost::FromID(rph_id); |
- if (host) |
- host->RemoveObserver(this); |
- } |
+ if (delegate_->CanFreezeRenderers()) |
+ DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(this); |
} |
void RendererFreezer::SuspendImminent() { |
- if (delegate_->FreezeRenderers()) |
- frozen_ = true; |
+ // If there was already a callback pending, this will cancel it and create a |
+ // new one. |
+ suspend_readiness_callback_.Reset( |
+ base::Bind(&RendererFreezer::OnReadyToSuspend, |
+ weak_factory_.GetWeakPtr(), |
+ DBusThreadManager::Get() |
+ ->GetPowerManagerClient() |
+ ->GetSuspendReadinessCallback())); |
+ |
+ base::MessageLoop::current()->PostTask( |
+ FROM_HERE, suspend_readiness_callback_.callback()); |
} |
-void RendererFreezer::SuspendDone() { |
+void RendererFreezer::SuspendDone(const base::TimeDelta& sleep_duration) { |
+ // If we get a SuspendDone before we've had a chance to run OnReadyForSuspend, |
+ // we should cancel it because we no longer want to freeze the renderers. If |
+ // we've already run it then cancelling the callback shouldn't really make a |
+ // difference. |
+ suspend_readiness_callback_.Cancel(); |
+ |
if (!frozen_) |
return; |
@@ -69,98 +58,13 @@ |
frozen_ = false; |
} |
-void RendererFreezer::Observe(int type, |
- const content::NotificationSource& source, |
- const content::NotificationDetails& details) { |
- switch (type) { |
- case content::NOTIFICATION_RENDERER_PROCESS_CREATED: { |
- content::RenderProcessHost* process = |
- content::Source<content::RenderProcessHost>(source).ptr(); |
- OnRenderProcessCreated(process); |
- break; |
- } |
- default: { |
- NOTREACHED(); |
- break; |
- } |
- } |
-} |
+void RendererFreezer::OnReadyToSuspend( |
+ const base::Closure& power_manager_callback) { |
+ if (delegate_->FreezeRenderers()) |
+ frozen_ = true; |
-void RendererFreezer::RenderProcessExited(content::RenderProcessHost* host, |
- base::TerminationStatus status, |
- int exit_code) { |
- auto it = gcm_extension_processes_.find(host->GetID()); |
- if (it == gcm_extension_processes_.end()) { |
- LOG(ERROR) << "Received unrequested RenderProcessExited message"; |
- return; |
- } |
- gcm_extension_processes_.erase(it); |
- |
- // When this function is called, the renderer process has died but the |
- // RenderProcessHost will not be destroyed. If a new renderer process is |
- // created for this RPH, registering as an observer again will trigger a |
- // warning about duplicate observers. To prevent this we just stop observing |
- // this RPH until another renderer process is created for it. |
- host->RemoveObserver(this); |
-} |
- |
-void RendererFreezer::RenderProcessHostDestroyed( |
- content::RenderProcessHost* host) { |
- auto it = gcm_extension_processes_.find(host->GetID()); |
- if (it == gcm_extension_processes_.end()) { |
- LOG(ERROR) << "Received unrequested RenderProcessHostDestroyed message"; |
- return; |
- } |
- |
- gcm_extension_processes_.erase(it); |
-} |
- |
-void RendererFreezer::OnRenderProcessCreated(content::RenderProcessHost* rph) { |
- const int rph_id = rph->GetID(); |
- |
- if (gcm_extension_processes_.find(rph_id) != gcm_extension_processes_.end()) { |
- LOG(ERROR) << "Received duplicate notifications about the creation of a " |
- << "RenderProcessHost with id " << rph_id; |
- return; |
- } |
- |
- // According to extensions::ProcessMap, extensions and renderers have a |
- // many-to-many relationship. Specifically, a hosted app can appear in many |
- // renderers while any other kind of extension can be running in "split mode" |
- // if there is an incognito window open and so could appear in two renderers. |
- // |
- // We don't care about hosted apps because they cannot use GCM so we only need |
- // to worry about extensions in "split mode". Luckily for us this function is |
- // called any time a new renderer process is created so we don't really need |
- // to care whether we are currently in an incognito context. We just need to |
- // iterate over all the extensions in the newly created process and take the |
- // appropriate action based on whether we find an extension using GCM. |
- content::BrowserContext* context = rph->GetBrowserContext(); |
- extensions::ExtensionRegistry* registry = |
- extensions::ExtensionRegistry::Get(context); |
- for (const std::string& extension_id : |
- extensions::ProcessMap::Get(context)->GetExtensionsInProcess(rph_id)) { |
- if (!registry->GetExtensionById(extension_id, |
- extensions::ExtensionRegistry::ENABLED) |
- ->permissions_data() |
- ->HasAPIPermission(extensions::APIPermission::kGcm)) { |
- continue; |
- } |
- |
- // This renderer has an extension that is using GCM. Make sure it is not |
- // frozen during suspend. |
- delegate_->SetShouldFreezeRenderer(rph->GetHandle(), false); |
- gcm_extension_processes_.insert(rph_id); |
- |
- // Watch to see if the renderer process or the RenderProcessHost is |
- // destroyed. |
- rph->AddObserver(this); |
- return; |
- } |
- |
- // We didn't find an extension in this RenderProcessHost that is using GCM so |
- // we can go ahead and freeze it on suspend. |
- delegate_->SetShouldFreezeRenderer(rph->GetHandle(), true); |
+ DCHECK(!power_manager_callback.is_null()); |
+ power_manager_callback.Run(); |
} |
} // namespace chromeos |