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

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

Issue 284153006: Introduce ScriptInjection in extensions/renderer to inject UserScripts (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « extensions/renderer/script_injection.h ('k') | extensions/renderer/user_script_scheduler.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "extensions/renderer/script_injection.h"
6
7 #include <vector>
8
9 #include "base/lazy_instance.h"
10 #include "base/metrics/histogram.h"
11 #include "content/public/common/url_constants.h"
12 #include "extensions/common/extension.h"
13 #include "extensions/common/extension_messages.h"
14 #include "extensions/common/permissions/permissions_data.h"
15 #include "extensions/renderer/dom_activity_logger.h"
16 #include "extensions/renderer/extension_groups.h"
17 #include "extensions/renderer/script_context.h"
18 #include "extensions/renderer/user_script_slave.h"
19 #include "grit/renderer_resources.h"
20 #include "third_party/WebKit/public/web/WebDocument.h"
21 #include "third_party/WebKit/public/web/WebFrame.h"
22 #include "third_party/WebKit/public/web/WebScriptSource.h"
23 #include "ui/base/resource/resource_bundle.h"
24 #include "url/gurl.h"
25
26 namespace extensions {
27
28 namespace {
29
30 // These two strings are injected before and after the Greasemonkey API and
31 // user script to wrap it in an anonymous scope.
32 const char kUserScriptHead[] = "(function (unsafeWindow) {\n";
33 const char kUserScriptTail[] = "\n})(window);";
34
35 // Greasemonkey API source that is injected with the scripts.
36 struct GreasemonkeyApiJsString {
37 GreasemonkeyApiJsString();
38 blink::WebScriptSource source;
39 };
40
41 // The below constructor, monstrous as it is, just makes a WebScriptSource from
42 // the GreasemonkeyApiJs resource.
43 GreasemonkeyApiJsString::GreasemonkeyApiJsString()
44 : source(blink::WebScriptSource(blink::WebString::fromUTF8(
45 ResourceBundle::GetSharedInstance().GetRawDataResource(
46 IDR_GREASEMONKEY_API_JS).as_string()))) {
47 }
48
49 base::LazyInstance<GreasemonkeyApiJsString> g_greasemonkey_api =
50 LAZY_INSTANCE_INITIALIZER;
51
52 } // namespace
53
54 ScriptInjection::ScriptsRunInfo::ScriptsRunInfo() : num_css(0u), num_js(0u) {
55 }
56
57 ScriptInjection::ScriptsRunInfo::~ScriptsRunInfo() {
58 }
59
60 // static
61 GURL ScriptInjection::GetDocumentUrlForFrame(blink::WebFrame* frame) {
62 GURL data_source_url = ScriptContext::GetDataSourceURLForFrame(frame);
63 if (!data_source_url.is_empty() && frame->isViewSourceModeEnabled()) {
64 data_source_url = GURL(content::kViewSourceScheme + std::string(":") +
65 data_source_url.spec());
66 }
67
68 return data_source_url;
69 }
70
71 ScriptInjection::ScriptInjection(
72 scoped_ptr<UserScript> script,
73 UserScriptSlave* user_script_slave)
74 : script_(script.Pass()),
75 extension_id_(script_->extension_id()),
76 user_script_slave_(user_script_slave),
77 is_standalone_or_emulate_greasemonkey_(
78 script_->is_standalone() || script_->emulate_greasemonkey()) {
79 }
80
81 ScriptInjection::~ScriptInjection() {
82 }
83
84 bool ScriptInjection::WantsToRun(blink::WebFrame* frame,
85 UserScript::RunLocation run_location,
86 const GURL& document_url) const {
87 if (frame->parent() && !script_->match_all_frames())
88 return false; // Only match subframes if the script declared it wanted to.
89
90 const Extension* extension = user_script_slave_->GetExtension(extension_id_);
91 // Since extension info is sent separately from user script info, they can
92 // be out of sync. We just ignore this situation.
93 if (!extension)
94 return false;
95
96 // Content scripts are not tab-specific.
97 static const int kNoTabId = -1;
98 // We don't have a process id in this context.
99 static const int kNoProcessId = -1;
100
101 GURL effective_document_url = ScriptContext::GetEffectiveDocumentURL(
102 frame, document_url, script_->match_about_blank());
103
104 if (!PermissionsData::CanExecuteScriptOnPage(extension,
105 effective_document_url,
106 frame->top()->document().url(),
107 kNoTabId,
108 script_.get(),
109 kNoProcessId,
110 NULL /* ignore error */)) {
111 return false;
112 }
113
114 return ShouldInjectCSS(run_location) || ShouldInjectJS(run_location);
115 }
116
117 void ScriptInjection::Inject(blink::WebFrame* frame,
118 UserScript::RunLocation run_location,
119 ScriptsRunInfo* scripts_run_info) const {
120 DCHECK(frame);
121 DCHECK(scripts_run_info);
122 DCHECK(WantsToRun(frame, run_location, GetDocumentUrlForFrame(frame)));
123 DCHECK(user_script_slave_->GetExtension(extension_id_));
124
125 if (ShouldInjectCSS(run_location))
126 InjectCSS(frame, scripts_run_info);
127 if (ShouldInjectJS(run_location))
128 InjectJS(frame, scripts_run_info);
129 }
130
131 bool ScriptInjection::ShouldInjectJS(UserScript::RunLocation run_location)
132 const {
133 return !script_->js_scripts().empty() &&
134 script_->run_location() == run_location;
135 }
136
137 bool ScriptInjection::ShouldInjectCSS(UserScript::RunLocation run_location)
138 const {
139 return !script_->css_scripts().empty() &&
140 run_location == UserScript::DOCUMENT_START;
141 }
142
143 void ScriptInjection::InjectJS(blink::WebFrame* frame,
144 ScriptsRunInfo* scripts_run_info) const {
145 const UserScript::FileList& js_scripts = script_->js_scripts();
146 std::vector<blink::WebScriptSource> sources;
147 scripts_run_info->num_js += js_scripts.size();
148 for (UserScript::FileList::const_iterator iter = js_scripts.begin();
149 iter != js_scripts.end();
150 ++iter) {
151 std::string content = iter->GetContent().as_string();
152
153 // We add this dumb function wrapper for standalone user script to
154 // emulate what Greasemonkey does.
155 // TODO(aa): I think that maybe "is_standalone" scripts don't exist
156 // anymore. Investigate.
157 if (is_standalone_or_emulate_greasemonkey_) {
158 content.insert(0, kUserScriptHead);
159 content += kUserScriptTail;
160 }
161 sources.push_back(blink::WebScriptSource(
162 blink::WebString::fromUTF8(content), iter->url()));
163 }
164
165 // Emulate Greasemonkey API for scripts that were converted to extensions
166 // and "standalone" user scripts.
167 if (is_standalone_or_emulate_greasemonkey_)
168 sources.insert(sources.begin(), g_greasemonkey_api.Get().source);
169
170 int isolated_world_id =
171 user_script_slave_->GetIsolatedWorldIdForExtension(
172 user_script_slave_->GetExtension(extension_id_), frame);
173 base::ElapsedTimer exec_timer;
174 DOMActivityLogger::AttachToWorld(isolated_world_id, extension_id_);
175 frame->executeScriptInIsolatedWorld(isolated_world_id,
176 &sources.front(),
177 sources.size(),
178 EXTENSION_GROUP_CONTENT_SCRIPTS);
179 UMA_HISTOGRAM_TIMES("Extensions.InjectScriptTime", exec_timer.Elapsed());
180
181 for (std::vector<blink::WebScriptSource>::const_iterator iter =
182 sources.begin();
183 iter != sources.end();
184 ++iter) {
185 scripts_run_info->executing_scripts[extension_id_].insert(
186 GURL(iter->url).path());
187 }
188 }
189
190 void ScriptInjection::InjectCSS(blink::WebFrame* frame,
191 ScriptsRunInfo* scripts_run_info) const {
192 const UserScript::FileList& css_scripts = script_->css_scripts();
193 scripts_run_info->num_css += css_scripts.size();
194 for (UserScript::FileList::const_iterator iter = css_scripts.begin();
195 iter != css_scripts.end();
196 ++iter) {
197 frame->document().insertStyleSheet(
198 blink::WebString::fromUTF8(iter->GetContent().as_string()));
199 }
200 }
201
202 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/renderer/script_injection.h ('k') | extensions/renderer/user_script_scheduler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698