// Copyright 2014 The Chromium Authors
// 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_manager.h"

#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "base/check_op.h"
#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "content/browser/bad_message.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/permissions/permission_controller_impl.h"
#include "content/browser/renderer_host/render_view_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/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_host.h"
#include "content/public/browser/permission_controller.h"
#include "content/public/browser/permission_descriptor_util.h"
#include "content/public/browser/permission_request_description.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_switches.h"
#include "third_party/blink/public/common/permissions/permission_utils.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
#include "third_party/blink/public/mojom/push_messaging/push_messaging.mojom.h"
#include "third_party/blink/public/mojom/push_messaging/push_messaging_status.mojom.h"
#include "url/origin.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 called from the SW and/or UI threads. Racey but ok, see
// https://groups.google.com/a/chromium.org/d/msg/chromium-dev/FNzZRJtN2aw/Aw0CWAXJJ1kJ
void RecordRegistrationStatus(blink::mojom::PushRegistrationStatus status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  UMA_HISTOGRAM_ENUMERATION("PushMessaging.RegistrationStatus", status);
}
void RecordUnregistrationStatus(blink::mojom::PushUnregistrationStatus status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  UMA_HISTOGRAM_ENUMERATION("PushMessaging.UnregistrationStatus", status);
}
void RecordGetRegistrationStatus(
    blink::mojom::PushGetRegistrationStatus status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  UMA_HISTOGRAM_ENUMERATION("PushMessaging.GetRegistrationStatus", status);
}

const char* PushUnregistrationStatusToString(
    blink::mojom::PushUnregistrationStatus status) {
  switch (status) {
    case blink::mojom::PushUnregistrationStatus::SUCCESS_UNREGISTERED:
      return "Unregistration successful - from push service";

    case blink::mojom::PushUnregistrationStatus::SUCCESS_WAS_NOT_REGISTERED:
      return "Unregistration successful - was not registered";

    case blink::mojom::PushUnregistrationStatus::PENDING_NETWORK_ERROR:
      return "Unregistration pending - a network error occurred, but it will "
             "be retried until it succeeds";

    case blink::mojom::PushUnregistrationStatus::NO_SERVICE_WORKER:
      return "Unregistration failed - no Service Worker";

    case blink::mojom::PushUnregistrationStatus::SERVICE_NOT_AVAILABLE:
      return "Unregistration failed - push service not available";

    case blink::mojom::PushUnregistrationStatus::PENDING_SERVICE_ERROR:
      return "Unregistration pending - a push service error occurred, but it "
             "will be retried until it succeeds";

    case blink::mojom::PushUnregistrationStatus::STORAGE_ERROR:
      return "Unregistration failed - storage error";

    case blink::mojom::PushUnregistrationStatus::NETWORK_ERROR:
      return "Unregistration failed - could not connect to push server";
  }
  NOTREACHED();
}

// Returns application_server_key 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 application_server_key is empty and the
// fallback is not a numeric gcm sender id.
std::string FixSenderInfo(const std::string& application_server_key,
                          const std::string& stored_sender_id) {
  if (!application_server_key.empty())
    return application_server_key;
  if (base::ContainsOnlyChars(stored_sender_id, "0123456789"))
    return stored_sender_id;
  return std::string();
}

bool IsRequestFromDocument(int render_frame_id) {
  return render_frame_id != ChildProcessHost::kInvalidUniqueID;
}

}  // namespace

struct PushMessagingManager::RegisterData {
  RegisterData() = default;
  RegisterData(RegisterData&& other) = default;

  blink::StorageKey requesting_storage_key{};
  int64_t service_worker_registration_id{0};
  std::optional<std::string> existing_subscription_id;
  blink::mojom::PushSubscriptionOptionsPtr options;
  SubscribeCallback callback;

  // True if the call to register was made with a user gesture.
  bool user_gesture;
};

PushMessagingManager::PushMessagingManager(
    RenderProcessHost& render_process_host,
    int render_frame_id,
    scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)
    : render_process_host_(render_process_host),
      render_frame_id_(render_frame_id),
      service_worker_context_(std::move(service_worker_context)),
      is_incognito_(
          render_process_host_->GetBrowserContext()->IsOffTheRecord()),
      service_available_(!!GetService()) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
}

