OLD | NEW |
---|---|
(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 | |
not at google - send to devlin
2014/05/15 23:23:21
dd
Devlin
2014/05/16 22:32:20
Done.
| |
91 const Extension* extension = user_script_slave_->GetExtension(extension_id_); | |
92 // Since extension info is sent separately from user script info, they can | |
93 // be out of sync. We just ignore this situation. | |
94 if (!extension) | |
95 return false; | |
96 | |
97 // Content scripts are not tab-specific. | |
98 static const int kNoTabId = -1; | |
99 // We don't have a process id in this context. | |
100 static const int kNoProcessId = -1; | |
101 | |
102 if (!PermissionsData::CanExecuteScriptOnPage(extension, | |
103 document_url, | |
104 frame->top()->document().url(), | |
105 kNoTabId, | |
106 script_.get(), | |
107 kNoProcessId, | |
108 NULL /* ignore error */)) { | |
109 return false; | |
110 } | |
111 | |
112 return ShouldInjectCSS(run_location) || ShouldInjectJS(run_location); | |
113 } | |
114 | |
115 void ScriptInjection::Inject(blink::WebFrame* frame, | |
116 UserScript::RunLocation run_location, | |
117 ScriptsRunInfo* scripts_run_info) const { | |
118 DCHECK(frame); | |
119 DCHECK(scripts_run_info); | |
120 DCHECK(WantsToRun(frame, run_location, GetDocumentUrlForFrame(frame))); | |
121 DCHECK(user_script_slave_->GetExtension(extension_id_)); | |
122 | |
123 if (ShouldInjectCSS(run_location)) | |
124 InjectCSS(frame, scripts_run_info); | |
125 if (ShouldInjectJS(run_location)) | |
126 InjectJS(frame, scripts_run_info); | |
127 } | |
128 | |
129 bool ScriptInjection::ShouldInjectJS(UserScript::RunLocation run_location) | |
130 const { | |
131 return !script_->js_scripts().empty() && | |
132 script_->run_location() == run_location; | |
133 } | |
134 | |
135 bool ScriptInjection::ShouldInjectCSS(UserScript::RunLocation run_location) | |
136 const { | |
137 return !script_->css_scripts().empty() && | |
138 script_->run_location() == UserScript::DOCUMENT_START; | |
not at google - send to devlin
2014/05/15 23:23:21
I think you want |run_location| == DOCUMENT_START
Devlin
2014/05/16 22:32:20
Whoops, good catch - yes, meant |run_location|.
| |
139 } | |
140 | |
141 void ScriptInjection::InjectJS(blink::WebFrame* frame, | |
142 ScriptsRunInfo* scripts_run_info) const { | |
143 const UserScript::FileList& js_scripts = script_->js_scripts(); | |
144 std::vector<blink::WebScriptSource> sources; | |
145 scripts_run_info->num_js += js_scripts.size(); | |
146 for (UserScript::FileList::const_iterator iter = js_scripts.begin(); | |
147 iter != js_scripts.end(); | |
148 ++iter) { | |
149 std::string content = iter->GetContent().as_string(); | |
150 | |
151 // We add this dumb function wrapper for standalone user script to | |
152 // emulate what Greasemonkey does. | |
153 // TODO(aa): I think that maybe "is_standalone" scripts don't exist | |
154 // anymore. Investigate. | |
155 if (is_standalone_or_emulate_greasemonkey_) { | |
156 content.insert(0, kUserScriptHead); | |
157 content += kUserScriptTail; | |
158 } | |
159 sources.push_back(blink::WebScriptSource( | |
160 blink::WebString::fromUTF8(content), iter->url())); | |
161 } | |
162 | |
163 // Emulate Greasemonkey API for scripts that were converted to extensions | |
164 // and "standalone" user scripts. | |
165 if (is_standalone_or_emulate_greasemonkey_) | |
166 sources.insert(sources.begin(), g_greasemonkey_api.Get().source); | |
167 | |
168 int isolated_world_id = | |
169 user_script_slave_->GetIsolatedWorldIdForExtension( | |
170 user_script_slave_->GetExtension(extension_id_), frame); | |
171 base::ElapsedTimer exec_timer; | |
172 DOMActivityLogger::AttachToWorld(isolated_world_id, extension_id_); | |
173 frame->executeScriptInIsolatedWorld(isolated_world_id, | |
174 &sources.front(), | |
175 sources.size(), | |
176 EXTENSION_GROUP_CONTENT_SCRIPTS); | |
177 UMA_HISTOGRAM_TIMES("Extensions.InjectScriptTime", exec_timer.Elapsed()); | |
178 | |
179 for (std::vector<blink::WebScriptSource>::const_iterator iter = | |
180 sources.begin(); | |
181 iter != sources.end(); | |
182 ++iter) { | |
183 scripts_run_info->executing_scripts[extension_id_].insert( | |
184 GURL(iter->url).path()); | |
185 } | |
186 } | |
187 | |
188 void ScriptInjection::InjectCSS(blink::WebFrame* frame, | |
189 ScriptsRunInfo* scripts_run_info) const { | |
190 const UserScript::FileList& css_scripts = script_->css_scripts(); | |
191 scripts_run_info->num_css += css_scripts.size(); | |
192 for (UserScript::FileList::const_iterator iter = css_scripts.begin(); | |
193 iter != css_scripts.end(); | |
194 ++iter) { | |
195 frame->document().insertStyleSheet( | |
196 blink::WebString::fromUTF8(iter->GetContent().as_string())); | |
197 } | |
198 } | |
199 | |
200 } // namespace extensions | |
OLD | NEW |