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

Unified Diff: chrome/browser/services/gcm/push_messaging_service_impl.cc

Issue 955673004: Move gcm-independent parts of push messaging out of gcm namespace and directory (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: remove redundant cast Created 5 years, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/services/gcm/push_messaging_service_impl.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/services/gcm/push_messaging_service_impl.cc
diff --git a/chrome/browser/services/gcm/push_messaging_service_impl.cc b/chrome/browser/services/gcm/push_messaging_service_impl.cc
deleted file mode 100644
index b0cc76d2dfc9e7047f48987da0260ccbc6276968..0000000000000000000000000000000000000000
--- a/chrome/browser/services/gcm/push_messaging_service_impl.cc
+++ /dev/null
@@ -1,791 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/services/gcm/push_messaging_service_impl.h"
-
-#include <bitset>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/metrics/histogram.h"
-#include "base/prefs/pref_service.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/notifications/notification_ui_manager.h"
-#include "chrome/browser/notifications/platform_notification_service_impl.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/browser/services/gcm/push_messaging_application_id.h"
-#include "chrome/browser/services/gcm/push_messaging_constants.h"
-#include "chrome/browser/services/gcm/push_messaging_permission_context.h"
-#include "chrome/browser/services/gcm/push_messaging_permission_context_factory.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/grit/generated_resources.h"
-#include "components/content_settings/core/browser/host_content_settings_map.h"
-#include "components/content_settings/core/common/permission_request_id.h"
-#include "components/gcm_driver/gcm_driver.h"
-#include "components/pref_registry/pref_registry_syncable.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/service_worker_context.h"
-#include "content/public/browser/storage_partition.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/child_process_host.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/platform_notification_data.h"
-#include "content/public/common/push_messaging_status.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/base/l10n/l10n_util.h"
-
-#if defined(OS_ANDROID)
-#include "chrome/browser/ui/android/tab_model/tab_model.h"
-#include "chrome/browser/ui/android/tab_model/tab_model_list.h"
-#else
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_iterator.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#endif
-
-namespace gcm {
-
-namespace {
-const int kMaxRegistrations = 1000000;
-
-void RecordDeliveryStatus(content::PushDeliveryStatus status) {
- UMA_HISTOGRAM_ENUMERATION("PushMessaging.DeliveryStatus",
- status,
- content::PUSH_DELIVERY_STATUS_LAST + 1);
-}
-
-void RecordUserVisibleStatus(content::PushUserVisibleStatus status) {
- UMA_HISTOGRAM_ENUMERATION("PushMessaging.UserVisibleStatus",
- status,
- content::PUSH_USER_VISIBLE_STATUS_LAST + 1);
-}
-
-blink::WebPushPermissionStatus ToPushPermission(ContentSetting setting) {
- switch (setting) {
- case CONTENT_SETTING_ALLOW:
- return blink::WebPushPermissionStatusGranted;
- case CONTENT_SETTING_BLOCK:
- return blink::WebPushPermissionStatusDenied;
- case CONTENT_SETTING_ASK:
- return blink::WebPushPermissionStatusDefault;
- default:
- NOTREACHED();
- return blink::WebPushPermissionStatusDenied;
- }
-}
-
-} // namespace
-
-// static
-void PushMessagingServiceImpl::RegisterProfilePrefs(
- user_prefs::PrefRegistrySyncable* registry) {
- registry->RegisterIntegerPref(
- prefs::kPushMessagingRegistrationCount,
- 0,
- user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
- PushMessagingApplicationId::RegisterProfilePrefs(registry);
-}
-
-// static
-void PushMessagingServiceImpl::InitializeForProfile(Profile* profile) {
- // TODO(johnme): Consider whether push should be enabled in incognito.
- if (!profile || profile->IsOffTheRecord())
- return;
-
- // TODO(johnme): If push becomes enabled in incognito (and this still uses a
- // pref), be careful that this pref is read from the right profile, as prefs
- // defined in a regular profile are visible in the corresponding incognito
- // profile unless overridden.
- // TODO(johnme): Make sure this pref doesn't get out of sync after crashes.
- int count = profile->GetPrefs()->GetInteger(
- prefs::kPushMessagingRegistrationCount);
- if (count <= 0)
- return;
-
- // Create the GCMProfileService, and hence instantiate this class.
- GCMProfileService* gcm_service =
- GCMProfileServiceFactory::GetForProfile(profile);
- PushMessagingServiceImpl* push_service =
- static_cast<PushMessagingServiceImpl*>(
- gcm_service->push_messaging_service());
-
- push_service->IncreasePushRegistrationCount(count, false /* is_pending */);
-}
-
-PushMessagingServiceImpl::PushMessagingServiceImpl(
- GCMProfileService* gcm_profile_service,
- Profile* profile)
- : gcm_profile_service_(gcm_profile_service),
- profile_(profile),
- push_registration_count_(0),
- pending_push_registration_count_(0),
- weak_factory_(this) {
- // In some tests, we might end up with |profile_| being null at this point.
- // When that is the case |profile_| will be set in SetProfileForTesting(), at
- // which point the service will start to observe HostContentSettingsMap.
- if (profile_)
- profile_->GetHostContentSettingsMap()->AddObserver(this);
-}
-
-PushMessagingServiceImpl::~PushMessagingServiceImpl() {
- // TODO(johnme): If it's possible for this to be destroyed before GCMDriver,
- // then we should call RemoveAppHandler.
- profile_->GetHostContentSettingsMap()->RemoveObserver(this);
-}
-
-void PushMessagingServiceImpl::IncreasePushRegistrationCount(int add,
- bool is_pending) {
- DCHECK(add > 0);
- if (push_registration_count_ + pending_push_registration_count_ == 0) {
- gcm_profile_service_->driver()->AddAppHandler(
- kPushMessagingApplicationIdPrefix, this);
- }
- if (is_pending) {
- pending_push_registration_count_ += add;
- } else {
- push_registration_count_ += add;
- profile_->GetPrefs()->SetInteger(prefs::kPushMessagingRegistrationCount,
- push_registration_count_);
- }
-}
-
-void PushMessagingServiceImpl::DecreasePushRegistrationCount(int subtract,
- bool was_pending) {
- DCHECK(subtract > 0);
- if (was_pending) {
- pending_push_registration_count_ -= subtract;
- DCHECK(pending_push_registration_count_ >= 0);
- } else {
- push_registration_count_ -= subtract;
- DCHECK(push_registration_count_ >= 0);
- profile_->GetPrefs()->SetInteger(prefs::kPushMessagingRegistrationCount,
- push_registration_count_);
- }
- if (push_registration_count_ + pending_push_registration_count_ == 0) {
- gcm_profile_service_->driver()->RemoveAppHandler(
- kPushMessagingApplicationIdPrefix);
- }
-}
-
-bool PushMessagingServiceImpl::CanHandle(const std::string& app_id) const {
- return PushMessagingApplicationId::Get(profile_, app_id).IsValid();
-}
-
-void PushMessagingServiceImpl::ShutdownHandler() {
- // TODO(johnme): Do any necessary cleanup.
-}
-
-// OnMessage methods -----------------------------------------------------------
-
-void PushMessagingServiceImpl::OnMessage(
- const std::string& app_id,
- const GCMClient::IncomingMessage& message) {
- PushMessagingApplicationId application_id =
- PushMessagingApplicationId::Get(profile_, app_id);
- // Drop message and unregister if app id was unknown (maybe recently deleted).
- if (!application_id.IsValid()) {
- DeliverMessageCallback(app_id, GURL::EmptyGURL(), -1, message,
- content::PUSH_DELIVERY_STATUS_UNKNOWN_APP_ID);
- return;
- }
- // Drop message and unregister if |origin| has lost push permission.
- if (!HasPermission(application_id.origin())) {
- DeliverMessageCallback(app_id, application_id.origin(),
- application_id.service_worker_registration_id(),
- message,
- content::PUSH_DELIVERY_STATUS_PERMISSION_DENIED);
- return;
- }
-
- // The Push API only exposes a single string of data in the push event fired
- // on the Service Worker. When developers send messages using GCM to the Push
- // API and want to include a message payload, they must pass a single key-
- // value pair, where the key is "data" and the value is the string they want
- // to be passed to their Service Worker. For example, they could send the
- // following JSON using the HTTPS GCM API:
- // {
- // "registration_ids": ["FOO", "BAR"],
- // "data": {
- // "data": "BAZ",
- // },
- // "delay_while_idle": true,
- // }
- // TODO(johnme): Make sure this is clearly documented for developers.
- std::string data;
- // TODO(peter): Message payloads are disabled pending mandatory encryption.
- // https://crbug.com/449184
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnablePushMessagePayload)) {
- GCMClient::MessageData::const_iterator it = message.data.find("data");
- if (it != message.data.end())
- data = it->second;
- }
-
- content::BrowserContext::DeliverPushMessage(
- profile_,
- application_id.origin(),
- application_id.service_worker_registration_id(),
- data,
- base::Bind(&PushMessagingServiceImpl::DeliverMessageCallback,
- weak_factory_.GetWeakPtr(),
- application_id.app_id_guid(), application_id.origin(),
- application_id.service_worker_registration_id(), message));
-}
-
-void PushMessagingServiceImpl::DeliverMessageCallback(
- const std::string& app_id_guid,
- const GURL& requesting_origin,
- int64 service_worker_registration_id,
- const GCMClient::IncomingMessage& message,
- content::PushDeliveryStatus status) {
- // TODO(mvanouwerkerk): Show a warning in the developer console of the
- // Service Worker corresponding to app_id (and/or on an internals page).
- // TODO(mvanouwerkerk): Is there a way to recover from failure?
- switch (status) {
- // Call RequireUserVisibleUX if the message was delivered to the Service
- // Worker JS, even if the website's event handler failed (to prevent sites
- // deliberately failing in order to avoid having to show notifications).
- case content::PUSH_DELIVERY_STATUS_SUCCESS:
- case content::PUSH_DELIVERY_STATUS_EVENT_WAITUNTIL_REJECTED:
- RequireUserVisibleUX(requesting_origin, service_worker_registration_id);
- break;
- case content::PUSH_DELIVERY_STATUS_INVALID_MESSAGE:
- case content::PUSH_DELIVERY_STATUS_SERVICE_WORKER_ERROR:
- break;
- case content::PUSH_DELIVERY_STATUS_UNKNOWN_APP_ID:
- case content::PUSH_DELIVERY_STATUS_PERMISSION_DENIED:
- case content::PUSH_DELIVERY_STATUS_NO_SERVICE_WORKER:
- Unregister(app_id_guid, message.sender_id, true /* retry_on_failure */,
- UnregisterCallback());
- break;
- }
- RecordDeliveryStatus(status);
-}
-
-void PushMessagingServiceImpl::RequireUserVisibleUX(
- const GURL& requesting_origin, int64 service_worker_registration_id) {
-#if defined(ENABLE_NOTIFICATIONS)
- // TODO(johnme): Relax this heuristic slightly.
- PlatformNotificationServiceImpl* notification_service =
- PlatformNotificationServiceImpl::GetInstance();
- // Can't use g_browser_process->notification_ui_manager(), since the test uses
- // PlatformNotificationServiceImpl::SetNotificationUIManagerForTesting.
- // TODO(peter): Remove the need to use both APIs here once Notification.get()
- // is supported.
- int notification_count = notification_service->GetNotificationUIManager()->
- GetAllIdsByProfileAndSourceOrigin(profile_, requesting_origin).size();
- // TODO(johnme): Hiding an existing notification should also count as a useful
- // user-visible action done in response to a push message - but make sure that
- // sending two messages in rapid succession which show then hide a
- // notification doesn't count.
- bool notification_shown = notification_count > 0;
-
- bool notification_needed = true;
- // Sites with a currently visible tab don't need to show notifications.
-#if defined(OS_ANDROID)
- for (auto it = TabModelList::begin(); it != TabModelList::end(); ++it) {
- Profile* profile = (*it)->GetProfile();
- content::WebContents* active_web_contents =
- (*it)->GetActiveWebContents();
-#else
- for (chrome::BrowserIterator it; !it.done(); it.Next()) {
- Profile* profile = it->profile();
- content::WebContents* active_web_contents =
- it->tab_strip_model()->GetActiveWebContents();
-#endif
- if (!active_web_contents || !active_web_contents->GetMainFrame())
- continue;
-
- // Don't leak information from other profiles.
- if (profile != profile_)
- continue;
-
- // Ignore minimized windows etc.
- switch (active_web_contents->GetMainFrame()->GetVisibilityState()) {
- case blink::WebPageVisibilityStateHidden:
- case blink::WebPageVisibilityStatePrerender:
- continue;
- case blink::WebPageVisibilityStateVisible:
- break;
- }
-
- // Use the visible URL since that's the one the user is aware of (and it
- // doesn't matter whether the page loaded successfully).
- const GURL& active_url = active_web_contents->GetVisibleURL();
- if (requesting_origin == active_url.GetOrigin()) {
- notification_needed = false;
- break;
- }
-#if defined(OS_ANDROID)
- }
-#else
- }
-#endif
-
- // Don't track push messages that didn't show a notification but were exempt
- // from needing to do so.
- if (notification_shown || notification_needed) {
- content::ServiceWorkerContext* service_worker_context =
- content::BrowserContext::GetStoragePartitionForSite(
- profile_, requesting_origin)->GetServiceWorkerContext();
-
- PushMessagingService::GetNotificationsShownByLastFewPushes(
- service_worker_context, service_worker_registration_id,
- base::Bind(&PushMessagingServiceImpl::DidGetNotificationsShown,
- weak_factory_.GetWeakPtr(),
- requesting_origin, service_worker_registration_id,
- notification_shown, notification_needed));
- } else {
- RecordUserVisibleStatus(
- content::PUSH_USER_VISIBLE_STATUS_NOT_REQUIRED_AND_NOT_SHOWN);
- }
-#endif // defined(ENABLE_NOTIFICATIONS)
-}
-
-static void IgnoreResult(bool unused) {
-}
-
-void PushMessagingServiceImpl::DidGetNotificationsShown(
- const GURL& requesting_origin, int64 service_worker_registration_id,
- bool notification_shown, bool notification_needed,
- const std::string& data, bool success, bool not_found) {
- content::ServiceWorkerContext* service_worker_context =
- content::BrowserContext::GetStoragePartitionForSite(
- profile_, requesting_origin)->GetServiceWorkerContext();
-
- // We remember whether the last (up to) 10 pushes showed notifications.
- const size_t MISSED_NOTIFICATIONS_LENGTH = 10;
- // data is a string like "0001000", where '0' means shown, and '1' means
- // needed but not shown. We manipulate it in bitset form.
- std::bitset<MISSED_NOTIFICATIONS_LENGTH> missed_notifications(data);
-
- bool needed_but_not_shown = notification_needed && !notification_shown;
-
- // New entries go at the end, and old ones are shifted off the beginning once
- // the history length is exceeded.
- missed_notifications <<= 1;
- missed_notifications[0] = needed_but_not_shown;
- std::string updated_data(missed_notifications.
- to_string<char, std::string::traits_type, std::string::allocator_type>());
- PushMessagingService::SetNotificationsShownByLastFewPushes(
- service_worker_context, service_worker_registration_id,
- requesting_origin, updated_data,
- base::Bind(&IgnoreResult)); // This is a heuristic; ignore failure.
-
- if (notification_shown) {
- RecordUserVisibleStatus(
- notification_needed
- ? content::PUSH_USER_VISIBLE_STATUS_REQUIRED_AND_SHOWN
- : content::PUSH_USER_VISIBLE_STATUS_NOT_REQUIRED_BUT_SHOWN);
- return;
- }
- if (needed_but_not_shown) {
- if (missed_notifications.count() <= 1) {
- RecordUserVisibleStatus(
- content::PUSH_USER_VISIBLE_STATUS_REQUIRED_BUT_NOT_SHOWN_USED_GRACE);
- return;
- }
- RecordUserVisibleStatus(
- content::
- PUSH_USER_VISIBLE_STATUS_REQUIRED_BUT_NOT_SHOWN_GRACE_EXCEEDED);
- // The site failed to show a notification when one was needed, and they have
- // already failed once in the previous 10 push messages, so we will show a
- // generic notification. See https://crbug.com/437277.
- // TODO(johnme): The generic notification should probably automatically
- // close itself when the next push message arrives?
- content::PlatformNotificationData notification_data;
- // TODO(johnme): Switch to FormatOriginForDisplay from crbug.com/402698
- notification_data.title = base::UTF8ToUTF16(requesting_origin.host());
- notification_data.direction =
- content::PlatformNotificationData::NotificationDirectionLeftToRight;
- notification_data.body =
- l10n_util::GetStringUTF16(IDS_PUSH_MESSAGING_GENERIC_NOTIFICATION_BODY);
- notification_data.tag =
- base::ASCIIToUTF16(kPushMessagingForcedNotificationTag);
- notification_data.icon = GURL(); // TODO(johnme): Better icon?
- PlatformNotificationServiceImpl* notification_service =
- PlatformNotificationServiceImpl::GetInstance();
- notification_service->DisplayPersistentNotification(
- profile_,
- service_worker_registration_id,
- requesting_origin,
- SkBitmap() /* icon */,
- notification_data);
- }
-}
-
-// Other GCMAppHandler methods -------------------------------------------------
-
-void PushMessagingServiceImpl::OnMessagesDeleted(const std::string& app_id) {
- // TODO(mvanouwerkerk): Fire push error event on the Service Worker
- // corresponding to app_id.
-}
-
-void PushMessagingServiceImpl::OnSendError(
- const std::string& app_id,
- const GCMClient::SendErrorDetails& send_error_details) {
- NOTREACHED() << "The Push API shouldn't have sent messages upstream";
-}
-
-void PushMessagingServiceImpl::OnSendAcknowledged(
- const std::string& app_id,
- const std::string& message_id) {
- NOTREACHED() << "The Push API shouldn't have sent messages upstream";
-}
-
-// GetPushEndpoint method ------------------------------------------------------
-
-GURL PushMessagingServiceImpl::GetPushEndpoint() {
- return GURL(std::string(kPushMessagingEndpoint));
-}
-
-// Register and GetPermissionStatus methods ------------------------------------
-
-void PushMessagingServiceImpl::RegisterFromDocument(
- const GURL& requesting_origin,
- int64 service_worker_registration_id,
- const std::string& sender_id,
- int renderer_id,
- int render_frame_id,
- bool user_visible_only,
- const content::PushMessagingService::RegisterCallback& callback) {
- if (!gcm_profile_service_->driver()) {
- NOTREACHED() << "There is no GCMDriver. Has GCMProfileService shut down?";
- return;
- }
-
- PushMessagingApplicationId application_id =
- PushMessagingApplicationId::Generate(requesting_origin,
- service_worker_registration_id);
- DCHECK(application_id.IsValid());
-
- if (push_registration_count_ + pending_push_registration_count_
- >= kMaxRegistrations) {
- RegisterEnd(callback,
- std::string(),
- content::PUSH_REGISTRATION_STATUS_LIMIT_REACHED);
- return;
- }
-
- content::RenderFrameHost* render_frame_host =
- content::RenderFrameHost::FromID(renderer_id, render_frame_id);
- if (!render_frame_host)
- return;
-
- content::WebContents* web_contents =
- content::WebContents::FromRenderFrameHost(render_frame_host);
- if (!web_contents)
- return;
-
- // TODO(miguelg) need to send this over IPC when bubble support is
- // implemented.
- int bridge_id = -1;
-
- const PermissionRequestID id(
- renderer_id, web_contents->GetRoutingID(), bridge_id, GURL());
-
- gcm::PushMessagingPermissionContext* permission_context =
- gcm::PushMessagingPermissionContextFactory::GetForProfile(profile_);
-
- if (permission_context == NULL || !user_visible_only) {
- RegisterEnd(callback,
- std::string(),
- content::PUSH_REGISTRATION_STATUS_PERMISSION_DENIED);
- return;
- }
-
- // TODO(miguelg): Consider the value of |user_visible_only| when making
- // the permission request.
- // TODO(mlamouri): Move requesting Push permission over to using Mojo, and
- // re-introduce the ability of |user_gesture| when bubbles require this.
- // https://crbug.com/423770.
- permission_context->RequestPermission(
- web_contents, id, requesting_origin, true /* user_gesture */,
- base::Bind(&PushMessagingServiceImpl::DidRequestPermission,
- weak_factory_.GetWeakPtr(), application_id, sender_id,
- callback));
-}
-
-void PushMessagingServiceImpl::RegisterFromWorker(
- const GURL& requesting_origin,
- int64 service_worker_registration_id,
- const std::string& sender_id,
- const content::PushMessagingService::RegisterCallback& register_callback) {
- if (!gcm_profile_service_->driver()) {
- NOTREACHED() << "There is no GCMDriver. Has GCMProfileService shut down?";
- return;
- }
-
- PushMessagingApplicationId application_id =
- PushMessagingApplicationId::Generate(requesting_origin,
- service_worker_registration_id);
- DCHECK(application_id.IsValid());
-
- if (profile_->GetPrefs()->GetInteger(
- prefs::kPushMessagingRegistrationCount) >= kMaxRegistrations) {
- RegisterEnd(register_callback, std::string(),
- content::PUSH_REGISTRATION_STATUS_LIMIT_REACHED);
- return;
- }
-
- GURL embedding_origin = requesting_origin;
- blink::WebPushPermissionStatus permission_status =
- PushMessagingServiceImpl::GetPermissionStatus(requesting_origin,
- embedding_origin);
- if (permission_status != blink::WebPushPermissionStatusGranted) {
- RegisterEnd(register_callback, std::string(),
- content::PUSH_REGISTRATION_STATUS_PERMISSION_DENIED);
- return;
- }
-
- IncreasePushRegistrationCount(1, true /* is_pending */);
- std::vector<std::string> sender_ids(1, sender_id);
- gcm_profile_service_->driver()->Register(
- application_id.app_id_guid(), sender_ids,
- base::Bind(&PushMessagingServiceImpl::DidRegister,
- weak_factory_.GetWeakPtr(),
- application_id, register_callback));
-}
-
-blink::WebPushPermissionStatus PushMessagingServiceImpl::GetPermissionStatus(
- const GURL& requesting_origin,
- const GURL& embedding_origin) {
- PushMessagingPermissionContext* permission_context =
- PushMessagingPermissionContextFactory::GetForProfile(profile_);
- return ToPushPermission(permission_context->GetPermissionStatus(
- requesting_origin, embedding_origin));
-}
-
-void PushMessagingServiceImpl::RegisterEnd(
- const content::PushMessagingService::RegisterCallback& callback,
- const std::string& registration_id,
- content::PushRegistrationStatus status) {
- callback.Run(registration_id, status);
-}
-
-void PushMessagingServiceImpl::DidRegister(
- const PushMessagingApplicationId& application_id,
- const content::PushMessagingService::RegisterCallback& callback,
- const std::string& registration_id,
- GCMClient::Result result) {
- content::PushRegistrationStatus status =
- content::PUSH_REGISTRATION_STATUS_SERVICE_ERROR;
- switch (result) {
- case GCMClient::SUCCESS:
- status = content::PUSH_REGISTRATION_STATUS_SUCCESS_FROM_PUSH_SERVICE;
- application_id.PersistToDisk(profile_);
- IncreasePushRegistrationCount(1, false /* is_pending */);
- break;
- case GCMClient::INVALID_PARAMETER:
- case GCMClient::GCM_DISABLED:
- case GCMClient::ASYNC_OPERATION_PENDING:
- case GCMClient::SERVER_ERROR:
- case GCMClient::UNKNOWN_ERROR:
- status = content::PUSH_REGISTRATION_STATUS_SERVICE_ERROR;
- break;
- case GCMClient::NETWORK_ERROR:
- case GCMClient::TTL_EXCEEDED:
- status = content::PUSH_REGISTRATION_STATUS_NETWORK_ERROR;
- break;
- }
- RegisterEnd(callback, registration_id, status);
- DecreasePushRegistrationCount(1, true /* was_pending */);
-}
-
-void PushMessagingServiceImpl::DidRequestPermission(
- const PushMessagingApplicationId& application_id,
- const std::string& sender_id,
- const content::PushMessagingService::RegisterCallback& register_callback,
- ContentSetting content_setting) {
- if (content_setting != CONTENT_SETTING_ALLOW) {
- RegisterEnd(register_callback,
- std::string(),
- content::PUSH_REGISTRATION_STATUS_PERMISSION_DENIED);
- return;
- }
-
- // The GCMDriver could be NULL if GCMProfileService has been shut down.
- if (!gcm_profile_service_->driver())
- return;
-
- IncreasePushRegistrationCount(1, true /* is_pending */);
- std::vector<std::string> sender_ids(1, sender_id);
- gcm_profile_service_->driver()->Register(
- application_id.app_id_guid(),
- sender_ids,
- base::Bind(&PushMessagingServiceImpl::DidRegister,
- weak_factory_.GetWeakPtr(),
- application_id, register_callback));
-}
-
-// Unregister methods ----------------------------------------------------------
-
-void PushMessagingServiceImpl::Unregister(
- const GURL& requesting_origin,
- int64 service_worker_registration_id,
- const std::string& sender_id,
- bool retry_on_failure,
- const content::PushMessagingService::UnregisterCallback& callback) {
- DCHECK(gcm_profile_service_->driver());
-
- PushMessagingApplicationId application_id = PushMessagingApplicationId::Get(
- profile_, requesting_origin, service_worker_registration_id);
- if (!application_id.IsValid()) {
- if (!callback.is_null()) {
- callback.Run(
- content::PUSH_UNREGISTRATION_STATUS_SUCCESS_WAS_NOT_REGISTERED);
- }
- return;
- }
-
- Unregister(application_id.app_id_guid(), sender_id, retry_on_failure,
- callback);
-}
-
-void PushMessagingServiceImpl::Unregister(
- const std::string& app_id_guid,
- const std::string& sender_id,
- bool retry_on_failure,
- const content::PushMessagingService::UnregisterCallback& callback) {
- DCHECK(gcm_profile_service_->driver());
-
- if (retry_on_failure) {
- // Delete the mapping for this app id, to guarantee that no messages get
- // delivered in future (even if unregistration fails).
- // TODO(johnme): Instead of deleting these app ids, store them elsewhere,
- // and retry unregistration if it fails due to network errors.
- PushMessagingApplicationId application_id =
- PushMessagingApplicationId::Get(profile_, app_id_guid);
- if (application_id.IsValid())
- application_id.DeleteFromDisk(profile_);
- }
-
- const auto& unregister_callback =
- base::Bind(&PushMessagingServiceImpl::DidUnregister,
- weak_factory_.GetWeakPtr(),
- app_id_guid, retry_on_failure, callback);
-#if defined(OS_ANDROID)
- // On Android the backend is different, and requires the original sender_id.
- gcm_profile_service_->driver()->UnregisterWithSenderId(app_id_guid, sender_id,
- unregister_callback);
-#else
- gcm_profile_service_->driver()->Unregister(app_id_guid, unregister_callback);
-#endif
-}
-
-void PushMessagingServiceImpl::DidUnregister(
- const std::string& app_id_guid,
- bool retry_on_failure,
- const content::PushMessagingService::UnregisterCallback& callback,
- GCMClient::Result result) {
- if (result == GCMClient::SUCCESS) {
- PushMessagingApplicationId application_id =
- PushMessagingApplicationId::Get(profile_, app_id_guid);
- if (!application_id.IsValid()) {
- if (!callback.is_null()) {
- callback.Run(
- content::PUSH_UNREGISTRATION_STATUS_SUCCESS_WAS_NOT_REGISTERED);
- }
- return;
- }
-
- application_id.DeleteFromDisk(profile_);
- DecreasePushRegistrationCount(1, false /* was_pending */);
- }
-
- // Internal calls pass a null callback.
- if (!callback.is_null()) {
- switch (result) {
- case GCMClient::SUCCESS:
- callback.Run(content::PUSH_UNREGISTRATION_STATUS_SUCCESS_UNREGISTERED);
- break;
- case GCMClient::INVALID_PARAMETER:
- case GCMClient::GCM_DISABLED:
- case GCMClient::ASYNC_OPERATION_PENDING:
- case GCMClient::SERVER_ERROR:
- case GCMClient::UNKNOWN_ERROR:
- callback.Run(content::PUSH_UNREGISTRATION_STATUS_SERVICE_ERROR);
- break;
- case GCMClient::NETWORK_ERROR:
- case GCMClient::TTL_EXCEEDED:
- callback.Run(
- retry_on_failure
- ? content::
- PUSH_UNREGISTRATION_STATUS_PENDING_WILL_RETRY_NETWORK_ERROR
- : content::PUSH_UNREGISTRATION_STATUS_NETWORK_ERROR);
- break;
- }
- }
-}
-
-// OnContentSettingChanged methods ---------------------------------------------
-
-void PushMessagingServiceImpl::OnContentSettingChanged(
- const ContentSettingsPattern& primary_pattern,
- const ContentSettingsPattern& secondary_pattern,
- ContentSettingsType content_type,
- std::string resource_identifier) {
- if (content_type != CONTENT_SETTINGS_TYPE_PUSH_MESSAGING &&
- content_type != CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
- return;
- }
-
- for (const auto& id : PushMessagingApplicationId::GetAll(profile_)) {
- // If |primary_pattern| is not valid, we should always check for a
- // permission change because it can happen for example when the entire
- // Push or Notifications permissions are cleared.
- // Otherwise, the permission should be checked if the pattern matches the
- // origin.
- if (primary_pattern.IsValid() && !primary_pattern.Matches(id.origin()))
- continue;
-
- if (HasPermission(id.origin()))
- continue;
-
- PushMessagingService::GetSenderId(
- profile_, id.origin(), id.service_worker_registration_id(),
- base::Bind(
- &PushMessagingServiceImpl::UnregisterBecausePermissionRevoked,
- weak_factory_.GetWeakPtr(), id));
- }
-}
-
-void PushMessagingServiceImpl::UnregisterBecausePermissionRevoked(
- const PushMessagingApplicationId& id,
- const std::string& sender_id, bool success, bool not_found) {
- // Unregister the PushMessagingApplicationId with the push service.
- Unregister(id.app_id_guid(), sender_id, true /* retry_on_failure */,
- UnregisterCallback());
-
- // Clear the associated service worker push registration id.
- PushMessagingService::ClearPushRegistrationID(
- profile_, id.origin(), id.service_worker_registration_id());
-}
-
-// Helper methods --------------------------------------------------------------
-
-bool PushMessagingServiceImpl::HasPermission(const GURL& origin) {
- gcm::PushMessagingPermissionContext* permission_context =
- gcm::PushMessagingPermissionContextFactory::GetForProfile(profile_);
- DCHECK(permission_context);
-
- return permission_context->GetPermissionStatus(origin, origin) ==
- CONTENT_SETTING_ALLOW;
-}
-
-void PushMessagingServiceImpl::SetProfileForTesting(Profile* profile) {
- profile_ = profile;
- profile_->GetHostContentSettingsMap()->AddObserver(this);
-}
-
-} // namespace gcm
« no previous file with comments | « chrome/browser/services/gcm/push_messaging_service_impl.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698