| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/chrome_launcher.h" | 5 #include "chrome/test/chromedriver/chrome_launcher.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/base64.h" | 10 #include "base/base64.h" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 #include "base/threading/platform_thread.h" | 25 #include "base/threading/platform_thread.h" |
| 26 #include "base/time/time.h" | 26 #include "base/time/time.h" |
| 27 #include "base/values.h" | 27 #include "base/values.h" |
| 28 #include "chrome/test/chromedriver/chrome/chrome_android_impl.h" | 28 #include "chrome/test/chromedriver/chrome/chrome_android_impl.h" |
| 29 #include "chrome/test/chromedriver/chrome/chrome_desktop_impl.h" | 29 #include "chrome/test/chromedriver/chrome/chrome_desktop_impl.h" |
| 30 #include "chrome/test/chromedriver/chrome/chrome_existing_impl.h" | 30 #include "chrome/test/chromedriver/chrome/chrome_existing_impl.h" |
| 31 #include "chrome/test/chromedriver/chrome/chrome_finder.h" | 31 #include "chrome/test/chromedriver/chrome/chrome_finder.h" |
| 32 #include "chrome/test/chromedriver/chrome/device_manager.h" | 32 #include "chrome/test/chromedriver/chrome/device_manager.h" |
| 33 #include "chrome/test/chromedriver/chrome/devtools_http_client.h" | 33 #include "chrome/test/chromedriver/chrome/devtools_http_client.h" |
| 34 #include "chrome/test/chromedriver/chrome/embedded_automation_extension.h" | 34 #include "chrome/test/chromedriver/chrome/embedded_automation_extension.h" |
| 35 #include "chrome/test/chromedriver/chrome/log.h" | |
| 36 #include "chrome/test/chromedriver/chrome/status.h" | 35 #include "chrome/test/chromedriver/chrome/status.h" |
| 37 #include "chrome/test/chromedriver/chrome/user_data_dir.h" | 36 #include "chrome/test/chromedriver/chrome/user_data_dir.h" |
| 38 #include "chrome/test/chromedriver/chrome/version.h" | 37 #include "chrome/test/chromedriver/chrome/version.h" |
| 39 #include "chrome/test/chromedriver/chrome/web_view.h" | 38 #include "chrome/test/chromedriver/chrome/web_view.h" |
| 40 #include "chrome/test/chromedriver/chrome/zip.h" | 39 #include "chrome/test/chromedriver/chrome/zip.h" |
| 41 #include "chrome/test/chromedriver/net/net_util.h" | 40 #include "chrome/test/chromedriver/net/net_util.h" |
| 42 #include "chrome/test/chromedriver/net/url_request_context_getter.h" | 41 #include "chrome/test/chromedriver/net/url_request_context_getter.h" |
| 43 #include "crypto/sha2.h" | 42 #include "crypto/sha2.h" |
| 44 | 43 |
| 45 namespace { | 44 namespace { |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 return status; | 139 return status; |
| 141 switches.AppendToCommandLine(&command); | 140 switches.AppendToCommandLine(&command); |
| 142 *prepared_command = command; | 141 *prepared_command = command; |
| 143 return Status(kOk); | 142 return Status(kOk); |
| 144 } | 143 } |
| 145 | 144 |
| 146 Status WaitForDevToolsAndCheckVersion( | 145 Status WaitForDevToolsAndCheckVersion( |
| 147 const NetAddress& address, | 146 const NetAddress& address, |
| 148 URLRequestContextGetter* context_getter, | 147 URLRequestContextGetter* context_getter, |
| 149 const SyncWebSocketFactory& socket_factory, | 148 const SyncWebSocketFactory& socket_factory, |
| 150 Log* log, | |
| 151 scoped_ptr<DevToolsHttpClient>* user_client) { | 149 scoped_ptr<DevToolsHttpClient>* user_client) { |
| 152 scoped_ptr<DevToolsHttpClient> client(new DevToolsHttpClient( | 150 scoped_ptr<DevToolsHttpClient> client(new DevToolsHttpClient( |
| 153 address, context_getter, socket_factory, log)); | 151 address, context_getter, socket_factory)); |
| 154 base::TimeTicks deadline = | 152 base::TimeTicks deadline = |
| 155 base::TimeTicks::Now() + base::TimeDelta::FromSeconds(20); | 153 base::TimeTicks::Now() + base::TimeDelta::FromSeconds(20); |
| 156 Status status = client->Init(deadline - base::TimeTicks::Now()); | 154 Status status = client->Init(deadline - base::TimeTicks::Now()); |
| 157 if (status.IsError()) | 155 if (status.IsError()) |
| 158 return status; | 156 return status; |
| 159 if (client->build_no() < kMinimumSupportedChromeBuildNo) { | 157 if (client->build_no() < kMinimumSupportedChromeBuildNo) { |
| 160 return Status(kUnknownError, "Chrome version must be >= " + | 158 return Status(kUnknownError, "Chrome version must be >= " + |
| 161 GetMinimumSupportedChromeVersion()); | 159 GetMinimumSupportedChromeVersion()); |
| 162 } | 160 } |
| 163 | 161 |
| 164 while (base::TimeTicks::Now() < deadline) { | 162 while (base::TimeTicks::Now() < deadline) { |
| 165 WebViewsInfo views_info; | 163 WebViewsInfo views_info; |
| 166 client->GetWebViewsInfo(&views_info); | 164 client->GetWebViewsInfo(&views_info); |
| 167 for (size_t i = 0; i < views_info.GetSize(); ++i) { | 165 for (size_t i = 0; i < views_info.GetSize(); ++i) { |
| 168 if (views_info.Get(i).type == WebViewInfo::kPage) { | 166 if (views_info.Get(i).type == WebViewInfo::kPage) { |
| 169 *user_client = client.Pass(); | 167 *user_client = client.Pass(); |
| 170 return Status(kOk); | 168 return Status(kOk); |
| 171 } | 169 } |
| 172 } | 170 } |
| 173 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50)); | 171 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50)); |
| 174 } | 172 } |
| 175 return Status(kUnknownError, "unable to discover open pages"); | 173 return Status(kUnknownError, "unable to discover open pages"); |
| 176 } | 174 } |
| 177 | 175 |
| 178 Status LaunchExistingChromeSession( | 176 Status LaunchExistingChromeSession( |
| 179 URLRequestContextGetter* context_getter, | 177 URLRequestContextGetter* context_getter, |
| 180 const SyncWebSocketFactory& socket_factory, | 178 const SyncWebSocketFactory& socket_factory, |
| 181 Log* log, | |
| 182 const Capabilities& capabilities, | 179 const Capabilities& capabilities, |
| 183 ScopedVector<DevToolsEventListener>& devtools_event_listeners, | 180 ScopedVector<DevToolsEventListener>& devtools_event_listeners, |
| 184 scoped_ptr<Chrome>* chrome) { | 181 scoped_ptr<Chrome>* chrome) { |
| 185 Status status(kOk); | 182 Status status(kOk); |
| 186 scoped_ptr<DevToolsHttpClient> devtools_client; | 183 scoped_ptr<DevToolsHttpClient> devtools_client; |
| 187 status = WaitForDevToolsAndCheckVersion( | 184 status = WaitForDevToolsAndCheckVersion( |
| 188 capabilities.debugger_address, context_getter, socket_factory, log, | 185 capabilities.debugger_address, context_getter, socket_factory, |
| 189 &devtools_client); | 186 &devtools_client); |
| 190 if (status.IsError()) { | 187 if (status.IsError()) { |
| 191 return Status(kUnknownError, "cannot connect to chrome at " + | 188 return Status(kUnknownError, "cannot connect to chrome at " + |
| 192 capabilities.debugger_address.ToString(), | 189 capabilities.debugger_address.ToString(), |
| 193 status); | 190 status); |
| 194 } | 191 } |
| 195 chrome->reset(new ChromeExistingImpl(devtools_client.Pass(), | 192 chrome->reset(new ChromeExistingImpl(devtools_client.Pass(), |
| 196 devtools_event_listeners, | 193 devtools_event_listeners)); |
| 197 log)); | |
| 198 return Status(kOk); | 194 return Status(kOk); |
| 199 } | 195 } |
| 200 | 196 |
| 201 Status LaunchDesktopChrome( | 197 Status LaunchDesktopChrome( |
| 202 URLRequestContextGetter* context_getter, | 198 URLRequestContextGetter* context_getter, |
| 203 int port, | 199 int port, |
| 204 const SyncWebSocketFactory& socket_factory, | 200 const SyncWebSocketFactory& socket_factory, |
| 205 Log* log, | |
| 206 const Capabilities& capabilities, | 201 const Capabilities& capabilities, |
| 207 ScopedVector<DevToolsEventListener>& devtools_event_listeners, | 202 ScopedVector<DevToolsEventListener>& devtools_event_listeners, |
| 208 scoped_ptr<Chrome>* chrome) { | 203 scoped_ptr<Chrome>* chrome) { |
| 209 CommandLine command(CommandLine::NO_PROGRAM); | 204 CommandLine command(CommandLine::NO_PROGRAM); |
| 210 base::ScopedTempDir user_data_dir; | 205 base::ScopedTempDir user_data_dir; |
| 211 base::ScopedTempDir extension_dir; | 206 base::ScopedTempDir extension_dir; |
| 212 std::vector<std::string> extension_bg_pages; | 207 std::vector<std::string> extension_bg_pages; |
| 213 Status status = PrepareCommandLine(port, | 208 Status status = PrepareCommandLine(port, |
| 214 capabilities, | 209 capabilities, |
| 215 &command, | 210 &command, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 226 options.environ["CHROME_LOG_FILE"] = capabilities.log_path; | 221 options.environ["CHROME_LOG_FILE"] = capabilities.log_path; |
| 227 if (capabilities.detach) | 222 if (capabilities.detach) |
| 228 options.new_process_group = true; | 223 options.new_process_group = true; |
| 229 #endif | 224 #endif |
| 230 | 225 |
| 231 #if defined(OS_WIN) | 226 #if defined(OS_WIN) |
| 232 std::string command_string = base::WideToUTF8(command.GetCommandLineString()); | 227 std::string command_string = base::WideToUTF8(command.GetCommandLineString()); |
| 233 #else | 228 #else |
| 234 std::string command_string = command.GetCommandLineString(); | 229 std::string command_string = command.GetCommandLineString(); |
| 235 #endif | 230 #endif |
| 236 log->AddEntry(Log::kLog, "Launching chrome: " + command_string); | 231 VLOG(0) << "Launching chrome: " << command_string; |
| 237 base::ProcessHandle process; | 232 base::ProcessHandle process; |
| 238 if (!base::LaunchProcess(command, options, &process)) | 233 if (!base::LaunchProcess(command, options, &process)) |
| 239 return Status(kUnknownError, "chrome failed to start"); | 234 return Status(kUnknownError, "chrome failed to start"); |
| 240 | 235 |
| 241 scoped_ptr<DevToolsHttpClient> devtools_client; | 236 scoped_ptr<DevToolsHttpClient> devtools_client; |
| 242 status = WaitForDevToolsAndCheckVersion( | 237 status = WaitForDevToolsAndCheckVersion( |
| 243 NetAddress(port), context_getter, socket_factory, log, &devtools_client); | 238 NetAddress(port), context_getter, socket_factory, &devtools_client); |
| 244 | 239 |
| 245 if (status.IsError()) { | 240 if (status.IsError()) { |
| 246 int exit_code; | 241 int exit_code; |
| 247 base::TerminationStatus chrome_status = | 242 base::TerminationStatus chrome_status = |
| 248 base::GetTerminationStatus(process, &exit_code); | 243 base::GetTerminationStatus(process, &exit_code); |
| 249 if (chrome_status != base::TERMINATION_STATUS_STILL_RUNNING) { | 244 if (chrome_status != base::TERMINATION_STATUS_STILL_RUNNING) { |
| 250 std::string termination_reason; | 245 std::string termination_reason; |
| 251 switch (chrome_status) { | 246 switch (chrome_status) { |
| 252 case base::TERMINATION_STATUS_NORMAL_TERMINATION: | 247 case base::TERMINATION_STATUS_NORMAL_TERMINATION: |
| 253 termination_reason = "exited normally"; | 248 termination_reason = "exited normally"; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 272 int exit_code; | 267 int exit_code; |
| 273 if (base::GetTerminationStatus(process, &exit_code) == | 268 if (base::GetTerminationStatus(process, &exit_code) == |
| 274 base::TERMINATION_STATUS_STILL_RUNNING) | 269 base::TERMINATION_STATUS_STILL_RUNNING) |
| 275 return Status(kUnknownError, "cannot kill Chrome", status); | 270 return Status(kUnknownError, "cannot kill Chrome", status); |
| 276 } | 271 } |
| 277 return status; | 272 return status; |
| 278 } | 273 } |
| 279 scoped_ptr<ChromeDesktopImpl> chrome_desktop( | 274 scoped_ptr<ChromeDesktopImpl> chrome_desktop( |
| 280 new ChromeDesktopImpl(devtools_client.Pass(), | 275 new ChromeDesktopImpl(devtools_client.Pass(), |
| 281 devtools_event_listeners, | 276 devtools_event_listeners, |
| 282 log, | |
| 283 process, | 277 process, |
| 284 &user_data_dir, | 278 &user_data_dir, |
| 285 &extension_dir)); | 279 &extension_dir)); |
| 286 for (size_t i = 0; i < extension_bg_pages.size(); ++i) { | 280 for (size_t i = 0; i < extension_bg_pages.size(); ++i) { |
| 287 scoped_ptr<WebView> web_view; | 281 scoped_ptr<WebView> web_view; |
| 288 Status status = chrome_desktop->WaitForPageToLoad( | 282 Status status = chrome_desktop->WaitForPageToLoad( |
| 289 extension_bg_pages[i], base::TimeDelta::FromSeconds(10), &web_view); | 283 extension_bg_pages[i], base::TimeDelta::FromSeconds(10), &web_view); |
| 290 if (status.IsError()) { | 284 if (status.IsError()) { |
| 291 return Status(kUnknownError, | 285 return Status(kUnknownError, |
| 292 "failed to wait for extension background page to load: " + | 286 "failed to wait for extension background page to load: " + |
| 293 extension_bg_pages[i], | 287 extension_bg_pages[i], |
| 294 status); | 288 status); |
| 295 } | 289 } |
| 296 } | 290 } |
| 297 *chrome = chrome_desktop.Pass(); | 291 *chrome = chrome_desktop.Pass(); |
| 298 return Status(kOk); | 292 return Status(kOk); |
| 299 } | 293 } |
| 300 | 294 |
| 301 Status LaunchAndroidChrome( | 295 Status LaunchAndroidChrome( |
| 302 URLRequestContextGetter* context_getter, | 296 URLRequestContextGetter* context_getter, |
| 303 int port, | 297 int port, |
| 304 const SyncWebSocketFactory& socket_factory, | 298 const SyncWebSocketFactory& socket_factory, |
| 305 Log* log, | |
| 306 const Capabilities& capabilities, | 299 const Capabilities& capabilities, |
| 307 ScopedVector<DevToolsEventListener>& devtools_event_listeners, | 300 ScopedVector<DevToolsEventListener>& devtools_event_listeners, |
| 308 DeviceManager* device_manager, | 301 DeviceManager* device_manager, |
| 309 scoped_ptr<Chrome>* chrome) { | 302 scoped_ptr<Chrome>* chrome) { |
| 310 Status status(kOk); | 303 Status status(kOk); |
| 311 scoped_ptr<Device> device; | 304 scoped_ptr<Device> device; |
| 312 if (capabilities.android_device_serial.empty()) { | 305 if (capabilities.android_device_serial.empty()) { |
| 313 status = device_manager->AcquireDevice(&device); | 306 status = device_manager->AcquireDevice(&device); |
| 314 } else { | 307 } else { |
| 315 status = device_manager->AcquireSpecificDevice( | 308 status = device_manager->AcquireSpecificDevice( |
| (...skipping 13 matching lines...) Expand all Loading... |
| 329 switches.ToString(), port); | 322 switches.ToString(), port); |
| 330 if (!status.IsOk()) { | 323 if (!status.IsOk()) { |
| 331 device->StopApp(); | 324 device->StopApp(); |
| 332 return status; | 325 return status; |
| 333 } | 326 } |
| 334 | 327 |
| 335 scoped_ptr<DevToolsHttpClient> devtools_client; | 328 scoped_ptr<DevToolsHttpClient> devtools_client; |
| 336 status = WaitForDevToolsAndCheckVersion(NetAddress(port), | 329 status = WaitForDevToolsAndCheckVersion(NetAddress(port), |
| 337 context_getter, | 330 context_getter, |
| 338 socket_factory, | 331 socket_factory, |
| 339 log, | |
| 340 &devtools_client); | 332 &devtools_client); |
| 341 if (status.IsError()) | 333 if (status.IsError()) |
| 342 return status; | 334 return status; |
| 343 | 335 |
| 344 chrome->reset(new ChromeAndroidImpl( | 336 chrome->reset(new ChromeAndroidImpl( |
| 345 devtools_client.Pass(), devtools_event_listeners, device.Pass(), log)); | 337 devtools_client.Pass(), devtools_event_listeners, device.Pass())); |
| 346 return Status(kOk); | 338 return Status(kOk); |
| 347 } | 339 } |
| 348 | 340 |
| 349 } // namespace | 341 } // namespace |
| 350 | 342 |
| 351 Status LaunchChrome( | 343 Status LaunchChrome( |
| 352 URLRequestContextGetter* context_getter, | 344 URLRequestContextGetter* context_getter, |
| 353 const SyncWebSocketFactory& socket_factory, | 345 const SyncWebSocketFactory& socket_factory, |
| 354 Log* log, | |
| 355 DeviceManager* device_manager, | 346 DeviceManager* device_manager, |
| 356 const Capabilities& capabilities, | 347 const Capabilities& capabilities, |
| 357 ScopedVector<DevToolsEventListener>& devtools_event_listeners, | 348 ScopedVector<DevToolsEventListener>& devtools_event_listeners, |
| 358 scoped_ptr<Chrome>* chrome) { | 349 scoped_ptr<Chrome>* chrome) { |
| 359 if (capabilities.IsExistingBrowser()) { | 350 if (capabilities.IsExistingBrowser()) { |
| 360 return LaunchExistingChromeSession( | 351 return LaunchExistingChromeSession( |
| 361 context_getter, socket_factory, | 352 context_getter, socket_factory, |
| 362 log, capabilities, devtools_event_listeners, chrome); | 353 capabilities, devtools_event_listeners, chrome); |
| 363 } | 354 } |
| 364 | 355 |
| 365 int port; | 356 int port; |
| 366 if (!FindOpenPort(&port)) | 357 if (!FindOpenPort(&port)) |
| 367 return Status(kUnknownError, "failed to find an open port for Chrome"); | 358 return Status(kUnknownError, "failed to find an open port for Chrome"); |
| 368 | 359 |
| 369 if (capabilities.IsAndroid()) { | 360 if (capabilities.IsAndroid()) { |
| 370 return LaunchAndroidChrome( | 361 return LaunchAndroidChrome( |
| 371 context_getter, port, socket_factory, log, capabilities, | 362 context_getter, port, socket_factory, capabilities, |
| 372 devtools_event_listeners, device_manager, chrome); | 363 devtools_event_listeners, device_manager, chrome); |
| 373 } else { | 364 } else { |
| 374 return LaunchDesktopChrome( | 365 return LaunchDesktopChrome( |
| 375 context_getter, port, socket_factory, log, capabilities, | 366 context_getter, port, socket_factory, capabilities, |
| 376 devtools_event_listeners, chrome); | 367 devtools_event_listeners, chrome); |
| 377 } | 368 } |
| 378 } | 369 } |
| 379 | 370 |
| 380 namespace internal { | 371 namespace internal { |
| 381 | 372 |
| 382 void ConvertHexadecimalToIDAlphabet(std::string* id) { | 373 void ConvertHexadecimalToIDAlphabet(std::string* id) { |
| 383 for (size_t i = 0; i < id->size(); ++i) { | 374 for (size_t i = 0; i < id->size(); ++i) { |
| 384 int val; | 375 int val; |
| 385 if (base::HexStringToInt(base::StringPiece(id->begin() + i, | 376 if (base::HexStringToInt(base::StringPiece(id->begin() + i, |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 599 // Write empty "First Run" file, otherwise Chrome will wipe the default | 590 // Write empty "First Run" file, otherwise Chrome will wipe the default |
| 600 // profile that was written. | 591 // profile that was written. |
| 601 if (file_util::WriteFile( | 592 if (file_util::WriteFile( |
| 602 user_data_dir.AppendASCII("First Run"), "", 0) != 0) { | 593 user_data_dir.AppendASCII("First Run"), "", 0) != 0) { |
| 603 return Status(kUnknownError, "failed to write first run file"); | 594 return Status(kUnknownError, "failed to write first run file"); |
| 604 } | 595 } |
| 605 return Status(kOk); | 596 return Status(kOk); |
| 606 } | 597 } |
| 607 | 598 |
| 608 } // namespace internal | 599 } // namespace internal |
| OLD | NEW |