summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreaugusti@chromium.org <eaugusti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-25 23:34:31 +0000
committereaugusti@chromium.org <eaugusti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-25 23:34:31 +0000
commit771baf0c6d0a97c3a10eb6448c2161daf351fb40 (patch)
treee95f17214e578748cc5a99bfdae5a67d8b6052d1
parentf6f72fb8adde6f5c901fd887e275831df8de3b58 (diff)
downloadchromium_src-771baf0c6d0a97c3a10eb6448c2161daf351fb40.zip
chromium_src-771baf0c6d0a97c3a10eb6448c2161daf351fb40.tar.gz
chromium_src-771baf0c6d0a97c3a10eb6448c2161daf351fb40.tar.bz2
Uses the result of injected js as an optional parameter to an optional callback.
This feature requires changes to WebKitt. The diff for these changes are here: https://gist.github.com/1732015 BUG=22349 Review URL: https://chromiumcodereview.appspot.com/9325032 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@144055 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/api/tabs/execute_code_in_tab_function.cc14
-rw-r--r--chrome/browser/extensions/api/tabs/execute_code_in_tab_function.h12
-rw-r--r--chrome/browser/extensions/api/tabs/tabs.cc3
-rw-r--r--chrome/browser/extensions/api/tabs/tabs.h3
-rw-r--r--chrome/browser/extensions/execute_script_apitest.cc6
-rw-r--r--chrome/browser/extensions/script_badge_controller.cc5
-rw-r--r--chrome/browser/extensions/script_badge_controller.h7
-rw-r--r--chrome/browser/extensions/script_executor.h11
-rw-r--r--chrome/browser/extensions/script_executor_impl.cc14
-rw-r--r--chrome/common/extensions/api/tabs.json10
-rw-r--r--chrome/common/extensions/docs/extensions/tabs.html33
-rw-r--r--chrome/common/extensions/extension_messages.h5
-rw-r--r--chrome/renderer/extensions/extension_helper.cc5
-rw-r--r--chrome/renderer/extensions/user_script_scheduler.cc44
-rw-r--r--chrome/test/data/extensions/api_test/executescript/callback/manifest.json10
-rw-r--r--chrome/test/data/extensions/api_test/executescript/callback/test.html1
-rw-r--r--chrome/test/data/extensions/api_test/executescript/callback/test.js91
17 files changed, 246 insertions, 28 deletions
diff --git a/chrome/browser/extensions/api/tabs/execute_code_in_tab_function.cc b/chrome/browser/extensions/api/tabs/execute_code_in_tab_function.cc
index cdcbd0d..b967b10 100644
--- a/chrome/browser/extensions/api/tabs/execute_code_in_tab_function.cc
+++ b/chrome/browser/extensions/api/tabs/execute_code_in_tab_function.cc
@@ -143,7 +143,8 @@ bool ExecuteCodeInTabFunction::RunImpl() {
void ExecuteCodeInTabFunction::OnExecuteCodeFinished(bool success,
int32 page_id,
- const std::string& error) {
+ const std::string& error,
+ const ListValue& result) {
if (!error.empty()) {
CHECK(!success);
error_ = error;
@@ -152,6 +153,17 @@ void ExecuteCodeInTabFunction::OnExecuteCodeFinished(bool success,
SendResponse(success);
}
+
+void TabsExecuteScriptFunction::OnExecuteCodeFinished(bool success,
+ int32 page_id,
+ const std::string& error,
+ const ListValue& result) {
+ if (error.empty())
+ result_.reset(result.DeepCopy());
+ ExecuteCodeInTabFunction::OnExecuteCodeFinished(success, page_id, error,
+ result);
+}
+
void ExecuteCodeInTabFunction::DidLoadFile(bool success,
const std::string& data) {
std::string function_name = name();
diff --git a/chrome/browser/extensions/api/tabs/execute_code_in_tab_function.h b/chrome/browser/extensions/api/tabs/execute_code_in_tab_function.h
index 5c97e3e..a954ede 100644
--- a/chrome/browser/extensions/api/tabs/execute_code_in_tab_function.h
+++ b/chrome/browser/extensions/api/tabs/execute_code_in_tab_function.h
@@ -23,12 +23,13 @@ class ExecuteCodeInTabFunction : public AsyncExtensionFunction {
// ExtensionFunction:
virtual bool RunImpl() OVERRIDE;
- private:
// Message handler.
- void OnExecuteCodeFinished(bool success,
- int32 page_id,
- const std::string& error);
+ virtual void OnExecuteCodeFinished(bool success,
+ int32 page_id,
+ const std::string& error,
+ const ListValue& script_result);
+ private:
// Called when contents from the file whose path is specified in JSON
// arguments has been loaded.
void DidLoadFile(bool success, const std::string& data);
@@ -66,6 +67,9 @@ class ExecuteCodeInTabFunction : public AsyncExtensionFunction {
class TabsExecuteScriptFunction : public ExecuteCodeInTabFunction {
private:
virtual ~TabsExecuteScriptFunction() {}
+ virtual void OnExecuteCodeFinished(bool success, int32 page_id,
+ const std::string& error,
+ const ListValue& script_result) OVERRIDE;
DECLARE_EXTENSION_FUNCTION_NAME("tabs.executeScript")
};
diff --git a/chrome/browser/extensions/api/tabs/tabs.cc b/chrome/browser/extensions/api/tabs/tabs.cc
index 8b2ed1b..f245e17 100644
--- a/chrome/browser/extensions/api/tabs/tabs.cc
+++ b/chrome/browser/extensions/api/tabs/tabs.cc
@@ -1363,7 +1363,8 @@ void UpdateTabFunction::PopulateResult() {
void UpdateTabFunction::OnExecuteCodeFinished(bool success,
int32 page_id,
- const std::string& error) {
+ const std::string& error,
+ const ListValue& script_result) {
if (!error.empty()) {
CHECK(!success);
error_ = error;
diff --git a/chrome/browser/extensions/api/tabs/tabs.h b/chrome/browser/extensions/api/tabs/tabs.h
index 14276a0..f44e4e2 100644
--- a/chrome/browser/extensions/api/tabs/tabs.h
+++ b/chrome/browser/extensions/api/tabs/tabs.h
@@ -131,7 +131,8 @@ class UpdateTabFunction : public AsyncExtensionFunction {
virtual bool RunImpl() OVERRIDE;
void OnExecuteCodeFinished(bool success,
int32 page_id,
- const std::string& error);
+ const std::string& error,
+ const ListValue& script_result);
DECLARE_EXTENSION_FUNCTION_NAME("tabs.update")
};
diff --git a/chrome/browser/extensions/execute_script_apitest.cc b/chrome/browser/extensions/execute_script_apitest.cc
index 0594c79..1edb440 100644
--- a/chrome/browser/extensions/execute_script_apitest.cc
+++ b/chrome/browser/extensions/execute_script_apitest.cc
@@ -78,3 +78,9 @@ IN_PROC_BROWSER_TEST_F(ExecuteScriptApiTest, ExecuteScriptRunAt) {
ASSERT_TRUE(StartTestServer());
ASSERT_TRUE(RunExtensionTest("executescript/run_at")) << message_;
}
+
+IN_PROC_BROWSER_TEST_F(ExecuteScriptApiTest, ExecuteScriptCallback) {
+ SetupDelayedHostResolver();
+ ASSERT_TRUE(StartTestServer());
+ ASSERT_TRUE(RunExtensionTest("executescript/callback")) << message_;
+}
diff --git a/chrome/browser/extensions/script_badge_controller.cc b/chrome/browser/extensions/script_badge_controller.cc
index e15b259..bb655a6 100644
--- a/chrome/browser/extensions/script_badge_controller.cc
+++ b/chrome/browser/extensions/script_badge_controller.cc
@@ -88,13 +88,14 @@ void ScriptBadgeController::OnExecuteScriptFinished(
const ExecuteScriptCallback& callback,
bool success,
int32 page_id,
- const std::string& error) {
+ const std::string& error,
+ const base::ListValue& script_results) {
if (success && page_id == GetPageID()) {
if (InsertExtension(extension_id))
Notify();
}
- callback.Run(success, page_id, error);
+ callback.Run(success, page_id, error, script_results);
}
ExtensionService* ScriptBadgeController::GetExtensionService() {
diff --git a/chrome/browser/extensions/script_badge_controller.h b/chrome/browser/extensions/script_badge_controller.h
index 420e666b..7ae4b6c 100644
--- a/chrome/browser/extensions/script_badge_controller.h
+++ b/chrome/browser/extensions/script_badge_controller.h
@@ -24,6 +24,10 @@ class ExtensionAction;
class ExtensionService;
class TabContents;
+namespace base {
+class ListValue;
+}
+
namespace IPC {
class Message;
}
@@ -79,7 +83,8 @@ class ScriptBadgeController
const ExecuteScriptCallback& callback,
bool success,
int32 page_id,
- const std::string& error);
+ const std::string& error,
+ const base::ListValue& script_result);
// Gets the ExtensionService for |tab_contents_|.
ExtensionService* GetExtensionService();
diff --git a/chrome/browser/extensions/script_executor.h b/chrome/browser/extensions/script_executor.h
index 2119cc6..93c423e 100644
--- a/chrome/browser/extensions/script_executor.h
+++ b/chrome/browser/extensions/script_executor.h
@@ -11,6 +11,10 @@
#include "base/callback_forward.h"
#include "chrome/common/extensions/user_script.h"
+namespace base {
+ class ListValue;
+}
+
namespace content {
class WebContents;
}
@@ -42,9 +46,10 @@ class ScriptExecutor {
ISOLATED_WORLD,
};
- // Callback from ExecuteScript. The arguments are (success, page_id, error).
- // page_id is only valid on success, error is only valid on !success.
- typedef base::Callback<void(bool, int32, const std::string&)>
+ // Callback from ExecuteScript. The arguments are (success, page_id, error,
+ // result). page_id is only valid on success, error is only valid on !success.
+ typedef base::Callback<void(bool, int32, const std::string&,
+ const base::ListValue&)>
ExecuteScriptCallback;
// Executes a script. The arguments match ExtensionMsg_ExecuteCode_Params in
diff --git a/chrome/browser/extensions/script_executor_impl.cc b/chrome/browser/extensions/script_executor_impl.cc
index e8f6199..ae8c251 100644
--- a/chrome/browser/extensions/script_executor_impl.cc
+++ b/chrome/browser/extensions/script_executor_impl.cc
@@ -14,6 +14,10 @@
#include "ipc/ipc_message.h"
#include "ipc/ipc_message_macros.h"
+namespace base {
+class ListValue;
+} // namespace base
+
namespace extensions {
namespace {
@@ -58,7 +62,8 @@ class Handler : public content::WebContentsObserver {
}
virtual void WebContentsDestroyed(content::WebContents* tab) OVERRIDE {
- callback_.Run(false, -1, kRendererDestroyed);
+ base::ListValue val;
+ callback_.Run(false, -1, kRendererDestroyed, val);
delete this;
}
@@ -66,8 +71,9 @@ class Handler : public content::WebContentsObserver {
void OnExecuteCodeFinished(int request_id,
bool success,
int32 page_id,
- const std::string& error) {
- callback_.Run(success, page_id, error);
+ const std::string& error,
+ const base::ListValue& script_result) {
+ callback_.Run(success, page_id, error, script_result);
delete this;
}
@@ -98,7 +104,7 @@ void ScriptExecutorImpl::ExecuteScript(
params.is_javascript = (script_type == JAVASCRIPT);
params.code = code;
params.all_frames = (frame_scope == ALL_FRAMES);
- params.run_at = (int) run_at;
+ params.run_at = static_cast<int>(run_at);
params.in_main_world = (world_type == MAIN_WORLD);
// Handler handles IPCs and deletes itself on completion.
diff --git a/chrome/common/extensions/api/tabs.json b/chrome/common/extensions/api/tabs.json
index bb94fef..ccf137a 100644
--- a/chrome/common/extensions/api/tabs.json
+++ b/chrome/common/extensions/api/tabs.json
@@ -620,7 +620,15 @@
"name": "callback",
"optional": true,
"description": "Called after all the JavaScript has been executed.",
- "parameters": []
+ "parameters": [
+ {
+ "name": "result",
+ "optional": true,
+ "type": "array",
+ "items": {"type": "any", "minimum": 0},
+ "description": "The result of the script in every injected frame."
+ }
+ ]
}
]
},
diff --git a/chrome/common/extensions/docs/extensions/tabs.html b/chrome/common/extensions/docs/extensions/tabs.html
index a94b5b2..89bde6f 100644
--- a/chrome/common/extensions/docs/extensions/tabs.html
+++ b/chrome/common/extensions/docs/extensions/tabs.html
@@ -1209,8 +1209,39 @@ For other examples and for help in viewing the source code, see
specify a function that looks like this:
</p>
<!-- Note: intentionally longer 80 columns -->
- <pre>function(<span></span>) <span class="subdued">{...}</span>;</pre>
+ <pre>function(<span>array of any result</span>) <span class="subdued">{...}</span>;</pre>
<dl>
+ <div>
+ <div>
+ <dt>
+ <var>result</var>
+ <em>
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span id="typeTemplate">
+ <span>
+ <span>
+ array of <span><span>
+ <span>
+ <span>any</span>
+ </span>
+ </span></span>
+ </span>
+ </span>
+ </span>
+ )
+ </div>
+ </em>
+ </dt>
+ <dd>The result of the script in every injected frame.</dd>
+ <!-- OBJECT PROPERTIES -->
+ <!-- OBJECT METHODS -->
+ <!-- OBJECT EVENT FIELDS -->
+ <!-- FUNCTION PARAMETERS -->
+ </div>
+ </div>
</dl>
</div>
</div>
diff --git a/chrome/common/extensions/extension_messages.h b/chrome/common/extensions/extension_messages.h
index ae2b7f9..dfc8df9 100644
--- a/chrome/common/extensions/extension_messages.h
+++ b/chrome/common/extensions/extension_messages.h
@@ -408,11 +408,12 @@ IPC_SYNC_MESSAGE_CONTROL1_1(ExtensionHostMsg_GetMessageBundle,
SubstitutionMap /* message bundle */)
// Sent from the renderer to the browser to return the script running result.
-IPC_MESSAGE_ROUTED4(ExtensionHostMsg_ExecuteCodeFinished,
+IPC_MESSAGE_ROUTED5(ExtensionHostMsg_ExecuteCodeFinished,
int /* request id */,
bool /* whether the script ran successfully */,
int32 /* page_id the code executed on, if successful */,
- std::string /* error message, if unsuccessful */)
+ std::string /* error message, if unsuccessful */,
+ ListValue /* result of the script */)
// Sent from the renderer to the browser to notify that content scripts are
// running in the renderer that the IPC originated from.
diff --git a/chrome/renderer/extensions/extension_helper.cc b/chrome/renderer/extensions/extension_helper.cc
index 24d3dc2..67be4a62 100644
--- a/chrome/renderer/extensions/extension_helper.cc
+++ b/chrome/renderer/extensions/extension_helper.cc
@@ -11,6 +11,7 @@
#include "base/lazy_instance.h"
#include "base/message_loop.h"
#include "base/utf_string_conversions.h"
+#include "base/values.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension_messages.h"
#include "chrome/common/render_messages.h"
@@ -111,7 +112,6 @@ class ExtensionViewAccumulator : public content::RenderViewVisitor {
chrome::ViewType view_type_;
std::vector<content::RenderView*> views_;
};
-
}
// static
@@ -339,8 +339,9 @@ void ExtensionHelper::OnExecuteCode(
WebView* webview = render_view()->GetWebView();
WebFrame* main_frame = webview->mainFrame();
if (!main_frame) {
+ ListValue val;
Send(new ExtensionHostMsg_ExecuteCodeFinished(
- routing_id(), params.request_id, false, -1, ""));
+ routing_id(), params.request_id, false, -1, "", val));
return;
}
diff --git a/chrome/renderer/extensions/user_script_scheduler.cc b/chrome/renderer/extensions/user_script_scheduler.cc
index dc4ebee..8fb5554 100644
--- a/chrome/renderer/extensions/user_script_scheduler.cc
+++ b/chrome/renderer/extensions/user_script_scheduler.cc
@@ -5,6 +5,7 @@
#include "chrome/renderer/extensions/user_script_scheduler.h"
#include "base/bind.h"
+#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "chrome/common/extensions/extension_error_utils.h"
#include "chrome/common/extensions/extension_manifest_constants.h"
@@ -14,10 +15,13 @@
#include "chrome/renderer/extensions/extension_helper.h"
#include "chrome/renderer/extensions/user_script_slave.h"
#include "content/public/renderer/render_view.h"
+#include "content/public/renderer/v8_value_converter.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebVector.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
+#include "v8/include/v8.h"
namespace {
// The length of time to wait after the DOM is complete to try and run user
@@ -28,6 +32,7 @@ const int kUserScriptIdleTimeoutMs = 200;
using WebKit::WebDocument;
using WebKit::WebFrame;
using WebKit::WebString;
+using WebKit::WebVector;
using WebKit::WebView;
using extensions::Extension;
@@ -134,12 +139,14 @@ void UserScriptScheduler::ExecuteCodeImpl(
content::RenderView* render_view =
content::RenderView::FromWebView(frame_->view());
ExtensionHelper* extension_helper = ExtensionHelper::Get(render_view);
+ base::ListValue execution_results;
// Since extension info is sent separately from user script info, they can
// be out of sync. We just ignore this situation.
if (!extension) {
render_view->Send(new ExtensionHostMsg_ExecuteCodeFinished(
- render_view->GetRoutingID(), params.request_id, true, -1, ""));
+ render_view->GetRoutingID(), params.request_id, true, -1, "",
+ execution_results));
return;
}
@@ -176,21 +183,47 @@ void UserScriptScheduler::ExecuteCodeImpl(
-1,
ExtensionErrorUtils::FormatErrorMessage(
extension_manifest_errors::kCannotAccessPage,
- frame->document().url().spec())));
+ frame->document().url().spec()),
+ execution_results));
return;
}
}
WebScriptSource source(WebString::fromUTF8(params.code));
+ v8::HandleScope scope;
+ v8::Persistent<v8::Context> persistent_context = v8::Context::New();
+ v8::Local<v8::Context> context =
+ v8::Local<v8::Context>::New(persistent_context);
+ persistent_context.Dispose();
+ scoped_ptr<content::V8ValueConverter> v8_converter(
+ content::V8ValueConverter::create());
+ v8_converter->SetUndefinedAllowed(true);
+ v8::Handle<v8::Value> script_value;
if (params.in_main_world) {
- frame->executeScript(source);
+ script_value = frame->executeScriptAndReturnValue(source);
} else {
+ WebKit::WebVector<v8::Local<v8::Value> > results;
std::vector<WebScriptSource> sources;
sources.push_back(source);
frame->executeScriptInIsolatedWorld(
extension_dispatcher_->user_script_slave()->
GetIsolatedWorldIdForExtension(extension, frame),
- &sources.front(), sources.size(), EXTENSION_GROUP_CONTENT_SCRIPTS);
+ &sources.front(), sources.size(), EXTENSION_GROUP_CONTENT_SCRIPTS,
+ &results);
+ // We only expect one value back since we only pushed one source
+ if (results.size() == 1 && !results[0].IsEmpty())
+ script_value = results[0];
+ }
+ if (!script_value.IsEmpty()) {
+ base::Value* base_val = NULL;
+ // Don't try and convert non-pure JS objects.
+ if (!script_value->IsObject() ||
+ script_value->ToObject()->InternalFieldCount() == 0)
+ base_val = v8_converter->FromV8Value(script_value, context);
+ if (!base_val)
+ base_val = base::Value::CreateNullValue();
+ execution_results.Append(base_val);
+ script_value.Clear();
}
} else {
frame->document().insertUserStyleSheet(
@@ -205,7 +238,8 @@ void UserScriptScheduler::ExecuteCodeImpl(
params.request_id,
true,
render_view->GetPageId(),
- ""));
+ "",
+ execution_results));
}
bool UserScriptScheduler::GetAllChildFrames(
diff --git a/chrome/test/data/extensions/api_test/executescript/callback/manifest.json b/chrome/test/data/extensions/api_test/executescript/callback/manifest.json
new file mode 100644
index 0000000..b5162e7
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/executescript/callback/manifest.json
@@ -0,0 +1,10 @@
+{
+ "version": "1.0.0.0",
+ "manifest_version": 2,
+ "name": "callback test",
+ "description": "Test that executeScript uses the result of the evaluated script in the callback.",
+ "background": {
+ "scripts": ["test.js"]
+ },
+ "permissions": ["tabs", "http://b.com/"]
+}
diff --git a/chrome/test/data/extensions/api_test/executescript/callback/test.html b/chrome/test/data/extensions/api_test/executescript/callback/test.html
new file mode 100644
index 0000000..18ecdcb
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/executescript/callback/test.html
@@ -0,0 +1 @@
+<html></html>
diff --git a/chrome/test/data/extensions/api_test/executescript/callback/test.js b/chrome/test/data/extensions/api_test/executescript/callback/test.js
new file mode 100644
index 0000000..0474938
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/executescript/callback/test.js
@@ -0,0 +1,91 @@
+// Copyright (c) 2012 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.
+
+var relativePath =
+ '/files/extensions/api_test/executescript/callback/test.html';
+var testUrl = 'http://b.com:PORT' + relativePath;
+
+chrome.test.getConfig(function(config) {
+ testUrl = testUrl.replace(/PORT/, config.testServer.port);
+ chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
+ if (changeInfo.status != 'complete')
+ return;
+ chrome.tabs.onUpdated.removeListener(arguments.callee);
+ chrome.test.runTests([
+
+ function executeCallbackIntShouldSucceed() {
+ var scriptDetails = {code: '3'};
+ chrome.tabs.executeScript(tabId, scriptDetails, function(scriptVal) {
+ chrome.tabs.get(tabId, chrome.test.callbackPass(function(tab) {
+ chrome.test.assertEq(3, scriptVal[0]);
+ }));
+ });
+ },
+
+ function executeCallbackDoubleShouldSucceed() {
+ var scriptDetails = {code: '1.4'};
+ chrome.tabs.executeScript(tabId, scriptDetails, function(scriptVal) {
+ chrome.tabs.get(tabId, chrome.test.callbackPass(function(tab) {
+ chrome.test.assertEq(1.4, scriptVal[0]);
+ }));
+ });
+ },
+
+ function executeCallbackStringShouldSucceed() {
+ var scriptDetails = {code: '"foobar"'};
+ chrome.tabs.executeScript(tabId, scriptDetails, function(scriptVal) {
+ chrome.tabs.get(tabId, chrome.test.callbackPass(function(tab) {
+ chrome.test.assertEq('foobar', scriptVal[0]);
+ }));
+ });
+ },
+
+ function executeCallbackTrueShouldSucceed() {
+ var scriptDetails = {code: 'true'};
+ chrome.tabs.executeScript(tabId, scriptDetails, function(scriptVal) {
+ chrome.tabs.get(tabId, chrome.test.callbackPass(function(tab) {
+ chrome.test.assertEq(true, scriptVal[0]);
+ }));
+ });
+ },
+
+ function executeCallbackFalseShouldSucceed() {
+ var scriptDetails = {code: 'false'};
+ chrome.tabs.executeScript(tabId, scriptDetails, function(scriptVal) {
+ chrome.tabs.get(tabId, chrome.test.callbackPass(function(tab) {
+ chrome.test.assertEq(false, scriptVal[0]);
+ }));
+ });
+ },
+
+ function executeCallbackNullShouldSucceed() {
+ var scriptDetails = {code: 'null'};
+ chrome.tabs.executeScript(tabId, scriptDetails, function(scriptVal) {
+ chrome.tabs.get(tabId, chrome.test.callbackPass(function(tab) {
+ chrome.test.assertEq(null, scriptVal[0]);
+ }));
+ });
+ },
+
+ function executeCallbackArrayShouldSucceed() {
+ var scriptDetails = {code: '[1, "5", false, null]'};
+ chrome.tabs.executeScript(tabId, scriptDetails, function(scriptVal) {
+ chrome.tabs.get(tabId, chrome.test.callbackPass(function(tab) {
+ chrome.test.assertEq([1, "5", false, null], scriptVal[0]);
+ }));
+ });
+ },
+
+ function executeCallbackObjShouldSucceed() {
+ var scriptDetails = {code: 'var obj = {"id": "foo", "bar": 9}; obj'};
+ chrome.tabs.executeScript(tabId, scriptDetails, function(scriptVal) {
+ chrome.tabs.get(tabId, chrome.test.callbackPass(function(tab) {
+ chrome.test.assertEq({"id": "foo", "bar": 9}, scriptVal[0]);
+ }));
+ });
+ }
+ ]);
+ });
+ chrome.tabs.create({ url: testUrl });
+});