Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / extensions / renderer / programmatic_script_injector.cc
blob3c9b938f27968c8aad806ceab25b73e300c99c0b
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
3 // found in the LICENSE file.
5 #include "extensions/renderer/programmatic_script_injector.h"
7 #include <vector>
9 #include "base/values.h"
10 #include "content/public/common/url_constants.h"
11 #include "content/public/renderer/render_frame.h"
12 #include "content/public/renderer/render_frame_observer.h"
13 #include "extensions/common/error_utils.h"
14 #include "extensions/common/extension_messages.h"
15 #include "extensions/common/manifest_constants.h"
16 #include "extensions/common/permissions/permissions_data.h"
17 #include "extensions/renderer/injection_host.h"
18 #include "extensions/renderer/script_context.h"
19 #include "third_party/WebKit/public/platform/WebString.h"
20 #include "third_party/WebKit/public/web/WebDocument.h"
21 #include "third_party/WebKit/public/web/WebLocalFrame.h"
22 #include "third_party/WebKit/public/web/WebScriptSource.h"
24 namespace extensions {
26 // Watches for the deletion of a RenderFrame, after which is_valid will return
27 // false.
28 class ProgrammaticScriptInjector::FrameWatcher
29 : public content::RenderFrameObserver {
30 public:
31 explicit FrameWatcher(content::RenderFrame* render_frame)
32 : content::RenderFrameObserver(render_frame), is_valid_(true) {}
33 ~FrameWatcher() override {}
35 bool is_frame_valid() const { return is_valid_; }
37 private:
38 void FrameDetached() override { is_valid_ = false; }
39 void OnDestruct() override { is_valid_ = false; }
41 bool is_valid_;
43 DISALLOW_COPY_AND_ASSIGN(FrameWatcher);
46 ProgrammaticScriptInjector::ProgrammaticScriptInjector(
47 const ExtensionMsg_ExecuteCode_Params& params,
48 content::RenderFrame* render_frame)
49 : params_(new ExtensionMsg_ExecuteCode_Params(params)),
50 url_(
51 ScriptContext::GetDataSourceURLForFrame(render_frame->GetWebFrame())),
52 frame_watcher_(new FrameWatcher(render_frame)),
53 finished_(false) {
54 effective_url_ = ScriptContext::GetEffectiveDocumentURL(
55 render_frame->GetWebFrame(), url_, params.match_about_blank);
58 ProgrammaticScriptInjector::~ProgrammaticScriptInjector() {
61 UserScript::InjectionType ProgrammaticScriptInjector::script_type()
62 const {
63 return UserScript::PROGRAMMATIC_SCRIPT;
66 bool ProgrammaticScriptInjector::ShouldExecuteInMainWorld() const {
67 return params_->in_main_world;
70 bool ProgrammaticScriptInjector::IsUserGesture() const {
71 return params_->user_gesture;
74 bool ProgrammaticScriptInjector::ExpectsResults() const {
75 return params_->wants_result;
78 bool ProgrammaticScriptInjector::ShouldInjectJs(
79 UserScript::RunLocation run_location) const {
80 return GetRunLocation() == run_location && params_->is_javascript;
83 bool ProgrammaticScriptInjector::ShouldInjectCss(
84 UserScript::RunLocation run_location) const {
85 return GetRunLocation() == run_location && !params_->is_javascript;
88 PermissionsData::AccessType ProgrammaticScriptInjector::CanExecuteOnFrame(
89 const InjectionHost* injection_host,
90 blink::WebLocalFrame* frame,
91 int tab_id) const {
92 GURL effective_document_url = ScriptContext::GetEffectiveDocumentURL(
93 frame, frame->document().url(), params_->match_about_blank);
94 if (params_->is_web_view) {
95 if (frame->parent()) {
96 // This is a subframe inside <webview>, so allow it.
97 return PermissionsData::ACCESS_ALLOWED;
100 return effective_document_url == params_->webview_src
101 ? PermissionsData::ACCESS_ALLOWED
102 : PermissionsData::ACCESS_DENIED;
104 DCHECK_EQ(injection_host->id().type(), HostID::EXTENSIONS);
106 return injection_host->CanExecuteOnFrame(
107 effective_document_url,
108 content::RenderFrame::FromWebFrame(frame),
109 tab_id,
110 true /* is_declarative */);
113 std::vector<blink::WebScriptSource> ProgrammaticScriptInjector::GetJsSources(
114 UserScript::RunLocation run_location) const {
115 DCHECK_EQ(GetRunLocation(), run_location);
116 DCHECK(params_->is_javascript);
118 return std::vector<blink::WebScriptSource>(
120 blink::WebScriptSource(
121 blink::WebString::fromUTF8(params_->code), params_->file_url));
124 std::vector<std::string> ProgrammaticScriptInjector::GetCssSources(
125 UserScript::RunLocation run_location) const {
126 DCHECK_EQ(GetRunLocation(), run_location);
127 DCHECK(!params_->is_javascript);
129 return std::vector<std::string>(1, params_->code);
132 void ProgrammaticScriptInjector::GetRunInfo(
133 ScriptsRunInfo* scripts_run_info,
134 UserScript::RunLocation run_location) const {
137 void ProgrammaticScriptInjector::OnInjectionComplete(
138 scoped_ptr<base::Value> execution_result,
139 UserScript::RunLocation run_location) {
140 DCHECK(results_.empty());
141 if (execution_result)
142 results_.Append(execution_result.Pass());
143 Finish(std::string());
146 void ProgrammaticScriptInjector::OnWillNotInject(InjectFailureReason reason) {
147 std::string error;
148 switch (reason) {
149 case NOT_ALLOWED:
150 if (url_.SchemeIs(url::kAboutScheme)) {
151 error = ErrorUtils::FormatErrorMessage(
152 manifest_errors::kCannotAccessAboutUrl, url_.spec(),
153 effective_url_.GetOrigin().spec());
154 } else {
155 error = ErrorUtils::FormatErrorMessage(
156 manifest_errors::kCannotAccessPage, url_.spec());
158 break;
159 case EXTENSION_REMOVED: // no special error here.
160 case WONT_INJECT:
161 break;
163 Finish(error);
166 UserScript::RunLocation ProgrammaticScriptInjector::GetRunLocation() const {
167 return static_cast<UserScript::RunLocation>(params_->run_at);
170 void ProgrammaticScriptInjector::Finish(const std::string& error) {
171 DCHECK(!finished_);
172 finished_ = true;
174 // It's possible that the render frame was destroyed in the course of
175 // injecting scripts. Don't respond if it was (the browser side watches for
176 // frame deletions so nothing is left hanging).
177 if (frame_watcher_->is_frame_valid()) {
178 frame_watcher_->render_frame()->Send(
179 new ExtensionHostMsg_ExecuteCodeFinished(
180 frame_watcher_->render_frame()->GetRoutingID(), params_->request_id,
181 error, url_, results_));
185 } // namespace extensions