Push API: dispatch push event to service worker.

BUG=350377

Depends on https://codereview.chromium.org/404353003/

Review URL: https://codereview.chromium.org/340773006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@288023 0039d316-1c4b-4281-b951-d872f2087c98
parent 069c1d40
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "chrome/common/pref_names.h" #include "chrome/common/pref_names.h"
#include "components/gcm_driver/gcm_driver.h" #include "components/gcm_driver/gcm_driver.h"
#include "components/pref_registry/pref_registry_syncable.h" #include "components/pref_registry/pref_registry_syncable.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
...@@ -109,9 +110,16 @@ void PushMessagingServiceImpl::OnMessage( ...@@ -109,9 +110,16 @@ void PushMessagingServiceImpl::OnMessage(
DCHECK(application_id.IsValid()); DCHECK(application_id.IsValid());
GCMClient::MessageData::const_iterator it = message.data.find("data"); GCMClient::MessageData::const_iterator it = message.data.find("data");
if (application_id.IsValid() && it != message.data.end()) { if (application_id.IsValid() && it != message.data.end()) {
const std::string& data ALLOW_UNUSED = it->second; const std::string& data = it->second;
// TODO(mvanouwerkerk): Fire push event with data on the Service Worker content::BrowserContext::DeliverPushMessage(
// corresponding to app_id (and remove ALLOW_UNUSED above). profile_,
application_id.origin,
application_id.service_worker_registration_id,
data,
base::Bind(&PushMessagingServiceImpl::DeliverMessageCallback,
weak_factory_.GetWeakPtr(),
application_id,
message));
} else { } else {
// Drop the message, as it is invalid. // Drop the message, as it is invalid.
// TODO(mvanouwerkerk): Show a warning in the developer console of the // TODO(mvanouwerkerk): Show a warning in the developer console of the
...@@ -121,6 +129,14 @@ void PushMessagingServiceImpl::OnMessage( ...@@ -121,6 +129,14 @@ void PushMessagingServiceImpl::OnMessage(
} }
} }
void PushMessagingServiceImpl::DeliverMessageCallback(
const PushMessagingApplicationId& application_id,
const GCMClient::IncomingMessage& message,
content::PushMessagingStatus status) {
// TODO(mvanouwerkerk): UMA logging.
// TODO(mvanouwerkerk): Is there a way to recover from failure?
}
void PushMessagingServiceImpl::OnMessagesDeleted(const std::string& app_id) { void PushMessagingServiceImpl::OnMessagesDeleted(const std::string& app_id) {
// TODO(mvanouwerkerk): Fire push error event on the Service Worker // TODO(mvanouwerkerk): Fire push error event on the Service Worker
// corresponding to app_id. // corresponding to app_id.
......
...@@ -59,6 +59,10 @@ class PushMessagingServiceImpl : public content::PushMessagingService, ...@@ -59,6 +59,10 @@ class PushMessagingServiceImpl : public content::PushMessagingService,
const content::PushMessagingService::RegisterCallback& callback) OVERRIDE; const content::PushMessagingService::RegisterCallback& callback) OVERRIDE;
private: private:
void DeliverMessageCallback(const PushMessagingApplicationId& application_id,
const GCMClient::IncomingMessage& message,
content::PushMessagingStatus status);
void RegisterEnd( void RegisterEnd(
const content::PushMessagingService::RegisterCallback& callback, const content::PushMessagingService::RegisterCallback& callback,
const std::string& registration_id, const std::string& registration_id,
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "content/browser/fileapi/chrome_blob_storage_context.h" #include "content/browser/fileapi/chrome_blob_storage_context.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h" #include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h" #include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/push_messaging_router.h"
#include "content/browser/storage_partition_impl_map.h" #include "content/browser/storage_partition_impl_map.h"
#include "content/common/child_process_host_impl.h" #include "content/common/child_process_host_impl.h"
#include "content/public/browser/blob_handle.h" #include "content/public/browser/blob_handle.h"
...@@ -212,6 +213,18 @@ void BrowserContext::CreateMemoryBackedBlob(BrowserContext* browser_context, ...@@ -212,6 +213,18 @@ void BrowserContext::CreateMemoryBackedBlob(BrowserContext* browser_context,
callback); callback);
} }
// static
void BrowserContext::DeliverPushMessage(
BrowserContext* browser_context,
const GURL& origin,
int64 service_worker_registration_id,
const std::string& data,
const base::Callback<void(PushMessagingStatus)>& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
PushMessagingRouter::DeliverMessage(
browser_context, origin, service_worker_registration_id, data, callback);
}
void BrowserContext::EnsureResourceContextInitialized(BrowserContext* context) { void BrowserContext::EnsureResourceContextInitialized(BrowserContext* context) {
// This will be enough to tickle initialization of BrowserContext if // This will be enough to tickle initialization of BrowserContext if
// necessary, which initializes ResourceContext. The reason we don't call // necessary, which initializes ResourceContext. The reason we don't call
......
// 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_router.h"
#include "base/bind.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
namespace content {
// static
void PushMessagingRouter::DeliverMessage(
BrowserContext* browser_context,
const GURL& origin,
int64 service_worker_registration_id,
const std::string& data,
const DeliverMessageCallback& deliver_message_callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
StoragePartition* partition =
BrowserContext::GetStoragePartitionForSite(browser_context, origin);
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context =
static_cast<ServiceWorkerContextWrapper*>(
partition->GetServiceWorkerContext());
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&PushMessagingRouter::FindServiceWorkerRegistration,
origin,
service_worker_registration_id,
data,
deliver_message_callback,
service_worker_context));
}
// static
void PushMessagingRouter::FindServiceWorkerRegistration(
const GURL& origin,
int64 service_worker_registration_id,
const std::string& data,
const DeliverMessageCallback& deliver_message_callback,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// Try to acquire the registration from storage. If it's already live we'll
// receive it right away. If not, it will be revived from storage.
service_worker_context->context()->storage()->FindRegistrationForId(
service_worker_registration_id,
origin,
base::Bind(&PushMessagingRouter::FindServiceWorkerRegistrationCallback,
data,
deliver_message_callback));
}
// static
void PushMessagingRouter::FindServiceWorkerRegistrationCallback(
const std::string& data,
const DeliverMessageCallback& deliver_message_callback,
ServiceWorkerStatusCode service_worker_status,
const scoped_refptr<ServiceWorkerRegistration>&
service_worker_registration) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (service_worker_status == SERVICE_WORKER_OK) {
// Hold on to the service worker registration in the callback to keep it
// alive until the callback dies. Otherwise the registration could be
// released when this method returns - before the event is delivered to the
// service worker.
base::Callback<void(ServiceWorkerStatusCode)> dispatch_event_callback =
base::Bind(&PushMessagingRouter::DeliverMessageEnd,
deliver_message_callback,
service_worker_registration);
service_worker_registration->active_version()->DispatchPushEvent(
dispatch_event_callback, data);
} else {
// TODO(mvanouwerkerk): UMA logging.
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(
deliver_message_callback,
PUSH_MESSAGING_STATUS_MESSAGE_DELIVERY_FAILED_NO_SERVICE_WORKER));
}
}
// static
void PushMessagingRouter::DeliverMessageEnd(
const DeliverMessageCallback& deliver_message_callback,
const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
ServiceWorkerStatusCode service_worker_status) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// TODO(mvanouwerkerk): UMA logging.
PushMessagingStatus push_messaging_status =
service_worker_status == SERVICE_WORKER_OK
? PUSH_MESSAGING_STATUS_OK
: PUSH_MESSAGING_STATUS_MESSAGE_DELIVERY_FAILED_SERVICE_WORKER_ERROR;
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(deliver_message_callback, push_messaging_status));
}
} // namespace content
// 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_ROUTER_H_
#define CONTENT_BROWSER_PUSH_MESSAGING_ROUTER_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 "url/gurl.h"
namespace content {
class BrowserContext;
class ServiceWorkerContextWrapper;
class ServiceWorkerRegistration;
class PushMessagingRouter {
public:
typedef base::Callback<void(PushMessagingStatus /* push_messaging_status */)>
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 service_worker_registration_id,
const std::string& data,
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 service_worker_registration_id,
const std::string& data,
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 std::string& data,
const DeliverMessageCallback& deliver_message_callback,
ServiceWorkerStatusCode service_worker_status,
const scoped_refptr<ServiceWorkerRegistration>&
service_worker_registration);
// 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_ROUTER_H_
...@@ -886,6 +886,8 @@ ...@@ -886,6 +886,8 @@
'browser/profiler_message_filter.h', 'browser/profiler_message_filter.h',
'browser/push_messaging_message_filter.cc', 'browser/push_messaging_message_filter.cc',
'browser/push_messaging_message_filter.h', 'browser/push_messaging_message_filter.h',
'browser/push_messaging_router.cc',
'browser/push_messaging_router.h',
'browser/quota_dispatcher_host.cc', 'browser/quota_dispatcher_host.cc',
'browser/quota_dispatcher_host.h', 'browser/quota_dispatcher_host.h',
'browser/renderer_data_memoizing_store.h', 'browser/renderer_data_memoizing_store.h',
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/supports_user_data.h" #include "base/supports_user_data.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "content/public/common/push_messaging_status.h"
class GURL; class GURL;
...@@ -86,6 +87,15 @@ class CONTENT_EXPORT BrowserContext : public base::SupportsUserData { ...@@ -86,6 +87,15 @@ class CONTENT_EXPORT BrowserContext : public base::SupportsUserData {
const char* data, size_t length, const char* data, size_t length,
const BlobCallback& callback); const BlobCallback& callback);
// Delivers a push message with |data| to the Service Worker identified by
// |origin| and |service_worker_registration_id|.
static void DeliverPushMessage(
BrowserContext* browser_context,
const GURL& origin,
int64 service_worker_registration_id,
const std::string& data,
const base::Callback<void(PushMessagingStatus)>& callback);
// Ensures that the corresponding ResourceContext is initialized. Normally the // Ensures that the corresponding ResourceContext is initialized. Normally the
// BrowserContext initializs the corresponding getters when its objects are // BrowserContext initializs the corresponding getters when its objects are
// created, but if the embedder wants to pass the ResourceContext to another // created, but if the embedder wants to pass the ResourceContext to another
......
...@@ -28,6 +28,12 @@ const char* PushMessagingStatusToString(PushMessagingStatus status) { ...@@ -28,6 +28,12 @@ const char* PushMessagingStatusToString(PushMessagingStatus status) {
case PUSH_MESSAGING_STATUS_REGISTRATION_FAILED_SERVICE_ERROR: case PUSH_MESSAGING_STATUS_REGISTRATION_FAILED_SERVICE_ERROR:
return "Registration failed - push service error"; return "Registration failed - push service error";
case PUSH_MESSAGING_STATUS_MESSAGE_DELIVERY_FAILED_NO_SERVICE_WORKER:
return "Message delivery failed - no Service Worker";
case PUSH_MESSAGING_STATUS_MESSAGE_DELIVERY_FAILED_SERVICE_WORKER_ERROR:
return "Message delivery failed - Service Worker error";
case PUSH_MESSAGING_STATUS_ERROR: case PUSH_MESSAGING_STATUS_ERROR:
return "Operation has failed (unspecified reason)"; return "Operation has failed (unspecified reason)";
} }
......
...@@ -27,6 +27,12 @@ enum PushMessagingStatus { ...@@ -27,6 +27,12 @@ enum PushMessagingStatus {
// Registration failed in the push service implemented by the embedder. // Registration failed in the push service implemented by the embedder.
PUSH_MESSAGING_STATUS_REGISTRATION_FAILED_SERVICE_ERROR, PUSH_MESSAGING_STATUS_REGISTRATION_FAILED_SERVICE_ERROR,
// The message could not be delivered because no service worker was found.
PUSH_MESSAGING_STATUS_MESSAGE_DELIVERY_FAILED_NO_SERVICE_WORKER,
// The message could not be delivered because of a service worker error.
PUSH_MESSAGING_STATUS_MESSAGE_DELIVERY_FAILED_SERVICE_WORKER_ERROR,
// Generic error (a more specific error should be used whenever possible). // Generic error (a more specific error should be used whenever possible).
PUSH_MESSAGING_STATUS_ERROR, PUSH_MESSAGING_STATUS_ERROR,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment