| Index: chrome/browser/chromeos/net/wake_on_wifi_manager.cc
|
| diff --git a/chrome/browser/chromeos/net/wake_on_wifi_manager.cc b/chrome/browser/chromeos/net/wake_on_wifi_manager.cc
|
| index 5584524f1aa66098c896412cf2315d3985cabf48..b43de4434f158ded0951e03df2805d47d01217f5 100644
|
| --- a/chrome/browser/chromeos/net/wake_on_wifi_manager.cc
|
| +++ b/chrome/browser/chromeos/net/wake_on_wifi_manager.cc
|
| @@ -11,13 +11,16 @@
|
| #include "base/logging.h"
|
| #include "base/macros.h"
|
| #include "base/memory/scoped_ptr.h"
|
| +#include "base/message_loop/message_loop_proxy.h"
|
| #include "base/sys_info.h"
|
| #include "base/values.h"
|
| #include "chrome/browser/chrome_notification_types.h"
|
| #include "chrome/browser/profiles/profile.h"
|
| #include "chrome/browser/services/gcm/gcm_profile_service.h"
|
| #include "chrome/browser/services/gcm/gcm_profile_service_factory.h"
|
| +#include "chrome/common/extensions/api/gcm.h"
|
| #include "chromeos/chromeos_switches.h"
|
| +#include "chromeos/dbus/dbus_thread_manager.h"
|
| #include "chromeos/login/login_state.h"
|
| #include "chromeos/network/device_state.h"
|
| #include "chromeos/network/network_device_handler.h"
|
| @@ -26,9 +29,17 @@
|
| #include "chromeos/network/network_type_pattern.h"
|
| #include "components/gcm_driver/gcm_connection_observer.h"
|
| #include "components/gcm_driver/gcm_driver.h"
|
| +#include "content/public/browser/browser_context.h"
|
| #include "content/public/browser/browser_thread.h"
|
| #include "content/public/browser/notification_service.h"
|
| #include "content/public/browser/notification_source.h"
|
| +#include "extensions/browser/extension_registry.h"
|
| +#include "extensions/browser/extension_system.h"
|
| +#include "extensions/common/extension.h"
|
| +#include "extensions/common/extension_set.h"
|
| +#include "extensions/common/one_shot_event.h"
|
| +#include "extensions/common/permissions/api_permission.h"
|
| +#include "extensions/common/permissions/permissions_data.h"
|
| #include "net/base/ip_endpoint.h"
|
| #include "third_party/cros_system_api/dbus/service_constants.h"
|
|
|
| @@ -141,7 +152,9 @@ WakeOnWifiManager* WakeOnWifiManager::Get() {
|
|
|
| WakeOnWifiManager::WakeOnWifiManager()
|
| : current_feature_(WakeOnWifiManager::INVALID),
|
| + suspend_is_pending_(false),
|
| weak_ptr_factory_(this) {
|
| + LOG(WARNING) << "CONSTRUCTOR";
|
| // This class must be constructed before any users are logged in, i.e., before
|
| // any profiles are created or added to the ProfileManager. Additionally,
|
| // IsUserLoggedIn always returns true when we are not running on a Chrome OS
|
| @@ -168,6 +181,8 @@ WakeOnWifiManager::WakeOnWifiManager()
|
|
|
| if (!switches::WakeOnWifiEnabled())
|
| return;
|
| + LOG(WARNING) << "Adding WakeOnWifiManager as PowerManagerClient::Observer.";
|
| + DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(this);
|
|
|
| const DeviceState* device =
|
| NetworkHandler::Get()->network_state_handler()->GetDeviceStateByType(
|
| @@ -186,6 +201,14 @@ WakeOnWifiManager::~WakeOnWifiManager() {
|
| DCHECK(g_wake_on_wifi_manager);
|
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| g_wake_on_wifi_manager = NULL;
|
| +
|
| + for (const auto& kv_pair : connection_observers_) {
|
| + Profile* profile = kv_pair.first;
|
| + extensions::ExtensionRegistry::Get(profile)->RemoveObserver(this);
|
| + }
|
| +
|
| + if (switches::WakeOnWifiEnabled())
|
| + DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(this);
|
| }
|
|
|
| void WakeOnWifiManager::OnPreferenceChanged(
|
| @@ -245,6 +268,7 @@ void WakeOnWifiManager::GetDevicePropertiesCallback(
|
| void WakeOnWifiManager::Observe(int type,
|
| const content::NotificationSource& source,
|
| const content::NotificationDetails& details) {
|
| + using DispatchDetails = extensions::EventRouter::DispatchDetails;
|
| switch (type) {
|
| case chrome::NOTIFICATION_PROFILE_ADDED: {
|
| OnProfileAdded(content::Source<Profile>(source).ptr());
|
| @@ -254,11 +278,47 @@ void WakeOnWifiManager::Observe(int type,
|
| OnProfileDestroyed(content::Source<Profile>(source).ptr());
|
| break;
|
| }
|
| + case extensions::NOTIFICATION_EXTENSION_MESSAGE_DISPATCHED: {
|
| + OnExtensionMessageDispatched(
|
| + content::Details<DispatchDetails>(details).ptr());
|
| + break;
|
| + }
|
| + case extensions::NOTIFICATION_EXTENSION_MESSAGE_ACKED: {
|
| + OnExtensionMessageAcked(*(content::Details<int>(details).ptr()));
|
| + break;
|
| + }
|
| default:
|
| NOTREACHED();
|
| }
|
| }
|
|
|
| +void WakeOnWifiManager::OnExtensionLoaded(
|
| + content::BrowserContext* context, const extensions::Extension* extension) {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| + if (!extension->permissions_data()->HasAPIPermission(
|
| + extensions::APIPermission::kGcm))
|
| + return;
|
| +
|
| + gcm_extensions_.insert(extension->id());
|
| +}
|
| +
|
| +void WakeOnWifiManager::SuspendImminent() {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| + OnSuspendImminent(false);
|
| +}
|
| +
|
| +void WakeOnWifiManager::SuspendDone(const base::TimeDelta& duration) {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| + suspend_is_pending_ = false;
|
| + power_manager_callback_.Reset();
|
| + suspend_readiness_callback_.Cancel();
|
| +}
|
| +
|
| +void WakeOnWifiManager::DarkSuspendImminent() {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| + OnSuspendImminent(true);
|
| +}
|
| +
|
| void WakeOnWifiManager::OnProfileAdded(Profile* profile) {
|
| // add will do nothing if |profile| already exists in |connection_observers_|.
|
| auto result = connection_observers_.add(
|
| @@ -272,11 +332,99 @@ void WakeOnWifiManager::OnProfileAdded(Profile* profile) {
|
| ->driver()
|
| ->WakeFromSuspendForHeartbeat(
|
| IsWakeOnPacketEnabled(current_feature_));
|
| +
|
| + // The ExtensionRegistry will call OnExtensionLoaded whenever the user
|
| + // installs and enables a new extension.
|
| + extensions::ExtensionRegistry::Get(profile)->AddObserver(this);
|
| +
|
| + // OnExtensionLoaded is not called for extensions that the user had already
|
| + // installed and enabled. So we wait until the ExtensionSystem for the
|
| + // profile is ready and then iterate through the installed extensions,
|
| + // manually calling OnExtensionLoaded for each of them.
|
| + extensions::ExtensionSystem::Get(profile)->ready().Post(
|
| + FROM_HERE,
|
| + base::Bind(&WakeOnWifiManager::OnExtensionSystemReady,
|
| + weak_ptr_factory_.GetWeakPtr(), profile));
|
| +
|
| + registrar_.Add(this,
|
| + extensions::NOTIFICATION_EXTENSION_MESSAGE_DISPATCHED,
|
| + content::Source<content::BrowserContext>(profile));
|
| + registrar_.Add(this,
|
| + extensions::NOTIFICATION_EXTENSION_MESSAGE_ACKED,
|
| + content::Source<content::BrowserContext>(profile));
|
| }
|
| }
|
|
|
| void WakeOnWifiManager::OnProfileDestroyed(Profile* profile) {
|
| connection_observers_.erase(profile);
|
| +
|
| + extensions::ExtensionRegistry::Get(profile)->RemoveObserver(this);
|
| + registrar_.Remove(this,
|
| + extensions::NOTIFICATION_EXTENSION_MESSAGE_DISPATCHED,
|
| + content::Source<content::BrowserContext>(profile));
|
| + registrar_.Remove(this,
|
| + extensions::NOTIFICATION_EXTENSION_MESSAGE_ACKED,
|
| + content::Source<content::BrowserContext>(profile));
|
| +}
|
| +
|
| +void WakeOnWifiManager::OnSuspendImminent(bool dark_suspend) {
|
| + if (suspend_is_pending_) {
|
| + LOG(WARNING) << "OnSuspendImminent called while previous suspend attempt "
|
| + << "is still pending.";
|
| + }
|
| +
|
| + suspend_is_pending_ = true;
|
| + power_manager_callback_ =
|
| + DBusThreadManager::Get()
|
| + ->GetPowerManagerClient()
|
| + ->GetSuspendReadinessCallback();
|
| +
|
| + suspend_readiness_callback_.Reset(
|
| + base::Bind(&WakeOnWifiManager::MaybeReportSuspendReadiness,
|
| + weak_ptr_factory_.GetWeakPtr()));
|
| +
|
| + base::MessageLoopProxy::current()->PostDelayedTask(
|
| + FROM_HERE,
|
| + suspend_readiness_callback_.callback(),
|
| + dark_suspend ? base::TimeDelta::FromSeconds(1) : base::TimeDelta());
|
| +}
|
| +
|
| +void WakeOnWifiManager::MaybeReportSuspendReadiness() {
|
| + LOG(WARNING) << "MaybeReportSuspendReadiness. keepalive count = "
|
| + << unacked_extension_messages_.size();
|
| + if (!suspend_is_pending_ || unacked_extension_messages_.size() > 0 ||
|
| + power_manager_callback_.is_null())
|
| + return;
|
| +
|
| + suspend_is_pending_ = false;
|
| + power_manager_callback_.Run();
|
| + power_manager_callback_.Reset();
|
| +}
|
| +
|
| +void WakeOnWifiManager::OnExtensionMessageDispatched(
|
| + extensions::EventRouter::DispatchDetails* details) {
|
| + if (details->event_name_ != extensions::api::gcm::OnMessage::kEventName)
|
| + return;
|
| +
|
| + if (gcm_extensions_.find(details->extension_id_) == gcm_extensions_.end())
|
| + return;
|
| +
|
| + unacked_extension_messages_.insert(details->message_id_);
|
| +}
|
| +
|
| +void WakeOnWifiManager::OnExtensionMessageAcked(int message_id) {
|
| + if (unacked_extension_messages_.erase(message_id) > 0)
|
| + MaybeReportSuspendReadiness();
|
| +}
|
| +
|
| +void WakeOnWifiManager::OnExtensionSystemReady(Profile* profile) {
|
| + scoped_ptr<extensions::ExtensionSet> installed_set =
|
| + extensions::ExtensionRegistry::Get(profile)
|
| + ->GenerateInstalledExtensionsSet();
|
| +
|
| + for (const auto& extension_refptr : *installed_set) {
|
| + OnExtensionLoaded(profile, extension_refptr.get());
|
| + }
|
| }
|
|
|
| } // namespace chromeos
|
|
|