Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / browser / push_messaging / push_messaging_router.cc
blob68d15aff497ab6833181c944ecb7ca75b2c6d723
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/push_messaging/push_messaging_router.h"
7 #include "base/bind.h"
8 #include "content/browser/service_worker/service_worker_context_wrapper.h"
9 #include "content/browser/service_worker/service_worker_registration.h"
10 #include "content/browser/service_worker/service_worker_storage.h"
11 #include "content/common/service_worker/service_worker_status_code.h"
12 #include "content/public/browser/browser_context.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/storage_partition.h"
16 namespace content {
18 // static
19 void PushMessagingRouter::DeliverMessage(
20 BrowserContext* browser_context,
21 const GURL& origin,
22 int64 service_worker_registration_id,
23 const std::string& data,
24 const DeliverMessageCallback& deliver_message_callback) {
25 DCHECK_CURRENTLY_ON(BrowserThread::UI);
26 StoragePartition* partition =
27 BrowserContext::GetStoragePartitionForSite(browser_context, origin);
28 scoped_refptr<ServiceWorkerContextWrapper> service_worker_context =
29 static_cast<ServiceWorkerContextWrapper*>(
30 partition->GetServiceWorkerContext());
31 BrowserThread::PostTask(
32 BrowserThread::IO,
33 FROM_HERE,
34 base::Bind(&PushMessagingRouter::FindServiceWorkerRegistration,
35 origin,
36 service_worker_registration_id,
37 data,
38 deliver_message_callback,
39 service_worker_context));
42 // static
43 void PushMessagingRouter::FindServiceWorkerRegistration(
44 const GURL& origin,
45 int64 service_worker_registration_id,
46 const std::string& data,
47 const DeliverMessageCallback& deliver_message_callback,
48 scoped_refptr<ServiceWorkerContextWrapper> service_worker_context) {
49 DCHECK_CURRENTLY_ON(BrowserThread::IO);
50 // Try to acquire the registration from storage. If it's already live we'll
51 // receive it right away. If not, it will be revived from storage.
52 service_worker_context->context()->storage()->FindRegistrationForId(
53 service_worker_registration_id,
54 origin,
55 base::Bind(&PushMessagingRouter::FindServiceWorkerRegistrationCallback,
56 data,
57 deliver_message_callback));
60 // static
61 void PushMessagingRouter::FindServiceWorkerRegistrationCallback(
62 const std::string& data,
63 const DeliverMessageCallback& deliver_message_callback,
64 ServiceWorkerStatusCode service_worker_status,
65 const scoped_refptr<ServiceWorkerRegistration>&
66 service_worker_registration) {
67 DCHECK_CURRENTLY_ON(BrowserThread::IO);
68 if (service_worker_status == SERVICE_WORKER_OK) {
69 // Hold on to the service worker registration in the callback to keep it
70 // alive until the callback dies. Otherwise the registration could be
71 // released when this method returns - before the event is delivered to the
72 // service worker.
73 base::Callback<void(ServiceWorkerStatusCode)> dispatch_event_callback =
74 base::Bind(&PushMessagingRouter::DeliverMessageEnd,
75 deliver_message_callback,
76 service_worker_registration);
77 service_worker_registration->active_version()->DispatchPushEvent(
78 dispatch_event_callback, data);
79 } else {
80 // TODO(mvanouwerkerk): UMA logging.
81 BrowserThread::PostTask(BrowserThread::UI,
82 FROM_HERE,
83 base::Bind(deliver_message_callback,
84 PUSH_DELIVERY_STATUS_NO_SERVICE_WORKER));
88 // static
89 void PushMessagingRouter::DeliverMessageEnd(
90 const DeliverMessageCallback& deliver_message_callback,
91 const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
92 ServiceWorkerStatusCode service_worker_status) {
93 DCHECK_CURRENTLY_ON(BrowserThread::IO);
94 // TODO(mvanouwerkerk): UMA logging.
95 PushDeliveryStatus delivery_status =
96 PUSH_DELIVERY_STATUS_SERVICE_WORKER_ERROR;
97 switch (service_worker_status) {
98 case SERVICE_WORKER_OK:
99 delivery_status = PUSH_DELIVERY_STATUS_SUCCESS;
100 break;
101 case SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED:
102 delivery_status = PUSH_DELIVERY_STATUS_EVENT_WAITUNTIL_REJECTED;
103 break;
104 case SERVICE_WORKER_ERROR_FAILED:
105 case SERVICE_WORKER_ERROR_ABORT:
106 case SERVICE_WORKER_ERROR_START_WORKER_FAILED:
107 case SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND:
108 case SERVICE_WORKER_ERROR_NOT_FOUND:
109 case SERVICE_WORKER_ERROR_IPC_FAILED:
110 case SERVICE_WORKER_ERROR_TIMEOUT:
111 delivery_status = PUSH_DELIVERY_STATUS_SERVICE_WORKER_ERROR;
112 break;
113 case SERVICE_WORKER_ERROR_EXISTS:
114 case SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED:
115 case SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED:
116 case SERVICE_WORKER_ERROR_NETWORK:
117 case SERVICE_WORKER_ERROR_SECURITY:
118 case SERVICE_WORKER_ERROR_STATE:
119 case SERVICE_WORKER_ERROR_MAX_VALUE:
120 NOTREACHED() << "Got unexpected error code: " << service_worker_status
121 << " " << ServiceWorkerStatusToString(service_worker_status);
122 delivery_status = PUSH_DELIVERY_STATUS_SERVICE_WORKER_ERROR;
123 break;
125 BrowserThread::PostTask(
126 BrowserThread::UI,
127 FROM_HERE,
128 base::Bind(deliver_message_callback, delivery_status));
131 } // namespace content