Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Side by Side Diff: content/browser/renderer_host/java/java_bridge_dispatcher_host.cc

Issue 8834013: Fix a race condition in the Java Bridge when adding objects (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed rebase Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/renderer_host/java/java_bridge_dispatcher_host.h" 5 #include "content/browser/renderer_host/java/java_bridge_dispatcher_host.h"
6 6
7 #include "base/bind.h"
7 #include "content/browser/renderer_host/browser_render_process_host.h" 8 #include "content/browser/renderer_host/browser_render_process_host.h"
8 #include "content/browser/renderer_host/java/java_bridge_channel_host.h" 9 #include "content/browser/renderer_host/java/java_bridge_channel_host.h"
9 #include "content/browser/renderer_host/render_view_host.h" 10 #include "content/browser/renderer_host/render_view_host.h"
10 #include "content/common/child_process.h" 11 #include "content/common/child_process.h"
11 #include "content/common/java_bridge_messages.h" 12 #include "content/common/java_bridge_messages.h"
12 #include "content/common/npobject_stub.h" 13 #include "content/common/npobject_stub.h"
13 #include "content/common/npobject_util.h" // For CreateNPVariantParam() 14 #include "content/common/npobject_util.h" // For CreateNPVariantParam()
14 #include "content/public/browser/browser_thread.h" 15 #include "content/public/browser/browser_thread.h"
15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h" 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h"
16 17
17 using content::BrowserThread; 18 using content::BrowserThread;
18 19
19 JavaBridgeDispatcherHost::JavaBridgeDispatcherHost( 20 JavaBridgeDispatcherHost::JavaBridgeDispatcherHost(
20 RenderViewHost* render_view_host) 21 RenderViewHost* render_view_host)
21 : render_view_host_(render_view_host) { 22 : RenderViewHostObserver(render_view_host)
22 DCHECK(render_view_host_); 23 , is_renderer_initialized_(false) {
jam 2011/12/07 22:07:03 nit: , on previous line per Google C++ style guide
Steve Block 2011/12/08 11:17:56 Done.
23 } 24 }
24 25
25 JavaBridgeDispatcherHost::~JavaBridgeDispatcherHost() { 26 JavaBridgeDispatcherHost::~JavaBridgeDispatcherHost() {
26 } 27 }
27 28
28 void JavaBridgeDispatcherHost::AddNamedObject(const string16& name, 29 void JavaBridgeDispatcherHost::AddNamedObject(const string16& name,
29 NPObject* object) { 30 NPObject* object) {
30 // Post to the WEBKIT thread, as that's where we want injected objects to 31 NPVariant_Param variant_param;
31 // live. 32 CreateNPVariantParam(object, &variant_param);
32 WebKit::WebBindings::retainObject(object); 33
33 BrowserThread::PostTask( 34 if (!is_renderer_initialized_) {
34 BrowserThread::WEBKIT, 35 is_renderer_initialized_ = true;
35 FROM_HERE, 36 render_view_host()->Send(new JavaBridgeMsg_Init(routing_id()));
36 NewRunnableMethod(this, 37 }
37 &JavaBridgeDispatcherHost::DoAddNamedObject, 38 render_view_host()->Send(new JavaBridgeMsg_AddNamedObject(routing_id(), name,
38 name, 39 variant_param));
39 object));
40 } 40 }
41 41
42 void JavaBridgeDispatcherHost::RemoveNamedObject(const string16& name) { 42 void JavaBridgeDispatcherHost::RemoveNamedObject(const string16& name) {
43 // On receipt of this message, the JavaBridgeDispatcher will drop its 43 // On receipt of this message, the JavaBridgeDispatcher will drop its
44 // reference to the corresponding proxy object. When the last reference is 44 // reference to the corresponding proxy object. When the last reference is
45 // removed, the proxy object will delete its NPObjectProxy, which will cause 45 // removed, the proxy object will delete its NPObjectProxy, which will cause
46 // the NPObjectStub to be deleted, which will drop its reference to the 46 // the NPObjectStub to be deleted, which will drop its reference to the
47 // original NPObject. 47 // original NPObject.
48 render_view_host_->Send(new JavaBridgeMsg_RemoveNamedObject( 48 render_view_host()->Send(new JavaBridgeMsg_RemoveNamedObject(routing_id(),
49 render_view_host_->routing_id(), name)); 49 name));
50 } 50 }
51 51
52 void JavaBridgeDispatcherHost::DoAddNamedObject(const string16& name, 52 bool JavaBridgeDispatcherHost::Send(IPC::Message* msg) {
53 NPObject* object) { 53 return RenderViewHostObserver::Send(msg);
54 EnsureChannelIsSetUp();
55
56 NPVariant variant;
57 OBJECT_TO_NPVARIANT(object, variant);
58 DCHECK_EQ(variant.type, NPVariantType_Object);
59
60 // Create an NPVariantParam suitable for serialization over IPC from our
61 // NPVariant. Internally, this will create an NPObjectStub, which takes a
62 // reference to the underlying NPObject. We pass release = true to release
63 // the ref added in AddNamedObject(). We don't need the containing window or
64 // the page URL, as we don't do re-entrant sync IPC.
65 NPVariant_Param variant_param;
66 CreateNPVariantParam(variant, channel_, &variant_param, true, 0, GURL());
67 DCHECK_EQ(variant_param.type, NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID);
68
69 render_view_host_->Send(new JavaBridgeMsg_AddNamedObject(
70 render_view_host_->routing_id(), name, variant_param));
71 } 54 }
72 55
73 void JavaBridgeDispatcherHost::EnsureChannelIsSetUp() { 56 bool JavaBridgeDispatcherHost::OnMessageReceived(const IPC::Message& msg) {
74 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); 57 bool handled = true;
75 if (channel_) { 58 IPC_BEGIN_MESSAGE_MAP(JavaBridgeDispatcherHost, msg)
76 return; 59 IPC_MESSAGE_HANDLER_DELAY_REPLY(JavaBridgeMsg_GetChannelHandle,
60 OnGetChannelHandle)
61 IPC_MESSAGE_UNHANDLED(handled = false)
62 IPC_END_MESSAGE_MAP()
63 return handled;
64 }
65
66 void JavaBridgeDispatcherHost::OnGetChannelHandle(IPC::Message* reply_msg) {
67 // In renderer-in-process mode, this sync IPC is coming from the WEBKIT
68 // thread, so we can't post to the WEBKIT thread.
69 if (RenderProcessHost::run_renderer_in_process()) {
70 GetChannelHandle(reply_msg);
71 } else {
72 BrowserThread::PostTask(
73 BrowserThread::WEBKIT,
74 FROM_HERE,
75 base::Bind(&JavaBridgeDispatcherHost::GetChannelHandle, this,
76 reply_msg));
77 } 77 }
78 }
78 79
79 channel_ = JavaBridgeChannelHost::GetJavaBridgeChannelHost( 80 void JavaBridgeDispatcherHost::GetChannelHandle(IPC::Message* reply_msg) {
80 render_view_host_->process()->id(),
81 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
82
83 // The channel creates the channel handle based on the renderer ID we passed 81 // The channel creates the channel handle based on the renderer ID we passed
84 // to GetJavaBridgeChannelHost() and, on POSIX, the file descriptor used by 82 // to GetJavaBridgeChannelHost() and, on POSIX, the file descriptor used by
85 // the underlying channel. 83 // the underlying channel.
86 IPC::ChannelHandle channel_handle = channel_->channel_handle(); 84 JavaBridgeMsg_GetChannelHandle::WriteReplyParams(reply_msg,
85 channel_->channel_handle());
86 Send(reply_msg);
87 }
87 88
88 bool sent = render_view_host_->Send(new JavaBridgeMsg_Init( 89 void JavaBridgeDispatcherHost::CreateNPVariantParam(NPObject* object,
89 render_view_host_->routing_id(), channel_handle)); 90 NPVariant_Param* param) {
90 DCHECK(sent); 91 // The JavaBridgeChannelHost needs to be created on the WEBKIT thread, as
92 // that is where Java objects will live, and CreateNPVariantParam() needs the
93 // channel to create the NPObjectStub. To avoid blocking here until the
94 // channel is ready, create the NPVariant_Param by hand, then post a message
95 // to the WEBKIT thread to set up the channel and create the corresponding
96 // NPObjectStub. Post that message before doing any IPC, to make sure that
97 // the channel and object proxies are ready before responses are received
98 // from the renderer.
99
100 // Create an NPVariantParam suitable for serialization over IPC from our
101 // NPVariant. See CreateNPVariantParam() in npobject_utils.
102 param->type = NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID;
103 int route_id = JavaBridgeChannelHost::ThreadsafeGenerateRouteID();
104 param->npobject_routing_id = route_id;
105
106 WebKit::WebBindings::retainObject(object);
107 BrowserThread::PostTask(
108 BrowserThread::WEBKIT,
109 FROM_HERE,
110 base::Bind(&JavaBridgeDispatcherHost::CreateObjectStub, this, object,
111 route_id));
91 } 112 }
113
114 void JavaBridgeDispatcherHost::CreateObjectStub(NPObject* object,
115 int route_id) {
116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
117
118 if (!channel_) {
119 channel_ = JavaBridgeChannelHost::GetJavaBridgeChannelHost(
120 render_view_host()->process()->id(),
121 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
122 }
123
124 // We don't need the containing window or the page URL, as we don't do
125 // re-entrant sync IPC.
126 new NPObjectStub(object, channel_, route_id, 0, GURL());
127 // The NPObjectStub takes a reference to the NPObject. Release the ref added
128 // in CreateNPVariantParam().
129 WebKit::WebBindings::releaseObject(object);
130 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698