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 |