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

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

Issue 2633253002: Split content script injections into multiple tasks (Closed)
Patch Set: comments addressed Created 3 years, 9 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/script_injection.h ('k') | extensions/renderer/script_injection_manager.cc » ('j') | 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/script_injection.h" 5 #include "extensions/renderer/script_injection.h"
6 6
7 #include <map> 7 #include <map>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/lazy_instance.h" 10 #include "base/lazy_instance.h"
11 #include "base/macros.h" 11 #include "base/macros.h"
12 #include "base/metrics/histogram_macros.h" 12 #include "base/metrics/histogram_macros.h"
13 #include "base/timer/elapsed_timer.h" 13 #include "base/timer/elapsed_timer.h"
14 #include "base/values.h" 14 #include "base/values.h"
15 #include "content/public/child/v8_value_converter.h" 15 #include "content/public/child/v8_value_converter.h"
16 #include "content/public/renderer/render_frame.h" 16 #include "content/public/renderer/render_frame.h"
17 #include "extensions/common/extension_messages.h" 17 #include "extensions/common/extension_messages.h"
18 #include "extensions/common/feature_switch.h"
18 #include "extensions/common/host_id.h" 19 #include "extensions/common/host_id.h"
19 #include "extensions/renderer/dom_activity_logger.h" 20 #include "extensions/renderer/dom_activity_logger.h"
20 #include "extensions/renderer/extension_frame_helper.h" 21 #include "extensions/renderer/extension_frame_helper.h"
21 #include "extensions/renderer/extensions_renderer_client.h" 22 #include "extensions/renderer/extensions_renderer_client.h"
22 #include "extensions/renderer/script_injection_callback.h" 23 #include "extensions/renderer/script_injection_callback.h"
23 #include "extensions/renderer/scripts_run_info.h" 24 #include "extensions/renderer/scripts_run_info.h"
24 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h" 25 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
25 #include "third_party/WebKit/public/platform/WebString.h" 26 #include "third_party/WebKit/public/platform/WebString.h"
26 #include "third_party/WebKit/public/web/WebDocument.h" 27 #include "third_party/WebKit/public/web/WebDocument.h"
27 #include "third_party/WebKit/public/web/WebLocalFrame.h" 28 #include "third_party/WebKit/public/web/WebLocalFrame.h"
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 id, blink::WebSecurityOrigin::create(injection_host->url())); 71 id, blink::WebSecurityOrigin::create(injection_host->url()));
71 frame->setIsolatedWorldContentSecurityPolicy( 72 frame->setIsolatedWorldContentSecurityPolicy(
72 id, blink::WebString::fromUTF8( 73 id, blink::WebString::fromUTF8(
73 injection_host->GetContentSecurityPolicy())); 74 injection_host->GetContentSecurityPolicy()));
74 frame->setIsolatedWorldHumanReadableName( 75 frame->setIsolatedWorldHumanReadableName(
75 id, blink::WebString::fromUTF8(injection_host->name())); 76 id, blink::WebString::fromUTF8(injection_host->name()));
76 77
77 return id; 78 return id;
78 } 79 }
79 80
81 // This class manages its own lifetime.
82 class TimedScriptInjectionCallback : public ScriptInjectionCallback {
83 public:
84 explicit TimedScriptInjectionCallback(
85 base::WeakPtr<ScriptInjection> injection)
86 : ScriptInjectionCallback(
87 base::Bind(&TimedScriptInjectionCallback::OnCompleted,
88 base::Unretained(this))),
89 injection_(injection) {}
90 ~TimedScriptInjectionCallback() override {}
91
92 void OnCompleted(const std::vector<v8::Local<v8::Value>>& result) {
93 if (injection_) {
94 base::TimeDelta elapsed = base::TimeTicks::Now() - start_time_;
95 injection_->OnJsInjectionCompleted(result, elapsed);
96 }
97 }
98
99 void willExecute() override { start_time_ = base::TimeTicks::Now(); }
100
101 private:
102 base::WeakPtr<ScriptInjection> injection_;
103 base::TimeTicks start_time_;
104 };
105
80 } // namespace 106 } // namespace
81 107
82 // Watches for the deletion of a RenderFrame, after which is_valid will return 108 // Watches for the deletion of a RenderFrame, after which is_valid will return
83 // false. 109 // false.
84 class ScriptInjection::FrameWatcher : public content::RenderFrameObserver { 110 class ScriptInjection::FrameWatcher : public content::RenderFrameObserver {
85 public: 111 public:
86 FrameWatcher(content::RenderFrame* render_frame, 112 FrameWatcher(content::RenderFrame* render_frame,
87 ScriptInjection* injection) 113 ScriptInjection* injection)
88 : content::RenderFrameObserver(render_frame), 114 : content::RenderFrameObserver(render_frame),
89 injection_(injection) {} 115 injection_(injection) {}
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 run_location_, executing_scripts, num_injected_js_scripts); 277 run_location_, executing_scripts, num_injected_js_scripts);
252 DCHECK(!sources.empty()); 278 DCHECK(!sources.empty());
253 bool in_main_world = injector_->ShouldExecuteInMainWorld(); 279 bool in_main_world = injector_->ShouldExecuteInMainWorld();
254 int world_id = in_main_world 280 int world_id = in_main_world
255 ? DOMActivityLogger::kMainWorldId 281 ? DOMActivityLogger::kMainWorldId
256 : GetIsolatedWorldIdForInstance(injection_host_.get(), 282 : GetIsolatedWorldIdForInstance(injection_host_.get(),
257 web_frame); 283 web_frame);
258 bool is_user_gesture = injector_->IsUserGesture(); 284 bool is_user_gesture = injector_->IsUserGesture();
259 285
260 std::unique_ptr<blink::WebScriptExecutionCallback> callback( 286 std::unique_ptr<blink::WebScriptExecutionCallback> callback(
261 new ScriptInjectionCallback( 287 new TimedScriptInjectionCallback(weak_ptr_factory_.GetWeakPtr()));
262 base::Bind(&ScriptInjection::OnJsInjectionCompleted,
263 weak_ptr_factory_.GetWeakPtr())));
264 288
265 base::ElapsedTimer exec_timer; 289 base::ElapsedTimer exec_timer;
266 if (injection_host_->id().type() == HostID::EXTENSIONS && log_activity_) 290 if (injection_host_->id().type() == HostID::EXTENSIONS && log_activity_)
267 DOMActivityLogger::AttachToWorld(world_id, injection_host_->id().id()); 291 DOMActivityLogger::AttachToWorld(world_id, injection_host_->id().id());
268 if (in_main_world) { 292 if (in_main_world) {
269 // We only inject in the main world for javascript: urls. 293 // We only inject in the main world for javascript: urls.
270 DCHECK_EQ(1u, sources.size()); 294 DCHECK_EQ(1u, sources.size());
271 295
272 web_frame->requestExecuteScriptAndReturnValue(sources.front(), 296 web_frame->requestExecuteScriptAndReturnValue(sources.front(),
273 is_user_gesture, 297 is_user_gesture,
274 callback.release()); 298 callback.release());
275 } else { 299 } else {
300 blink::WebLocalFrame::ScriptExecutionType option;
301 if (injector_->script_type() == UserScript::CONTENT_SCRIPT &&
302 FeatureSwitch::yield_between_content_script_runs()->IsEnabled()) {
303 switch (run_location_) {
304 case UserScript::DOCUMENT_END:
305 case UserScript::DOCUMENT_IDLE:
306 option = blink::WebLocalFrame::AsynchronousBlockingOnload;
307 break;
308 default:
309 option = blink::WebLocalFrame::Synchronous;
310 break;
311 }
312 } else {
313 option = blink::WebLocalFrame::Synchronous;
314 }
276 web_frame->requestExecuteScriptInIsolatedWorld( 315 web_frame->requestExecuteScriptInIsolatedWorld(
277 world_id, 316 world_id, &sources.front(), sources.size(), is_user_gesture, option,
278 &sources.front(),
279 sources.size(),
280 is_user_gesture,
281 callback.release()); 317 callback.release());
282 } 318 }
283 319
284 if (injection_host_->id().type() == HostID::EXTENSIONS) 320 if (injection_host_->id().type() == HostID::EXTENSIONS)
285 UMA_HISTOGRAM_TIMES("Extensions.InjectScriptTime", exec_timer.Elapsed()); 321 UMA_HISTOGRAM_TIMES("Extensions.InjectScriptTime", exec_timer.Elapsed());
286 } 322 }
287 323
288 void ScriptInjection::OnJsInjectionCompleted( 324 void ScriptInjection::OnJsInjectionCompleted(
289 const std::vector<v8::Local<v8::Value>>& results) { 325 const std::vector<v8::Local<v8::Value>>& results,
326 base::TimeDelta elapsed) {
290 DCHECK(!did_inject_js_); 327 DCHECK(!did_inject_js_);
291 328
329 if (injection_host_->id().type() == HostID::EXTENSIONS)
330 UMA_HISTOGRAM_TIMES("Extensions.InjectedScriptExecutionTime", elapsed);
331
292 bool expects_results = injector_->ExpectsResults(); 332 bool expects_results = injector_->ExpectsResults();
293 if (expects_results) { 333 if (expects_results) {
294 if (!results.empty() && !results[0].IsEmpty()) { 334 if (!results.empty() && !results[0].IsEmpty()) {
295 // Right now, we only support returning single results (per frame). 335 // Right now, we only support returning single results (per frame).
296 std::unique_ptr<content::V8ValueConverter> v8_converter( 336 std::unique_ptr<content::V8ValueConverter> v8_converter(
297 content::V8ValueConverter::create()); 337 content::V8ValueConverter::create());
298 // It's safe to always use the main world context when converting 338 // It's safe to always use the main world context when converting
299 // here. V8ValueConverterImpl shouldn't actually care about the 339 // here. V8ValueConverterImpl shouldn't actually care about the
300 // context scope, and it switches to v8::Object's creation context 340 // context scope, and it switches to v8::Object's creation context
301 // when encountered. 341 // when encountered.
302 v8::Local<v8::Context> context = 342 v8::Local<v8::Context> context =
303 render_frame_->GetWebFrame()->mainWorldScriptContext(); 343 render_frame_->GetWebFrame()->mainWorldScriptContext();
304 execution_result_ = v8_converter->FromV8Value(results[0], context); 344 execution_result_ = v8_converter->FromV8Value(results[0], context);
305 } 345 }
306 if (!execution_result_.get()) 346 if (!execution_result_.get())
307 execution_result_ = base::Value::CreateNullValue(); 347 execution_result_ = base::Value::CreateNullValue();
308 } 348 }
309 did_inject_js_ = true; 349 did_inject_js_ = true;
310 350
311 // If |async_completion_callback_| is set, it means the script finished 351 // If |async_completion_callback_| is set, it means the script finished
312 // asynchronously, and we should run it. 352 // asynchronously, and we should run it.
313 if (!async_completion_callback_.is_null()) { 353 if (!async_completion_callback_.is_null()) {
354 complete_ = true;
314 injector_->OnInjectionComplete(std::move(execution_result_), run_location_, 355 injector_->OnInjectionComplete(std::move(execution_result_), run_location_,
315 render_frame_); 356 render_frame_);
316 // Warning: this object can be destroyed after this line! 357 // Warning: this object can be destroyed after this line!
317 async_completion_callback_.Run(this); 358 async_completion_callback_.Run(this);
318 } 359 }
319 } 360 }
320 361
321 void ScriptInjection::InjectCss(std::set<std::string>* injected_stylesheets, 362 void ScriptInjection::InjectCss(std::set<std::string>* injected_stylesheets,
322 size_t* num_injected_stylesheets) { 363 size_t* num_injected_stylesheets) {
323 std::vector<blink::WebString> css_sources = injector_->GetCssSources( 364 std::vector<blink::WebString> css_sources = injector_->GetCssSources(
324 run_location_, injected_stylesheets, num_injected_stylesheets); 365 run_location_, injected_stylesheets, num_injected_stylesheets);
325 blink::WebLocalFrame* web_frame = render_frame_->GetWebFrame(); 366 blink::WebLocalFrame* web_frame = render_frame_->GetWebFrame();
326 for (const blink::WebString& css : css_sources) 367 for (const blink::WebString& css : css_sources)
327 web_frame->document().insertStyleSheet(css); 368 web_frame->document().insertStyleSheet(css);
328 } 369 }
329 370
330 } // namespace extensions 371 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/renderer/script_injection.h ('k') | extensions/renderer/script_injection_manager.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698