OLD | NEW |
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/user_script_injector.h" | 5 #include "extensions/renderer/user_script_injector.h" |
6 | 6 |
7 #include <tuple> | 7 #include <tuple> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 blink::WebString::fromUTF8(source_piece.data(), source_piece.length()); | 73 blink::WebString::fromUTF8(source_piece.data(), source_piece.length()); |
74 } | 74 } |
75 | 75 |
76 blink::WebScriptSource GreasemonkeyApiJsString::GetSource() const { | 76 blink::WebScriptSource GreasemonkeyApiJsString::GetSource() const { |
77 return blink::WebScriptSource(source_); | 77 return blink::WebScriptSource(source_); |
78 } | 78 } |
79 | 79 |
80 base::LazyInstance<GreasemonkeyApiJsString> g_greasemonkey_api = | 80 base::LazyInstance<GreasemonkeyApiJsString> g_greasemonkey_api = |
81 LAZY_INSTANCE_INITIALIZER; | 81 LAZY_INSTANCE_INITIALIZER; |
82 | 82 |
| 83 bool ShouldInjectScripts(const UserScript::FileList& scripts, |
| 84 const std::set<std::string>& injected_files) { |
| 85 for (const std::unique_ptr<UserScript::File>& file : scripts) { |
| 86 // Check if the script is already injected. |
| 87 if (injected_files.count(file->url().path()) == 0) { |
| 88 return true; |
| 89 } |
| 90 } |
| 91 return false; |
| 92 } |
| 93 |
83 } // namespace | 94 } // namespace |
84 | 95 |
85 UserScriptInjector::UserScriptInjector(const UserScript* script, | 96 UserScriptInjector::UserScriptInjector(const UserScript* script, |
86 UserScriptSet* script_list, | 97 UserScriptSet* script_list, |
87 bool is_declarative) | 98 bool is_declarative) |
88 : script_(script), | 99 : script_(script), |
89 user_script_set_(script_list), | 100 user_script_set_(script_list), |
90 script_id_(script_->id()), | 101 script_id_(script_->id()), |
91 host_id_(script_->host_id()), | 102 host_id_(script_->host_id()), |
92 is_declarative_(is_declarative), | 103 is_declarative_(is_declarative), |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 | 139 |
129 bool UserScriptInjector::IsUserGesture() const { | 140 bool UserScriptInjector::IsUserGesture() const { |
130 return false; | 141 return false; |
131 } | 142 } |
132 | 143 |
133 bool UserScriptInjector::ExpectsResults() const { | 144 bool UserScriptInjector::ExpectsResults() const { |
134 return false; | 145 return false; |
135 } | 146 } |
136 | 147 |
137 bool UserScriptInjector::ShouldInjectJs( | 148 bool UserScriptInjector::ShouldInjectJs( |
138 UserScript::RunLocation run_location) const { | 149 UserScript::RunLocation run_location, |
| 150 const std::set<std::string>& executing_scripts) const { |
139 return script_ && script_->run_location() == run_location && | 151 return script_ && script_->run_location() == run_location && |
140 !script_->js_scripts().empty(); | 152 !script_->js_scripts().empty() && |
| 153 ShouldInjectScripts(script_->js_scripts(), executing_scripts); |
141 } | 154 } |
142 | 155 |
143 bool UserScriptInjector::ShouldInjectCss( | 156 bool UserScriptInjector::ShouldInjectCss( |
144 UserScript::RunLocation run_location) const { | 157 UserScript::RunLocation run_location, |
| 158 const std::set<std::string>& injected_stylesheets) const { |
145 return script_ && run_location == UserScript::DOCUMENT_START && | 159 return script_ && run_location == UserScript::DOCUMENT_START && |
146 !script_->css_scripts().empty(); | 160 !script_->css_scripts().empty() && |
| 161 ShouldInjectScripts(script_->css_scripts(), injected_stylesheets); |
147 } | 162 } |
148 | 163 |
149 PermissionsData::AccessType UserScriptInjector::CanExecuteOnFrame( | 164 PermissionsData::AccessType UserScriptInjector::CanExecuteOnFrame( |
150 const InjectionHost* injection_host, | 165 const InjectionHost* injection_host, |
151 blink::WebLocalFrame* web_frame, | 166 blink::WebLocalFrame* web_frame, |
152 int tab_id) const { | 167 int tab_id) const { |
153 // There is no harm in allowing the injection when the script is gone, | 168 // There is no harm in allowing the injection when the script is gone, |
154 // because there is nothing to inject. | 169 // because there is nothing to inject. |
155 if (!script_) | 170 if (!script_) |
156 return PermissionsData::ACCESS_ALLOWED; | 171 return PermissionsData::ACCESS_ALLOWED; |
(...skipping 30 matching lines...) Expand all Loading... |
187 web_frame, web_frame->document().url(), script_->match_about_blank()); | 202 web_frame, web_frame->document().url(), script_->match_about_blank()); |
188 | 203 |
189 return injection_host->CanExecuteOnFrame( | 204 return injection_host->CanExecuteOnFrame( |
190 effective_document_url, | 205 effective_document_url, |
191 content::RenderFrame::FromWebFrame(web_frame), | 206 content::RenderFrame::FromWebFrame(web_frame), |
192 tab_id, | 207 tab_id, |
193 is_declarative_); | 208 is_declarative_); |
194 } | 209 } |
195 | 210 |
196 std::vector<blink::WebScriptSource> UserScriptInjector::GetJsSources( | 211 std::vector<blink::WebScriptSource> UserScriptInjector::GetJsSources( |
197 UserScript::RunLocation run_location) const { | 212 UserScript::RunLocation run_location, |
| 213 std::set<std::string>* executing_scripts, |
| 214 size_t* num_injected_js_scripts) const { |
| 215 DCHECK(script_); |
198 std::vector<blink::WebScriptSource> sources; | 216 std::vector<blink::WebScriptSource> sources; |
199 if (!script_) | |
200 return sources; | |
201 | 217 |
202 DCHECK_EQ(script_->run_location(), run_location); | 218 DCHECK_EQ(script_->run_location(), run_location); |
203 | 219 |
204 const UserScript::FileList& js_scripts = script_->js_scripts(); | 220 const UserScript::FileList& js_scripts = script_->js_scripts(); |
205 sources.reserve(js_scripts.size() + | 221 sources.reserve(js_scripts.size() + |
206 (script_->emulate_greasemonkey() ? 1 : 0)); | 222 (script_->emulate_greasemonkey() ? 1 : 0)); |
207 | |
208 // Emulate Greasemonkey API for scripts that were converted to extension | 223 // Emulate Greasemonkey API for scripts that were converted to extension |
209 // user scripts. | 224 // user scripts. |
210 if (script_->emulate_greasemonkey()) | 225 if (script_->emulate_greasemonkey()) |
211 sources.push_back(g_greasemonkey_api.Get().GetSource()); | 226 sources.push_back(g_greasemonkey_api.Get().GetSource()); |
| 227 for (const std::unique_ptr<UserScript::File>& file : js_scripts) { |
| 228 const GURL& script_url = file->url(); |
| 229 // Check if the script is already injected. |
| 230 if (executing_scripts->count(script_url.path()) != 0) |
| 231 continue; |
212 | 232 |
213 for (const std::unique_ptr<UserScript::File>& file : js_scripts) { | |
214 sources.push_back(blink::WebScriptSource( | 233 sources.push_back(blink::WebScriptSource( |
215 user_script_set_->GetJsSource(*file, script_->emulate_greasemonkey()), | 234 user_script_set_->GetJsSource(*file, script_->emulate_greasemonkey()), |
216 file->url())); | 235 script_url)); |
| 236 |
| 237 (*num_injected_js_scripts) += 1; |
| 238 executing_scripts->insert(script_url.path()); |
217 } | 239 } |
218 | 240 |
219 return sources; | 241 return sources; |
220 } | 242 } |
221 | 243 |
222 std::vector<blink::WebString> UserScriptInjector::GetCssSources( | 244 std::vector<blink::WebString> UserScriptInjector::GetCssSources( |
223 UserScript::RunLocation run_location) const { | 245 UserScript::RunLocation run_location, |
| 246 std::set<std::string>* injected_stylesheets, |
| 247 size_t* num_injected_stylesheets) const { |
| 248 DCHECK(script_); |
224 DCHECK_EQ(UserScript::DOCUMENT_START, run_location); | 249 DCHECK_EQ(UserScript::DOCUMENT_START, run_location); |
225 | 250 |
226 std::vector<blink::WebString> sources; | 251 std::vector<blink::WebString> sources; |
227 if (!script_) | |
228 return sources; | |
229 | 252 |
230 const UserScript::FileList& css_scripts = script_->css_scripts(); | 253 const UserScript::FileList& css_scripts = script_->css_scripts(); |
231 sources.reserve(css_scripts.size()); | 254 sources.reserve(css_scripts.size()); |
232 for (const std::unique_ptr<UserScript::File>& file : script_->css_scripts()) | 255 for (const std::unique_ptr<UserScript::File>& file : script_->css_scripts()) { |
| 256 const std::string& stylesheet_path = file->url().path(); |
| 257 // Check if the stylesheet is already injected. |
| 258 if (injected_stylesheets->count(stylesheet_path) != 0) |
| 259 continue; |
| 260 |
233 sources.push_back(user_script_set_->GetCssSource(*file)); | 261 sources.push_back(user_script_set_->GetCssSource(*file)); |
| 262 (*num_injected_stylesheets) += 1; |
| 263 injected_stylesheets->insert(stylesheet_path); |
| 264 } |
234 return sources; | 265 return sources; |
235 } | 266 } |
236 | 267 |
237 void UserScriptInjector::GetRunInfo( | |
238 ScriptsRunInfo* scripts_run_info, | |
239 UserScript::RunLocation run_location) const { | |
240 if (!script_) | |
241 return; | |
242 | |
243 if (ShouldInjectJs(run_location)) { | |
244 const UserScript::FileList& js_scripts = script_->js_scripts(); | |
245 scripts_run_info->num_js += js_scripts.size(); | |
246 for (const std::unique_ptr<UserScript::File>& iter : js_scripts) { | |
247 scripts_run_info->executing_scripts[host_id_.id()].insert( | |
248 iter->url().path()); | |
249 } | |
250 } | |
251 | |
252 if (ShouldInjectCss(run_location)) | |
253 scripts_run_info->num_css += script_->css_scripts().size(); | |
254 } | |
255 | |
256 void UserScriptInjector::OnInjectionComplete( | 268 void UserScriptInjector::OnInjectionComplete( |
257 std::unique_ptr<base::Value> execution_result, | 269 std::unique_ptr<base::Value> execution_result, |
258 UserScript::RunLocation run_location, | 270 UserScript::RunLocation run_location, |
259 content::RenderFrame* render_frame) {} | 271 content::RenderFrame* render_frame) {} |
260 | 272 |
261 void UserScriptInjector::OnWillNotInject(InjectFailureReason reason, | 273 void UserScriptInjector::OnWillNotInject(InjectFailureReason reason, |
262 content::RenderFrame* render_frame) { | 274 content::RenderFrame* render_frame) { |
263 } | 275 } |
264 | 276 |
265 } // namespace extensions | 277 } // namespace extensions |
OLD | NEW |