OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/chromedriver/commands.h" | 5 #include "chrome/test/chromedriver/commands.h" |
6 | 6 |
7 #include <list> | 7 #include <list> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
12 #include "base/lazy_instance.h" | |
13 #include "base/logging.h" // For CHECK macros. | 12 #include "base/logging.h" // For CHECK macros. |
14 #include "base/memory/linked_ptr.h" | 13 #include "base/memory/linked_ptr.h" |
15 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" |
16 #include "base/message_loop/message_loop_proxy.h" | 15 #include "base/message_loop/message_loop_proxy.h" |
17 #include "base/run_loop.h" | 16 #include "base/run_loop.h" |
18 #include "base/strings/stringprintf.h" | 17 #include "base/strings/stringprintf.h" |
19 #include "base/sys_info.h" | 18 #include "base/sys_info.h" |
20 #include "base/threading/thread_local.h" | |
21 #include "base/values.h" | 19 #include "base/values.h" |
22 #include "chrome/test/chromedriver/capabilities.h" | 20 #include "chrome/test/chromedriver/capabilities.h" |
23 #include "chrome/test/chromedriver/chrome/chrome.h" | 21 #include "chrome/test/chromedriver/chrome/chrome.h" |
24 #include "chrome/test/chromedriver/chrome/chrome_android_impl.h" | |
25 #include "chrome/test/chromedriver/chrome/chrome_desktop_impl.h" | |
26 #include "chrome/test/chromedriver/chrome/device_manager.h" | |
27 #include "chrome/test/chromedriver/chrome/devtools_event_listener.h" | |
28 #include "chrome/test/chromedriver/chrome/status.h" | 22 #include "chrome/test/chromedriver/chrome/status.h" |
29 #include "chrome/test/chromedriver/chrome/version.h" | |
30 #include "chrome/test/chromedriver/chrome/web_view.h" | |
31 #include "chrome/test/chromedriver/chrome_launcher.h" | |
32 #include "chrome/test/chromedriver/logging.h" | 23 #include "chrome/test/chromedriver/logging.h" |
33 #include "chrome/test/chromedriver/net/net_util.h" | |
34 #include "chrome/test/chromedriver/net/url_request_context_getter.h" | |
35 #include "chrome/test/chromedriver/session.h" | 24 #include "chrome/test/chromedriver/session.h" |
36 #include "chrome/test/chromedriver/session_thread_map.h" | 25 #include "chrome/test/chromedriver/session_thread_map.h" |
37 #include "chrome/test/chromedriver/util.h" | 26 #include "chrome/test/chromedriver/util.h" |
38 | 27 |
39 void ExecuteGetStatus( | 28 void ExecuteGetStatus( |
40 const base::DictionaryValue& params, | 29 const base::DictionaryValue& params, |
41 const std::string& session_id, | 30 const std::string& session_id, |
42 const CommandCallback& callback) { | 31 const CommandCallback& callback) { |
43 base::DictionaryValue build; | 32 base::DictionaryValue build; |
44 build.SetString("version", "alpha"); | 33 build.SetString("version", "alpha"); |
45 | 34 |
46 base::DictionaryValue os; | 35 base::DictionaryValue os; |
47 os.SetString("name", base::SysInfo::OperatingSystemName()); | 36 os.SetString("name", base::SysInfo::OperatingSystemName()); |
48 os.SetString("version", base::SysInfo::OperatingSystemVersion()); | 37 os.SetString("version", base::SysInfo::OperatingSystemVersion()); |
49 os.SetString("arch", base::SysInfo::OperatingSystemArchitecture()); | 38 os.SetString("arch", base::SysInfo::OperatingSystemArchitecture()); |
50 | 39 |
51 base::DictionaryValue info; | 40 base::DictionaryValue info; |
52 info.Set("build", build.DeepCopy()); | 41 info.Set("build", build.DeepCopy()); |
53 info.Set("os", os.DeepCopy()); | 42 info.Set("os", os.DeepCopy()); |
54 callback.Run( | 43 callback.Run( |
55 Status(kOk), scoped_ptr<base::Value>(info.DeepCopy()), std::string()); | 44 Status(kOk), scoped_ptr<base::Value>(info.DeepCopy()), std::string()); |
56 } | 45 } |
57 | 46 |
58 NewSessionParams::NewSessionParams( | 47 void ExecuteCreateSession( |
59 SessionThreadMap* session_thread_map, | 48 SessionThreadMap* session_thread_map, |
60 scoped_refptr<URLRequestContextGetter> context_getter, | 49 const Command& init_session_cmd, |
61 const SyncWebSocketFactory& socket_factory, | |
62 DeviceManager* device_manager) | |
63 : session_thread_map(session_thread_map), | |
64 context_getter(context_getter), | |
65 socket_factory(socket_factory), | |
66 device_manager(device_manager) {} | |
67 | |
68 NewSessionParams::~NewSessionParams() {} | |
69 | |
70 namespace { | |
71 | |
72 base::LazyInstance<base::ThreadLocalPointer<Session> > | |
73 lazy_tls_session = LAZY_INSTANCE_INITIALIZER; | |
74 | |
75 Status CreateSessionOnSessionThreadHelper( | |
76 const NewSessionParams& bound_params, | |
77 const base::DictionaryValue& params, | |
78 const std::string& session_id, | |
79 scoped_ptr<base::Value>* out_value) { | |
80 const base::DictionaryValue* desired_caps; | |
81 if (!params.GetDictionary("desiredCapabilities", &desired_caps)) | |
82 return Status(kUnknownError, "cannot find dict 'desiredCapabilities'"); | |
83 | |
84 Capabilities capabilities; | |
85 Status status = capabilities.Parse(*desired_caps); | |
86 if (status.IsError()) | |
87 return status; | |
88 | |
89 // Create Log's and DevToolsEventListener's for ones that are DevTools-based. | |
90 // Session will own the Log's, Chrome will own the listeners. | |
91 ScopedVector<WebDriverLog> devtools_logs; | |
92 // TODO(kkania): Save this log in the session. | |
93 scoped_ptr<WebDriverLog> driver_log; | |
94 ScopedVector<DevToolsEventListener> devtools_event_listeners; | |
95 status = CreateLogs( | |
96 capabilities, &devtools_logs, &driver_log, &devtools_event_listeners); | |
97 if (status.IsError()) | |
98 return status; | |
99 | |
100 scoped_ptr<Chrome> chrome; | |
101 status = LaunchChrome(bound_params.context_getter.get(), | |
102 bound_params.socket_factory, | |
103 bound_params.device_manager, | |
104 capabilities, | |
105 devtools_event_listeners, | |
106 &chrome); | |
107 if (status.IsError()) | |
108 return status; | |
109 | |
110 std::list<std::string> web_view_ids; | |
111 status = chrome->GetWebViewIds(&web_view_ids); | |
112 if (status.IsError() || web_view_ids.empty()) { | |
113 chrome->Quit(); | |
114 return status.IsError() ? status : | |
115 Status(kUnknownError, "unable to discover open window in chrome"); | |
116 } | |
117 | |
118 scoped_ptr<Session> session(new Session(session_id, chrome.Pass())); | |
119 session->devtools_logs.swap(devtools_logs); | |
120 session->window = web_view_ids.front(); | |
121 session->detach = capabilities.detach; | |
122 session->force_devtools_screenshot = capabilities.force_devtools_screenshot; | |
123 out_value->reset(session->capabilities->DeepCopy()); | |
124 lazy_tls_session.Pointer()->Set(session.release()); | |
125 return Status(kOk); | |
126 } | |
127 | |
128 void CreateSessionOnSessionThread( | |
129 const scoped_refptr<base::SingleThreadTaskRunner>& cmd_task_runner, | |
130 const NewSessionParams& bound_params, | |
131 scoped_ptr<base::DictionaryValue> params, | |
132 const std::string& session_id, | |
133 const CommandCallback& callback_on_cmd) { | |
134 scoped_ptr<base::Value> value; | |
135 Status status = CreateSessionOnSessionThreadHelper( | |
136 bound_params, *params, session_id, &value); | |
137 cmd_task_runner->PostTask( | |
138 FROM_HERE, | |
139 base::Bind(callback_on_cmd, status, base::Passed(&value), session_id)); | |
140 } | |
141 | |
142 } // namespace | |
143 | |
144 void ExecuteNewSession( | |
145 const NewSessionParams& bound_params, | |
146 const base::DictionaryValue& params, | 50 const base::DictionaryValue& params, |
147 const std::string& session_id, | 51 const std::string& session_id, |
148 const CommandCallback& callback) { | 52 const CommandCallback& callback) { |
149 std::string new_id = session_id; | 53 std::string new_id = session_id; |
150 if (new_id.empty()) | 54 if (new_id.empty()) |
151 new_id = GenerateId(); | 55 new_id = GenerateId(); |
56 scoped_ptr<Session> session(new Session(new_id)); | |
152 scoped_ptr<base::Thread> thread(new base::Thread(new_id.c_str())); | 57 scoped_ptr<base::Thread> thread(new base::Thread(new_id.c_str())); |
153 if (!thread->Start()) { | 58 if (!thread->Start()) { |
154 callback.Run( | 59 callback.Run( |
155 Status(kUnknownError, "failed to start a thread for the new session"), | 60 Status(kUnknownError, "failed to start a thread for the new session"), |
156 scoped_ptr<base::Value>(), | 61 scoped_ptr<base::Value>(), |
157 std::string()); | 62 std::string()); |
158 return; | 63 return; |
159 } | 64 } |
160 | 65 |
161 thread->message_loop() | 66 thread->message_loop()->PostTask( |
162 ->PostTask(FROM_HERE, | 67 FROM_HERE, base::Bind(&SetThreadLocalSession, base::Passed(&session))); |
163 base::Bind(&CreateSessionOnSessionThread, | 68 session_thread_map |
164 base::MessageLoopProxy::current(), | |
165 bound_params, | |
166 base::Passed(make_scoped_ptr(params.DeepCopy())), | |
167 new_id, | |
168 callback)); | |
169 bound_params.session_thread_map | |
170 ->insert(std::make_pair(new_id, make_linked_ptr(thread.release()))); | 69 ->insert(std::make_pair(new_id, make_linked_ptr(thread.release()))); |
70 init_session_cmd.Run(params, new_id, callback); | |
chrisgao (Use stgao instead)
2013/09/06 21:20:13
I like this change, although it is a little hard f
kkania
2013/09/06 23:09:29
Done.
| |
171 } | 71 } |
172 | 72 |
173 namespace { | 73 namespace { |
174 | 74 |
175 void OnSessionQuit(const base::WeakPtr<size_t>& quit_remaining_count, | 75 void OnSessionQuit(const base::WeakPtr<size_t>& quit_remaining_count, |
176 const base::Closure& all_quit_func, | 76 const base::Closure& all_quit_func, |
177 const Status& status, | 77 const Status& status, |
178 scoped_ptr<base::Value> value, | 78 scoped_ptr<base::Value> value, |
179 const std::string& session_id) { | 79 const std::string& session_id) { |
180 // |quit_remaining_count| may no longer be valid if a timeout occurred. | 80 // |quit_remaining_count| may no longer be valid if a timeout occurred. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
220 } | 120 } |
221 | 121 |
222 namespace { | 122 namespace { |
223 | 123 |
224 void TerminateSessionThreadOnCommandThread(SessionThreadMap* session_thread_map, | 124 void TerminateSessionThreadOnCommandThread(SessionThreadMap* session_thread_map, |
225 const std::string& session_id) { | 125 const std::string& session_id) { |
226 session_thread_map->erase(session_id); | 126 session_thread_map->erase(session_id); |
227 } | 127 } |
228 | 128 |
229 void ExecuteSessionCommandOnSessionThread( | 129 void ExecuteSessionCommandOnSessionThread( |
130 const char* command_name, | |
230 const SessionCommand& command, | 131 const SessionCommand& command, |
231 bool return_ok_without_session, | 132 bool return_ok_without_session, |
232 scoped_ptr<base::DictionaryValue> params, | 133 scoped_ptr<base::DictionaryValue> params, |
233 scoped_refptr<base::SingleThreadTaskRunner> cmd_task_runner, | 134 scoped_refptr<base::SingleThreadTaskRunner> cmd_task_runner, |
234 const CommandCallback& callback_on_cmd, | 135 const CommandCallback& callback_on_cmd, |
235 const base::Closure& terminate_on_cmd) { | 136 const base::Closure& terminate_on_cmd) { |
236 Session* session = lazy_tls_session.Pointer()->Get(); | 137 Session* session = GetThreadLocalSession(); |
237 if (!session) { | 138 if (!session) { |
238 cmd_task_runner->PostTask( | 139 cmd_task_runner->PostTask( |
239 FROM_HERE, | 140 FROM_HERE, |
240 base::Bind(callback_on_cmd, | 141 base::Bind(callback_on_cmd, |
241 Status(return_ok_without_session ? kOk : kNoSuchSession), | 142 Status(return_ok_without_session ? kOk : kNoSuchSession), |
242 base::Passed(scoped_ptr<base::Value>()), | 143 base::Passed(scoped_ptr<base::Value>()), |
243 std::string())); | 144 std::string())); |
244 return; | 145 return; |
245 } | 146 } |
246 | 147 |
148 VLOG(0) << "COMMAND " << command_name << " " | |
chrisgao (Use stgao instead)
2013/09/06 21:20:13
I like command names than guessing from urls :)
Th
kkania
2013/09/06 23:09:29
Done.
| |
149 << PrettyPrintValue(*params); | |
chrisgao (Use stgao instead)
2013/09/06 21:20:13
No need to check if log is enabled?
kkania
2013/09/06 23:09:29
Done.
| |
247 scoped_ptr<base::Value> value; | 150 scoped_ptr<base::Value> value; |
248 Status status = command.Run(session, *params, &value); | 151 Status status = command.Run(session, *params, &value); |
249 if (status.IsError() && session->chrome) | 152 if (status.IsError() && session->chrome) |
250 status.AddDetails("Session info: chrome=" + session->chrome->GetVersion()); | 153 status.AddDetails("Session info: chrome=" + session->chrome->GetVersion()); |
251 | 154 |
155 if (IsVLogOn(0)) { | |
156 std::string result; | |
157 if (status.IsError()) { | |
158 result = status.message(); | |
159 } else if (value) { | |
160 result = FormatValueForDisplay(*value); | |
161 } | |
162 VLOG(0) << "RESPONSE " << command_name | |
163 << (result.length() ? " " + result : ""); | |
164 } | |
165 | |
252 cmd_task_runner->PostTask( | 166 cmd_task_runner->PostTask( |
253 FROM_HERE, | 167 FROM_HERE, |
254 base::Bind(callback_on_cmd, status, base::Passed(&value), session->id)); | 168 base::Bind(callback_on_cmd, status, base::Passed(&value), session->id)); |
255 | 169 |
256 if (session->quit) { | 170 if (session->quit) { |
257 lazy_tls_session.Pointer()->Set(NULL); | 171 SetThreadLocalSession(scoped_ptr<Session>()); |
258 delete session; | 172 delete session; |
259 cmd_task_runner->PostTask(FROM_HERE, terminate_on_cmd); | 173 cmd_task_runner->PostTask(FROM_HERE, terminate_on_cmd); |
260 } | 174 } |
261 } | 175 } |
262 | 176 |
263 } // namespace | 177 } // namespace |
264 | 178 |
265 void ExecuteSessionCommand( | 179 void ExecuteSessionCommand( |
266 SessionThreadMap* session_thread_map, | 180 SessionThreadMap* session_thread_map, |
181 const char* command_name, | |
267 const SessionCommand& command, | 182 const SessionCommand& command, |
268 bool return_ok_without_session, | 183 bool return_ok_without_session, |
269 const base::DictionaryValue& params, | 184 const base::DictionaryValue& params, |
270 const std::string& session_id, | 185 const std::string& session_id, |
271 const CommandCallback& callback) { | 186 const CommandCallback& callback) { |
272 SessionThreadMap::iterator iter = session_thread_map->find(session_id); | 187 SessionThreadMap::iterator iter = session_thread_map->find(session_id); |
273 if (iter == session_thread_map->end()) { | 188 if (iter == session_thread_map->end()) { |
274 Status status(return_ok_without_session ? kOk : kNoSuchSession); | 189 Status status(return_ok_without_session ? kOk : kNoSuchSession); |
275 callback.Run(status, scoped_ptr<base::Value>(), session_id); | 190 callback.Run(status, scoped_ptr<base::Value>(), session_id); |
276 } else { | 191 } else { |
277 iter->second->message_loop() | 192 iter->second->message_loop() |
278 ->PostTask(FROM_HERE, | 193 ->PostTask(FROM_HERE, |
279 base::Bind(&ExecuteSessionCommandOnSessionThread, | 194 base::Bind(&ExecuteSessionCommandOnSessionThread, |
195 command_name, | |
280 command, | 196 command, |
281 return_ok_without_session, | 197 return_ok_without_session, |
282 base::Passed(make_scoped_ptr(params.DeepCopy())), | 198 base::Passed(make_scoped_ptr(params.DeepCopy())), |
283 base::MessageLoopProxy::current(), | 199 base::MessageLoopProxy::current(), |
284 callback, | 200 callback, |
285 base::Bind(&TerminateSessionThreadOnCommandThread, | 201 base::Bind(&TerminateSessionThreadOnCommandThread, |
286 session_thread_map, | 202 session_thread_map, |
287 session_id))); | 203 session_id))); |
288 } | 204 } |
289 } | 205 } |
290 | 206 |
291 namespace internal { | 207 namespace internal { |
292 | 208 |
293 void CreateSessionOnSessionThreadForTesting(const std::string& id) { | 209 void CreateSessionOnSessionThreadForTesting(const std::string& id) { |
294 lazy_tls_session.Pointer()->Set(new Session(id)); | 210 SetThreadLocalSession(make_scoped_ptr(new Session(id))); |
295 } | 211 } |
296 | 212 |
297 } // namespace internal | 213 } // namespace internal |
OLD | NEW |