// 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 "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/metrics/histogram.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/push_messaging_service.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/push_messaging_status.h"
#include "third_party/WebKit/public/platform/modules/push_messaging/WebPushPermissionStatus.h"

namespace content {

const char kPushSenderIdServiceWorkerKey[] = "push_sender_id";
const char kPushRegistrationIdServiceWorkerKey[] = "push_registration_id";

namespace {

// 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);
}

// Concatenates the subscription id with the endpoint base to create a new
// GURL object containing the endpoint unique to the subscription.
GURL CreatePushEndpoint(const GURL& push_endpoint_base,
                        const std::string& push_subscription_id) {
  return GURL(push_endpoint_base.spec() + "/" + push_subscription_id);
}

}  // 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;
  bool user_visible;
  // 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, const std::string& sender_id);

  // 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 (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 DidRegister(const RegisterData& data,
                   const std::string& push_registration_id,
                   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),
      user_visible(false),
      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* push_service = ui_core_->service();
  if (push_service)
    push_endpoint_base_ = push_service->GetPushEndpoint();
}

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_SubscribeFromDocument,
                        OnSubscribeFromDocument)
    IPC_MESSAGE_HANDLER(PushMessagingHostMsg_SubscribeFromWorker,
                        OnSubscribeFromWorker)
    IPC_MESSAGE_HANDLER(PushMessagingHostMsg_Unsubscribe,
                        OnUnsubscribe)
    IPC_MESSAGE_HANDLER(PushMessagingHostMsg_GetRegistration, OnGetRegistration)
    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::OnSubscribeFromDocument(
    int render_frame_id,
    int request_id,
    const std::string& sender_id,
    bool user_visible,
    int64_t service_worker_registration_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  // TODO(mvanouwerkerk): Validate arguments?
  RegisterData data;
  data.request_id = request_id;
  data.service_worker_registration_id = service_worker_registration_id;
  data.render_frame_id = render_frame_id;
  data.user_visible = user_visible;

  ServiceWorkerRegistration* service_worker_registration =
      service_worker_context_->GetLiveRegistration(
          service_worker_registration_id);
  if (!service_worker_registration ||
      !service_worker_registration->active_version()) {
    SendRegisterError(data, PUSH_REGISTRATION_STATUS_NO_SERVICE_WORKER);
    return;
  }
  data.requesting_origin = service_worker_registration->pattern().GetOrigin();

  service_worker_context_->StoreRegistrationUserData(
      service_worker_registration_id,
      data.requesting_origin,
      kPushSenderIdServiceWorkerKey,
      sender_id,
      base::Bind(&PushMessagingMessageFilter::DidPersistSenderId,
                 weak_factory_io_to_io_.GetWeakPtr(),
                 data, sender_id));
}

void PushMessagingMessageFilter::OnSubscribeFromWorker(
    int request_id,
    int64_t service_worker_registration_id,
    bool user_visible) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  RegisterData data;
  data.request_id = request_id;
  data.service_worker_registration_id = service_worker_registration_id;
  data.user_visible = user_visible;

  ServiceWorkerRegistration* service_worker_registration =
      service_worker_context_->GetLiveRegistration(
          service_worker_registration_id);
  if (!service_worker_registration) {
    SendRegisterError(data, PUSH_REGISTRATION_STATUS_NO_SERVICE_WORKER);
    return;
  }
  data.requesting_origin = service_worker_registration->pattern().GetOrigin();

  // This sender_id will be ignored; instead it will be fetched from storage.
  CheckForExistingRegistration(data, std::string() /* sender_id */);
}

void PushMessagingMessageFilter::DidPersistSenderId(
    const RegisterData& data,
    const std::string& sender_id,
    ServiceWorkerStatusCode service_worker_status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (service_worker_status != SERVICE_WORKER_OK)
    SendRegisterError(data, PUSH_REGISTRATION_STATUS_STORAGE_ERROR);
  else
    CheckForExistingRegistration(data, sender_id);
}

