Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(416)

Side by Side Diff: content/browser/navigator_connect/navigator_connect_context_impl.cc

Issue 1224263007: Refactor browser side navigator.connect code to not use MessagePortService. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@serviceport-serviceside
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 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_impl.h" 5 #include "content/browser/navigator_connect/navigator_connect_context_impl.h"
6 6
7 #include "content/browser/message_port_message_filter.h"
8 #include "content/browser/message_port_service.h" 7 #include "content/browser/message_port_service.h"
9 #include "content/browser/navigator_connect/service_port_service_impl.h" 8 #include "content/browser/navigator_connect/service_port_service_impl.h"
10 #include "content/public/browser/message_port_provider.h" 9 #include "content/browser/service_worker/service_worker_context_wrapper.h"
10 #include "content/browser/service_worker/service_worker_utils.h"
11 #include "content/public/browser/browser_thread.h"
11 #include "content/public/browser/navigator_connect_service_factory.h" 12 #include "content/public/browser/navigator_connect_service_factory.h"
12 #include "content/public/common/navigator_connect_client.h" 13 #include "content/public/common/navigator_connect_client.h"
13 14
14 namespace content { 15 namespace content {
15 16
16 struct NavigatorConnectContextImpl::Port { 17 struct NavigatorConnectContextImpl::Port {
17 int message_port_id; 18 // ID of this port.
19 int id;
20 // ID of the port this port is connected to.
21 int entangled_id;
22
23 // Service url and client origin describing this connection. These fields will
24 // always be the same as the same fields for the entangled port.
25 GURL target_url;
26 GURL client_origin;
27
18 // Set to nullptr when the ServicePortService goes away. 28 // Set to nullptr when the ServicePortService goes away.
19 ServicePortServiceImpl* service; 29 ServicePortServiceImpl* service;
30
31 // If this port is associated with a service worker, these fields store that
32 // information.
33 int64 service_worker_registration_id = kInvalidServiceWorkerRegistrationId;
34 GURL service_worker_registration_origin;
20 }; 35 };
21 36
22 NavigatorConnectContextImpl::NavigatorConnectContextImpl() { 37 NavigatorConnectContextImpl::NavigatorConnectContextImpl(
23 } 38 const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context)
39 : service_worker_context_(service_worker_context), next_port_id_(0) {}
24 40
25 NavigatorConnectContextImpl::~NavigatorConnectContextImpl() { 41 NavigatorConnectContextImpl::~NavigatorConnectContextImpl() {
26 } 42 }
27 43
28 void NavigatorConnectContextImpl::AddFactory( 44 void NavigatorConnectContextImpl::AddFactory(
29 scoped_ptr<NavigatorConnectServiceFactory> factory) { 45 scoped_ptr<NavigatorConnectServiceFactory> factory) {
30 DCHECK_CURRENTLY_ON(BrowserThread::UI); 46 DCHECK_CURRENTLY_ON(BrowserThread::UI);
31 BrowserThread::PostTask( 47 BrowserThread::PostTask(
32 BrowserThread::IO, FROM_HERE, 48 BrowserThread::IO, FROM_HERE,
33 base::Bind(&NavigatorConnectContextImpl::AddFactoryOnIOThread, this, 49 base::Bind(&NavigatorConnectContextImpl::AddFactoryOnIOThread, this,
34 base::Passed(&factory))); 50 base::Passed(&factory)));
35 } 51 }
36 52
37 void NavigatorConnectContextImpl::AddFactoryOnIOThread( 53 void NavigatorConnectContextImpl::AddFactoryOnIOThread(
38 scoped_ptr<NavigatorConnectServiceFactory> factory) { 54 scoped_ptr<NavigatorConnectServiceFactory> factory) {
39 DCHECK_CURRENTLY_ON(BrowserThread::IO); 55 DCHECK_CURRENTLY_ON(BrowserThread::IO);
40 service_factories_.push_back(factory.release()); 56 service_factories_.push_back(factory.release());
41 } 57 }
42 58
43 void NavigatorConnectContextImpl::Connect( 59 void NavigatorConnectContextImpl::Connect(
44 const GURL& target_url, 60 const GURL& target_url,
45 const GURL& origin, 61 const GURL& origin,
46 ServicePortServiceImpl* service_port_service, 62 ServicePortServiceImpl* service_port_service,
47 const ConnectCallback& callback) { 63 const ConnectCallback& callback) {
48 DCHECK_CURRENTLY_ON(BrowserThread::IO); 64 DCHECK_CURRENTLY_ON(BrowserThread::IO);
49 // Create a new message channel. Use |this| as delegate for both ports until 65 // Create a new message channel.
50 // the real delegate for the service port is known later on. 66 int client_port_id = next_port_id_++;
51 int client_port_id; 67 int service_port_id = next_port_id_++;
52 int service_port;
53 MessagePortProvider::CreateMessageChannel(this, &client_port_id,
54 &service_port);
55 // Hold messages send to the client while setting up connection.
56 MessagePortService::GetInstance()->HoldMessages(client_port_id);
57 68
58 Port& client_port = ports_[client_port_id]; 69 Port& client_port = ports_[client_port_id];
59 client_port.message_port_id = client_port_id; 70 client_port.id = client_port_id;
71 client_port.entangled_id = service_port_id;
72 client_port.target_url = target_url;
73 client_port.client_origin = origin;
60 client_port.service = service_port_service; 74 client_port.service = service_port_service;
61 75
62 // The message_port_id stored in the client object is the one associated with 76 Port& service_port = ports_[service_port_id];
63 // the service. 77 service_port.id = service_port_id;
64 NavigatorConnectClient client(target_url, origin, service_port); 78 service_port.entangled_id = client_port_id;
79 service_port.target_url = target_url;
80 service_port.client_origin = origin;
65 81
66 // Find factory to handle request, more recently added factories should take 82 // Find the right service worker to service this connection.
67 // priority as per comment at NavigatorConnectContext::AddFactory.. 83 service_worker_context_->FindRegistrationForDocument(
68 NavigatorConnectServiceFactory* factory = nullptr; 84 target_url,
69 for (auto it = service_factories_.rbegin(); it != service_factories_.rend(); 85 base::Bind(&NavigatorConnectContextImpl::GotServiceWorkerRegistration,
70 ++it) { 86 this, callback, client_port_id, service_port_id));
71 if ((*it)->HandlesUrl(client.target_url)) { 87 }
72 factory = *it; 88
73 break; 89 void NavigatorConnectContextImpl::PostMessage(
74 } 90 int sender_port_id,
91 const MessagePortMessage& message,
92 const std::vector<TransferredMessagePort>& sent_message_ports) {
93 DCHECK_CURRENTLY_ON(BrowserThread::IO);
94 DCHECK(ports_.find(sender_port_id) != ports_.end());
95 DCHECK(message.message_as_value.empty());
96
97 const Port& sender_port = ports_[sender_port_id];
98 DCHECK(ports_.find(sender_port.entangled_id) != ports_.end());
99 const Port& port = ports_[sender_port.entangled_id];
100
101 if (port.service_worker_registration_id !=
102 kInvalidServiceWorkerRegistrationId) {
103 // Port is associated with service worker, dispatch message event via
104 // ServiceWorkerVersion.
105
106 // Hold messages on transferred message ports. Actual delivery of the
107 // message
Avi (use Gerrit) 2015/08/05 15:17:20 re-wrap this comment block
Marijn Kruisselbrink 2015/08/05 17:00:16 Done
108 // by the service can be asynchronous. When a message is delivered,
109 // WebMessagePortChannelImpl instances will be constructed which send
110 // MessagePortHostMsg_ReleaseMessages to release messages.
111 for (const auto& sent_port : sent_message_ports)
112 MessagePortService::GetInstance()->HoldMessages(sent_port.id);
113
114 service_worker_context_->FindRegistrationForId(
115 port.service_worker_registration_id,
116 port.service_worker_registration_origin,
117 base::Bind(&NavigatorConnectContextImpl::DeliverMessage, this, port.id,
118 message.message_as_string, sent_message_ports));
75 } 119 }
76 120
77 if (!factory) { 121 if (!port.service) {
78 // No factories found. 122 // TODO(mek): Figure out what to do in this situation.
79 OnConnectResult(client, client_port_id, callback, nullptr, false); 123 return;
124 }
125 port.service->PostMessageToClient(port.id, message, sent_message_ports);
126 }
127
128 void NavigatorConnectContextImpl::GotServiceWorkerRegistration(
129 const ConnectCallback& callback,
130 int client_port_id,
131 int service_port_id,
132 ServiceWorkerStatusCode status,
133 const scoped_refptr<ServiceWorkerRegistration>& registration) {
134 DCHECK_CURRENTLY_ON(BrowserThread::IO);
135 DCHECK(ports_.find(client_port_id) != ports_.end());
136 DCHECK(ports_.find(service_port_id) != ports_.end());
137
138 if (status != SERVICE_WORKER_OK) {
139 // No service worker found, reject connection attempt.
140 OnConnectResult(callback, client_port_id, service_port_id, registration,
141 status, false, base::string16(), base::string16());
80 return; 142 return;
81 } 143 }
82 144
83 // Actually initiate connection. 145 ServiceWorkerVersion* active_version = registration->active_version();
84 factory->Connect( 146 if (!active_version) {
85 client, base::Bind(&NavigatorConnectContextImpl::OnConnectResult, this, 147 // No active version, reject connection attempt.
86 client, client_port_id, callback)); 148 OnConnectResult(callback, client_port_id, service_port_id, registration,
149 status, false, base::string16(), base::string16());
150 return;
151 }
152
153 Port& service_port = ports_[service_port_id];
154 service_port.service_worker_registration_id = registration->id();
155 service_port.service_worker_registration_origin =
156 registration->pattern().GetOrigin();
157
158 active_version->DispatchServicePortConnectEvent(
159 base::Bind(&NavigatorConnectContextImpl::OnConnectResult, this, callback,
160 client_port_id, service_port_id, registration),
161 service_port.target_url, service_port.client_origin, service_port_id);
87 } 162 }
88 163
89 void NavigatorConnectContextImpl::ServicePortServiceDestroyed( 164 void NavigatorConnectContextImpl::ServicePortServiceDestroyed(
90 ServicePortServiceImpl* service_port_service) { 165 ServicePortServiceImpl* service_port_service) {
166 DCHECK_CURRENTLY_ON(BrowserThread::IO);
91 for (auto& port : ports_) { 167 for (auto& port : ports_) {
92 if (port.second.service != service_port_service) 168 if (port.second.service != service_port_service)
93 continue; 169 continue;
94 port.second.service = nullptr; 170 port.second.service = nullptr;
95 // TODO(mek): Should actually inform other side of connections that the 171 // TODO(mek): Should actually inform other side of connections that the
96 // connection was closed, or in the case of service workers somehow keep 172 // connection was closed, or in the case of service workers somehow keep
97 // track of the connection. 173 // track of the connection.
98 } 174 }
99 } 175 }
100 176
101 void NavigatorConnectContextImpl::SendMessage(
102 int route_id,
103 const MessagePortMessage& message,
104 const std::vector<TransferredMessagePort>& sent_message_ports) {
105 DCHECK(ports_.find(route_id) != ports_.end());
106 const Port& port = ports_[route_id];
107 if (!port.service) {
108 // TODO(mek): Figure out what to do in this situation.
109 return;
110 }
111
112 port.service->PostMessageToClient(route_id, message, sent_message_ports);
113 }
114
115 void NavigatorConnectContextImpl::SendMessagesAreQueued(int route_id) {
116 NOTREACHED() << "navigator.services endpoints should never queue messages.";
117 }
118
119 void NavigatorConnectContextImpl::OnConnectResult( 177 void NavigatorConnectContextImpl::OnConnectResult(
120 const NavigatorConnectClient& client,
121 int client_message_port_id,
122 const ConnectCallback& callback, 178 const ConnectCallback& callback,
123 MessagePortDelegate* delegate, 179 int client_port_id,
124 bool data_as_values) { 180 int service_port_id,
181 const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
182 ServiceWorkerStatusCode status,
183 bool accept_connection,
184 const base::string16& name,
185 const base::string16& data) {
125 DCHECK_CURRENTLY_ON(BrowserThread::IO); 186 DCHECK_CURRENTLY_ON(BrowserThread::IO);
126 if (delegate) { 187 if (accept_connection) {
127 DCHECK(!data_as_values) << "Data as values is not currently implemented";
128 // TODO(mek): Might have to do something else if the client connection got 188 // TODO(mek): Might have to do something else if the client connection got
129 // severed while the service side connection was being set up. 189 // severed while the service side connection was being set up.
130 190 callback.Run(client_port_id, true);
131 // Update service side port with delegate.
132 MessagePortService::GetInstance()->UpdateMessagePort(
133 client.message_port_id, delegate, client.message_port_id);
134 callback.Run(client_message_port_id, true);
135 MessagePortService::GetInstance()->ReleaseMessages(client_message_port_id);
136 } else { 191 } else {
137 // Destroy ports since connection failed. 192 // Destroy ports since connection failed.
138 MessagePortService::GetInstance()->Destroy(client.message_port_id); 193 ports_.erase(service_port_id);
139 MessagePortService::GetInstance()->Destroy(client_message_port_id); 194 ports_.erase(client_port_id);
140 ports_.erase(client_message_port_id);
141 callback.Run(MSG_ROUTING_NONE, false); 195 callback.Run(MSG_ROUTING_NONE, false);
142 } 196 }
143 } 197 }
144 198
199 void NavigatorConnectContextImpl::DeliverMessage(
200 int port_id,
201 const base::string16& message,
202 const std::vector<TransferredMessagePort>& sent_message_ports,
203 ServiceWorkerStatusCode service_worker_status,
204 const scoped_refptr<ServiceWorkerRegistration>&
205 service_worker_registration) {
206 DCHECK_CURRENTLY_ON(BrowserThread::IO);
207 DCHECK(ports_.find(port_id) != ports_.end());
208
209 if (service_worker_status != SERVICE_WORKER_OK) {
210 // TODO(mek): Do something when no service worker was found.
211 return;
212 }
213
214 ServiceWorkerVersion* active_version =
215 service_worker_registration->active_version();
216 if (!active_version) {
217 // TODO(mek): Do something when no active version exists.
218 return;
219 }
220
221 const Port& port = ports_[port_id];
222 NavigatorConnectClient client(port.target_url, port.client_origin, port_id);
223 active_version->DispatchCrossOriginMessageEvent(
224 client, message, sent_message_ports,
225 base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
226 }
227
145 } // namespace content 228 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698