PushMessagingManager::~PushMessagingManager() {}

void PushMessagingManager::AddPushMessagingReceiver(
    mojo::PendingReceiver<blink::mojom::PushMessaging> receiver) {
  receivers_.Add(this, std::move(receiver));
}

// Subscribe methods, merged in order of use.
// -----------------------------------------------------------------------------

void PushMessagingManager::Subscribe(
    int64_t service_worker_registration_id,
    blink::mojom::PushSubscriptionOptionsPtr options,
    bool user_gesture,
    SubscribeCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(options);

  RegisterData data;

  data.service_worker_registration_id = service_worker_registration_id;
  data.callback = std::move(callback);
  data.options = std::move(options);
  data.user_gesture = user_gesture;

  scoped_refptr<ServiceWorkerRegistration> service_worker_registration =
      service_worker_context_->GetLiveRegistration(
          data.service_worker_registration_id);
  if (!service_worker_registration ||
      !service_worker_registration->active_version()) {
    SendSubscriptionError(
        std::move(data),
        blink::mojom::PushRegistrationStatus::NO_SERVICE_WORKER);
    return;
  }

  // The renderer should have checked and disallowed the request for fenced
  // frames and thrown an exception in blink::PushManager. Report a bad message
  // if the renderer if the renderer side check didn't happen for some reason.
  if (service_worker_registration->ancestor_frame_type() ==
      blink::mojom::AncestorFrameType::kFencedFrame) {
    bad_message::ReceivedBadMessage(render_process_host_->GetDeprecatedID(),
                                    bad_message::PMM_SUBSCRIBE_IN_FENCED_FRAME);
    return;
  }

  const blink::StorageKey& storage_key = service_worker_registration->key();

  if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanAccessDataForOrigin(
          render_process_host_->GetDeprecatedID(), storage_key.origin())) {
    bad_message::ReceivedBadMessage(&*render_process_host_,
                                    bad_message::PMM_SUBSCRIBE_INVALID_ORIGIN);
    return;
  }

  data.requesting_storage_key = storage_key;

  DCHECK(!(data.options->application_server_key.empty() &&
           IsRequestFromDocument(render_frame_id_)));

  int64_t registration_id = data.service_worker_registration_id;
  service_worker_context_->GetRegistrationUserData(
      registration_id,
      {kPushRegistrationIdServiceWorkerKey, kPushSenderIdServiceWorkerKey},
      base::BindOnce(&PushMessagingManager::DidCheckForExistingRegistration,
                     weak_factory_.GetWeakPtr(), std::move(data)));
}

void PushMessagingManager::DidCheckForExistingRegistration(
    RegisterData data,
    const std::vector<std::string>& subscription_id_and_sender_id,
    blink::ServiceWorkerStatusCode service_worker_status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // Validate the stored subscription against the subscription request made by
  // the developer. The authorized entity must match.
  if (service_worker_status == blink::ServiceWorkerStatusCode::kOk) {
    DCHECK_EQ(2u, subscription_id_and_sender_id.size());

    const std::string& subscription_id = subscription_id_and_sender_id[0];
    const std::string& stored_sender_id = subscription_id_and_sender_id[1];

    const std::string application_server_key_string(
        data.options->application_server_key.begin(),
        data.options->application_server_key.end());

    std::string fixed_sender_id(
        FixSenderInfo(application_server_key_string, stored_sender_id));
    if (fixed_sender_id.empty()) {
      SendSubscriptionError(std::move(data),
                            blink::mojom::PushRegistrationStatus::NO_SENDER_ID);
      return;
    }

    if (fixed_sender_id != stored_sender_id) {
      SendSubscriptionError(
          std::move(data),
          blink::mojom::PushRegistrationStatus::SENDER_ID_MISMATCH);
      return;
    }

    data.existing_subscription_id = subscription_id;
  }

  // TODO(peter): Handle failures other than
  // blink::ServiceWorkerStatusCode::kErrorNotFound by rejecting
  // the subscription algorithm instead of trying to subscribe.

  if (!data.options->application_server_key.empty()) {
    Register(std::move(data));
  } else {
    // No |application_server_key| was provided by the developer. Fall back to
    // checking whether a previous subscription did identify a sender.
    int64_t registration_id = data.service_worker_registration_id;
    service_worker_context_->GetRegistrationUserData(
        registration_id, {kPushSenderIdServiceWorkerKey},
        base::BindOnce(&PushMessagingManager::DidGetSenderIdFromStorage,
                       weak_factory_.GetWeakPtr(), std::move(data)));
  }
}

