Index: chrome/test/automation/automation_proxy.cc |
=================================================================== |
--- chrome/test/automation/automation_proxy.cc (revision 261647) |
+++ chrome/test/automation/automation_proxy.cc (working copy) |
@@ -1,426 +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 "chrome/test/automation/automation_proxy.h" |
- |
-#include <sstream> |
- |
-#include "base/basictypes.h" |
-#include "base/file_util.h" |
-#include "base/logging.h" |
-#include "base/memory/ref_counted.h" |
-#include "base/synchronization/waitable_event.h" |
-#include "base/threading/platform_thread.h" |
-#include "chrome/common/automation_constants.h" |
-#include "chrome/common/automation_messages.h" |
-#include "chrome/common/chrome_version_info.h" |
-#include "chrome/test/automation/browser_proxy.h" |
-#include "chrome/test/automation/tab_proxy.h" |
-#include "ipc/ipc_descriptors.h" |
-#if defined(OS_WIN) |
-// TODO(port): Enable when dialog_delegate is ported. |
-#include "ui/views/window/dialog_delegate.h" |
-#endif |
- |
-using base::TimeDelta; |
-using base::TimeTicks; |
- |
-namespace { |
- |
-const char kChannelErrorVersionString[] = "***CHANNEL_ERROR***"; |
- |
-// This object allows messages received on the background thread to be |
-// properly triaged. |
-class AutomationMessageFilter : public IPC::ChannelProxy::MessageFilter { |
- public: |
- explicit AutomationMessageFilter(AutomationProxy* server) : server_(server) {} |
- |
- // Return true to indicate that the message was handled, or false to let |
- // the message be handled in the default way. |
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { |
- bool handled = true; |
- IPC_BEGIN_MESSAGE_MAP(AutomationMessageFilter, message) |
- IPC_MESSAGE_HANDLER_GENERIC(AutomationMsg_Hello, |
- OnAutomationHello(message)) |
- IPC_MESSAGE_HANDLER_GENERIC( |
- AutomationMsg_InitialLoadsComplete, server_->SignalInitialLoads()) |
- IPC_MESSAGE_HANDLER(AutomationMsg_InitialNewTabUILoadComplete, |
- NewTabLoaded) |
- IPC_MESSAGE_HANDLER_GENERIC( |
- AutomationMsg_InvalidateHandle, server_->InvalidateHandle(message)) |
- IPC_MESSAGE_UNHANDLED(handled = false) |
- IPC_END_MESSAGE_MAP() |
- |
- return handled; |
- } |
- |
- virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE { |
- server_->SetChannel(channel); |
- } |
- |
- virtual void OnFilterRemoved() OVERRIDE { |
- server_->ResetChannel(); |
- } |
- |
- virtual void OnChannelError() OVERRIDE { |
- server_->SignalAppLaunch(kChannelErrorVersionString); |
- server_->SignalNewTabUITab(-1); |
- } |
- |
- private: |
- void NewTabLoaded(int load_time) { |
- server_->SignalNewTabUITab(load_time); |
- } |
- |
- void OnAutomationHello(const IPC::Message& hello_message) { |
- std::string server_version; |
- PickleIterator iter(hello_message); |
- if (!hello_message.ReadString(&iter, &server_version)) { |
- // We got an AutomationMsg_Hello from an old automation provider |
- // that doesn't send version info. Leave server_version as an empty |
- // string to signal a version mismatch. |
- LOG(ERROR) << "Pre-versioning protocol detected in automation provider."; |
- } |
- |
- server_->SignalAppLaunch(server_version); |
- } |
- |
- AutomationProxy* server_; |
- |
- DISALLOW_COPY_AND_ASSIGN(AutomationMessageFilter); |
-}; |
- |
-} // anonymous namespace |
- |
- |
-AutomationProxy::AutomationProxy(base::TimeDelta action_timeout, |
- bool disconnect_on_failure) |
- : app_launched_(true, false), |
- initial_loads_complete_(true, false), |
- new_tab_ui_load_complete_(true, false), |
- shutdown_event_(new base::WaitableEvent(true, false)), |
- perform_version_check_(false), |
- disconnect_on_failure_(disconnect_on_failure), |
- channel_disconnected_on_failure_(false), |
- action_timeout_(action_timeout), |
- listener_thread_id_(0) { |
- // base::WaitableEvent::TimedWait() will choke if we give it a negative value. |
- // Zero also seems unreasonable, since we need to wait for IPC, but at |
- // least it is legal... ;-) |
- DCHECK_GE(action_timeout.InMilliseconds(), 0); |
- listener_thread_id_ = base::PlatformThread::CurrentId(); |
- InitializeHandleTracker(); |
- InitializeThread(); |
-} |
- |
-AutomationProxy::~AutomationProxy() { |
- // Destruction order is important. Thread has to outlive the channel and |
- // tracker has to outlive the thread since we access the tracker inside |
- // AutomationMessageFilter::OnMessageReceived. |
- Disconnect(); |
- thread_.reset(); |
- tracker_.reset(); |
-} |
- |
-std::string AutomationProxy::GenerateChannelID() { |
- // The channel counter keeps us out of trouble if we create and destroy |
- // several AutomationProxies sequentially over the course of a test run. |
- // (Creating the channel sometimes failed before when running a lot of |
- // tests in sequence, and our theory is that sometimes the channel ID |
- // wasn't getting freed up in time for the next test.) |
- static int channel_counter = 0; |
- |
- std::ostringstream buf; |
- buf << "ChromeTestingInterface:" << base::GetCurrentProcId() << |
- "." << ++channel_counter; |
- return buf.str(); |
-} |
- |
-void AutomationProxy::InitializeThread() { |
- scoped_ptr<base::Thread> thread( |
- new base::Thread("AutomationProxy_BackgroundThread")); |
- base::Thread::Options options; |
- options.message_loop_type = base::MessageLoop::TYPE_IO; |
- bool thread_result = thread->StartWithOptions(options); |
- DCHECK(thread_result); |
- thread_.swap(thread); |
-} |
- |
-void AutomationProxy::InitializeChannel(const std::string& channel_id, |
- bool use_named_interface) { |
- DCHECK(shutdown_event_.get() != NULL); |
- |
- // TODO(iyengar) |
- // The shutdown event could be global on the same lines as the automation |
- // provider, where we use the shutdown event provided by the chrome browser |
- // process. |
- channel_.reset(new IPC::SyncChannel(this, // we are the listener |
- thread_->message_loop_proxy().get(), |
- shutdown_event_.get())); |
- channel_->AddFilter(new AutomationMessageFilter(this)); |
- |
- // Create the pipe synchronously so that Chrome doesn't try to connect to an |
- // unready server. Note this is done after adding a message filter to |
- // guarantee that it doesn't miss any messages when we are the client. |
- // See crbug.com/102894. |
- channel_->Init( |
- channel_id, |
- use_named_interface ? IPC::Channel::MODE_NAMED_CLIENT |
- : IPC::Channel::MODE_SERVER, |
- true /* create_pipe_now */); |
-} |
- |
-void AutomationProxy::InitializeHandleTracker() { |
- tracker_.reset(new AutomationHandleTracker()); |
-} |
- |
-AutomationLaunchResult AutomationProxy::WaitForAppLaunch() { |
- AutomationLaunchResult result = AUTOMATION_SUCCESS; |
- if (app_launched_.TimedWait(action_timeout_)) { |
- if (server_version_ == kChannelErrorVersionString) { |
- result = AUTOMATION_CHANNEL_ERROR; |
- } else if (perform_version_check_) { |
- // Obtain our own version number and compare it to what the automation |
- // provider sent. |
- chrome::VersionInfo version_info; |
- DCHECK(version_info.is_valid()); |
- |
- // Note that we use a simple string comparison since we expect the version |
- // to be a punctuated numeric string. Consider using base/Version if we |
- // ever need something more complicated here. |
- if (server_version_ != version_info.Version()) { |
- result = AUTOMATION_VERSION_MISMATCH; |
- } |
- } |
- } else { |
- result = AUTOMATION_TIMEOUT; |
- } |
- return result; |
-} |
- |
-void AutomationProxy::SignalAppLaunch(const std::string& version_string) { |
- server_version_ = version_string; |
- app_launched_.Signal(); |
-} |
- |
-bool AutomationProxy::WaitForProcessLauncherThreadToGoIdle() { |
- return Send(new AutomationMsg_WaitForProcessLauncherThreadToGoIdle()); |
-} |
- |
-bool AutomationProxy::WaitForInitialLoads() { |
- return initial_loads_complete_.TimedWait(action_timeout_); |
-} |
- |
-bool AutomationProxy::WaitForInitialNewTabUILoad(int* load_time) { |
- if (new_tab_ui_load_complete_.TimedWait(action_timeout_)) { |
- *load_time = new_tab_ui_load_time_; |
- new_tab_ui_load_complete_.Reset(); |
- return true; |
- } |
- return false; |
-} |
- |
-void AutomationProxy::SignalInitialLoads() { |
- initial_loads_complete_.Signal(); |
-} |
- |
-void AutomationProxy::SignalNewTabUITab(int load_time) { |
- new_tab_ui_load_time_ = load_time; |
- new_tab_ui_load_complete_.Signal(); |
-} |
- |
-bool AutomationProxy::GetBrowserWindowCount(int* num_windows) { |
- if (!num_windows) { |
- NOTREACHED(); |
- return false; |
- } |
- |
- return Send(new AutomationMsg_BrowserWindowCount(num_windows)); |
-} |
- |
-bool AutomationProxy::GetNormalBrowserWindowCount(int* num_windows) { |
- if (!num_windows) { |
- NOTREACHED(); |
- return false; |
- } |
- |
- return Send(new AutomationMsg_NormalBrowserWindowCount(num_windows)); |
-} |
- |
-bool AutomationProxy::WaitForWindowCountToBecome(int count) { |
- bool wait_success = false; |
- if (!Send(new AutomationMsg_WaitForBrowserWindowCountToBecome( |
- count, &wait_success))) { |
- return false; |
- } |
- return wait_success; |
-} |
- |
-bool AutomationProxy::IsURLDisplayed(GURL url) { |
- int window_count; |
- if (!GetBrowserWindowCount(&window_count)) |
- return false; |
- |
- for (int i = 0; i < window_count; i++) { |
- scoped_refptr<BrowserProxy> window = GetBrowserWindow(i); |
- if (!window.get()) |
- break; |
- |
- int tab_count; |
- if (!window->GetTabCount(&tab_count)) |
- continue; |
- |
- for (int j = 0; j < tab_count; j++) { |
- scoped_refptr<TabProxy> tab = window->GetTab(j); |
- if (!tab.get()) |
- break; |
- |
- GURL tab_url; |
- if (!tab->GetCurrentURL(&tab_url)) |
- continue; |
- |
- if (tab_url == url) |
- return true; |
- } |
- } |
- |
- return false; |
-} |
- |
-bool AutomationProxy::GetMetricEventDuration(const std::string& event_name, |
- int* duration_ms) { |
- return Send(new AutomationMsg_GetMetricEventDuration(event_name, |
- duration_ms)); |
-} |
- |
-void AutomationProxy::Disconnect() { |
- DCHECK(shutdown_event_.get() != NULL); |
- shutdown_event_->Signal(); |
- channel_.reset(); |
-} |
- |
-bool AutomationProxy::OnMessageReceived(const IPC::Message& msg) { |
- // This won't get called unless AutomationProxy is run from |
- // inside a message loop. |
- NOTREACHED(); |
- return false; |
-} |
- |
-void AutomationProxy::OnChannelError() { |
- LOG(ERROR) << "Channel error in AutomationProxy."; |
- if (disconnect_on_failure_) |
- Disconnect(); |
-} |
- |
-scoped_refptr<BrowserProxy> AutomationProxy::GetBrowserWindow( |
- int window_index) { |
- int handle = 0; |
- if (!Send(new AutomationMsg_BrowserWindow(window_index, &handle))) |
- return NULL; |
- |
- return ProxyObjectFromHandle<BrowserProxy>(handle); |
-} |
- |
-IPC::SyncChannel* AutomationProxy::channel() { |
- return channel_.get(); |
-} |
- |
-bool AutomationProxy::Send(IPC::Message* message) { |
- return Send(message, |
- static_cast<int>(action_timeout_.InMilliseconds())); |
-} |
- |
-bool AutomationProxy::Send(IPC::Message* message, int timeout_ms) { |
- if (!channel_.get()) { |
- LOG(ERROR) << "Automation channel has been closed; dropping message!"; |
- delete message; |
- return false; |
- } |
- |
- bool success = channel_->SendWithTimeout(message, timeout_ms); |
- |
- if (!success && disconnect_on_failure_) { |
- // Send failed (possibly due to a timeout). Browser is likely in a weird |
- // state, and further IPC requests are extremely likely to fail (possibly |
- // timeout, which would make tests slower). Disconnect the channel now |
- // to avoid the slowness. |
- channel_disconnected_on_failure_ = true; |
- LOG(ERROR) << "Disconnecting channel after error!"; |
- Disconnect(); |
- } |
- |
- return success; |
-} |
- |
-void AutomationProxy::InvalidateHandle(const IPC::Message& message) { |
- PickleIterator iter(message); |
- int handle; |
- |
- if (message.ReadInt(&iter, &handle)) { |
- tracker_->InvalidateHandle(handle); |
- } |
-} |
- |
-bool AutomationProxy::OpenNewBrowserWindow(Browser::Type type, bool show) { |
- return Send( |
- new AutomationMsg_OpenNewBrowserWindowOfType(static_cast<int>(type), |
- show)); |
-} |
- |
-template <class T> scoped_refptr<T> AutomationProxy::ProxyObjectFromHandle( |
- int handle) { |
- if (!handle) |
- return NULL; |
- |
- // Get AddRef-ed pointer to the object if handle is already seen. |
- T* p = static_cast<T*>(tracker_->GetResource(handle)); |
- if (!p) { |
- p = new T(this, tracker_.get(), handle); |
- p->AddRef(); |
- } |
- |
- // Since there is no scoped_refptr::attach. |
- scoped_refptr<T> result; |
- result.swap(&p); |
- return result; |
-} |
- |
-void AutomationProxy::SetChannel(IPC::Channel* channel) { |
- if (tracker_.get()) |
- tracker_->put_channel(channel); |
-} |
- |
-void AutomationProxy::ResetChannel() { |
- if (tracker_.get()) |
- tracker_->put_channel(NULL); |
-} |
- |
-bool AutomationProxy::BeginTracing(const std::string& category_patterns) { |
- bool result = false; |
- bool send_success = Send(new AutomationMsg_BeginTracing(category_patterns, |
- &result)); |
- return send_success && result; |
-} |
- |
-bool AutomationProxy::EndTracing(std::string* json_trace_output) { |
- bool success = false; |
- base::FilePath path; |
- if (!Send(new AutomationMsg_EndTracing(&path, &success)) || !success) |
- return false; |
- |
- bool ok = base::ReadFileToString(path, json_trace_output); |
- DCHECK(ok); |
- base::DeleteFile(path, false); |
- return true; |
-} |
- |
-bool AutomationProxy::SendJSONRequest(const std::string& request, |
- int timeout_ms, |
- std::string* response) { |
- bool result = false; |
- if (!Send(new AutomationMsg_SendJSONRequest(-1, request, response, &result), |
- timeout_ms)) |
- return false; |
- return result; |
-} |