Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(48)

Side by Side Diff: chrome/browser/chromeos/net/wake_on_wifi_manager.cc

Issue 823703004: Tracking push events for lucid sleep (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Version 2 with NotificationService Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/net/wake_on_wifi_manager.h" 5 #include "chrome/browser/chromeos/net/wake_on_wifi_manager.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/containers/scoped_ptr_hash_map.h" 10 #include "base/containers/scoped_ptr_hash_map.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/macros.h" 12 #include "base/macros.h"
13 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/scoped_ptr.h"
14 #include "base/message_loop/message_loop_proxy.h"
14 #include "base/sys_info.h" 15 #include "base/sys_info.h"
15 #include "base/values.h" 16 #include "base/values.h"
16 #include "chrome/browser/chrome_notification_types.h" 17 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/services/gcm/gcm_profile_service.h" 19 #include "chrome/browser/services/gcm/gcm_profile_service.h"
19 #include "chrome/browser/services/gcm/gcm_profile_service_factory.h" 20 #include "chrome/browser/services/gcm/gcm_profile_service_factory.h"
21 #include "chrome/common/extensions/api/gcm.h"
20 #include "chromeos/chromeos_switches.h" 22 #include "chromeos/chromeos_switches.h"
23 #include "chromeos/dbus/dbus_thread_manager.h"
21 #include "chromeos/login/login_state.h" 24 #include "chromeos/login/login_state.h"
22 #include "chromeos/network/device_state.h" 25 #include "chromeos/network/device_state.h"
23 #include "chromeos/network/network_device_handler.h" 26 #include "chromeos/network/network_device_handler.h"
24 #include "chromeos/network/network_handler.h" 27 #include "chromeos/network/network_handler.h"
25 #include "chromeos/network/network_state_handler.h" 28 #include "chromeos/network/network_state_handler.h"
26 #include "chromeos/network/network_type_pattern.h" 29 #include "chromeos/network/network_type_pattern.h"
27 #include "components/gcm_driver/gcm_connection_observer.h" 30 #include "components/gcm_driver/gcm_connection_observer.h"
28 #include "components/gcm_driver/gcm_driver.h" 31 #include "components/gcm_driver/gcm_driver.h"
32 #include "content/public/browser/browser_context.h"
29 #include "content/public/browser/browser_thread.h" 33 #include "content/public/browser/browser_thread.h"
30 #include "content/public/browser/notification_service.h" 34 #include "content/public/browser/notification_service.h"
31 #include "content/public/browser/notification_source.h" 35 #include "content/public/browser/notification_source.h"
36 #include "extensions/browser/extension_registry.h"
37 #include "extensions/browser/extension_system.h"
38 #include "extensions/common/extension.h"
39 #include "extensions/common/extension_set.h"
40 #include "extensions/common/one_shot_event.h"
41 #include "extensions/common/permissions/api_permission.h"
42 #include "extensions/common/permissions/permissions_data.h"
32 #include "net/base/ip_endpoint.h" 43 #include "net/base/ip_endpoint.h"
33 #include "third_party/cros_system_api/dbus/service_constants.h" 44 #include "third_party/cros_system_api/dbus/service_constants.h"
34 45
35 namespace chromeos { 46 namespace chromeos {
36 47
37 namespace { 48 namespace {
38 49
39 const char kWakeOnNone[] = "none"; 50 const char kWakeOnNone[] = "none";
40 const char kWakeOnPacket[] = "packet"; 51 const char kWakeOnPacket[] = "packet";
41 const char kWakeOnSsid[] = "ssid"; 52 const char kWakeOnSsid[] = "ssid";
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 145
135 // static 146 // static
136 WakeOnWifiManager* WakeOnWifiManager::Get() { 147 WakeOnWifiManager* WakeOnWifiManager::Get() {
137 DCHECK(g_wake_on_wifi_manager); 148 DCHECK(g_wake_on_wifi_manager);
138 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 149 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
139 return g_wake_on_wifi_manager; 150 return g_wake_on_wifi_manager;
140 } 151 }
141 152
142 WakeOnWifiManager::WakeOnWifiManager() 153 WakeOnWifiManager::WakeOnWifiManager()
143 : current_feature_(WakeOnWifiManager::INVALID), 154 : current_feature_(WakeOnWifiManager::INVALID),
155 suspend_is_pending_(false),
144 weak_ptr_factory_(this) { 156 weak_ptr_factory_(this) {
157 LOG(WARNING) << "CONSTRUCTOR";
145 // This class must be constructed before any users are logged in, i.e., before 158 // This class must be constructed before any users are logged in, i.e., before
146 // any profiles are created or added to the ProfileManager. Additionally, 159 // any profiles are created or added to the ProfileManager. Additionally,
147 // IsUserLoggedIn always returns true when we are not running on a Chrome OS 160 // IsUserLoggedIn always returns true when we are not running on a Chrome OS
148 // device so this check should only run on real devices. 161 // device so this check should only run on real devices.
149 CHECK(!base::SysInfo::IsRunningOnChromeOS() || 162 CHECK(!base::SysInfo::IsRunningOnChromeOS() ||
150 !LoginState::Get()->IsUserLoggedIn()); 163 !LoginState::Get()->IsUserLoggedIn());
151 DCHECK(!g_wake_on_wifi_manager); 164 DCHECK(!g_wake_on_wifi_manager);
152 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 165 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
153 166
154 g_wake_on_wifi_manager = this; 167 g_wake_on_wifi_manager = this;
155 168
156 registrar_.Add(this, 169 registrar_.Add(this,
157 chrome::NOTIFICATION_PROFILE_ADDED, 170 chrome::NOTIFICATION_PROFILE_ADDED,
158 content::NotificationService::AllBrowserContextsAndSources()); 171 content::NotificationService::AllBrowserContextsAndSources());
159 registrar_.Add(this, 172 registrar_.Add(this,
160 chrome::NOTIFICATION_PROFILE_DESTROYED, 173 chrome::NOTIFICATION_PROFILE_DESTROYED,
161 content::NotificationService::AllBrowserContextsAndSources()); 174 content::NotificationService::AllBrowserContextsAndSources());
162 175
163 NetworkHandler::Get() 176 NetworkHandler::Get()
164 ->network_device_handler() 177 ->network_device_handler()
165 ->RemoveAllWifiWakeOnPacketConnections( 178 ->RemoveAllWifiWakeOnPacketConnections(
166 base::Bind(&base::DoNothing), 179 base::Bind(&base::DoNothing),
167 network_handler::ErrorCallback()); 180 network_handler::ErrorCallback());
168 181
169 if (!switches::WakeOnWifiEnabled()) 182 if (!switches::WakeOnWifiEnabled())
170 return; 183 return;
184 LOG(WARNING) << "Adding WakeOnWifiManager as PowerManagerClient::Observer.";
185 DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(this);
171 186
172 const DeviceState* device = 187 const DeviceState* device =
173 NetworkHandler::Get()->network_state_handler()->GetDeviceStateByType( 188 NetworkHandler::Get()->network_state_handler()->GetDeviceStateByType(
174 NetworkTypePattern::WiFi()); 189 NetworkTypePattern::WiFi());
175 if (!device) 190 if (!device)
176 return; 191 return;
177 // Get device properties to check whether wake-on-wifi is supported. 192 // Get device properties to check whether wake-on-wifi is supported.
178 NetworkHandler::Get()->network_device_handler()->GetDeviceProperties( 193 NetworkHandler::Get()->network_device_handler()->GetDeviceProperties(
179 device->path(), 194 device->path(),
180 base::Bind(&WakeOnWifiManager::GetDevicePropertiesCallback, 195 base::Bind(&WakeOnWifiManager::GetDevicePropertiesCallback,
181 weak_ptr_factory_.GetWeakPtr()), 196 weak_ptr_factory_.GetWeakPtr()),
182 network_handler::ErrorCallback()); 197 network_handler::ErrorCallback());
183 } 198 }
184 199
185 WakeOnWifiManager::~WakeOnWifiManager() { 200 WakeOnWifiManager::~WakeOnWifiManager() {
186 DCHECK(g_wake_on_wifi_manager); 201 DCHECK(g_wake_on_wifi_manager);
187 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 202 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
188 g_wake_on_wifi_manager = NULL; 203 g_wake_on_wifi_manager = NULL;
204
205 for (const auto& kv_pair : connection_observers_) {
206 Profile* profile = kv_pair.first;
207 extensions::ExtensionRegistry::Get(profile)->RemoveObserver(this);
208 }
209
210 if (switches::WakeOnWifiEnabled())
211 DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(this);
189 } 212 }
190 213
191 void WakeOnWifiManager::OnPreferenceChanged( 214 void WakeOnWifiManager::OnPreferenceChanged(
192 WakeOnWifiManager::WakeOnWifiFeature feature) { 215 WakeOnWifiManager::WakeOnWifiFeature feature) {
193 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 216 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
194 if (current_feature_ == NOT_SUPPORTED) 217 if (current_feature_ == NOT_SUPPORTED)
195 return; 218 return;
196 if (!switches::WakeOnWifiEnabled()) 219 if (!switches::WakeOnWifiEnabled())
197 feature = WAKE_ON_NONE; 220 feature = WAKE_ON_NONE;
198 if (feature == current_feature_) 221 if (feature == current_feature_)
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 if (properties.GetString(shill::kWakeOnWiFiFeaturesEnabledProperty, 261 if (properties.GetString(shill::kWakeOnWiFiFeaturesEnabledProperty,
239 &enabled) && 262 &enabled) &&
240 enabled == shill::kWakeOnWiFiFeaturesEnabledNotSupported) { 263 enabled == shill::kWakeOnWiFiFeaturesEnabledNotSupported) {
241 current_feature_ = NOT_SUPPORTED; 264 current_feature_ = NOT_SUPPORTED;
242 } 265 }
243 } 266 }
244 267
245 void WakeOnWifiManager::Observe(int type, 268 void WakeOnWifiManager::Observe(int type,
246 const content::NotificationSource& source, 269 const content::NotificationSource& source,
247 const content::NotificationDetails& details) { 270 const content::NotificationDetails& details) {
271 using DispatchDetails = extensions::EventRouter::DispatchDetails;
248 switch (type) { 272 switch (type) {
249 case chrome::NOTIFICATION_PROFILE_ADDED: { 273 case chrome::NOTIFICATION_PROFILE_ADDED: {
250 OnProfileAdded(content::Source<Profile>(source).ptr()); 274 OnProfileAdded(content::Source<Profile>(source).ptr());
251 break; 275 break;
252 } 276 }
253 case chrome::NOTIFICATION_PROFILE_DESTROYED: { 277 case chrome::NOTIFICATION_PROFILE_DESTROYED: {
254 OnProfileDestroyed(content::Source<Profile>(source).ptr()); 278 OnProfileDestroyed(content::Source<Profile>(source).ptr());
255 break; 279 break;
256 } 280 }
281 case extensions::NOTIFICATION_EXTENSION_MESSAGE_DISPATCHED: {
282 OnExtensionMessageDispatched(
283 content::Details<DispatchDetails>(details).ptr());
284 break;
285 }
286 case extensions::NOTIFICATION_EXTENSION_MESSAGE_ACKED: {
287 OnExtensionMessageAcked(*(content::Details<int>(details).ptr()));
288 break;
289 }
257 default: 290 default:
258 NOTREACHED(); 291 NOTREACHED();
259 } 292 }
260 } 293 }
261 294
295 void WakeOnWifiManager::OnExtensionLoaded(
296 content::BrowserContext* context, const extensions::Extension* extension) {
297 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
298 if (!extension->permissions_data()->HasAPIPermission(
299 extensions::APIPermission::kGcm))
300 return;
301
302 gcm_extensions_.insert(extension->id());
303 }
304
305 void WakeOnWifiManager::SuspendImminent() {
306 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
307 OnSuspendImminent(false);
308 }
309
310 void WakeOnWifiManager::SuspendDone(const base::TimeDelta& duration) {
311 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
312 suspend_is_pending_ = false;
313 power_manager_callback_.Reset();
314 suspend_readiness_callback_.Cancel();
315 }
316
317 void WakeOnWifiManager::DarkSuspendImminent() {
318 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
319 OnSuspendImminent(true);
320 }
321
262 void WakeOnWifiManager::OnProfileAdded(Profile* profile) { 322 void WakeOnWifiManager::OnProfileAdded(Profile* profile) {
263 // add will do nothing if |profile| already exists in |connection_observers_|. 323 // add will do nothing if |profile| already exists in |connection_observers_|.
264 auto result = connection_observers_.add( 324 auto result = connection_observers_.add(
265 profile, 325 profile,
266 make_scoped_ptr( 326 make_scoped_ptr(
267 new WakeOnWifiManager::WakeOnPacketConnectionObserver(profile))); 327 new WakeOnWifiManager::WakeOnPacketConnectionObserver(profile)));
268 328
269 if (result.second) { 329 if (result.second) {
270 // This is a profile we haven't seen before. 330 // This is a profile we haven't seen before.
271 gcm::GCMProfileServiceFactory::GetForProfile(profile) 331 gcm::GCMProfileServiceFactory::GetForProfile(profile)
272 ->driver() 332 ->driver()
273 ->WakeFromSuspendForHeartbeat( 333 ->WakeFromSuspendForHeartbeat(
274 IsWakeOnPacketEnabled(current_feature_)); 334 IsWakeOnPacketEnabled(current_feature_));
335
336 // The ExtensionRegistry will call OnExtensionLoaded whenever the user
337 // installs and enables a new extension.
338 extensions::ExtensionRegistry::Get(profile)->AddObserver(this);
339
340 // OnExtensionLoaded is not called for extensions that the user had already
341 // installed and enabled. So we wait until the ExtensionSystem for the
342 // profile is ready and then iterate through the installed extensions,
343 // manually calling OnExtensionLoaded for each of them.
344 extensions::ExtensionSystem::Get(profile)->ready().Post(
345 FROM_HERE,
346 base::Bind(&WakeOnWifiManager::OnExtensionSystemReady,
347 weak_ptr_factory_.GetWeakPtr(), profile));
348
349 registrar_.Add(this,
350 extensions::NOTIFICATION_EXTENSION_MESSAGE_DISPATCHED,
351 content::Source<content::BrowserContext>(profile));
352 registrar_.Add(this,
353 extensions::NOTIFICATION_EXTENSION_MESSAGE_ACKED,
354 content::Source<content::BrowserContext>(profile));
275 } 355 }
276 } 356 }
277 357
278 void WakeOnWifiManager::OnProfileDestroyed(Profile* profile) { 358 void WakeOnWifiManager::OnProfileDestroyed(Profile* profile) {
279 connection_observers_.erase(profile); 359 connection_observers_.erase(profile);
360
361 extensions::ExtensionRegistry::Get(profile)->RemoveObserver(this);
362 registrar_.Remove(this,
363 extensions::NOTIFICATION_EXTENSION_MESSAGE_DISPATCHED,
364 content::Source<content::BrowserContext>(profile));
365 registrar_.Remove(this,
366 extensions::NOTIFICATION_EXTENSION_MESSAGE_ACKED,
367 content::Source<content::BrowserContext>(profile));
368 }
369
370 void WakeOnWifiManager::OnSuspendImminent(bool dark_suspend) {
371 if (suspend_is_pending_) {
372 LOG(WARNING) << "OnSuspendImminent called while previous suspend attempt "
373 << "is still pending.";
374 }
375
376 suspend_is_pending_ = true;
377 power_manager_callback_ =
378 DBusThreadManager::Get()
379 ->GetPowerManagerClient()
380 ->GetSuspendReadinessCallback();
381
382 suspend_readiness_callback_.Reset(
383 base::Bind(&WakeOnWifiManager::MaybeReportSuspendReadiness,
384 weak_ptr_factory_.GetWeakPtr()));
385
386 base::MessageLoopProxy::current()->PostDelayedTask(
387 FROM_HERE,
388 suspend_readiness_callback_.callback(),
389 dark_suspend ? base::TimeDelta::FromSeconds(1) : base::TimeDelta());
390 }
391
392 void WakeOnWifiManager::MaybeReportSuspendReadiness() {
393 LOG(WARNING) << "MaybeReportSuspendReadiness. keepalive count = "
394 << unacked_extension_messages_.size();
395 if (!suspend_is_pending_ || unacked_extension_messages_.size() > 0 ||
396 power_manager_callback_.is_null())
397 return;
398
399 suspend_is_pending_ = false;
400 power_manager_callback_.Run();
401 power_manager_callback_.Reset();
402 }
403
404 void WakeOnWifiManager::OnExtensionMessageDispatched(
405 extensions::EventRouter::DispatchDetails* details) {
406 if (details->event_name_ != extensions::api::gcm::OnMessage::kEventName)
407 return;
408
409 if (gcm_extensions_.find(details->extension_id_) == gcm_extensions_.end())
410 return;
411
412 unacked_extension_messages_.insert(details->message_id_);
413 }
414
415 void WakeOnWifiManager::OnExtensionMessageAcked(int message_id) {
416 if (unacked_extension_messages_.erase(message_id) > 0)
417 MaybeReportSuspendReadiness();
418 }
419
420 void WakeOnWifiManager::OnExtensionSystemReady(Profile* profile) {
421 scoped_ptr<extensions::ExtensionSet> installed_set =
422 extensions::ExtensionRegistry::Get(profile)
423 ->GenerateInstalledExtensionsSet();
424
425 for (const auto& extension_refptr : *installed_set) {
426 OnExtensionLoaded(profile, extension_refptr.get());
427 }
280 } 428 }
281 429
282 } // namespace chromeos 430 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698