void PushMessagingManager::DidGetSenderIdFromStorage(
    RegisterData data,
    const std::vector<std::string>& stored_sender_id,
    blink::ServiceWorkerStatusCode service_worker_status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
    SendSubscriptionError(std::move(data),
                          blink::mojom::PushRegistrationStatus::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->application_server_key.empty());

  const std::string application_server_key_string(
      std::string(data.options->application_server_key.begin(),
                  data.options->application_server_key.end()));
  std::string fixed_sender_id(
      FixSenderInfo(application_server_key_string, stored_sender_id[0]));
  if (fixed_sender_id.empty()) {
    SendSubscriptionError(std::move(data),
                          blink::mojom::PushRegistrationStatus::NO_SENDER_ID);
    return;
  }
  data.options->application_server_key =
      std::vector<uint8_t>(fixed_sender_id.begin(), fixed_sender_id.end());
  Register(std::move(data));
}

void PushMessagingManager::Register(PushMessagingManager::RegisterData data) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  PushMessagingService* push_service = GetService();
  if (!push_service) {
    if (!is_incognito_) {
      // This might happen if InstanceIDProfileService::IsInstanceIDEnabled
      // returns false because the Instance ID kill switch was enabled.
      SendSubscriptionError(
          std::move(data),
          blink::mojom::PushRegistrationStatus::SERVICE_NOT_AVAILABLE);
    } else {
      // Prevent websites from detecting incognito mode, by emulating what would
      // have happened if we had a PushMessagingService available.
      if (!IsRequestFromDocument(render_frame_id_) ||
          !data.options->user_visible_only) {
        // Throw a permission denied error under the same circumstances.
        SendSubscriptionError(
            std::move(data),
            blink::mojom::PushRegistrationStatus::INCOGNITO_PERMISSION_DENIED);
      } else {
        RenderFrameHostImpl* render_frame_host_impl =
            RenderFrameHostImpl::FromID(render_process_host_->GetDeprecatedID(),
                                        render_frame_id_);
        if (render_frame_host_impl) {
          render_frame_host_impl->AddMessageToConsole(
              blink::mojom::ConsoleMessageLevel::kError,
              kIncognitoPushUnsupportedMessage);

          // Request notifications permission (which will fail, since
          // notifications aren't supported in incognito), so the website can't
          // detect whether incognito is active.
          bool user_gesture = data.user_gesture;

          DCHECK_EQ(data.requesting_storage_key,
                    render_frame_host_impl->GetStorageKey());

          render_frame_host_impl->GetBrowserContext()
              ->GetPermissionController()
              ->RequestPermissionFromCurrentDocument(
                  render_frame_host_impl,
                  PermissionRequestDescription(
                      PermissionDescriptorUtil::
                          CreatePermissionDescriptorForPermissionType(
                              blink::PermissionType::NOTIFICATIONS),
                      user_gesture),
                  base::BindOnce(
                      &PushMessagingManager::DidRequestPermissionInIncognito,
                      AsWeakPtr(), std::move(data)));
        }
      }
    }
    return;
  }

  int64_t registration_id = data.service_worker_registration_id;
  url::Origin requesting_origin = data.requesting_storage_key.origin();
  bool user_gesture = data.user_gesture;

  auto options = data.options->Clone();
  if (IsRequestFromDocument(render_frame_id_)) {
    push_service->SubscribeFromDocument(
        requesting_origin.GetURL(), registration_id,
        render_process_host_->GetDeprecatedID(), render_frame_id_,
        std::move(options), user_gesture,
        base::BindOnce(&PushMessagingManager::DidRegister, AsWeakPtr(),
                       std::move(data)));
  } else {
    push_service->SubscribeFromWorker(
        requesting_origin.GetURL(), registration_id,
        render_process_host_->GetDeprecatedID(), std::move(options),
        base::BindOnce(&PushMessagingManager::DidRegister, AsWeakPtr(),
                       std::move(data)));
  }
}

