Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / browser / navigator_connect / navigator_connect_context_impl.cc
blobc5f01f4534a60e52c622eb4c0d66f266a645ae4c
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"
12 namespace content {
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();
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;
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
55 // the service.
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();
62 ++it) {
63 if ((*it)->HandlesUrl(client.target_url)) {
64 factory = *it;
65 break;
69 if (!factory) {
70 // No factories found.
71 OnConnectResult(client, client_port, client_port_route_id, callback,
72 nullptr, false);
73 return;
76 // Actually initiate connection.
77 factory->Connect(
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);
90 if (delegate) {
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);
98 } else {
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