• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
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"
21 
22 // PyUITestSuiteBase
PyUITestSuiteBase(int argc,char ** argv)23 PyUITestSuiteBase::PyUITestSuiteBase(int argc, char** argv)
24     : UITestSuite(argc, argv) {
25 }
26 
~PyUITestSuiteBase()27 PyUITestSuiteBase::~PyUITestSuiteBase() {
28 #if defined(OS_MACOSX)
29   pool_.Recycle();
30 #endif
31   Shutdown();
32 }
33 
InitializeWithPath(const base::FilePath & browser_dir)34 void PyUITestSuiteBase::InitializeWithPath(const base::FilePath& browser_dir) {
35   SetBrowserDirectory(browser_dir);
36   UITestSuite::Initialize();
37 }
38 
SetCrSourceRoot(const base::FilePath & path)39 void PyUITestSuiteBase::SetCrSourceRoot(const base::FilePath& path) {
40   PathService::Override(base::DIR_SOURCE_ROOT, path);
41 }
42 
43 // PyUITestBase
PyUITestBase(bool clear_profile,std::wstring homepage)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);
52 }
53 
~PyUITestBase()54 PyUITestBase::~PyUITestBase() {
55 }
56 
57 // static, refer .h for why it needs to be static
58 base::MessageLoop* PyUITestBase::message_loop_ = NULL;
59 
60 // static
GetSharedMessageLoop(base::MessageLoop::Type msg_loop_type)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_;
66 }
67 
Initialize(const base::FilePath & browser_dir)68 void PyUITestBase::Initialize(const base::FilePath& browser_dir) {
69   UITestBase::SetBrowserDirectory(browser_dir);
70 }
71 
CreateProxyLauncher()72 ProxyLauncher* PyUITestBase::CreateProxyLauncher() {
73   if (named_channel_id_.empty())
74     return new AnonymousProxyLauncher(false);
75   return new NamedProxyLauncher(named_channel_id_, false, false);
76 }
77 
SetUp()78 void PyUITestBase::SetUp() {
79   UITestBase::SetUp();
80 }
81 
TearDown()82 void PyUITestBase::TearDown() {
83   UITestBase::TearDown();
84 }
85 
SetLaunchSwitches()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_);
91 
92   UITestBase::SetLaunchSwitches();
93 
94   // However, we *do* want the --homepage switch.
95   std::swap(homepage_original, homepage_);
96   launch_arguments_.AppendSwitchASCII(switches::kHomePage, homepage_);
97 }
98 
automation() const99 AutomationProxy* PyUITestBase::automation() const {
100   AutomationProxy* automation_proxy = UITestBase::automation();
101   if (!automation_proxy) {
102     LOG(FATAL) << "The automation proxy is NULL.";
103   }
104   return automation_proxy;
105 }
106 
_SendJSONRequest(int window_index,const std::string & request,int timeout)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();
114 
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);
127   }
128   return response;
129 }
130 
ErrorResponse(const std::string & error_string,const std::string & request,bool is_timeout,std::string * 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);
144 }
145 
RequestFailureResponse(const std::string & request,const base::TimeDelta & duration,const base::TimeDelta & timeout,std::string * 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);
162   }
163 }
164