void PushMessagingManager::DidRequestPermissionInIncognito(
    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);
  SendSubscriptionError(
      std::move(data),
      blink::mojom::PushRegistrationStatus::INCOGNITO_PERMISSION_DENIED);
}

// TODO(crbug.com/40139581): Handle expiration_time that is passed from push
// service check if |expiration_time| is valid before saving it in |data| and
// passing it back in SendSubscriptionSuccess.
void PushMessagingManager::DidRegister(
    RegisterData data,
    const std::string& push_subscription_id,
    const GURL& endpoint,
    const std::optional<base::Time>& expiration_time,
    const std::vector<uint8_t>& p256dh,
    const std::vector<uint8_t>& auth,
    blink::mojom::PushRegistrationStatus status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // TODO(crbug.com/41275327): Handle the case where |push_subscription_id| and
  // |data.existing_subscription_id| are not the same. Right now we just
  // override the old subscription ID and encryption information.
  const bool subscription_changed =
      data.existing_subscription_id.has_value() &&
      data.existing_subscription_id.value() != push_subscription_id;

  if (status ==
      blink::mojom::PushRegistrationStatus::SUCCESS_FROM_PUSH_SERVICE) {
    PersistRegistration(
        std::move(data), push_subscription_id, endpoint, expiration_time,
        p256dh, auth,
        subscription_changed
            ? blink::mojom::PushRegistrationStatus::
                  SUCCESS_NEW_SUBSCRIPTION_FROM_PUSH_SERVICE
            : blink::mojom::PushRegistrationStatus::SUCCESS_FROM_PUSH_SERVICE);
  } else {
    // TODO(crbug.com/41275327): for invalid |expiration_time| send a
    // subscription error with a new PushRegistrationStatus
    SendSubscriptionError(std::move(data), status);
  }
}

void PushMessagingManager::PersistRegistration(
    RegisterData data,
    const std::string& push_subscription_id,
    const GURL& endpoint,
    const std::optional<base::Time>& expiration_time,
    const std::vector<uint8_t>& p256dh,
    const std::vector<uint8_t>& auth,
    blink::mojom::PushRegistrationStatus status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  blink::StorageKey storage_key = data.requesting_storage_key;
  int64_t registration_id = data.service_worker_registration_id;
  std::string application_server_key(
      std::string(data.options->application_server_key.begin(),
                  data.options->application_server_key.end()));

  service_worker_context_->StoreRegistrationUserData(
      registration_id, std::move(storage_key),
      {{kPushRegistrationIdServiceWorkerKey, push_subscription_id},
       {kPushSenderIdServiceWorkerKey, application_server_key}},
      base::BindOnce(&PushMessagingManager::DidPersistRegistration,
                     weak_factory_.GetWeakPtr(), std::move(data), endpoint,
                     expiration_time, p256dh, auth, status));
}

void PushMessagingManager::DidPersistRegistration(
    RegisterData data,
    const GURL& endpoint,
    const std::optional<base::Time>& expiration_time,
    const std::vector<uint8_t>& p256dh,
    const std::vector<uint8_t>& auth,
    blink::mojom::PushRegistrationStatus push_registration_status,
    blink::ServiceWorkerStatusCode service_worker_status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (service_worker_status == blink::ServiceWorkerStatusCode::kOk) {
    SendSubscriptionSuccess(std::move(data), push_registration_status, endpoint,
                            expiration_time, p256dh, auth);
  } else {
    // TODO(johnme): Unregister, so PushMessagingServiceImpl can decrease count.
    SendSubscriptionError(std::move(data),
                          blink::mojom::PushRegistrationStatus::STORAGE_ERROR);
  }
}

void PushMessagingManager::SendSubscriptionError(
    RegisterData data,
    blink::mojom::PushRegistrationStatus status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  std::move(data.callback).Run(status, nullptr /* subscription */);
  RecordRegistrationStatus(status);
}

void PushMessagingManager::SendSubscriptionSuccess(
    RegisterData data,
    blink::mojom::PushRegistrationStatus status,
    const GURL& endpoint,
    const std::optional<base::Time>& expiration_time,
    const std::vector<uint8_t>& p256dh,
    const std::vector<uint8_t>& auth) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  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(!is_incognito_);
    SendSubscriptionError(
        std::move(data),
        blink::mojom::PushRegistrationStatus::SERVICE_NOT_AVAILABLE);
    return;
  }

  std::move(data.callback)
      .Run(status, blink::mojom::PushSubscription::New(
                       endpoint, expiration_time, std::move(data.options),
                       p256dh, auth));

  RecordRegistrationStatus(status);
}

