blob: 9178bfb0c0cf408122c7142d51b9331625843b45 [file] [log] [blame]
[email protected]3c220782014-05-20 01:59:461// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "extensions/renderer/script_injection.h"
6
[email protected]ac2f89372014-06-23 21:44:257#include <map>
dchenge59eca1602015-12-18 17:48:008#include <utility>
[email protected]3c220782014-05-20 01:59:469
Sebastien Marchand6d0558fd2019-01-25 16:49:3710#include "base/bind.h"
Devlin Cronin4cd6bc12017-12-05 23:46:4911#include "base/feature_list.h"
[email protected]3c220782014-05-20 01:59:4612#include "base/lazy_instance.h"
avi2d124c02015-12-23 06:36:4213#include "base/macros.h"
asvitkinef5d4ee562016-11-07 18:57:0814#include "base/metrics/histogram_macros.h"
[email protected]c11e6592014-06-27 17:07:3415#include "base/timer/elapsed_timer.h"
16#include "base/values.h"
rdevlin.cronin3e11c9862015-06-04 19:54:2517#include "content/public/renderer/render_frame.h"
John Abd-El-Malek312a30bb2017-10-23 19:51:5218#include "content/public/renderer/v8_value_converter.h"
Devlin Cronin4cd6bc12017-12-05 23:46:4919#include "extensions/common/extension_features.h"
[email protected]f8abc6e42014-06-24 21:14:4320#include "extensions/common/extension_messages.h"
hanxia5c856cf2015-02-13 20:51:5821#include "extensions/common/host_id.h"
[email protected]c11e6592014-06-27 17:07:3422#include "extensions/renderer/dom_activity_logger.h"
rdevlin.croninc318b93d2015-09-14 20:22:2923#include "extensions/renderer/extension_frame_helper.h"
[email protected]ac2f89372014-06-23 21:44:2524#include "extensions/renderer/extensions_renderer_client.h"
kozyatinskiyc8bc9a582015-03-06 09:33:4125#include "extensions/renderer/script_injection_callback.h"
kozyatinskiyc8bc9a582015-03-06 09:33:4126#include "extensions/renderer/scripts_run_info.h"
Karan Bhatiadc28bfbd2019-01-15 05:36:1127#include "third_party/blink/public/platform/web_isolated_world_info.h"
Blink Reformata30d4232018-04-07 15:31:0628#include "third_party/blink/public/platform/web_security_origin.h"
29#include "third_party/blink/public/platform/web_string.h"
30#include "third_party/blink/public/web/web_document.h"
31#include "third_party/blink/public/web/web_local_frame.h"
32#include "third_party/blink/public/web/web_script_source.h"
[email protected]c11e6592014-06-27 17:07:3433#include "url/gurl.h"
[email protected]3c220782014-05-20 01:59:4634
35namespace extensions {
36
37namespace {
38
hanxia5c856cf2015-02-13 20:51:5839using IsolatedWorldMap = std::map<std::string, int>;
scottmg5e65e3a2017-03-08 08:48:4640base::LazyInstance<IsolatedWorldMap>::DestructorAtExit g_isolated_worlds =
[email protected]3c220782014-05-20 01:59:4641 LAZY_INSTANCE_INITIALIZER;
42
avi2d124c02015-12-23 06:36:4243const int64_t kInvalidRequestId = -1;
[email protected]f8abc6e42014-06-24 21:14:4344
45// The id of the next pending injection.
avi2d124c02015-12-23 06:36:4246int64_t g_next_pending_id = 0;
[email protected]f8abc6e42014-06-24 21:14:4347
hanxia5c856cf2015-02-13 20:51:5848// Gets the isolated world ID to use for the given |injection_host|
49// in the given |frame|. If no isolated world has been created for that
50// |injection_host| one will be created and initialized.
51int GetIsolatedWorldIdForInstance(const InjectionHost* injection_host,
52 blink::WebLocalFrame* frame) {
[email protected]ac2f89372014-06-23 21:44:2553 static int g_next_isolated_world_id =
54 ExtensionsRendererClient::Get()->GetLowestIsolatedWorldId();
[email protected]0d8d6972014-06-03 22:41:0255
[email protected]ac2f89372014-06-23 21:44:2556 IsolatedWorldMap& isolated_worlds = g_isolated_worlds.Get();
[email protected]0d8d6972014-06-03 22:41:0257
[email protected]ac2f89372014-06-23 21:44:2558 int id = 0;
hanxia5c856cf2015-02-13 20:51:5859 const std::string& key = injection_host->id().id();
jdoerriea1e1598b2018-10-10 09:10:3760 auto iter = isolated_worlds.find(key);
[email protected]ac2f89372014-06-23 21:44:2561 if (iter != isolated_worlds.end()) {
62 id = iter->second;
63 } else {
64 id = g_next_isolated_world_id++;
65 // This map will tend to pile up over time, but realistically, you're never
hanxia5c856cf2015-02-13 20:51:5866 // going to have enough injection hosts for it to matter.
67 isolated_worlds[key] = id;
[email protected]0d8d6972014-06-03 22:41:0268 }
69
[email protected]ac2f89372014-06-23 21:44:2570 // We need to set the isolated world origin and CSP even if it's not a new
71 // world since these are stored per frame, and we might not have used this
72 // isolated world in this frame before.
Karan Bhatiadc28bfbd2019-01-15 05:36:1173 blink::WebIsolatedWorldInfo info;
74 info.security_origin =
75 blink::WebSecurityOrigin::Create(injection_host->url());
76 info.human_readable_name = blink::WebString::FromUTF8(injection_host->name());
77
78 const std::string* csp = injection_host->GetContentSecurityPolicy();
79 if (csp)
80 info.content_security_policy = blink::WebString::FromUTF8(*csp);
81
82 frame->SetIsolatedWorldInfo(id, info);
[email protected]ac2f89372014-06-23 21:44:2583
84 return id;
[email protected]0d8d6972014-06-03 22:41:0285}
86
ksakamotocbf167aa2017-03-17 06:45:4887// This class manages its own lifetime.
88class TimedScriptInjectionCallback : public ScriptInjectionCallback {
89 public:
Kunihiko Sakamoto46b7bc52019-06-20 02:42:2590 TimedScriptInjectionCallback(base::WeakPtr<ScriptInjection> injection)
ksakamotocbf167aa2017-03-17 06:45:4891 : ScriptInjectionCallback(
92 base::Bind(&TimedScriptInjectionCallback::OnCompleted,
93 base::Unretained(this))),
Kunihiko Sakamoto46b7bc52019-06-20 02:42:2594 injection_(injection) {}
ksakamotocbf167aa2017-03-17 06:45:4895 ~TimedScriptInjectionCallback() override {}
96
97 void OnCompleted(const std::vector<v8::Local<v8::Value>>& result) {
98 if (injection_) {
Kunihiko Sakamoto7d386bf2017-07-31 03:19:5399 base::TimeTicks timestamp(base::TimeTicks::Now());
ksakamoto4178f502017-04-07 04:40:21100 base::Optional<base::TimeDelta> elapsed;
101 // If the script will never execute (such as if the context is destroyed),
102 // willExecute() will not be called, but OnCompleted() will. Only log a
103 // time for execution if the script, in fact, executed.
Kunihiko Sakamoto46b7bc52019-06-20 02:42:25104 if (!start_time_.is_null())
Kunihiko Sakamoto7d386bf2017-07-31 03:19:53105 elapsed = timestamp - start_time_;
ksakamotocbf167aa2017-03-17 06:45:48106 injection_->OnJsInjectionCompleted(result, elapsed);
107 }
108 }
109
Kunihiko Sakamoto7d386bf2017-07-31 03:19:53110 void WillExecute() override {
111 start_time_ = base::TimeTicks::Now();
Kunihiko Sakamoto7d386bf2017-07-31 03:19:53112 }
ksakamotocbf167aa2017-03-17 06:45:48113
114 private:
115 base::WeakPtr<ScriptInjection> injection_;
116 base::TimeTicks start_time_;
117};
118
[email protected]c11e6592014-06-27 17:07:34119} // namespace
120
rdevlin.cronind533be962015-10-02 17:01:18121// Watches for the deletion of a RenderFrame, after which is_valid will return
122// false.
123class ScriptInjection::FrameWatcher : public content::RenderFrameObserver {
124 public:
125 FrameWatcher(content::RenderFrame* render_frame,
126 ScriptInjection* injection)
127 : content::RenderFrameObserver(render_frame),
128 injection_(injection) {}
129 ~FrameWatcher() override {}
130
131 private:
132 void FrameDetached() override { injection_->invalidate_render_frame(); }
133 void OnDestruct() override { injection_->invalidate_render_frame(); }
134
135 ScriptInjection* injection_;
136
137 DISALLOW_COPY_AND_ASSIGN(FrameWatcher);
138};
139
[email protected]ac2f89372014-06-23 21:44:25140// static
hanxia5c856cf2015-02-13 20:51:58141std::string ScriptInjection::GetHostIdForIsolatedWorld(int isolated_world_id) {
142 const IsolatedWorldMap& isolated_worlds = g_isolated_worlds.Get();
[email protected]0d8d6972014-06-03 22:41:02143
hanxia5c856cf2015-02-13 20:51:58144 for (const auto& iter : isolated_worlds) {
145 if (iter.second == isolated_world_id)
146 return iter.first;
[email protected]3c220782014-05-20 01:59:46147 }
[email protected]ac2f89372014-06-23 21:44:25148 return std::string();
[email protected]3c220782014-05-20 01:59:46149}
150
[email protected]ac2f89372014-06-23 21:44:25151// static
hanxia5c856cf2015-02-13 20:51:58152void ScriptInjection::RemoveIsolatedWorld(const std::string& host_id) {
153 g_isolated_worlds.Get().erase(host_id);
[email protected]3c220782014-05-20 01:59:46154}
155
dchengf6f80662016-04-20 20:26:04156ScriptInjection::ScriptInjection(
157 std::unique_ptr<ScriptInjector> injector,
158 content::RenderFrame* render_frame,
159 std::unique_ptr<const InjectionHost> injection_host,
rdevlin.cronin6fba7ec2016-06-24 16:15:05160 UserScript::RunLocation run_location,
161 bool log_activity)
dchenge59eca1602015-12-18 17:48:00162 : injector_(std::move(injector)),
rdevlin.cronin3e11c9862015-06-04 19:54:25163 render_frame_(render_frame),
dchenge59eca1602015-12-18 17:48:00164 injection_host_(std::move(injection_host)),
[email protected]f8abc6e42014-06-24 21:14:43165 run_location_(run_location),
[email protected]d2056002014-07-03 06:18:06166 request_id_(kInvalidRequestId),
kozyatinskiyc8bc9a582015-03-06 09:33:41167 complete_(false),
rdevlin.cronin3e11c9862015-06-04 19:54:25168 did_inject_js_(false),
rdevlin.cronin6fba7ec2016-06-24 16:15:05169 log_activity_(log_activity),
Jeremy Roman9fc2de62019-07-12 14:15:03170 frame_watcher_(new FrameWatcher(render_frame, this)) {
hanxi9b841662015-03-04 14:36:41171 CHECK(injection_host_.get());
[email protected]f8abc6e42014-06-24 21:14:43172}
173
174ScriptInjection::~ScriptInjection() {
175 if (!complete_)
rdevlin.cronind533be962015-10-02 17:01:18176 NotifyWillNotInject(ScriptInjector::WONT_INJECT);
[email protected]f8abc6e42014-06-24 21:14:43177}
178
kozyatinskiyc8bc9a582015-03-06 09:33:41179ScriptInjection::InjectionResult ScriptInjection::TryToInject(
180 UserScript::RunLocation current_location,
181 ScriptsRunInfo* scripts_run_info,
rdevlin.cronin4bb32d72015-06-02 21:55:01182 const CompletionCallback& async_completion_callback) {
[email protected]f8abc6e42014-06-24 21:14:43183 if (current_location < run_location_)
kozyatinskiyc8bc9a582015-03-06 09:33:41184 return INJECTION_WAITING; // Wait for the right location.
[email protected]f8abc6e42014-06-24 21:14:43185
kozyatinskiyc8bc9a582015-03-06 09:33:41186 if (request_id_ != kInvalidRequestId) {
187 // We're waiting for permission right now, try again later.
188 return INJECTION_WAITING;
189 }
[email protected]f8abc6e42014-06-24 21:14:43190
hanxi9b841662015-03-04 14:36:41191 if (!injection_host_) {
[email protected]c11e6592014-06-27 17:07:34192 NotifyWillNotInject(ScriptInjector::EXTENSION_REMOVED);
kozyatinskiyc8bc9a582015-03-06 09:33:41193 return INJECTION_FINISHED; // We're done.
[email protected]f8abc6e42014-06-24 21:14:43194 }
195
rdevlin.cronin3e11c9862015-06-04 19:54:25196 blink::WebLocalFrame* web_frame = render_frame_->GetWebFrame();
hanxi9b841662015-03-04 14:36:41197 switch (injector_->CanExecuteOnFrame(
rdevlin.croninc318b93d2015-09-14 20:22:29198 injection_host_.get(), web_frame,
199 ExtensionFrameHelper::Get(render_frame_)->tab_id())) {
Devlin Cronin3e532b82018-05-03 21:27:19200 case PermissionsData::PageAccess::kDenied:
[email protected]c11e6592014-06-27 17:07:34201 NotifyWillNotInject(ScriptInjector::NOT_ALLOWED);
kozyatinskiyc8bc9a582015-03-06 09:33:41202 return INJECTION_FINISHED; // We're done.
Devlin Cronin3e532b82018-05-03 21:27:19203 case PermissionsData::PageAccess::kWithheld:
rdevlin.croninb03d1572015-10-02 02:23:52204 RequestPermissionFromBrowser();
kozyatinskiyc8bc9a582015-03-06 09:33:41205 return INJECTION_WAITING; // Wait around for permission.
Devlin Cronin3e532b82018-05-03 21:27:19206 case PermissionsData::PageAccess::kAllowed:
Kunihiko Sakamoto46b7bc52019-06-20 02:42:25207 InjectionResult result = Inject(scripts_run_info);
kozyatinskiyc8bc9a582015-03-06 09:33:41208 // If the injection is blocked, we need to set the manager so we can
209 // notify it upon completion.
210 if (result == INJECTION_BLOCKED)
rdevlin.cronin4bb32d72015-06-02 21:55:01211 async_completion_callback_ = async_completion_callback;
kozyatinskiyc8bc9a582015-03-06 09:33:41212 return result;
[email protected]f8abc6e42014-06-24 21:14:43213 }
214
rdevlin.cronin958e9f82015-02-17 21:57:14215 NOTREACHED();
kozyatinskiyc8bc9a582015-03-06 09:33:41216 return INJECTION_FINISHED;
[email protected]f8abc6e42014-06-24 21:14:43217}
218
kozyatinskiyc8bc9a582015-03-06 09:33:41219ScriptInjection::InjectionResult ScriptInjection::OnPermissionGranted(
220 ScriptsRunInfo* scripts_run_info) {
hanxi9b841662015-03-04 14:36:41221 if (!injection_host_) {
[email protected]c11e6592014-06-27 17:07:34222 NotifyWillNotInject(ScriptInjector::EXTENSION_REMOVED);
kozyatinskiyc8bc9a582015-03-06 09:33:41223 return INJECTION_FINISHED;
[email protected]f8abc6e42014-06-24 21:14:43224 }
225
Kunihiko Sakamoto46b7bc52019-06-20 02:42:25226 return Inject(scripts_run_info);
[email protected]f8abc6e42014-06-24 21:14:43227}
228
hanxi9b841662015-03-04 14:36:41229void ScriptInjection::OnHostRemoved() {
230 injection_host_.reset(nullptr);
231}
232
rdevlin.croninb03d1572015-10-02 02:23:52233void ScriptInjection::RequestPermissionFromBrowser() {
[email protected]23a85362014-07-07 23:26:19234 // If we are just notifying the browser of the injection, then send an
[email protected]f8abc6e42014-06-24 21:14:43235 // invalid request (which is treated like a notification).
rdevlin.croninb03d1572015-10-02 02:23:52236 request_id_ = g_next_pending_id++;
rdevlin.cronin45dca7f2015-06-08 19:47:03237 render_frame_->Send(new ExtensionHostMsg_RequestScriptInjectionPermission(
rdevlin.cronin8d034e52016-02-02 22:46:32238 render_frame_->GetRoutingID(), host_id().id(), injector_->script_type(),
239 run_location_, request_id_));
[email protected]f8abc6e42014-06-24 21:14:43240}
241
[email protected]c11e6592014-06-27 17:07:34242void ScriptInjection::NotifyWillNotInject(
243 ScriptInjector::InjectFailureReason reason) {
[email protected]f8abc6e42014-06-24 21:14:43244 complete_ = true;
rdevlin.cronind533be962015-10-02 17:01:18245 injector_->OnWillNotInject(reason, render_frame_);
[email protected]f8abc6e42014-06-24 21:14:43246}
247
kozyatinskiyc8bc9a582015-03-06 09:33:41248ScriptInjection::InjectionResult ScriptInjection::Inject(
Kunihiko Sakamoto46b7bc52019-06-20 02:42:25249 ScriptsRunInfo* scripts_run_info) {
hanxi9b841662015-03-04 14:36:41250 DCHECK(injection_host_);
[email protected]c11e6592014-06-27 17:07:34251 DCHECK(scripts_run_info);
252 DCHECK(!complete_);
catmullingsd4faad4f2016-09-08 19:55:30253 bool should_inject_js = injector_->ShouldInjectJs(
254 run_location_, scripts_run_info->executing_scripts[host_id().id()]);
255 bool should_inject_css = injector_->ShouldInjectCss(
256 run_location_, scripts_run_info->injected_stylesheets[host_id().id()]);
[email protected]c11e6592014-06-27 17:07:34257
catmullingsd4faad4f2016-09-08 19:55:30258 // This can happen if the extension specified a script to
259 // be run in multiple rules, and the script has already run.
260 // See crbug.com/631247.
261 if (!should_inject_js && !should_inject_css) {
262 return INJECTION_FINISHED;
263 }
[email protected]c11e6592014-06-27 17:07:34264
rdevlin.cronin4bb32d72015-06-02 21:55:01265 if (should_inject_js)
catmullingsd4faad4f2016-09-08 19:55:30266 InjectJs(&(scripts_run_info->executing_scripts[host_id().id()]),
Kunihiko Sakamoto46b7bc52019-06-20 02:42:25267 &(scripts_run_info->num_js));
rdevlin.cronin4bb32d72015-06-02 21:55:01268 if (should_inject_css)
catmullingsd4faad4f2016-09-08 19:55:30269 InjectCss(&(scripts_run_info->injected_stylesheets[host_id().id()]),
270 &(scripts_run_info->num_css));
[email protected]c11e6592014-06-27 17:07:34271
rdevlin.cronin4bb32d72015-06-02 21:55:01272 complete_ = did_inject_js_ || !should_inject_js;
[email protected]c11e6592014-06-27 17:07:34273
rdevlin.cronind533be962015-10-02 17:01:18274 if (complete_) {
dchenge59eca1602015-12-18 17:48:00275 injector_->OnInjectionComplete(std::move(execution_result_), run_location_,
rdevlin.cronind533be962015-10-02 17:01:18276 render_frame_);
277 } else {
rdevlin.cronin4bb32d72015-06-02 21:55:01278 ++scripts_run_info->num_blocking_js;
rdevlin.cronind533be962015-10-02 17:01:18279 }
rdevlin.cronin4bb32d72015-06-02 21:55:01280
kozyatinskiyc8bc9a582015-03-06 09:33:41281 return complete_ ? INJECTION_FINISHED : INJECTION_BLOCKED;
[email protected]c11e6592014-06-27 17:07:34282}
283
Kunihiko Sakamoto46b7bc52019-06-20 02:42:25284void ScriptInjection::InjectJs(std::set<std::string>* executing_scripts,
285 size_t* num_injected_js_scripts) {
rdevlin.cronin4bb32d72015-06-02 21:55:01286 DCHECK(!did_inject_js_);
rdevlin.cronin3e11c9862015-06-04 19:54:25287 blink::WebLocalFrame* web_frame = render_frame_->GetWebFrame();
catmullingsd4faad4f2016-09-08 19:55:30288 std::vector<blink::WebScriptSource> sources = injector_->GetJsSources(
289 run_location_, executing_scripts, num_injected_js_scripts);
290 DCHECK(!sources.empty());
Devlin Cronine684a212019-10-05 15:26:36291 int world_id =
292 GetIsolatedWorldIdForInstance(injection_host_.get(), web_frame);
kozyatinskiyc8bc9a582015-03-06 09:33:41293 bool is_user_gesture = injector_->IsUserGesture();
294
dchengf6f80662016-04-20 20:26:04295 std::unique_ptr<blink::WebScriptExecutionCallback> callback(
Kunihiko Sakamoto46b7bc52019-06-20 02:42:25296 new TimedScriptInjectionCallback(weak_ptr_factory_.GetWeakPtr()));
[email protected]c11e6592014-06-27 17:07:34297
298 base::ElapsedTimer exec_timer;
rdevlin.cronin6fba7ec2016-06-24 16:15:05299 if (injection_host_->id().type() == HostID::EXTENSIONS && log_activity_)
hanxi9b841662015-03-04 14:36:41300 DOMActivityLogger::AttachToWorld(world_id, injection_host_->id().id());
[email protected]c11e6592014-06-27 17:07:34301
Devlin Cronin0e60ff72019-11-26 01:13:07302 // For content scripts executing during page load, we run them asynchronously
303 // in order to reduce UI jank experienced by the user. (We don't do this for
304 // DOCUMENT_START scripts, because there's no UI to jank until after those
305 // run, so we run them as soon as we can.)
306 // Note: We could potentially also run deferred and browser-driven scripts
307 // asynchronously; however, these are rare enough that there probably isn't
308 // UI jank. If this changes, we can update this.
309 bool should_execute_asynchronously =
310 injector_->script_type() == UserScript::CONTENT_SCRIPT &&
311 (run_location_ == UserScript::DOCUMENT_END ||
312 run_location_ == UserScript::DOCUMENT_IDLE);
313 blink::WebLocalFrame::ScriptExecutionType execution_option =
314 should_execute_asynchronously
315 ? blink::WebLocalFrame::kAsynchronousBlockingOnload
316 : blink::WebLocalFrame::kSynchronous;
Devlin Cronine684a212019-10-05 15:26:36317 web_frame->RequestExecuteScriptInIsolatedWorld(
Devlin Cronin0e60ff72019-11-26 01:13:07318 world_id, &sources.front(), sources.size(), is_user_gesture,
319 execution_option, callback.release());
kozyatinskiyc8bc9a582015-03-06 09:33:41320}
[email protected]c11e6592014-06-27 17:07:34321
kozyatinskiyc8bc9a582015-03-06 09:33:41322void ScriptInjection::OnJsInjectionCompleted(
ksakamotocbf167aa2017-03-17 06:45:48323 const std::vector<v8::Local<v8::Value>>& results,
ksakamoto4178f502017-04-07 04:40:21324 base::Optional<base::TimeDelta> elapsed) {
rdevlin.cronin4bb32d72015-06-02 21:55:01325 DCHECK(!did_inject_js_);
kozyatinskiyc8bc9a582015-03-06 09:33:41326
ksakamoto4178f502017-04-07 04:40:21327 if (injection_host_->id().type() == HostID::EXTENSIONS && elapsed) {
328 UMA_HISTOGRAM_TIMES("Extensions.InjectedScriptExecutionTime", *elapsed);
ksakamoto049f8332017-03-24 06:39:07329 switch (run_location_) {
330 case UserScript::DOCUMENT_START:
331 UMA_HISTOGRAM_TIMES(
ksakamoto4178f502017-04-07 04:40:21332 "Extensions.InjectedScriptExecutionTime.DocumentStart", *elapsed);
ksakamoto049f8332017-03-24 06:39:07333 break;
334 case UserScript::DOCUMENT_END:
335 UMA_HISTOGRAM_TIMES(
ksakamoto4178f502017-04-07 04:40:21336 "Extensions.InjectedScriptExecutionTime.DocumentEnd", *elapsed);
ksakamoto049f8332017-03-24 06:39:07337 break;
338 case UserScript::DOCUMENT_IDLE:
339 UMA_HISTOGRAM_TIMES(
ksakamoto4178f502017-04-07 04:40:21340 "Extensions.InjectedScriptExecutionTime.DocumentIdle", *elapsed);
ksakamoto049f8332017-03-24 06:39:07341 break;
342 default:
343 break;
344 }
345 }
ksakamotocbf167aa2017-03-17 06:45:48346
kozyatinskiyc8bc9a582015-03-06 09:33:41347 bool expects_results = injector_->ExpectsResults();
[email protected]c11e6592014-06-27 17:07:34348 if (expects_results) {
rdevlin.cronin0d94256f2016-12-09 15:34:23349 if (!results.empty() && !results[0].IsEmpty()) {
kozyatinskiyefaa59a2015-04-03 17:57:16350 // Right now, we only support returning single results (per frame).
kozyatinskiyefaa59a2015-04-03 17:57:16351 // It's safe to always use the main world context when converting
352 // here. V8ValueConverterImpl shouldn't actually care about the
353 // context scope, and it switches to v8::Object's creation context
354 // when encountered.
rdevlin.cronin3e11c9862015-06-04 19:54:25355 v8::Local<v8::Context> context =
Blink Reformat1c4d759e2017-04-09 16:34:54356 render_frame_->GetWebFrame()->MainWorldScriptContext();
rdevlin.cronin694c6052017-06-13 22:07:35357 execution_result_ =
358 content::V8ValueConverter::Create()->FromV8Value(results[0], context);
kozyatinskiyefaa59a2015-04-03 17:57:16359 }
rdevlin.cronin4bb32d72015-06-02 21:55:01360 if (!execution_result_.get())
Jeremy Roman16529d0e2017-08-24 18:13:47361 execution_result_ = std::make_unique<base::Value>();
kozyatinskiyc8bc9a582015-03-06 09:33:41362 }
rdevlin.cronin4bb32d72015-06-02 21:55:01363 did_inject_js_ = true;
kozyatinskiyc8bc9a582015-03-06 09:33:41364
rdevlin.cronin4bb32d72015-06-02 21:55:01365 // If |async_completion_callback_| is set, it means the script finished
366 // asynchronously, and we should run it.
367 if (!async_completion_callback_.is_null()) {
ksakamotocbf167aa2017-03-17 06:45:48368 complete_ = true;
dchenge59eca1602015-12-18 17:48:00369 injector_->OnInjectionComplete(std::move(execution_result_), run_location_,
rdevlin.cronind533be962015-10-02 17:01:18370 render_frame_);
rdevlin.cronin4bb32d72015-06-02 21:55:01371 // Warning: this object can be destroyed after this line!
372 async_completion_callback_.Run(this);
[email protected]c11e6592014-06-27 17:07:34373 }
374}
375
catmullingsd4faad4f2016-09-08 19:55:30376void ScriptInjection::InjectCss(std::set<std::string>* injected_stylesheets,
377 size_t* num_injected_stylesheets) {
378 std::vector<blink::WebString> css_sources = injector_->GetCssSources(
379 run_location_, injected_stylesheets, num_injected_stylesheets);
rdevlin.cronin3e11c9862015-06-04 19:54:25380 blink::WebLocalFrame* web_frame = render_frame_->GetWebFrame();
Manish Jethani9494d722018-01-20 00:28:47381 // Default CSS origin is "author", but can be overridden to "user" by scripts.
382 base::Optional<CSSOrigin> css_origin = injector_->GetCssOrigin();
383 blink::WebDocument::CSSOrigin blink_css_origin =
384 css_origin && *css_origin == CSS_ORIGIN_USER
385 ? blink::WebDocument::kUserOrigin
386 : blink::WebDocument::kAuthorOrigin;
Manish Jethaniff6ff852018-02-23 07:24:55387 blink::WebStyleSheetKey style_sheet_key;
388 if (const base::Optional<std::string>& injection_key =
389 injector_->GetInjectionKey())
390 style_sheet_key = blink::WebString::FromASCII(*injection_key);
lazyboy49cc0b3a2016-08-18 21:55:12391 for (const blink::WebString& css : css_sources)
Manish Jethaniff6ff852018-02-23 07:24:55392 web_frame->GetDocument().InsertStyleSheet(css, &style_sheet_key,
393 blink_css_origin);
[email protected]f8abc6e42014-06-24 21:14:43394}
395
[email protected]3c220782014-05-20 01:59:46396} // namespace extensions