summaryrefslogtreecommitdiffstats
path: root/chrome/renderer/greasemonkey_slave.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/renderer/greasemonkey_slave.cc')
-rw-r--r--chrome/renderer/greasemonkey_slave.cc117
1 files changed, 109 insertions, 8 deletions
diff --git a/chrome/renderer/greasemonkey_slave.cc b/chrome/renderer/greasemonkey_slave.cc
index cba48d1..5a4072a 100644
--- a/chrome/renderer/greasemonkey_slave.cc
+++ b/chrome/renderer/greasemonkey_slave.cc
@@ -7,7 +7,109 @@
#include "base/logging.h"
#include "base/pickle.h"
#include "base/shared_memory.h"
+#include "googleurl/src/gurl.h"
+
+// GreasemonkeyScript
+
+void GreasemonkeyScript::Parse(const StringPiece& script_text) {
+ ParseMetadata(script_text);
+
+ // TODO(aa): Set body to just the part after the metadata block? This would
+ // significantly cut down on the size of the injected script in some cases.
+ // Would require remembering the line number the body begins at, for correct
+ // error line number reporting.
+ body_ = script_text;
+}
+
+bool GreasemonkeyScript::MatchesUrl(const GURL& url) {
+ for (std::vector<std::string>::iterator pattern = include_patterns_.begin();
+ pattern != include_patterns_.end(); ++pattern) {
+ if (MatchPattern(url.spec(), *pattern)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void GreasemonkeyScript::ParseMetadata(const StringPiece& script_text) {
+ // http://wiki.greasespot.net/Metadata_block
+ StringPiece line;
+ size_t line_start = 0;
+ size_t line_end = 0;
+ bool in_metadata = false;
+
+ static const StringPiece kUserScriptBegin("// ==UserScript==");
+ static const StringPiece kUserScriptEng("// ==/UserScript==");
+ static const StringPiece kIncludeDeclaration("// @include ");
+
+ while (line_start < script_text.length()) {
+ line_end = script_text.find('\n', line_start);
+
+ // Handle the case where there is no trailing newline in the file.
+ if (line_end == std::string::npos) {
+ line_end = script_text.length() - 1;
+ }
+
+ line.set(script_text.data() + line_start, line_end - line_start);
+
+ if (!in_metadata) {
+ if (line.starts_with(kUserScriptBegin)) {
+ in_metadata = true;
+ }
+ } else {
+ if (line.starts_with(kUserScriptEng)) {
+ break;
+ }
+
+ if (line.starts_with(kIncludeDeclaration)) {
+ std::string pattern(line.data() + kIncludeDeclaration.length(),
+ line.length() - kIncludeDeclaration.length());
+ std::string pattern_trimmed;
+ TrimWhitespace(pattern, TRIM_ALL, &pattern_trimmed);
+ AddInclude(pattern_trimmed);
+ }
+
+ // TODO(aa): Handle more types of metadata.
+ }
+
+ line_start = line_end + 1;
+ }
+
+ // If no @include patterns were specified, default to @include *.
+ // This is what Greasemonkey for Firefox does.
+ if (include_patterns_.size() == 0) {
+ AddInclude("*");
+ }
+}
+
+void GreasemonkeyScript::AddInclude(const std::string &glob_pattern) {
+ include_patterns_.push_back(EscapeGlob(glob_pattern));
+}
+
+std::string GreasemonkeyScript::EscapeGlob(const std::string& input_pattern) {
+ std::string output_pattern;
+
+ for (size_t i = 0; i < input_pattern.length(); ++i) {
+ switch (input_pattern[i]) {
+ // These characters have special meaning to the MatchPattern() function,
+ // so we escape them.
+ case '\\':
+ case '?':
+ output_pattern += '\\';
+ // fall through
+
+ default:
+ output_pattern += input_pattern[i];
+ }
+ }
+
+ return output_pattern;
+}
+
+
+// GreasemonkeySlave
GreasemonkeySlave::GreasemonkeySlave() : shared_memory_(NULL) {
}
@@ -47,22 +149,21 @@ bool GreasemonkeySlave::UpdateScripts(SharedMemoryHandle shared_memory) {
pickle.ReadData(&iter, &url, &url_length);
pickle.ReadData(&iter, &body, &body_length);
- GreasemonkeyScript script(StringPiece(url, url_length));
- if (script.Parse(StringPiece(body, body_length))) {
- scripts_.push_back(script);
- }
+ scripts_.push_back(GreasemonkeyScript(StringPiece(url, url_length)));
+ GreasemonkeyScript& script = scripts_.back();
+ script.Parse(StringPiece(body, body_length));
}
return true;
}
bool GreasemonkeySlave::InjectScripts(WebFrame* frame) {
- // TODO(aa): Check script patterns here
-
for (std::vector<GreasemonkeyScript>::iterator script = scripts_.begin();
script != scripts_.end(); ++script) {
- frame->ExecuteJavaScript(script->GetBody().as_string(),
- script->GetURL().as_string());
+ if (script->MatchesUrl(frame->GetURL())) {
+ frame->ExecuteJavaScript(script->GetBody().as_string(),
+ script->GetURL().as_string());
+ }
}
return true;