summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-17 00:11:31 +0000
committeraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-17 00:11:31 +0000
commitfae45b07ffdaf1966002caa9d623737f593f38f4 (patch)
tree0981955b61c564f4f831b198f7b2d06074ccf1f5
parent3094eaca9ef8aef595b1f0fcae2c839dae40a35a (diff)
downloadchromium_src-fae45b07ffdaf1966002caa9d623737f593f38f4.zip
chromium_src-fae45b07ffdaf1966002caa9d623737f593f38f4.tar.gz
chromium_src-fae45b07ffdaf1966002caa9d623737f593f38f4.tar.bz2
Merge 33035 - Introduce a new 'all_frames' property to content scripts and
default it to false. This should improve performance in sites that use frames and elimiate confusion, since in most cases developers *don't* expect content scripts to match frames. Review URL: http://codereview.chromium.org/412008 TBR=aa@chromium.org git-svn-id: svn://svn.chromium.org/chrome/branches/249/src@34785 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/content_script_all_frames_apitest.cc10
-rwxr-xr-xchrome/chrome.gyp2
-rw-r--r--chrome/common/extensions/docs/content_scripts.html8
-rw-r--r--chrome/common/extensions/docs/examples/api/messaging/timer/page.js18
-rw-r--r--chrome/common/extensions/docs/static/content_scripts.html8
-rw-r--r--chrome/common/extensions/extension.cc15
-rw-r--r--chrome/common/extensions/extension_constants.cc3
-rw-r--r--chrome/common/extensions/extension_constants.h2
-rw-r--r--chrome/common/extensions/user_script.cc6
-rw-r--r--chrome/common/extensions/user_script.h11
-rw-r--r--chrome/renderer/user_script_slave.cc4
-rw-r--r--chrome/test/data/extensions/api_test/content_script_all_frames/all_frames.js1
-rw-r--r--chrome/test/data/extensions/api_test/content_script_all_frames/manifest.json18
-rw-r--r--chrome/test/data/extensions/api_test/content_script_all_frames/test.html34
-rw-r--r--chrome/test/data/extensions/api_test/content_script_all_frames/top_frame_only.js1
-rw-r--r--chrome/test/data/extensions/subscribe_page_action/feed_finder.js6
-rw-r--r--chrome/test/data/extensions/test_file_with_iframe.html4
17 files changed, 135 insertions, 16 deletions
diff --git a/chrome/browser/extensions/content_script_all_frames_apitest.cc b/chrome/browser/extensions/content_script_all_frames_apitest.cc
new file mode 100644
index 0000000..1f61ea4
--- /dev/null
+++ b/chrome/browser/extensions/content_script_all_frames_apitest.cc
@@ -0,0 +1,10 @@
+// Copyright (c) 2009 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 "chrome/browser/extensions/extension_apitest.h"
+
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptAllFrames) {
+ StartHTTPServer();
+ ASSERT_TRUE(RunExtensionTest("content_script_all_frames")) << message_;
+}
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 16fb895..440b610 100755
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -61,6 +61,7 @@
'browser/extensions/autoupdate_interceptor.cc',
'browser/extensions/autoupdate_interceptor.h',
'browser/extensions/browser_action_apitest.cc',
+ 'browser/extensions/content_script_all_frames_apitest.cc',
'browser/extensions/cross_origin_xhr_apitest.cc',
'browser/extensions/execute_script_apitest.cc',
'browser/extensions/extension_apitest.cc',
@@ -108,6 +109,7 @@
],
'browser_tests_sources_exclude_on_mac': [
'browser/extensions/browser_action_apitest.cc',
+ 'browser/extensions/content_script_all_frames_apitest.cc',
'browser/extensions/cross_origin_xhr_apitest.cc',
'browser/extensions/execute_script_apitest.cc',
'browser/extensions/extension_apitest.cc',
diff --git a/chrome/common/extensions/docs/content_scripts.html b/chrome/common/extensions/docs/content_scripts.html
index 34b7d05..c3b720c 100644
--- a/chrome/common/extensions/docs/content_scripts.html
+++ b/chrome/common/extensions/docs/content_scripts.html
@@ -409,6 +409,14 @@ learn about the
<b>NOTE:</b> In <code>document_idle</code>, content scripts may not necessarily receive the window.onload event, because they may run after it has
already fired. In most cases, listening for the onload event is unnecessary for content scripts running at <code>document_idle</code> because they are guaranteed to run after the DOM is complete. If your script definitely needs to run after <code>window.onload</code> you can check if it has already fired by using the <code><a href="http://www.whatwg.org/specs/web-apps/current-work/#dom-document-readystate">document.readyState</a></code> property.</td>
</tr>
+ <tr>
+ <td>all_frames</td>
+ <td>boolean</td>
+ <td><em>Optional.</em>
+ Controls whether the content script runs in all frames of the matching page, or only the top frame.
+ <br><br>
+ Defaults to <code>false</code>, meaning that only the top frame is matched.</td>
+ </tr>
</tbody></table>
diff --git a/chrome/common/extensions/docs/examples/api/messaging/timer/page.js b/chrome/common/extensions/docs/examples/api/messaging/timer/page.js
index 4914aab..92f8df3 100644
--- a/chrome/common/extensions/docs/examples/api/messaging/timer/page.js
+++ b/chrome/common/extensions/docs/examples/api/messaging/timer/page.js
@@ -1,12 +1,10 @@
-if (window == top) {
- chrome.extension.onConnect.addListener(function(port) {
- port.onMessage.addListener(function(msg) {
- port.postMessage({counter: msg.counter+1});
- });
+chrome.extension.onConnect.addListener(function(port) {
+ port.onMessage.addListener(function(msg) {
+ port.postMessage({counter: msg.counter+1});
});
+});
- chrome.extension.onRequest.addListener(
- function(request, sender, sendResponse) {
- sendResponse({counter: request.counter+1});
- });
-}
+chrome.extension.onRequest.addListener(
+ function(request, sender, sendResponse) {
+ sendResponse({counter: request.counter+1});
+ });
diff --git a/chrome/common/extensions/docs/static/content_scripts.html b/chrome/common/extensions/docs/static/content_scripts.html
index ffd3c89..3e52078 100644
--- a/chrome/common/extensions/docs/static/content_scripts.html
+++ b/chrome/common/extensions/docs/static/content_scripts.html
@@ -127,6 +127,14 @@ learn about the
<b>NOTE:</b> In <code>document_idle</code>, content scripts may not necessarily receive the window.onload event, because they may run after it has
already fired. In most cases, listening for the onload event is unnecessary for content scripts running at <code>document_idle</code> because they are guaranteed to run after the DOM is complete. If your script definitely needs to run after <code>window.onload</code> you can check if it has already fired by using the <code><a href="http://www.whatwg.org/specs/web-apps/current-work/#dom-document-readystate">document.readyState</a></code> property.</td>
</tr>
+ <tr>
+ <td>all_frames</td>
+ <td>boolean</td>
+ <td><em>Optional.</em>
+ Controls whether the content script runs in all frames of the matching page, or only the top frame.
+ <br><br>
+ Defaults to <code>false</code>, meaning that only the top frame is matched.</td>
+ </tr>
</table>
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
index 72ebe24..34975f9 100644
--- a/chrome/common/extensions/extension.cc
+++ b/chrome/common/extensions/extension.cc
@@ -217,6 +217,17 @@ bool Extension::LoadUserScriptHelper(const DictionaryValue* content_script,
}
}
+ // all frames
+ if (content_script->HasKey(keys::kAllFrames)) {
+ bool all_frames = false;
+ if (!content_script->GetBoolean(keys::kAllFrames, &all_frames)) {
+ *error = ExtensionErrorUtils::FormatErrorMessage(
+ errors::kInvalidAllFrames, IntToString(definition_index));
+ return false;
+ }
+ result->set_match_all_frames(all_frames);
+ }
+
// matches
ListValue* matches = NULL;
if (!content_script->GetList(keys::kMatches, &matches)) {
@@ -991,8 +1002,10 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_id,
if (!LoadUserScriptHelper(content_script, i, error, &script))
return false; // Failed to parse script context definition
script.set_extension_id(id());
- if (converted_from_user_script_)
+ if (converted_from_user_script_) {
script.set_emulate_greasemonkey(true);
+ script.set_match_all_frames(true); // greasemonkey matches all frames
+ }
content_scripts_.push_back(script);
}
}
diff --git a/chrome/common/extensions/extension_constants.cc b/chrome/common/extensions/extension_constants.cc
index f89e23f..54588e5a 100644
--- a/chrome/common/extensions/extension_constants.cc
+++ b/chrome/common/extensions/extension_constants.cc
@@ -6,6 +6,7 @@
namespace extension_manifest_keys {
+const wchar_t* kAllFrames = L"all_frames";
const wchar_t* kBackground = L"background_page";
const wchar_t* kBrowserAction = L"browser_action";
const wchar_t* kChromeURLOverrides = L"chrome_url_overrides";
@@ -65,6 +66,8 @@ const char* kPageActionTypePermanent = "permanent";
// printf because we want to unit test them and scanf is hard to make
// cross-platform.
namespace extension_manifest_errors {
+const char* kInvalidAllFrames =
+ "Invalid value for 'content_scripts[*].all_frames'.";
const char* kInvalidBrowserAction =
"Invalid value for 'browser_action'.";
const char* kInvalidChromeURLOverrides =
diff --git a/chrome/common/extensions/extension_constants.h b/chrome/common/extensions/extension_constants.h
index 17ca5cb..01d1ff4 100644
--- a/chrome/common/extensions/extension_constants.h
+++ b/chrome/common/extensions/extension_constants.h
@@ -7,6 +7,7 @@
// Keys used in JSON representation of extensions.
namespace extension_manifest_keys {
+ extern const wchar_t* kAllFrames;
extern const wchar_t* kBackground;
extern const wchar_t* kBrowserAction;
extern const wchar_t* kChromeURLOverrides;
@@ -89,6 +90,7 @@ namespace extension_manifest_errors {
extern const char* kInvalidPrivacyBlacklists;
extern const char* kInvalidPrivacyBlacklistsPath;
+ extern const char* kInvalidAllFrames;
extern const char* kInvalidBackground;
extern const char* kInvalidRunAt;
extern const char* kInvalidSignature;
diff --git a/chrome/common/extensions/user_script.cc b/chrome/common/extensions/user_script.cc
index 10d0b60..96f7dd4 100644
--- a/chrome/common/extensions/user_script.cc
+++ b/chrome/common/extensions/user_script.cc
@@ -84,6 +84,9 @@ void UserScript::Pickle(::Pickle* pickle) const {
// Write Greasemonkey emulation.
pickle->WriteBool(emulate_greasemonkey());
+ // Write match all frames
+ pickle->WriteBool(match_all_frames());
+
// Write globs.
std::vector<std::string>::const_iterator glob;
pickle->WriteSize(globs_.size());
@@ -130,6 +133,9 @@ void UserScript::Unpickle(const ::Pickle& pickle, void** iter) {
// Read Greasemonkey emulation.
CHECK(pickle.ReadBool(iter, &emulate_greasemonkey_));
+ // Read match all frames
+ CHECK(pickle.ReadBool(iter, &match_all_frames_));
+
// Read globs.
size_t num_globs = 0;
CHECK(pickle.ReadSize(iter, &num_globs));
diff --git a/chrome/common/extensions/user_script.h b/chrome/common/extensions/user_script.h
index adcfa3f..b7093c1 100644
--- a/chrome/common/extensions/user_script.h
+++ b/chrome/common/extensions/user_script.h
@@ -102,7 +102,8 @@ class UserScript {
// Constructor. Default the run location to document end, which is like
// Greasemonkey and probably more useful for typical scripts.
UserScript()
- : run_location_(DOCUMENT_IDLE), emulate_greasemonkey_(false) {
+ : run_location_(DOCUMENT_IDLE), emulate_greasemonkey_(false),
+ match_all_frames_(false) {
}
const std::string& name_space() const { return name_space_; }
@@ -126,6 +127,10 @@ class UserScript {
bool emulate_greasemonkey() const { return emulate_greasemonkey_; }
void set_emulate_greasemonkey(bool val) { emulate_greasemonkey_ = val; }
+ // Whether to match all frames, or only the top one.
+ bool match_all_frames() const { return match_all_frames_; }
+ void set_match_all_frames(bool val) { match_all_frames_ = val; }
+
// The globs, if any, that determine which pages this script runs against.
// These are only used with "standalone" Greasemonkey-like user scripts.
const std::vector<std::string>& globs() const { return globs_; }
@@ -209,6 +214,10 @@ class UserScript {
// Whether we should try to emulate Greasemonkey's APIs when running this
// script.
bool emulate_greasemonkey_;
+
+ // Whether the user script should run in all frames, or only just the top one.
+ // Defaults to false.
+ bool match_all_frames_;
};
typedef std::vector<UserScript> UserScriptList;
diff --git a/chrome/renderer/user_script_slave.cc b/chrome/renderer/user_script_slave.cc
index 4820c83..68dec43 100644
--- a/chrome/renderer/user_script_slave.cc
+++ b/chrome/renderer/user_script_slave.cc
@@ -163,6 +163,10 @@ bool UserScriptSlave::InjectScripts(WebFrame* frame,
for (size_t i = 0; i < scripts_.size(); ++i) {
std::vector<WebScriptSource> sources;
UserScript* script = scripts_[i];
+
+ if (frame->parent() && !script->match_all_frames())
+ continue; // Only match subframes if the script declared it wanted to.
+
if (!script->MatchesUrl(frame->url()))
continue; // This frame doesn't match the script url pattern, skip it.
diff --git a/chrome/test/data/extensions/api_test/content_script_all_frames/all_frames.js b/chrome/test/data/extensions/api_test/content_script_all_frames/all_frames.js
new file mode 100644
index 0000000..71d22fd
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/content_script_all_frames/all_frames.js
@@ -0,0 +1 @@
+chrome.extension.sendRequest("all_frames");
diff --git a/chrome/test/data/extensions/api_test/content_script_all_frames/manifest.json b/chrome/test/data/extensions/api_test/content_script_all_frames/manifest.json
new file mode 100644
index 0000000..0f73a8f
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/content_script_all_frames/manifest.json
@@ -0,0 +1,18 @@
+{
+ "name": "content_script_all_frames",
+ "version": "1.0",
+ "description": "Tests the all_frames property of content script declarations.",
+ "background_page": "test.html",
+ "permissions": ["tabs"],
+ "content_scripts": [
+ {
+ "matches": ["http://*/*"],
+ "js": ["top_frame_only.js"]
+ },
+ {
+ "matches": ["http://*/*"],
+ "js": ["all_frames.js"],
+ "all_frames": true
+ }
+ ]
+}
diff --git a/chrome/test/data/extensions/api_test/content_script_all_frames/test.html b/chrome/test/data/extensions/api_test/content_script_all_frames/test.html
new file mode 100644
index 0000000..e8f8088
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/content_script_all_frames/test.html
@@ -0,0 +1,34 @@
+<script>
+// We load a page that has one iframe
+// So we should receive two "all_frames" messages, and one "top_frame_only"
+// messages.
+
+var num_all_frames_messages = 0;
+var num_top_frame_only_messages = 0;
+
+chrome.test.runTests([
+ // Tests receiving a request from a content script and responding.
+ function onRequest() {
+ chrome.extension.onRequest.addListener(
+ function(request, sender, sendResponse) {
+ if (request == "all_frames") {
+ num_all_frames_messages++;
+ } else if (request == "top_frame_only") {
+ num_top_frame_only_messages++;
+ } else {
+ chrome.test.fail("Unexpected request: " + JSON.stringify(request));
+ }
+
+ if (num_all_frames_messages == 2 && num_top_frame_only_messages == 1) {
+ chrome.test.succeed();
+ }
+ }
+ );
+ }
+]);
+
+chrome.test.log("Creating tab...");
+chrome.tabs.create({
+ url: "http://localhost:1337/files/extensions/test_file_with_iframe.html"
+});
+</script>
diff --git a/chrome/test/data/extensions/api_test/content_script_all_frames/top_frame_only.js b/chrome/test/data/extensions/api_test/content_script_all_frames/top_frame_only.js
new file mode 100644
index 0000000..76ad923
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/content_script_all_frames/top_frame_only.js
@@ -0,0 +1 @@
+chrome.extension.sendRequest("top_frame_only");
diff --git a/chrome/test/data/extensions/subscribe_page_action/feed_finder.js b/chrome/test/data/extensions/subscribe_page_action/feed_finder.js
index d5c4f2a..5261264 100644
--- a/chrome/test/data/extensions/subscribe_page_action/feed_finder.js
+++ b/chrome/test/data/extensions/subscribe_page_action/feed_finder.js
@@ -2,10 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-if (window == top) {
- findFeeds();
- window.addEventListener("focus", findFeeds);
-}
+findFeeds();
+window.addEventListener("focus", findFeeds);
function findFeeds() {
// Find all the RSS link elements.
diff --git a/chrome/test/data/extensions/test_file_with_iframe.html b/chrome/test/data/extensions/test_file_with_iframe.html
new file mode 100644
index 0000000..8a310c7
--- /dev/null
+++ b/chrome/test/data/extensions/test_file_with_iframe.html
@@ -0,0 +1,4 @@
+<html>
+Test file!
+<iframe src="test_file.html"></iframe>
+</html>