void PushMessagingMessageFilter::CheckForExistingRegistration(
    const RegisterData& data,
    const std::string& sender_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  service_worker_context_->GetRegistrationUserData(
      data.service_worker_registration_id,
      kPushRegistrationIdServiceWorkerKey,
      base::Bind(&PushMessagingMessageFilter::DidCheckForExistingRegistration,
                 weak_factory_io_to_io_.GetWeakPtr(), data, sender_id));
}

void PushMessagingMessageFilter::DidCheckForExistingRegistration(
    const RegisterData& data,
    const std::string& sender_id,
    const std::string& push_registration_id,
    ServiceWorkerStatusCode service_worker_status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (service_worker_status == SERVICE_WORKER_OK) {
    SendRegisterSuccess(data, PUSH_REGISTRATION_STATUS_SUCCESS_FROM_CACHE,
                        push_registration_id);
    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.FromDocument()) {
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        base::Bind(&Core::RegisterOnUI, base::Unretained(ui_core_.get()),
                   data, sender_id));
  } else {
    service_worker_context_->GetRegistrationUserData(
        data.service_worker_registration_id,
        kPushSenderIdServiceWorkerKey,
        base::Bind(&PushMessagingMessageFilter::DidGetSenderIdFromStorage,
                   weak_factory_io_to_io_.GetWeakPtr(), data));
  }
}

void PushMessagingMessageFilter::DidGetSenderIdFromStorage(
    const RegisterData& data,
    const std::string& sender_id,
    ServiceWorkerStatusCode service_worker_status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (service_worker_status != SERVICE_WORKER_OK) {
    SendRegisterError(data, PUSH_REGISTRATION_STATUS_NO_SENDER_ID);
    return;
  }
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::Bind(&Core::RegisterOnUI, base::Unretained(ui_core_.get()),
                 data, sender_id));
}

void PushMessagingMessageFilter::Core::RegisterOnUI(
    const PushMessagingMessageFilter::RegisterData& data,
    const std::string& sender_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  PushMessagingService* push_service = service();
  if (!push_service) {
    if (!is_incognito()) {
      // TODO(johnme): Might be better not to expose the API in this case.
      BrowserThread::PostTask(
          BrowserThread::IO, FROM_HERE,
          base::Bind(&PushMessagingMessageFilter::SendRegisterError,
                     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.user_visible) {
        // Throw a permission denied error under the same circumstances.
        BrowserThread::PostTask(
            BrowserThread::IO, FROM_HERE,
            base::Bind(&PushMessagingMessageFilter::SendRegisterError,
                       io_parent_,
                       data,
                       PUSH_REGISTRATION_STATUS_INCOGNITO_PERMISSION_DENIED));
      }
      // Else leave the promise hanging forever, to simulate a user ignoring the
      // infobar. TODO(johnme): Simulate the user dismissing the infobar after a
      // random time period.
    }
    return;
  }

  if (data.FromDocument()) {
    push_service->SubscribeFromDocument(
        data.requesting_origin, data.service_worker_registration_id, sender_id,
        render_process_id_, data.render_frame_id, data.user_visible,
        base::Bind(&Core::DidRegister, weak_factory_ui_to_ui_.GetWeakPtr(),
                   data));
  } else {
    push_service->SubscribeFromWorker(
        data.requesting_origin, data.service_worker_registration_id, sender_id,
        data.user_visible,
        base::Bind(&Core::DidRegister, weak_factory_ui_to_ui_.GetWeakPtr(),
                   data));
  }
}

void PushMessagingMessageFilter::Core::DidRegister(
    const RegisterData& data,
    const std::string& push_registration_id,
    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));
  } else {
    BrowserThread::PostTask(
        BrowserThread::IO, FROM_HERE,
        base::Bind(&PushMessagingMessageFilter::SendRegisterError, io_parent_,
                   data, status));
  }
}

