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

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 nits 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) {
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 Send(new JavaBridgeMsg_Init(routing_id()));
36 NewRunnableMethod(this, 37 }
37 &JavaBridgeDispatcherHost::DoAddNamedObject, 38 Send(new JavaBridgeMsg_AddNamedObject(routing_id(), name, variant_param));
38 name,
39 object));
40 } 39 }
41 40
42 void JavaBridgeDispatcherHost::RemoveNamedObject(const string16& name) { 41 void JavaBridgeDispatcherHost::RemoveNamedObject(const string16& name) {
43 // On receipt of this message, the JavaBridgeDispatcher will drop its 42 // On receipt of this message, the JavaBridgeDispatcher will drop its
44 // reference to the corresponding proxy object. When the last reference is 43 // reference to the corresponding proxy object. When the last reference is
45 // removed, the proxy object will delete its NPObjectProxy, which will cause 44 // removed, the proxy object will delete its NPObjectProxy, which will cause
46 // the NPObjectStub to be deleted, which will drop its reference to the 45 // the NPObjectStub to be deleted, which will drop its reference to the
47 // original NPObject. 46 // original NPObject.
48 render_view_host_->Send(new JavaBridgeMsg_RemoveNamedObject( 47 Send(new JavaBridgeMsg_RemoveNamedObject(routing_id(), name));
49 render_view_host_->routing_id(), name));
50 } 48 }
51 49
52 void JavaBridgeDispatcherHost::DoAddNamedObject(const string16& name, 50 bool JavaBridgeDispatcherHost::Send(IPC::Message* msg) {
53 NPObject* object) { 51 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 } 52 }
72 53
73 void JavaBridgeDispatcherHost::EnsureChannelIsSetUp() { 54 bool JavaBridgeDispatcherHost::OnMessageReceived(const IPC::Message& msg) {
74 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); 55 bool handled = true;
75 if (channel_) { 56 IPC_BEGIN_MESSAGE_MAP(JavaBridgeDispatcherHost, msg)
76 return; 57 IPC_MESSAGE_HANDLER_DELAY_REPLY(JavaBridgeHostMsg_GetChannelHandle,
58 OnGetChannelHandle)
59 IPC_MESSAGE_UNHANDLED(handled = false)
60 IPC_END_MESSAGE_MAP()
61 return handled;
62 }
63
64 void JavaBridgeDispatcherHost::OnGetChannelHandle(IPC::Message* reply_msg) {
65 // In renderer-in-process mode, this sync IPC is coming from the WEBKIT
66 // thread, so we can't post to the WEBKIT thread.
67 if (RenderProcessHost::run_renderer_in_process()) {
Steve Block 2011/12/08 13:46:04 Given the ongoing discussion about renderer-in-pro
joth 2011/12/08 18:15:46 I don't mind either way, given http://codereview.c
Steve Block 2011/12/09 12:27:32 Added a TODO.
68 GetChannelHandle(reply_msg);
69 } else {
70 BrowserThread::PostTask(
71 BrowserThread::WEBKIT,
72 FROM_HERE,
73 base::Bind(&JavaBridgeDispatcherHost::GetChannelHandle, this,
74 reply_msg));
77 } 75 }
76 }
78 77
79 channel_ = JavaBridgeChannelHost::GetJavaBridgeChannelHost( 78 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 79 // The channel creates the channel handle based on the renderer ID we passed
84 // to GetJavaBridgeChannelHost() and, on POSIX, the file descriptor used by 80 // to GetJavaBridgeChannelHost() and, on POSIX, the file descriptor used by
85 // the underlying channel. 81 // the underlying channel.
86 IPC::ChannelHandle channel_handle = channel_->channel_handle(); 82 JavaBridgeHostMsg_GetChannelHandle::WriteReplyParams(
83 reply_msg,
84 channel_->channel_handle());
85 Send(reply_msg);
86 }
87 87
88 bool sent = render_view_host_->Send(new JavaBridgeMsg_Init( 88 void JavaBridgeDispatcherHost::CreateNPVariantParam(NPObject* object,
89 render_view_host_->routing_id(), channel_handle)); 89 NPVariant_Param* param) {
90 DCHECK(sent); 90 // The JavaBridgeChannelHost needs to be created on the WEBKIT thread, as
91 // that is where Java objects will live, and CreateNPVariantParam() needs the
92 // channel to create the NPObjectStub. To avoid blocking here until the
93 // channel is ready, create the NPVariant_Param by hand, then post a message
94 // to the WEBKIT thread to set up the channel and create the corresponding
95 // NPObjectStub. Post that message before doing any IPC, to make sure that
96 // the channel and object proxies are ready before responses are received
97 // from the renderer.
98
99 // Create an NPVariantParam suitable for serialization over IPC from our
100 // NPVariant. See CreateNPVariantParam() in npobject_utils.
101 param->type = NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID;
102 int route_id = JavaBridgeChannelHost::ThreadsafeGenerateRouteID();
103 param->npobject_routing_id = route_id;
104
105 WebKit::WebBindings::retainObject(object);
106 BrowserThread::PostTask(
107 BrowserThread::WEBKIT,
108 FROM_HERE,
109 base::Bind(&JavaBridgeDispatcherHost::CreateObjectStub, this, object,
110 route_id));
91 } 111 }
112
113 void JavaBridgeDispatcherHost::CreateObjectStub(NPObject* object,
114 int route_id) {
115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
116
117 if (!channel_) {
118 channel_ = JavaBridgeChannelHost::GetJavaBridgeChannelHost(
119 render_view_host()->process()->id(),
120 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
121 }
122
123 // We don't need the containing window or the page URL, as we don't do
124 // re-entrant sync IPC.
125 new NPObjectStub(object, channel_, route_id, 0, GURL());
126 // The NPObjectStub takes a reference to the NPObject. Release the ref added
127 // in CreateNPVariantParam().
128 WebKit::WebBindings::releaseObject(object);
129 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698