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

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

Issue 2295753003: [Extensions] Clean up MessagingBindings (Closed)
Patch Set: Created 4 years, 3 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
« no previous file with comments | « extensions/renderer/messaging_bindings.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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>
11 11
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/bind_helpers.h" 13 #include "base/bind_helpers.h"
14 #include "base/callback.h" 14 #include "base/callback.h"
15 #include "base/macros.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/message_loop/message_loop.h" 15 #include "base/message_loop/message_loop.h"
18 #include "base/values.h" 16 #include "base/values.h"
19 #include "components/guest_view/common/guest_view_constants.h"
20 #include "content/public/child/v8_value_converter.h" 17 #include "content/public/child/v8_value_converter.h"
21 #include "content/public/common/child_process_host.h" 18 #include "content/public/common/child_process_host.h"
22 #include "content/public/renderer/render_frame.h" 19 #include "content/public/renderer/render_frame.h"
23 #include "content/public/renderer/render_thread.h" 20 #include "content/public/renderer/render_thread.h"
24 #include "extensions/common/api/messaging/message.h" 21 #include "extensions/common/api/messaging/message.h"
25 #include "extensions/common/extension_messages.h" 22 #include "extensions/common/extension_messages.h"
26 #include "extensions/common/manifest_handlers/externally_connectable.h" 23 #include "extensions/common/manifest_handlers/externally_connectable.h"
27 #include "extensions/renderer/event_bindings.h"
28 #include "extensions/renderer/extension_frame_helper.h" 24 #include "extensions/renderer/extension_frame_helper.h"
29 #include "extensions/renderer/gc_callback.h" 25 #include "extensions/renderer/gc_callback.h"
30 #include "extensions/renderer/object_backed_native_handler.h"
31 #include "extensions/renderer/script_context.h" 26 #include "extensions/renderer/script_context.h"
32 #include "extensions/renderer/script_context_set.h" 27 #include "extensions/renderer/script_context_set.h"
33 #include "extensions/renderer/v8_helpers.h" 28 #include "extensions/renderer/v8_helpers.h"
34 #include "third_party/WebKit/public/web/WebDocument.h" 29 #include "third_party/WebKit/public/web/WebDocument.h"
35 #include "third_party/WebKit/public/web/WebLocalFrame.h" 30 #include "third_party/WebKit/public/web/WebLocalFrame.h"
36 #include "third_party/WebKit/public/web/WebScopedUserGesture.h" 31 #include "third_party/WebKit/public/web/WebScopedUserGesture.h"
37 #include "third_party/WebKit/public/web/WebScopedWindowFocusAllowedIndicator.h" 32 #include "third_party/WebKit/public/web/WebScopedWindowFocusAllowedIndicator.h"
38 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" 33 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
39 #include "v8/include/v8.h" 34 #include "v8/include/v8.h"
40 35
41 // Message passing API example (in a content script): 36 // Message passing API example (in a content script):
42 // var extension = 37 // var extension =
43 // new chrome.Extension('00123456789abcdef0123456789abcdef0123456'); 38 // new chrome.Extension('00123456789abcdef0123456789abcdef0123456');
44 // var port = runtime.connect(); 39 // var port = runtime.connect();
45 // port.postMessage('Can you hear me now?'); 40 // port.postMessage('Can you hear me now?');
46 // port.onmessage.addListener(function(msg, port) { 41 // port.onmessage.addListener(function(msg, port) {
47 // alert('response=' + msg); 42 // alert('response=' + msg);
48 // port.postMessage('I got your reponse'); 43 // port.postMessage('I got your reponse');
49 // }); 44 // });
50 45
51 using content::RenderThread;
52 using content::V8ValueConverter;
53
54 namespace extensions { 46 namespace extensions {
55 47
56 using v8_helpers::ToV8String; 48 using v8_helpers::ToV8String;
57 using v8_helpers::ToV8StringUnsafe;
58 using v8_helpers::IsEmptyOrUndefied; 49 using v8_helpers::IsEmptyOrUndefied;
59 50
60 namespace { 51 namespace {
61 52
62 class ExtensionImpl : public ObjectBackedNativeHandler {
Devlin 2016/08/30 22:40:56 All these are copy-pasted with no behavior changes
63 public:
64 explicit ExtensionImpl(ScriptContext* context)
65 : ObjectBackedNativeHandler(context), weak_ptr_factory_(this) {
66 RouteFunction(
67 "CloseChannel",
68 base::Bind(&ExtensionImpl::CloseChannel, base::Unretained(this)));
69 RouteFunction(
70 "PostMessage",
71 base::Bind(&ExtensionImpl::PostMessage, base::Unretained(this)));
72 // TODO(fsamuel, kalman): Move BindToGC out of messaging natives.
73 RouteFunction("BindToGC",
74 base::Bind(&ExtensionImpl::BindToGC, base::Unretained(this)));
75 }
76
77 ~ExtensionImpl() override {}
78
79 private:
80 // Sends a message along the given channel.
81 void PostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
82 // Arguments are (int32_t port_id, string message).
83 CHECK(args.Length() == 2 && args[0]->IsInt32() && args[1]->IsString());
84
85 int port_id = args[0].As<v8::Int32>()->Value();
86
87 content::RenderFrame* render_frame = context()->GetRenderFrame();
88 if (render_frame) {
89 render_frame->Send(new ExtensionHostMsg_PostMessage(
90 render_frame->GetRoutingID(), port_id,
91 Message(*v8::String::Utf8Value(args[1]),
92 blink::WebUserGestureIndicator::isProcessingUserGesture())));
93 }
94 }
95
96 // Close a port, optionally forcefully (i.e. close the whole channel instead
97 // of just the given port).
98 void CloseChannel(const v8::FunctionCallbackInfo<v8::Value>& args) {
99 // Arguments are (int32_t port_id, bool force_close).
100 CHECK_EQ(2, args.Length());
101 CHECK(args[0]->IsInt32());
102 CHECK(args[1]->IsBoolean());
103
104 int port_id = args[0].As<v8::Int32>()->Value();
105 bool force_close = args[1].As<v8::Boolean>()->Value();
106 ClosePort(port_id, force_close);
107 }
108
109 // void BindToGC(object, callback, port_id)
110 //
111 // Binds |callback| to be invoked *sometime after* |object| is garbage
112 // collected. We don't call the method re-entrantly so as to avoid executing
113 // JS in some bizarro undefined mid-GC state, nor do we then call into the
114 // script context if it's been invalidated.
115 //
116 // If the script context *is* invalidated in the meantime, as a slight hack,
117 // release the port with ID |port_id| if it's >= 0.
118 void BindToGC(const v8::FunctionCallbackInfo<v8::Value>& args) {
119 CHECK(args.Length() == 3 && args[0]->IsObject() && args[1]->IsFunction() &&
120 args[2]->IsInt32());
121 int port_id = args[2].As<v8::Int32>()->Value();
122 base::Closure fallback = base::Bind(&base::DoNothing);
123 if (port_id >= 0) {
124 // TODO(robwu): Falling back to closing the port shouldn't be needed. If
125 // the script context is destroyed, then the frame has navigated. But that
126 // is already detected by the browser, so this logic is redundant. Remove
127 // this fallback (and move BindToGC out of messaging because it is also
128 // used in other places that have nothing to do with messaging...).
129 fallback =
130 base::Bind(&ExtensionImpl::ClosePort, weak_ptr_factory_.GetWeakPtr(),
131 port_id, false /* force_close */);
132 }
133 // Destroys itself when the object is GC'd or context is invalidated.
134 new GCCallback(context(), args[0].As<v8::Object>(),
135 args[1].As<v8::Function>(), fallback);
136 }
137
138 // See ExtensionImpl::CloseChannel for documentation.
139 // TODO(robwu): Merge this logic with CloseChannel once the TODO in BindToGC
140 // has been addressed.
141 void ClosePort(int port_id, bool force_close) {
142 content::RenderFrame* render_frame = context()->GetRenderFrame();
143 if (render_frame) {
144 render_frame->Send(new ExtensionHostMsg_CloseMessagePort(
145 render_frame->GetRoutingID(), port_id, force_close));
146 }
147 }
148
149 base::WeakPtrFactory<ExtensionImpl> weak_ptr_factory_;
150 };
151
152 void HasMessagePort(int port_id, 53 void HasMessagePort(int port_id,
153 bool* has_port, 54 bool* has_port,
154 ScriptContext* script_context) { 55 ScriptContext* script_context) {
155 if (*has_port) 56 if (*has_port)
156 return; // Stop checking if the port was found. 57 return; // Stop checking if the port was found.
157 58
158 v8::Isolate* isolate = script_context->isolate(); 59 v8::Isolate* isolate = script_context->isolate();
159 v8::HandleScope handle_scope(isolate); 60 v8::HandleScope handle_scope(isolate);
160 61
161 v8::Local<v8::Value> port_id_handle = v8::Integer::New(isolate, port_id); 62 v8::Local<v8::Value> port_id_handle = v8::Integer::New(isolate, port_id);
(...skipping 12 matching lines...) Expand all
174 int target_port_id, 75 int target_port_id,
175 const std::string& channel_name, 76 const std::string& channel_name,
176 const ExtensionMsg_TabConnectionInfo* source, 77 const ExtensionMsg_TabConnectionInfo* source,
177 const ExtensionMsg_ExternalConnectionInfo& info, 78 const ExtensionMsg_ExternalConnectionInfo& info,
178 const std::string& tls_channel_id, 79 const std::string& tls_channel_id,
179 bool* port_created, 80 bool* port_created,
180 ScriptContext* script_context) { 81 ScriptContext* script_context) {
181 v8::Isolate* isolate = script_context->isolate(); 82 v8::Isolate* isolate = script_context->isolate();
182 v8::HandleScope handle_scope(isolate); 83 v8::HandleScope handle_scope(isolate);
183 84
184 std::unique_ptr<V8ValueConverter> converter(V8ValueConverter::create()); 85 std::unique_ptr<content::V8ValueConverter> converter(
86 content::V8ValueConverter::create());
185 87
186 const std::string& source_url_spec = info.source_url.spec(); 88 const std::string& source_url_spec = info.source_url.spec();
187 std::string target_extension_id = script_context->GetExtensionID(); 89 std::string target_extension_id = script_context->GetExtensionID();
188 const Extension* extension = script_context->extension(); 90 const Extension* extension = script_context->extension();
189 91
190 v8::Local<v8::Value> tab = v8::Null(isolate); 92 v8::Local<v8::Value> tab = v8::Null(isolate);
191 v8::Local<v8::Value> tls_channel_id_value = v8::Undefined(isolate); 93 v8::Local<v8::Value> tls_channel_id_value = v8::Undefined(isolate);
192 v8::Local<v8::Value> guest_process_id = v8::Undefined(isolate); 94 v8::Local<v8::Value> guest_process_id = v8::Undefined(isolate);
193 v8::Local<v8::Value> guest_render_frame_routing_id = v8::Undefined(isolate); 95 v8::Local<v8::Value> guest_render_frame_routing_id = v8::Undefined(isolate);
194 96
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 } else { 223 } else {
322 arguments.push_back(v8::Null(isolate)); 224 arguments.push_back(v8::Null(isolate));
323 } 225 }
324 226
325 script_context->module_system()->CallModuleMethod( 227 script_context->module_system()->CallModuleMethod(
326 "messaging", "dispatchOnDisconnect", &arguments); 228 "messaging", "dispatchOnDisconnect", &arguments);
327 } 229 }
328 230
329 } // namespace 231 } // namespace
330 232
331 ObjectBackedNativeHandler* MessagingBindings::Get(ScriptContext* context) { 233 MessagingBindings::MessagingBindings(ScriptContext* context)
332 return new ExtensionImpl(context); 234 : ObjectBackedNativeHandler(context), weak_ptr_factory_(this) {
235 RouteFunction("CloseChannel", base::Bind(&MessagingBindings::CloseChannel,
236 base::Unretained(this)));
237 RouteFunction("PostMessage", base::Bind(&MessagingBindings::PostMessage,
238 base::Unretained(this)));
239 // TODO(fsamuel, kalman): Move BindToGC out of messaging natives.
240 RouteFunction("BindToGC", base::Bind(&MessagingBindings::BindToGC,
241 base::Unretained(this)));
333 } 242 }
334 243
244 MessagingBindings::~MessagingBindings() {}
245
246 // static
335 void MessagingBindings::ValidateMessagePort( 247 void MessagingBindings::ValidateMessagePort(
336 const ScriptContextSet& context_set, 248 const ScriptContextSet& context_set,
337 int port_id, 249 int port_id,
338 content::RenderFrame* render_frame) { 250 content::RenderFrame* render_frame) {
339 int routing_id = render_frame->GetRoutingID(); 251 int routing_id = render_frame->GetRoutingID();
340 252
341 bool has_port = false; 253 bool has_port = false;
342 context_set.ForEach(render_frame, 254 context_set.ForEach(render_frame,
343 base::Bind(&HasMessagePort, port_id, &has_port)); 255 base::Bind(&HasMessagePort, port_id, &has_port));
344 // Note: HasMessagePort invokes a JavaScript function. If the runtime of the 256 // Note: HasMessagePort invokes a JavaScript function. If the runtime of the
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 void MessagingBindings::DispatchOnDisconnect( 308 void MessagingBindings::DispatchOnDisconnect(
397 const ScriptContextSet& context_set, 309 const ScriptContextSet& context_set,
398 int port_id, 310 int port_id,
399 const std::string& error_message, 311 const std::string& error_message,
400 content::RenderFrame* restrict_to_render_frame) { 312 content::RenderFrame* restrict_to_render_frame) {
401 context_set.ForEach( 313 context_set.ForEach(
402 restrict_to_render_frame, 314 restrict_to_render_frame,
403 base::Bind(&DispatchOnDisconnectToScriptContext, port_id, error_message)); 315 base::Bind(&DispatchOnDisconnectToScriptContext, port_id, error_message));
404 } 316 }
405 317
318 void MessagingBindings::PostMessage(
319 const v8::FunctionCallbackInfo<v8::Value>& args) {
320 // Arguments are (int32_t port_id, string message).
321 CHECK(args.Length() == 2 && args[0]->IsInt32() && args[1]->IsString());
322
323 int port_id = args[0].As<v8::Int32>()->Value();
324
325 content::RenderFrame* render_frame = context()->GetRenderFrame();
326 if (render_frame) {
327 render_frame->Send(new ExtensionHostMsg_PostMessage(
328 render_frame->GetRoutingID(), port_id,
329 Message(*v8::String::Utf8Value(args[1]),
330 blink::WebUserGestureIndicator::isProcessingUserGesture())));
331 }
332 }
333
334 void MessagingBindings::CloseChannel(
335 const v8::FunctionCallbackInfo<v8::Value>& args) {
336 // Arguments are (int32_t port_id, bool force_close).
337 CHECK_EQ(2, args.Length());
338 CHECK(args[0]->IsInt32());
339 CHECK(args[1]->IsBoolean());
340
341 int port_id = args[0].As<v8::Int32>()->Value();
342 bool force_close = args[1].As<v8::Boolean>()->Value();
343 ClosePort(port_id, force_close);
344 }
345
346 void MessagingBindings::BindToGC(
347 const v8::FunctionCallbackInfo<v8::Value>& args) {
348 CHECK(args.Length() == 3 && args[0]->IsObject() && args[1]->IsFunction() &&
349 args[2]->IsInt32());
350 int port_id = args[2].As<v8::Int32>()->Value();
351 base::Closure fallback = base::Bind(&base::DoNothing);
352 if (port_id >= 0) {
353 // TODO(robwu): Falling back to closing the port shouldn't be needed. If
354 // the script context is destroyed, then the frame has navigated. But that
355 // is already detected by the browser, so this logic is redundant. Remove
356 // this fallback (and move BindToGC out of messaging because it is also
357 // used in other places that have nothing to do with messaging...).
358 fallback = base::Bind(&MessagingBindings::ClosePort,
359 weak_ptr_factory_.GetWeakPtr(), port_id,
360 false /* force_close */);
361 }
362 // Destroys itself when the object is GC'd or context is invalidated.
363 new GCCallback(context(), args[0].As<v8::Object>(),
364 args[1].As<v8::Function>(), fallback);
365 }
366
367 void MessagingBindings::ClosePort(int port_id, bool force_close) {
368 // TODO(robwu): Merge this logic with CloseChannel once the TODO in BindToGC
369 // has been addressed.
370 content::RenderFrame* render_frame = context()->GetRenderFrame();
371 if (render_frame) {
372 render_frame->Send(new ExtensionHostMsg_CloseMessagePort(
373 render_frame->GetRoutingID(), port_id, force_close));
374 }
375 }
376
406 } // namespace extensions 377 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/renderer/messaging_bindings.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698