Home | History | Annotate | Download | only in java
      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 
     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