diff options
-rw-r--r-- | chrome/browser/debugger/debugger_remote_service.cc | 6 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_view_host.cc | 27 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_view_host.h | 6 | ||||
-rw-r--r-- | chrome/browser/renderer_host/test/render_view_host_browsertest.cc | 93 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 | ||||
-rw-r--r-- | chrome/common/notification_type.h | 8 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 20 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 29 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 12 |
9 files changed, 179 insertions, 23 deletions
diff --git a/chrome/browser/debugger/debugger_remote_service.cc b/chrome/browser/debugger/debugger_remote_service.cc index 4c3341b..3d102d5 100644 --- a/chrome/browser/debugger/debugger_remote_service.cc +++ b/chrome/browser/debugger/debugger_remote_service.cc @@ -331,9 +331,7 @@ bool DebuggerRemoteService::DispatchEvaluateJavascript( } std::string javascript; content->GetString(kDataKey, &javascript); - render_view_host->Send( - new ViewMsg_ScriptEvalRequest(render_view_host->routing_id(), - L"", - UTF8ToWide(javascript))); + render_view_host->ExecuteJavascriptInWebFrame(std::wstring(), + UTF8ToWide(javascript)); return false; } diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index de32b0c..a702b08 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -14,6 +14,7 @@ #include "base/stats_counters.h" #include "base/string_util.h" #include "base/time.h" +#include "base/values.h" #include "chrome/browser/blocked_plugin_manager.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/child_process_security_policy.h" @@ -490,8 +491,20 @@ void RenderViewHost::ReservePageIDRange(int size) { } void RenderViewHost::ExecuteJavascriptInWebFrame( - const std::wstring& frame_xpath, const std::wstring& jscript) { - Send(new ViewMsg_ScriptEvalRequest(routing_id(), frame_xpath, jscript)); + const std::wstring& frame_xpath, + const std::wstring& jscript) { + Send(new ViewMsg_ScriptEvalRequest(routing_id(), WideToUTF16(frame_xpath), + WideToUTF16(jscript), + 0, false)); +} + +int RenderViewHost::ExecuteJavascriptInWebFrameNotifyResult( + const string16& frame_xpath, + const string16& jscript) { + static int next_id = 1; + Send(new ViewMsg_ScriptEvalRequest(routing_id(), frame_xpath, jscript, + next_id, true)); + return next_id++; } void RenderViewHost::InsertCSSInWebFrame( @@ -871,6 +884,7 @@ void RenderViewHost::OnMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER(ViewHostMsg_SetSuggestResult, OnSetSuggestResult) IPC_MESSAGE_HANDLER(ViewHostMsg_DetectedPhishingSite, OnDetectedPhishingSite) + IPC_MESSAGE_HANDLER(ViewHostMsg_ScriptEvalResponse, OnScriptEvalResponse) // Have the super handle all other messages. IPC_MESSAGE_UNHANDLED(RenderWidgetHost::OnMessageReceived(msg)) IPC_END_MESSAGE_MAP_EX() @@ -2102,3 +2116,12 @@ void RenderViewHost::OnDetectedPhishingSite(const GURL& phishing_url, // TODO(noelutz): send an HTTP request to the client-side detection frontends // to confirm that the URL is really phishing. } + +void RenderViewHost::OnScriptEvalResponse(int id, bool result) { + scoped_ptr<Value> result_value(Value::CreateBooleanValue(result)); + std::pair<int, Value*> details(id, result_value.get()); + NotificationService::current()->Notify( + NotificationType::EXECUTE_JAVASCRIPT_RESULT, + Source<RenderViewHost>(this), + Details<std::pair<int, Value*> >(&details)); +} diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h index e5f09ff..b9bf703 100644 --- a/chrome/browser/renderer_host/render_view_host.h +++ b/chrome/browser/renderer_host/render_view_host.h @@ -252,6 +252,11 @@ class RenderViewHost : public RenderWidgetHost { void ExecuteJavascriptInWebFrame(const std::wstring& frame_xpath, const std::wstring& jscript); + // Runs some javascript within the context of a frame in the page. The result + // is sent back via the notification EXECUTE_JAVASCRIPT_RESULT. + int ExecuteJavascriptInWebFrameNotifyResult(const string16& frame_xpath, + const string16& jscript); + // Insert some css into a frame in the page. |id| is optional, and specifies // the element id given when inserting/replacing the style element. void InsertCSSInWebFrame(const std::wstring& frame_xpath, @@ -688,6 +693,7 @@ class RenderViewHost : public RenderWidgetHost { void OnDetectedPhishingSite(const GURL& phishing_url, double phishing_score, const SkBitmap& thumbnail); + void OnScriptEvalResponse(int id, bool result); private: friend class TestRenderViewHost; diff --git a/chrome/browser/renderer_host/test/render_view_host_browsertest.cc b/chrome/browser/renderer_host/test/render_view_host_browsertest.cc new file mode 100644 index 0000000..b75c09b --- /dev/null +++ b/chrome/browser/renderer_host/test/render_view_host_browsertest.cc @@ -0,0 +1,93 @@ +// Copyright (c) 2010 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 "base/utf_string_conversions.h" +#include "base/values.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/renderer_host/render_view_host.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/test/in_process_browser_test.h" +#include "chrome/test/ui_test_utils.h" +#include "net/test/test_server.h" + +typedef InProcessBrowserTest RenderViewHostTest; + +typedef std::pair<int, Value*> ExecuteDetailType; + +namespace { + +// NotificationObserver used to listen for EXECUTE_JAVASCRIPT_RESULT +// notifications. +class ExecuteNotificationObserver : public NotificationObserver { + public: + ExecuteNotificationObserver() : id_(0) {} + + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + id_ = (static_cast<Details<ExecuteDetailType > >(details))->first; + Value* value = (static_cast<Details<ExecuteDetailType > >(details))->second; + if (value) + value_.reset(value->DeepCopy()); + MessageLoopForUI::current()->Quit(); + } + + int id() const { return id_; } + + Value* value() const { return value_.get(); } + + private: + int id_; + scoped_ptr<Value> value_; + + DISALLOW_COPY_AND_ASSIGN(ExecuteNotificationObserver); +}; + +} // namespace + +// Makes sure ExecuteJavascriptInWebFrameNotifyResult works. +IN_PROC_BROWSER_TEST_F(RenderViewHostTest, + ExecuteJavascriptInWebFrameNotifyResult) { + ASSERT_TRUE(test_server()->Start()); + GURL empty_url(test_server()->GetURL("files/empty.html")); + ui_test_utils::NavigateToURL(browser(), empty_url); + RenderViewHost* rvh = browser()->GetSelectedTabContents()->render_view_host(); + ASSERT_TRUE(rvh); + + // Execute the script 'true' and make sure we get back true. + int execute_id = rvh->ExecuteJavascriptInWebFrameNotifyResult( + string16(), + ASCIIToUTF16("true;")); + { + ExecuteNotificationObserver observer; + ui_test_utils::RegisterAndWait( + &observer, + NotificationType::EXECUTE_JAVASCRIPT_RESULT, + Source<RenderViewHost>(rvh)); + EXPECT_EQ(execute_id, observer.id()); + ASSERT_TRUE(observer.value()); + bool bool_value; + ASSERT_TRUE(observer.value()->GetAsBoolean(&bool_value)); + EXPECT_TRUE(bool_value); + } + + // Execute the script 'false' and make sure we get back false. + int execute_id2 = rvh->ExecuteJavascriptInWebFrameNotifyResult( + string16(), + ASCIIToUTF16("false;")); + // The ids should change. + EXPECT_NE(execute_id, execute_id2); + { + ExecuteNotificationObserver observer; + ui_test_utils::RegisterAndWait( + &observer, + NotificationType::EXECUTE_JAVASCRIPT_RESULT, + Source<RenderViewHost>(rvh)); + EXPECT_EQ(execute_id2, observer.id()); + ASSERT_TRUE(observer.value()); + bool bool_value; + ASSERT_TRUE(observer.value()->GetAsBoolean(&bool_value)); + EXPECT_FALSE(bool_value); + } +} diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 70cea2d..9040353 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1970,6 +1970,7 @@ 'browser/popup_blocker_browsertest.cc', 'browser/printing/print_dialog_cloud_uitest.cc', 'browser/renderer_host/test/render_process_host_browsertest.cc', + 'browser/renderer_host/test/render_view_host_browsertest.cc', 'browser/renderer_host/test/render_view_host_manager_browsertest.cc', 'browser/renderer_host/test/renderer_accessibility_browsertest.cc', 'browser/renderer_host/test/web_cache_manager_browsertest.cc', diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h index bd3ebcd..5febed7 100644 --- a/chrome/common/notification_type.h +++ b/chrome/common/notification_type.h @@ -494,6 +494,14 @@ class NotificationType { // view host for the page, there are no details. FOCUS_CHANGED_IN_PAGE, + // Notification posted from ExecuteJavascriptInWebFrameNotifyResult. The + // source is the RenderViewHost ExecuteJavascriptInWebFrameNotifyResult was + // invoked on. The details are a std::pair<int, Value*> with the int giving + // the id returned from ExecuteJavascriptInWebFrameNotifyResult and the + // Value the results of the javascript expression. The Value is owned by + // RenderViewHost. + EXECUTE_JAVASCRIPT_RESULT, + // BackgroundContents ------------------------------------------------------ // A new background contents was opened by script. The source is the parent diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 349c423..b2cb0bf 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -370,9 +370,16 @@ IPC_BEGIN_MESSAGES(View) // jscript_url is the string containing the javascript: url to be executed // in the target frame's context. The string should start with "javascript:" // and continue with a valid JS text. - IPC_MESSAGE_ROUTED2(ViewMsg_ScriptEvalRequest, - std::wstring, /* frame_xpath */ - std::wstring /* jscript_url */) + // + // If the fourth parameter is true the result is sent back to the renderer + // using the message ViewHostMsg_ScriptEvalResponse. + // ViewHostMsg_ScriptEvalResponse is passed the ID parameter so that the + // client can uniquely identify the request. + IPC_MESSAGE_ROUTED4(ViewMsg_ScriptEvalRequest, + string16, /* frame_xpath */ + string16, /* jscript_url */ + int, /* ID */ + bool /* If true, result is sent back. */) // Request for the renderer to evaluate an xpath to a frame and insert css // into that frame's document. See ViewMsg_ScriptEvalRequest for details on @@ -2925,4 +2932,11 @@ IPC_BEGIN_MESSAGES(ViewHost) double /* phishing_score */, SkBitmap /* thumbnail */) + // Response from ViewMsg_ScriptEvalRequest. The ID is the parameter supplied + // to ViewMsg_ScriptEvalRequest. The result is true if the script evaluated + // to the boolean result true, false otherwise. + IPC_MESSAGE_ROUTED2(ViewHostMsg_ScriptEvalResponse, + int /* id */, + bool /* result */) + IPC_END_MESSAGES(ViewHost) diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index ab4336a..38a44f3 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -143,6 +143,7 @@ #include "third_party/WebKit/WebKit/chromium/public/WebVector.h" #include "third_party/WebKit/WebKit/chromium/public/WebView.h" #include "third_party/WebKit/WebKit/chromium/public/WebWindowFeatures.h" +#include "v8/include/v8.h" #include "webkit/appcache/web_application_cache_host_impl.h" #include "webkit/glue/context_menu.h" #include "webkit/glue/dom_operations.h" @@ -4151,13 +4152,19 @@ void RenderView::SetSuggestResult(const std::string& suggest) { Send(new ViewHostMsg_SetSuggestResult(routing_id_, page_id_, suggest)); } -void RenderView::EvaluateScript(const std::wstring& frame_xpath, - const std::wstring& script) { - WebFrame* web_frame = GetChildFrame(frame_xpath); - if (!web_frame) - return; - - web_frame->executeScript(WebScriptSource(WideToUTF16Hack(script))); +void RenderView::EvaluateScript(const string16& frame_xpath, + const string16& script, + int id, + bool notify_result) { + v8::Handle<v8::Value> result; + WebFrame* web_frame = GetChildFrame(UTF16ToWideHack(frame_xpath)); + if (web_frame) + result = web_frame->executeScriptAndReturnValue(WebScriptSource(script)); + if (notify_result) { + bool bool_result = !result.IsEmpty() && result->IsBoolean() ? + result->BooleanValue() : false; + Send(new ViewHostMsg_ScriptEvalResponse(routing_id_, id, bool_result)); + } } void RenderView::InsertCSS(const std::wstring& frame_xpath, @@ -4199,9 +4206,11 @@ void RenderView::OnPepperPluginDestroy( } } -void RenderView::OnScriptEvalRequest(const std::wstring& frame_xpath, - const std::wstring& jscript) { - EvaluateScript(frame_xpath, jscript); +void RenderView::OnScriptEvalRequest(const string16& frame_xpath, + const string16& jscript, + int id, + bool notify_result) { + EvaluateScript(frame_xpath, jscript, id, notify_result); } void RenderView::OnCSSInsertRequest(const std::wstring& frame_xpath, diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 2292a3c..2fb488c 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -232,8 +232,10 @@ class RenderView : public RenderWidget, void SetSuggestResult(const std::string& suggest); // Evaluates a string of JavaScript in a particular frame. - void EvaluateScript(const std::wstring& frame_xpath, - const std::wstring& jscript); + void EvaluateScript(const string16& frame_xpath, + const string16& jscript, + int id, + bool notify_result); // Adds the given file chooser request to the file_chooser_completion_ queue // (see that var for more) and requests the chooser be displayed if there are @@ -828,8 +830,10 @@ class RenderView : public RenderWidget, void OnReservePageIDRange(int size_of_range); void OnResetPageEncodingToDefault(); void OnRevertTranslation(int page_id); - void OnScriptEvalRequest(const std::wstring& frame_xpath, - const std::wstring& jscript); + void OnScriptEvalRequest(const string16& frame_xpath, + const string16& jscript, + int id, + bool notify_result); void OnSelectAll(); void OnSetAccessibilityFocus(int acc_obj_id); void OnSetActive(bool active); |