// Unsubscribe methods, merged in order of use.
// -----------------------------------------------------------------------------

void PushMessagingManager::Unsubscribe(int64_t service_worker_registration_id,
                                       UnsubscribeCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  scoped_refptr<ServiceWorkerRegistration> service_worker_registration =
      service_worker_context_->GetLiveRegistration(
          service_worker_registration_id);
  if (!service_worker_registration) {
    DidUnregister(std::move(callback),
                  blink::mojom::PushUnregistrationStatus::NO_SERVICE_WORKER);
    return;
  }

  const url::Origin& origin = service_worker_registration->key().origin();

  if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanAccessDataForOrigin(
          render_process_host_->GetDeprecatedID(), origin)) {
    bad_message::ReceivedBadMessage(
        &*render_process_host_, bad_message::PMM_UNSUBSCRIBE_INVALID_ORIGIN);
    return;
  }

  service_worker_context_->GetRegistrationUserData(
      service_worker_registration_id, {kPushSenderIdServiceWorkerKey},
      base::BindOnce(&PushMessagingManager::UnsubscribeHavingGottenSenderId,
                     weak_factory_.GetWeakPtr(), std::move(callback),
                     service_worker_registration_id, origin));
}

void PushMessagingManager::UnsubscribeHavingGottenSenderId(
    UnsubscribeCallback callback,
    int64_t service_worker_registration_id,
    const url::Origin& requesting_origin,
    const std::vector<std::string>& sender_ids,
    blink::ServiceWorkerStatusCode service_worker_status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  std::string sender_id;
  if (service_worker_status == blink::ServiceWorkerStatusCode::kOk) {
    DCHECK_EQ(1u, sender_ids.size());
    sender_id = sender_ids[0];
  }

  PushMessagingService* push_service = GetService();
  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_);
    DidUnregister(
        std::move(callback),
        blink::mojom::PushUnregistrationStatus::SERVICE_NOT_AVAILABLE);
    return;
  }

  push_service->Unsubscribe(
      blink::mojom::PushUnregistrationReason::JAVASCRIPT_API,
      requesting_origin.GetURL(), service_worker_registration_id, sender_id,
      base::BindOnce(&PushMessagingManager::DidUnregister, AsWeakPtr(),
                     std::move(callback)));
}

void PushMessagingManager::DidUnregister(
    UnsubscribeCallback callback,
    blink::mojom::PushUnregistrationStatus unregistration_status) {
  // Only called from SW thread, but would be safe to call from UI thread.
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  switch (unregistration_status) {
    case blink::mojom::PushUnregistrationStatus::SUCCESS_UNREGISTERED:
    case blink::mojom::PushUnregistrationStatus::PENDING_NETWORK_ERROR:
    case blink::mojom::PushUnregistrationStatus::PENDING_SERVICE_ERROR:
      std::move(callback).Run(blink::mojom::PushErrorType::NONE,
                              true /* did_unsubscribe */,
                              std::nullopt /* error_message */);
      break;
    case blink::mojom::PushUnregistrationStatus::SUCCESS_WAS_NOT_REGISTERED:
      std::move(callback).Run(blink::mojom::PushErrorType::NONE,
                              false /* did_unsubscribe */,
                              std::nullopt /* error_message */);
      break;
    case blink::mojom::PushUnregistrationStatus::NO_SERVICE_WORKER:
    case blink::mojom::PushUnregistrationStatus::SERVICE_NOT_AVAILABLE:
    case blink::mojom::PushUnregistrationStatus::STORAGE_ERROR:
      std::move(callback).Run(blink::mojom::PushErrorType::ABORT, false,
                              std::string(PushUnregistrationStatusToString(
                                  unregistration_status)) /* error_message */);
      break;
    case blink::mojom::PushUnregistrationStatus::NETWORK_ERROR:
      NOTREACHED();
  }
  RecordUnregistrationStatus(unregistration_status);
}

