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

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

Issue 321993003: Refactor renderer-side script injection (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Missing files Created 6 years, 6 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
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/user_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 "content/public/renderer/render_view.h"
13 #include "extensions/common/extension.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 "grit/extensions_renderer_resources.h"
18 #include "third_party/WebKit/public/web/WebDocument.h"
19 #include "third_party/WebKit/public/web/WebFrame.h"
20 #include "third_party/WebKit/public/web/WebScriptSource.h"
21 #include "third_party/WebKit/public/web/WebView.h"
22 #include "ui/base/resource/resource_bundle.h"
23 #include "url/gurl.h"
24
25 namespace extensions {
26
27 namespace {
28
29 // These two strings are injected before and after the Greasemonkey API and
30 // user script to wrap it in an anonymous scope.
31 const char kUserScriptHead[] = "(function (unsafeWindow) {\n";
32 const char kUserScriptTail[] = "\n})(window);";
33
34 // Greasemonkey API source that is injected with the scripts.
35 struct GreasemonkeyApiJsString {
36 GreasemonkeyApiJsString();
37 blink::WebScriptSource source;
38 };
39
40 // The below constructor, monstrous as it is, just makes a WebScriptSource from
41 // the GreasemonkeyApiJs resource.
42 GreasemonkeyApiJsString::GreasemonkeyApiJsString()
43 : source(blink::WebScriptSource(blink::WebString::fromUTF8(
44 ResourceBundle::GetSharedInstance()
45 .GetRawDataResource(IDR_GREASEMONKEY_API_JS)
46 .as_string()))) {
47 }
48
49 base::LazyInstance<GreasemonkeyApiJsString> g_greasemonkey_api =
50 LAZY_INSTANCE_INITIALIZER;
51
52 } // namespace
53
54 UserScriptInjection::UserScriptInjection(
55 blink::WebFrame* web_frame,
56 const std::string& extension_id,
57 UserScript::RunLocation run_location,
58 int tab_id,
59 UserScriptInjectionList* script_list,
60 const UserScript* script,
61 bool inject_js,
62 bool inject_css)
63 : ScriptInjection(web_frame,
64 extension_id,
65 run_location,
66 tab_id),
67 script_(script),
68 script_id_(script_->id()),
69 inject_js_(inject_js),
70 inject_css_(inject_css),
not at google - send to devlin 2014/06/15 23:53:38 see comment in user_script_injection_list; I'd ski
Devlin 2014/06/16 18:11:16 Done.
71 user_script_injection_list_observer_(this) {
72 user_script_injection_list_observer_.Add(script_list);
73 }
74
75 UserScriptInjection::~UserScriptInjection() {
76 }
77
78 void UserScriptInjection::InjectJS(const Extension* extension,
79 ScriptsRunInfo* scripts_run_info) {
80 const UserScript::FileList& js_scripts = script_->js_scripts();
81 std::vector<blink::WebScriptSource> sources;
82 scripts_run_info->num_js += js_scripts.size();
83
84 bool is_standalone_or_emulate_greasemonkey =
85 script_->is_standalone() || script_->emulate_greasemonkey();
86 for (UserScript::FileList::const_iterator iter = js_scripts.begin();
87 iter != js_scripts.end();
88 ++iter) {
89 std::string content = iter->GetContent().as_string();
90
91 // We add this dumb function wrapper for standalone user script to
92 // emulate what Greasemonkey does.
93 // TODO(aa): I think that maybe "is_standalone" scripts don't exist
94 // anymore. Investigate.
95 if (is_standalone_or_emulate_greasemonkey) {
96 content.insert(0, kUserScriptHead);
97 content += kUserScriptTail;
98 }
99 sources.push_back(blink::WebScriptSource(
100 blink::WebString::fromUTF8(content), iter->url()));
101 }
102
103 // Emulate Greasemonkey API for scripts that were converted to extensions
104 // and "standalone" user scripts.
105 if (is_standalone_or_emulate_greasemonkey)
106 sources.insert(sources.begin(), g_greasemonkey_api.Get().source);
107
108 int isolated_world_id =
109 GetIsolatedWorldIdForExtension(extension, web_frame());
110 base::ElapsedTimer exec_timer;
111 DOMActivityLogger::AttachToWorld(isolated_world_id, script_->extension_id());
112 web_frame()->executeScriptInIsolatedWorld(isolated_world_id,
113 &sources.front(),
114 sources.size(),
115 EXTENSION_GROUP_CONTENT_SCRIPTS);
116 UMA_HISTOGRAM_TIMES("Extensions.InjectScriptTime", exec_timer.Elapsed());
117
118 for (std::vector<blink::WebScriptSource>::const_iterator iter =
119 sources.begin();
120 iter != sources.end();
121 ++iter) {
122 scripts_run_info->executing_scripts[script_->extension_id()].insert(
123 GURL(iter->url).path());
124 }
125 }
126
127 void UserScriptInjection::InjectCSS(ScriptsRunInfo* scripts_run_info) {
128 const UserScript::FileList& css_scripts = script_->css_scripts();
129 scripts_run_info->num_css += css_scripts.size();
130 for (UserScript::FileList::const_iterator iter = css_scripts.begin();
131 iter != css_scripts.end();
132 ++iter) {
133 web_frame()->document().insertStyleSheet(
134 blink::WebString::fromUTF8(iter->GetContent().as_string()));
135 }
136 }
137
138 bool UserScriptInjection::Allowed(const Extension* extension) {
139 // If we don't have a tab id, we have no UI surface to ask for user consent.
140 // For now, we treat this as an automatic allow.
141 if (tab_id() == -1)
142 return true;
143
144 return !extension->permissions_data()->RequiresActionForScriptExecution(
145 extension, tab_id(), web_frame()->top()->document().url());
146 }
147
148 void UserScriptInjection::Inject(ScriptsRunInfo* scripts_run_info,
149 const Extension* extension) {
150 if (inject_js_)
151 InjectJS(extension, scripts_run_info);
152 if (inject_css_)
153 InjectCSS(scripts_run_info);
154 }
155
156 void UserScriptInjection::OnUserScriptsUpdated(
157 const std::set<std::string>& changed_extensions,
158 const std::vector<UserScript*>& scripts) {
159 // If the extension causing this injection changed, then this injection
160 // will be removed, and there's no guarantee the backing script still even
not at google - send to devlin 2014/06/15 23:53:38 s/even //
Devlin 2014/06/16 18:11:16 Done.
161 // exists.
162 if (changed_extensions.count(extension_id()) > 0)
163 return;
164
165 for (std::vector<UserScript*>::const_iterator iter = scripts.begin();
166 iter != scripts.end();
167 ++iter) {
168 if ((*iter)->id() == script_id_) {
169 script_ = *iter;
170 break;
171 }
172 }
173 }
174
175 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698