void PushMessagingMessageFilter::PersistRegistrationOnIO(
    const RegisterData& data,
    const std::string& push_registration_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  service_worker_context_->StoreRegistrationUserData(
      data.service_worker_registration_id,
      data.requesting_origin,
      kPushRegistrationIdServiceWorkerKey,
      push_registration_id,
      base::Bind(&PushMessagingMessageFilter::DidPersistRegistrationOnIO,
                 weak_factory_io_to_io_.GetWeakPtr(),
                 data, push_registration_id));
}

void PushMessagingMessageFilter::DidPersistRegistrationOnIO(
    const RegisterData& data,
    const std::string& push_registration_id,
    ServiceWorkerStatusCode service_worker_status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (service_worker_status == SERVICE_WORKER_OK) {
    SendRegisterSuccess(data,
                        PUSH_REGISTRATION_STATUS_SUCCESS_FROM_PUSH_SERVICE,
                        push_registration_id);
  } else {
    // TODO(johnme): Unregister, so PushMessagingServiceImpl can decrease count.
    SendRegisterError(data, PUSH_REGISTRATION_STATUS_STORAGE_ERROR);
  }
}

void PushMessagingMessageFilter::SendRegisterError(
    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::SendRegisterSuccess(
    const RegisterData& data,
    PushRegistrationStatus status,
    const std::string& push_registration_id) {
  // Only called from IO thread, but would be safe to call from UI thread.
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (push_endpoint_base_.is_empty()) {
    // 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());
    SendRegisterError(data, PUSH_REGISTRATION_STATUS_SERVICE_NOT_AVAILABLE);
    return;
  }
  if (data.FromDocument()) {
    Send(new PushMessagingMsg_SubscribeFromDocumentSuccess(
        data.render_frame_id,
        data.request_id,
        CreatePushEndpoint(push_endpoint_base_, push_registration_id)));
  } else {
    Send(new PushMessagingMsg_SubscribeFromWorkerSuccess(
        data.request_id,
        CreatePushEndpoint(push_endpoint_base_, push_registration_id)));
  }
  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,
      kPushRegistrationIdServiceWorkerKey,
      base::Bind(&PushMessagingMessageFilter::
                     UnsubscribeHavingGottenPushSubscriptionId,
                 weak_factory_io_to_io_.GetWeakPtr(), request_id,
                 service_worker_registration_id,
                 service_worker_registration->pattern().GetOrigin()));
}

void PushMessagingMessageFilter::UnsubscribeHavingGottenPushSubscriptionId(
    int request_id,
    int64_t service_worker_registration_id,
    const GURL& requesting_origin,
    const std::string& push_subscription_id,  // Unused, we just want the status
    ServiceWorkerStatusCode service_worker_status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (service_worker_status == SERVICE_WORKER_OK) {
    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,
            requesting_origin));
  } else {
    // Errors are handled the same, whether we were trying to get the
    // push_subscription_id or the sender_id.
    UnsubscribeHavingGottenSenderId(request_id, service_worker_registration_id,
                                    requesting_origin,
                                    std::string() /* sender_id */,
                                    service_worker_status);
  }
}

