OLD | NEW |
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" | 7 #include "content/browser/message_port_message_filter.h" |
8 #include "content/browser/message_port_service.h" | 8 #include "content/browser/message_port_service.h" |
| 9 #include "content/browser/navigator_connect/service_port_service_impl.h" |
| 10 #include "content/public/browser/message_port_provider.h" |
9 #include "content/public/browser/navigator_connect_service_factory.h" | 11 #include "content/public/browser/navigator_connect_service_factory.h" |
10 #include "content/public/common/navigator_connect_client.h" | 12 #include "content/public/common/navigator_connect_client.h" |
11 | 13 |
12 namespace content { | 14 namespace content { |
13 | 15 |
| 16 struct NavigatorConnectContextImpl::Port { |
| 17 int message_port_id; |
| 18 // Set to nullptr when the ServicePortService goes away. |
| 19 ServicePortServiceImpl* service; |
| 20 }; |
| 21 |
14 NavigatorConnectContextImpl::NavigatorConnectContextImpl() { | 22 NavigatorConnectContextImpl::NavigatorConnectContextImpl() { |
15 } | 23 } |
16 | 24 |
17 NavigatorConnectContextImpl::~NavigatorConnectContextImpl() { | 25 NavigatorConnectContextImpl::~NavigatorConnectContextImpl() { |
18 } | 26 } |
19 | 27 |
20 void NavigatorConnectContextImpl::AddFactory( | 28 void NavigatorConnectContextImpl::AddFactory( |
21 scoped_ptr<NavigatorConnectServiceFactory> factory) { | 29 scoped_ptr<NavigatorConnectServiceFactory> factory) { |
22 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 30 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
23 BrowserThread::PostTask( | 31 BrowserThread::PostTask( |
24 BrowserThread::IO, FROM_HERE, | 32 BrowserThread::IO, FROM_HERE, |
25 base::Bind(&NavigatorConnectContextImpl::AddFactoryOnIOThread, this, | 33 base::Bind(&NavigatorConnectContextImpl::AddFactoryOnIOThread, this, |
26 base::Passed(&factory))); | 34 base::Passed(&factory))); |
27 } | 35 } |
28 | 36 |
29 void NavigatorConnectContextImpl::AddFactoryOnIOThread( | 37 void NavigatorConnectContextImpl::AddFactoryOnIOThread( |
30 scoped_ptr<NavigatorConnectServiceFactory> factory) { | 38 scoped_ptr<NavigatorConnectServiceFactory> factory) { |
31 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 39 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
32 service_factories_.push_back(factory.release()); | 40 service_factories_.push_back(factory.release()); |
33 } | 41 } |
34 | 42 |
35 void NavigatorConnectContextImpl::Connect( | 43 void NavigatorConnectContextImpl::Connect( |
36 NavigatorConnectClient client, | 44 const GURL& target_url, |
37 MessagePortMessageFilter* message_port_message_filter, | 45 const GURL& origin, |
| 46 ServicePortServiceImpl* service_port_service, |
38 const ConnectCallback& callback) { | 47 const ConnectCallback& callback) { |
39 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 48 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
40 // Create a new message channel. Client port is setup to talk to client | 49 // Create a new message channel. Use |this| as delegate for both ports until |
41 // process, service port is initially setup without a delegate. | 50 // the real delegate for the service port is known later on. |
42 MessagePortService* message_port_service = MessagePortService::GetInstance(); | 51 int client_port_id; |
43 int client_port; | |
44 int client_port_route_id = message_port_message_filter->GetNextRoutingID(); | |
45 message_port_service->Create(client_port_route_id, | |
46 message_port_message_filter, &client_port); | |
47 int service_port; | 52 int service_port; |
48 message_port_service->Create(MSG_ROUTING_NONE, nullptr, &service_port); | 53 MessagePortProvider::CreateMessageChannel(this, &client_port_id, |
49 message_port_service->Entangle(client_port, service_port); | 54 &service_port); |
50 message_port_service->Entangle(service_port, client_port); | 55 // Hold messages send to the client while setting up connection. |
51 // Hold messages on client port while setting up connection. | 56 MessagePortService::GetInstance()->HoldMessages(client_port_id); |
52 message_port_service->HoldMessages(client_port); | 57 |
| 58 Port& client_port = ports_[client_port_id]; |
| 59 client_port.message_port_id = client_port_id; |
| 60 client_port.service = service_port_service; |
53 | 61 |
54 // The message_port_id stored in the client object is the one associated with | 62 // The message_port_id stored in the client object is the one associated with |
55 // the service. | 63 // the service. |
56 client.message_port_id = service_port; | 64 NavigatorConnectClient client(target_url, origin, service_port); |
57 | 65 |
58 // Find factory to handle request, more recently added factories should take | 66 // Find factory to handle request, more recently added factories should take |
59 // priority as per comment at NavigatorConnectContext::AddFactory.. | 67 // priority as per comment at NavigatorConnectContext::AddFactory.. |
60 NavigatorConnectServiceFactory* factory = nullptr; | 68 NavigatorConnectServiceFactory* factory = nullptr; |
61 for (auto it = service_factories_.rbegin(); it != service_factories_.rend(); | 69 for (auto it = service_factories_.rbegin(); it != service_factories_.rend(); |
62 ++it) { | 70 ++it) { |
63 if ((*it)->HandlesUrl(client.target_url)) { | 71 if ((*it)->HandlesUrl(client.target_url)) { |
64 factory = *it; | 72 factory = *it; |
65 break; | 73 break; |
66 } | 74 } |
67 } | 75 } |
68 | 76 |
69 if (!factory) { | 77 if (!factory) { |
70 // No factories found. | 78 // No factories found. |
71 OnConnectResult(client, client_port, client_port_route_id, callback, | 79 OnConnectResult(client, client_port_id, callback, nullptr, false); |
72 nullptr, false); | |
73 return; | 80 return; |
74 } | 81 } |
75 | 82 |
76 // Actually initiate connection. | 83 // Actually initiate connection. |
77 factory->Connect( | 84 factory->Connect( |
78 client, base::Bind(&NavigatorConnectContextImpl::OnConnectResult, this, | 85 client, base::Bind(&NavigatorConnectContextImpl::OnConnectResult, this, |
79 client, client_port, client_port_route_id, callback)); | 86 client, client_port_id, callback)); |
| 87 } |
| 88 |
| 89 void NavigatorConnectContextImpl::ServicePortServiceDestroyed( |
| 90 ServicePortServiceImpl* service_port_service) { |
| 91 for (auto& port : ports_) { |
| 92 if (port.second.service != service_port_service) |
| 93 continue; |
| 94 port.second.service = nullptr; |
| 95 // TODO(mek): Should actually inform other side of connections that the |
| 96 // connection was closed, or in the case of service workers somehow keep |
| 97 // track of the connection. |
| 98 } |
| 99 } |
| 100 |
| 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."; |
80 } | 117 } |
81 | 118 |
82 void NavigatorConnectContextImpl::OnConnectResult( | 119 void NavigatorConnectContextImpl::OnConnectResult( |
83 const NavigatorConnectClient& client, | 120 const NavigatorConnectClient& client, |
84 int client_message_port_id, | 121 int client_message_port_id, |
85 int client_port_route_id, | |
86 const ConnectCallback& callback, | 122 const ConnectCallback& callback, |
87 MessagePortDelegate* delegate, | 123 MessagePortDelegate* delegate, |
88 bool data_as_values) { | 124 bool data_as_values) { |
89 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 125 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
90 if (delegate) { | 126 if (delegate) { |
| 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 |
| 129 // severed while the service side connection was being set up. |
| 130 |
91 // Update service side port with delegate. | 131 // Update service side port with delegate. |
92 MessagePortService::GetInstance()->UpdateMessagePort( | 132 MessagePortService::GetInstance()->UpdateMessagePort( |
93 client.message_port_id, delegate, client.message_port_id); | 133 client.message_port_id, delegate, client.message_port_id); |
94 TransferredMessagePort port; | 134 callback.Run(client_message_port_id, true); |
95 port.id = client_message_port_id; | 135 MessagePortService::GetInstance()->ReleaseMessages(client_message_port_id); |
96 port.send_messages_as_values = data_as_values; | |
97 callback.Run(port, client_port_route_id, true); | |
98 } else { | 136 } else { |
99 // Destroy ports since connection failed. | 137 // Destroy ports since connection failed. |
100 MessagePortService::GetInstance()->Destroy(client.message_port_id); | 138 MessagePortService::GetInstance()->Destroy(client.message_port_id); |
101 MessagePortService::GetInstance()->Destroy(client_message_port_id); | 139 MessagePortService::GetInstance()->Destroy(client_message_port_id); |
102 callback.Run(TransferredMessagePort(), MSG_ROUTING_NONE, false); | 140 ports_.erase(client_message_port_id); |
| 141 callback.Run(MSG_ROUTING_NONE, false); |
103 } | 142 } |
104 } | 143 } |
105 | 144 |
106 } // namespace content | 145 } // namespace content |
OLD | NEW |