Chromium Code Reviews| 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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 78 blink::WebString::fromUTF8(source_piece.data(), source_piece.length()); | 78 blink::WebString::fromUTF8(source_piece.data(), source_piece.length()); |
| 79 } | 79 } |
| 80 | 80 |
| 81 blink::WebScriptSource GreasemonkeyApiJsString::GetSource() const { | 81 blink::WebScriptSource GreasemonkeyApiJsString::GetSource() const { |
| 82 return blink::WebScriptSource(source_); | 82 return blink::WebScriptSource(source_); |
| 83 } | 83 } |
| 84 | 84 |
| 85 base::LazyInstance<GreasemonkeyApiJsString> g_greasemonkey_api = | 85 base::LazyInstance<GreasemonkeyApiJsString> g_greasemonkey_api = |
| 86 LAZY_INSTANCE_INITIALIZER; | 86 LAZY_INSTANCE_INITIALIZER; |
| 87 | 87 |
| 88 bool ShouldInjectScripts(const UserScript::FileList& scripts, | |
| 89 std::set<std::string>* injected_files) { | |
|
Devlin
2016/09/07 18:22:40
nit: const & for injected files
catmullings
2016/09/07 18:56:31
Done.
| |
| 90 for (const std::unique_ptr<UserScript::File>& file : scripts) { | |
| 91 // Check if the script is already injected. | |
| 92 if ((*injected_files).count(file->url().path()) == 0) { | |
| 93 return true; | |
| 94 } | |
| 95 } | |
| 96 return false; | |
| 97 } | |
| 98 | |
| 88 } // namespace | 99 } // namespace |
| 89 | 100 |
| 90 UserScriptInjector::UserScriptInjector(const UserScript* script, | 101 UserScriptInjector::UserScriptInjector(const UserScript* script, |
| 91 UserScriptSet* script_list, | 102 UserScriptSet* script_list, |
| 92 bool is_declarative) | 103 bool is_declarative) |
| 93 : script_(script), | 104 : script_(script), |
| 94 script_id_(script_->id()), | 105 script_id_(script_->id()), |
| 95 host_id_(script_->host_id()), | 106 host_id_(script_->host_id()), |
| 96 is_declarative_(is_declarative), | 107 is_declarative_(is_declarative), |
| 97 user_script_set_observer_(this) { | 108 user_script_set_observer_(this) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 132 | 143 |
| 133 bool UserScriptInjector::IsUserGesture() const { | 144 bool UserScriptInjector::IsUserGesture() const { |
| 134 return false; | 145 return false; |
| 135 } | 146 } |
| 136 | 147 |
| 137 bool UserScriptInjector::ExpectsResults() const { | 148 bool UserScriptInjector::ExpectsResults() const { |
| 138 return false; | 149 return false; |
| 139 } | 150 } |
| 140 | 151 |
| 141 bool UserScriptInjector::ShouldInjectJs( | 152 bool UserScriptInjector::ShouldInjectJs( |
| 142 UserScript::RunLocation run_location) const { | 153 UserScript::RunLocation run_location, |
| 154 std::set<std::string>* executing_scripts) const { | |
| 143 return script_ && script_->run_location() == run_location && | 155 return script_ && script_->run_location() == run_location && |
| 144 !script_->js_scripts().empty(); | 156 !script_->js_scripts().empty() && |
| 157 ShouldInjectScripts(script_->js_scripts(), executing_scripts); | |
| 145 } | 158 } |
| 146 | 159 |
| 147 bool UserScriptInjector::ShouldInjectCss( | 160 bool UserScriptInjector::ShouldInjectCss( |
| 148 UserScript::RunLocation run_location) const { | 161 UserScript::RunLocation run_location, |
| 162 std::set<std::string>* injected_stylesheets) const { | |
| 149 return script_ && run_location == UserScript::DOCUMENT_START && | 163 return script_ && run_location == UserScript::DOCUMENT_START && |
| 150 !script_->css_scripts().empty(); | 164 !script_->css_scripts().empty() && |
| 165 ShouldInjectScripts(script_->css_scripts(), injected_stylesheets); | |
| 151 } | 166 } |
| 152 | 167 |
| 153 PermissionsData::AccessType UserScriptInjector::CanExecuteOnFrame( | 168 PermissionsData::AccessType UserScriptInjector::CanExecuteOnFrame( |
| 154 const InjectionHost* injection_host, | 169 const InjectionHost* injection_host, |
| 155 blink::WebLocalFrame* web_frame, | 170 blink::WebLocalFrame* web_frame, |
| 156 int tab_id) const { | 171 int tab_id) const { |
| 157 // There is no harm in allowing the injection when the script is gone, | 172 // There is no harm in allowing the injection when the script is gone, |
| 158 // because there is nothing to inject. | 173 // because there is nothing to inject. |
| 159 if (!script_) | 174 if (!script_) |
| 160 return PermissionsData::ACCESS_ALLOWED; | 175 return PermissionsData::ACCESS_ALLOWED; |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 191 web_frame, web_frame->document().url(), script_->match_about_blank()); | 206 web_frame, web_frame->document().url(), script_->match_about_blank()); |
| 192 | 207 |
| 193 return injection_host->CanExecuteOnFrame( | 208 return injection_host->CanExecuteOnFrame( |
| 194 effective_document_url, | 209 effective_document_url, |
| 195 content::RenderFrame::FromWebFrame(web_frame), | 210 content::RenderFrame::FromWebFrame(web_frame), |
| 196 tab_id, | 211 tab_id, |
| 197 is_declarative_); | 212 is_declarative_); |
| 198 } | 213 } |
| 199 | 214 |
| 200 std::vector<blink::WebScriptSource> UserScriptInjector::GetJsSources( | 215 std::vector<blink::WebScriptSource> UserScriptInjector::GetJsSources( |
| 201 UserScript::RunLocation run_location) const { | 216 UserScript::RunLocation run_location, |
| 217 std::set<std::string>* executing_scripts, | |
| 218 size_t* num_injected_js_scripts) const { | |
| 219 DCHECK(script_); | |
| 202 std::vector<blink::WebScriptSource> sources; | 220 std::vector<blink::WebScriptSource> sources; |
| 203 if (!script_) | |
| 204 return sources; | |
| 205 | 221 |
| 206 DCHECK_EQ(script_->run_location(), run_location); | 222 DCHECK_EQ(script_->run_location(), run_location); |
| 207 | 223 |
| 208 const UserScript::FileList& js_scripts = script_->js_scripts(); | 224 const UserScript::FileList& js_scripts = script_->js_scripts(); |
| 209 sources.reserve(js_scripts.size()); | 225 sources.reserve(js_scripts.size()); |
| 210 for (const std::unique_ptr<UserScript::File>& file : js_scripts) { | 226 for (const std::unique_ptr<UserScript::File>& file : js_scripts) { |
| 227 const GURL& script_url = file->url(); | |
| 228 // Check if the script is already injected. | |
| 229 if ((*executing_scripts).count(script_url.path()) != 0) | |
| 230 continue; | |
| 211 base::StringPiece script_content = file->GetContent(); | 231 base::StringPiece script_content = file->GetContent(); |
| 212 blink::WebString source; | 232 blink::WebString source; |
| 213 if (script_->emulate_greasemonkey()) { | 233 if (script_->emulate_greasemonkey()) { |
| 214 // We add this dumb function wrapper for user scripts to emulate what | 234 // We add this dumb function wrapper for user scripts to emulate what |
| 215 // Greasemonkey does. |script_content| becomes: | 235 // Greasemonkey does. |script_content| becomes: |
| 216 // concat(kUserScriptHead, script_content, kUserScriptTail). | 236 // concat(kUserScriptHead, script_content, kUserScriptTail). |
| 217 std::string content; | 237 std::string content; |
| 218 content.reserve(strlen(kUserScriptHead) + script_content.length() + | 238 content.reserve(strlen(kUserScriptHead) + script_content.length() + |
| 219 strlen(kUserScriptTail)); | 239 strlen(kUserScriptTail)); |
| 220 content.append(kUserScriptHead); | 240 content.append(kUserScriptHead); |
| 221 script_content.AppendToString(&content); | 241 script_content.AppendToString(&content); |
| 222 content.append(kUserScriptTail); | 242 content.append(kUserScriptTail); |
| 223 // TODO(lazyboy): |content| is copied to |source|, should be avoided. | 243 // TODO(lazyboy): |content| is copied to |source|, should be avoided. |
| 224 // Investigate if we can leverage WebString's cheap copying mechanism | 244 // Investigate if we can leverage WebString's cheap copying mechanism |
| 225 // somehow. | 245 // somehow. |
| 226 source = blink::WebString::fromUTF8(content); | 246 source = blink::WebString::fromUTF8(content); |
| 227 } else { | 247 } else { |
| 228 source = blink::WebString::fromUTF8(script_content.data(), | 248 source = blink::WebString::fromUTF8(script_content.data(), |
| 229 script_content.length()); | 249 script_content.length()); |
| 230 } | 250 } |
| 231 sources.push_back(blink::WebScriptSource(source, file->url())); | 251 sources.push_back(blink::WebScriptSource(source, script_url)); |
| 252 (*num_injected_js_scripts) += 1; | |
| 253 (*executing_scripts).insert(script_url.path()); | |
| 232 } | 254 } |
| 233 | |
| 234 // Emulate Greasemonkey API for scripts that were converted to extension | 255 // Emulate Greasemonkey API for scripts that were converted to extension |
| 235 // user scripts. | 256 // user scripts. |
| 236 if (script_->emulate_greasemonkey()) | 257 if (script_->emulate_greasemonkey()) |
| 237 sources.insert(sources.begin(), g_greasemonkey_api.Get().GetSource()); | 258 sources.insert(sources.begin(), g_greasemonkey_api.Get().GetSource()); |
| 238 | 259 |
| 239 return sources; | 260 return sources; |
| 240 } | 261 } |
| 241 | 262 |
| 242 std::vector<blink::WebString> UserScriptInjector::GetCssSources( | 263 std::vector<blink::WebString> UserScriptInjector::GetCssSources( |
| 243 UserScript::RunLocation run_location) const { | 264 UserScript::RunLocation run_location, |
| 265 std::set<std::string>* injected_stylesheets, | |
| 266 size_t* num_injected_stylesheets) const { | |
| 267 DCHECK(script_); | |
| 244 DCHECK_EQ(UserScript::DOCUMENT_START, run_location); | 268 DCHECK_EQ(UserScript::DOCUMENT_START, run_location); |
| 245 | 269 |
| 246 std::vector<blink::WebString> sources; | 270 std::vector<blink::WebString> sources; |
| 247 if (!script_) | |
| 248 return sources; | |
| 249 | 271 |
| 250 const UserScript::FileList& css_scripts = script_->css_scripts(); | 272 const UserScript::FileList& css_scripts = script_->css_scripts(); |
| 251 sources.reserve(css_scripts.size()); | 273 sources.reserve(css_scripts.size()); |
| 252 for (const std::unique_ptr<UserScript::File>& file : script_->css_scripts()) { | 274 for (const std::unique_ptr<UserScript::File>& file : script_->css_scripts()) { |
| 275 const std::string stylesheet_path = file->url().path(); | |
|
Devlin
2016/09/07 18:22:40
nit: no need to copy here, so const std::string&
catmullings
2016/09/07 18:56:31
Done.
catmullings
2016/09/07 18:56:31
Yup, didn't mean to drop the &.
| |
| 276 // Check if the stylesheet is already injected. | |
| 277 if ((*injected_stylesheets).count(stylesheet_path) != 0) | |
| 278 continue; | |
| 279 | |
| 253 // TODO(lazyboy): |css_content| string is copied into blink::WebString for | 280 // TODO(lazyboy): |css_content| string is copied into blink::WebString for |
| 254 // every frame in the current renderer process. Avoid the copy, possibly by | 281 // every frame in the current renderer process. Avoid the copy, possibly by |
| 255 // only performing the copy once. | 282 // only performing the copy once. |
| 256 base::StringPiece css_content = file->GetContent(); | 283 base::StringPiece css_content = file->GetContent(); |
| 257 sources.push_back( | 284 sources.push_back( |
| 258 blink::WebString::fromUTF8(css_content.data(), css_content.length())); | 285 blink::WebString::fromUTF8(css_content.data(), css_content.length())); |
| 286 (*num_injected_stylesheets) += 1; | |
| 287 (*injected_stylesheets).insert(stylesheet_path); | |
| 259 } | 288 } |
| 260 return sources; | 289 return sources; |
| 261 } | 290 } |
| 262 | 291 |
| 263 void UserScriptInjector::GetRunInfo( | |
| 264 ScriptsRunInfo* scripts_run_info, | |
| 265 UserScript::RunLocation run_location) const { | |
| 266 if (!script_) | |
| 267 return; | |
| 268 | |
| 269 if (ShouldInjectJs(run_location)) { | |
| 270 const UserScript::FileList& js_scripts = script_->js_scripts(); | |
| 271 scripts_run_info->num_js += js_scripts.size(); | |
| 272 for (const std::unique_ptr<UserScript::File>& iter : js_scripts) { | |
| 273 scripts_run_info->executing_scripts[host_id_.id()].insert( | |
| 274 iter->url().path()); | |
| 275 } | |
| 276 } | |
| 277 | |
| 278 if (ShouldInjectCss(run_location)) | |
| 279 scripts_run_info->num_css += script_->css_scripts().size(); | |
| 280 } | |
| 281 | |
| 282 void UserScriptInjector::OnInjectionComplete( | 292 void UserScriptInjector::OnInjectionComplete( |
| 283 std::unique_ptr<base::Value> execution_result, | 293 std::unique_ptr<base::Value> execution_result, |
| 284 UserScript::RunLocation run_location, | 294 UserScript::RunLocation run_location, |
| 285 content::RenderFrame* render_frame) {} | 295 content::RenderFrame* render_frame) {} |
| 286 | 296 |
| 287 void UserScriptInjector::OnWillNotInject(InjectFailureReason reason, | 297 void UserScriptInjector::OnWillNotInject(InjectFailureReason reason, |
| 288 content::RenderFrame* render_frame) { | 298 content::RenderFrame* render_frame) { |
| 289 } | 299 } |
| 290 | 300 |
| 291 } // namespace extensions | 301 } // namespace extensions |
| OLD | NEW |