// GetSubscription methods, merged in order of use.
// -----------------------------------------------------------------------------

void PushMessagingManager::GetSubscription(
    int64_t service_worker_registration_id,
    GetSubscriptionCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  scoped_refptr<ServiceWorkerRegistration> registration =
      service_worker_context_->GetLiveRegistration(
          service_worker_registration_id);
  if (registration) {
    if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanAccessDataForOrigin(
            render_process_host_->GetDeprecatedID(),
            registration->key().origin())) {
      bad_message::ReceivedBadMessage(
          &*render_process_host_,
          bad_message::PMM_GET_SUBSCRIPTION_INVALID_ORIGIN);
      return;
    }
  }

  service_worker_context_->GetRegistrationUserData(
      service_worker_registration_id,
      {kPushRegistrationIdServiceWorkerKey, kPushSenderIdServiceWorkerKey},
      base::BindOnce(&PushMessagingManager::DidGetSubscription,
                     weak_factory_.GetWeakPtr(), std::move(callback),
                     service_worker_registration_id));
}

void PushMessagingManager::DidGetSubscription(
    GetSubscriptionCallback callback,
    int64_t service_worker_registration_id,
    const std::vector<std::string>&
        push_subscription_id_and_application_server_key,
    blink::ServiceWorkerStatusCode service_worker_status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  blink::mojom::PushGetRegistrationStatus get_status =
      blink::mojom::PushGetRegistrationStatus::STORAGE_ERROR;
  switch (service_worker_status) {
    case blink::ServiceWorkerStatusCode::kOk: {
      DCHECK_EQ(2u, push_subscription_id_and_application_server_key.size());
      const std::string& push_subscription_id =
          push_subscription_id_and_application_server_key[0];
      const std::string& application_server_key =
          push_subscription_id_and_application_server_key[1];

      if (!service_available_) {
        // Return not found in incognito mode, so websites can't detect it.
        get_status = is_incognito_ ? blink::mojom::PushGetRegistrationStatus::
                                         INCOGNITO_REGISTRATION_NOT_FOUND
                                   : blink::mojom::PushGetRegistrationStatus::
                                         SERVICE_NOT_AVAILABLE;
        break;
      }

      scoped_refptr<ServiceWorkerRegistration> registration =
          service_worker_context_->GetLiveRegistration(
              service_worker_registration_id);
      if (!registration) {
        get_status =
            blink::mojom::PushGetRegistrationStatus::NO_LIVE_SERVICE_WORKER;
        break;
      }

      const url::Origin& origin = registration->key().origin();

      GetSubscriptionInfo(
          origin, service_worker_registration_id, application_server_key,
          push_subscription_id,
          base::BindOnce(&PushMessagingManager::GetSubscriptionDidGetInfo,
                         AsWeakPtr(), std::move(callback), origin,
                         service_worker_registration_id,
                         application_server_key));

      return;
    }
    case blink::ServiceWorkerStatusCode::kErrorNotFound: {
      get_status =
          blink::mojom::PushGetRegistrationStatus::REGISTRATION_NOT_FOUND;
      break;
    }
    case blink::ServiceWorkerStatusCode::kErrorFailed: {
      get_status = blink::mojom::PushGetRegistrationStatus::STORAGE_ERROR;
      break;
    }
    case blink::ServiceWorkerStatusCode::kErrorAbort:
    case blink::ServiceWorkerStatusCode::kErrorStartWorkerFailed:
    case blink::ServiceWorkerStatusCode::kErrorProcessNotFound:
    case blink::ServiceWorkerStatusCode::kErrorExists:
    case blink::ServiceWorkerStatusCode::kErrorInstallWorkerFailed:
    case blink::ServiceWorkerStatusCode::kErrorActivateWorkerFailed:
    case blink::ServiceWorkerStatusCode::kErrorIpcFailed:
    case blink::ServiceWorkerStatusCode::kErrorNetwork:
    case blink::ServiceWorkerStatusCode::kErrorSecurity:
    case blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected:
    case blink::ServiceWorkerStatusCode::kErrorState:
    case blink::ServiceWorkerStatusCode::kErrorTimeout:
    case blink::ServiceWorkerStatusCode::kErrorScriptEvaluateFailed:
    case blink::ServiceWorkerStatusCode::kErrorDiskCache:
    case blink::ServiceWorkerStatusCode::kErrorRedundant:
    case blink::ServiceWorkerStatusCode::kErrorDisallowed:
    case blink::ServiceWorkerStatusCode::kErrorInvalidArguments:
    case blink::ServiceWorkerStatusCode::kErrorStorageDisconnected:
    case blink::ServiceWorkerStatusCode::kErrorStorageDataCorrupted: {
      DUMP_WILL_BE_NOTREACHED()
          << "Got unexpected error code: "
          << static_cast<uint32_t>(service_worker_status) << " "
          << blink::ServiceWorkerStatusToString(service_worker_status);
      get_status = blink::mojom::PushGetRegistrationStatus::STORAGE_ERROR;
      break;
    }
  }
  std::move(callback).Run(get_status, nullptr /* subscription */);
  RecordGetRegistrationStatus(get_status);
}

