// 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 "base/base_paths.h" #include "base/json/json_writer.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/path_service.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "base/values.h" #include "chrome/common/automation_messages.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/automation/automation_proxy.h" #include "chrome/test/automation/tab_proxy.h" #include "chrome/test/pyautolib/pyautolib.h" #include "url/gurl.h" // PyUITestSuiteBase PyUITestSuiteBase::PyUITestSuiteBase(int argc, char** argv) : UITestSuite(argc, argv) { } PyUITestSuiteBase::~PyUITestSuiteBase() { #if defined(OS_MACOSX) pool_.Recycle(); #endif Shutdown(); } void PyUITestSuiteBase::InitializeWithPath(const base::FilePath& browser_dir) { SetBrowserDirectory(browser_dir); UITestSuite::Initialize(); } void PyUITestSuiteBase::SetCrSourceRoot(const base::FilePath& path) { PathService::Override(base::DIR_SOURCE_ROOT, path); } // PyUITestBase PyUITestBase::PyUITestBase(bool clear_profile, std::wstring homepage) : UITestBase() { set_clear_profile(clear_profile); set_homepage(WideToASCII(homepage)); // We add this so that pyauto can execute javascript in the renderer and // read values back. dom_automation_enabled_ = true; message_loop_ = GetSharedMessageLoop(base::MessageLoop::TYPE_DEFAULT); } PyUITestBase::~PyUITestBase() { } // static, refer .h for why it needs to be static base::MessageLoop* PyUITestBase::message_loop_ = NULL; // static base::MessageLoop* PyUITestBase::GetSharedMessageLoop( base::MessageLoop::Type msg_loop_type) { if (!message_loop_) // Create a shared instance of MessageLoop message_loop_ = new base::MessageLoop(msg_loop_type); return message_loop_; } void PyUITestBase::Initialize(const base::FilePath& browser_dir) { UITestBase::SetBrowserDirectory(browser_dir); } ProxyLauncher* PyUITestBase::CreateProxyLauncher() { if (named_channel_id_.empty()) return new AnonymousProxyLauncher(false); return new NamedProxyLauncher(named_channel_id_, false, false); } void PyUITestBase::SetUp() { UITestBase::SetUp(); } void PyUITestBase::TearDown() { UITestBase::TearDown(); } void PyUITestBase::SetLaunchSwitches() { // Clear the homepage because some of the pyauto tests don't work correctly // if a URL argument is passed. std::string homepage_original; std::swap(homepage_original, homepage_); UITestBase::SetLaunchSwitches(); // However, we *do* want the --homepage switch. std::swap(homepage_original, homepage_); launch_arguments_.AppendSwitchASCII(switches::kHomePage, homepage_); } AutomationProxy* PyUITestBase::automation() const { AutomationProxy* automation_proxy = UITestBase::automation(); if (!automation_proxy) { LOG(FATAL) << "The automation proxy is NULL."; } return automation_proxy; } std::string PyUITestBase::_SendJSONRequest(int window_index, const std::string& request, int timeout) { std::string response; bool success; AutomationProxy* automation_sender = automation(); base::TimeTicks time = base::TimeTicks::Now(); if (!automation_sender) { ErrorResponse("Automation proxy does not exist", request, false, &response); } else if (!automation_sender->channel()) { ErrorResponse("Chrome automation IPC channel was found already broken", request, false, &response); } else if (!automation_sender->Send( new AutomationMsg_SendJSONRequest(window_index, request, &response, &success), timeout)) { RequestFailureResponse(request, base::TimeTicks::Now() - time, base::TimeDelta::FromMilliseconds(timeout), &response); } return response; } void PyUITestBase::ErrorResponse( const std::string& error_string, const std::string& request, bool is_timeout, std::string* response) { base::DictionaryValue error_dict; std::string error_msg = base::StringPrintf("%s for %s", error_string.c_str(), request.c_str()); LOG(ERROR) << "Error during automation: " << error_msg; error_dict.SetString("error", error_msg); error_dict.SetBoolean("is_interface_error", true); error_dict.SetBoolean("is_interface_timeout", is_timeout); base::JSONWriter::Write(&error_dict, response); } void PyUITestBase::RequestFailureResponse( const std::string& request, const base::TimeDelta& duration, const base::TimeDelta& timeout, std::string* response) { // TODO(craigdh): Determine timeout directly from IPC's Send(). if (duration >= timeout) { ErrorResponse( base::StringPrintf("Chrome automation timed out after %d seconds", static_cast(duration.InSeconds())), request, true, response); } else { // TODO(craigdh): Determine specific cause. ErrorResponse( "Chrome automation failed prior to timing out, did chrome crash?", request, false, response); } }