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

Side by Side Diff: chrome/browser/push_messaging/push_messaging_service_impl.cc

Issue 1099093003: Push API: Forced notifications should use Notifications database (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Also write forced notifications to database Created 5 years, 8 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/push_messaging/push_messaging_service_impl.h" 5 #include "chrome/browser/push_messaging/push_messaging_service_impl.h"
6 6
7 #include <bitset> 7 #include <bitset>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/barrier_closure.h" 10 #include "base/barrier_closure.h"
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/bind_helpers.h" 12 #include "base/bind_helpers.h"
13 #include "base/bind_to_current_loop.h"
13 #include "base/command_line.h" 14 #include "base/command_line.h"
14 #include "base/logging.h" 15 #include "base/logging.h"
15 #include "base/metrics/histogram.h" 16 #include "base/metrics/histogram.h"
16 #include "base/prefs/pref_service.h" 17 #include "base/prefs/pref_service.h"
17 #include "base/strings/string_util.h" 18 #include "base/strings/string_util.h"
18 #include "base/strings/utf_string_conversions.h" 19 #include "base/strings/utf_string_conversions.h"
19 #include "chrome/browser/browser_process.h" 20 #include "chrome/browser/browser_process.h"
20 #include "chrome/browser/notifications/notification_ui_manager.h" 21 #include "chrome/browser/notifications/notification_ui_manager.h"
21 #include "chrome/browser/notifications/platform_notification_service_impl.h" 22 #include "chrome/browser/notifications/platform_notification_service_impl.h"
22 #include "chrome/browser/profiles/profile.h" 23 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/push_messaging/push_messaging_application_id.h" 24 #include "chrome/browser/push_messaging/push_messaging_application_id.h"
24 #include "chrome/browser/push_messaging/push_messaging_constants.h" 25 #include "chrome/browser/push_messaging/push_messaging_constants.h"
25 #include "chrome/browser/push_messaging/push_messaging_permission_context.h" 26 #include "chrome/browser/push_messaging/push_messaging_permission_context.h"
26 #include "chrome/browser/push_messaging/push_messaging_permission_context_factor y.h" 27 #include "chrome/browser/push_messaging/push_messaging_permission_context_factor y.h"
27 #include "chrome/browser/push_messaging/push_messaging_service_factory.h" 28 #include "chrome/browser/push_messaging/push_messaging_service_factory.h"
28 #include "chrome/browser/services/gcm/gcm_profile_service.h" 29 #include "chrome/browser/services/gcm/gcm_profile_service.h"
29 #include "chrome/browser/services/gcm/gcm_profile_service_factory.h" 30 #include "chrome/browser/services/gcm/gcm_profile_service_factory.h"
30 #include "chrome/common/chrome_switches.h" 31 #include "chrome/common/chrome_switches.h"
31 #include "chrome/common/pref_names.h" 32 #include "chrome/common/pref_names.h"
32 #include "chrome/grit/generated_resources.h" 33 #include "chrome/grit/generated_resources.h"
33 #include "components/content_settings/core/browser/host_content_settings_map.h" 34 #include "components/content_settings/core/browser/host_content_settings_map.h"
34 #include "components/content_settings/core/common/permission_request_id.h" 35 #include "components/content_settings/core/common/permission_request_id.h"
35 #include "components/gcm_driver/gcm_driver.h" 36 #include "components/gcm_driver/gcm_driver.h"
36 #include "components/pref_registry/pref_registry_syncable.h" 37 #include "components/pref_registry/pref_registry_syncable.h"
37 #include "components/rappor/rappor_utils.h" 38 #include "components/rappor/rappor_utils.h"
38 #include "content/public/browser/browser_context.h" 39 #include "content/public/browser/browser_context.h"
39 #include "content/public/browser/browser_thread.h" 40 #include "content/public/browser/browser_thread.h"
41 #include "content/public/browser/notification_database_data.h"
42 #include "content/public/browser/platform_notification_context.h"
40 #include "content/public/browser/render_frame_host.h" 43 #include "content/public/browser/render_frame_host.h"
41 #include "content/public/browser/service_worker_context.h" 44 #include "content/public/browser/service_worker_context.h"
42 #include "content/public/browser/storage_partition.h" 45 #include "content/public/browser/storage_partition.h"
43 #include "content/public/browser/web_contents.h" 46 #include "content/public/browser/web_contents.h"
44 #include "content/public/common/child_process_host.h" 47 #include "content/public/common/child_process_host.h"
45 #include "content/public/common/content_switches.h" 48 #include "content/public/common/content_switches.h"
46 #include "content/public/common/platform_notification_data.h" 49 #include "content/public/common/platform_notification_data.h"
47 #include "content/public/common/push_messaging_status.h" 50 #include "content/public/common/push_messaging_status.h"
48 #include "third_party/skia/include/core/SkBitmap.h" 51 #include "third_party/skia/include/core/SkBitmap.h"
49 #include "ui/base/l10n/l10n_util.h" 52 #include "ui/base/l10n/l10n_util.h"
50 53
51 #if defined(OS_ANDROID) 54 #if defined(OS_ANDROID)
52 #include "chrome/browser/ui/android/tab_model/tab_model.h" 55 #include "chrome/browser/ui/android/tab_model/tab_model.h"
53 #include "chrome/browser/ui/android/tab_model/tab_model_list.h" 56 #include "chrome/browser/ui/android/tab_model/tab_model_list.h"
54 #else 57 #else
55 #include "chrome/browser/ui/browser.h" 58 #include "chrome/browser/ui/browser.h"
56 #include "chrome/browser/ui/browser_iterator.h" 59 #include "chrome/browser/ui/browser_iterator.h"
57 #include "chrome/browser/ui/tabs/tab_strip_model.h" 60 #include "chrome/browser/ui/tabs/tab_strip_model.h"
58 #endif 61 #endif
59 62
63 using content::BrowserThread;
64
60 namespace { 65 namespace {
61 const int kMaxRegistrations = 1000000; 66 const int kMaxRegistrations = 1000000;
62 67
63 void RecordDeliveryStatus(content::PushDeliveryStatus status) { 68 void RecordDeliveryStatus(content::PushDeliveryStatus status) {
64 UMA_HISTOGRAM_ENUMERATION("PushMessaging.DeliveryStatus", 69 UMA_HISTOGRAM_ENUMERATION("PushMessaging.DeliveryStatus",
65 status, 70 status,
66 content::PUSH_DELIVERY_STATUS_LAST + 1); 71 content::PUSH_DELIVERY_STATUS_LAST + 1);
67 } 72 }
68 73
69 void RecordUserVisibleStatus(content::PushUserVisibleStatus status) { 74 void RecordUserVisibleStatus(content::PushUserVisibleStatus status) {
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 base::Bind(&UnregisterCallbackToClosure, 281 base::Bind(&UnregisterCallbackToClosure,
277 message_handled_closure)); 282 message_handled_closure));
278 break; 283 break;
279 } 284 }
280 RecordDeliveryStatus(status); 285 RecordDeliveryStatus(status);
281 } 286 }
282 287
283 void PushMessagingServiceImpl::RequireUserVisibleUX( 288 void PushMessagingServiceImpl::RequireUserVisibleUX(
284 const GURL& requesting_origin, int64 service_worker_registration_id, 289 const GURL& requesting_origin, int64 service_worker_registration_id,
285 const base::Closure& message_handled_closure) { 290 const base::Closure& message_handled_closure) {
291 DCHECK_CURRENTLY_ON(BrowserThread::UI);
286 #if defined(ENABLE_NOTIFICATIONS) 292 #if defined(ENABLE_NOTIFICATIONS)
287 // TODO(johnme): Relax this heuristic slightly. 293 // TODO(johnme): Relax this heuristic slightly.
288 PlatformNotificationServiceImpl* notification_service = 294 scoped_refptr<content::PlatformNotificationContext> notification_context =
289 PlatformNotificationServiceImpl::GetInstance(); 295 content::BrowserContext::GetStoragePartitionForSite(
290 // Can't use g_browser_process->notification_ui_manager(), since the test uses 296 profile_, requesting_origin)->GetPlatformNotificationContext();
291 // PlatformNotificationServiceImpl::SetNotificationUIManagerForTesting. 297 BrowserThread::PostTask(
292 // TODO(peter): Remove the need to use both APIs here once Notification.get() 298 BrowserThread::IO, FROM_HERE,
293 // is supported. 299 base::Bind(&content::PlatformNotificationContext
294 int notification_count = notification_service->GetNotificationUIManager()-> 300 ::ReadAllNotificationDataForServiceWorkerRegistration,
295 GetAllIdsByProfileAndSourceOrigin(profile_, requesting_origin).size(); 301 notification_context,
302 requesting_origin, service_worker_registration_id,
303 base::BindToCurrentLoop(base::Bind(
304 &PushMessagingServiceImpl::DidGetNotificationsShowing,
305 weak_factory_.GetWeakPtr(),
306 requesting_origin, service_worker_registration_id,
307 message_handled_closure))));
308 #else
309 message_handled_closure.Run();
310 #endif // defined(ENABLE_NOTIFICATIONS)
311 }
312
313 void PushMessagingServiceImpl::DidGetNotificationsShowing(
314 const GURL& requesting_origin, int64 service_worker_registration_id,
315 const base::Closure& message_handled_closure,
316 bool success, const std::vector<content::NotificationDatabaseData>& data) {
317 DCHECK_CURRENTLY_ON(BrowserThread::UI);
296 // TODO(johnme): Hiding an existing notification should also count as a useful 318 // TODO(johnme): Hiding an existing notification should also count as a useful
297 // user-visible action done in response to a push message - but make sure that 319 // user-visible action done in response to a push message - but make sure that
298 // sending two messages in rapid succession which show then hide a 320 // sending two messages in rapid succession which show then hide a
299 // notification doesn't count. 321 // notification doesn't count.
322 int notification_count = success ? data.size() : 0;
300 bool notification_shown = notification_count > 0; 323 bool notification_shown = notification_count > 0;
301 324
302 bool notification_needed = true; 325 bool notification_needed = true;
303 // Sites with a currently visible tab don't need to show notifications. 326 // Sites with a currently visible tab don't need to show notifications.
304 #if defined(OS_ANDROID) 327 #if defined(OS_ANDROID)
305 for (auto it = TabModelList::begin(); it != TabModelList::end(); ++it) { 328 for (auto it = TabModelList::begin(); it != TabModelList::end(); ++it) {
306 Profile* profile = (*it)->GetProfile(); 329 Profile* profile = (*it)->GetProfile();
307 content::WebContents* active_web_contents = 330 content::WebContents* active_web_contents =
308 (*it)->GetActiveWebContents(); 331 (*it)->GetActiveWebContents();
309 #else 332 #else
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 base::Bind(&PushMessagingServiceImpl::DidGetNotificationsShown, 376 base::Bind(&PushMessagingServiceImpl::DidGetNotificationsShown,
354 weak_factory_.GetWeakPtr(), 377 weak_factory_.GetWeakPtr(),
355 requesting_origin, service_worker_registration_id, 378 requesting_origin, service_worker_registration_id,
356 notification_shown, notification_needed, 379 notification_shown, notification_needed,
357 message_handled_closure)); 380 message_handled_closure));
358 } else { 381 } else {
359 RecordUserVisibleStatus( 382 RecordUserVisibleStatus(
360 content::PUSH_USER_VISIBLE_STATUS_NOT_REQUIRED_AND_NOT_SHOWN); 383 content::PUSH_USER_VISIBLE_STATUS_NOT_REQUIRED_AND_NOT_SHOWN);
361 message_handled_closure.Run(); 384 message_handled_closure.Run();
362 } 385 }
363 #else
364 message_handled_closure.Run();
365 #endif // defined(ENABLE_NOTIFICATIONS)
366 } 386 }
367 387
368 static void IgnoreResult(bool unused) { 388 static void IgnoreResult(bool unused) {
369 } 389 }
370 390
371 void PushMessagingServiceImpl::DidGetNotificationsShown( 391 void PushMessagingServiceImpl::DidGetNotificationsShown(
372 const GURL& requesting_origin, int64 service_worker_registration_id, 392 const GURL& requesting_origin, int64 service_worker_registration_id,
373 bool notification_shown, bool notification_needed, 393 bool notification_shown, bool notification_needed,
374 const base::Closure& message_handled_closure, 394 const base::Closure& message_handled_closure,
375 const std::string& data, bool success, bool not_found) { 395 const std::string& data, bool success, bool not_found) {
396 DCHECK_CURRENTLY_ON(BrowserThread::UI);
376 content::ServiceWorkerContext* service_worker_context = 397 content::ServiceWorkerContext* service_worker_context =
377 content::BrowserContext::GetStoragePartitionForSite( 398 content::BrowserContext::GetStoragePartitionForSite(
378 profile_, requesting_origin)->GetServiceWorkerContext(); 399 profile_, requesting_origin)->GetServiceWorkerContext();
379 400
380 // We remember whether the last (up to) 10 pushes showed notifications. 401 // We remember whether the last (up to) 10 pushes showed notifications.
381 const size_t MISSED_NOTIFICATIONS_LENGTH = 10; 402 const size_t MISSED_NOTIFICATIONS_LENGTH = 10;
382 // data is a string like "0001000", where '0' means shown, and '1' means 403 // data is a string like "0001000", where '0' means shown, and '1' means
383 // needed but not shown. We manipulate it in bitset form. 404 // needed but not shown. We manipulate it in bitset form.
384 std::bitset<MISSED_NOTIFICATIONS_LENGTH> missed_notifications(data); 405 std::bitset<MISSED_NOTIFICATIONS_LENGTH> missed_notifications(data);
385 406
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 // TODO(johnme): The generic notification should probably automatically 446 // TODO(johnme): The generic notification should probably automatically
426 // close itself when the next push message arrives? 447 // close itself when the next push message arrives?
427 content::PlatformNotificationData notification_data; 448 content::PlatformNotificationData notification_data;
428 // TODO(johnme): Switch to FormatOriginForDisplay from crbug.com/402698 449 // TODO(johnme): Switch to FormatOriginForDisplay from crbug.com/402698
429 notification_data.title = base::UTF8ToUTF16(requesting_origin.host()); 450 notification_data.title = base::UTF8ToUTF16(requesting_origin.host());
430 notification_data.direction = 451 notification_data.direction =
431 content::PlatformNotificationData::NotificationDirectionLeftToRight; 452 content::PlatformNotificationData::NotificationDirectionLeftToRight;
432 notification_data.body = 453 notification_data.body =
433 l10n_util::GetStringUTF16(IDS_PUSH_MESSAGING_GENERIC_NOTIFICATION_BODY); 454 l10n_util::GetStringUTF16(IDS_PUSH_MESSAGING_GENERIC_NOTIFICATION_BODY);
434 notification_data.tag = kPushMessagingForcedNotificationTag; 455 notification_data.tag = kPushMessagingForcedNotificationTag;
435 notification_data.icon = GURL(); // TODO(johnme): Better icon? 456 notification_data.icon = GURL();
436 notification_data.silent = true; 457 notification_data.silent = true;
437 PlatformNotificationServiceImpl* notification_service = 458
438 PlatformNotificationServiceImpl::GetInstance(); 459 content::NotificationDatabaseData database_data;
439 notification_service->DisplayPersistentNotification( 460 database_data.origin = requesting_origin;
461 database_data.service_worker_registration_id =
462 service_worker_registration_id;
463 database_data.notification_data = notification_data;
464
465 scoped_refptr<content::PlatformNotificationContext> notification_context =
466 content::BrowserContext::GetStoragePartitionForSite(
467 profile_, requesting_origin)->GetPlatformNotificationContext();
468 BrowserThread::PostTask(
469 BrowserThread::IO, FROM_HERE,
470 base::Bind(&content::PlatformNotificationContext::WriteNotificationData,
471 notification_context,
472 requesting_origin, database_data,
473 base::BindToCurrentLoop(base::Bind(
474 &PushMessagingServiceImpl::DidWriteNotificationData,
475 weak_factory_.GetWeakPtr(),
476 requesting_origin, notification_data,
477 message_handled_closure))));
478 }
479
480 void PushMessagingServiceImpl::DidWriteNotificationData(
481 const GURL& requesting_origin,
482 const content::PlatformNotificationData& notification_data,
483 const base::Closure& message_handled_closure,
484 bool success,
485 int64_t persistent_notification_id) {
486 DCHECK_CURRENTLY_ON(BrowserThread::UI);
487 if (!success) {
488 DLOG(ERROR) << "Writing forced notification to database should rarely fail";
489 message_handled_closure.Run();
490 return;
491 }
492 PlatformNotificationServiceImpl::GetInstance()->DisplayPersistentNotification(
440 profile_, 493 profile_,
441 service_worker_registration_id, 494 persistent_notification_id,
442 requesting_origin, 495 requesting_origin,
443 SkBitmap() /* icon */, 496 SkBitmap() /* icon */,
444 notification_data); 497 notification_data);
445 message_handled_closure.Run(); 498 message_handled_closure.Run();
446 } 499 }
447 500
448 void PushMessagingServiceImpl::SetMessageCallbackForTesting( 501 void PushMessagingServiceImpl::SetMessageCallbackForTesting(
449 const base::Closure& callback) { 502 const base::Closure& callback) {
450 message_callback_for_testing_ = callback; 503 message_callback_for_testing_ = callback;
451 } 504 }
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after
820 CONTENT_SETTING_ALLOW; 873 CONTENT_SETTING_ALLOW;
821 } 874 }
822 875
823 gcm::GCMDriver* PushMessagingServiceImpl::GetGCMDriver() const { 876 gcm::GCMDriver* PushMessagingServiceImpl::GetGCMDriver() const {
824 gcm::GCMProfileService* gcm_profile_service = 877 gcm::GCMProfileService* gcm_profile_service =
825 gcm::GCMProfileServiceFactory::GetForProfile(profile_); 878 gcm::GCMProfileServiceFactory::GetForProfile(profile_);
826 CHECK(gcm_profile_service); 879 CHECK(gcm_profile_service);
827 CHECK(gcm_profile_service->driver()); 880 CHECK(gcm_profile_service->driver());
828 return gcm_profile_service->driver(); 881 return gcm_profile_service->driver();
829 } 882 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698