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/navigator_connect/navigator_connect_context_impl.h"
7 #include "content/browser/message_port_message_filter.h"
8 #include "content/browser/message_port_service.h"
9 #include "content/public/browser/navigator_connect_service_factory.h"
10 #include "content/public/common/navigator_connect_client.h"
14 NavigatorConnectContextImpl::NavigatorConnectContextImpl() {
17 NavigatorConnectContextImpl::~NavigatorConnectContextImpl() {
20 void NavigatorConnectContextImpl::AddFactory(
21 scoped_ptr
<NavigatorConnectServiceFactory
> factory
) {
22 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
23 BrowserThread::PostTask(
24 BrowserThread::IO
, FROM_HERE
,
25 base::Bind(&NavigatorConnectContextImpl::AddFactoryOnIOThread
, this,
26 base::Passed(&factory
)));
29 void NavigatorConnectContextImpl::AddFactoryOnIOThread(
30 scoped_ptr
<NavigatorConnectServiceFactory
> factory
) {
31 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
32 service_factories_
.push_back(factory
.release());
35 void NavigatorConnectContextImpl::Connect(
36 NavigatorConnectClient client
,
37 MessagePortMessageFilter
* message_port_message_filter
,
38 const ConnectCallback
& callback
) {
39 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
40 // Create a new message channel. Client port is setup to talk to client
41 // process, service port is initially setup without a delegate.
42 MessagePortService
* message_port_service
= MessagePortService::GetInstance();
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
);
48 message_port_service
->Create(MSG_ROUTING_NONE
, nullptr, &service_port
);
49 message_port_service
->Entangle(client_port
, service_port
);
50 message_port_service
->Entangle(service_port
, client_port
);
51 // Hold messages on client port while setting up connection.
52 message_port_service
->HoldMessages(client_port
);
54 // The message_port_id stored in the client object is the one associated with
56 client
.message_port_id
= service_port
;
58 // Find factory to handle request, more recently added factories should take
59 // priority as per comment at NavigatorConnectContext::AddFactory..
60 NavigatorConnectServiceFactory
* factory
= nullptr;
61 for (auto it
= service_factories_
.rbegin(); it
!= service_factories_
.rend();
63 if ((*it
)->HandlesUrl(client
.target_url
)) {
70 // No factories found.
71 OnConnectResult(client
, client_port
, client_port_route_id
, callback
,
76 // Actually initiate connection.
78 client
, base::Bind(&NavigatorConnectContextImpl::OnConnectResult
, this,
79 client
, client_port
, client_port_route_id
, callback
));
82 void NavigatorConnectContextImpl::OnConnectResult(
83 const NavigatorConnectClient
& client
,
84 int client_message_port_id
,
85 int client_port_route_id
,
86 const ConnectCallback
& callback
,
87 MessagePortDelegate
* delegate
,
88 bool data_as_values
) {
89 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
91 // Update service side port with delegate.
92 MessagePortService::GetInstance()->UpdateMessagePort(
93 client
.message_port_id
, delegate
, client
.message_port_id
);
94 TransferredMessagePort port
;
95 port
.id
= client_message_port_id
;
96 port
.send_messages_as_values
= data_as_values
;
97 callback
.Run(port
, client_port_route_id
, true);
99 // Destroy ports since connection failed.
100 MessagePortService::GetInstance()->Destroy(client
.message_port_id
);
101 MessagePortService::GetInstance()->Destroy(client_message_port_id
);
102 callback
.Run(TransferredMessagePort(), MSG_ROUTING_NONE
, false);
106 } // namespace content