OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "content/browser/navigator_connect/service_port_service_impl.h" |
| 6 |
| 7 #include "content/browser/message_port_message_filter.h" |
| 8 #include "content/browser/message_port_service.h" |
| 9 #include "content/browser/navigator_connect/navigator_connect_context_impl.h" |
| 10 #include "content/common/service_port_type_converters.h" |
| 11 #include "content/public/browser/browser_thread.h" |
| 12 #include "content/public/common/message_port_types.h" |
| 13 #include "mojo/common/common_type_converters.h" |
| 14 #include "url/gurl.h" |
| 15 |
| 16 namespace content { |
| 17 |
| 18 // static |
| 19 void ServicePortServiceImpl::Create( |
| 20 const scoped_refptr<NavigatorConnectContextImpl>& navigator_connect_context, |
| 21 const scoped_refptr<MessagePortMessageFilter>& message_port_message_filter, |
| 22 mojo::InterfaceRequest<ServicePortService> request) { |
| 23 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 24 BrowserThread::PostTask( |
| 25 BrowserThread::IO, FROM_HERE, |
| 26 base::Bind(&ServicePortServiceImpl::CreateOnIOThread, |
| 27 navigator_connect_context, message_port_message_filter, |
| 28 base::Passed(&request))); |
| 29 } |
| 30 |
| 31 ServicePortServiceImpl::~ServicePortServiceImpl() { |
| 32 // Should always be destroyed on the IO thread, but can't check that with |
| 33 // DCHECK_CURRENTLY_ON because this class could be destroyed during thread |
| 34 // shutdown, at which point that check doesn't work. |
| 35 navigator_connect_context_->ServicePortServiceDestroyed(this); |
| 36 } |
| 37 |
| 38 void ServicePortServiceImpl::PostMessageToClient( |
| 39 int port_id, |
| 40 const MessagePortMessage& message, |
| 41 const std::vector<TransferredMessagePort>& sent_message_ports) { |
| 42 DCHECK(client_.get()); |
| 43 // Hold messages on transferred message ports. Normally this wouldn't be |
| 44 // needed, but since MessagePort uses regular IPC while this class uses mojo, |
| 45 // without holding messages mojo IPC might overtake regular IPC resulting in a |
| 46 // non-functional port. When WebMessagePortChannelImpl instances are |
| 47 // constructed in the renderer, they will send |
| 48 // MessagePortHostMsg_ReleaseMessages to release messages. |
| 49 for (const auto& port : sent_message_ports) |
| 50 MessagePortService::GetInstance()->HoldMessages(port.id); |
| 51 |
| 52 std::vector<int> new_routing_ids; |
| 53 message_port_message_filter_->UpdateMessagePortsWithNewRoutes( |
| 54 sent_message_ports, &new_routing_ids); |
| 55 client_->PostMessage( |
| 56 port_id, mojo::String::From(message.message_as_string), |
| 57 mojo::Array<MojoTransferredMessagePortPtr>::From(sent_message_ports), |
| 58 mojo::Array<int32_t>::From(new_routing_ids)); |
| 59 } |
| 60 |
| 61 // static |
| 62 void ServicePortServiceImpl::CreateOnIOThread( |
| 63 const scoped_refptr<NavigatorConnectContextImpl>& navigator_connect_context, |
| 64 const scoped_refptr<MessagePortMessageFilter>& message_port_message_filter, |
| 65 mojo::InterfaceRequest<ServicePortService> request) { |
| 66 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 67 new ServicePortServiceImpl(navigator_connect_context, |
| 68 message_port_message_filter, request.Pass()); |
| 69 } |
| 70 |
| 71 ServicePortServiceImpl::ServicePortServiceImpl( |
| 72 const scoped_refptr<NavigatorConnectContextImpl>& navigator_connect_context, |
| 73 const scoped_refptr<MessagePortMessageFilter>& message_port_message_filter, |
| 74 mojo::InterfaceRequest<ServicePortService> request) |
| 75 : binding_(this, request.Pass()), |
| 76 navigator_connect_context_(navigator_connect_context), |
| 77 message_port_message_filter_(message_port_message_filter), |
| 78 weak_ptr_factory_(this) { |
| 79 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 80 } |
| 81 |
| 82 void ServicePortServiceImpl::SetClient(ServicePortServiceClientPtr client) { |
| 83 DCHECK(!client_.get()); |
| 84 // TODO(mek): Set ErrorHandler to listen for errors. |
| 85 client_ = client.Pass(); |
| 86 } |
| 87 |
| 88 void ServicePortServiceImpl::Connect(const mojo::String& target_url, |
| 89 const mojo::String& origin, |
| 90 const ConnectCallback& callback) { |
| 91 navigator_connect_context_->Connect( |
| 92 GURL(target_url), GURL(origin), this, |
| 93 base::Bind(&ServicePortServiceImpl::OnConnectResult, |
| 94 weak_ptr_factory_.GetWeakPtr(), callback)); |
| 95 } |
| 96 |
| 97 void ServicePortServiceImpl::PostMessage( |
| 98 int32_t port_id, |
| 99 const mojo::String& message, |
| 100 mojo::Array<MojoTransferredMessagePortPtr> ports) { |
| 101 // TODO(mek): Similar to http://crbug.com/490222 this code should make sure |
| 102 // port_id belongs to the process this IPC was received from. |
| 103 std::vector<TransferredMessagePort> transferred_ports = |
| 104 ports.To<std::vector<TransferredMessagePort>>(); |
| 105 |
| 106 MessagePortService* mps = MessagePortService::GetInstance(); |
| 107 // First, call QueueMessages for all transferred ports, since the ports |
| 108 // haven't sent their own IPC for that. |
| 109 for (const TransferredMessagePort& port : transferred_ports) { |
| 110 mps->QueueMessages(port.id); |
| 111 } |
| 112 |
| 113 // Second, pass of the actual to MessagePortService now ServicePort instances |
| 114 // are still backed by MessagePort. |
| 115 mps->PostMessage(port_id, MessagePortMessage(message.To<base::string16>()), |
| 116 transferred_ports); |
| 117 } |
| 118 |
| 119 void ServicePortServiceImpl::ClosePort(int32_t port_id) { |
| 120 MessagePortService::GetInstance()->Destroy(port_id); |
| 121 } |
| 122 |
| 123 void ServicePortServiceImpl::OnConnectResult(const ConnectCallback& callback, |
| 124 int message_port_id, |
| 125 bool success) { |
| 126 callback.Run(success ? SERVICE_PORT_CONNECT_RESULT_ACCEPT |
| 127 : SERVICE_PORT_CONNECT_RESULT_REJECT, |
| 128 message_port_id); |
| 129 } |
| 130 |
| 131 } // namespace content |
OLD | NEW |