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

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: Fix typo 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 } 23 }
24 24
25 JavaBridgeDispatcherHost::~JavaBridgeDispatcherHost() { 25 JavaBridgeDispatcherHost::~JavaBridgeDispatcherHost() {
26 } 26 }
27 27
28 void JavaBridgeDispatcherHost::AddNamedObject(const string16& name, 28 void JavaBridgeDispatcherHost::AddNamedObject(const string16& name,
29 NPObject* object) { 29 NPObject* object) {
30 // Post to the WEBKIT thread, as that's where we want injected objects to 30 NPVariant_Param variant_param;
31 // live. 31 CreateNPVariantParam(object, &variant_param);
32 WebKit::WebBindings::retainObject(object); 32 render_view_host()->Send(new JavaBridgeMsg_AddNamedObject(routing_id(), name,
33 BrowserThread::PostTask( 33 variant_param));
34 BrowserThread::WEBKIT,
35 FROM_HERE,
36 NewRunnableMethod(this,
37 &JavaBridgeDispatcherHost::DoAddNamedObject,
38 name,
39 object));
40 } 34 }
41 35
42 void JavaBridgeDispatcherHost::RemoveNamedObject(const string16& name) { 36 void JavaBridgeDispatcherHost::RemoveNamedObject(const string16& name) {
43 // On receipt of this message, the JavaBridgeDispatcher will drop its 37 // On receipt of this message, the JavaBridgeDispatcher will drop its
44 // reference to the corresponding proxy object. When the last reference is 38 // reference to the corresponding proxy object. When the last reference is
45 // removed, the proxy object will delete its NPObjectProxy, which will cause 39 // removed, the proxy object will delete its NPObjectProxy, which will cause
46 // the NPObjectStub to be deleted, which will drop its reference to the 40 // the NPObjectStub to be deleted, which will drop its reference to the
47 // original NPObject. 41 // original NPObject.
48 render_view_host_->Send(new JavaBridgeMsg_RemoveNamedObject( 42 render_view_host()->Send(new JavaBridgeMsg_RemoveNamedObject(routing_id(),
49 render_view_host_->routing_id(), name)); 43 name));
50 } 44 }
51 45
52 void JavaBridgeDispatcherHost::DoAddNamedObject(const string16& name, 46 bool JavaBridgeDispatcherHost::Send(IPC::Message* msg) {
53 NPObject* object) { 47 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 } 48 }
72 49
73 void JavaBridgeDispatcherHost::EnsureChannelIsSetUp() { 50 bool JavaBridgeDispatcherHost::OnMessageReceived(const IPC::Message& msg) {
74 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); 51 bool handled = true;
75 if (channel_) { 52 IPC_BEGIN_MESSAGE_MAP(JavaBridgeDispatcherHost, msg)
76 return; 53 IPC_MESSAGE_HANDLER_DELAY_REPLY(JavaBridgeMsg_GetChannelHandle,
54 OnGetChannelHandle)
55 IPC_MESSAGE_UNHANDLED(handled = false)
56 IPC_END_MESSAGE_MAP()
57 return handled;
58 }
59
60 void JavaBridgeDispatcherHost::OnGetChannelHandle(IPC::Message* reply_msg) {
61 // In renderer-in-process mode, this sync IPC is coming from the WEBKIT
62 // thread, so we can't post to the WEBKIT thread.
63 if (RenderProcessHost::run_renderer_in_process()) {
64 GetChannelHandle(reply_msg);
65 } else {
66 BrowserThread::PostTask(
67 BrowserThread::WEBKIT,
68 FROM_HERE,
69 base::Bind(&JavaBridgeDispatcherHost::GetChannelHandle, this,
70 reply_msg));
77 } 71 }
72 }
78 73
79 channel_ = JavaBridgeChannelHost::GetJavaBridgeChannelHost( 74 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 75 // The channel creates the channel handle based on the renderer ID we passed
84 // to GetJavaBridgeChannelHost() and, on POSIX, the file descriptor used by 76 // to GetJavaBridgeChannelHost() and, on POSIX, the file descriptor used by
85 // the underlying channel. 77 // the underlying channel.
86 IPC::ChannelHandle channel_handle = channel_->channel_handle(); 78 JavaBridgeMsg_GetChannelHandle::WriteReplyParams(reply_msg,
79 channel_->channel_handle());
80 Send(reply_msg);
81 }
87 82
88 bool sent = render_view_host_->Send(new JavaBridgeMsg_Init( 83 void JavaBridgeDispatcherHost::CreateNPVariantParam(NPObject* object,
89 render_view_host_->routing_id(), channel_handle)); 84 NPVariant_Param* param) {
90 DCHECK(sent); 85 // The JavaBridgeChannelHost needs to be created on the WEBKIT thread, as
86 // that is where Java objects will live, and CreateNPVariantParam() needs the
87 // channel to create the NPObjectStub. To avoid blocking here until the
88 // channel is ready, create the NPVariant_Param by hand, then post a message
89 // to the WEBKIT thread to set up the channel and create the corresponding
90 // NPObjectStub. Post that message before doing any IPC, to make sure that
91 // the channel and object proxies are ready before responses are received
92 // from the renderer.
93
94 bool is_first_run = !route_id_generator_;
95 if (is_first_run) {
96 route_id_generator_ = new RouteIDGenerator();
97 }
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 = route_id_generator_->GenerateRouteID();
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));
111
112 if (is_first_run) {
113 render_view_host()->Send(new JavaBridgeMsg_Init(routing_id()));
114 }
91 } 115 }
116
117 void JavaBridgeDispatcherHost::CreateObjectStub(NPObject* object,
118 int route_id) {
119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT));
120
121 if (!channel_) {
122 channel_ = JavaBridgeChannelHost::GetJavaBridgeChannelHost(
123 render_view_host()->process()->id(),
124 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
125 route_id_generator_);
126 }
127
128 // We don't need the containing window or the page URL, as we don't do
129 // re-entrant sync IPC.
130 new NPObjectStub(object, channel_, route_id, 0, GURL());
131 // The NPObjectStub takes a reference to the NPObject. Release the ref added
132 // in CreateNPVariantParam().
133 WebKit::WebBindings::releaseObject(object);
134 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698