summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/extensions/execute_code_in_tab_function.cc21
-rw-r--r--chrome/browser/extensions/execute_code_in_tab_function.h7
-rw-r--r--chrome/browser/extensions/execute_script_apitest.cc1
-rw-r--r--chrome/browser/extensions/extension_tabs_module_constants.cc4
-rw-r--r--chrome/browser/tab_contents/tab_contents.cc6
-rw-r--r--chrome/browser/tab_contents/tab_contents.h3
-rwxr-xr-xchrome/common/extensions/api/extension_api.json14
-rw-r--r--chrome/common/render_messages_internal.h7
-rw-r--r--chrome/renderer/render_view.cc54
-rw-r--r--chrome/renderer/render_view.h18
-rw-r--r--chrome/test/data/extensions/api_test/executescript/test.html23
-rw-r--r--chrome/test/data/extensions/api_test/executescript_in_frame/frame0.html5
-rw-r--r--chrome/test/data/extensions/api_test/executescript_in_frame/frame1.html5
-rw-r--r--chrome/test/data/extensions/api_test/executescript_in_frame/frame2.html5
-rw-r--r--chrome/test/data/extensions/api_test/executescript_in_frame/frame3.html5
-rw-r--r--chrome/test/data/extensions/api_test/executescript_in_frame/manifest.json7
-rw-r--r--chrome/test/data/extensions/api_test/executescript_in_frame/script.js19
-rw-r--r--chrome/test/data/extensions/api_test/executescript_in_frame/test.html68
-rw-r--r--chrome/test/data/extensions/api_test/executescript_in_frame/test_executescript.html10
19 files changed, 241 insertions, 41 deletions
diff --git a/chrome/browser/extensions/execute_code_in_tab_function.cc b/chrome/browser/extensions/execute_code_in_tab_function.cc
index 98bd3be..3fb0e86 100644
--- a/chrome/browser/extensions/execute_code_in_tab_function.cc
+++ b/chrome/browser/extensions/execute_code_in_tab_function.cc
@@ -17,6 +17,7 @@ namespace keys = extension_tabs_module_constants;
const wchar_t* kCodeKey = L"code";
const wchar_t* kFileKey = L"file";
+const wchar_t* kAllFramesKey = L"allFrames";
bool ExecuteCodeInTabFunction::RunImpl() {
EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST));
@@ -28,9 +29,16 @@ bool ExecuteCodeInTabFunction::RunImpl() {
if (number_of_value == 0) {
error_ = keys::kNoCodeOrFileToExecuteError;
return false;
- } else if (number_of_value > 1) {
- error_ = keys::kMoreThanOneValuesError;
- return false;
+ } else {
+ bool has_code = script_info->HasKey(kCodeKey);
+ bool has_file = script_info->HasKey(kFileKey);
+ if (has_code && has_file) {
+ error_ = keys::kMoreThanOneValuesError;
+ return false;
+ } else if (!has_code && !has_file) {
+ error_ = keys::kNoCodeOrFileToExecuteError;
+ return false;
+ }
}
execute_tab_id_ = -1;
@@ -66,6 +74,11 @@ bool ExecuteCodeInTabFunction::RunImpl() {
return false;
}
+ if (script_info->HasKey(kAllFramesKey)) {
+ if (!script_info->GetBoolean(kAllFramesKey, &all_frames_))
+ return false;
+ }
+
std::string code_string;
if (script_info->HasKey(kCodeKey)) {
if (!script_info->GetString(kCodeKey, &code_string))
@@ -133,7 +146,7 @@ void ExecuteCodeInTabFunction::Execute(const std::string& code_string) {
NotificationService::AllSources());
AddRef(); // balanced in Observe()
contents->ExecuteCode(request_id(), extension_id(), is_js_code,
- code_string);
+ code_string, all_frames_);
}
void ExecuteCodeInTabFunction::Observe(NotificationType type,
diff --git a/chrome/browser/extensions/execute_code_in_tab_function.h b/chrome/browser/extensions/execute_code_in_tab_function.h
index 8215fd2..bd765f5 100644
--- a/chrome/browser/extensions/execute_code_in_tab_function.h
+++ b/chrome/browser/extensions/execute_code_in_tab_function.h
@@ -20,7 +20,8 @@ class MessageLoop;
class ExecuteCodeInTabFunction : public AsyncExtensionFunction,
public NotificationObserver {
public:
- ExecuteCodeInTabFunction() : execute_tab_id_(-1) {}
+ ExecuteCodeInTabFunction() : execute_tab_id_(-1),
+ all_frames_(false) {}
private:
virtual bool RunImpl();
@@ -44,6 +45,10 @@ class ExecuteCodeInTabFunction : public AsyncExtensionFunction,
// Contains extension resource built from path of file which is
// specified in JSON arguments.
ExtensionResource resource_;
+
+ // If all_frames_ is true, script or CSS text would be injected
+ // to all frames; Otherwise only injected to top main frame.
+ bool all_frames_;
};
class TabsExecuteScriptFunction : public ExecuteCodeInTabFunction {
diff --git a/chrome/browser/extensions/execute_script_apitest.cc b/chrome/browser/extensions/execute_script_apitest.cc
index f519702..2ac734b 100644
--- a/chrome/browser/extensions/execute_script_apitest.cc
+++ b/chrome/browser/extensions/execute_script_apitest.cc
@@ -10,4 +10,5 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ExecuteScript) {
StartHTTPServer();
ASSERT_TRUE(RunExtensionTest("executescript")) << message_;
+ ASSERT_TRUE(RunExtensionTest("executescript_in_frame")) << message_;
}
diff --git a/chrome/browser/extensions/extension_tabs_module_constants.cc b/chrome/browser/extensions/extension_tabs_module_constants.cc
index dac399f3..a3fc48d 100644
--- a/chrome/browser/extensions/extension_tabs_module_constants.cc
+++ b/chrome/browser/extensions/extension_tabs_module_constants.cc
@@ -47,8 +47,8 @@ const char kCannotAccessPageError[] = "Cannot access contents of url \"*\". "
const char kSupportedInWindowsOnlyError[] = "Supported in Windows only";
const char kNoCodeOrFileToExecuteError[] = "No source code or file specified.";
-const char kMoreThanOneValuesError[] = "There should be only one value (either"
- "code or file) in the second argument.";
+const char kMoreThanOneValuesError[] = "Code and file should not be specified "
+ "at the same time in the second argument.";
const char kLoadFileError[] = "Failed to load file: \"*\". ";
} // namespace extension_tabs_module_constants
diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc
index 7706c5b..0251f03 100644
--- a/chrome/browser/tab_contents/tab_contents.cc
+++ b/chrome/browser/tab_contents/tab_contents.cc
@@ -815,10 +815,12 @@ void TabContents::CloseAllSuppressedPopups() {
}
void TabContents::ExecuteCode(int request_id, const std::string& extension_id,
- bool is_js_code, const std::string& code_string) {
+ bool is_js_code, const std::string& code_string,
+ bool all_frames) {
render_view_host()->Send(
new ViewMsg_ExecuteCode(render_view_host()->routing_id(), request_id,
- extension_id, is_js_code, code_string));
+ extension_id, is_js_code, code_string,
+ all_frames));
}
void TabContents::PopupNotificationVisibilityChanged(bool visible) {
diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h
index 1b1bd13..e440a53 100644
--- a/chrome/browser/tab_contents/tab_contents.h
+++ b/chrome/browser/tab_contents/tab_contents.h
@@ -363,7 +363,8 @@ class TabContents : public PageNavigator,
// Execute code in this tab.
void ExecuteCode(int request_id, const std::string& extension_id,
- bool is_js_code, const std::string& code_string);
+ bool is_js_code, const std::string& code_string,
+ bool all_frames);
// Called when the blocked popup notification is shown or hidden.
virtual void PopupNotificationVisibilityChanged(bool visible);
diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json
index 9a29dae..8797153 100755
--- a/chrome/common/extensions/api/extension_api.json
+++ b/chrome/common/extensions/api/extension_api.json
@@ -718,11 +718,12 @@
{"type": "integer", "name": "tabId", "optional": true, "description": "The id of tab which run the script, default to selected tab of current window."},
{
"type": "object",
- "name": "scriptDef",
- "description": "Note:scripts are injected in the following definition order.",
+ "name": "details",
+ "description": "Details of the script to run. Either the code or file property must be set, but both may not be set at the same time.",
"properties": {
"code": {"type": "string", "optional": true, "description": "JavaScript code to execute."},
- "file": {"type": "string", "optional": true, "description": "JavaScript file to execute."}
+ "file": {"type": "string", "optional": true, "description": "JavaScript file to execute."},
+ "allFrames": {"type": "boolean", "optional": true, "description": "If allFrames is true, this function injects script into all frames of current page. By default, it's false and only inject script into top main frame."}
},
"optional": true
},
@@ -743,11 +744,12 @@
{"type": "integer", "name": "tabId", "optional": true, "description": "The id of tab which run the script, default to selected tab of current window."},
{
"type": "object",
- "name": "scriptDef",
- "description": "Note:css are injected in the following definition order.",
+ "name": "details",
+ "description": "Details of the css text to insert. Either the code or file property must be set, but both may not be set at the same time.",
"properties": {
"code": {"type": "string", "optional": true, "description": "CSS code to be injected."},
- "file": {"type": "string", "optional": true, "description": "CSS file to be injected."}
+ "file": {"type": "string", "optional": true, "description": "CSS file to be injected."},
+ "allFrames": {"type": "boolean", "optional": true, "description": "If allFrames is true, this function injects css text into all frames of current page. By default, it's false and only inject css text into top main frame."}
},
"optional": true
},
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index ec9e869..618b46d 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -736,12 +736,15 @@ IPC_BEGIN_MESSAGES(View)
ViewType::Type /* view_type */)
// Notification that renderer should run some JavaScript code.
- IPC_MESSAGE_ROUTED4(ViewMsg_ExecuteCode,
+ IPC_MESSAGE_ROUTED5(ViewMsg_ExecuteCode,
int, /* request id */
std::string, /* id of extension which runs the scripts */
bool, /* It's true if the code is JavaScript; Otherwise
the code is CSS text. */
- std::string /* code would be executed */)
+ std::string, /* code would be executed */
+ bool /* It's true if the code would be injected into all
+ frames; Otherwise the code is only injected into
+ top main frame */)
// Returns a file handle
IPC_MESSAGE_CONTROL2(ViewMsg_DatabaseOpenFileResponse,
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 030222a..8a9df7a 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -2351,7 +2351,7 @@ void RenderView::OnUserScriptIdleTriggered(WebFrame* frame) {
scoped_refptr<CodeExecutionInfo> info =
pending_code_execution_queue_.front();
ExecuteCodeImpl(main_frame, info->request_id, info->extension_id,
- info->is_js_code, info->code_string);
+ info->is_js_code, info->code_string, info->all_frames);
pending_code_execution_queue_.pop();
}
}
@@ -2989,6 +2989,19 @@ void RenderView::OnResetPageEncodingToDefault() {
webview()->setPageEncoding(no_encoding);
}
+bool RenderView::GetAllChildFrames(
+ WebFrame* parent_frame,
+ std::vector<WebFrame*>* frames_vector) const {
+ if (!parent_frame)
+ return false;
+ for (WebFrame* child_frame = parent_frame->firstChild(); child_frame;
+ child_frame = child_frame->nextSibling()) {
+ frames_vector->push_back(child_frame);
+ GetAllChildFrames(child_frame, frames_vector);
+ }
+ return true;
+}
+
WebFrame* RenderView::GetChildFrame(const std::wstring& xpath) const {
if (xpath.empty())
return webview()->mainFrame();
@@ -3770,7 +3783,8 @@ void RenderView::OnSetEditCommandsForNextKeyEvent(
void RenderView::OnExecuteCode(int request_id, const std::string& extension_id,
bool is_js_code,
- const std::string& code_string) {
+ const std::string& code_string,
+ bool all_frames) {
WebFrame* main_frame = webview() ? webview()->mainFrame() : NULL;
if (!main_frame) {
Send(new ViewMsg_ExecuteCodeFinished(routing_id_, request_id, false));
@@ -3781,30 +3795,40 @@ void RenderView::OnExecuteCode(int request_id, const std::string& extension_id,
NavigationState* navigation_state = NavigationState::FromDataSource(ds);
if (!navigation_state->user_script_idle_scheduler()->has_run()) {
scoped_refptr<CodeExecutionInfo> info = new CodeExecutionInfo(
- request_id, extension_id, is_js_code, code_string);
+ request_id, extension_id, is_js_code, code_string, all_frames);
pending_code_execution_queue_.push(info);
return;
}
ExecuteCodeImpl(main_frame, request_id, extension_id, is_js_code,
- code_string);
+ code_string, all_frames);
}
void RenderView::ExecuteCodeImpl(WebFrame* frame,
int request_id,
const std::string& extension_id,
bool is_js_code,
- const std::string& code_string) {
- if (is_js_code) {
- std::vector<WebScriptSource> sources;
- sources.push_back(
- WebScriptSource(WebString::fromUTF8(code_string)));
- UserScriptSlave::InsertInitExtensionCode(&sources, extension_id);
- frame->executeScriptInIsolatedWorld(
- UserScriptSlave::GetIsolatedWorldId(extension_id),
- &sources.front(), sources.size(), EXTENSION_GROUP_CONTENT_SCRIPTS);
- } else {
- frame->insertStyleText(WebString::fromUTF8(code_string), WebString());
+ const std::string& code_string,
+ bool all_frames) {
+ std::vector<WebFrame*> frame_vector;
+ frame_vector.push_back(frame);
+ if (all_frames)
+ GetAllChildFrames(frame, &frame_vector);
+
+ for (std::vector<WebFrame*>::iterator frame_it = frame_vector.begin();
+ frame_it != frame_vector.end(); ++frame_it) {
+ WebFrame* frame = *frame_it;
+ if (is_js_code) {
+ std::vector<WebScriptSource> sources;
+ sources.push_back(
+ WebScriptSource(WebString::fromUTF8(code_string)));
+ UserScriptSlave::InsertInitExtensionCode(&sources, extension_id);
+ frame->executeScriptInIsolatedWorld(
+ UserScriptSlave::GetIsolatedWorldId(extension_id),
+ &sources.front(), sources.size(), EXTENSION_GROUP_CONTENT_SCRIPTS);
+ } else {
+ frame->insertStyleText(WebString::fromUTF8(code_string), WebString());
+ }
}
Send(new ViewMsg_ExecuteCodeFinished(routing_id_, request_id, true));
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index 2cc7e7a..d53c998 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -610,12 +610,14 @@ class RenderView : public RenderWidget,
void OnExecuteCode(int request_id,
const std::string& extension_id,
bool is_js_code,
- const std::string& code_string);
+ const std::string& code_string,
+ bool all_frames);
void ExecuteCodeImpl(WebKit::WebFrame* frame,
int request_id,
const std::string& extension_id,
bool is_js_code,
- const std::string& code_string);
+ const std::string& code_string,
+ bool all_frames);
void OnUpdateBackForwardListCount(int back_list_count,
int forward_list_count);
void OnGetAccessibilityInfo(
@@ -679,6 +681,10 @@ class RenderView : public RenderWidget,
// Locates a sub frame with given xpath
WebKit::WebFrame* GetChildFrame(const std::wstring& frame_xpath) const;
+ // Get all child frames of parent_frame, returned by frames_vector.
+ bool GetAllChildFrames(WebKit::WebFrame* parent_frame,
+ std::vector<WebKit::WebFrame* >* frames_vector) const;
+
// Requests to download an image. When done, the RenderView is
// notified by way of DidDownloadImage. Returns true if the request was
// successfully started, false otherwise. id is used to uniquely identify the
@@ -953,11 +959,13 @@ class RenderView : public RenderWidget,
// page is loaded.
struct CodeExecutionInfo : public base::RefCounted<CodeExecutionInfo> {
CodeExecutionInfo(int id_of_request, const std::string& id_of_extension,
- bool is_js, const std::string& code)
+ bool is_js, const std::string& code,
+ bool inject_to_all_frames)
: request_id(id_of_request),
extension_id(id_of_extension),
code_string(code),
- is_js_code(is_js) {}
+ is_js_code(is_js),
+ all_frames(inject_to_all_frames) {}
int request_id;
// The id of extension who issues the pending executeScript API call.
@@ -969,6 +977,8 @@ class RenderView : public RenderWidget,
// It's true if |code_string| is JavaScript; otherwise |code_string| is
// CSS text.
bool is_js_code;
+ // It's true if the code_string would be injected into all frames.
+ bool all_frames;
};
std::queue<scoped_refptr<CodeExecutionInfo> > pending_code_execution_queue_;
diff --git a/chrome/test/data/extensions/api_test/executescript/test.html b/chrome/test/data/extensions/api_test/executescript/test.html
index c4bbbe3..8a2db2d 100644
--- a/chrome/test/data/extensions/api_test/executescript/test.html
+++ b/chrome/test/data/extensions/api_test/executescript/test.html
@@ -8,14 +8,15 @@ var relativePath =
'/files/extensions/api_test/executescript/test_executescript.html';
var testUrl = 'http://a.com:1337' + relativePath;
var testFailureUrl = 'http://b.com:1337' + relativePath;
-var testingFailure = false;
+var firstEnter = true;
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
- if (changeInfo.status == 'complete')
+ if (changeInfo.status != 'complete')
return;
- if (testingFailure) {
+ if (!firstEnter) {
return;
}
+ firstEnter = false;
chrome.test.runTests([
@@ -68,7 +69,6 @@ chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
},
function executeJavaScriptCodeShouldFail() {
- testingFailure = true;
chrome.tabs.update(tabId, { url: testFailureUrl }, function() {
var script_file = {};
script_file.code = "document.title = 'executeScript';";
@@ -77,6 +77,21 @@ chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
'". Extension manifest must request permission to access this ' +
'host.'));
});
+ },
+
+ function executeJavaScriptWithNoneValueShouldFail() {
+ var script_file = {};
+ chrome.tabs.executeScript(tabId, script_file, fail(
+ 'No source code or file specified.'));
+ },
+
+ function executeJavaScriptWithTwoValuesShouldFail() {
+ var script_file = {};
+ script_file.file = 'script1.js';
+ script_file.code = 'var test = 1;';
+ chrome.tabs.executeScript(tabId, script_file, fail(
+ 'Code and file should not be specified ' +
+ 'at the same time in the second argument.'));
}
]);
});
diff --git a/chrome/test/data/extensions/api_test/executescript_in_frame/frame0.html b/chrome/test/data/extensions/api_test/executescript_in_frame/frame0.html
new file mode 100644
index 0000000..6bb02a0
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/executescript_in_frame/frame0.html
@@ -0,0 +1,5 @@
+<html>
+ <title>test0</title>
+ <b id='test1'>text</b>
+ <p id='test2'>text</p>
+</html> \ No newline at end of file
diff --git a/chrome/test/data/extensions/api_test/executescript_in_frame/frame1.html b/chrome/test/data/extensions/api_test/executescript_in_frame/frame1.html
new file mode 100644
index 0000000..148114b
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/executescript_in_frame/frame1.html
@@ -0,0 +1,5 @@
+<html>
+ <title>test1</title>
+ <b id='test1'>text</b>
+ <p id='test2'>text</p>
+</html> \ No newline at end of file
diff --git a/chrome/test/data/extensions/api_test/executescript_in_frame/frame2.html b/chrome/test/data/extensions/api_test/executescript_in_frame/frame2.html
new file mode 100644
index 0000000..e8b5b3c
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/executescript_in_frame/frame2.html
@@ -0,0 +1,5 @@
+<html>
+ <title>test2</title>
+ <b id='test1'>text</b>
+ <p id='test2'>text</p>
+</html> \ No newline at end of file
diff --git a/chrome/test/data/extensions/api_test/executescript_in_frame/frame3.html b/chrome/test/data/extensions/api_test/executescript_in_frame/frame3.html
new file mode 100644
index 0000000..63f8807
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/executescript_in_frame/frame3.html
@@ -0,0 +1,5 @@
+<html>
+ <title>test3</title>
+ <b id='test1'>text</b>
+ <p id='test2'>text</p>
+</html> \ No newline at end of file
diff --git a/chrome/test/data/extensions/api_test/executescript_in_frame/manifest.json b/chrome/test/data/extensions/api_test/executescript_in_frame/manifest.json
new file mode 100644
index 0000000..b2f3856
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/executescript_in_frame/manifest.json
@@ -0,0 +1,7 @@
+{
+ "version": "1.0.0.0",
+ "name": "executeScript and insertCSS test",
+ "description": "Test extension API: executeScript and insertCSS",
+ "background_page": "test.html",
+ "permissions": ["tabs", "http://a.com/"]
+}
diff --git a/chrome/test/data/extensions/api_test/executescript_in_frame/script.js b/chrome/test/data/extensions/api_test/executescript_in_frame/script.js
new file mode 100644
index 0000000..a4efa64
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/executescript_in_frame/script.js
@@ -0,0 +1,19 @@
+function getStyle(elem, name) {
+ if (document.defaultView && document.defaultView.getComputedStyle) {
+ name = name.toLowerCase();
+
+ try {
+ var s = document.defaultView.getComputedStyle(elem, '');
+ return s && s.getPropertyValue(name);
+ } catch (ex) {
+ return null;
+ }
+ } else {
+ return null;
+ }
+}
+
+var bElement = document.getElementById('test2');
+var display = getStyle(bElement, 'display').toLowerCase();
+var extensionPort = chrome.extension.connect();
+extensionPort.postMessage({message: display});
diff --git a/chrome/test/data/extensions/api_test/executescript_in_frame/test.html b/chrome/test/data/extensions/api_test/executescript_in_frame/test.html
new file mode 100644
index 0000000..a8e2f06
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/executescript_in_frame/test.html
@@ -0,0 +1,68 @@
+<script>
+
+var pass = chrome.test.callbackPass;
+var fail = chrome.test.callbackFail;
+var assertEq = chrome.test.assertEq;
+var assertTrue = chrome.test.assertTrue;
+var relativePath =
+ '/files/extensions/api_test/executescript_in_frame/test_executescript.html';
+var testUrl = 'http://a.com:1337' + relativePath;
+
+chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
+ if (changeInfo.status != 'complete')
+ return;
+
+ chrome.test.runTests([
+ function executeJavaScriptCodeInAllFramesShouldSucceed() {
+ var script_file = {};
+ script_file.code = "var extensionPort = chrome.extension.connect();";
+ script_file.code = script_file.code +
+ "extensionPort.postMessage({message: document.title});";
+ script_file.allFrames = true;
+ var counter = 0;
+ var totalTitles = '';
+ function eventListener(port) {
+ port.onMessage.addListener(function(data) {
+ counter++;
+ totalTitles += data.message;
+ });
+ };
+ chrome.self.onConnect.addListener(eventListener);
+ chrome.tabs.executeScript(tabId, script_file, pass(function() {
+ assertEq(counter, 5);
+ assertEq(totalTitles, 'frametest0test1test2test3');
+ chrome.self.onConnect.removeListener(eventListener);
+ }));
+ },
+
+ function insertCSSTextInAllFramesShouldSucceed() {
+ var css_file = {};
+ css_file.code = "p {display:none;}";
+ css_file.allFrames = true;
+ var newStyle = '';
+ var counter = 0;
+ function eventListener(port) {
+ port.onMessage.addListener(function(data) {
+ counter++;
+ newStyle += data.message;
+ });
+ };
+ chrome.self.onConnect.addListener(eventListener);
+ chrome.tabs.insertCSS(tabId, css_file, function() {
+ var script_file = {};
+ script_file.file = 'script.js';
+ script_file.allFrames = true;
+ chrome.tabs.executeScript(tabId, script_file,
+ pass(function() {
+ assertEq(newStyle, 'nonenonenonenone');
+ assertEq(counter, 4);
+ chrome.self.onConnect.removeListener(eventListener);
+ }));
+ });
+ }
+ ]);
+});
+
+chrome.tabs.create({ url: testUrl });
+
+</script>
diff --git a/chrome/test/data/extensions/api_test/executescript_in_frame/test_executescript.html b/chrome/test/data/extensions/api_test/executescript_in_frame/test_executescript.html
new file mode 100644
index 0000000..b1f0b6c
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/executescript_in_frame/test_executescript.html
@@ -0,0 +1,10 @@
+<html>
+<title>frame</title>
+<frameset cols="25%,25%,25%,25%">
+ <frame src="frame0.html" />
+ <frame src="frame1.html" />
+ <frame src="frame2.html" />
+ <frame src="frame3.html" />
+</frameset>
+
+</html> \ No newline at end of file