Index: content/test/browser_test_utils.cc |
=================================================================== |
--- content/test/browser_test_utils.cc (revision 151499) |
+++ content/test/browser_test_utils.cc (working copy) |
@@ -1,499 +0,0 @@ |
-// 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. |
- |
-#include "content/public/test/browser_test_utils.h" |
- |
-#include "base/command_line.h" |
-#include "base/json/json_reader.h" |
-#include "base/path_service.h" |
-#include "base/process_util.h" |
-#include "base/rand_util.h" |
-#include "base/string_number_conversions.h" |
-#include "base/test/test_timeouts.h" |
-#include "base/utf_string_conversions.h" |
-#include "net/base/net_util.h" |
-#include "content/public/browser/dom_operation_notification_details.h" |
-#include "content/public/browser/notification_types.h" |
-#include "content/public/browser/render_process_host.h" |
-#include "content/public/browser/render_view_host.h" |
-#include "content/public/browser/web_contents.h" |
-#include "content/public/browser/web_contents_observer.h" |
-#include "content/public/browser/web_contents_view.h" |
-#include "content/public/test/test_utils.h" |
-#include "net/test/python_utils.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
- |
-static const int kDefaultWsPort = 8880; |
- |
-namespace content { |
- |
-namespace { |
- |
-class DOMOperationObserver : public NotificationObserver, |
- public WebContentsObserver { |
- public: |
- explicit DOMOperationObserver(RenderViewHost* render_view_host) |
- : WebContentsObserver(WebContents::FromRenderViewHost(render_view_host)), |
- did_respond_(false) { |
- registrar_.Add(this, NOTIFICATION_DOM_OPERATION_RESPONSE, |
- Source<RenderViewHost>(render_view_host)); |
- message_loop_runner_ = new MessageLoopRunner; |
- } |
- |
- virtual void Observe(int type, |
- const NotificationSource& source, |
- const NotificationDetails& details) OVERRIDE { |
- DCHECK(type == NOTIFICATION_DOM_OPERATION_RESPONSE); |
- Details<DomOperationNotificationDetails> dom_op_details(details); |
- response_ = dom_op_details->json; |
- did_respond_ = true; |
- message_loop_runner_->Quit(); |
- } |
- |
- // Overridden from WebContentsObserver: |
- virtual void RenderViewGone(base::TerminationStatus status) OVERRIDE { |
- message_loop_runner_->Quit(); |
- } |
- |
- bool WaitAndGetResponse(std::string* response) WARN_UNUSED_RESULT { |
- message_loop_runner_->Run(); |
- *response = response_; |
- return did_respond_; |
- } |
- |
- private: |
- NotificationRegistrar registrar_; |
- std::string response_; |
- bool did_respond_; |
- scoped_refptr<MessageLoopRunner> message_loop_runner_; |
- |
- DISALLOW_COPY_AND_ASSIGN(DOMOperationObserver); |
-}; |
- |
-// Specifying a prototype so that we can add the WARN_UNUSED_RESULT attribute. |
-bool ExecuteJavaScriptHelper(RenderViewHost* render_view_host, |
- const std::wstring& frame_xpath, |
- const std::wstring& original_script, |
- scoped_ptr<Value>* result) WARN_UNUSED_RESULT; |
- |
-// Executes the passed |original_script| in the frame pointed to by |
-// |frame_xpath|. If |result| is not NULL, stores the value that the evaluation |
-// of the script in |result|. Returns true on success. |
-bool ExecuteJavaScriptHelper(RenderViewHost* render_view_host, |
- const std::wstring& frame_xpath, |
- const std::wstring& original_script, |
- scoped_ptr<Value>* result) { |
- // TODO(jcampan): we should make the domAutomationController not require an |
- // automation id. |
- std::wstring script = L"window.domAutomationController.setAutomationId(0);" + |
- original_script; |
- DOMOperationObserver dom_op_observer(render_view_host); |
- render_view_host->ExecuteJavascriptInWebFrame(WideToUTF16Hack(frame_xpath), |
- WideToUTF16Hack(script)); |
- std::string json; |
- if (!dom_op_observer.WaitAndGetResponse(&json)) { |
- DLOG(ERROR) << "Cannot communicate with DOMOperationObserver."; |
- return false; |
- } |
- |
- // Nothing more to do for callers that ignore the returned JS value. |
- if (!result) |
- return true; |
- |
- base::JSONReader reader(base::JSON_ALLOW_TRAILING_COMMAS); |
- result->reset(reader.ReadToValue(json)); |
- if (!result->get()) { |
- DLOG(ERROR) << reader.GetErrorMessage(); |
- return false; |
- } |
- |
- return true; |
-} |
- |
-void BuildSimpleWebKeyEvent(WebKit::WebInputEvent::Type type, |
- ui::KeyboardCode key, |
- bool control, |
- bool shift, |
- bool alt, |
- bool command, |
- NativeWebKeyboardEvent* event) { |
- event->nativeKeyCode = 0; |
- event->windowsKeyCode = key; |
- event->setKeyIdentifierFromWindowsKeyCode(); |
- event->type = type; |
- event->modifiers = 0; |
- event->isSystemKey = false; |
- event->timeStampSeconds = base::Time::Now().ToDoubleT(); |
- event->skip_in_browser = true; |
- |
- if (type == WebKit::WebInputEvent::Char || |
- type == WebKit::WebInputEvent::RawKeyDown) { |
- event->text[0] = key; |
- event->unmodifiedText[0] = key; |
- } |
- |
- if (control) |
- event->modifiers |= WebKit::WebInputEvent::ControlKey; |
- |
- if (shift) |
- event->modifiers |= WebKit::WebInputEvent::ShiftKey; |
- |
- if (alt) |
- event->modifiers |= WebKit::WebInputEvent::AltKey; |
- |
- if (command) |
- event->modifiers |= WebKit::WebInputEvent::MetaKey; |
-} |
- |
-} // namespace |
- |
- |
-GURL GetFileUrlWithQuery(const FilePath& path, |
- const std::string& query_string) { |
- GURL url = net::FilePathToFileURL(path); |
- if (!query_string.empty()) { |
- GURL::Replacements replacements; |
- replacements.SetQueryStr(query_string); |
- return url.ReplaceComponents(replacements); |
- } |
- return url; |
-} |
- |
-void WaitForLoadStop(WebContents* web_contents) { |
- WindowedNotificationObserver load_stop_observer( |
- NOTIFICATION_LOAD_STOP, |
- Source<NavigationController>(&web_contents->GetController())); |
- // In many cases, the load may have finished before we get here. Only wait if |
- // the tab still has a pending navigation. |
- if (!web_contents->IsLoading()) |
- return; |
- load_stop_observer.Wait(); |
-} |
- |
-void CrashTab(WebContents* web_contents) { |
- RenderProcessHost* rph = web_contents->GetRenderProcessHost(); |
- WindowedNotificationObserver observer( |
- NOTIFICATION_RENDERER_PROCESS_CLOSED, |
- Source<RenderProcessHost>(rph)); |
- base::KillProcess(rph->GetHandle(), 0, false); |
- observer.Wait(); |
-} |
- |
-void SimulateMouseClick(WebContents* web_contents) { |
- int x = web_contents->GetView()->GetContainerSize().width() / 2; |
- int y = web_contents->GetView()->GetContainerSize().height() / 2; |
- WebKit::WebMouseEvent mouse_event; |
- mouse_event.type = WebKit::WebInputEvent::MouseDown; |
- mouse_event.button = WebKit::WebMouseEvent::ButtonLeft; |
- mouse_event.x = x; |
- mouse_event.y = y; |
- // Mac needs globalX/globalY for events to plugins. |
- gfx::Rect offset; |
- web_contents->GetView()->GetContainerBounds(&offset); |
- mouse_event.globalX = x + offset.x(); |
- mouse_event.globalY = y + offset.y(); |
- mouse_event.clickCount = 1; |
- web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event); |
- mouse_event.type = WebKit::WebInputEvent::MouseUp; |
- web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event); |
-} |
- |
-void SimulateMouseEvent(WebContents* web_contents, |
- WebKit::WebInputEvent::Type type, |
- const gfx::Point& point) { |
- WebKit::WebMouseEvent mouse_event; |
- mouse_event.type = type; |
- mouse_event.x = point.x(); |
- mouse_event.y = point.y(); |
- web_contents->GetRenderViewHost()->ForwardMouseEvent(mouse_event); |
-} |
- |
-void SimulateKeyPress(WebContents* web_contents, |
- ui::KeyboardCode key, |
- bool control, |
- bool shift, |
- bool alt, |
- bool command) { |
- NativeWebKeyboardEvent event_down; |
- BuildSimpleWebKeyEvent( |
- WebKit::WebInputEvent::RawKeyDown, key, control, shift, alt, command, |
- &event_down); |
- web_contents->GetRenderViewHost()->ForwardKeyboardEvent(event_down); |
- |
- NativeWebKeyboardEvent char_event; |
- BuildSimpleWebKeyEvent( |
- WebKit::WebInputEvent::Char, key, control, shift, alt, command, |
- &char_event); |
- web_contents->GetRenderViewHost()->ForwardKeyboardEvent(char_event); |
- |
- NativeWebKeyboardEvent event_up; |
- BuildSimpleWebKeyEvent( |
- WebKit::WebInputEvent::KeyUp, key, control, shift, alt, command, |
- &event_up); |
- web_contents->GetRenderViewHost()->ForwardKeyboardEvent(event_up); |
-} |
- |
-bool ExecuteJavaScript(RenderViewHost* render_view_host, |
- const std::wstring& frame_xpath, |
- const std::wstring& original_script) { |
- std::wstring script = |
- original_script + L";window.domAutomationController.send(0);"; |
- return ExecuteJavaScriptHelper(render_view_host, frame_xpath, script, NULL); |
-} |
- |
-bool ExecuteJavaScriptAndExtractInt(RenderViewHost* render_view_host, |
- const std::wstring& frame_xpath, |
- const std::wstring& script, |
- int* result) { |
- DCHECK(result); |
- scoped_ptr<Value> value; |
- if (!ExecuteJavaScriptHelper(render_view_host, frame_xpath, script, &value) || |
- !value.get()) |
- return false; |
- |
- return value->GetAsInteger(result); |
-} |
- |
-bool ExecuteJavaScriptAndExtractBool(RenderViewHost* render_view_host, |
- const std::wstring& frame_xpath, |
- const std::wstring& script, |
- bool* result) { |
- DCHECK(result); |
- scoped_ptr<Value> value; |
- if (!ExecuteJavaScriptHelper(render_view_host, frame_xpath, script, &value) || |
- !value.get()) |
- return false; |
- |
- return value->GetAsBoolean(result); |
-} |
- |
-bool ExecuteJavaScriptAndExtractString(RenderViewHost* render_view_host, |
- const std::wstring& frame_xpath, |
- const std::wstring& script, |
- std::string* result) { |
- DCHECK(result); |
- scoped_ptr<Value> value; |
- if (!ExecuteJavaScriptHelper(render_view_host, frame_xpath, script, &value) || |
- !value.get()) |
- return false; |
- |
- return value->GetAsString(result); |
-} |
- |
-TitleWatcher::TitleWatcher(WebContents* web_contents, |
- const string16& expected_title) |
- : web_contents_(web_contents), |
- expected_title_observed_(false), |
- quit_loop_on_observation_(false) { |
- EXPECT_TRUE(web_contents != NULL); |
- expected_titles_.push_back(expected_title); |
- notification_registrar_.Add(this, |
- NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED, |
- Source<WebContents>(web_contents)); |
- |
- // When navigating through the history, the restored NavigationEntry's title |
- // will be used. If the entry ends up having the same title after we return |
- // to it, as will usually be the case, the |
- // NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED will then be suppressed, since the |
- // NavigationEntry's title hasn't changed. |
- notification_registrar_.Add( |
- this, |
- NOTIFICATION_LOAD_STOP, |
- Source<NavigationController>(&web_contents->GetController())); |
-} |
- |
-void TitleWatcher::AlsoWaitForTitle(const string16& expected_title) { |
- expected_titles_.push_back(expected_title); |
-} |
- |
-TitleWatcher::~TitleWatcher() { |
-} |
- |
-const string16& TitleWatcher::WaitAndGetTitle() { |
- if (expected_title_observed_) |
- return observed_title_; |
- quit_loop_on_observation_ = true; |
- message_loop_runner_ = new MessageLoopRunner; |
- message_loop_runner_->Run(); |
- return observed_title_; |
-} |
- |
-void TitleWatcher::Observe(int type, |
- const NotificationSource& source, |
- const NotificationDetails& details) { |
- if (type == NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED) { |
- WebContents* source_contents = Source<WebContents>(source).ptr(); |
- ASSERT_EQ(web_contents_, source_contents); |
- } else if (type == NOTIFICATION_LOAD_STOP) { |
- NavigationController* controller = |
- Source<NavigationController>(source).ptr(); |
- ASSERT_EQ(&web_contents_->GetController(), controller); |
- } else { |
- FAIL() << "Unexpected notification received."; |
- } |
- |
- std::vector<string16>::const_iterator it = |
- std::find(expected_titles_.begin(), |
- expected_titles_.end(), |
- web_contents_->GetTitle()); |
- if (it == expected_titles_.end()) |
- return; |
- observed_title_ = *it; |
- expected_title_observed_ = true; |
- if (quit_loop_on_observation_) { |
- // Only call Quit once, on first Observe: |
- quit_loop_on_observation_ = false; |
- message_loop_runner_->Quit(); |
- } |
-} |
- |
-TestWebSocketServer::TestWebSocketServer() |
- : started_(false), |
- port_(kDefaultWsPort), |
- secure_(false) { |
-#if defined(OS_POSIX) |
- process_group_id_ = base::kNullProcessHandle; |
-#endif |
-} |
- |
-int TestWebSocketServer::UseRandomPort() { |
- port_ = base::RandInt(1024, 65535); |
- return port_; |
-} |
- |
-void TestWebSocketServer::UseTLS() { |
- secure_ = true; |
-} |
- |
-bool TestWebSocketServer::Start(const FilePath& root_directory) { |
- if (started_) |
- return true; |
- // Append CommandLine arguments after the server script, switches won't work. |
- scoped_ptr<CommandLine> cmd_line(CreateWebSocketServerCommandLine()); |
- cmd_line->AppendArg("--server=start"); |
- cmd_line->AppendArg("--chromium"); |
- cmd_line->AppendArg("--register_cygwin"); |
- cmd_line->AppendArgNative(FILE_PATH_LITERAL("--root=") + |
- root_directory.value()); |
- cmd_line->AppendArg("--port=" + base::IntToString(port_)); |
- if (secure_) |
- cmd_line->AppendArg("--tls"); |
- if (!temp_dir_.CreateUniqueTempDir()) { |
- LOG(ERROR) << "Unable to create a temporary directory."; |
- return false; |
- } |
- cmd_line->AppendArgNative(FILE_PATH_LITERAL("--output-dir=") + |
- temp_dir_.path().value()); |
- websocket_pid_file_ = temp_dir_.path().AppendASCII("websocket.pid"); |
- cmd_line->AppendArgNative(FILE_PATH_LITERAL("--pidfile=") + |
- websocket_pid_file_.value()); |
- SetPythonPath(); |
- |
- base::LaunchOptions options; |
- base::ProcessHandle process_handle; |
- |
-#if defined(OS_POSIX) |
- options.new_process_group = true; |
-#elif defined(OS_WIN) |
- job_handle_.Set(CreateJobObject(NULL, NULL)); |
- if (!job_handle_.IsValid()) { |
- LOG(ERROR) << "Could not create JobObject."; |
- return false; |
- } |
- |
- if (!base::SetJobObjectAsKillOnJobClose(job_handle_.Get())) { |
- LOG(ERROR) << "Could not SetInformationJobObject."; |
- return false; |
- } |
- |
- options.inherit_handles = true; |
- options.job_handle = job_handle_.Get(); |
-#endif |
- |
- // Launch a new WebSocket server process. |
- if (!base::LaunchProcess(*cmd_line.get(), options, &process_handle)) { |
- LOG(ERROR) << "Unable to launch websocket server:\n" |
- << cmd_line.get()->GetCommandLineString(); |
- return false; |
- } |
-#if defined(OS_POSIX) |
- process_group_id_ = process_handle; |
-#endif |
- int exit_code; |
- bool wait_success = base::WaitForExitCodeWithTimeout( |
- process_handle, |
- &exit_code, |
- TestTimeouts::action_max_timeout()); |
- base::CloseProcessHandle(process_handle); |
- |
- if (!wait_success || exit_code != 0) { |
- LOG(ERROR) << "Failed to run new-run-webkit-websocketserver: " |
- << "wait_success = " << wait_success << ", " |
- << "exit_code = " << exit_code << ", " |
- << "command_line = " << cmd_line.get()->GetCommandLineString(); |
- return false; |
- } |
- |
- started_ = true; |
- return true; |
-} |
- |
-CommandLine* TestWebSocketServer::CreatePythonCommandLine() { |
- // Note: Python's first argument must be the script; do not append CommandLine |
- // switches, as they would precede the script path and break this CommandLine. |
- FilePath path; |
- CHECK(GetPythonRunTime(&path)); |
- return new CommandLine(path); |
-} |
- |
-void TestWebSocketServer::SetPythonPath() { |
- FilePath scripts_path; |
- PathService::Get(base::DIR_SOURCE_ROOT, &scripts_path); |
- |
- scripts_path = scripts_path |
- .Append(FILE_PATH_LITERAL("third_party")) |
- .Append(FILE_PATH_LITERAL("WebKit")) |
- .Append(FILE_PATH_LITERAL("Tools")) |
- .Append(FILE_PATH_LITERAL("Scripts")); |
- AppendToPythonPath(scripts_path); |
-} |
- |
-CommandLine* TestWebSocketServer::CreateWebSocketServerCommandLine() { |
- FilePath src_path; |
- // Get to 'src' dir. |
- PathService::Get(base::DIR_SOURCE_ROOT, &src_path); |
- |
- FilePath script_path(src_path); |
- script_path = script_path.AppendASCII("third_party"); |
- script_path = script_path.AppendASCII("WebKit"); |
- script_path = script_path.AppendASCII("Tools"); |
- script_path = script_path.AppendASCII("Scripts"); |
- script_path = script_path.AppendASCII("new-run-webkit-websocketserver"); |
- |
- CommandLine* cmd_line = CreatePythonCommandLine(); |
- cmd_line->AppendArgPath(script_path); |
- return cmd_line; |
-} |
- |
-TestWebSocketServer::~TestWebSocketServer() { |
- if (!started_) |
- return; |
- // Append CommandLine arguments after the server script, switches won't work. |
- scoped_ptr<CommandLine> cmd_line(CreateWebSocketServerCommandLine()); |
- cmd_line->AppendArg("--server=stop"); |
- cmd_line->AppendArg("--chromium"); |
- cmd_line->AppendArgNative(FILE_PATH_LITERAL("--pidfile=") + |
- websocket_pid_file_.value()); |
- base::LaunchOptions options; |
- options.wait = true; |
- base::LaunchProcess(*cmd_line.get(), options, NULL); |
- |
-#if defined(OS_POSIX) |
- // Just to make sure that the server process terminates certainly. |
- if (process_group_id_ != base::kNullProcessHandle) |
- base::KillProcessGroup(process_group_id_); |
-#endif |
-} |
- |
-} // namespace content |