1 // Copyright (c) 2011 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/renderer_host/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 13 using base::WaitableEvent; 14 15 namespace content { 16 namespace { 17 struct 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 }; 25 base::LazyInstance<WaitableEvent, WaitableEventLazyInstanceTraits> dummy_event = 26 LAZY_INSTANCE_INITIALIZER; 27 28 base::subtle::AtomicWord g_last_id = 0; 29 } 30 31 JavaBridgeChannelHost::~JavaBridgeChannelHost() { 32 #if defined(OS_POSIX) 33 if (channel_handle_.socket.fd > 0) { 34 close(channel_handle_.socket.fd); 35 } 36 #endif 37 } 38 39 JavaBridgeChannelHost* 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 56 int JavaBridgeChannelHost::ThreadsafeGenerateRouteID() { 57 return base::subtle::NoBarrier_AtomicIncrement(&g_last_id, 1); 58 } 59 60 int JavaBridgeChannelHost::GenerateRouteID() { 61 return ThreadsafeGenerateRouteID(); 62 } 63 64 bool 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 82 bool 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 91 void JavaBridgeChannelHost::OnGenerateRouteID(int* route_id) { 92 *route_id = GenerateRouteID(); 93 } 94 95 } // namespace content 96