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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: extensions/renderer/user_script_injection.cc
diff --git a/extensions/renderer/user_script_injection.cc b/extensions/renderer/user_script_injection.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ba30dd8c7564c41a16115fc3d587b00202a7223d
--- /dev/null
+++ b/extensions/renderer/user_script_injection.cc
@@ -0,0 +1,175 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/renderer/user_script_injection.h"
+
+#include <vector>
+
+#include "base/lazy_instance.h"
+#include "base/metrics/histogram.h"
+#include "content/public/common/url_constants.h"
+#include "content/public/renderer/render_view.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/permissions/permissions_data.h"
+#include "extensions/renderer/dom_activity_logger.h"
+#include "extensions/renderer/extension_groups.h"
+#include "grit/extensions_renderer_resources.h"
+#include "third_party/WebKit/public/web/WebDocument.h"
+#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebScriptSource.h"
+#include "third_party/WebKit/public/web/WebView.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "url/gurl.h"
+
+namespace extensions {
+
+namespace {
+
+// These two strings are injected before and after the Greasemonkey API and
+// user script to wrap it in an anonymous scope.
+const char kUserScriptHead[] = "(function (unsafeWindow) {\n";
+const char kUserScriptTail[] = "\n})(window);";
+
+// Greasemonkey API source that is injected with the scripts.
+struct GreasemonkeyApiJsString {
+ GreasemonkeyApiJsString();
+ blink::WebScriptSource source;
+};
+
+// The below constructor, monstrous as it is, just makes a WebScriptSource from
+// the GreasemonkeyApiJs resource.
+GreasemonkeyApiJsString::GreasemonkeyApiJsString()
+ : source(blink::WebScriptSource(blink::WebString::fromUTF8(
+ ResourceBundle::GetSharedInstance()
+ .GetRawDataResource(IDR_GREASEMONKEY_API_JS)
+ .as_string()))) {
+}
+
+base::LazyInstance<GreasemonkeyApiJsString> g_greasemonkey_api =
+ LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+UserScriptInjection::UserScriptInjection(
+ blink::WebFrame* web_frame,
+ const std::string& extension_id,
+ UserScript::RunLocation run_location,
+ int tab_id,
+ UserScriptInjectionList* script_list,
+ const UserScript* script,
+ bool inject_js,
+ bool inject_css)
+ : ScriptInjection(web_frame,
+ extension_id,
+ run_location,
+ tab_id),
+ script_(script),
+ script_id_(script_->id()),
+ inject_js_(inject_js),
+ 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.
+ user_script_injection_list_observer_(this) {
+ user_script_injection_list_observer_.Add(script_list);
+}
+
+UserScriptInjection::~UserScriptInjection() {
+}
+
+void UserScriptInjection::InjectJS(const Extension* extension,
+ ScriptsRunInfo* scripts_run_info) {
+ const UserScript::FileList& js_scripts = script_->js_scripts();
+ std::vector<blink::WebScriptSource> sources;
+ scripts_run_info->num_js += js_scripts.size();
+
+ bool is_standalone_or_emulate_greasemonkey =
+ script_->is_standalone() || script_->emulate_greasemonkey();
+ for (UserScript::FileList::const_iterator iter = js_scripts.begin();
+ iter != js_scripts.end();
+ ++iter) {
+ std::string content = iter->GetContent().as_string();
+
+ // We add this dumb function wrapper for standalone user script to
+ // emulate what Greasemonkey does.
+ // TODO(aa): I think that maybe "is_standalone" scripts don't exist
+ // anymore. Investigate.
+ if (is_standalone_or_emulate_greasemonkey) {
+ content.insert(0, kUserScriptHead);
+ content += kUserScriptTail;
+ }
+ sources.push_back(blink::WebScriptSource(
+ blink::WebString::fromUTF8(content), iter->url()));
+ }
+
+ // Emulate Greasemonkey API for scripts that were converted to extensions
+ // and "standalone" user scripts.
+ if (is_standalone_or_emulate_greasemonkey)
+ sources.insert(sources.begin(), g_greasemonkey_api.Get().source);
+
+ int isolated_world_id =
+ GetIsolatedWorldIdForExtension(extension, web_frame());
+ base::ElapsedTimer exec_timer;
+ DOMActivityLogger::AttachToWorld(isolated_world_id, script_->extension_id());
+ web_frame()->executeScriptInIsolatedWorld(isolated_world_id,
+ &sources.front(),
+ sources.size(),
+ EXTENSION_GROUP_CONTENT_SCRIPTS);
+ UMA_HISTOGRAM_TIMES("Extensions.InjectScriptTime", exec_timer.Elapsed());
+
+ for (std::vector<blink::WebScriptSource>::const_iterator iter =
+ sources.begin();
+ iter != sources.end();
+ ++iter) {
+ scripts_run_info->executing_scripts[script_->extension_id()].insert(
+ GURL(iter->url).path());
+ }
+}
+
+void UserScriptInjection::InjectCSS(ScriptsRunInfo* scripts_run_info) {
+ const UserScript::FileList& css_scripts = script_->css_scripts();
+ scripts_run_info->num_css += css_scripts.size();
+ for (UserScript::FileList::const_iterator iter = css_scripts.begin();
+ iter != css_scripts.end();
+ ++iter) {
+ web_frame()->document().insertStyleSheet(
+ blink::WebString::fromUTF8(iter->GetContent().as_string()));
+ }
+}
+
+bool UserScriptInjection::Allowed(const Extension* extension) {
+ // If we don't have a tab id, we have no UI surface to ask for user consent.
+ // For now, we treat this as an automatic allow.
+ if (tab_id() == -1)
+ return true;
+
+ return !extension->permissions_data()->RequiresActionForScriptExecution(
+ extension, tab_id(), web_frame()->top()->document().url());
+}
+
+void UserScriptInjection::Inject(ScriptsRunInfo* scripts_run_info,
+ const Extension* extension) {
+ if (inject_js_)
+ InjectJS(extension, scripts_run_info);
+ if (inject_css_)
+ InjectCSS(scripts_run_info);
+}
+
+void UserScriptInjection::OnUserScriptsUpdated(
+ const std::set<std::string>& changed_extensions,
+ const std::vector<UserScript*>& scripts) {
+ // If the extension causing this injection changed, then this injection
+ // 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.
+ // exists.
+ if (changed_extensions.count(extension_id()) > 0)
+ return;
+
+ for (std::vector<UserScript*>::const_iterator iter = scripts.begin();
+ iter != scripts.end();
+ ++iter) {
+ if ((*iter)->id() == script_id_) {
+ script_ = *iter;
+ break;
+ }
+ }
+}
+
+} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698