Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(394)

Side by Side Diff: chrome/test/chromedriver/chrome_launcher.cc

Issue 23643005: [chromedriver] Load the automation extension as a component extension. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 27 matching lines...) Expand all
38 #include "chrome/test/chromedriver/chrome/version.h" 38 #include "chrome/test/chromedriver/chrome/version.h"
39 #include "chrome/test/chromedriver/chrome/web_view.h" 39 #include "chrome/test/chromedriver/chrome/web_view.h"
40 #include "chrome/test/chromedriver/chrome/zip.h" 40 #include "chrome/test/chromedriver/chrome/zip.h"
41 #include "chrome/test/chromedriver/net/net_util.h" 41 #include "chrome/test/chromedriver/net/net_util.h"
42 #include "chrome/test/chromedriver/net/url_request_context_getter.h" 42 #include "chrome/test/chromedriver/net/url_request_context_getter.h"
43 #include "crypto/sha2.h" 43 #include "crypto/sha2.h"
44 44
45 namespace { 45 namespace {
46 46
47 const char* kCommonSwitches[] = { 47 const char* kCommonSwitches[] = {
48 "ignore-certificate-errors", "metrics-recording-only"}; 48 "ignore-certificate-errors", "metrics-recording-only"};
49 49
50 Status UnpackAutomationExtension(const base::FilePath& temp_dir, 50 Status UnpackAutomationExtension(const base::FilePath& temp_dir,
51 base::FilePath* automation_extension) { 51 base::FilePath* automation_extension) {
52 std::string decoded_extension; 52 std::string decoded_extension;
53 if (!base::Base64Decode(kAutomationExtension, &decoded_extension)) 53 if (!base::Base64Decode(kAutomationExtension, &decoded_extension))
54 return Status(kUnknownError, "failed to base64decode automation extension"); 54 return Status(kUnknownError, "failed to base64decode automation extension");
55 55
56 base::FilePath extension_zip = temp_dir.AppendASCII("internal.zip"); 56 base::FilePath extension_zip = temp_dir.AppendASCII("internal.zip");
57 int size = static_cast<int>(decoded_extension.length()); 57 int size = static_cast<int>(decoded_extension.length());
58 if (file_util::WriteFile(extension_zip, decoded_extension.c_str(), size) 58 if (file_util::WriteFile(extension_zip, decoded_extension.c_str(), size)
59 != size) { 59 != size) {
60 return Status(kUnknownError, "failed to write automation extension zip"); 60 return Status(kUnknownError, "failed to write automation extension zip");
61 } 61 }
62 62
63 base::FilePath extension_dir = temp_dir.AppendASCII("internal"); 63 base::FilePath extension_dir = temp_dir.AppendASCII("internal");
64 if (!zip::Unzip(extension_zip, extension_dir)) 64 if (!zip::Unzip(extension_zip, extension_dir))
65 return Status(kUnknownError, "failed to unzip automation extension"); 65 return Status(kUnknownError, "failed to unzip automation extension");
66 66
67 *automation_extension = extension_dir; 67 *automation_extension = extension_dir;
68 return Status(kOk); 68 return Status(kOk);
69 } 69 }
70 70
71 void AddSwitches(CommandLine* command,
72 const char* switches[],
73 size_t switch_count,
74 const std::set<std::string>& exclude_switches) {
75 for (size_t i = 0; i < switch_count; ++i) {
76 if (exclude_switches.find(switches[i]) == exclude_switches.end())
77 command->AppendSwitch(switches[i]);
78 }
79 }
80
81 Status PrepareCommandLine(int port, 71 Status PrepareCommandLine(int port,
82 const Capabilities& capabilities, 72 const Capabilities& capabilities,
83 CommandLine* prepared_command, 73 CommandLine* prepared_command,
84 base::ScopedTempDir* user_data_dir, 74 base::ScopedTempDir* user_data_dir,
85 base::ScopedTempDir* extension_dir, 75 base::ScopedTempDir* extension_dir,
86 std::vector<std::string>* extension_bg_pages) { 76 std::vector<std::string>* extension_bg_pages) {
87 CommandLine command = capabilities.command; 77 base::FilePath program = capabilities.binary;
88 base::FilePath program = command.GetProgram();
89 if (program.empty()) { 78 if (program.empty()) {
90 if (!FindChrome(&program)) 79 if (!FindChrome(&program))
91 return Status(kUnknownError, "cannot find Chrome binary"); 80 return Status(kUnknownError, "cannot find Chrome binary");
92 command.SetProgram(program);
93 } else if (!base::PathExists(program)) { 81 } else if (!base::PathExists(program)) {
94 return Status(kUnknownError, 82 return Status(kUnknownError,
95 base::StringPrintf("no chrome binary at %" PRFilePath, 83 base::StringPrintf("no chrome binary at %" PRFilePath,
96 program.value().c_str())); 84 program.value().c_str()));
97 } 85 }
86 CommandLine command(program);
87 Switches switches;
98 88
99 const char* excludable_switches[] = { 89 // TODO(chrisgao): Add "disable-sync" when chrome 30- is not supported.
100 "disable-hang-monitor", 90 // For chrome 30-, it leads to crash when opening chrome://settings.
101 "disable-prompt-on-repost", 91 for (size_t i = 0; i < arraysize(kCommonSwitches); ++i)
102 "full-memory-crash-report", 92 switches.SetSwitch(kCommonSwitches[i]);
103 "no-first-run", 93 switches.SetSwitch("disable-hang-monitor");
104 "disable-background-networking", 94 switches.SetSwitch("disable-prompt-on-repost");
105 // TODO(chrisgao): Add "disable-sync" when chrome 30- is not supported. 95 switches.SetSwitch("full-memory-crash-report");
106 // For chrome 30-, it leads to crash when opening chrome://settings. 96 switches.SetSwitch("no-first-run");
107 "disable-web-resources", 97 switches.SetSwitch("disable-background-networking");
108 "safebrowsing-disable-auto-update", 98 switches.SetSwitch("disable-web-resources");
109 "safebrowsing-disable-download-protection", 99 switches.SetSwitch("safebrowsing-disable-auto-update");
110 "disable-client-side-phishing-detection", 100 switches.SetSwitch("safebrowsing-disable-download-protection");
111 "disable-component-update", 101 switches.SetSwitch("disable-client-side-phishing-detection");
112 "disable-default-apps", 102 switches.SetSwitch("disable-component-update");
113 }; 103 switches.SetSwitch("disable-default-apps");
104 switches.SetSwitch("enable-logging");
105 switches.SetSwitch("logging-level", "1");
106 switches.SetSwitch("password-store", "basic");
107 switches.SetSwitch("use-mock-keychain");
108 switches.SetSwitch("remote-debugging-port", base::IntToString(port));
114 109
115 AddSwitches(&command, excludable_switches, arraysize(excludable_switches), 110 for (std::set<std::string>::const_iterator iter =
116 capabilities.exclude_switches); 111 capabilities.exclude_switches.begin();
117 AddSwitches(&command, kCommonSwitches, arraysize(kCommonSwitches), 112 iter != capabilities.exclude_switches.end();
118 capabilities.exclude_switches); 113 ++iter) {
114 switches.RemoveSwitch(*iter);
115 }
116 switches.SetFromSwitches(capabilities.switches);
119 117
120 command.AppendSwitch("enable-logging"); 118 if (!switches.HasSwitch("user-data-dir")) {
121 command.AppendSwitchASCII("logging-level", "1");
122 command.AppendSwitchASCII("password-store", "basic");
123 command.AppendSwitch("use-mock-keychain");
124 command.AppendSwitchASCII("remote-debugging-port", base::IntToString(port));
125
126 if (!command.HasSwitch("user-data-dir")) {
127 command.AppendArg("about:blank"); 119 command.AppendArg("about:blank");
128 if (!user_data_dir->CreateUniqueTempDir()) 120 if (!user_data_dir->CreateUniqueTempDir())
129 return Status(kUnknownError, "cannot create temp dir for user data dir"); 121 return Status(kUnknownError, "cannot create temp dir for user data dir");
130 command.AppendSwitchPath("user-data-dir", user_data_dir->path()); 122 switches.SetSwitch("user-data-dir", user_data_dir->path().value());
131 Status status = internal::PrepareUserDataDir( 123 Status status = internal::PrepareUserDataDir(
132 user_data_dir->path(), capabilities.prefs.get(), 124 user_data_dir->path(), capabilities.prefs.get(),
133 capabilities.local_state.get()); 125 capabilities.local_state.get());
134 if (status.IsError()) 126 if (status.IsError())
135 return status; 127 return status;
136 } 128 }
137 129
138 if (!extension_dir->CreateUniqueTempDir()) { 130 if (!extension_dir->CreateUniqueTempDir()) {
139 return Status(kUnknownError, 131 return Status(kUnknownError,
140 "cannot create temp dir for unpacking extensions"); 132 "cannot create temp dir for unpacking extensions");
141 } 133 }
142 Status status = internal::ProcessExtensions(capabilities.extensions, 134 Status status = internal::ProcessExtensions(capabilities.extensions,
143 extension_dir->path(), 135 extension_dir->path(),
144 true, 136 true,
145 &command, 137 &switches,
146 extension_bg_pages); 138 extension_bg_pages);
147 if (status.IsError()) 139 if (status.IsError())
148 return status; 140 return status;
149 141 switches.AppendToCommandLine(&command);
150 *prepared_command = command; 142 *prepared_command = command;
151 return Status(kOk); 143 return Status(kOk);
152 } 144 }
153 145
154 Status WaitForDevToolsAndCheckVersion( 146 Status WaitForDevToolsAndCheckVersion(
155 const NetAddress& address, 147 const NetAddress& address,
156 URLRequestContextGetter* context_getter, 148 URLRequestContextGetter* context_getter,
157 const SyncWebSocketFactory& socket_factory, 149 const SyncWebSocketFactory& socket_factory,
158 Log* log, 150 Log* log,
159 scoped_ptr<DevToolsHttpClient>* user_client) { 151 scoped_ptr<DevToolsHttpClient>* user_client) {
(...skipping 23 matching lines...) Expand all
183 Status LaunchExistingChromeSession( 175 Status LaunchExistingChromeSession(
184 URLRequestContextGetter* context_getter, 176 URLRequestContextGetter* context_getter,
185 const SyncWebSocketFactory& socket_factory, 177 const SyncWebSocketFactory& socket_factory,
186 Log* log, 178 Log* log,
187 const Capabilities& capabilities, 179 const Capabilities& capabilities,
188 ScopedVector<DevToolsEventListener>& devtools_event_listeners, 180 ScopedVector<DevToolsEventListener>& devtools_event_listeners,
189 scoped_ptr<Chrome>* chrome) { 181 scoped_ptr<Chrome>* chrome) {
190 Status status(kOk); 182 Status status(kOk);
191 scoped_ptr<DevToolsHttpClient> devtools_client; 183 scoped_ptr<DevToolsHttpClient> devtools_client;
192 status = WaitForDevToolsAndCheckVersion( 184 status = WaitForDevToolsAndCheckVersion(
193 capabilities.use_existing_browser, context_getter, socket_factory, log, 185 capabilities.debugger_address, context_getter, socket_factory, log,
194 &devtools_client); 186 &devtools_client);
195 if (status.IsError()) { 187 if (status.IsError()) {
196 return Status(kUnknownError, "cannot connect to chrome at " + 188 return Status(kUnknownError, "cannot connect to chrome at " +
197 capabilities.use_existing_browser.ToString(), 189 capabilities.debugger_address.ToString(),
198 status); 190 status);
199 } 191 }
200 chrome->reset(new ChromeExistingImpl(devtools_client.Pass(), 192 chrome->reset(new ChromeExistingImpl(devtools_client.Pass(),
201 devtools_event_listeners, 193 devtools_event_listeners,
202 log)); 194 log));
203 return Status(kOk); 195 return Status(kOk);
204 } 196 }
205 197
206 Status LaunchDesktopChrome( 198 Status LaunchDesktopChrome(
207 URLRequestContextGetter* context_getter, 199 URLRequestContextGetter* context_getter,
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 scoped_ptr<Device> device; 313 scoped_ptr<Device> device;
322 if (capabilities.android_device_serial.empty()) { 314 if (capabilities.android_device_serial.empty()) {
323 status = device_manager->AcquireDevice(&device); 315 status = device_manager->AcquireDevice(&device);
324 } else { 316 } else {
325 status = device_manager->AcquireSpecificDevice( 317 status = device_manager->AcquireSpecificDevice(
326 capabilities.android_device_serial, &device); 318 capabilities.android_device_serial, &device);
327 } 319 }
328 if (!status.IsOk()) 320 if (!status.IsOk())
329 return status; 321 return status;
330 322
331 std::string args(capabilities.android_args); 323 Switches switches(capabilities.switches);
332 for (size_t i = 0; i < arraysize(kCommonSwitches); i++) 324 for (size_t i = 0; i < arraysize(kCommonSwitches); ++i)
333 args += "--" + std::string(kCommonSwitches[i]) + " "; 325 switches.SetSwitch(kCommonSwitches[i]);
334 args += "--disable-fre --enable-remote-debugging"; 326 switches.SetSwitch("disable-fre");
335 327 switches.SetSwitch("enable-remote-debugging");
336 status = device->StartApp(capabilities.android_package, 328 status = device->StartApp(capabilities.android_package,
337 capabilities.android_activity, 329 capabilities.android_activity,
338 capabilities.android_process, 330 capabilities.android_process,
339 args, port); 331 switches.ToString(), port);
340 if (!status.IsOk()) { 332 if (!status.IsOk()) {
341 device->StopApp(); 333 device->StopApp();
342 return status; 334 return status;
343 } 335 }
344 336
345 scoped_ptr<DevToolsHttpClient> devtools_client; 337 scoped_ptr<DevToolsHttpClient> devtools_client;
346 status = WaitForDevToolsAndCheckVersion(NetAddress(port), 338 status = WaitForDevToolsAndCheckVersion(NetAddress(port),
347 context_getter, 339 context_getter,
348 socket_factory, 340 socket_factory,
349 log, 341 log,
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 Status status = GetExtensionBackgroundPage(manifest, id, &bg_page_tmp); 485 Status status = GetExtensionBackgroundPage(manifest, id, &bg_page_tmp);
494 if (status.IsError()) 486 if (status.IsError())
495 return status; 487 return status;
496 488
497 *path = extension_dir; 489 *path = extension_dir;
498 if (bg_page_tmp.size()) 490 if (bg_page_tmp.size())
499 *bg_page = bg_page_tmp; 491 *bg_page = bg_page_tmp;
500 return Status(kOk); 492 return Status(kOk);
501 } 493 }
502 494
495 void UpdateExtensionSwitch(Switches* switches,
496 const char name[],
497 const base::FilePath::StringType& extension) {
498 base::FilePath::StringType value = switches->GetSwitchValueNative(name);
499 if (value.length())
500 value += FILE_PATH_LITERAL(",");
501 value += extension;
502 switches->SetSwitch(name, value);
503 }
504
503 Status ProcessExtensions(const std::vector<std::string>& extensions, 505 Status ProcessExtensions(const std::vector<std::string>& extensions,
504 const base::FilePath& temp_dir, 506 const base::FilePath& temp_dir,
505 bool include_automation_extension, 507 bool include_automation_extension,
506 CommandLine* command, 508 Switches* switches,
507 std::vector<std::string>* bg_pages) { 509 std::vector<std::string>* bg_pages) {
508 std::vector<std::string> bg_pages_tmp; 510 std::vector<std::string> bg_pages_tmp;
509 std::vector<base::FilePath::StringType> extension_paths; 511 std::vector<base::FilePath::StringType> extension_paths;
510 for (size_t i = 0; i < extensions.size(); ++i) { 512 for (size_t i = 0; i < extensions.size(); ++i) {
511 base::FilePath path; 513 base::FilePath path;
512 std::string bg_page; 514 std::string bg_page;
513 Status status = ProcessExtension(extensions[i], temp_dir, &path, &bg_page); 515 Status status = ProcessExtension(extensions[i], temp_dir, &path, &bg_page);
514 if (status.IsError()) { 516 if (status.IsError()) {
515 return Status( 517 return Status(
516 kUnknownError, 518 kUnknownError,
517 base::StringPrintf("cannot process extension #%" PRIuS, i + 1), 519 base::StringPrintf("cannot process extension #%" PRIuS, i + 1),
518 status); 520 status);
519 } 521 }
520 extension_paths.push_back(path.value()); 522 extension_paths.push_back(path.value());
521 if (bg_page.length()) 523 if (bg_page.length())
522 bg_pages_tmp.push_back(bg_page); 524 bg_pages_tmp.push_back(bg_page);
523 } 525 }
524 526
525 if (include_automation_extension) { 527 if (include_automation_extension) {
526 base::FilePath automation_extension; 528 base::FilePath automation_extension;
527 Status status = UnpackAutomationExtension(temp_dir, &automation_extension); 529 Status status = UnpackAutomationExtension(temp_dir, &automation_extension);
528 if (status.IsError()) 530 if (status.IsError())
529 return status; 531 return status;
530 if (command->HasSwitch("disable-extensions")) { 532 if (switches->HasSwitch("disable-extensions")) {
531 command->AppendSwitchNative("load-component-extension", 533 UpdateExtensionSwitch(switches, "load-component-extension",
532 automation_extension.value()); 534 automation_extension.value());
533 } else { 535 } else {
534 extension_paths.push_back(automation_extension.value()); 536 extension_paths.push_back(automation_extension.value());
535 } 537 }
536 } 538 }
537 539
538 if (extension_paths.size()) { 540 if (extension_paths.size()) {
539 base::FilePath::StringType extension_paths_value = JoinString( 541 base::FilePath::StringType extension_paths_value = JoinString(
540 extension_paths, FILE_PATH_LITERAL(',')); 542 extension_paths, FILE_PATH_LITERAL(','));
541 command->AppendSwitchNative("load-extension", extension_paths_value); 543 UpdateExtensionSwitch(switches, "load-extension", extension_paths_value);
542 } 544 }
543 bg_pages->swap(bg_pages_tmp); 545 bg_pages->swap(bg_pages_tmp);
544 return Status(kOk); 546 return Status(kOk);
545 } 547 }
546 548
547 Status WritePrefsFile( 549 Status WritePrefsFile(
548 const std::string& template_string, 550 const std::string& template_string,
549 const base::DictionaryValue* custom_prefs, 551 const base::DictionaryValue* custom_prefs,
550 const base::FilePath& path) { 552 const base::FilePath& path) {
551 int code; 553 int code;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 // Write empty "First Run" file, otherwise Chrome will wipe the default 601 // Write empty "First Run" file, otherwise Chrome will wipe the default
600 // profile that was written. 602 // profile that was written.
601 if (file_util::WriteFile( 603 if (file_util::WriteFile(
602 user_data_dir.AppendASCII("First Run"), "", 0) != 0) { 604 user_data_dir.AppendASCII("First Run"), "", 0) != 0) {
603 return Status(kUnknownError, "failed to write first run file"); 605 return Status(kUnknownError, "failed to write first run file");
604 } 606 }
605 return Status(kOk); 607 return Status(kOk);
606 } 608 }
607 609
608 } // namespace internal 610 } // namespace internal
OLDNEW
« no previous file with comments | « chrome/test/chromedriver/chrome_launcher.h ('k') | chrome/test/chromedriver/chrome_launcher_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698