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