Index: content/browser/navigator_connect/service_port_service_impl.cc |
diff --git a/content/browser/navigator_connect/service_port_service_impl.cc b/content/browser/navigator_connect/service_port_service_impl.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..432f57fb76a1dac100ef974b8e617472ed83af5d |
--- /dev/null |
+++ b/content/browser/navigator_connect/service_port_service_impl.cc |
@@ -0,0 +1,131 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/browser/navigator_connect/service_port_service_impl.h" |
+ |
+#include "content/browser/message_port_message_filter.h" |
+#include "content/browser/message_port_service.h" |
+#include "content/browser/navigator_connect/navigator_connect_context_impl.h" |
+#include "content/common/service_port_type_converters.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "content/public/common/message_port_types.h" |
+#include "mojo/common/common_type_converters.h" |
+#include "url/gurl.h" |
+ |
+namespace content { |
+ |
+// static |
+void ServicePortServiceImpl::Create( |
+ const scoped_refptr<NavigatorConnectContextImpl>& navigator_connect_context, |
+ const scoped_refptr<MessagePortMessageFilter>& message_port_message_filter, |
+ mojo::InterfaceRequest<ServicePortService> request) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::UI); |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ base::Bind(&ServicePortServiceImpl::CreateOnIOThread, |
+ navigator_connect_context, message_port_message_filter, |
+ base::Passed(&request))); |
+} |
+ |
+ServicePortServiceImpl::~ServicePortServiceImpl() { |
+ // Should always be destroyed on the IO thread, but can't check that with |
+ // DCHECK_CURRENTLY_ON because this class could be destroyed during thread |
+ // shutdown, at which point that check doesn't work. |
+ navigator_connect_context_->ServicePortServiceDestroyed(this); |
+} |
+ |
+void ServicePortServiceImpl::PostMessageToClient( |
+ int port_id, |
+ const MessagePortMessage& message, |
+ const std::vector<TransferredMessagePort>& sent_message_ports) { |
+ DCHECK(client_.get()); |
+ // Hold messages on transferred message ports. Normally this wouldn't be |
+ // needed, but since MessagePort uses regular IPC while this class uses mojo, |
+ // without holding messages mojo IPC might overtake regular IPC resulting in a |
+ // non-functional port. When WebMessagePortChannelImpl instances are |
+ // constructed in the renderer, they will send |
+ // MessagePortHostMsg_ReleaseMessages to release messages. |
+ for (const auto& port : sent_message_ports) |
+ MessagePortService::GetInstance()->HoldMessages(port.id); |
+ |
+ std::vector<int> new_routing_ids; |
+ message_port_message_filter_->UpdateMessagePortsWithNewRoutes( |
+ sent_message_ports, &new_routing_ids); |
+ client_->PostMessage( |
+ port_id, mojo::String::From(message.message_as_string), |
+ mojo::Array<MojoTransferredMessagePortPtr>::From(sent_message_ports), |
+ mojo::Array<int32_t>::From(new_routing_ids)); |
+} |
+ |
+// static |
+void ServicePortServiceImpl::CreateOnIOThread( |
+ const scoped_refptr<NavigatorConnectContextImpl>& navigator_connect_context, |
+ const scoped_refptr<MessagePortMessageFilter>& message_port_message_filter, |
+ mojo::InterfaceRequest<ServicePortService> request) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ new ServicePortServiceImpl(navigator_connect_context, |
+ message_port_message_filter, request.Pass()); |
+} |
+ |
+ServicePortServiceImpl::ServicePortServiceImpl( |
+ const scoped_refptr<NavigatorConnectContextImpl>& navigator_connect_context, |
+ const scoped_refptr<MessagePortMessageFilter>& message_port_message_filter, |
+ mojo::InterfaceRequest<ServicePortService> request) |
+ : binding_(this, request.Pass()), |
+ navigator_connect_context_(navigator_connect_context), |
+ message_port_message_filter_(message_port_message_filter), |
+ weak_ptr_factory_(this) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+} |
+ |
+void ServicePortServiceImpl::SetClient(ServicePortServiceClientPtr client) { |
+ DCHECK(!client_.get()); |
+ // TODO(mek): Set ErrorHandler to listen for errors. |
+ client_ = client.Pass(); |
+} |
+ |
+void ServicePortServiceImpl::Connect(const mojo::String& target_url, |
+ const mojo::String& origin, |
+ const ConnectCallback& callback) { |
+ navigator_connect_context_->Connect( |
+ GURL(target_url), GURL(origin), this, |
+ base::Bind(&ServicePortServiceImpl::OnConnectResult, |
+ weak_ptr_factory_.GetWeakPtr(), callback)); |
+} |
+ |
+void ServicePortServiceImpl::PostMessage( |
+ int32_t port_id, |
+ const mojo::String& message, |
+ mojo::Array<MojoTransferredMessagePortPtr> ports) { |
+ // TODO(mek): Similar to http://crbug.com/490222 this code should make sure |
+ // port_id belongs to the process this IPC was received from. |
+ std::vector<TransferredMessagePort> transferred_ports = |
+ ports.To<std::vector<TransferredMessagePort>>(); |
+ |
+ MessagePortService* mps = MessagePortService::GetInstance(); |
+ // First, call QueueMessages for all transferred ports, since the ports |
+ // haven't sent their own IPC for that. |
+ for (const TransferredMessagePort& port : transferred_ports) { |
+ mps->QueueMessages(port.id); |
+ } |
+ |
+ // Second, pass of the actual to MessagePortService now ServicePort instances |
+ // are still backed by MessagePort. |
+ mps->PostMessage(port_id, MessagePortMessage(message.To<base::string16>()), |
+ transferred_ports); |
+} |
+ |
+void ServicePortServiceImpl::ClosePort(int32_t port_id) { |
+ MessagePortService::GetInstance()->Destroy(port_id); |
+} |
+ |
+void ServicePortServiceImpl::OnConnectResult(const ConnectCallback& callback, |
+ int message_port_id, |
+ bool success) { |
+ callback.Run(success ? SERVICE_PORT_CONNECT_RESULT_ACCEPT |
+ : SERVICE_PORT_CONNECT_RESULT_REJECT, |
+ message_port_id); |
+} |
+ |
+} // namespace content |