Allow overlapping sync and async startup requests
[chromium-blink-merge.git] / chrome / test / pyautolib / pyautolib.cc
blobfdd48a820e255db27564a3b8442b757b096bc4b6
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/base_paths.h"
6 #include "base/json/json_writer.h"
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/path_service.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/time/time.h"
14 #include "base/values.h"
15 #include "chrome/common/automation_messages.h"
16 #include "chrome/common/chrome_switches.h"
17 #include "chrome/test/automation/automation_proxy.h"
18 #include "chrome/test/automation/tab_proxy.h"
19 #include "chrome/test/pyautolib/pyautolib.h"
20 #include "url/gurl.h"
22 // PyUITestSuiteBase
23 PyUITestSuiteBase::PyUITestSuiteBase(int argc, char** argv)
24 : UITestSuite(argc, argv) {
27 PyUITestSuiteBase::~PyUITestSuiteBase() {
28 #if defined(OS_MACOSX)
29 pool_.Recycle();
30 #endif
31 Shutdown();
34 void PyUITestSuiteBase::InitializeWithPath(const base::FilePath& browser_dir) {
35 SetBrowserDirectory(browser_dir);
36 UITestSuite::Initialize();
39 void PyUITestSuiteBase::SetCrSourceRoot(const base::FilePath& path) {
40 PathService::Override(base::DIR_SOURCE_ROOT, path);
43 // PyUITestBase
44 PyUITestBase::PyUITestBase(bool clear_profile, std::wstring homepage)
45 : UITestBase() {
46 set_clear_profile(clear_profile);
47 set_homepage(WideToASCII(homepage));
48 // We add this so that pyauto can execute javascript in the renderer and
49 // read values back.
50 dom_automation_enabled_ = true;
51 message_loop_ = GetSharedMessageLoop(base::MessageLoop::TYPE_DEFAULT);
54 PyUITestBase::~PyUITestBase() {
57 // static, refer .h for why it needs to be static
58 base::MessageLoop* PyUITestBase::message_loop_ = NULL;
60 // static
61 base::MessageLoop* PyUITestBase::GetSharedMessageLoop(
62 base::MessageLoop::Type msg_loop_type) {
63 if (!message_loop_) // Create a shared instance of MessageLoop
64 message_loop_ = new base::MessageLoop(msg_loop_type);
65 return message_loop_;
68 void PyUITestBase::Initialize(const base::FilePath& browser_dir) {
69 UITestBase::SetBrowserDirectory(browser_dir);
72 ProxyLauncher* PyUITestBase::CreateProxyLauncher() {
73 if (named_channel_id_.empty())
74 return new AnonymousProxyLauncher(false);
75 return new NamedProxyLauncher(named_channel_id_, false, false);
78 void PyUITestBase::SetUp() {
79 UITestBase::SetUp();
82 void PyUITestBase::TearDown() {
83 UITestBase::TearDown();
86 void PyUITestBase::SetLaunchSwitches() {
87 // Clear the homepage because some of the pyauto tests don't work correctly
88 // if a URL argument is passed.
89 std::string homepage_original;
90 std::swap(homepage_original, homepage_);
92 UITestBase::SetLaunchSwitches();
94 // However, we *do* want the --homepage switch.
95 std::swap(homepage_original, homepage_);
96 launch_arguments_.AppendSwitchASCII(switches::kHomePage, homepage_);
99 AutomationProxy* PyUITestBase::automation() const {
100 AutomationProxy* automation_proxy = UITestBase::automation();
101 if (!automation_proxy) {
102 LOG(FATAL) << "The automation proxy is NULL.";
104 return automation_proxy;
107 std::string PyUITestBase::_SendJSONRequest(int window_index,
108 const std::string& request,
109 int timeout) {
110 std::string response;
111 bool success;
112 AutomationProxy* automation_sender = automation();
113 base::TimeTicks time = base::TimeTicks::Now();
115 if (!automation_sender) {
116 ErrorResponse("Automation proxy does not exist", request, false, &response);
117 } else if (!automation_sender->channel()) {
118 ErrorResponse("Chrome automation IPC channel was found already broken",
119 request, false, &response);
120 } else if (!automation_sender->Send(
121 new AutomationMsg_SendJSONRequest(window_index, request, &response,
122 &success),
123 timeout)) {
124 RequestFailureResponse(request, base::TimeTicks::Now() - time,
125 base::TimeDelta::FromMilliseconds(timeout),
126 &response);
128 return response;
131 void PyUITestBase::ErrorResponse(
132 const std::string& error_string,
133 const std::string& request,
134 bool is_timeout,
135 std::string* response) {
136 base::DictionaryValue error_dict;
137 std::string error_msg = base::StringPrintf("%s for %s", error_string.c_str(),
138 request.c_str());
139 LOG(ERROR) << "Error during automation: " << error_msg;
140 error_dict.SetString("error", error_msg);
141 error_dict.SetBoolean("is_interface_error", true);
142 error_dict.SetBoolean("is_interface_timeout", is_timeout);
143 base::JSONWriter::Write(&error_dict, response);
146 void PyUITestBase::RequestFailureResponse(
147 const std::string& request,
148 const base::TimeDelta& duration,
149 const base::TimeDelta& timeout,
150 std::string* response) {
151 // TODO(craigdh): Determine timeout directly from IPC's Send().
152 if (duration >= timeout) {
153 ErrorResponse(
154 base::StringPrintf("Chrome automation timed out after %d seconds",
155 static_cast<int>(duration.InSeconds())),
156 request, true, response);
157 } else {
158 // TODO(craigdh): Determine specific cause.
159 ErrorResponse(
160 "Chrome automation failed prior to timing out, did chrome crash?",
161 request, false, response);