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

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

Powered by Google App Engine
This is Rietveld 408576698