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

Side by Side Diff: chrome/test/webdriver/webdriver_automation.cc

Issue 23526047: Delete old chromedriver code, and remove mongoose webserver. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
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 | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/test/webdriver/webdriver_automation.h"
6
7 #if defined(OS_WIN)
8 #include <windows.h>
9 #endif
10
11 #include "base/base_paths.h"
12 #include "base/basictypes.h"
13 #include "base/callback.h"
14 #include "base/environment.h"
15 #include "base/file_util.h"
16 #include "base/files/file_path.h"
17 #include "base/json/json_writer.h"
18 #include "base/memory/ref_counted.h"
19 #include "base/path_service.h"
20 #include "base/strings/string_number_conversions.h"
21 #include "base/strings/string_split.h"
22 #include "base/strings/stringprintf.h"
23 #include "base/strings/utf_string_conversions.h"
24 #include "base/synchronization/waitable_event.h"
25 #include "base/values.h"
26 #include "chrome/common/automation_constants.h"
27 #include "chrome/common/automation_messages.h"
28 #include "chrome/common/chrome_constants.h"
29 #include "chrome/common/chrome_switches.h"
30 #include "chrome/common/url_constants.h"
31 #include "chrome/test/automation/automation_json_requests.h"
32 #include "chrome/test/automation/automation_proxy.h"
33 #include "chrome/test/automation/browser_proxy.h"
34 #include "chrome/test/automation/proxy_launcher.h"
35 #include "chrome/test/automation/tab_proxy.h"
36 #include "chrome/test/base/chrome_process_util.h"
37 #include "chrome/test/webdriver/frame_path.h"
38 #include "chrome/test/webdriver/webdriver_basic_types.h"
39 #include "chrome/test/webdriver/webdriver_error.h"
40 #include "chrome/test/webdriver/webdriver_util.h"
41
42 #if defined(OS_WIN)
43 #include "base/win/registry.h"
44 #include "base/win/windows_version.h"
45 #endif
46
47 namespace {
48
49 // Iterates through each browser executable path, and checks if the path exists
50 // in any of the given locations. If found, returns true and sets |browser_exe|.
51 bool CheckForChromeExe(const std::vector<base::FilePath>& browser_exes,
52 const std::vector<base::FilePath>& locations,
53 base::FilePath* browser_exe) {
54 for (size_t i = 0; i < browser_exes.size(); ++i) {
55 for (size_t j = 0; j < locations.size(); ++j) {
56 base::FilePath path = locations[j].Append(browser_exes[i]);
57 if (base::PathExists(path)) {
58 *browser_exe = path;
59 return true;
60 }
61 }
62 }
63 return false;
64 }
65
66 // Gets the path to the default Chrome executable. Returns true on success.
67 bool GetDefaultChromeExe(base::FilePath* browser_exe) {
68 // Instead of using chrome constants, we hardcode these constants here so
69 // that we can locate chrome or chromium regardless of the branding
70 // chromedriver is built with. It may be argued that then we need to keep
71 // these in sync with chrome constants. However, if chrome constants changes,
72 // we need to look for the previous and new versions to support some
73 // backwards compatibility.
74 #if defined(OS_WIN)
75 base::FilePath browser_exes_array[] = {
76 base::FilePath(L"chrome.exe")
77 };
78 #elif defined(OS_MACOSX)
79 base::FilePath browser_exes_array[] = {
80 base::FilePath("Google Chrome.app/Contents/MacOS/Google Chrome"),
81 base::FilePath("Chromium.app/Contents/MacOS/Chromium")
82 };
83 #elif defined(OS_LINUX)
84 base::FilePath browser_exes_array[] = {
85 base::FilePath("google-chrome"),
86 base::FilePath("chrome"),
87 base::FilePath("chromium"),
88 base::FilePath("chromium-browser")
89 };
90 #endif
91 std::vector<base::FilePath> browser_exes(
92 browser_exes_array, browser_exes_array + arraysize(browser_exes_array));
93
94 // Step 1: Check the directory this module resides in. This is done
95 // before all else so that the tests will pickup the built chrome.
96 base::FilePath module_dir;
97 if (PathService::Get(base::DIR_MODULE, &module_dir)) {
98 for (size_t j = 0; j < browser_exes.size(); ++j) {
99 base::FilePath path = module_dir.Append(browser_exes[j]);
100 if (base::PathExists(path)) {
101 *browser_exe = path;
102 return true;
103 }
104 }
105 }
106
107 // Step 2: Add all possible install locations, in order they should be
108 // searched. If a location can only hold a chromium install, add it to
109 // |chromium_locations|. Since on some platforms we cannot tell by the binary
110 // name whether it is chrome or chromium, we search these locations last.
111 // We attempt to run chrome before chromium, if any install can be found.
112 std::vector<base::FilePath> locations;
113 std::vector<base::FilePath> chromium_locations;
114 #if defined(OS_WIN)
115 // Add the App Paths registry key location.
116 const wchar_t kSubKey[] =
117 L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe";
118 base::win::RegKey key(HKEY_CURRENT_USER, kSubKey, KEY_READ);
119 std::wstring path;
120 if (key.ReadValue(L"path", &path) == ERROR_SUCCESS)
121 locations.push_back(base::FilePath(path));
122 base::win::RegKey sys_key(HKEY_LOCAL_MACHINE, kSubKey, KEY_READ);
123 if (sys_key.ReadValue(L"path", &path) == ERROR_SUCCESS)
124 locations.push_back(base::FilePath(path));
125
126 // Add the user-level location for Chrome.
127 base::FilePath app_from_google(L"Google\\Chrome\\Application");
128 base::FilePath app_from_chromium(L"Chromium\\Application");
129 scoped_ptr<base::Environment> env(base::Environment::Create());
130 std::string home_dir;
131 if (env->GetVar("userprofile", &home_dir)) {
132 base::FilePath default_location(UTF8ToWide(home_dir));
133 if (base::win::GetVersion() < base::win::VERSION_VISTA) {
134 default_location = default_location.Append(
135 L"Local Settings\\Application Data");
136 } else {
137 default_location = default_location.Append(L"AppData\\Local");
138 }
139 locations.push_back(default_location.Append(app_from_google));
140 chromium_locations.push_back(default_location.Append(app_from_chromium));
141 }
142
143 // Add the system-level location for Chrome.
144 std::string program_dir;
145 if (env->GetVar("ProgramFiles", &program_dir)) {
146 locations.push_back(base::FilePath(UTF8ToWide(program_dir))
147 .Append(app_from_google));
148 chromium_locations.push_back(base::FilePath(UTF8ToWide(program_dir))
149 .Append(app_from_chromium));
150 }
151 if (env->GetVar("ProgramFiles(x86)", &program_dir)) {
152 locations.push_back(base::FilePath(UTF8ToWide(program_dir))
153 .Append(app_from_google));
154 chromium_locations.push_back(base::FilePath(UTF8ToWide(program_dir))
155 .Append(app_from_chromium));
156 }
157 #elif defined(OS_MACOSX)
158 std::vector<base::FilePath> app_dirs;
159 webdriver::GetApplicationDirs(&app_dirs);
160 locations.insert(locations.end(), app_dirs.begin(), app_dirs.end());
161 #elif defined(OS_LINUX)
162 locations.push_back(base::FilePath("/opt/google/chrome"));
163 locations.push_back(base::FilePath("/usr/local/bin"));
164 locations.push_back(base::FilePath("/usr/local/sbin"));
165 locations.push_back(base::FilePath("/usr/bin"));
166 locations.push_back(base::FilePath("/usr/sbin"));
167 locations.push_back(base::FilePath("/bin"));
168 locations.push_back(base::FilePath("/sbin"));
169 #endif
170
171 // Add the current directory.
172 base::FilePath current_dir;
173 if (file_util::GetCurrentDirectory(&current_dir))
174 locations.push_back(current_dir);
175
176 // Step 3: For each browser exe path, check each location to see if the
177 // browser is installed there. Check the chromium locations lastly.
178 return CheckForChromeExe(browser_exes, locations, browser_exe) ||
179 CheckForChromeExe(browser_exes, chromium_locations, browser_exe);
180 }
181
182 // Message that duplicates a given message but uses a different type.
183 class MessageWithAlternateType : public IPC::Message {
184 public:
185 MessageWithAlternateType(const IPC::Message& msg, int type)
186 : IPC::Message(msg) {
187 header()->type = type;
188 }
189 virtual ~MessageWithAlternateType() {}
190 };
191
192 // Filters incoming and outgoing messages on the IO thread. Translates messages
193 // from old Chrome versions to the new version. This is needed so that new
194 // ChromeDriver releases support the current stable and beta channels of Chrome.
195 // TODO(kkania): Delete this when Chrome v21 is stable.
196 class BackwardsCompatAutomationMessageFilter
197 : public IPC::ChannelProxy::MessageFilter,
198 public IPC::ChannelProxy::OutgoingMessageFilter {
199 public:
200 explicit BackwardsCompatAutomationMessageFilter(AutomationProxy* server);
201
202 // Overriden from IPC::ChannelProxy::MessageFiler.
203 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
204
205 // Overriden from IPC::ChannelProxy::OutgoingMessageFiler.
206 virtual IPC::Message* Rewrite(IPC::Message* message) OVERRIDE;
207
208 private:
209 virtual ~BackwardsCompatAutomationMessageFilter();
210
211 // The first version of Chrome using the new IPC automation message set,
212 // after r137672 changed most of the message IDs.
213 static const int kNewAutomationVersion = 1142;
214
215 // The first version of Chrome using the new JSON interface which takes a
216 // browser index instead of a browser handle.
217 static const int kNewJSONInterfaceVersion = 1195;
218
219 AutomationProxy* server_;
220 bool old_version_;
221
222 DISALLOW_COPY_AND_ASSIGN(BackwardsCompatAutomationMessageFilter);
223 };
224
225 BackwardsCompatAutomationMessageFilter::BackwardsCompatAutomationMessageFilter(
226 AutomationProxy* server)
227 : server_(server), old_version_(false) {
228 }
229
230 bool BackwardsCompatAutomationMessageFilter::OnMessageReceived(
231 const IPC::Message& message) {
232 const uint32 kOldHelloType = 44,
233 kOldInitialLoadsCompleteType = 47,
234 kOldInitialNewTabUILoadCompleteType = 267;
235 if (message.type() == kOldHelloType) {
236 old_version_ = true;
237 std::string server_version;
238 PickleIterator iter(message);
239 CHECK(message.ReadString(&iter, &server_version));
240 server_->SignalAppLaunch(server_version);
241 return true;
242 }
243 if (!old_version_)
244 return false;
245
246 switch (message.type()) {
247 case kOldInitialLoadsCompleteType:
248 server_->SignalInitialLoads();
249 break;
250 case kOldInitialNewTabUILoadCompleteType:
251 server_->SignalNewTabUITab(-1);
252 break;
253 default:
254 return false;
255 }
256 return true;
257 }
258
259 IPC::Message* BackwardsCompatAutomationMessageFilter::Rewrite(
260 IPC::Message* message) {
261 int build_no = -1;
262 std::string version = server_->server_version();
263 std::vector<std::string> version_parts;
264 base::SplitString(version, '.', &version_parts);
265 CHECK(version_parts.size() == 4 &&
266 base::StringToInt(version_parts[2], &build_no))
267 << "Can't rewrite message (type: " << message->type()
268 << ") because unknown server (version: " << version << ")";
269 CHECK_EQ(static_cast<uint32>(AutomationMsg_SendJSONRequest::ID),
270 message->type());
271 int type = AutomationMsg_SendJSONRequest::ID;
272 // These old message types are determined by inspecting the line number
273 // of the SendJSONRequest message in older versions of
274 // automation_messages_internal.h.
275 if (build_no < kNewAutomationVersion)
276 type = 1301;
277 else if (build_no < kNewJSONInterfaceVersion)
278 type = 863;
279 IPC::Message* new_message = new MessageWithAlternateType(*message, type);
280 delete message;
281 return new_message;
282 }
283
284 BackwardsCompatAutomationMessageFilter::
285 ~BackwardsCompatAutomationMessageFilter() {
286 }
287
288 void AddBackwardsCompatFilter(AutomationProxy* proxy) {
289 // The filter is ref-counted in AddFilter.
290 BackwardsCompatAutomationMessageFilter* filter =
291 new BackwardsCompatAutomationMessageFilter(proxy);
292 proxy->channel()->AddFilter(filter);
293 proxy->channel()->set_outgoing_message_filter(filter);
294 }
295
296 class WebDriverAnonymousProxyLauncher : public AnonymousProxyLauncher {
297 public:
298 WebDriverAnonymousProxyLauncher()
299 : AnonymousProxyLauncher(false) {}
300 virtual ~WebDriverAnonymousProxyLauncher() {}
301
302 virtual AutomationProxy* CreateAutomationProxy(
303 base::TimeDelta execution_timeout) OVERRIDE {
304 AutomationProxy* proxy =
305 AnonymousProxyLauncher::CreateAutomationProxy(execution_timeout);
306 AddBackwardsCompatFilter(proxy);
307 return proxy;
308 }
309 };
310
311 class WebDriverNamedProxyLauncher : public NamedProxyLauncher {
312 public:
313 WebDriverNamedProxyLauncher(const std::string& channel_id,
314 bool launch_browser)
315 : NamedProxyLauncher(channel_id, launch_browser, false) {}
316 virtual ~WebDriverNamedProxyLauncher() {}
317
318 virtual AutomationProxy* CreateAutomationProxy(
319 base::TimeDelta execution_timeout) OVERRIDE {
320 AutomationProxy* proxy =
321 NamedProxyLauncher::CreateAutomationProxy(execution_timeout);
322 // We can only add the filter here if the browser has not already been
323 // started. Otherwise the filter is not guaranteed to receive the
324 // first message. The only occasion where we don't launch the browser is
325 // in PyAuto, in which case the backwards compat filter isn't needed
326 // anyways because ChromeDriver and Chrome are at the same version there.
327 if (launch_browser_)
328 AddBackwardsCompatFilter(proxy);
329 return proxy;
330 }
331 };
332
333 } // namespace
334
335 namespace webdriver {
336
337 Automation::BrowserOptions::BrowserOptions()
338 : command(CommandLine::NO_PROGRAM),
339 detach_process(false),
340 ignore_certificate_errors(false) {}
341
342 Automation::BrowserOptions::~BrowserOptions() {}
343
344 Automation::Automation(const Logger& logger)
345 : logger_(logger),
346 build_no_(0) {}
347
348 Automation::~Automation() {}
349
350 void Automation::Init(
351 const BrowserOptions& options,
352 int* build_no,
353 Error** error) {
354 // Prepare Chrome's command line.
355 CommandLine command(CommandLine::NO_PROGRAM);
356 if (CommandLine::ForCurrentProcess()->HasSwitch("no-sandbox")) {
357 command.AppendSwitch(switches::kNoSandbox);
358 }
359
360 const char* excludable_switches[] = {
361 switches::kDisableHangMonitor,
362 switches::kDisablePromptOnRepost,
363 switches::kDomAutomationController,
364 switches::kFullMemoryCrashReport,
365 switches::kNoDefaultBrowserCheck,
366 switches::kNoFirstRun,
367 switches::kDisableBackgroundNetworking,
368 switches::kDisableSync,
369 switches::kDisableTranslate,
370 switches::kDisableWebResources,
371 switches::kSbDisableAutoUpdate,
372 switches::kSbDisableDownloadProtection,
373 switches::kDisableClientSidePhishingDetection,
374 switches::kDisableComponentUpdate,
375 switches::kDisableDefaultApps
376 };
377 std::vector<std::string> switches(excludable_switches,
378 excludable_switches + arraysize(excludable_switches));
379 for (size_t i = 0; i < switches.size(); ++i) {
380 const std::string& switch_name = switches[i];
381 if (options.exclude_switches.find(switch_name) ==
382 options.exclude_switches.end()) {
383 command.AppendSwitch(switch_name);
384 }
385 }
386
387 command.AppendSwitch(switches::kEnableLogging);
388 command.AppendSwitchASCII(switches::kLoggingLevel, "1");
389
390 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
391 command.AppendSwitchASCII(switches::kPasswordStore, "basic");
392 #endif
393 #if defined(OS_MACOSX)
394 command.AppendSwitch(switches::kUseMockKeychain);
395 #endif
396 if (options.detach_process)
397 command.AppendSwitch(switches::kAutomationReinitializeOnChannelError);
398 if (options.ignore_certificate_errors)
399 command.AppendSwitch(switches::kIgnoreCertificateErrors);
400 if (options.user_data_dir.empty())
401 command.AppendArg(content::kAboutBlankURL);
402
403 command.AppendArguments(options.command, true /* include_program */);
404
405 // Find the Chrome binary.
406 if (command.GetProgram().empty()) {
407 base::FilePath browser_exe;
408 if (!GetDefaultChromeExe(&browser_exe)) {
409 *error = new Error(kUnknownError, "Could not find default Chrome binary");
410 return;
411 }
412 command.SetProgram(browser_exe);
413 }
414 if (!base::PathExists(command.GetProgram())) {
415 std::string message = base::StringPrintf(
416 "Could not find Chrome binary at: %" PRFilePath,
417 command.GetProgram().value().c_str());
418 *error = new Error(kUnknownError, message);
419 return;
420 }
421 std::string chrome_details = base::StringPrintf(
422 "Using Chrome binary at: %" PRFilePath,
423 command.GetProgram().value().c_str());
424
425 // Create the ProxyLauncher and launch Chrome.
426 // In Chrome 13/14, the only way to detach the browser process is to use a
427 // named proxy launcher.
428 // TODO(kkania): Remove this when Chrome 15 is stable.
429 std::string channel_id = options.channel_id;
430 bool launch_browser = false;
431 if (options.detach_process) {
432 launch_browser = true;
433 if (!channel_id.empty()) {
434 *error = new Error(
435 kUnknownError, "Cannot detach an already running browser process");
436 return;
437 }
438 #if defined(OS_WIN)
439 channel_id = "chromedriver" + GenerateRandomID();
440 #elif defined(OS_POSIX)
441 base::FilePath temp_file;
442 if (!file_util::CreateTemporaryFile(&temp_file) ||
443 !base::DeleteFile(temp_file, false /* recursive */)) {
444 *error = new Error(kUnknownError, "Could not create temporary filename");
445 return;
446 }
447 channel_id = temp_file.value();
448 #endif
449 }
450 if (channel_id.empty()) {
451 std::string command_line_str;
452 #if defined(OS_WIN)
453 command_line_str = WideToUTF8(command.GetCommandLineString());
454 #elif defined(OS_POSIX)
455 command_line_str = command.GetCommandLineString();
456 #endif
457 logger_.Log(kInfoLogLevel, "Launching chrome: " + command_line_str);
458 launcher_.reset(new WebDriverAnonymousProxyLauncher());
459 } else {
460 logger_.Log(kInfoLogLevel, "Using named testing interface");
461 launcher_.reset(new WebDriverNamedProxyLauncher(
462 channel_id, launch_browser));
463 }
464 ProxyLauncher::LaunchState launch_props = {
465 false, // clear_profile
466 options.user_data_dir, // template_user_data
467 base::Closure(),
468 command,
469 true, // include_testing_id
470 true // show_window
471 };
472 if (!launcher_->InitializeConnection(launch_props, true)) {
473 logger_.Log(kSevereLogLevel, "Failed to initialize connection");
474 *error = new Error(
475 kUnknownError,
476 "Unable to either launch or connect to Chrome. Please check that "
477 "ChromeDriver is up-to-date. " + chrome_details);
478 return;
479 }
480
481 launcher_->automation()->set_action_timeout(
482 base::TimeDelta::FromMilliseconds(base::kNoTimeout));
483 logger_.Log(kInfoLogLevel, "Connected to Chrome successfully. Version: " +
484 automation()->server_version());
485
486 *error = DetermineBuildNumber();
487 if (*error)
488 return;
489 *build_no = build_no_;
490
491 // Check the version of Chrome is compatible with this ChromeDriver.
492 chrome_details += ", version (" + automation()->server_version() + ")";
493 int version = 0;
494 automation::Error auto_error;
495 if (!SendGetChromeDriverAutomationVersion(
496 automation(), &version, &auto_error)) {
497 *error = Error::FromAutomationError(auto_error);
498 return;
499 }
500 if (version > automation::kChromeDriverAutomationVersion) {
501 *error = new Error(
502 kUnknownError,
503 "ChromeDriver is not compatible with this version of Chrome. " +
504 chrome_details);
505 return;
506 }
507 }
508
509 void Automation::Terminate() {
510 if (launcher_.get() && launcher_->process() != base::kNullProcessHandle) {
511 #if defined(OS_MACOSX)
512 // There's currently no way to shutdown gracefully with mac chrome.
513 // An alert could be open or (open before shutdown is started) and stop
514 // the whole process. Close any current dialog, try to kill gently, and
515 // if all else fails, kill it hard.
516 Error* error = NULL;
517 AcceptOrDismissAppModalDialog(true /* accept */, &error);
518 scoped_ptr<Error> scoped_error(error);
519
520 kill(launcher_->process(), SIGTERM);
521 #else
522 automation()->Disconnect();
523 #endif
524 int exit_code = -1;
525 if (!launcher_->WaitForBrowserProcessToQuit(
526 base::TimeDelta::FromSeconds(10), &exit_code)) {
527 logger_.Log(kWarningLogLevel, "Chrome still running, terminating...");
528 ChromeProcessList process_pids(GetRunningChromeProcesses(
529 launcher_->process_id()));
530 TerminateAllChromeProcesses(process_pids);
531 }
532 base::CloseProcessHandle(launcher_->process());
533 logger_.Log(kInfoLogLevel, "Chrome shutdown");
534 }
535 }
536
537 void Automation::ExecuteScript(const WebViewId& view_id,
538 const FramePath& frame_path,
539 const std::string& script,
540 std::string* result,
541 Error** error) {
542 WebViewLocator view_locator;
543 *error = ConvertViewIdToLocator(view_id, &view_locator);
544 if (*error)
545 return;
546
547 automation::Error auto_error;
548 scoped_ptr<Value> value;
549 if (!SendExecuteJavascriptJSONRequest(automation(), view_locator,
550 frame_path.value(), script,
551 &value, &auto_error)) {
552 *error = Error::FromAutomationError(auto_error);
553 return;
554 }
555 if (!value->GetAsString(result))
556 *error = new Error(kUnknownError, "Execute script did not return string");
557 }
558
559 void Automation::MouseMoveDeprecated(
560 const WebViewId& view_id,
561 const Point& p,
562 Error** error) {
563 WebViewLocator view_locator;
564 *error = ConvertViewIdToLocator(view_id, &view_locator);
565 if (*error)
566 return;
567
568 automation::Error auto_error;
569 if (!SendMouseMoveJSONRequestDeprecated(
570 automation(), view_locator, p.rounded_x(), p.rounded_y(),
571 &auto_error)) {
572 *error = Error::FromAutomationError(auto_error);
573 }
574 }
575
576 void Automation::MouseClickDeprecated(
577 const WebViewId& view_id,
578 const Point& p,
579 automation::MouseButton button,
580 Error** error) {
581 WebViewLocator view_locator;
582 *error = ConvertViewIdToLocator(view_id, &view_locator);
583 if (*error)
584 return;
585
586 automation::Error auto_error;
587 if (!SendMouseClickJSONRequestDeprecated(
588 automation(), view_locator, button, p.rounded_x(),
589 p.rounded_y(), &auto_error)) {
590 *error = Error::FromAutomationError(auto_error);
591 }
592 }
593
594 void Automation::MouseDragDeprecated(
595 const WebViewId& view_id,
596 const Point& start,
597 const Point& end,
598 Error** error) {
599 WebViewLocator view_locator;
600 *error = ConvertViewIdToLocator(view_id, &view_locator);
601 if (*error)
602 return;
603
604 automation::Error auto_error;
605 if (!SendMouseDragJSONRequestDeprecated(
606 automation(), view_locator, start.rounded_x(), start.rounded_y(),
607 end.rounded_x(), end.rounded_y(), &auto_error)) {
608 *error = Error::FromAutomationError(auto_error);
609 }
610 }
611
612 void Automation::MouseButtonUpDeprecated(
613 const WebViewId& view_id,
614 const Point& p,
615 Error** error) {
616 *error = CheckAdvancedInteractionsSupported();
617 if (*error)
618 return;
619
620 WebViewLocator view_locator;
621 *error = ConvertViewIdToLocator(view_id, &view_locator);
622 if (*error)
623 return;
624
625 automation::Error auto_error;
626 if (!SendMouseButtonUpJSONRequestDeprecated(
627 automation(), view_locator, p.rounded_x(), p.rounded_y(),
628 &auto_error)) {
629 *error = Error::FromAutomationError(auto_error);
630 }
631 }
632
633 void Automation::MouseButtonDownDeprecated(
634 const WebViewId& view_id,
635 const Point& p,
636 Error** error) {
637 *error = CheckAdvancedInteractionsSupported();
638 if (*error)
639 return;
640
641 WebViewLocator view_locator;
642 *error = ConvertViewIdToLocator(view_id, &view_locator);
643 if (*error)
644 return;
645
646 automation::Error auto_error;
647 if (!SendMouseButtonDownJSONRequestDeprecated(
648 automation(), view_locator, p.rounded_x(), p.rounded_y(),
649 &auto_error)) {
650 *error = Error::FromAutomationError(auto_error);
651 }
652 }
653
654 void Automation::MouseDoubleClickDeprecated(
655 const WebViewId& view_id,
656 const Point& p,
657 Error** error) {
658 *error = CheckAdvancedInteractionsSupported();
659 if (*error)
660 return;
661
662 WebViewLocator view_locator;
663 *error = ConvertViewIdToLocator(view_id, &view_locator);
664 if (*error)
665 return;
666
667 automation::Error auto_error;
668 if (!SendMouseDoubleClickJSONRequestDeprecated(
669 automation(), view_locator, p.rounded_x(), p.rounded_y(),
670 &auto_error)) {
671 *error = Error::FromAutomationError(auto_error);
672 }
673 }
674
675 void Automation::DragAndDropFilePaths(
676 const WebViewId& view_id, const Point& location,
677 const std::vector<base::FilePath::StringType>& paths, Error** error) {
678 WebViewLocator view_locator;
679 *error = ConvertViewIdToLocator(view_id, &view_locator);
680 if (*error) {
681 return;
682 }
683
684 automation::Error auto_error;
685 if (!SendDragAndDropFilePathsJSONRequest(
686 automation(), view_locator, location.rounded_x(),
687 location.rounded_y(), paths, &auto_error)) {
688 *error = Error::FromAutomationError(auto_error);
689 }
690 }
691
692 void Automation::SendWebKeyEvent(const WebViewId& view_id,
693 const WebKeyEvent& key_event,
694 Error** error) {
695 WebViewLocator view_locator;
696 *error = ConvertViewIdToLocator(view_id, &view_locator);
697 if (*error)
698 return;
699
700 automation::Error auto_error;
701 if (!SendWebKeyEventJSONRequest(
702 automation(), view_locator, key_event, &auto_error)) {
703 *error = Error::FromAutomationError(auto_error);
704 }
705 }
706
707 void Automation::SendWebMouseEvent(const WebViewId& view_id,
708 const WebMouseEvent& event,
709 Error** error) {
710 WebViewLocator view_locator;
711 *error = ConvertViewIdToLocator(view_id, &view_locator);
712 if (*error)
713 return;
714
715 automation::Error auto_error;
716 if (!SendWebMouseEventJSONRequestDeprecated(
717 automation(), view_locator, event, &auto_error)) {
718 *error = Error::FromAutomationError(auto_error);
719 }
720 }
721
722 void Automation::CaptureEntirePageAsPNG(const WebViewId& view_id,
723 const base::FilePath& path,
724 Error** error) {
725 WebViewLocator view_locator;
726 *error = ConvertViewIdToLocator(view_id, &view_locator);
727 if (*error)
728 return;
729
730 automation::Error auto_error;
731 if (!SendCaptureEntirePageJSONRequestDeprecated(
732 automation(), view_locator, path, &auto_error)) {
733 *error = Error::FromAutomationError(auto_error);
734 }
735 }
736
737 #if !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
738 void Automation::HeapProfilerDump(const WebViewId& view_id,
739 const std::string& reason,
740 Error** error) {
741 WebViewLocator view_locator;
742 *error = ConvertViewIdToLocator(view_id, &view_locator);
743 if (*error)
744 return;
745
746 automation::Error auto_error;
747 if (!SendHeapProfilerDumpJSONRequestDeprecated(
748 automation(), view_locator, reason, &auto_error)) {
749 *error = Error::FromAutomationError(auto_error);
750 }
751 }
752 #endif // !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
753
754 void Automation::NavigateToURL(const WebViewId& view_id,
755 const std::string& url,
756 Error** error) {
757 WebViewLocator view_locator;
758 *error = ConvertViewIdToLocator(view_id, &view_locator);
759 if (*error)
760 return;
761
762 AutomationMsg_NavigationResponseValues navigate_response;
763 automation::Error auto_error;
764 if (!SendNavigateToURLJSONRequest(automation(), view_locator,
765 url, 1, &navigate_response,
766 &auto_error)) {
767 *error = Error::FromAutomationError(auto_error);
768 return;
769 }
770 // TODO(kkania): Do not rely on this enum.
771 if (navigate_response == AUTOMATION_MSG_NAVIGATION_ERROR)
772 *error = new Error(kUnknownError, "Navigation error occurred");
773 }
774
775 void Automation::NavigateToURLAsync(const WebViewId& view_id,
776 const std::string& url,
777 Error** error) {
778 WebViewLocator view_locator;
779 *error = ConvertViewIdToLocator(view_id, &view_locator);
780 if (*error)
781 return;
782
783 automation::Error auto_error;
784 if (!view_id.old_style()) {
785 AutomationMsg_NavigationResponseValues navigate_response;
786 if (!SendNavigateToURLJSONRequest(automation(), view_locator, url,
787 0, &navigate_response, &auto_error)) {
788 *error = Error::FromAutomationError(auto_error);
789 return;
790 }
791 } else {
792 scoped_refptr<BrowserProxy> browser =
793 automation()->GetBrowserWindow(view_locator.browser_index());
794 if (!browser.get()) {
795 *error = new Error(kUnknownError, "Couldn't obtain browser proxy");
796 return;
797 }
798 scoped_refptr<TabProxy> tab = browser->GetTab(view_locator.tab_index());
799 if (!tab.get()) {
800 *error = new Error(kUnknownError, "Couldn't obtain tab proxy");
801 return;
802 }
803 if (!tab->NavigateToURLAsync(GURL(url))) {
804 *error = new Error(kUnknownError, "Unable to navigate to url");
805 return;
806 }
807 }
808 }
809
810 void Automation::GoForward(const WebViewId& view_id, Error** error) {
811 WebViewLocator view_locator;
812 *error = ConvertViewIdToLocator(view_id, &view_locator);
813 if (*error)
814 return;
815
816 automation::Error auto_error;
817 if (!SendGoForwardJSONRequest(
818 automation(), view_locator, &auto_error)) {
819 *error = Error::FromAutomationError(auto_error);
820 }
821 }
822
823 void Automation::GoBack(const WebViewId& view_id, Error** error) {
824 WebViewLocator view_locator;
825 *error = ConvertViewIdToLocator(view_id, &view_locator);
826 if (*error)
827 return;
828
829 automation::Error auto_error;
830 if (!SendGoBackJSONRequest(automation(), view_locator, &auto_error))
831 *error = Error::FromAutomationError(auto_error);
832 }
833
834 void Automation::Reload(const WebViewId& view_id, Error** error) {
835 WebViewLocator view_locator;
836 *error = ConvertViewIdToLocator(view_id, &view_locator);
837 if (*error)
838 return;
839
840 automation::Error auto_error;
841 if (!SendReloadJSONRequest(automation(), view_locator, &auto_error))
842 *error = Error::FromAutomationError(auto_error);
843 }
844
845 void Automation::GetCookies(const std::string& url,
846 scoped_ptr<ListValue>* cookies,
847 Error** error) {
848 automation::Error auto_error;
849 if (!SendGetCookiesJSONRequest(automation(), url, cookies, &auto_error))
850 *error = Error::FromAutomationError(auto_error);
851 }
852
853 void Automation::DeleteCookie(const std::string& url,
854 const std::string& cookie_name,
855 Error** error) {
856 automation::Error auto_error;
857 if (!SendDeleteCookieJSONRequest(
858 automation(), url, cookie_name, &auto_error)) {
859 *error = Error::FromAutomationError(auto_error);
860 }
861 }
862
863 void Automation::SetCookie(const std::string& url,
864 DictionaryValue* cookie_dict,
865 Error** error) {
866 automation::Error auto_error;
867 if (!SendSetCookieJSONRequest(automation(), url, cookie_dict, &auto_error))
868 *error = Error::FromAutomationError(auto_error);
869 }
870
871 void Automation::GetViews(std::vector<WebViewInfo>* views,
872 Error** error) {
873 automation::Error auto_error;
874 if (build_no_ >= 963) {
875 if (!SendGetWebViewsJSONRequest(automation(), views, &auto_error))
876 *error = Error::FromAutomationError(auto_error);
877 } else {
878 if (!SendGetTabIdsJSONRequest(automation(), views, &auto_error))
879 *error = Error::FromAutomationError(auto_error);
880 }
881 }
882
883 void Automation::DoesViewExist(
884 const WebViewId& view_id, bool* does_exist, Error** error) {
885 automation::Error auto_error;
886 if (view_id.old_style()) {
887 if (!SendIsTabIdValidJSONRequest(
888 automation(), view_id, does_exist, &auto_error))
889 *error = Error::FromAutomationError(auto_error);
890 } else {
891 if (!SendDoesAutomationObjectExistJSONRequest(
892 automation(), view_id, does_exist, &auto_error))
893 *error = Error::FromAutomationError(auto_error);
894 }
895 }
896
897 void Automation::CloseView(const WebViewId& view_id, Error** error) {
898 WebViewLocator view_locator;
899 *error = ConvertViewIdToLocator(view_id, &view_locator);
900 if (*error)
901 return;
902
903 automation::Error auto_error;
904 if (!SendCloseViewJSONRequest(automation(), view_locator, &auto_error))
905 *error = Error::FromAutomationError(auto_error);
906 }
907
908 void Automation::SetViewBounds(const WebViewId& view_id,
909 const Rect& bounds,
910 Error** error) {
911 automation::Error auto_error;
912 if (!SendSetViewBoundsJSONRequest(
913 automation(), view_id, bounds.x(), bounds.y(),
914 bounds.width(), bounds.height(), &auto_error))
915 *error = Error::FromAutomationError(auto_error);
916 }
917
918 void Automation::MaximizeView(const WebViewId& view_id, Error** error) {
919 *error = CheckMaximizeSupported();
920 if (*error)
921 return;
922
923 automation::Error auto_error;
924 if (!SendMaximizeJSONRequest(
925 automation(), view_id, &auto_error))
926 *error = Error::FromAutomationError(auto_error);
927 }
928
929 void Automation::GetAppModalDialogMessage(std::string* message, Error** error) {
930 *error = CheckAlertsSupported();
931 if (*error)
932 return;
933
934 automation::Error auto_error;
935 if (!SendGetAppModalDialogMessageJSONRequest(
936 automation(), message, &auto_error)) {
937 *error = Error::FromAutomationError(auto_error);
938 }
939 }
940
941 void Automation::AcceptOrDismissAppModalDialog(bool accept, Error** error) {
942 *error = CheckAlertsSupported();
943 if (*error)
944 return;
945
946 automation::Error auto_error;
947 if (!SendAcceptOrDismissAppModalDialogJSONRequest(
948 automation(), accept, &auto_error)) {
949 *error = Error::FromAutomationError(auto_error);
950 }
951 }
952
953 void Automation::AcceptPromptAppModalDialog(const std::string& prompt_text,
954 Error** error) {
955 *error = CheckAlertsSupported();
956 if (*error)
957 return;
958
959 automation::Error auto_error;
960 if (!SendAcceptPromptAppModalDialogJSONRequest(
961 automation(), prompt_text, &auto_error)) {
962 *error = Error::FromAutomationError(auto_error);
963 }
964 }
965
966 void Automation::GetBrowserVersion(std::string* version) {
967 *version = automation()->server_version();
968 }
969
970 void Automation::GetChromeDriverAutomationVersion(int* version, Error** error) {
971 automation::Error auto_error;
972 if (!SendGetChromeDriverAutomationVersion(automation(), version, &auto_error))
973 *error = Error::FromAutomationError(auto_error);
974 }
975
976 void Automation::WaitForAllViewsToStopLoading(Error** error) {
977 automation::Error auto_error;
978 if (!SendWaitForAllViewsToStopLoadingJSONRequestDeprecated(
979 automation(), &auto_error))
980 *error = Error::FromAutomationError(auto_error);
981 }
982
983 void Automation::InstallExtension(
984 const base::FilePath& path, std::string* extension_id, Error** error) {
985 *error = CheckNewExtensionInterfaceSupported();
986 if (*error)
987 return;
988
989 automation::Error auto_error;
990 if (!SendInstallExtensionJSONRequest(
991 automation(), path, false /* with_ui */, extension_id,
992 &auto_error))
993 *error = Error::FromAutomationError(auto_error);
994 }
995
996 void Automation::GetExtensionsInfo(
997 base::ListValue* extensions_list, Error** error) {
998 *error = CheckNewExtensionInterfaceSupported();
999 if (*error)
1000 return;
1001
1002 automation::Error auto_error;
1003 if (!SendGetExtensionsInfoJSONRequest(
1004 automation(), extensions_list, &auto_error))
1005 *error = Error::FromAutomationError(auto_error);
1006 }
1007
1008 void Automation::IsPageActionVisible(
1009 const WebViewId& tab_id,
1010 const std::string& extension_id,
1011 bool* is_visible,
1012 Error** error) {
1013 *error = CheckNewExtensionInterfaceSupported();
1014 if (*error)
1015 return;
1016
1017 automation::Error auto_error;
1018 if (!SendIsPageActionVisibleJSONRequest(
1019 automation(), tab_id, extension_id, is_visible, &auto_error))
1020 *error = Error::FromAutomationError(auto_error);
1021 }
1022
1023 void Automation::SetExtensionState(
1024 const std::string& extension_id,
1025 bool enable,
1026 Error** error) {
1027 *error = CheckNewExtensionInterfaceSupported();
1028 if (*error)
1029 return;
1030
1031 automation::Error auto_error;
1032 if (!SendSetExtensionStateJSONRequest(
1033 automation(), extension_id, enable /* enable */,
1034 false /* allow_in_incognito */, &auto_error))
1035 *error = Error::FromAutomationError(auto_error);
1036 }
1037
1038 void Automation::ClickExtensionButton(
1039 const std::string& extension_id,
1040 bool browser_action,
1041 Error** error) {
1042 automation::Error auto_error;
1043 if (!SendClickExtensionButtonJSONRequest(
1044 automation(), extension_id, browser_action, &auto_error))
1045 *error = Error::FromAutomationError(auto_error);
1046 }
1047
1048 void Automation::UninstallExtension(
1049 const std::string& extension_id, Error** error) {
1050 *error = CheckNewExtensionInterfaceSupported();
1051 if (*error)
1052 return;
1053
1054 automation::Error auto_error;
1055 if (!SendUninstallExtensionJSONRequest(
1056 automation(), extension_id, &auto_error))
1057 *error = Error::FromAutomationError(auto_error);
1058 }
1059
1060 void Automation::SetLocalStatePreference(const std::string& pref,
1061 base::Value* value,
1062 Error** error) {
1063 scoped_ptr<Value> scoped_value(value);
1064 // In version 927, SetLocalStatePrefs was changed from taking a browser
1065 // handle to a browser index.
1066 if (build_no_ >= 927) {
1067 automation::Error auto_error;
1068 if (!SendSetLocalStatePreferenceJSONRequest(
1069 automation(), pref, scoped_value.release(), &auto_error))
1070 *error = Error::FromAutomationError(auto_error);
1071 } else {
1072 std::string request, response;
1073 DictionaryValue request_dict;
1074 request_dict.SetString("command", "SetLocalStatePrefs");
1075 request_dict.SetString("path", pref);
1076 request_dict.Set("value", scoped_value.release());
1077 base::JSONWriter::Write(&request_dict, &request);
1078 if (!automation()->GetBrowserWindow(0)->SendJSONRequest(
1079 request, -1, &response)) {
1080 *error = new Error(kUnknownError, base::StringPrintf(
1081 "Failed to set local state pref '%s'", pref.c_str()));
1082 }
1083 }
1084 }
1085
1086 void Automation::SetPreference(const std::string& pref,
1087 base::Value* value,
1088 Error** error) {
1089 scoped_ptr<Value> scoped_value(value);
1090 // Chrome 17 is on the 963 branch. The first released 18 build should have
1091 // the new SetPrefs method which uses a browser index instead of handle.
1092 if (build_no_ >= 964) {
1093 automation::Error auto_error;
1094 if (!SendSetPreferenceJSONRequest(
1095 automation(), pref, scoped_value.release(), &auto_error))
1096 *error = Error::FromAutomationError(auto_error);
1097 } else {
1098 std::string request, response;
1099 DictionaryValue request_dict;
1100 request_dict.SetString("command", "SetPrefs");
1101 request_dict.SetInteger("windex", 0);
1102 request_dict.SetString("path", pref);
1103 request_dict.Set("value", scoped_value.release());
1104 base::JSONWriter::Write(&request_dict, &request);
1105 if (!automation()->GetBrowserWindow(0)->SendJSONRequest(
1106 request, -1, &response)) {
1107 *error = new Error(kUnknownError, base::StringPrintf(
1108 "Failed to set pref '%s'", pref.c_str()));
1109 }
1110 }
1111 }
1112
1113 void Automation::GetGeolocation(scoped_ptr<DictionaryValue>* geolocation,
1114 Error** error) {
1115 *error = CheckGeolocationSupported();
1116 if (*error)
1117 return;
1118
1119 if (geolocation_.get()) {
1120 geolocation->reset(geolocation_->DeepCopy());
1121 } else {
1122 *error = new Error(kUnknownError,
1123 "Location must be set before it can be retrieved");
1124 }
1125 }
1126
1127 void Automation::OverrideGeolocation(const DictionaryValue* geolocation,
1128 Error** error) {
1129 *error = CheckGeolocationSupported();
1130 if (*error)
1131 return;
1132
1133 automation::Error auto_error;
1134 if (SendOverrideGeolocationJSONRequest(
1135 automation(), geolocation, &auto_error)) {
1136 geolocation_.reset(geolocation->DeepCopy());
1137 } else {
1138 *error = Error::FromAutomationError(auto_error);
1139 }
1140 }
1141
1142 AutomationProxy* Automation::automation() const {
1143 return launcher_->automation();
1144 }
1145
1146 Error* Automation::ConvertViewIdToLocator(
1147 const WebViewId& view_id, WebViewLocator* view_locator) {
1148 if (view_id.old_style()) {
1149 int browser_index, tab_index;
1150 automation::Error auto_error;
1151 if (!SendGetIndicesFromTabIdJSONRequest(
1152 automation(), view_id.tab_id(), &browser_index, &tab_index,
1153 &auto_error))
1154 return Error::FromAutomationError(auto_error);
1155 *view_locator = WebViewLocator::ForIndexPair(browser_index, tab_index);
1156 } else {
1157 *view_locator = WebViewLocator::ForViewId(view_id.GetId());
1158 }
1159 return NULL;
1160 }
1161
1162 Error* Automation::DetermineBuildNumber() {
1163 std::string version = automation()->server_version();
1164 std::vector<std::string> split_version;
1165 base::SplitString(version, '.', &split_version);
1166 if (split_version.size() != 4) {
1167 return new Error(
1168 kUnknownError, "Browser version has unrecognized format: " + version);
1169 }
1170 if (!base::StringToInt(split_version[2], &build_no_)) {
1171 return new Error(
1172 kUnknownError, "Browser version has unrecognized format: " + version);
1173 }
1174 return NULL;
1175 }
1176
1177 Error* Automation::CheckVersion(int min_required_build_no,
1178 const std::string& error_msg) {
1179 if (build_no_ < min_required_build_no)
1180 return new Error(kUnknownError, error_msg);
1181 return NULL;
1182 }
1183
1184 Error* Automation::CheckAlertsSupported() {
1185 return CheckVersion(
1186 768, "Alerts are not supported for this version of Chrome");
1187 }
1188
1189 Error* Automation::CheckAdvancedInteractionsSupported() {
1190 const char* message =
1191 "Advanced user interactions are not supported for this version of Chrome";
1192 return CheckVersion(750, message);
1193 }
1194
1195 Error* Automation::CheckNewExtensionInterfaceSupported() {
1196 const char* message =
1197 "Extension interface is not supported for this version of Chrome";
1198 return CheckVersion(947, message);
1199 }
1200
1201 Error* Automation::CheckGeolocationSupported() {
1202 const char* message =
1203 "Geolocation automation interface is not supported for this version of "
1204 "Chrome.";
1205 return CheckVersion(1119, message);
1206 }
1207
1208 Error* Automation::CheckMaximizeSupported() {
1209 const char* message =
1210 "Maximize automation interface is not supported for this version of "
1211 "Chrome.";
1212 return CheckVersion(1160, message);
1213 }
1214
1215 } // namespace webdriver
OLDNEW
« no previous file with comments | « chrome/test/webdriver/webdriver_automation.h ('k') | chrome/test/webdriver/webdriver_basic_types.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698