OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/navigator_connect/navigator_connect_context.h" | 5 #include "content/browser/navigator_connect/navigator_connect_service_worker_ser
vice_factory.h" |
6 | 6 |
| 7 #include "base/bind.h" |
7 #include "content/browser/message_port_service.h" | 8 #include "content/browser/message_port_service.h" |
8 #include "content/browser/service_worker/service_worker_context_wrapper.h" | 9 #include "content/browser/service_worker/service_worker_context_wrapper.h" |
9 #include "content/browser/service_worker/service_worker_utils.h" | 10 #include "content/browser/service_worker/service_worker_utils.h" |
10 #include "content/common/navigator_connect_types.h" | 11 #include "content/public/browser/browser_thread.h" |
| 12 #include "content/public/browser/message_port_delegate.h" |
| 13 #include "content/public/common/navigator_connect_client.h" |
11 | 14 |
12 namespace content { | 15 namespace content { |
13 | 16 |
14 struct NavigatorConnectContext::Connection { | 17 namespace { |
15 CrossOriginServiceWorkerClient client; | 18 |
16 int64 service_worker_registration_id; | 19 // MessagePortDelegate implementation that directs all messages to the |
17 GURL service_worker_registration_origin; | 20 // oncrossoriginmessage event of a service worker. |
| 21 // TODO(mek): Somehow clean up message ports when a service worker is |
| 22 // unregistered. |
| 23 class NavigatorConnectServiceWorkerService : public MessagePortDelegate { |
| 24 public: |
| 25 NavigatorConnectServiceWorkerService( |
| 26 const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context, |
| 27 const NavigatorConnectClient& client, |
| 28 const scoped_refptr<ServiceWorkerRegistration>& |
| 29 service_worker_registration); |
| 30 ~NavigatorConnectServiceWorkerService() override; |
| 31 |
| 32 // MessagePortDelegate implementation. |
| 33 void SendMessage(int route_id, |
| 34 const base::string16& message, |
| 35 const std::vector<int>& sent_message_port_ids) override; |
| 36 void SendMessagesAreQueued(int route_id) override; |
| 37 |
| 38 private: |
| 39 // Callback called by SendMessage when the ServiceWorkerRegistration for this |
| 40 // service has been located. |
| 41 void DeliverMessage(const base::string16& message, |
| 42 const std::vector<int>& sent_message_port_ids, |
| 43 ServiceWorkerStatusCode service_worker_status, |
| 44 const scoped_refptr<ServiceWorkerRegistration>& |
| 45 service_worker_registration); |
| 46 |
| 47 scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_; |
| 48 NavigatorConnectClient client_; |
| 49 int64 service_worker_registration_id_; |
| 50 GURL service_worker_registration_origin_; |
| 51 |
| 52 base::WeakPtrFactory<NavigatorConnectServiceWorkerService> weak_factory_; |
18 }; | 53 }; |
19 | 54 |
20 NavigatorConnectContext::NavigatorConnectContext( | 55 NavigatorConnectServiceWorkerService::NavigatorConnectServiceWorkerService( |
21 const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context) | 56 const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context, |
22 : service_worker_context_(service_worker_context) { | 57 const NavigatorConnectClient& client, |
| 58 const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration) |
| 59 : service_worker_context_(service_worker_context), |
| 60 client_(client), |
| 61 service_worker_registration_id_(service_worker_registration->id()), |
| 62 service_worker_registration_origin_( |
| 63 service_worker_registration->pattern().GetOrigin()), |
| 64 weak_factory_(this) { |
23 } | 65 } |
24 | 66 |
25 NavigatorConnectContext::~NavigatorConnectContext() { | 67 NavigatorConnectServiceWorkerService::~NavigatorConnectServiceWorkerService() { |
26 } | 68 } |
27 | 69 |
28 void NavigatorConnectContext::RegisterConnection( | 70 void NavigatorConnectServiceWorkerService::SendMessage( |
29 const CrossOriginServiceWorkerClient& client, | |
30 const scoped_refptr<ServiceWorkerRegistration>& | |
31 service_worker_registration) { | |
32 MessagePortService::GetInstance()->UpdateMessagePort( | |
33 client.message_port_id, this, client.message_port_id); | |
34 MessagePortService::GetInstance()->ReleaseMessages(client.message_port_id); | |
35 Connection& connection = connections_[client.message_port_id]; | |
36 connection.client = client; | |
37 connection.service_worker_registration_id = service_worker_registration->id(); | |
38 connection.service_worker_registration_origin = | |
39 service_worker_registration->pattern().GetOrigin(); | |
40 } | |
41 | |
42 void NavigatorConnectContext::SendMessage( | |
43 int route_id, | 71 int route_id, |
44 const base::string16& message, | 72 const base::string16& message, |
45 const std::vector<int>& sent_message_port_ids) { | 73 const std::vector<int>& sent_message_port_ids) { |
46 DCHECK(connections_.find(route_id) != connections_.end()); | 74 DCHECK(route_id == client_.message_port_id); |
47 const Connection& connection = connections_[route_id]; | |
48 | 75 |
49 // Hold messages while service worker is found, activated, and message sent | 76 // Hold messages on transferred message ports. Actual delivery of the message |
50 // causing ServiceWorkerScriptContext::OnCrossOriginMessageToWorker to | 77 // by the service can be asynchronous. When a message is delivered, |
51 // construct WebMessagePortChannelImpl instances which send | 78 // WebMessagePortChannelImpl instances will be constructed which send |
52 // MessagePortHostMsg_ReleaseMessages. | 79 // MessagePortHostMsg_ReleaseMessages to release messages. |
53 for (int sent_message_port_id : sent_message_port_ids) | 80 for (int sent_message_port_id : sent_message_port_ids) |
54 MessagePortService::GetInstance()->HoldMessages(sent_message_port_id); | 81 MessagePortService::GetInstance()->HoldMessages(sent_message_port_id); |
55 | 82 |
56 service_worker_context_->context()->storage()->FindRegistrationForId( | 83 service_worker_context_->context()->storage()->FindRegistrationForId( |
57 connection.service_worker_registration_id, | 84 service_worker_registration_id_, service_worker_registration_origin_, |
58 connection.service_worker_registration_origin, | 85 base::Bind(&NavigatorConnectServiceWorkerService::DeliverMessage, |
59 base::Bind(&NavigatorConnectContext::DoSendMessage, this, | 86 weak_factory_.GetWeakPtr(), message, sent_message_port_ids)); |
60 connection.client, message, sent_message_port_ids)); | |
61 } | 87 } |
62 | 88 |
63 void NavigatorConnectContext::SendMessagesAreQueued(int route_id) { | 89 void NavigatorConnectServiceWorkerService::SendMessagesAreQueued(int route_id) { |
64 NOTREACHED() << "navigator.connect endpoints should never queue messages."; | 90 NOTREACHED() << "navigator.connect endpoints should never queue messages."; |
65 } | 91 } |
66 | 92 |
67 void NavigatorConnectContext::DoSendMessage( | 93 void NavigatorConnectServiceWorkerService::DeliverMessage( |
68 const CrossOriginServiceWorkerClient& client, | |
69 const base::string16& message, | 94 const base::string16& message, |
70 const std::vector<int>& sent_message_port_ids, | 95 const std::vector<int>& sent_message_port_ids, |
71 ServiceWorkerStatusCode service_worker_status, | 96 ServiceWorkerStatusCode service_worker_status, |
72 const scoped_refptr<ServiceWorkerRegistration>& | 97 const scoped_refptr<ServiceWorkerRegistration>& |
73 service_worker_registration) { | 98 service_worker_registration) { |
74 if (service_worker_status != SERVICE_WORKER_OK) { | 99 if (service_worker_status != SERVICE_WORKER_OK) { |
75 // TODO(mek): Do something when no service worker was found. | 100 // TODO(mek): Do something when no service worker was found. |
76 return; | 101 return; |
77 } | 102 } |
78 | 103 |
79 ServiceWorkerVersion* active_version = | 104 ServiceWorkerVersion* active_version = |
80 service_worker_registration->active_version(); | 105 service_worker_registration->active_version(); |
81 if (!active_version) { | 106 if (!active_version) { |
82 // TODO(mek): Do something when no active version exists. | 107 // TODO(mek): Do something when no active version exists. |
83 return; | 108 return; |
84 } | 109 } |
85 | 110 |
86 active_version->DispatchCrossOriginMessageEvent( | 111 active_version->DispatchCrossOriginMessageEvent( |
87 client, message, sent_message_port_ids, | 112 client_, message, sent_message_port_ids, |
88 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); | 113 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); |
89 } | 114 } |
90 | 115 |
| 116 } // namespace |
| 117 |
| 118 NavigatorConnectServiceWorkerServiceFactory:: |
| 119 NavigatorConnectServiceWorkerServiceFactory(const scoped_refptr< |
| 120 ServiceWorkerContextWrapper>& service_worker_context) |
| 121 : service_worker_context_(service_worker_context), weak_factory_(this) { |
| 122 } |
| 123 |
| 124 NavigatorConnectServiceWorkerServiceFactory:: |
| 125 ~NavigatorConnectServiceWorkerServiceFactory() { |
| 126 } |
| 127 |
| 128 bool NavigatorConnectServiceWorkerServiceFactory::HandlesUrl( |
| 129 const GURL& target_url) { |
| 130 // Always return true, all URLs could potentially have a service worker, and |
| 131 // this factory will be installed as first factory, so it will only be used |
| 132 // if no other factory claims to handle the url. |
| 133 return true; |
| 134 } |
| 135 |
| 136 void NavigatorConnectServiceWorkerServiceFactory::Connect( |
| 137 const NavigatorConnectClient& client, |
| 138 const ConnectCallback& callback) { |
| 139 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 140 |
| 141 // Find the right service worker to service this connection. |
| 142 service_worker_context_->context()->storage()->FindRegistrationForDocument( |
| 143 client.target_url, |
| 144 base::Bind(&NavigatorConnectServiceWorkerServiceFactory:: |
| 145 GotServiceWorkerRegistration, |
| 146 weak_factory_.GetWeakPtr(), callback, client)); |
| 147 } |
| 148 |
| 149 void NavigatorConnectServiceWorkerServiceFactory::GotServiceWorkerRegistration( |
| 150 const ConnectCallback& callback, |
| 151 const NavigatorConnectClient& client, |
| 152 ServiceWorkerStatusCode status, |
| 153 const scoped_refptr<ServiceWorkerRegistration>& registration) { |
| 154 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 155 |
| 156 if (status != SERVICE_WORKER_OK) { |
| 157 // No service worker found, reject connection attempt. |
| 158 OnConnectResult(callback, client, registration, status, false); |
| 159 return; |
| 160 } |
| 161 |
| 162 ServiceWorkerVersion* active_version = registration->active_version(); |
| 163 if (!active_version) { |
| 164 // No active version, reject connection attempt. |
| 165 OnConnectResult(callback, client, registration, status, false); |
| 166 return; |
| 167 } |
| 168 |
| 169 active_version->DispatchCrossOriginConnectEvent( |
| 170 base::Bind(&NavigatorConnectServiceWorkerServiceFactory::OnConnectResult, |
| 171 weak_factory_.GetWeakPtr(), callback, client, registration), |
| 172 client); |
| 173 } |
| 174 |
| 175 void NavigatorConnectServiceWorkerServiceFactory::OnConnectResult( |
| 176 const ConnectCallback& callback, |
| 177 const NavigatorConnectClient& client, |
| 178 const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration, |
| 179 ServiceWorkerStatusCode status, |
| 180 bool accept_connection) { |
| 181 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 182 |
| 183 if (status != SERVICE_WORKER_OK || !accept_connection) { |
| 184 callback.Run(nullptr); |
| 185 return; |
| 186 } |
| 187 |
| 188 // TODO(mek): Keep track of NavigatorConnectServiceWorkerService instances and |
| 189 // clean them up when a service worker registration is deleted. |
| 190 callback.Run(new NavigatorConnectServiceWorkerService( |
| 191 service_worker_context_, client, service_worker_registration)); |
| 192 } |
| 193 |
91 } // namespace content | 194 } // namespace content |
OLD | NEW |