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

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

Issue 2633253002: Split content script injections into multiple tasks (Closed)
Patch Set: rebase 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
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 TimedScriptInjectionCallback(base::WeakPtr<ScriptInjection> injection)
85 : ScriptInjectionCallback(
86 base::Bind(&TimedScriptInjectionCallback::OnCompleted,
87 base::Unretained(this))),
88 injection_(injection) {}
89 ~TimedScriptInjectionCallback() override {}
90
91 void OnCompleted(const std::vector<v8::Local<v8::Value>>& result) {
92 if (injection_) {
93 base::TimeDelta elapsed = base::TimeTicks::Now() - start_time_;
94 injection_->OnJsInjectionCompleted(result, elapsed);
95 }
96 }
97
98 void willExecute() override { start_time_ = base::TimeTicks::Now(); }
99
100 private:
101 base::WeakPtr<ScriptInjection> injection_;
102 base::TimeTicks start_time_;
103 };
104
80 } // namespace 105 } // namespace
81 106
82 // Watches for the deletion of a RenderFrame, after which is_valid will return 107 // Watches for the deletion of a RenderFrame, after which is_valid will return
83 // false. 108 // false.
84 class ScriptInjection::FrameWatcher : public content::RenderFrameObserver { 109 class ScriptInjection::FrameWatcher : public content::RenderFrameObserver {
85 public: 110 public:
86 FrameWatcher(content::RenderFrame* render_frame, 111 FrameWatcher(content::RenderFrame* render_frame,
87 ScriptInjection* injection) 112 ScriptInjection* injection)
88 : content::RenderFrameObserver(render_frame), 113 : content::RenderFrameObserver(render_frame),
89 injection_(injection) {} 114 injection_(injection) {}
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 run_location_, executing_scripts, num_injected_js_scripts); 276 run_location_, executing_scripts, num_injected_js_scripts);
252 DCHECK(!sources.empty()); 277 DCHECK(!sources.empty());
253 bool in_main_world = injector_->ShouldExecuteInMainWorld(); 278 bool in_main_world = injector_->ShouldExecuteInMainWorld();
254 int world_id = in_main_world 279 int world_id = in_main_world
255 ? DOMActivityLogger::kMainWorldId 280 ? DOMActivityLogger::kMainWorldId
256 : GetIsolatedWorldIdForInstance(injection_host_.get(), 281 : GetIsolatedWorldIdForInstance(injection_host_.get(),
257 web_frame); 282 web_frame);
258 bool is_user_gesture = injector_->IsUserGesture(); 283 bool is_user_gesture = injector_->IsUserGesture();
259 284
260 std::unique_ptr<blink::WebScriptExecutionCallback> callback( 285 std::unique_ptr<blink::WebScriptExecutionCallback> callback(
261 new ScriptInjectionCallback( 286 new TimedScriptInjectionCallback(weak_ptr_factory_.GetWeakPtr()));
262 base::Bind(&ScriptInjection::OnJsInjectionCompleted,
263 weak_ptr_factory_.GetWeakPtr())));
264 287
265 base::ElapsedTimer exec_timer; 288 base::ElapsedTimer exec_timer;
266 if (injection_host_->id().type() == HostID::EXTENSIONS && log_activity_) 289 if (injection_host_->id().type() == HostID::EXTENSIONS && log_activity_)
267 DOMActivityLogger::AttachToWorld(world_id, injection_host_->id().id()); 290 DOMActivityLogger::AttachToWorld(world_id, injection_host_->id().id());
268 if (in_main_world) { 291 if (in_main_world) {
269 // We only inject in the main world for javascript: urls. 292 // We only inject in the main world for javascript: urls.
270 DCHECK_EQ(1u, sources.size()); 293 DCHECK_EQ(1u, sources.size());
271 294
272 web_frame->requestExecuteScriptAndReturnValue(sources.front(), 295 web_frame->requestExecuteScriptAndReturnValue(sources.front(),
273 is_user_gesture, 296 is_user_gesture,
274 callback.release()); 297 callback.release());
275 } else { 298 } else {
299 blink::WebLocalFrame::ScriptExecutionType option;
300 if (injector_->script_type() == UserScript::CONTENT_SCRIPT &&
301 FeatureSwitch::yield_between_content_script_runs()->IsEnabled()) {
302 switch (run_location_) {
303 case UserScript::DOCUMENT_END:
304 case UserScript::DOCUMENT_IDLE:
305 option = blink::WebLocalFrame::AsyncBlockingOnload;
306 break;
307 default:
308 option = blink::WebLocalFrame::Synchronous;
309 break;
310 }
311 } else {
312 option = blink::WebLocalFrame::Synchronous;
313 }
276 web_frame->requestExecuteScriptInIsolatedWorld( 314 web_frame->requestExecuteScriptInIsolatedWorld(
277 world_id, 315 world_id, &sources.front(), sources.size(), is_user_gesture, option,
278 &sources.front(),
279 sources.size(),
280 is_user_gesture,
281 callback.release()); 316 callback.release());
282 } 317 }
283 318
284 if (injection_host_->id().type() == HostID::EXTENSIONS) 319 if (injection_host_->id().type() == HostID::EXTENSIONS)
285 UMA_HISTOGRAM_TIMES("Extensions.InjectScriptTime", exec_timer.Elapsed()); 320 UMA_HISTOGRAM_TIMES("Extensions.InjectScriptTime", exec_timer.Elapsed());
286 } 321 }
287 322
288 void ScriptInjection::OnJsInjectionCompleted( 323 void ScriptInjection::OnJsInjectionCompleted(
289 const std::vector<v8::Local<v8::Value>>& results) { 324 const std::vector<v8::Local<v8::Value>>& results,
325 base::TimeDelta elapsed) {
290 DCHECK(!did_inject_js_); 326 DCHECK(!did_inject_js_);
291 327
328 if (injection_host_->id().type() == HostID::EXTENSIONS)
329 UMA_HISTOGRAM_TIMES("Extensions.InjectedScriptExecutionTime", elapsed);
Devlin 2017/03/02 02:33:17 Did you forget to add this metric to histograms.xm
Kunihiko Sakamoto 2017/03/06 09:11:05 Oops, added.
330
292 bool expects_results = injector_->ExpectsResults(); 331 bool expects_results = injector_->ExpectsResults();
293 if (expects_results) { 332 if (expects_results) {
294 if (!results.empty() && !results[0].IsEmpty()) { 333 if (!results.empty() && !results[0].IsEmpty()) {
295 // Right now, we only support returning single results (per frame). 334 // Right now, we only support returning single results (per frame).
296 std::unique_ptr<content::V8ValueConverter> v8_converter( 335 std::unique_ptr<content::V8ValueConverter> v8_converter(
297 content::V8ValueConverter::create()); 336 content::V8ValueConverter::create());
298 // It's safe to always use the main world context when converting 337 // It's safe to always use the main world context when converting
299 // here. V8ValueConverterImpl shouldn't actually care about the 338 // here. V8ValueConverterImpl shouldn't actually care about the
300 // context scope, and it switches to v8::Object's creation context 339 // context scope, and it switches to v8::Object's creation context
301 // when encountered. 340 // when encountered.
302 v8::Local<v8::Context> context = 341 v8::Local<v8::Context> context =
303 render_frame_->GetWebFrame()->mainWorldScriptContext(); 342 render_frame_->GetWebFrame()->mainWorldScriptContext();
304 execution_result_ = v8_converter->FromV8Value(results[0], context); 343 execution_result_ = v8_converter->FromV8Value(results[0], context);
305 } 344 }
306 if (!execution_result_.get()) 345 if (!execution_result_.get())
307 execution_result_ = base::Value::CreateNullValue(); 346 execution_result_ = base::Value::CreateNullValue();
308 } 347 }
309 did_inject_js_ = true; 348 did_inject_js_ = true;
310 349
311 // If |async_completion_callback_| is set, it means the script finished 350 // If |async_completion_callback_| is set, it means the script finished
312 // asynchronously, and we should run it. 351 // asynchronously, and we should run it.
313 if (!async_completion_callback_.is_null()) { 352 if (!async_completion_callback_.is_null()) {
353 complete_ = true;
314 injector_->OnInjectionComplete(std::move(execution_result_), run_location_, 354 injector_->OnInjectionComplete(std::move(execution_result_), run_location_,
315 render_frame_); 355 render_frame_);
316 // Warning: this object can be destroyed after this line! 356 // Warning: this object can be destroyed after this line!
317 async_completion_callback_.Run(this); 357 async_completion_callback_.Run(this);
318 } 358 }
319 } 359 }
320 360
321 void ScriptInjection::InjectCss(std::set<std::string>* injected_stylesheets, 361 void ScriptInjection::InjectCss(std::set<std::string>* injected_stylesheets,
322 size_t* num_injected_stylesheets) { 362 size_t* num_injected_stylesheets) {
323 std::vector<blink::WebString> css_sources = injector_->GetCssSources( 363 std::vector<blink::WebString> css_sources = injector_->GetCssSources(
324 run_location_, injected_stylesheets, num_injected_stylesheets); 364 run_location_, injected_stylesheets, num_injected_stylesheets);
325 blink::WebLocalFrame* web_frame = render_frame_->GetWebFrame(); 365 blink::WebLocalFrame* web_frame = render_frame_->GetWebFrame();
326 for (const blink::WebString& css : css_sources) 366 for (const blink::WebString& css : css_sources)
327 web_frame->document().insertStyleSheet(css); 367 web_frame->document().insertStyleSheet(css);
328 } 368 }
329 369
330 } // namespace extensions 370 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698