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

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

Issue 2213603002: Prevent duplicate content script injection defined in manifest.json (reland) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed patch 8 code review comments Created 4 years, 3 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
OLDNEW
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
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
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
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
OLDNEW
« extensions/renderer/script_injector.h ('K') | « extensions/renderer/user_script_injector.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698