| Index: content/browser/push_messaging/push_messaging_message_filter.cc | 
| diff --git a/content/browser/push_messaging/push_messaging_message_filter.cc b/content/browser/push_messaging/push_messaging_message_filter.cc | 
| deleted file mode 100644 | 
| index 9820f4f151d95be74ca3f6e4ad5b6fc6a80158dc..0000000000000000000000000000000000000000 | 
| --- a/content/browser/push_messaging/push_messaging_message_filter.cc | 
| +++ /dev/null | 
| @@ -1,917 +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 "content/browser/push_messaging/push_messaging_message_filter.h" | 
| - | 
| -#include <string> | 
| -#include <vector> | 
| - | 
| -#include "base/bind.h" | 
| -#include "base/bind_helpers.h" | 
| -#include "base/command_line.h" | 
| -#include "base/logging.h" | 
| -#include "base/macros.h" | 
| -#include "base/memory/ptr_util.h" | 
| -#include "base/metrics/histogram_macros.h" | 
| -#include "base/strings/string_number_conversions.h" | 
| -#include "content/browser/renderer_host/render_process_host_impl.h" | 
| -#include "content/browser/service_worker/service_worker_context_core.h" | 
| -#include "content/browser/service_worker/service_worker_context_wrapper.h" | 
| -#include "content/browser/service_worker/service_worker_storage.h" | 
| -#include "content/common/push_messaging_messages.h" | 
| -#include "content/public/browser/browser_context.h" | 
| -#include "content/public/browser/browser_thread.h" | 
| -#include "content/public/browser/permission_manager.h" | 
| -#include "content/public/browser/permission_type.h" | 
| -#include "content/public/browser/push_messaging_service.h" | 
| -#include "content/public/browser/render_frame_host.h" | 
| -#include "content/public/browser/web_contents.h" | 
| -#include "content/public/common/child_process_host.h" | 
| -#include "content/public/common/console_message_level.h" | 
| -#include "content/public/common/content_switches.h" | 
| -#include "content/public/common/push_messaging_status.h" | 
| -#include "third_party/WebKit/public/platform/modules/push_messaging/WebPushPermissionStatus.h" | 
| - | 
| -namespace content { | 
| - | 
| -// Service Worker database keys. If a registration ID is stored, the stored | 
| -// sender ID must be the one used to register. Unfortunately, this isn't always | 
| -// true of pre-InstanceID registrations previously stored in the database, but | 
| -// fortunately it's less important for their sender ID to be accurate. | 
| -const char kPushSenderIdServiceWorkerKey[] = "push_sender_id"; | 
| -const char kPushRegistrationIdServiceWorkerKey[] = "push_registration_id"; | 
| - | 
| -namespace { | 
| - | 
| -// Chrome currently does not support the Push API in incognito. | 
| -const char kIncognitoPushUnsupportedMessage[] = | 
| -    "Chrome currently does not support the Push API in incognito mode " | 
| -    "(https://crbug.com/401439). There is deliberately no way to " | 
| -    "feature-detect this, since incognito mode needs to be undetectable by " | 
| -    "websites."; | 
| - | 
| -// These UMA methods are only called from IO thread, but it would be acceptable | 
| -// (even though slightly racy) to call them from UI thread as well, see | 
| -// https://groups.google.com/a/chromium.org/d/msg/chromium-dev/FNzZRJtN2aw/Aw0CWAXJJ1kJ | 
| -void RecordRegistrationStatus(PushRegistrationStatus status) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| -  UMA_HISTOGRAM_ENUMERATION("PushMessaging.RegistrationStatus", status, | 
| -                            PUSH_REGISTRATION_STATUS_LAST + 1); | 
| -} | 
| - | 
| -void RecordUnregistrationStatus(PushUnregistrationStatus status) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| -  UMA_HISTOGRAM_ENUMERATION("PushMessaging.UnregistrationStatus", status, | 
| -                            PUSH_UNREGISTRATION_STATUS_LAST + 1); | 
| -} | 
| - | 
| -void RecordGetRegistrationStatus(PushGetRegistrationStatus status) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| -  UMA_HISTOGRAM_ENUMERATION("PushMessaging.GetRegistrationStatus", status, | 
| -                            PUSH_GETREGISTRATION_STATUS_LAST + 1); | 
| -} | 
| - | 
| -// Curries the |success| and |p256dh| parameters over to |callback| and | 
| -// posts a task to invoke |callback| on the IO thread. | 
| -void ForwardEncryptionInfoToIOThreadProxy( | 
| -    const PushMessagingService::EncryptionInfoCallback& callback, | 
| -    bool success, | 
| -    const std::vector<uint8_t>& p256dh, | 
| -    const std::vector<uint8_t>& auth) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| -  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 
| -                          base::Bind(callback, success, p256dh, auth)); | 
| -} | 
| - | 
| -// Returns whether |sender_info| contains a valid application server key, that | 
| -// is, a NIST P-256 public key in uncompressed format. | 
| -bool IsApplicationServerKey(const std::string& sender_info) { | 
| -  return sender_info.size() == 65 && sender_info[0] == 0x04; | 
| -} | 
| - | 
| -// Returns sender_info if non-empty, otherwise checks if stored_sender_id | 
| -// may be used as a fallback and if so, returns stored_sender_id instead. | 
| -// | 
| -// This is in order to support the legacy way of subscribing from a service | 
| -// worker (first subscribe from the document using a gcm_sender_id set in the | 
| -// manifest, and then subscribe from the service worker with no key). | 
| -// | 
| -// An empty string will be returned if sender_info is empty and the fallback | 
| -// is not a numeric gcm sender id. | 
| -std::string FixSenderInfo(const std::string& sender_info, | 
| -                          const std::string& stored_sender_id) { | 
| -  if (!sender_info.empty()) | 
| -    return sender_info; | 
| -  if (base::ContainsOnlyChars(stored_sender_id, "0123456789")) | 
| -    return stored_sender_id; | 
| -  return std::string(); | 
| -} | 
| - | 
| -}  // namespace | 
| - | 
| -struct PushMessagingMessageFilter::RegisterData { | 
| -  RegisterData(); | 
| -  RegisterData(const RegisterData& other) = default; | 
| -  bool FromDocument() const; | 
| -  int request_id; | 
| -  GURL requesting_origin; | 
| -  int64_t service_worker_registration_id; | 
| -  PushSubscriptionOptions options; | 
| -  // The following member should only be read if FromDocument() is true. | 
| -  int render_frame_id; | 
| -}; | 
| - | 
| -// Inner core of this message filter which lives on the UI thread. | 
| -class PushMessagingMessageFilter::Core { | 
| - public: | 
| -  Core(const base::WeakPtr<PushMessagingMessageFilter>& io_parent, | 
| -       int render_process_id); | 
| - | 
| -  // Public Register methods on UI thread -------------------------------------- | 
| - | 
| -  // Called via PostTask from IO thread. | 
| -  void RegisterOnUI(const RegisterData& data); | 
| - | 
| -  // Public Unregister methods on UI thread ------------------------------------ | 
| - | 
| -  // Called via PostTask from IO thread. | 
| -  void UnregisterFromService(int request_id, | 
| -                             int64_t service_worker_registration_id, | 
| -                             const GURL& requesting_origin, | 
| -                             const std::string& sender_id); | 
| - | 
| -  // Public GetPermission methods on UI thread --------------------------------- | 
| - | 
| -  // Called via PostTask from IO thread. | 
| -  void GetPermissionStatusOnUI(const GURL& requesting_origin, | 
| -                               bool user_visible, | 
| -                               int request_id); | 
| - | 
| -  // Public helper methods on UI thread ---------------------------------------- | 
| - | 
| -  // Called via PostTask from IO thread. The |io_thread_callback| callback | 
| -  // will be invoked on the IO thread. | 
| -  void GetEncryptionInfoOnUI( | 
| -      const GURL& origin, | 
| -      int64_t service_worker_registration_id, | 
| -      const std::string& sender_id, | 
| -      const PushMessagingService::EncryptionInfoCallback& io_thread_callback); | 
| - | 
| -  // Called (directly) from both the UI and IO threads. | 
| -  bool is_incognito() const { return is_incognito_; } | 
| - | 
| -  // Returns a push messaging service. May return null. | 
| -  PushMessagingService* service(); | 
| - | 
| - private: | 
| -  friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; | 
| -  friend class base::DeleteHelper<Core>; | 
| - | 
| -  ~Core(); | 
| - | 
| -  // Private Register methods on UI thread ------------------------------------- | 
| - | 
| -  void DidRequestPermissionInIncognito(const RegisterData& data, | 
| -                                       blink::mojom::PermissionStatus status); | 
| - | 
| -  void DidRegister(const RegisterData& data, | 
| -                   const std::string& push_registration_id, | 
| -                   const std::vector<uint8_t>& p256dh, | 
| -                   const std::vector<uint8_t>& auth, | 
| -                   PushRegistrationStatus status); | 
| - | 
| -  // Private Unregister methods on UI thread ----------------------------------- | 
| - | 
| -  void DidUnregisterFromService(int request_id, | 
| -                                int64_t service_worker_registration_id, | 
| -                                PushUnregistrationStatus unregistration_status); | 
| - | 
| -  // Private helper methods on UI thread --------------------------------------- | 
| - | 
| -  void Send(IPC::Message* message); | 
| - | 
| -  // Outer part of this message filter which lives on the IO thread. | 
| -  base::WeakPtr<PushMessagingMessageFilter> io_parent_; | 
| - | 
| -  int render_process_id_; | 
| - | 
| -  bool is_incognito_; | 
| - | 
| -  base::WeakPtrFactory<Core> weak_factory_ui_to_ui_; | 
| - | 
| -  DISALLOW_COPY_AND_ASSIGN(Core); | 
| -}; | 
| - | 
| -PushMessagingMessageFilter::RegisterData::RegisterData() | 
| -    : request_id(0), | 
| -      service_worker_registration_id(0), | 
| -      render_frame_id(ChildProcessHost::kInvalidUniqueID) {} | 
| - | 
| -bool PushMessagingMessageFilter::RegisterData::FromDocument() const { | 
| -  return render_frame_id != ChildProcessHost::kInvalidUniqueID; | 
| -} | 
| - | 
| -PushMessagingMessageFilter::Core::Core( | 
| -    const base::WeakPtr<PushMessagingMessageFilter>& io_parent, | 
| -    int render_process_id) | 
| -    : io_parent_(io_parent), | 
| -      render_process_id_(render_process_id), | 
| -      weak_factory_ui_to_ui_(this) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| -  RenderProcessHost* process_host = | 
| -      RenderProcessHost::FromID(render_process_id_);  // Can't be null yet. | 
| -  is_incognito_ = process_host->GetBrowserContext()->IsOffTheRecord(); | 
| -} | 
| - | 
| -PushMessagingMessageFilter::Core::~Core() {} | 
| - | 
| -PushMessagingMessageFilter::PushMessagingMessageFilter( | 
| -    int render_process_id, | 
| -    ServiceWorkerContextWrapper* service_worker_context) | 
| -    : BrowserMessageFilter(PushMessagingMsgStart), | 
| -      service_worker_context_(service_worker_context), | 
| -      weak_factory_io_to_io_(this) { | 
| -  // Although this class is used only on the IO thread, it is constructed on UI. | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| -  // Normally, it would be unsafe to obtain a weak pointer from the UI thread, | 
| -  // but it's ok in the constructor since we can't be destroyed before our | 
| -  // constructor finishes. | 
| -  ui_core_.reset( | 
| -      new Core(weak_factory_io_to_io_.GetWeakPtr(), render_process_id)); | 
| - | 
| -  PushMessagingService* service = ui_core_->service(); | 
| -  service_available_ = !!service; | 
| - | 
| -  if (service_available_) { | 
| -    default_endpoint_ = service->GetEndpoint(false /* standard_protocol */); | 
| -    web_push_protocol_endpoint_ = | 
| -        service->GetEndpoint(true /* standard_protocol */); | 
| -  } | 
| -} | 
| - | 
| -PushMessagingMessageFilter::~PushMessagingMessageFilter() {} | 
| - | 
| -void PushMessagingMessageFilter::OnDestruct() const { | 
| -  BrowserThread::DeleteOnIOThread::Destruct(this); | 
| -} | 
| - | 
| -bool PushMessagingMessageFilter::OnMessageReceived( | 
| -    const IPC::Message& message) { | 
| -  bool handled = true; | 
| -  IPC_BEGIN_MESSAGE_MAP(PushMessagingMessageFilter, message) | 
| -    IPC_MESSAGE_HANDLER(PushMessagingHostMsg_Subscribe, OnSubscribe) | 
| -    IPC_MESSAGE_HANDLER(PushMessagingHostMsg_Unsubscribe, OnUnsubscribe) | 
| -    IPC_MESSAGE_HANDLER(PushMessagingHostMsg_GetSubscription, OnGetSubscription) | 
| -    IPC_MESSAGE_HANDLER(PushMessagingHostMsg_GetPermissionStatus, | 
| -                        OnGetPermissionStatus) | 
| -    IPC_MESSAGE_UNHANDLED(handled = false) | 
| -  IPC_END_MESSAGE_MAP() | 
| -  return handled; | 
| -} | 
| - | 
| -// Subscribe methods on both IO and UI threads, merged in order of use from | 
| -// PushMessagingMessageFilter and Core. | 
| -// ----------------------------------------------------------------------------- | 
| - | 
| -void PushMessagingMessageFilter::OnSubscribe( | 
| -    int render_frame_id, | 
| -    int request_id, | 
| -    int64_t service_worker_registration_id, | 
| -    const PushSubscriptionOptions& options) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| -  // TODO(mvanouwerkerk): Validate arguments? | 
| -  RegisterData data; | 
| - | 
| -  // Will be ChildProcessHost::kInvalidUniqueID in requests from Service Worker. | 
| -  data.render_frame_id = render_frame_id; | 
| - | 
| -  data.request_id = request_id; | 
| -  data.service_worker_registration_id = service_worker_registration_id; | 
| -  data.options = options; | 
| - | 
| -  ServiceWorkerRegistration* service_worker_registration = | 
| -      service_worker_context_->GetLiveRegistration( | 
| -          data.service_worker_registration_id); | 
| -  if (!service_worker_registration || | 
| -      !service_worker_registration->active_version()) { | 
| -    SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_NO_SERVICE_WORKER); | 
| -    return; | 
| -  } | 
| -  data.requesting_origin = service_worker_registration->pattern().GetOrigin(); | 
| - | 
| -  DCHECK(!(data.options.sender_info.empty() && data.FromDocument())); | 
| - | 
| -  service_worker_context_->GetRegistrationUserData( | 
| -      data.service_worker_registration_id, | 
| -      {kPushRegistrationIdServiceWorkerKey, kPushSenderIdServiceWorkerKey}, | 
| -      base::Bind(&PushMessagingMessageFilter::DidCheckForExistingRegistration, | 
| -                 weak_factory_io_to_io_.GetWeakPtr(), data)); | 
| -} | 
| - | 
| -void PushMessagingMessageFilter::DidCheckForExistingRegistration( | 
| -    const RegisterData& data, | 
| -    const std::vector<std::string>& push_registration_id_and_sender_id, | 
| -    ServiceWorkerStatusCode service_worker_status) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| -  if (service_worker_status == SERVICE_WORKER_OK) { | 
| -    DCHECK_EQ(2u, push_registration_id_and_sender_id.size()); | 
| -    const auto& push_registration_id = push_registration_id_and_sender_id[0]; | 
| -    const auto& stored_sender_id = push_registration_id_and_sender_id[1]; | 
| -    std::string fixed_sender_id = | 
| -        FixSenderInfo(data.options.sender_info, stored_sender_id); | 
| -    if (fixed_sender_id.empty()) { | 
| -      SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_NO_SENDER_ID); | 
| -      return; | 
| -    } | 
| -    if (fixed_sender_id != stored_sender_id) { | 
| -      SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_SENDER_ID_MISMATCH); | 
| -      return; | 
| -    } | 
| -    auto callback = base::Bind( | 
| -        &PushMessagingMessageFilter::DidGetEncryptionKeys, | 
| -        weak_factory_io_to_io_.GetWeakPtr(), data, push_registration_id); | 
| -    BrowserThread::PostTask( | 
| -        BrowserThread::UI, FROM_HERE, | 
| -        base::Bind(&Core::GetEncryptionInfoOnUI, | 
| -                   base::Unretained(ui_core_.get()), data.requesting_origin, | 
| -                   data.service_worker_registration_id, fixed_sender_id, | 
| -                   callback)); | 
| -    return; | 
| -  } | 
| -  // TODO(johnme): The spec allows the register algorithm to reject with an | 
| -  // AbortError when accessing storage fails. Perhaps we should do that if | 
| -  // service_worker_status != SERVICE_WORKER_ERROR_NOT_FOUND instead of | 
| -  // attempting to do a fresh registration? | 
| -  // https://w3c.github.io/push-api/#widl-PushRegistrationManager-register-Promise-PushRegistration | 
| -  if (!data.options.sender_info.empty()) { | 
| -    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 
| -                            base::Bind(&Core::RegisterOnUI, | 
| -                                       base::Unretained(ui_core_.get()), data)); | 
| -  } else { | 
| -    // There is no existing registration and the sender_info passed in was | 
| -    // empty, but perhaps there is a stored sender id we can use. | 
| -    service_worker_context_->GetRegistrationUserData( | 
| -        data.service_worker_registration_id, {kPushSenderIdServiceWorkerKey}, | 
| -        base::Bind(&PushMessagingMessageFilter::DidGetSenderIdFromStorage, | 
| -                   weak_factory_io_to_io_.GetWeakPtr(), data)); | 
| -  } | 
| -} | 
| - | 
| -void PushMessagingMessageFilter::DidGetEncryptionKeys( | 
| -    const RegisterData& data, | 
| -    const std::string& push_registration_id, | 
| -    bool success, | 
| -    const std::vector<uint8_t>& p256dh, | 
| -    const std::vector<uint8_t>& auth) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| -  if (!success) { | 
| -    SendSubscriptionError( | 
| -        data, PUSH_REGISTRATION_STATUS_PUBLIC_KEY_UNAVAILABLE); | 
| -    return; | 
| -  } | 
| - | 
| -  SendSubscriptionSuccess(data, PUSH_REGISTRATION_STATUS_SUCCESS_FROM_CACHE, | 
| -                          push_registration_id, p256dh, auth); | 
| -} | 
| - | 
| -void PushMessagingMessageFilter::DidGetSenderIdFromStorage( | 
| -    const RegisterData& data, | 
| -    const std::vector<std::string>& stored_sender_id, | 
| -    ServiceWorkerStatusCode service_worker_status) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| -  if (service_worker_status != SERVICE_WORKER_OK) { | 
| -    SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_NO_SENDER_ID); | 
| -    return; | 
| -  } | 
| -  DCHECK_EQ(1u, stored_sender_id.size()); | 
| -  // We should only be here because no sender info was supplied to subscribe(). | 
| -  DCHECK(data.options.sender_info.empty()); | 
| -  std::string fixed_sender_id = | 
| -      FixSenderInfo(data.options.sender_info, stored_sender_id[0]); | 
| -  if (fixed_sender_id.empty()) { | 
| -    SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_NO_SENDER_ID); | 
| -    return; | 
| -  } | 
| -  RegisterData mutated_data = data; | 
| -  mutated_data.options.sender_info = fixed_sender_id; | 
| -  BrowserThread::PostTask( | 
| -      BrowserThread::UI, FROM_HERE, | 
| -      base::Bind(&Core::RegisterOnUI, base::Unretained(ui_core_.get()), | 
| -                 mutated_data)); | 
| -} | 
| - | 
| -void PushMessagingMessageFilter::Core::RegisterOnUI( | 
| -    const PushMessagingMessageFilter::RegisterData& data) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| -  PushMessagingService* push_service = service(); | 
| -  if (!push_service) { | 
| -    if (!is_incognito()) { | 
| -      // This might happen if InstanceIDProfileService::IsInstanceIDEnabled | 
| -      // returns false because the Instance ID kill switch was enabled. | 
| -      // TODO(johnme): Might be better not to expose the API in this case. | 
| -      BrowserThread::PostTask( | 
| -          BrowserThread::IO, FROM_HERE, | 
| -          base::Bind(&PushMessagingMessageFilter::SendSubscriptionError, | 
| -                     io_parent_, | 
| -                     data, PUSH_REGISTRATION_STATUS_SERVICE_NOT_AVAILABLE)); | 
| -    } else { | 
| -      // Prevent websites from detecting incognito mode, by emulating what would | 
| -      // have happened if we had a PushMessagingService available. | 
| -      if (!data.FromDocument() || !data.options.user_visible_only) { | 
| -        // Throw a permission denied error under the same circumstances. | 
| -        BrowserThread::PostTask( | 
| -            BrowserThread::IO, FROM_HERE, | 
| -            base::Bind(&PushMessagingMessageFilter::SendSubscriptionError, | 
| -                       io_parent_, data, | 
| -                       PUSH_REGISTRATION_STATUS_INCOGNITO_PERMISSION_DENIED)); | 
| -      } else { | 
| -        RenderFrameHost* render_frame_host = | 
| -            RenderFrameHost::FromID(render_process_id_, data.render_frame_id); | 
| -        WebContents* web_contents = | 
| -            WebContents::FromRenderFrameHost(render_frame_host); | 
| -        if (web_contents) { | 
| -          web_contents->GetMainFrame()->AddMessageToConsole( | 
| -              CONSOLE_MESSAGE_LEVEL_ERROR, kIncognitoPushUnsupportedMessage); | 
| -          // Request push messaging permission (which will fail, since | 
| -          // notifications aren't supported in incognito), so the website can't | 
| -          // detect whether incognito is active. | 
| -          web_contents->GetBrowserContext() | 
| -              ->GetPermissionManager() | 
| -              ->RequestPermission( | 
| -                  PermissionType::PUSH_MESSAGING, render_frame_host, | 
| -                  data.requesting_origin, false /* user_gesture */, | 
| -                  base::Bind(&PushMessagingMessageFilter::Core:: | 
| -                                 DidRequestPermissionInIncognito, | 
| -                             weak_factory_ui_to_ui_.GetWeakPtr(), data)); | 
| -        } | 
| -      } | 
| -    } | 
| -    return; | 
| -  } | 
| - | 
| -  if (data.FromDocument()) { | 
| -    push_service->SubscribeFromDocument( | 
| -        data.requesting_origin, data.service_worker_registration_id, | 
| -        render_process_id_, data.render_frame_id, data.options, | 
| -        base::Bind(&Core::DidRegister, weak_factory_ui_to_ui_.GetWeakPtr(), | 
| -                   data)); | 
| -  } else { | 
| -    push_service->SubscribeFromWorker( | 
| -        data.requesting_origin, data.service_worker_registration_id, | 
| -        data.options, base::Bind(&Core::DidRegister, | 
| -                                 weak_factory_ui_to_ui_.GetWeakPtr(), data)); | 
| -  } | 
| -} | 
| - | 
| -void PushMessagingMessageFilter::Core::DidRequestPermissionInIncognito( | 
| -    const RegisterData& data, | 
| -    blink::mojom::PermissionStatus status) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| -  // Notification permission should always be denied in incognito. | 
| -  DCHECK_EQ(blink::mojom::PermissionStatus::DENIED, status); | 
| -  BrowserThread::PostTask( | 
| -      BrowserThread::IO, FROM_HERE, | 
| -      base::Bind(&PushMessagingMessageFilter::SendSubscriptionError, io_parent_, | 
| -                 data, PUSH_REGISTRATION_STATUS_INCOGNITO_PERMISSION_DENIED)); | 
| -} | 
| - | 
| -void PushMessagingMessageFilter::Core::DidRegister( | 
| -    const RegisterData& data, | 
| -    const std::string& push_registration_id, | 
| -    const std::vector<uint8_t>& p256dh, | 
| -    const std::vector<uint8_t>& auth, | 
| -    PushRegistrationStatus status) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| -  if (status == PUSH_REGISTRATION_STATUS_SUCCESS_FROM_PUSH_SERVICE) { | 
| -    BrowserThread::PostTask( | 
| -        BrowserThread::IO, FROM_HERE, | 
| -        base::Bind(&PushMessagingMessageFilter::PersistRegistrationOnIO, | 
| -                   io_parent_, data, push_registration_id, p256dh, auth)); | 
| -  } else { | 
| -    BrowserThread::PostTask( | 
| -        BrowserThread::IO, FROM_HERE, | 
| -        base::Bind(&PushMessagingMessageFilter::SendSubscriptionError, | 
| -                   io_parent_, data, status)); | 
| -  } | 
| -} | 
| - | 
| -void PushMessagingMessageFilter::PersistRegistrationOnIO( | 
| -    const RegisterData& data, | 
| -    const std::string& push_registration_id, | 
| -    const std::vector<uint8_t>& p256dh, | 
| -    const std::vector<uint8_t>& auth) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| -  service_worker_context_->StoreRegistrationUserData( | 
| -      data.service_worker_registration_id, data.requesting_origin, | 
| -      {{kPushRegistrationIdServiceWorkerKey, push_registration_id}, | 
| -       {kPushSenderIdServiceWorkerKey, data.options.sender_info}}, | 
| -      base::Bind(&PushMessagingMessageFilter::DidPersistRegistrationOnIO, | 
| -                 weak_factory_io_to_io_.GetWeakPtr(), data, | 
| -                 push_registration_id, p256dh, auth)); | 
| -} | 
| - | 
| -void PushMessagingMessageFilter::DidPersistRegistrationOnIO( | 
| -    const RegisterData& data, | 
| -    const std::string& push_registration_id, | 
| -    const std::vector<uint8_t>& p256dh, | 
| -    const std::vector<uint8_t>& auth, | 
| -    ServiceWorkerStatusCode service_worker_status) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| -  if (service_worker_status == SERVICE_WORKER_OK) { | 
| -    SendSubscriptionSuccess(data, | 
| -                            PUSH_REGISTRATION_STATUS_SUCCESS_FROM_PUSH_SERVICE, | 
| -                            push_registration_id, p256dh, auth); | 
| -  } else { | 
| -    // TODO(johnme): Unregister, so PushMessagingServiceImpl can decrease count. | 
| -    SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_STORAGE_ERROR); | 
| -  } | 
| -} | 
| - | 
| -void PushMessagingMessageFilter::SendSubscriptionError( | 
| -    const RegisterData& data, PushRegistrationStatus status) { | 
| -  // Only called from IO thread, but would be safe to call from UI thread. | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| -  if (data.FromDocument()) { | 
| -    Send(new PushMessagingMsg_SubscribeFromDocumentError( | 
| -        data.render_frame_id, data.request_id, status)); | 
| -  } else { | 
| -    Send( | 
| -        new PushMessagingMsg_SubscribeFromWorkerError(data.request_id, status)); | 
| -  } | 
| -  RecordRegistrationStatus(status); | 
| -} | 
| - | 
| -void PushMessagingMessageFilter::SendSubscriptionSuccess( | 
| -    const RegisterData& data, | 
| -    PushRegistrationStatus status, | 
| -    const std::string& push_subscription_id, | 
| -    const std::vector<uint8_t>& p256dh, | 
| -    const std::vector<uint8_t>& auth) { | 
| -  // Only called from IO thread, but would be safe to call from UI thread. | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| -  if (!service_available_) { | 
| -    // This shouldn't be possible in incognito mode, since we've already checked | 
| -    // that we have an existing registration. Hence it's ok to throw an error. | 
| -    DCHECK(!ui_core_->is_incognito()); | 
| -    SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_SERVICE_NOT_AVAILABLE); | 
| -    return; | 
| -  } | 
| - | 
| -  const GURL endpoint = CreateEndpoint( | 
| -      IsApplicationServerKey(data.options.sender_info), push_subscription_id); | 
| - | 
| -  if (data.FromDocument()) { | 
| -    Send(new PushMessagingMsg_SubscribeFromDocumentSuccess( | 
| -        data.render_frame_id, data.request_id, endpoint, data.options, p256dh, | 
| -        auth)); | 
| -  } else { | 
| -    Send(new PushMessagingMsg_SubscribeFromWorkerSuccess( | 
| -        data.request_id, endpoint, data.options, p256dh, auth)); | 
| -  } | 
| -  RecordRegistrationStatus(status); | 
| -} | 
| - | 
| -// Unsubscribe methods on both IO and UI threads, merged in order of use from | 
| -// PushMessagingMessageFilter and Core. | 
| -// ----------------------------------------------------------------------------- | 
| - | 
| -void PushMessagingMessageFilter::OnUnsubscribe( | 
| -    int request_id, int64_t service_worker_registration_id) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| -  ServiceWorkerRegistration* service_worker_registration = | 
| -      service_worker_context_->GetLiveRegistration( | 
| -          service_worker_registration_id); | 
| -  if (!service_worker_registration) { | 
| -    DidUnregister(request_id, PUSH_UNREGISTRATION_STATUS_NO_SERVICE_WORKER); | 
| -    return; | 
| -  } | 
| - | 
| -  service_worker_context_->GetRegistrationUserData( | 
| -      service_worker_registration_id, {kPushSenderIdServiceWorkerKey}, | 
| -      base::Bind(&PushMessagingMessageFilter::UnsubscribeHavingGottenSenderId, | 
| -                 weak_factory_io_to_io_.GetWeakPtr(), request_id, | 
| -                 service_worker_registration_id, | 
| -                 service_worker_registration->pattern().GetOrigin())); | 
| -} | 
| - | 
| -void PushMessagingMessageFilter::UnsubscribeHavingGottenSenderId( | 
| -    int request_id, | 
| -    int64_t service_worker_registration_id, | 
| -    const GURL& requesting_origin, | 
| -    const std::vector<std::string>& sender_ids, | 
| -    ServiceWorkerStatusCode service_worker_status) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| - | 
| -  std::string sender_id; | 
| -  if (service_worker_status == SERVICE_WORKER_OK) { | 
| -    DCHECK_EQ(1u, sender_ids.size()); | 
| -    sender_id = sender_ids[0]; | 
| -  } | 
| -  BrowserThread::PostTask( | 
| -      BrowserThread::UI, FROM_HERE, | 
| -      base::Bind(&Core::UnregisterFromService, base::Unretained(ui_core_.get()), | 
| -                 request_id, service_worker_registration_id, requesting_origin, | 
| -                 sender_id)); | 
| -} | 
| - | 
| -void PushMessagingMessageFilter::Core::UnregisterFromService( | 
| -    int request_id, | 
| -    int64_t service_worker_registration_id, | 
| -    const GURL& requesting_origin, | 
| -    const std::string& sender_id) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| -  PushMessagingService* push_service = service(); | 
| -  if (!push_service) { | 
| -    // This shouldn't be possible in incognito mode, since we've already checked | 
| -    // that we have an existing registration. Hence it's ok to throw an error. | 
| -    DCHECK(!is_incognito()); | 
| -    BrowserThread::PostTask( | 
| -        BrowserThread::IO, FROM_HERE, | 
| -        base::Bind(&PushMessagingMessageFilter::DidUnregister, io_parent_, | 
| -                   request_id, | 
| -                   PUSH_UNREGISTRATION_STATUS_SERVICE_NOT_AVAILABLE)); | 
| -    return; | 
| -  } | 
| - | 
| -  push_service->Unsubscribe( | 
| -      requesting_origin, service_worker_registration_id, sender_id, | 
| -      base::Bind(&Core::DidUnregisterFromService, | 
| -                 weak_factory_ui_to_ui_.GetWeakPtr(), request_id, | 
| -                 service_worker_registration_id)); | 
| -} | 
| - | 
| -void PushMessagingMessageFilter::Core::DidUnregisterFromService( | 
| -    int request_id, | 
| -    int64_t service_worker_registration_id, | 
| -    PushUnregistrationStatus unregistration_status) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| - | 
| -  BrowserThread::PostTask( | 
| -      BrowserThread::IO, FROM_HERE, | 
| -      base::Bind(&PushMessagingMessageFilter::DidUnregister, io_parent_, | 
| -                 request_id, unregistration_status)); | 
| -} | 
| - | 
| -void PushMessagingMessageFilter::DidUnregister( | 
| -    int request_id, | 
| -    PushUnregistrationStatus unregistration_status) { | 
| -  // Only called from IO thread, but would be safe to call from UI thread. | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| -  switch (unregistration_status) { | 
| -    case PUSH_UNREGISTRATION_STATUS_SUCCESS_UNREGISTERED: | 
| -    case PUSH_UNREGISTRATION_STATUS_PENDING_NETWORK_ERROR: | 
| -    case PUSH_UNREGISTRATION_STATUS_PENDING_SERVICE_ERROR: | 
| -      Send(new PushMessagingMsg_UnsubscribeSuccess(request_id, true)); | 
| -      break; | 
| -    case PUSH_UNREGISTRATION_STATUS_SUCCESS_WAS_NOT_REGISTERED: | 
| -      Send(new PushMessagingMsg_UnsubscribeSuccess(request_id, false)); | 
| -      break; | 
| -    case PUSH_UNREGISTRATION_STATUS_NO_SERVICE_WORKER: | 
| -    case PUSH_UNREGISTRATION_STATUS_SERVICE_NOT_AVAILABLE: | 
| -    case PUSH_UNREGISTRATION_STATUS_STORAGE_ERROR: | 
| -      Send(new PushMessagingMsg_UnsubscribeError( | 
| -          request_id, blink::WebPushError::ErrorTypeAbort, | 
| -          PushUnregistrationStatusToString(unregistration_status))); | 
| -      break; | 
| -    case PUSH_UNREGISTRATION_STATUS_NETWORK_ERROR: | 
| -      NOTREACHED(); | 
| -      break; | 
| -  } | 
| -  RecordUnregistrationStatus(unregistration_status); | 
| -} | 
| - | 
| -// GetSubscription methods on both IO and UI threads, merged in order of use | 
| -// from PushMessagingMessageFilter and Core. | 
| -// ----------------------------------------------------------------------------- | 
| - | 
| -void PushMessagingMessageFilter::OnGetSubscription( | 
| -    int request_id, | 
| -    int64_t service_worker_registration_id) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| -  // TODO(johnme): Validate arguments? | 
| -  service_worker_context_->GetRegistrationUserData( | 
| -      service_worker_registration_id, | 
| -      {kPushRegistrationIdServiceWorkerKey, kPushSenderIdServiceWorkerKey}, | 
| -      base::Bind(&PushMessagingMessageFilter::DidGetSubscription, | 
| -                 weak_factory_io_to_io_.GetWeakPtr(), request_id, | 
| -                 service_worker_registration_id)); | 
| -} | 
| - | 
| -void PushMessagingMessageFilter::DidGetSubscription( | 
| -    int request_id, | 
| -    int64_t service_worker_registration_id, | 
| -    const std::vector<std::string>& push_subscription_id_and_sender_info, | 
| -    ServiceWorkerStatusCode service_worker_status) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| -  PushGetRegistrationStatus get_status = | 
| -      PUSH_GETREGISTRATION_STATUS_STORAGE_ERROR; | 
| -  switch (service_worker_status) { | 
| -    case SERVICE_WORKER_OK: { | 
| -      DCHECK_EQ(2u, push_subscription_id_and_sender_info.size()); | 
| - | 
| -      if (!service_available_) { | 
| -        // Return not found in incognito mode, so websites can't detect it. | 
| -        get_status = | 
| -            ui_core_->is_incognito() | 
| -                ? PUSH_GETREGISTRATION_STATUS_INCOGNITO_REGISTRATION_NOT_FOUND | 
| -                : PUSH_GETREGISTRATION_STATUS_SERVICE_NOT_AVAILABLE; | 
| -        break; | 
| -      } | 
| - | 
| -      ServiceWorkerRegistration* registration = | 
| -          service_worker_context_->GetLiveRegistration( | 
| -              service_worker_registration_id); | 
| -      const GURL origin = registration->pattern().GetOrigin(); | 
| - | 
| -      const bool uses_standard_protocol = | 
| -          IsApplicationServerKey(push_subscription_id_and_sender_info[1]); | 
| -      const GURL endpoint = CreateEndpoint( | 
| -          uses_standard_protocol, push_subscription_id_and_sender_info[0]); | 
| - | 
| -      auto callback = | 
| -          base::Bind(&PushMessagingMessageFilter::DidGetSubscriptionKeys, | 
| -                     weak_factory_io_to_io_.GetWeakPtr(), request_id, endpoint, | 
| -                     push_subscription_id_and_sender_info[1]); | 
| - | 
| -      BrowserThread::PostTask( | 
| -          BrowserThread::UI, FROM_HERE, | 
| -          base::Bind(&Core::GetEncryptionInfoOnUI, | 
| -                     base::Unretained(ui_core_.get()), origin, | 
| -                     service_worker_registration_id, | 
| -                     push_subscription_id_and_sender_info[1], callback)); | 
| - | 
| -      return; | 
| -    } | 
| -    case SERVICE_WORKER_ERROR_NOT_FOUND: { | 
| -      get_status = PUSH_GETREGISTRATION_STATUS_REGISTRATION_NOT_FOUND; | 
| -      break; | 
| -    } | 
| -    case SERVICE_WORKER_ERROR_FAILED: { | 
| -      get_status = PUSH_GETREGISTRATION_STATUS_STORAGE_ERROR; | 
| -      break; | 
| -    } | 
| -    case SERVICE_WORKER_ERROR_ABORT: | 
| -    case SERVICE_WORKER_ERROR_START_WORKER_FAILED: | 
| -    case SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND: | 
| -    case SERVICE_WORKER_ERROR_EXISTS: | 
| -    case SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED: | 
| -    case SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED: | 
| -    case SERVICE_WORKER_ERROR_IPC_FAILED: | 
| -    case SERVICE_WORKER_ERROR_NETWORK: | 
| -    case SERVICE_WORKER_ERROR_SECURITY: | 
| -    case SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED: | 
| -    case SERVICE_WORKER_ERROR_STATE: | 
| -    case SERVICE_WORKER_ERROR_TIMEOUT: | 
| -    case SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED: | 
| -    case SERVICE_WORKER_ERROR_DISK_CACHE: | 
| -    case SERVICE_WORKER_ERROR_REDUNDANT: | 
| -    case SERVICE_WORKER_ERROR_DISALLOWED: | 
| -    case SERVICE_WORKER_ERROR_MAX_VALUE: { | 
| -      NOTREACHED() << "Got unexpected error code: " << service_worker_status | 
| -                   << " " << ServiceWorkerStatusToString(service_worker_status); | 
| -      get_status = PUSH_GETREGISTRATION_STATUS_STORAGE_ERROR; | 
| -      break; | 
| -    } | 
| -  } | 
| -  Send(new PushMessagingMsg_GetSubscriptionError(request_id, get_status)); | 
| -  RecordGetRegistrationStatus(get_status); | 
| -} | 
| - | 
| -void PushMessagingMessageFilter::DidGetSubscriptionKeys( | 
| -    int request_id, | 
| -    const GURL& endpoint, | 
| -    const std::string& sender_info, | 
| -    bool success, | 
| -    const std::vector<uint8_t>& p256dh, | 
| -    const std::vector<uint8_t>& auth) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| -  if (!success) { | 
| -    PushGetRegistrationStatus status = | 
| -        PUSH_GETREGISTRATION_STATUS_PUBLIC_KEY_UNAVAILABLE; | 
| - | 
| -    Send(new PushMessagingMsg_GetSubscriptionError(request_id, status)); | 
| - | 
| -    RecordGetRegistrationStatus(status); | 
| -    return; | 
| -  } | 
| - | 
| -  PushSubscriptionOptions options; | 
| -  // Chrome rejects subscription requests with userVisibleOnly false, so it must | 
| -  // have been true. TODO(harkness): If Chrome starts accepting silent push | 
| -  // subscriptions with userVisibleOnly false, the bool will need to be stored. | 
| -  options.user_visible_only = true; | 
| -  options.sender_info = sender_info; | 
| - | 
| -  Send(new PushMessagingMsg_GetSubscriptionSuccess(request_id, endpoint, | 
| -                                                   options, p256dh, auth)); | 
| - | 
| -  RecordGetRegistrationStatus(PUSH_GETREGISTRATION_STATUS_SUCCESS); | 
| -} | 
| - | 
| -// GetPermission methods on both IO and UI threads, merged in order of use from | 
| -// PushMessagingMessageFilter and Core. | 
| -// ----------------------------------------------------------------------------- | 
| - | 
| -void PushMessagingMessageFilter::OnGetPermissionStatus( | 
| -    int request_id, | 
| -    int64_t service_worker_registration_id, | 
| -    bool user_visible) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| -  ServiceWorkerRegistration* service_worker_registration = | 
| -      service_worker_context_->GetLiveRegistration( | 
| -          service_worker_registration_id); | 
| -  if (!service_worker_registration) { | 
| -    Send(new PushMessagingMsg_GetPermissionStatusError( | 
| -        request_id, blink::WebPushError::ErrorTypeAbort)); | 
| -    return; | 
| -  } | 
| - | 
| -  BrowserThread::PostTask( | 
| -      BrowserThread::UI, FROM_HERE, | 
| -      base::Bind(&Core::GetPermissionStatusOnUI, | 
| -                 base::Unretained(ui_core_.get()), | 
| -                 service_worker_registration->pattern().GetOrigin(), | 
| -                 user_visible, request_id)); | 
| -} | 
| - | 
| -void PushMessagingMessageFilter::Core::GetPermissionStatusOnUI( | 
| -    const GURL& requesting_origin, bool user_visible, int request_id) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| -  blink::WebPushPermissionStatus permission_status; | 
| -  PushMessagingService* push_service = service(); | 
| -  if (push_service) { | 
| -    if (!user_visible && !push_service->SupportNonVisibleMessages()) { | 
| -      Send(new PushMessagingMsg_GetPermissionStatusError( | 
| -          request_id, blink::WebPushError::ErrorTypeNotSupported)); | 
| -      return; | 
| -    } | 
| -    permission_status = | 
| -        push_service->GetPermissionStatus(requesting_origin, user_visible); | 
| -  } else if (is_incognito()) { | 
| -    // Return prompt, so the website can't detect incognito mode. | 
| -    permission_status = blink::WebPushPermissionStatusPrompt; | 
| -  } else { | 
| -    Send(new PushMessagingMsg_GetPermissionStatusError( | 
| -        request_id, blink::WebPushError::ErrorTypeAbort)); | 
| -    return; | 
| -  } | 
| -  Send(new PushMessagingMsg_GetPermissionStatusSuccess(request_id, | 
| -                                                       permission_status)); | 
| -} | 
| - | 
| -// Helper methods on both IO and UI threads, merged from | 
| -// PushMessagingMessageFilter and Core. | 
| -// ----------------------------------------------------------------------------- | 
| - | 
| -void PushMessagingMessageFilter::Core::GetEncryptionInfoOnUI( | 
| -    const GURL& origin, | 
| -    int64_t service_worker_registration_id, | 
| -    const std::string& sender_id, | 
| -    const PushMessagingService::EncryptionInfoCallback& io_thread_callback) { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| -  PushMessagingService* push_service = service(); | 
| -  if (push_service) { | 
| -    push_service->GetEncryptionInfo( | 
| -        origin, service_worker_registration_id, sender_id, | 
| -        base::Bind(&ForwardEncryptionInfoToIOThreadProxy, io_thread_callback)); | 
| -    return; | 
| -  } | 
| - | 
| -  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 
| -                          base::Bind(io_thread_callback, false /* success */, | 
| -                                     std::vector<uint8_t>() /* p256dh */, | 
| -                                     std::vector<uint8_t>() /* auth */)); | 
| -} | 
| - | 
| -void PushMessagingMessageFilter::Core::Send(IPC::Message* message) { | 
| -  BrowserThread::PostTask( | 
| -      BrowserThread::IO, FROM_HERE, | 
| -      base::Bind(&PushMessagingMessageFilter::SendIPC, io_parent_, | 
| -                 base::Passed(base::WrapUnique(message)))); | 
| -} | 
| - | 
| -void PushMessagingMessageFilter::SendIPC( | 
| -    std::unique_ptr<IPC::Message> message) { | 
| -  Send(message.release()); | 
| -} | 
| - | 
| -GURL PushMessagingMessageFilter::CreateEndpoint( | 
| -    bool standard_protocol, | 
| -    const std::string& subscription_id) const { | 
| -  const GURL& base = | 
| -      standard_protocol ? web_push_protocol_endpoint_ : default_endpoint_; | 
| - | 
| -  return GURL(base.spec() + subscription_id); | 
| -} | 
| - | 
| -PushMessagingService* PushMessagingMessageFilter::Core::service() { | 
| -  DCHECK_CURRENTLY_ON(BrowserThread::UI); | 
| -  RenderProcessHost* process_host = | 
| -      RenderProcessHost::FromID(render_process_id_); | 
| -  return process_host | 
| -             ? process_host->GetBrowserContext()->GetPushMessagingService() | 
| -             : nullptr; | 
| -} | 
| - | 
| -}  // namespace content | 
|  |