| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/test/automation/automation_proxy.h" | 5 #include "chrome/test/automation/automation_proxy.h" |
| 6 | 6 |
| 7 #include <gtest/gtest.h> | 7 #include <gtest/gtest.h> |
| 8 | 8 |
| 9 #include <sstream> | 9 #include <sstream> |
| 10 | 10 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 #if defined(OS_WIN) | 26 #if defined(OS_WIN) |
| 27 // TODO(port): Enable when dialog_delegate is ported. | 27 // TODO(port): Enable when dialog_delegate is ported. |
| 28 #include "views/window/dialog_delegate.h" | 28 #include "views/window/dialog_delegate.h" |
| 29 #endif | 29 #endif |
| 30 | 30 |
| 31 using base::TimeDelta; | 31 using base::TimeDelta; |
| 32 using base::TimeTicks; | 32 using base::TimeTicks; |
| 33 | 33 |
| 34 namespace { | 34 namespace { |
| 35 | 35 |
| 36 const char kChannelErrorVersionString[] = "***CHANNEL_ERROR***"; |
| 37 |
| 36 // This object allows messages received on the background thread to be | 38 // This object allows messages received on the background thread to be |
| 37 // properly triaged. | 39 // properly triaged. |
| 38 class AutomationMessageFilter : public IPC::ChannelProxy::MessageFilter { | 40 class AutomationMessageFilter : public IPC::ChannelProxy::MessageFilter { |
| 39 public: | 41 public: |
| 40 explicit AutomationMessageFilter(AutomationProxy* server) : server_(server) {} | 42 explicit AutomationMessageFilter(AutomationProxy* server) : server_(server) {} |
| 41 | 43 |
| 42 // Return true to indicate that the message was handled, or false to let | 44 // Return true to indicate that the message was handled, or false to let |
| 43 // the message be handled in the default way. | 45 // the message be handled in the default way. |
| 44 virtual bool OnMessageReceived(const IPC::Message& message) { | 46 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { |
| 45 bool handled = true; | 47 bool handled = true; |
| 46 IPC_BEGIN_MESSAGE_MAP(AutomationMessageFilter, message) | 48 IPC_BEGIN_MESSAGE_MAP(AutomationMessageFilter, message) |
| 47 IPC_MESSAGE_HANDLER_GENERIC(AutomationMsg_Hello, | 49 IPC_MESSAGE_HANDLER_GENERIC(AutomationMsg_Hello, |
| 48 OnAutomationHello(message)) | 50 OnAutomationHello(message)) |
| 49 IPC_MESSAGE_HANDLER_GENERIC( | 51 IPC_MESSAGE_HANDLER_GENERIC( |
| 50 AutomationMsg_InitialLoadsComplete, server_->SignalInitialLoads()) | 52 AutomationMsg_InitialLoadsComplete, server_->SignalInitialLoads()) |
| 51 IPC_MESSAGE_HANDLER(AutomationMsg_InitialNewTabUILoadComplete, | 53 IPC_MESSAGE_HANDLER(AutomationMsg_InitialNewTabUILoadComplete, |
| 52 NewTabLoaded) | 54 NewTabLoaded) |
| 53 IPC_MESSAGE_HANDLER_GENERIC( | 55 IPC_MESSAGE_HANDLER_GENERIC( |
| 54 AutomationMsg_InvalidateHandle, server_->InvalidateHandle(message)) | 56 AutomationMsg_InvalidateHandle, server_->InvalidateHandle(message)) |
| 55 IPC_MESSAGE_UNHANDLED(handled = false) | 57 IPC_MESSAGE_UNHANDLED(handled = false) |
| 56 IPC_END_MESSAGE_MAP() | 58 IPC_END_MESSAGE_MAP() |
| 57 | 59 |
| 58 return handled; | 60 return handled; |
| 59 } | 61 } |
| 60 | 62 |
| 61 virtual void OnFilterAdded(IPC::Channel* channel) { | 63 virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE { |
| 62 server_->SetChannel(channel); | 64 server_->SetChannel(channel); |
| 63 } | 65 } |
| 64 | 66 |
| 65 virtual void OnFilterRemoved() { | 67 virtual void OnFilterRemoved() OVERRIDE { |
| 66 server_->ResetChannel(); | 68 server_->ResetChannel(); |
| 67 } | 69 } |
| 68 | 70 |
| 71 virtual void OnChannelError() OVERRIDE { |
| 72 server_->SignalAppLaunch(kChannelErrorVersionString); |
| 73 server_->SignalNewTabUITab(-1); |
| 74 } |
| 75 |
| 76 private: |
| 69 void NewTabLoaded(int load_time) { | 77 void NewTabLoaded(int load_time) { |
| 70 server_->SignalNewTabUITab(load_time); | 78 server_->SignalNewTabUITab(load_time); |
| 71 } | 79 } |
| 72 | 80 |
| 73 void OnAutomationHello(const IPC::Message& hello_message) { | 81 void OnAutomationHello(const IPC::Message& hello_message) { |
| 74 std::string server_version; | 82 std::string server_version; |
| 75 void* iter = NULL; | 83 void* iter = NULL; |
| 76 if (!hello_message.ReadString(&iter, &server_version)) { | 84 if (!hello_message.ReadString(&iter, &server_version)) { |
| 77 // We got an AutomationMsg_Hello from an old automation provider | 85 // We got an AutomationMsg_Hello from an old automation provider |
| 78 // that doesn't send version info. Leave server_version as an empty | 86 // that doesn't send version info. Leave server_version as an empty |
| 79 // string to signal a version mismatch. | 87 // string to signal a version mismatch. |
| 80 LOG(ERROR) << "Pre-versioning protocol detected in automation provider."; | 88 LOG(ERROR) << "Pre-versioning protocol detected in automation provider."; |
| 81 } | 89 } |
| 82 | 90 |
| 83 server_->SignalAppLaunch(server_version); | 91 server_->SignalAppLaunch(server_version); |
| 84 } | 92 } |
| 85 | 93 |
| 86 private: | |
| 87 AutomationProxy* server_; | 94 AutomationProxy* server_; |
| 95 |
| 96 DISALLOW_COPY_AND_ASSIGN(AutomationMessageFilter); |
| 88 }; | 97 }; |
| 89 | 98 |
| 90 } // anonymous namespace | 99 } // anonymous namespace |
| 91 | 100 |
| 92 | 101 |
| 93 AutomationProxy::AutomationProxy(int action_timeout_ms, | 102 AutomationProxy::AutomationProxy(int action_timeout_ms, |
| 94 bool disconnect_on_failure) | 103 bool disconnect_on_failure) |
| 95 : app_launched_(true, false), | 104 : app_launched_(true, false), |
| 96 initial_loads_complete_(true, false), | 105 initial_loads_complete_(true, false), |
| 97 new_tab_ui_load_complete_(true, false), | 106 new_tab_ui_load_complete_(true, false), |
| 98 shutdown_event_(new base::WaitableEvent(true, false)), | 107 shutdown_event_(new base::WaitableEvent(true, false)), |
| 99 app_launch_signaled_(0), | |
| 100 perform_version_check_(false), | 108 perform_version_check_(false), |
| 101 disconnect_on_failure_(disconnect_on_failure), | 109 disconnect_on_failure_(disconnect_on_failure), |
| 102 action_timeout_( | 110 action_timeout_( |
| 103 TimeDelta::FromMilliseconds(action_timeout_ms)), | 111 TimeDelta::FromMilliseconds(action_timeout_ms)), |
| 104 listener_thread_id_(0) { | 112 listener_thread_id_(0) { |
| 105 // base::WaitableEvent::TimedWait() will choke if we give it a negative value. | 113 // base::WaitableEvent::TimedWait() will choke if we give it a negative value. |
| 106 // Zero also seems unreasonable, since we need to wait for IPC, but at | 114 // Zero also seems unreasonable, since we need to wait for IPC, but at |
| 107 // least it is legal... ;-) | 115 // least it is legal... ;-) |
| 108 DCHECK_GE(action_timeout_ms, 0); | 116 DCHECK_GE(action_timeout_ms, 0); |
| 109 listener_thread_id_ = base::PlatformThread::CurrentId(); | 117 listener_thread_id_ = base::PlatformThread::CurrentId(); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 channel_->AddFilter(new AutomationMessageFilter(this)); | 171 channel_->AddFilter(new AutomationMessageFilter(this)); |
| 164 } | 172 } |
| 165 | 173 |
| 166 void AutomationProxy::InitializeHandleTracker() { | 174 void AutomationProxy::InitializeHandleTracker() { |
| 167 tracker_.reset(new AutomationHandleTracker()); | 175 tracker_.reset(new AutomationHandleTracker()); |
| 168 } | 176 } |
| 169 | 177 |
| 170 AutomationLaunchResult AutomationProxy::WaitForAppLaunch() { | 178 AutomationLaunchResult AutomationProxy::WaitForAppLaunch() { |
| 171 AutomationLaunchResult result = AUTOMATION_SUCCESS; | 179 AutomationLaunchResult result = AUTOMATION_SUCCESS; |
| 172 if (app_launched_.TimedWait(action_timeout_)) { | 180 if (app_launched_.TimedWait(action_timeout_)) { |
| 173 if (perform_version_check_) { | 181 if (server_version_ == kChannelErrorVersionString) { |
| 182 result = AUTOMATION_CHANNEL_ERROR; |
| 183 } else if (perform_version_check_) { |
| 174 // Obtain our own version number and compare it to what the automation | 184 // Obtain our own version number and compare it to what the automation |
| 175 // provider sent. | 185 // provider sent. |
| 176 chrome::VersionInfo version_info; | 186 chrome::VersionInfo version_info; |
| 177 DCHECK(version_info.is_valid()); | 187 DCHECK(version_info.is_valid()); |
| 178 | 188 |
| 179 // Note that we use a simple string comparison since we expect the version | 189 // Note that we use a simple string comparison since we expect the version |
| 180 // to be a punctuated numeric string. Consider using base/Version if we | 190 // to be a punctuated numeric string. Consider using base/Version if we |
| 181 // ever need something more complicated here. | 191 // ever need something more complicated here. |
| 182 if (server_version_ != version_info.Version()) { | 192 if (server_version_ != version_info.Version()) { |
| 183 result = AUTOMATION_VERSION_MISMATCH; | 193 result = AUTOMATION_VERSION_MISMATCH; |
| 184 } | 194 } |
| 185 } | 195 } |
| 186 } else { | 196 } else { |
| 187 result = AUTOMATION_TIMEOUT; | 197 result = AUTOMATION_TIMEOUT; |
| 188 } | 198 } |
| 189 return result; | 199 return result; |
| 190 } | 200 } |
| 191 | 201 |
| 192 void AutomationProxy::SignalAppLaunch(const std::string& version_string) { | 202 void AutomationProxy::SignalAppLaunch(const std::string& version_string) { |
| 193 // The synchronization of the reading / writing of server_version_ is a bit | |
| 194 // messy but does work as long as SignalAppLaunch is only called once. | |
| 195 // Review this if we ever want an AutomationProxy instance to launch | |
| 196 // multiple AutomationProviders. | |
| 197 app_launch_signaled_++; | |
| 198 if (app_launch_signaled_ > 1) { | |
| 199 NOTREACHED(); | |
| 200 LOG(ERROR) << "Multiple AutomationMsg_Hello messages received"; | |
| 201 return; | |
| 202 } | |
| 203 server_version_ = version_string; | 203 server_version_ = version_string; |
| 204 app_launched_.Signal(); | 204 app_launched_.Signal(); |
| 205 } | 205 } |
| 206 | 206 |
| 207 bool AutomationProxy::WaitForProcessLauncherThreadToGoIdle() { | 207 bool AutomationProxy::WaitForProcessLauncherThreadToGoIdle() { |
| 208 return Send(new AutomationMsg_WaitForProcessLauncherThreadToGoIdle()); | 208 return Send(new AutomationMsg_WaitForProcessLauncherThreadToGoIdle()); |
| 209 } | 209 } |
| 210 | 210 |
| 211 bool AutomationProxy::WaitForInitialLoads() { | 211 bool AutomationProxy::WaitForInitialLoads() { |
| 212 return initial_loads_complete_.TimedWait(action_timeout_); | 212 return initial_loads_complete_.TimedWait(action_timeout_); |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 } | 547 } |
| 548 | 548 |
| 549 bool AutomationProxy::SendJSONRequest(const std::string& request, | 549 bool AutomationProxy::SendJSONRequest(const std::string& request, |
| 550 int timeout_ms, | 550 int timeout_ms, |
| 551 std::string* response) { | 551 std::string* response) { |
| 552 bool result = false; | 552 bool result = false; |
| 553 if (!SendAutomationJSONRequest(this, request, timeout_ms, response, &result)) | 553 if (!SendAutomationJSONRequest(this, request, timeout_ms, response, &result)) |
| 554 return false; | 554 return false; |
| 555 return result; | 555 return result; |
| 556 } | 556 } |
| OLD | NEW |