void PushMessagingMessageFilter::UnsubscribeHavingGottenSenderId(
    int request_id,
    int64_t service_worker_registration_id,
    const GURL& requesting_origin,
    const std::string& sender_id,
    ServiceWorkerStatusCode service_worker_status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  switch (service_worker_status) {
    case SERVICE_WORKER_OK:
      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));
      break;
    case SERVICE_WORKER_ERROR_NOT_FOUND:
      // We did not find a registration, stop here and notify the renderer that
      // it was a success even though we did not unregister.
      DidUnregister(request_id,
                    PUSH_UNREGISTRATION_STATUS_SUCCESS_WAS_NOT_REGISTERED);
      break;
    case SERVICE_WORKER_ERROR_FAILED:
      DidUnregister(request_id,
                    PUSH_UNREGISTRATION_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_MAX_VALUE:
      NOTREACHED() << "Got unexpected error code: " << service_worker_status
                   << " " << ServiceWorkerStatusToString(service_worker_status);
      DidUnregister(request_id, PUSH_UNREGISTRATION_STATUS_STORAGE_ERROR);
      break;
  }
}

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);

  switch (unregistration_status) {
    case PUSH_UNREGISTRATION_STATUS_SUCCESS_UNREGISTERED:
    case PUSH_UNREGISTRATION_STATUS_SUCCESS_WAS_NOT_REGISTERED:
    case PUSH_UNREGISTRATION_STATUS_PENDING_NETWORK_ERROR:
    case PUSH_UNREGISTRATION_STATUS_PENDING_SERVICE_ERROR:
      BrowserThread::PostTask(
          BrowserThread::IO, FROM_HERE,
          base::Bind(&PushMessagingMessageFilter::ClearRegistrationData,
                     io_parent_, request_id, service_worker_registration_id,
                     unregistration_status));
      break;
    case PUSH_UNREGISTRATION_STATUS_NO_SERVICE_WORKER:
    case PUSH_UNREGISTRATION_STATUS_SERVICE_NOT_AVAILABLE:
    case PUSH_UNREGISTRATION_STATUS_STORAGE_ERROR:
    case PUSH_UNREGISTRATION_STATUS_NETWORK_ERROR:
      NOTREACHED();
      break;
  }
}

void PushMessagingMessageFilter::ClearRegistrationData(
    int request_id,
    int64_t service_worker_registration_id,
    PushUnregistrationStatus unregistration_status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  service_worker_context_->ClearRegistrationUserData(
      service_worker_registration_id,
      kPushRegistrationIdServiceWorkerKey,
      base::Bind(&PushMessagingMessageFilter::DidClearRegistrationData,
                 weak_factory_io_to_io_.GetWeakPtr(),
                 request_id, unregistration_status));
}

void PushMessagingMessageFilter::DidClearRegistrationData(
    int request_id,
    PushUnregistrationStatus unregistration_status,
    ServiceWorkerStatusCode service_worker_status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (service_worker_status != SERVICE_WORKER_OK &&
      service_worker_status != SERVICE_WORKER_ERROR_NOT_FOUND) {
    unregistration_status = PUSH_UNREGISTRATION_STATUS_STORAGE_ERROR;
    DLOG(WARNING) << "Got unexpected error code: " << service_worker_status
                  << " " << ServiceWorkerStatusToString(service_worker_status);
  }

  DidUnregister(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);
}

// GetRegistration methods on both IO and UI threads, merged in order of use
// from PushMessagingMessageFilter and Core.
// -----------------------------------------------------------------------------

void PushMessagingMessageFilter::OnGetRegistration(
    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,
      base::Bind(&PushMessagingMessageFilter::DidGetRegistration,
                 weak_factory_io_to_io_.GetWeakPtr(), request_id));
}

void PushMessagingMessageFilter::DidGetRegistration(
    int request_id,
    const std::string& push_registration_id,
    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:
      if (push_endpoint_base_.is_empty()) {
        // 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;
      }

      Send(new PushMessagingMsg_GetRegistrationSuccess(
          request_id,
          CreatePushEndpoint(push_endpoint_base_, push_registration_id)));
      RecordGetRegistrationStatus(PUSH_GETREGISTRATION_STATUS_SUCCESS);
      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_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_GetRegistrationError(request_id, get_status));
  RecordGetRegistrationStatus(get_status);
}

// 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;
    }
    GURL embedding_origin = requesting_origin;
    permission_status = push_service->GetPermissionStatus(requesting_origin,
                                                          embedding_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::Send(IPC::Message* message) {
  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      base::Bind(&PushMessagingMessageFilter::SendIPC, io_parent_,
                 base::Passed(make_scoped_ptr(message))));
}

void PushMessagingMessageFilter::SendIPC(scoped_ptr<IPC::Message> message) {
  Send(message.release());
}

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
