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

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: Charlie's nits (#33) Created 5 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
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.
232 void PortRelease(const v8::FunctionCallbackInfo<v8::Value>& args) { 231 void PortRelease(const v8::FunctionCallbackInfo<v8::Value>& args) {
233 // Arguments are (int32 port_id). 232 // Arguments are (int32 port_id).
234 CHECK(args.Length() == 1 && args[0]->IsInt32()); 233 CHECK(args.Length() == 1 && args[0]->IsInt32());
235 ReleasePort(args[0].As<v8::Int32>()->Value()); 234 ReleasePort(args[0].As<v8::Int32>()->Value());
236 } 235 }
237 236
238 // Releases the reference to |port_id| for this context, and clears all port 237 // Releases the reference to |port_id| for this context, and clears all port
239 // data if there are no more references. 238 // data if there are no more references.
240 void ReleasePort(int port_id) { 239 void ReleasePort(int port_id) {
240 content::RenderFrame* render_frame = context()->GetRenderFrame();
241 if (g_port_tracker.Get().RemoveReference(context(), port_id) && 241 if (g_port_tracker.Get().RemoveReference(context(), port_id) &&
242 !g_port_tracker.Get().HasPort(port_id)) { 242 !g_port_tracker.Get().HasPort(port_id) && render_frame) {
243 // Send via the RenderThread because the RenderFrame might be closing. 243 render_frame->Send(new ExtensionHostMsg_CloseMessagePort(
244 content::RenderThread::Get()->Send( 244 render_frame->GetRoutingID(), port_id, false));
245 new ExtensionHostMsg_CloseChannel(port_id, std::string()));
246 ClearPortDataAndNotifyDispatcher(port_id);
247 } 245 }
248 } 246 }
249 247
250 // void BindToGC(object, callback, port_id) 248 // void BindToGC(object, callback, port_id)
251 // 249 //
252 // Binds |callback| to be invoked *sometime after* |object| is garbage 250 // 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 251 // 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 252 // JS in some bizarro undefined mid-GC state, nor do we then call into the
255 // script context if it's been invalidated. 253 // script context if it's been invalidated.
256 // 254 //
(...skipping 20 matching lines...) Expand all
277 }; 275 };
278 276
279 void DispatchOnConnectToScriptContext( 277 void DispatchOnConnectToScriptContext(
280 int target_port_id, 278 int target_port_id,
281 const std::string& channel_name, 279 const std::string& channel_name,
282 const ExtensionMsg_TabConnectionInfo* source, 280 const ExtensionMsg_TabConnectionInfo* source,
283 const ExtensionMsg_ExternalConnectionInfo& info, 281 const ExtensionMsg_ExternalConnectionInfo& info,
284 const std::string& tls_channel_id, 282 const std::string& tls_channel_id,
285 bool* port_created, 283 bool* port_created,
286 ScriptContext* script_context) { 284 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(); 285 v8::Isolate* isolate = script_context->isolate();
305 v8::HandleScope handle_scope(isolate); 286 v8::HandleScope handle_scope(isolate);
306 287
307 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create()); 288 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
308 289
309 const std::string& source_url_spec = info.source_url.spec(); 290 const std::string& source_url_spec = info.source_url.spec();
310 std::string target_extension_id = script_context->GetExtensionID(); 291 std::string target_extension_id = script_context->GetExtensionID();
311 const Extension* extension = script_context->extension(); 292 const Extension* extension = script_context->extension();
312 293
313 v8::Local<v8::Value> tab = v8::Null(isolate); 294 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, 444 const ExtensionMsg_TabConnectionInfo& source,
464 const ExtensionMsg_ExternalConnectionInfo& info, 445 const ExtensionMsg_ExternalConnectionInfo& info,
465 const std::string& tls_channel_id, 446 const std::string& tls_channel_id,
466 content::RenderFrame* restrict_to_render_frame) { 447 content::RenderFrame* restrict_to_render_frame) {
467 bool port_created = false; 448 bool port_created = false;
468 context_set.ForEach( 449 context_set.ForEach(
469 info.target_id, restrict_to_render_frame, 450 info.target_id, restrict_to_render_frame,
470 base::Bind(&DispatchOnConnectToScriptContext, target_port_id, 451 base::Bind(&DispatchOnConnectToScriptContext, target_port_id,
471 channel_name, &source, info, tls_channel_id, &port_created)); 452 channel_name, &source, info, tls_channel_id, &port_created));
472 453
473 // If we didn't create a port, notify the other end of the channel (treat it 454 int routing_id = restrict_to_render_frame
474 // as a disconnect). 455 ? restrict_to_render_frame->GetRoutingID()
475 if (!port_created) { 456 : MSG_ROUTING_NONE;
476 content::RenderThread::Get()->Send(new ExtensionHostMsg_CloseChannel( 457 if (port_created) {
477 target_port_id, kReceivingEndDoesntExistError)); 458 content::RenderThread::Get()->Send(
459 new ExtensionHostMsg_OpenMessagePort(routing_id, target_port_id));
460 } else {
461 content::RenderThread::Get()->Send(new ExtensionHostMsg_CloseMessagePort(
462 routing_id, target_port_id, false));
478 } 463 }
479 } 464 }
480 465
481 // static 466 // static
482 void MessagingBindings::DeliverMessage( 467 void MessagingBindings::DeliverMessage(
483 const ScriptContextSet& context_set, 468 const ScriptContextSet& context_set,
484 int target_port_id, 469 int target_port_id,
485 const Message& message, 470 const Message& message,
486 content::RenderFrame* restrict_to_render_frame) { 471 content::RenderFrame* restrict_to_render_frame) {
487 context_set.ForEach( 472 context_set.ForEach(
488 restrict_to_render_frame, 473 restrict_to_render_frame,
489 base::Bind(&DeliverMessageToScriptContext, message, target_port_id)); 474 base::Bind(&DeliverMessageToScriptContext, message, target_port_id));
490 } 475 }
491 476
492 // static 477 // static
493 void MessagingBindings::DispatchOnDisconnect( 478 void MessagingBindings::DispatchOnDisconnect(
494 const ScriptContextSet& context_set, 479 const ScriptContextSet& context_set,
495 int port_id, 480 int port_id,
496 const std::string& error_message, 481 const std::string& error_message,
497 content::RenderFrame* restrict_to_render_frame) { 482 content::RenderFrame* restrict_to_render_frame) {
498 context_set.ForEach( 483 context_set.ForEach(
499 restrict_to_render_frame, 484 restrict_to_render_frame,
500 base::Bind(&DispatchOnDisconnectToScriptContext, port_id, error_message)); 485 base::Bind(&DispatchOnDisconnectToScriptContext, port_id, error_message));
501 } 486 }
502 487
503 } // namespace extensions 488 } // namespace extensions
OLDNEW
« extensions/browser/extension_api_frame_id_map.cc ('K') | « extensions/extensions.gypi ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698