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

Side by Side Diff: extensions/renderer/messaging_bindings.cc

Issue 1413543005: Use FrameTreeNode ID as frameId in extension APIs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: comments #47 Created 4 years, 12 months 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 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 "extensions/renderer/messaging_bindings.h" 5 #include "extensions/renderer/messaging_bindings.h"
6 6
7 #include <map> 7 #include <map>
8 #include <string> 8 #include <string>
9 9
10 #include "base/basictypes.h" 10 #include "base/basictypes.h"
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 private: 121 private:
122 // Maps ScriptContexts to the port IDs that have a reference to it. 122 // Maps ScriptContexts to the port IDs that have a reference to it.
123 std::map<ScriptContext*, std::set<int>> contexts_to_ports_; 123 std::map<ScriptContext*, std::set<int>> contexts_to_ports_;
124 124
125 DISALLOW_COPY_AND_ASSIGN(PortTracker); 125 DISALLOW_COPY_AND_ASSIGN(PortTracker);
126 }; 126 };
127 127
128 base::LazyInstance<PortTracker> g_port_tracker = LAZY_INSTANCE_INITIALIZER; 128 base::LazyInstance<PortTracker> g_port_tracker = LAZY_INSTANCE_INITIALIZER;
129 129
130 const char kPortClosedError[] = "Attempting to use a disconnected port object"; 130 const char kPortClosedError[] = "Attempting to use a disconnected port object";
131 const char kReceivingEndDoesntExistError[] =
132 "Could not establish connection. Receiving end does not exist.";
133 131
134 class ExtensionImpl : public ObjectBackedNativeHandler { 132 class ExtensionImpl : public ObjectBackedNativeHandler {
135 public: 133 public:
136 ExtensionImpl(Dispatcher* dispatcher, ScriptContext* context) 134 ExtensionImpl(Dispatcher* dispatcher, ScriptContext* context)
137 : ObjectBackedNativeHandler(context), 135 : ObjectBackedNativeHandler(context),
138 dispatcher_(dispatcher), 136 dispatcher_(dispatcher),
139 weak_ptr_factory_(this) { 137 weak_ptr_factory_(this) {
140 RouteFunction( 138 RouteFunction(
141 "CloseChannel", 139 "CloseChannel",
142 base::Bind(&ExtensionImpl::CloseChannel, base::Unretained(this))); 140 base::Bind(&ExtensionImpl::CloseChannel, base::Unretained(this)));
(...skipping 23 matching lines...) Expand all
166 ReleasePort(port_id); 164 ReleasePort(port_id);
167 } 165 }
168 166
169 void ClearPortDataAndNotifyDispatcher(int port_id) { 167 void ClearPortDataAndNotifyDispatcher(int port_id) {
170 g_port_tracker.Get().DeletePort(port_id); 168 g_port_tracker.Get().DeletePort(port_id);
171 dispatcher_->ClearPortData(port_id); 169 dispatcher_->ClearPortData(port_id);
172 } 170 }
173 171
174 // Sends a message along the given channel. 172 // Sends a message along the given channel.
175 void PostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) { 173 void PostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
176 content::RenderFrame* renderframe = context()->GetRenderFrame(); 174 content::RenderFrame* render_frame = context()->GetRenderFrame();
177 if (!renderframe) 175 if (!render_frame)
178 return; 176 return;
179 177
180 // Arguments are (int32 port_id, string message). 178 // Arguments are (int32 port_id, string message).
181 CHECK(args.Length() == 2 && args[0]->IsInt32() && args[1]->IsString()); 179 CHECK(args.Length() == 2 && args[0]->IsInt32() && args[1]->IsString());
182 180
183 int port_id = args[0].As<v8::Int32>()->Value(); 181 int port_id = args[0].As<v8::Int32>()->Value();
184 if (!g_port_tracker.Get().HasPort(port_id)) { 182 if (!g_port_tracker.Get().HasPort(port_id)) {
185 v8::Local<v8::String> error_message = 183 v8::Local<v8::String> error_message =
186 ToV8StringUnsafe(args.GetIsolate(), kPortClosedError); 184 ToV8StringUnsafe(args.GetIsolate(), kPortClosedError);
187 args.GetIsolate()->ThrowException(v8::Exception::Error(error_message)); 185 args.GetIsolate()->ThrowException(v8::Exception::Error(error_message));
188 return; 186 return;
189 } 187 }
190 188
191 renderframe->Send(new ExtensionHostMsg_PostMessage( 189 render_frame->Send(new ExtensionHostMsg_PostMessage(
192 renderframe->GetRoutingID(), port_id, 190 render_frame->GetRoutingID(), port_id,
193 Message(*v8::String::Utf8Value(args[1]), 191 Message(*v8::String::Utf8Value(args[1]),
194 blink::WebUserGestureIndicator::isProcessingUserGesture()))); 192 blink::WebUserGestureIndicator::isProcessingUserGesture())));
195 } 193 }
196 194
197 // Forcefully disconnects a port. 195 // Forcefully disconnects a port.
198 void CloseChannel(const v8::FunctionCallbackInfo<v8::Value>& args) { 196 void CloseChannel(const v8::FunctionCallbackInfo<v8::Value>& args) {
199 // Arguments are (int32 port_id, boolean notify_browser). 197 // Arguments are (int32 port_id, boolean notify_browser).
200 CHECK_EQ(2, args.Length()); 198 CHECK_EQ(2, args.Length());
201 CHECK(args[0]->IsInt32()); 199 CHECK(args[0]->IsInt32());
202 CHECK(args[1]->IsBoolean()); 200 CHECK(args[1]->IsBoolean());
203 201
204 int port_id = args[0].As<v8::Int32>()->Value(); 202 int port_id = args[0].As<v8::Int32>()->Value();
205 if (!g_port_tracker.Get().HasPort(port_id)) 203 if (!g_port_tracker.Get().HasPort(port_id))
206 return; 204 return;
207 205
208 // Send via the RenderThread because the RenderFrame might be closing. 206 // Send via the RenderThread because the RenderFrame might be closing.
209 bool notify_browser = args[1].As<v8::Boolean>()->Value(); 207 bool notify_browser = args[1].As<v8::Boolean>()->Value();
210 if (notify_browser) { 208 content::RenderFrame* render_frame = context()->GetRenderFrame();
211 content::RenderThread::Get()->Send( 209 if (notify_browser && render_frame) {
212 new ExtensionHostMsg_CloseChannel(port_id, std::string())); 210 render_frame->Send(new ExtensionHostMsg_CloseMessagePort(
211 render_frame->GetRoutingID(), port_id, true));
213 } 212 }
214 213
215 ClearPortDataAndNotifyDispatcher(port_id); 214 ClearPortDataAndNotifyDispatcher(port_id);
216 } 215 }
217 216
218 // A new port has been created for a context. This occurs both when script 217 // A new port has been created for a context. This occurs both when script
219 // opens a connection, and when a connection is opened to this script. 218 // opens a connection, and when a connection is opened to this script.
220 void PortAddRef(const v8::FunctionCallbackInfo<v8::Value>& args) { 219 void PortAddRef(const v8::FunctionCallbackInfo<v8::Value>& args) {
221 // Arguments are (int32 port_id). 220 // Arguments are (int32 port_id).
222 CHECK_EQ(1, args.Length()); 221 CHECK_EQ(1, args.Length());
223 CHECK(args[0]->IsInt32()); 222 CHECK(args[0]->IsInt32());
224 223
225 int port_id = args[0].As<v8::Int32>()->Value(); 224 int port_id = args[0].As<v8::Int32>()->Value();
226 g_port_tracker.Get().AddReference(context(), port_id); 225 g_port_tracker.Get().AddReference(context(), port_id);
227 } 226 }
228 227
229 // The frame a port lived in has been destroyed. When there are no more 228 // The frame a port lived in has been destroyed. When there are no more
230 // frames with a reference to a given port, we will disconnect it and notify 229 // frames with a reference to a given port, we will disconnect it and notify
231 // the other end of the channel. 230 // the other end of the channel.
231 // TODO(robwu): Port lifetime management has moved to the browser, this is no
232 // longer needed. See .destroy_() inmessaging.js for more details.
232 void PortRelease(const v8::FunctionCallbackInfo<v8::Value>& args) { 233 void PortRelease(const v8::FunctionCallbackInfo<v8::Value>& args) {
233 // Arguments are (int32 port_id). 234 // Arguments are (int32 port_id).
234 CHECK(args.Length() == 1 && args[0]->IsInt32()); 235 CHECK(args.Length() == 1 && args[0]->IsInt32());
235 ReleasePort(args[0].As<v8::Int32>()->Value()); 236 ReleasePort(args[0].As<v8::Int32>()->Value());
236 } 237 }
237 238
238 // Releases the reference to |port_id| for this context, and clears all port 239 // Releases the reference to |port_id| for this context, and clears all port
239 // data if there are no more references. 240 // data if there are no more references.
240 void ReleasePort(int port_id) { 241 void ReleasePort(int port_id) {
242 content::RenderFrame* render_frame = context()->GetRenderFrame();
241 if (g_port_tracker.Get().RemoveReference(context(), port_id) && 243 if (g_port_tracker.Get().RemoveReference(context(), port_id) &&
242 !g_port_tracker.Get().HasPort(port_id)) { 244 !g_port_tracker.Get().HasPort(port_id) && render_frame) {
243 // Send via the RenderThread because the RenderFrame might be closing. 245 render_frame->Send(new ExtensionHostMsg_CloseMessagePort(
244 content::RenderThread::Get()->Send( 246 render_frame->GetRoutingID(), port_id, false));
245 new ExtensionHostMsg_CloseChannel(port_id, std::string()));
246 ClearPortDataAndNotifyDispatcher(port_id);
247 } 247 }
248 } 248 }
249 249
250 // void BindToGC(object, callback, port_id) 250 // void BindToGC(object, callback, port_id)
251 // 251 //
252 // Binds |callback| to be invoked *sometime after* |object| is garbage 252 // Binds |callback| to be invoked *sometime after* |object| is garbage
253 // collected. We don't call the method re-entrantly so as to avoid executing 253 // collected. We don't call the method re-entrantly so as to avoid executing
254 // JS in some bizarro undefined mid-GC state, nor do we then call into the 254 // JS in some bizarro undefined mid-GC state, nor do we then call into the
255 // script context if it's been invalidated. 255 // script context if it's been invalidated.
256 // 256 //
(...skipping 20 matching lines...) Expand all
277 }; 277 };
278 278
279 void DispatchOnConnectToScriptContext( 279 void DispatchOnConnectToScriptContext(
280 int target_port_id, 280 int target_port_id,
281 const std::string& channel_name, 281 const std::string& channel_name,
282 const ExtensionMsg_TabConnectionInfo* source, 282 const ExtensionMsg_TabConnectionInfo* source,
283 const ExtensionMsg_ExternalConnectionInfo& info, 283 const ExtensionMsg_ExternalConnectionInfo& info,
284 const std::string& tls_channel_id, 284 const std::string& tls_channel_id,
285 bool* port_created, 285 bool* port_created,
286 ScriptContext* script_context) { 286 ScriptContext* script_context) {
287 // Only dispatch the events if this is the requested target frame (0 = main
288 // frame; positive = child frame).
289 content::RenderFrame* renderframe = script_context->GetRenderFrame();
290 if (info.target_frame_id == 0 && renderframe->GetWebFrame()->parent() != NULL)
291 return;
292 if (info.target_frame_id > 0 &&
293 renderframe->GetRoutingID() != info.target_frame_id)
294 return;
295
296 // Bandaid fix for crbug.com/520303.
297 // TODO(rdevlin.cronin): Fix this properly by routing messages to the correct
298 // RenderFrame from the browser (same with |target_frame_id| in fact).
299 if (info.target_tab_id != -1 &&
300 info.target_tab_id != ExtensionFrameHelper::Get(renderframe)->tab_id()) {
301 return;
302 }
303
304 v8::Isolate* isolate = script_context->isolate(); 287 v8::Isolate* isolate = script_context->isolate();
305 v8::HandleScope handle_scope(isolate); 288 v8::HandleScope handle_scope(isolate);
306 289
307 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create()); 290 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
308 291
309 const std::string& source_url_spec = info.source_url.spec(); 292 const std::string& source_url_spec = info.source_url.spec();
310 std::string target_extension_id = script_context->GetExtensionID(); 293 std::string target_extension_id = script_context->GetExtensionID();
311 const Extension* extension = script_context->extension(); 294 const Extension* extension = script_context->extension();
312 295
313 v8::Local<v8::Value> tab = v8::Null(isolate); 296 v8::Local<v8::Value> tab = v8::Null(isolate);
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 const ExtensionMsg_TabConnectionInfo& source, 446 const ExtensionMsg_TabConnectionInfo& source,
464 const ExtensionMsg_ExternalConnectionInfo& info, 447 const ExtensionMsg_ExternalConnectionInfo& info,
465 const std::string& tls_channel_id, 448 const std::string& tls_channel_id,
466 content::RenderFrame* restrict_to_render_frame) { 449 content::RenderFrame* restrict_to_render_frame) {
467 bool port_created = false; 450 bool port_created = false;
468 context_set.ForEach( 451 context_set.ForEach(
469 info.target_id, restrict_to_render_frame, 452 info.target_id, restrict_to_render_frame,
470 base::Bind(&DispatchOnConnectToScriptContext, target_port_id, 453 base::Bind(&DispatchOnConnectToScriptContext, target_port_id,
471 channel_name, &source, info, tls_channel_id, &port_created)); 454 channel_name, &source, info, tls_channel_id, &port_created));
472 455
473 // If we didn't create a port, notify the other end of the channel (treat it 456 int routing_id = restrict_to_render_frame
474 // as a disconnect). 457 ? restrict_to_render_frame->GetRoutingID()
475 if (!port_created) { 458 : MSG_ROUTING_NONE;
476 content::RenderThread::Get()->Send(new ExtensionHostMsg_CloseChannel( 459 if (port_created) {
477 target_port_id, kReceivingEndDoesntExistError)); 460 content::RenderThread::Get()->Send(
461 new ExtensionHostMsg_OpenMessagePort(routing_id, target_port_id));
462 } else {
463 content::RenderThread::Get()->Send(new ExtensionHostMsg_CloseMessagePort(
464 routing_id, target_port_id, false));
478 } 465 }
479 } 466 }
480 467
481 // static 468 // static
482 void MessagingBindings::DeliverMessage( 469 void MessagingBindings::DeliverMessage(
483 const ScriptContextSet& context_set, 470 const ScriptContextSet& context_set,
484 int target_port_id, 471 int target_port_id,
485 const Message& message, 472 const Message& message,
486 content::RenderFrame* restrict_to_render_frame) { 473 content::RenderFrame* restrict_to_render_frame) {
487 context_set.ForEach( 474 context_set.ForEach(
488 restrict_to_render_frame, 475 restrict_to_render_frame,
489 base::Bind(&DeliverMessageToScriptContext, message, target_port_id)); 476 base::Bind(&DeliverMessageToScriptContext, message, target_port_id));
490 } 477 }
491 478
492 // static 479 // static
493 void MessagingBindings::DispatchOnDisconnect( 480 void MessagingBindings::DispatchOnDisconnect(
494 const ScriptContextSet& context_set, 481 const ScriptContextSet& context_set,
495 int port_id, 482 int port_id,
496 const std::string& error_message, 483 const std::string& error_message,
497 content::RenderFrame* restrict_to_render_frame) { 484 content::RenderFrame* restrict_to_render_frame) {
498 context_set.ForEach( 485 context_set.ForEach(
499 restrict_to_render_frame, 486 restrict_to_render_frame,
500 base::Bind(&DispatchOnDisconnectToScriptContext, port_id, error_message)); 487 base::Bind(&DispatchOnDisconnectToScriptContext, port_id, error_message));
501 } 488 }
502 489
503 } // namespace extensions 490 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698