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. 4 5#include "content/browser/android/java/java_bridge_channel_host.h" 6 7#include "base/atomicops.h" 8#include "base/lazy_instance.h" 9#include "base/strings/stringprintf.h" 10#include "base/synchronization/waitable_event.h" 11#include "content/common/java_bridge_messages.h" 12 13using base::WaitableEvent; 14 15namespace content { 16namespace { 17struct WaitableEventLazyInstanceTraits 18 : public base::DefaultLazyInstanceTraits<WaitableEvent> { 19 static WaitableEvent* New(void* instance) { 20 // Use placement new to initialize our instance in our preallocated space. 21 // The parenthesis is very important here to force POD type initialization. 22 return new (instance) WaitableEvent(false, false); 23 } 24}; 25base::LazyInstance<WaitableEvent, WaitableEventLazyInstanceTraits> dummy_event = 26 LAZY_INSTANCE_INITIALIZER; 27 28base::subtle::AtomicWord g_last_id = 0; 29} 30 31JavaBridgeChannelHost::~JavaBridgeChannelHost() { 32#if defined(OS_POSIX) 33 if (channel_handle_.socket.fd > 0) { 34 close(channel_handle_.socket.fd); 35 } 36#endif 37} 38 39JavaBridgeChannelHost* JavaBridgeChannelHost::GetJavaBridgeChannelHost( 40 int renderer_id, 41 base::MessageLoopProxy* ipc_message_loop) { 42 std::string channel_name(base::StringPrintf("r%d.javabridge", renderer_id)); 43 // There's no need for a shutdown event here. If the browser is terminated 44 // while the JavaBridgeChannelHost is blocked on a synchronous IPC call, the 45 // renderer's shutdown event will cause the underlying channel to shut down, 46 // thus terminating the IPC call. 47 return static_cast<JavaBridgeChannelHost*>(NPChannelBase::GetChannel( 48 channel_name, 49 IPC::Channel::MODE_SERVER, 50 ClassFactory, 51 ipc_message_loop, 52 true, 53 dummy_event.Pointer())); 54} 55 56int JavaBridgeChannelHost::ThreadsafeGenerateRouteID() { 57 return base::subtle::NoBarrier_AtomicIncrement(&g_last_id, 1); 58} 59 60int JavaBridgeChannelHost::GenerateRouteID() { 61 return ThreadsafeGenerateRouteID(); 62} 63 64bool JavaBridgeChannelHost::Init(base::MessageLoopProxy* ipc_message_loop, 65 bool create_pipe_now, 66 WaitableEvent* shutdown_event) { 67 if (!NPChannelBase::Init(ipc_message_loop, create_pipe_now, shutdown_event)) { 68 return false; 69 } 70 71 // Finish populating our ChannelHandle. 72#if defined(OS_POSIX) 73 // We take control of the FD for all session between this host and 74 // the corresponding renderers. We keep it open until this object 75 // is deleted. 76 channel_handle_.socket.fd = channel_->TakeClientFileDescriptor(); 77#endif 78 79 return true; 80} 81 82bool JavaBridgeChannelHost::OnControlMessageReceived( 83 const IPC::Message& message) { 84 bool handled = true; 85 IPC_BEGIN_MESSAGE_MAP(JavaBridgeChannelHost, message) 86 IPC_MESSAGE_HANDLER(JavaBridgeMsg_GenerateRouteID, OnGenerateRouteID) 87 IPC_END_MESSAGE_MAP() 88 return handled; 89} 90 91void JavaBridgeChannelHost::OnGenerateRouteID(int* route_id) { 92 *route_id = GenerateRouteID(); 93} 94 95} // namespace content 96