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( |