void PushMessagingManager::GetSubscriptionDidGetInfo(
    GetSubscriptionCallback callback,
    const url::Origin& origin,
    int64_t service_worker_registration_id,
    const std::string& application_server_key,
    bool is_valid,
    const GURL& endpoint,
    const std::optional<base::Time>& expiration_time,
    const std::vector<uint8_t>& p256dh,
    const std::vector<uint8_t>& auth) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (is_valid) {
    auto options = blink::mojom::PushSubscriptionOptions::New();

    // 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->application_server_key = std::vector<uint8_t>(
        application_server_key.begin(), application_server_key.end());

    blink::mojom::PushGetRegistrationStatus status =
        blink::mojom::PushGetRegistrationStatus::SUCCESS;

    std::move(callback).Run(status, blink::mojom::PushSubscription::New(
                                        endpoint, expiration_time,
                                        std::move(options), p256dh, auth));

    RecordGetRegistrationStatus(status);
  } else {
    PushMessagingService* push_service = GetService();
    if (!push_service) {
      // Shouldn't be possible to have a stored push subscription in a profile
      // with no push service, but this case can occur when the renderer is
      // shutting down.
      std::move(callback).Run(
          blink::mojom::PushGetRegistrationStatus::RENDERER_SHUTDOWN,
          nullptr /* subscription */);
      return;
    }

    // Uh-oh! Although there was a cached subscription in the Service Worker
    // database, it did not have matching counterparts in the
    // PushMessagingAppIdentifier map and/or GCM Store. Unsubscribe to fix this
    // inconsistency.
    blink::mojom::PushGetRegistrationStatus status =
        blink::mojom::PushGetRegistrationStatus::STORAGE_CORRUPT;

    push_service->Unsubscribe(
        blink::mojom::PushUnregistrationReason::
            GET_SUBSCRIPTION_STORAGE_CORRUPT,
        origin.GetURL(), service_worker_registration_id, application_server_key,
        base::BindOnce(&PushMessagingManager::GetSubscriptionDidUnsubscribe,
                       AsWeakPtr(), std::move(callback), status));

    RecordGetRegistrationStatus(status);
  }
}

void PushMessagingManager::GetSubscriptionDidUnsubscribe(
    GetSubscriptionCallback callback,
    blink::mojom::PushGetRegistrationStatus get_status,
    blink::mojom::PushUnregistrationStatus unsubscribe_status) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  std::move(callback).Run(get_status, nullptr /* subscription */);
}

void PushMessagingManager::GetSubscriptionInfo(
    const url::Origin& origin,
    int64_t service_worker_registration_id,
    const std::string& sender_id,
    const std::string& push_subscription_id,
    PushMessagingService::SubscriptionInfoCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  PushMessagingService* push_service = GetService();
  if (!push_service) {
    std::move(callback).Run(false /* is_valid */, GURL() /* endpoint */,
                            std::nullopt /* expiration_time */,
                            std::vector<uint8_t>() /* p256dh */,
                            std::vector<uint8_t>() /* auth */);
    return;
  }

  push_service->GetSubscriptionInfo(origin.GetURL(),
                                    service_worker_registration_id, sender_id,
                                    push_subscription_id, std::move(callback));
}

PushMessagingService* PushMessagingManager::GetService() {
  return render_process_host_->GetBrowserContext()->GetPushMessagingService();
}

}  // namespace content
