// 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.

#ifndef CONTENT_BROWSER_PUSH_MESSAGING_PUSH_MESSAGING_ROUTER_H_
#define CONTENT_BROWSER_PUSH_MESSAGING_PUSH_MESSAGING_ROUTER_H_

#include <stdint.h>

#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "content/common/service_worker/service_worker_status_code.h"
#include "content/public/common/push_messaging_status.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerEventResult.h"
#include "url/gurl.h"

namespace content {

class BrowserContext;
struct PushEventPayload;
class ServiceWorkerContextWrapper;
class ServiceWorkerRegistration;
class ServiceWorkerVersion;

class PushMessagingRouter {
 public:
  typedef base::Callback<void(PushDeliveryStatus)> DeliverMessageCallback;

  // Delivers a push message with |data| to the Service Worker identified by
  // |origin| and |service_worker_registration_id|. Must be called on the UI
  // thread.
  static void DeliverMessage(
      BrowserContext* browser_context,
      const GURL& origin,
      int64_t service_worker_registration_id,
      const PushEventPayload& payload,
      const DeliverMessageCallback& deliver_message_callback);

 private:
  // Attempts to find a Service Worker registration so that a push event can be
  // dispatched. Must be called on the IO thread.
  static void FindServiceWorkerRegistration(
      const GURL& origin,
      int64_t service_worker_registration_id,
      const PushEventPayload& payload,
      const DeliverMessageCallback& deliver_message_callback,
      scoped_refptr<ServiceWorkerContextWrapper> service_worker_context);

  // If a registration was successfully retrieved, dispatches a push event with
  // |data| on the Service Worker identified by |service_worker_registration|.
  // Must be called on the IO thread.
  static void FindServiceWorkerRegistrationCallback(
      const PushEventPayload& payload,
      const DeliverMessageCallback& deliver_message_callback,
      ServiceWorkerStatusCode service_worker_status,
      const scoped_refptr<ServiceWorkerRegistration>&
          service_worker_registration);

  // Delivers a push message with |data| to a specific |service_worker|. Must be
  // called on the IO thread, with the the worker running.
  static void DeliverMessageToWorker(
      const scoped_refptr<ServiceWorkerVersion>& service_worker,
      const scoped_refptr<ServiceWorkerRegistration>&
          service_worker_registration,
      const PushEventPayload& payload,
      const DeliverMessageCallback& deliver_message_callback);

  // Gets called asynchronously after the Service Worker has dispatched the push
  // event. Must be called on the IO thread.
  static void DeliverMessageEnd(
      const DeliverMessageCallback& deliver_message_callback,
      const scoped_refptr<ServiceWorkerRegistration>&
          service_worker_registration,
      ServiceWorkerStatusCode service_worker_status);

  DISALLOW_IMPLICIT_CONSTRUCTORS(PushMessagingRouter);
};

}  // namespace content

#endif  // CONTENT_BROWSER_PUSH_MESSAGING_PUSH_MESSAGING_ROUTER_H_
