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

Unified Diff: chrome/browser/web_contents.cc

Issue 6274: Greasemonkey support. (Closed)
Patch Set: Created 12 years, 2 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: chrome/browser/web_contents.cc
diff --git a/chrome/browser/web_contents.cc b/chrome/browser/web_contents.cc
index d8eb687c226cb89239591ef8c4f15b559fc3a32b..b02c53e62ada08bc68b23197758ea7232e236ed6 100644
--- a/chrome/browser/web_contents.cc
+++ b/chrome/browser/web_contents.cc
@@ -6,6 +6,12 @@
#include "base/command_line.h"
#include "base/compiler_specific.h"
+#include "base/path_service.h"
+#include "base/singleton.h"
+#include "base/string_util.h"
+#include "net/base/escape.h"
+#include "chrome/common/chrome_paths.h"
+#include "base/file_util.h"
#include "base/file_version_info.h"
#include "chrome/app/locales/locale_settings.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
@@ -153,6 +159,137 @@ bool IsFormSubmit(const NavigationEntry* entry) {
} // namespace
+class GreaseMonkeyScript {
+public:
+ GreaseMonkeyScript(const std::wstring& path)
+ : path_(path) {}
+
+ bool Parse(const std::string& content) {
+ // http://wiki.greasespot.net/Metadata_block
+ std::map<std::string, std::string> keyvals;
+ std::vector<std::string> lines;
+ SplitString(content, '\n', &lines);
+ bool in_metadata = false;
+ for (std::vector<std::string>::iterator i = lines.begin(); i != lines.end(); ++i) {
+ std::string line;
+ TrimWhitespace(*i, TRIM_ALL, &line);
+ if (line == "// ==UserScript==") {
+ in_metadata = true;
+ } else if (in_metadata) {
+ if (line == "// ==/UserScript==")
+ break;
+ std::vector<std::string> parts;
+ SplitString(line, ' ', &parts);
+ if (parts.size() > 3) {
+ for (size_t i = 3; i < parts.size(); ++i) {
+ parts[2] += " " + parts[i];
+ }
+ parts.resize(3);
+ }
+ if (parts.size() == 3 && parts[0] == "//") {
+ std::string key = parts[1];
+ if (key.length() > 0 && key[0] == '@')
+ key = key.substr(1);
+ std::string value;
+ TrimWhitespace(parts[2], TRIM_ALL, &value);
+ if (key == "include") {
+ include_globs_.push_back(value);
+ } else {
+ //NOTREACHED();
+ }
+ }
+ }
+ }
+ script_ = content;
+ return true;
+ }
+
+ bool AffectsURL(const GURL& url) {
+ const std::string& spec = url.spec();
+ for (std::vector<std::string>::const_iterator glob = include_globs_.begin();
+ glob != include_globs_.end(); ++glob) {
+ for (size_t i = 0; i < glob->size(); ++i) {
+ char glob_char = (*glob)[i];
+ if (glob_char == '*' && i == glob->size() - 1)
+ return true;
+ if (i > spec.size() || spec[i] != glob_char)
+ return false;
+ }
+ }
+ return true;
+ }
+
+ std::string script() const {
+ return script_;
+ }
+
+ std::wstring path() const {
+ return path_;
+ }
+
+ std::vector<std::string> include_globs_;
+ std::string script_;
+ std::wstring path_;
+};
+
+class ScriptInjector {
+public:
+ ScriptInjector() {
+ LoadUserScripts();
+ }
+
+ ~ScriptInjector() {
+ ClearScripts();
+ }
+
+ void ClearScripts() {
+ for (std::vector<GreaseMonkeyScript*>::iterator script = scripts_.begin();
+ script != scripts_.end(); ++script) {
+ delete *script;
+ }
+ scripts_.clear();
+ }
+
+ void LoadUserScripts() {
+ ClearScripts();
+ std::wstring path;
+ DCHECK(PathService::Get(chrome::DIR_USER_SCRIPTS, &path));
+ file_util::FileEnumerator enumerator(path, false, file_util::FileEnumerator::FILES,
+ L"*.user.js");
+ for (std::wstring file = enumerator.Next(); !file.empty(); file = enumerator.Next()) {
+ std::string contents;
+ DCHECK(file_util::ReadFileToString(file, &contents));
+ GreaseMonkeyScript* script = new GreaseMonkeyScript(file);
+ DCHECK(script->Parse(contents));
+ scripts_.push_back(script);
+ //url_js_["http://" + WideToUTF8(file_util::GetFilenameFromPath(file)) + "/"] = UTF8ToWide(contents);
+ }
+ }
+
+ void LoadCompleted(WebContents* web_contents) {
+ LoadUserScripts();
+ NavigationEntry* nav_entry = web_contents->controller()->GetActiveEntry();
+ DCHECK(nav_entry);
+ for (std::vector<GreaseMonkeyScript*>::const_iterator script = scripts_.begin();
+ script != scripts_.end(); ++script) {
+ if ((*script)->AffectsURL(nav_entry->url())) {
+ RunJavaScript(web_contents, (*script)->script(), (*script)->path());
+ }
+ }
+ }
+
+ void RunJavaScript(WebContents* web_contents, const std::string& javascript,
+ const std::wstring& path) {
+ web_contents->render_view_host()->ExecuteJavascriptInWebFrame(std::wstring(),
+ UTF8ToWide(javascript),
+ path);
+ }
+
+ std::vector<GreaseMonkeyScript*> scripts_;
+};
+Singleton<ScriptInjector> script_injector;
+
+
class WebContents::GearsCreateShortcutCallbackFunctor {
public:
explicit GearsCreateShortcutCallbackFunctor(WebContents* contents)
@@ -1120,6 +1257,7 @@ void WebContents::DidStopLoading(RenderViewHost* rvh, int32 page_id) {
GetPasswordManager()->DidStopLoading();
SetIsLoading(false, details.get());
+ script_injector->LoadCompleted(this);
}
void WebContents::DidStartProvisionalLoadForFrame(

Powered by Google App Engine
This is Rietveld 408576698