1 // Copyright 2013 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.
5 #include "chrome/browser/automation/testing_automation_provider.h"
12 #include "base/bind.h"
13 #include "base/bind_helpers.h"
14 #include "base/command_line.h"
15 #include "base/files/file_path.h"
16 #include "base/json/json_reader.h"
17 #include "base/json/json_writer.h"
18 #include "base/json/string_escape.h"
19 #include "base/path_service.h"
20 #include "base/prefs/pref_service.h"
21 #include "base/process/process.h"
22 #include "base/process/process_iterator.h"
23 #include "base/sequenced_task_runner.h"
24 #include "base/strings/stringprintf.h"
25 #include "base/strings/utf_string_conversions.h"
26 #include "base/threading/thread_restrictions.h"
27 #include "base/time/time.h"
28 #include "chrome/app/chrome_command_ids.h"
29 #include "chrome/browser/autocomplete/autocomplete_controller.h"
30 #include "chrome/browser/autocomplete/autocomplete_match.h"
31 #include "chrome/browser/autocomplete/autocomplete_result.h"
32 #include "chrome/browser/automation/automation_browser_tracker.h"
33 #include "chrome/browser/automation/automation_provider_json.h"
34 #include "chrome/browser/automation/automation_provider_list.h"
35 #include "chrome/browser/automation/automation_provider_observers.h"
36 #include "chrome/browser/automation/automation_tab_tracker.h"
37 #include "chrome/browser/automation/automation_util.h"
38 #include "chrome/browser/automation/automation_window_tracker.h"
39 #include "chrome/browser/bookmarks/bookmark_model.h"
40 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
41 #include "chrome/browser/bookmarks/bookmark_storage.h"
42 #include "chrome/browser/browser_process.h"
43 #include "chrome/browser/browser_shutdown.h"
44 #include "chrome/browser/chrome_notification_types.h"
45 #include "chrome/browser/content_settings/host_content_settings_map.h"
46 #include "chrome/browser/devtools/devtools_window.h"
47 #include "chrome/browser/download/download_prefs.h"
48 #include "chrome/browser/download/download_service.h"
49 #include "chrome/browser/download/download_service_factory.h"
50 #include "chrome/browser/download/download_shelf.h"
51 #include "chrome/browser/download/save_package_file_picker.h"
52 #include "chrome/browser/extensions/browser_action_test_util.h"
53 #include "chrome/browser/extensions/crx_installer.h"
54 #include "chrome/browser/extensions/extension_action.h"
55 #include "chrome/browser/extensions/extension_action_manager.h"
56 #include "chrome/browser/extensions/extension_host.h"
57 #include "chrome/browser/extensions/extension_process_manager.h"
58 #include "chrome/browser/extensions/extension_service.h"
59 #include "chrome/browser/extensions/extension_system.h"
60 #include "chrome/browser/extensions/extension_tab_util.h"
61 #include "chrome/browser/extensions/extension_util.h"
62 #include "chrome/browser/extensions/unpacked_installer.h"
63 #include "chrome/browser/extensions/updater/extension_updater.h"
64 #include "chrome/browser/history/history_service_factory.h"
65 #include "chrome/browser/history/top_sites.h"
66 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
67 #include "chrome/browser/infobars/infobar_service.h"
68 #include "chrome/browser/lifetime/application_lifetime.h"
69 #include "chrome/browser/notifications/balloon.h"
70 #include "chrome/browser/notifications/balloon_collection.h"
71 #include "chrome/browser/notifications/balloon_notification_ui_manager.h"
72 #include "chrome/browser/notifications/notification.h"
73 #include "chrome/browser/password_manager/password_store.h"
74 #include "chrome/browser/password_manager/password_store_change.h"
75 #include "chrome/browser/password_manager/password_store_factory.h"
76 #include "chrome/browser/platform_util.h"
77 #include "chrome/browser/plugins/plugin_prefs.h"
78 #include "chrome/browser/profiles/profile.h"
79 #include "chrome/browser/profiles/profile_info_cache.h"
80 #include "chrome/browser/profiles/profile_manager.h"
81 #include "chrome/browser/profiles/profile_window.h"
82 #include "chrome/browser/profiles/profiles_state.h"
83 #include "chrome/browser/search_engines/template_url.h"
84 #include "chrome/browser/search_engines/template_url_service.h"
85 #include "chrome/browser/search_engines/template_url_service_factory.h"
86 #include "chrome/browser/sessions/session_service_factory.h"
87 #include "chrome/browser/sessions/session_tab_helper.h"
88 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h"
89 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h"
90 #include "chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h"
91 #include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h"
92 #include "chrome/browser/ui/bookmarks/bookmark_bar.h"
93 #include "chrome/browser/ui/browser_commands.h"
94 #include "chrome/browser/ui/browser_finder.h"
95 #include "chrome/browser/ui/browser_iterator.h"
96 #include "chrome/browser/ui/browser_list.h"
97 #include "chrome/browser/ui/browser_tabstrip.h"
98 #include "chrome/browser/ui/browser_window.h"
99 #include "chrome/browser/ui/extensions/application_launch.h"
100 #include "chrome/browser/ui/find_bar/find_bar.h"
101 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
102 #include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
103 #include "chrome/browser/ui/fullscreen/fullscreen_exit_bubble_type.h"
104 #include "chrome/browser/ui/host_desktop.h"
105 #include "chrome/browser/ui/login/login_prompt.h"
106 #include "chrome/browser/ui/omnibox/location_bar.h"
107 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
108 #include "chrome/browser/ui/omnibox/omnibox_view.h"
109 #include "chrome/browser/ui/search_engines/keyword_editor_controller.h"
110 #include "chrome/browser/ui/startup/startup_types.h"
111 #include "chrome/common/automation_constants.h"
112 #include "chrome/common/automation_messages.h"
113 #include "chrome/common/chrome_constants.h"
114 #include "chrome/common/chrome_paths.h"
115 #include "chrome/common/chrome_switches.h"
116 #include "chrome/common/extensions/background_info.h"
117 #include "chrome/common/extensions/extension.h"
118 #include "chrome/common/extensions/manifest_url_handler.h"
119 #include "chrome/common/extensions/permissions/permissions_data.h"
120 #include "chrome/common/pref_names.h"
121 #include "chrome/common/render_messages.h"
122 #include "content/public/browser/browser_child_process_host_iterator.h"
123 #include "content/public/browser/child_process_data.h"
124 #include "content/public/browser/favicon_status.h"
125 #include "content/public/browser/geolocation_provider.h"
126 #include "content/public/browser/interstitial_page.h"
127 #include "content/public/browser/interstitial_page_delegate.h"
128 #include "content/public/browser/navigation_entry.h"
129 #include "content/public/browser/notification_service.h"
130 #include "content/public/browser/plugin_service.h"
131 #include "content/public/browser/render_process_host.h"
132 #include "content/public/browser/render_view_host.h"
133 #include "content/public/browser/render_widget_host_view.h"
134 #include "content/public/browser/web_contents.h"
135 #include "content/public/common/child_process_host.h"
136 #include "content/public/common/common_param_traits.h"
137 #include "content/public/common/drop_data.h"
138 #include "content/public/common/geoposition.h"
139 #include "content/public/common/ssl_status.h"
140 #include "content/public/common/webplugininfo.h"
141 #include "extensions/browser/view_type_utils.h"
142 #include "extensions/common/permissions/permission_set.h"
143 #include "extensions/common/url_pattern.h"
144 #include "extensions/common/url_pattern_set.h"
145 #include "net/cookies/cookie_store.h"
146 #include "third_party/WebKit/public/web/WebInputEvent.h"
147 #include "ui/base/ui_base_types.h"
148 #include "ui/events/event_constants.h"
149 #include "ui/events/keycodes/keyboard_codes.h"
151 #if defined(ENABLE_CONFIGURATION_POLICY)
152 #include "chrome/browser/policy/policy_service.h"
155 #if defined(OS_CHROMEOS)
156 #include "chromeos/dbus/dbus_thread_manager.h"
159 #if defined(OS_MACOSX)
160 #include <mach/mach.h>
161 #include <mach/mach_vm.h>
164 using automation_util::SendErrorIfModalDialogActive;
165 using content::BrowserChildProcessHostIterator;
166 using content::BrowserContext;
167 using content::BrowserThread;
168 using content::ChildProcessHost;
169 using content::DownloadItem;
170 using content::DownloadManager;
171 using content::InterstitialPage;
172 using content::NativeWebKeyboardEvent;
173 using content::NavigationController;
174 using content::NavigationEntry;
175 using content::OpenURLParams;
176 using content::PluginService;
177 using content::Referrer;
178 using content::RenderViewHost;
179 using content::SSLStatus;
180 using content::WebContents;
181 using extensions::Extension;
182 using extensions::ExtensionActionManager;
183 using extensions::ExtensionList;
184 using extensions::Manifest;
188 // Helper to reply asynchronously if |automation| is still valid.
189 void SendSuccessReply(base::WeakPtr<AutomationProvider> automation,
190 IPC::Message* reply_message) {
191 if (automation.get())
192 AutomationJSONReply(automation.get(), reply_message).SendSuccess(NULL);
195 // Helper to process the result of CanEnablePlugin.
196 void DidEnablePlugin(base::WeakPtr<AutomationProvider> automation,
197 IPC::Message* reply_message,
198 const base::FilePath::StringType& path,
199 const std::string& error_msg,
202 SendSuccessReply(automation, reply_message);
204 if (automation.get()) {
205 AutomationJSONReply(automation.get(), reply_message)
206 .SendError(base::StringPrintf(error_msg.c_str(), path.c_str()));
211 // Helper to resolve the overloading of PostTask.
212 void PostTask(BrowserThread::ID id, const base::Closure& callback) {
213 BrowserThread::PostTask(id, FROM_HERE, callback);
216 class AutomationInterstitialPage : public content::InterstitialPageDelegate {
218 AutomationInterstitialPage(WebContents* tab,
220 const std::string& contents)
221 : contents_(contents) {
222 interstitial_page_ = InterstitialPage::Create(tab, true, url, this);
223 interstitial_page_->Show();
226 virtual std::string GetHTMLContents() OVERRIDE { return contents_; }
229 const std::string contents_;
230 InterstitialPage* interstitial_page_; // Owns us.
232 DISALLOW_COPY_AND_ASSIGN(AutomationInterstitialPage);
237 const int TestingAutomationProvider::kSynchronousCommands[] = {
240 IDC_SELECT_PREVIOUS_TAB,
241 IDC_SHOW_BOOKMARK_MANAGER,
244 TestingAutomationProvider::TestingAutomationProvider(Profile* profile)
245 : AutomationProvider(profile) {
246 BrowserList::AddObserver(this);
247 registrar_.Add(this, chrome::NOTIFICATION_SESSION_END,
248 content::NotificationService::AllSources());
249 #if defined(OS_CHROMEOS)
250 AddChromeosObservers();
254 TestingAutomationProvider::~TestingAutomationProvider() {
255 #if defined(OS_CHROMEOS)
256 RemoveChromeosObservers();
258 BrowserList::RemoveObserver(this);
261 IPC::Channel::Mode TestingAutomationProvider::GetChannelMode(
262 bool use_named_interface) {
263 if (use_named_interface)
264 #if defined(OS_POSIX)
265 return IPC::Channel::MODE_OPEN_NAMED_SERVER;
267 return IPC::Channel::MODE_NAMED_SERVER;
270 return IPC::Channel::MODE_CLIENT;
273 void TestingAutomationProvider::OnBrowserAdded(Browser* browser) {
276 void TestingAutomationProvider::OnBrowserRemoved(Browser* browser) {
277 #if !defined(OS_CHROMEOS) && !defined(OS_MACOSX)
278 // For backwards compatibility with the testing automation interface, we
279 // want the automation provider (and hence the process) to go away when the
280 // last browser goes away.
281 // The automation layer doesn't support non-native desktops.
282 if (BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE)->empty() &&
283 !CommandLine::ForCurrentProcess()->HasSwitch(
284 switches::kKeepAliveForTest)) {
285 // If you change this, update Observer for chrome::SESSION_END
287 base::MessageLoop::current()->PostTask(
289 base::Bind(&TestingAutomationProvider::OnRemoveProvider, this));
291 #endif // !defined(OS_CHROMEOS) && !defined(OS_MACOSX)
294 void TestingAutomationProvider::Observe(
296 const content::NotificationSource& source,
297 const content::NotificationDetails& details) {
298 DCHECK(type == chrome::NOTIFICATION_SESSION_END);
299 // OnBrowserRemoved does a ReleaseLater. When session end is received we exit
300 // before the task runs resulting in this object not being deleted. This
301 // Release balance out the Release scheduled by OnBrowserRemoved.
305 bool TestingAutomationProvider::OnMessageReceived(
306 const IPC::Message& message) {
307 base::ThreadRestrictions::ScopedAllowWait allow_wait;
309 bool deserialize_success = true;
310 IPC_BEGIN_MESSAGE_MAP_EX(TestingAutomationProvider,
313 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_CloseBrowser, CloseBrowser)
314 IPC_MESSAGE_HANDLER(AutomationMsg_ActivateTab, ActivateTab)
315 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_AppendTab, AppendTab)
316 IPC_MESSAGE_HANDLER(AutomationMsg_GetMachPortCount, GetMachPortCount)
317 IPC_MESSAGE_HANDLER(AutomationMsg_ActiveTabIndex, GetActiveTabIndex)
318 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_CloseTab, CloseTab)
319 IPC_MESSAGE_HANDLER(AutomationMsg_GetCookies, GetCookies)
320 IPC_MESSAGE_HANDLER_DELAY_REPLY(
321 AutomationMsg_NavigateToURLBlockUntilNavigationsComplete,
322 NavigateToURLBlockUntilNavigationsComplete)
323 IPC_MESSAGE_HANDLER(AutomationMsg_NavigationAsync, NavigationAsync)
324 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_Reload, Reload)
325 IPC_MESSAGE_HANDLER(AutomationMsg_BrowserWindowCount, GetBrowserWindowCount)
326 IPC_MESSAGE_HANDLER(AutomationMsg_NormalBrowserWindowCount,
327 GetNormalBrowserWindowCount)
328 IPC_MESSAGE_HANDLER(AutomationMsg_BrowserWindow, GetBrowserWindow)
329 IPC_MESSAGE_HANDLER(AutomationMsg_WindowExecuteCommandAsync,
330 ExecuteBrowserCommandAsync)
331 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WindowExecuteCommand,
332 ExecuteBrowserCommand)
333 IPC_MESSAGE_HANDLER(AutomationMsg_TerminateSession, TerminateSession)
334 IPC_MESSAGE_HANDLER(AutomationMsg_WindowViewBounds, WindowGetViewBounds)
335 IPC_MESSAGE_HANDLER(AutomationMsg_SetWindowBounds, SetWindowBounds)
336 IPC_MESSAGE_HANDLER(AutomationMsg_TabCount, GetTabCount)
337 IPC_MESSAGE_HANDLER(AutomationMsg_Type, GetType)
338 IPC_MESSAGE_HANDLER(AutomationMsg_Tab, GetTab)
339 IPC_MESSAGE_HANDLER(AutomationMsg_TabTitle, GetTabTitle)
340 IPC_MESSAGE_HANDLER(AutomationMsg_TabIndex, GetTabIndex)
341 IPC_MESSAGE_HANDLER(AutomationMsg_TabURL, GetTabURL)
342 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_DomOperation,
344 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_OpenNewBrowserWindowOfType,
345 OpenNewBrowserWindowOfType)
346 IPC_MESSAGE_HANDLER(AutomationMsg_WindowForBrowser, GetWindowForBrowser)
347 IPC_MESSAGE_HANDLER(AutomationMsg_GetMetricEventDuration,
348 GetMetricEventDuration)
349 IPC_MESSAGE_HANDLER(AutomationMsg_BringBrowserToFront, BringBrowserToFront)
350 IPC_MESSAGE_HANDLER(AutomationMsg_FindWindowVisibility,
351 GetFindWindowVisibility)
352 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForBookmarkModelToLoad,
353 WaitForBookmarkModelToLoad)
354 IPC_MESSAGE_HANDLER_DELAY_REPLY(
355 AutomationMsg_WaitForBrowserWindowCountToBecome,
356 WaitForBrowserWindowCountToBecome)
357 IPC_MESSAGE_HANDLER_DELAY_REPLY(
358 AutomationMsg_GoBackBlockUntilNavigationsComplete,
359 GoBackBlockUntilNavigationsComplete)
360 IPC_MESSAGE_HANDLER_DELAY_REPLY(
361 AutomationMsg_GoForwardBlockUntilNavigationsComplete,
362 GoForwardBlockUntilNavigationsComplete)
363 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_SendJSONRequest,
364 SendJSONRequestWithBrowserIndex)
365 IPC_MESSAGE_HANDLER_DELAY_REPLY(
366 AutomationMsg_SendJSONRequestWithBrowserHandle,
367 SendJSONRequestWithBrowserHandle)
368 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForTabCountToBecome,
369 WaitForTabCountToBecome)
370 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForInfoBarCount,
372 IPC_MESSAGE_HANDLER_DELAY_REPLY(
373 AutomationMsg_WaitForProcessLauncherThreadToGoIdle,
374 WaitForProcessLauncherThreadToGoIdle)
376 IPC_MESSAGE_UNHANDLED(
377 handled = AutomationProvider::OnMessageReceived(message))
378 IPC_END_MESSAGE_MAP_EX()
379 if (!deserialize_success)
380 OnMessageDeserializationFailure();
384 void TestingAutomationProvider::OnChannelError() {
385 if (!reinitialize_on_channel_error_ &&
386 browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID) {
387 chrome::AttemptExit();
389 AutomationProvider::OnChannelError();
392 void TestingAutomationProvider::CloseBrowser(int browser_handle,
393 IPC::Message* reply_message) {
394 if (!browser_tracker_->ContainsHandle(browser_handle))
397 Browser* browser = browser_tracker_->GetResource(browser_handle);
398 new BrowserClosedNotificationObserver(browser, this, reply_message, false);
399 browser->window()->Close();
402 void TestingAutomationProvider::ActivateTab(int handle,
406 if (browser_tracker_->ContainsHandle(handle) && at_index > -1) {
407 Browser* browser = browser_tracker_->GetResource(handle);
408 if (at_index >= 0 && at_index < browser->tab_strip_model()->count()) {
409 browser->tab_strip_model()->ActivateTabAt(at_index, true);
415 void TestingAutomationProvider::AppendTab(int handle,
417 IPC::Message* reply_message) {
418 int append_tab_response = -1; // -1 is the error code
419 TabAppendedNotificationObserver* observer = NULL;
421 if (browser_tracker_->ContainsHandle(handle)) {
422 Browser* browser = browser_tracker_->GetResource(handle);
423 observer = new TabAppendedNotificationObserver(browser, this,
424 reply_message, false);
425 WebContents* contents =
426 chrome::AddSelectedTabWithURL(browser, url,
427 content::PAGE_TRANSITION_TYPED);
429 append_tab_response = GetIndexForNavigationController(
430 &contents->GetController(), browser);
434 if (append_tab_response < 0) {
435 // Appending tab failed. Clean up and send failure response.
440 AutomationMsg_AppendTab::WriteReplyParams(reply_message,
441 append_tab_response);
446 void TestingAutomationProvider::GetMachPortCount(int* port_count) {
447 #if defined(OS_MACOSX)
448 mach_port_name_array_t names;
449 mach_msg_type_number_t names_count;
450 mach_port_type_array_t types;
451 mach_msg_type_number_t types_count;
453 mach_port_t port = mach_task_self();
455 // A friendlier interface would allow NULL buffers to only get the counts.
456 kern_return_t kr = mach_port_names(port, &names, &names_count,
457 &types, &types_count);
458 if (kr != KERN_SUCCESS) {
463 // The documentation states this is an invariant.
464 DCHECK_EQ(names_count, types_count);
465 *port_count = names_count;
467 mach_vm_deallocate(port, reinterpret_cast<mach_vm_address_t>(names),
468 names_count * sizeof(mach_port_name_array_t));
469 mach_vm_deallocate(port, reinterpret_cast<mach_vm_address_t>(types),
470 types_count * sizeof(mach_port_type_array_t));
476 void TestingAutomationProvider::GetActiveTabIndex(int handle,
477 int* active_tab_index) {
478 *active_tab_index = -1; // -1 is the error code
479 if (browser_tracker_->ContainsHandle(handle)) {
480 Browser* browser = browser_tracker_->GetResource(handle);
481 *active_tab_index = browser->tab_strip_model()->active_index();
485 void TestingAutomationProvider::CloseTab(int tab_handle,
486 bool wait_until_closed,
487 IPC::Message* reply_message) {
488 if (tab_tracker_->ContainsHandle(tab_handle)) {
489 NavigationController* controller = tab_tracker_->GetResource(tab_handle);
490 Browser* browser = chrome::FindBrowserWithWebContents(
491 controller->GetWebContents());
493 new TabClosedNotificationObserver(this, wait_until_closed, reply_message,
495 chrome::CloseWebContents(browser, controller->GetWebContents(), false);
499 AutomationMsg_CloseTab::WriteReplyParams(reply_message, false);
503 void TestingAutomationProvider::GetCookies(const GURL& url, int handle,
505 std::string* value) {
506 WebContents* contents = tab_tracker_->ContainsHandle(handle) ?
507 tab_tracker_->GetResource(handle)->GetWebContents() : NULL;
508 automation_util::GetCookies(url, contents, value_size, value);
511 void TestingAutomationProvider::NavigateToURLBlockUntilNavigationsComplete(
512 int handle, const GURL& url, int number_of_navigations,
513 IPC::Message* reply_message) {
514 if (tab_tracker_->ContainsHandle(handle)) {
515 NavigationController* tab = tab_tracker_->GetResource(handle);
517 // Simulate what a user would do. Activate the tab and then navigate.
518 // We could allow navigating in a background tab in future.
519 Browser* browser = FindAndActivateTab(tab);
522 new NavigationNotificationObserver(tab, this, reply_message,
523 number_of_navigations, false, false);
525 // TODO(darin): avoid conversion to GURL.
526 OpenURLParams params(
527 url, Referrer(), CURRENT_TAB,
528 content::PageTransitionFromInt(
529 content::PAGE_TRANSITION_TYPED |
530 content::PAGE_TRANSITION_FROM_ADDRESS_BAR),
532 browser->OpenURL(params);
537 AutomationMsg_NavigateToURLBlockUntilNavigationsComplete::WriteReplyParams(
538 reply_message, AUTOMATION_MSG_NAVIGATION_ERROR);
542 void TestingAutomationProvider::NavigationAsync(int handle,
547 if (tab_tracker_->ContainsHandle(handle)) {
548 NavigationController* tab = tab_tracker_->GetResource(handle);
550 // Simulate what a user would do. Activate the tab and then navigate.
551 // We could allow navigating in a background tab in future.
552 Browser* browser = FindAndActivateTab(tab);
555 // Don't add any listener unless a callback mechanism is desired.
556 // TODO(vibhor): Do this if such a requirement arises in future.
557 OpenURLParams params(
558 url, Referrer(), CURRENT_TAB,
559 content::PageTransitionFromInt(
560 content::PAGE_TRANSITION_TYPED |
561 content::PAGE_TRANSITION_FROM_ADDRESS_BAR),
563 browser->OpenURL(params);
569 void TestingAutomationProvider::Reload(int handle,
570 IPC::Message* reply_message) {
571 if (tab_tracker_->ContainsHandle(handle)) {
572 NavigationController* tab = tab_tracker_->GetResource(handle);
573 Browser* browser = FindAndActivateTab(tab);
574 if (chrome::IsCommandEnabled(browser, IDC_RELOAD)) {
575 new NavigationNotificationObserver(
576 tab, this, reply_message, 1, false, false);
577 chrome::ExecuteCommand(browser, IDC_RELOAD);
582 AutomationMsg_Reload::WriteReplyParams(
583 reply_message, AUTOMATION_MSG_NAVIGATION_ERROR);
587 void TestingAutomationProvider::GetBrowserWindowCount(int* window_count) {
588 // The automation layer doesn't support non-native desktops.
589 *window_count = static_cast<int>(BrowserList::GetInstance(
590 chrome::HOST_DESKTOP_TYPE_NATIVE)->size());
593 void TestingAutomationProvider::GetNormalBrowserWindowCount(int* window_count) {
594 *window_count = static_cast<int>(chrome::GetTabbedBrowserCount(
595 profile_, chrome::HOST_DESKTOP_TYPE_NATIVE));
598 void TestingAutomationProvider::GetBrowserWindow(int index, int* handle) {
600 Browser* browser = automation_util::GetBrowserAt(index);
602 *handle = browser_tracker_->Add(browser);
605 void TestingAutomationProvider::ExecuteBrowserCommandAsync(int handle,
609 if (!browser_tracker_->ContainsHandle(handle)) {
610 LOG(WARNING) << "Browser tracker does not contain handle: " << handle;
613 Browser* browser = browser_tracker_->GetResource(handle);
614 if (!chrome::SupportsCommand(browser, command)) {
615 LOG(WARNING) << "Browser does not support command: " << command;
618 if (!chrome::IsCommandEnabled(browser, command)) {
619 LOG(WARNING) << "Browser command not enabled: " << command;
622 chrome::ExecuteCommand(browser, command);
626 void TestingAutomationProvider::ExecuteBrowserCommand(
627 int handle, int command, IPC::Message* reply_message) {
628 if (browser_tracker_->ContainsHandle(handle)) {
629 Browser* browser = browser_tracker_->GetResource(handle);
630 if (chrome::SupportsCommand(browser, command) &&
631 chrome::IsCommandEnabled(browser, command)) {
632 // First check if we can handle the command without using an observer.
633 for (size_t i = 0; i < arraysize(kSynchronousCommands); i++) {
634 if (command == kSynchronousCommands[i]) {
635 chrome::ExecuteCommand(browser, command);
636 AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message,
643 // Use an observer if we have one, otherwise fail.
644 if (ExecuteBrowserCommandObserver::CreateAndRegisterObserver(
645 this, browser, command, reply_message, false)) {
646 chrome::ExecuteCommand(browser, command);
651 AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message, false);
655 void TestingAutomationProvider::WebkitMouseClick(DictionaryValue* args,
656 IPC::Message* reply_message) {
657 if (SendErrorIfModalDialogActive(this, reply_message))
660 RenderViewHost* view;
662 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
663 AutomationJSONReply(this, reply_message).SendError(error);
667 WebKit::WebMouseEvent mouse_event;
668 if (!args->GetInteger("x", &mouse_event.x) ||
669 !args->GetInteger("y", &mouse_event.y)) {
670 AutomationJSONReply(this, reply_message)
671 .SendError("(X,Y) coordinates missing or invalid");
676 if (!args->GetInteger("button", &button)) {
677 AutomationJSONReply(this, reply_message)
678 .SendError("Mouse button missing or invalid");
681 if (button == automation::kLeftButton) {
682 mouse_event.button = WebKit::WebMouseEvent::ButtonLeft;
683 } else if (button == automation::kRightButton) {
684 mouse_event.button = WebKit::WebMouseEvent::ButtonRight;
685 } else if (button == automation::kMiddleButton) {
686 mouse_event.button = WebKit::WebMouseEvent::ButtonMiddle;
688 AutomationJSONReply(this, reply_message)
689 .SendError("Invalid button press requested");
693 mouse_event.type = WebKit::WebInputEvent::MouseDown;
694 mouse_event.clickCount = 1;
696 view->ForwardMouseEvent(mouse_event);
698 mouse_event.type = WebKit::WebInputEvent::MouseUp;
699 new InputEventAckNotificationObserver(this, reply_message, mouse_event.type,
701 view->ForwardMouseEvent(mouse_event);
704 void TestingAutomationProvider::WebkitMouseMove(
705 DictionaryValue* args, IPC::Message* reply_message) {
706 if (SendErrorIfModalDialogActive(this, reply_message))
709 RenderViewHost* view;
711 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
712 AutomationJSONReply(this, reply_message).SendError(error);
716 WebKit::WebMouseEvent mouse_event;
717 if (!args->GetInteger("x", &mouse_event.x) ||
718 !args->GetInteger("y", &mouse_event.y)) {
719 AutomationJSONReply(this, reply_message)
720 .SendError("(X,Y) coordinates missing or invalid");
724 mouse_event.type = WebKit::WebInputEvent::MouseMove;
725 new InputEventAckNotificationObserver(this, reply_message, mouse_event.type,
727 view->ForwardMouseEvent(mouse_event);
730 void TestingAutomationProvider::WebkitMouseDrag(DictionaryValue* args,
731 IPC::Message* reply_message) {
732 if (SendErrorIfModalDialogActive(this, reply_message))
735 RenderViewHost* view;
737 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
738 AutomationJSONReply(this, reply_message).SendError(error);
742 WebKit::WebMouseEvent mouse_event;
743 int start_x, start_y, end_x, end_y;
744 if (!args->GetInteger("start_x", &start_x) ||
745 !args->GetInteger("start_y", &start_y) ||
746 !args->GetInteger("end_x", &end_x) ||
747 !args->GetInteger("end_y", &end_y)) {
748 AutomationJSONReply(this, reply_message)
749 .SendError("Invalid start/end positions");
753 mouse_event.type = WebKit::WebInputEvent::MouseMove;
754 // Step 1- Move the mouse to the start position.
755 mouse_event.x = start_x;
756 mouse_event.y = start_y;
757 view->ForwardMouseEvent(mouse_event);
759 // Step 2- Left click mouse down, the mouse button is fixed.
760 mouse_event.type = WebKit::WebInputEvent::MouseDown;
761 mouse_event.button = WebKit::WebMouseEvent::ButtonLeft;
762 mouse_event.clickCount = 1;
763 view->ForwardMouseEvent(mouse_event);
765 // Step 3 - Move the mouse to the end position.
766 mouse_event.type = WebKit::WebInputEvent::MouseMove;
767 mouse_event.x = end_x;
768 mouse_event.y = end_y;
769 mouse_event.clickCount = 0;
770 view->ForwardMouseEvent(mouse_event);
772 // Step 4 - Release the left mouse button.
773 mouse_event.type = WebKit::WebInputEvent::MouseUp;
774 mouse_event.clickCount = 1;
775 new InputEventAckNotificationObserver(this, reply_message, mouse_event.type,
777 view->ForwardMouseEvent(mouse_event);
780 void TestingAutomationProvider::WebkitMouseButtonDown(
781 DictionaryValue* args, IPC::Message* reply_message) {
782 if (SendErrorIfModalDialogActive(this, reply_message))
785 RenderViewHost* view;
787 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
788 AutomationJSONReply(this, reply_message).SendError(error);
792 WebKit::WebMouseEvent mouse_event;
793 if (!args->GetInteger("x", &mouse_event.x) ||
794 !args->GetInteger("y", &mouse_event.y)) {
795 AutomationJSONReply(this, reply_message)
796 .SendError("(X,Y) coordinates missing or invalid");
800 mouse_event.type = WebKit::WebInputEvent::MouseDown;
801 mouse_event.button = WebKit::WebMouseEvent::ButtonLeft;
802 mouse_event.clickCount = 1;
803 new InputEventAckNotificationObserver(this, reply_message, mouse_event.type,
805 view->ForwardMouseEvent(mouse_event);
808 void TestingAutomationProvider::WebkitMouseButtonUp(
809 DictionaryValue* args, IPC::Message* reply_message) {
810 if (SendErrorIfModalDialogActive(this, reply_message))
813 RenderViewHost* view;
815 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
816 AutomationJSONReply(this, reply_message).SendError(error);
820 WebKit::WebMouseEvent mouse_event;
821 if (!args->GetInteger("x", &mouse_event.x) ||
822 !args->GetInteger("y", &mouse_event.y)) {
823 AutomationJSONReply(this, reply_message)
824 .SendError("(X,Y) coordinates missing or invalid");
828 mouse_event.type = WebKit::WebInputEvent::MouseUp;
829 mouse_event.button = WebKit::WebMouseEvent::ButtonLeft;
830 mouse_event.clickCount = 1;
831 new InputEventAckNotificationObserver(this, reply_message, mouse_event.type,
833 view->ForwardMouseEvent(mouse_event);
836 void TestingAutomationProvider::WebkitMouseDoubleClick(
837 DictionaryValue* args, IPC::Message* reply_message) {
838 if (SendErrorIfModalDialogActive(this, reply_message))
841 RenderViewHost* view;
843 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
844 AutomationJSONReply(this, reply_message).SendError(error);
848 WebKit::WebMouseEvent mouse_event;
849 if (!args->GetInteger("x", &mouse_event.x) ||
850 !args->GetInteger("y", &mouse_event.y)) {
851 AutomationJSONReply(this, reply_message)
852 .SendError("(X,Y) coordinates missing or invalid");
856 mouse_event.type = WebKit::WebInputEvent::MouseDown;
857 mouse_event.button = WebKit::WebMouseEvent::ButtonLeft;
858 mouse_event.clickCount = 1;
859 view->ForwardMouseEvent(mouse_event);
861 mouse_event.type = WebKit::WebInputEvent::MouseUp;
862 new InputEventAckNotificationObserver(this, reply_message, mouse_event.type,
864 view->ForwardMouseEvent(mouse_event);
866 mouse_event.type = WebKit::WebInputEvent::MouseDown;
867 mouse_event.clickCount = 2;
868 view->ForwardMouseEvent(mouse_event);
870 mouse_event.type = WebKit::WebInputEvent::MouseUp;
871 view->ForwardMouseEvent(mouse_event);
874 void TestingAutomationProvider::DragAndDropFilePaths(
875 DictionaryValue* args, IPC::Message* reply_message) {
876 if (SendErrorIfModalDialogActive(this, reply_message))
879 RenderViewHost* view;
881 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
882 AutomationJSONReply(this, reply_message).SendError(error);
887 if (!args->GetInteger("x", &x) || !args->GetInteger("y", &y)) {
888 AutomationJSONReply(this, reply_message)
889 .SendError("(X,Y) coordinates missing or invalid");
893 ListValue* paths = NULL;
894 if (!args->GetList("paths", &paths)) {
895 AutomationJSONReply(this, reply_message)
896 .SendError("'paths' missing or invalid");
900 // Emulate drag and drop to set the file paths to the file upload control.
901 content::DropData drop_data;
902 for (size_t path_index = 0; path_index < paths->GetSize(); ++path_index) {
904 if (!paths->GetString(path_index, &path)) {
905 AutomationJSONReply(this, reply_message)
906 .SendError("'paths' contains a non-string type");
910 drop_data.filenames.push_back(
911 content::DropData::FileInfo(path, string16()));
914 const gfx::Point client(x, y);
915 // We don't set any values in screen variable because DragTarget*** ignore the
917 const gfx::Point screen;
920 operations |= WebKit::WebDragOperationCopy;
921 operations |= WebKit::WebDragOperationLink;
922 operations |= WebKit::WebDragOperationMove;
924 view->DragTargetDragEnter(
925 drop_data, client, screen,
926 static_cast<WebKit::WebDragOperationsMask>(operations), 0);
927 new DragTargetDropAckNotificationObserver(this, reply_message);
928 view->DragTargetDrop(client, screen, 0);
931 void TestingAutomationProvider::GetTabCount(int handle, int* tab_count) {
932 *tab_count = -1; // -1 is the error code
934 if (browser_tracker_->ContainsHandle(handle)) {
935 Browser* browser = browser_tracker_->GetResource(handle);
936 *tab_count = browser->tab_strip_model()->count();
940 void TestingAutomationProvider::GetType(int handle, int* type_as_int) {
941 *type_as_int = -1; // -1 is the error code
943 if (browser_tracker_->ContainsHandle(handle)) {
944 Browser* browser = browser_tracker_->GetResource(handle);
945 *type_as_int = static_cast<int>(browser->type());
949 void TestingAutomationProvider::GetTab(int win_handle,
953 if (browser_tracker_->ContainsHandle(win_handle) && (tab_index >= 0)) {
954 Browser* browser = browser_tracker_->GetResource(win_handle);
955 if (tab_index < browser->tab_strip_model()->count()) {
956 WebContents* web_contents =
957 browser->tab_strip_model()->GetWebContentsAt(tab_index);
958 *tab_handle = tab_tracker_->Add(&web_contents->GetController());
963 void TestingAutomationProvider::GetTabTitle(int handle,
964 int* title_string_size,
965 std::wstring* title) {
966 *title_string_size = -1; // -1 is the error code
967 if (tab_tracker_->ContainsHandle(handle)) {
968 NavigationController* tab = tab_tracker_->GetResource(handle);
969 NavigationEntry* entry = tab->GetActiveEntry();
971 *title = UTF16ToWideHack(entry->GetTitleForDisplay(std::string()));
973 *title = std::wstring();
975 *title_string_size = static_cast<int>(title->size());
979 void TestingAutomationProvider::GetTabIndex(int handle, int* tabstrip_index) {
980 *tabstrip_index = -1; // -1 is the error code
982 if (tab_tracker_->ContainsHandle(handle)) {
983 NavigationController* tab = tab_tracker_->GetResource(handle);
984 Browser* browser = chrome::FindBrowserWithWebContents(
985 tab->GetWebContents());
986 *tabstrip_index = browser->tab_strip_model()->GetIndexOfWebContents(
987 tab->GetWebContents());
991 void TestingAutomationProvider::GetTabURL(int handle,
995 if (tab_tracker_->ContainsHandle(handle)) {
996 NavigationController* tab = tab_tracker_->GetResource(handle);
997 // Return what the user would see in the location bar.
998 *url = tab->GetActiveEntry()->GetVirtualURL();
1003 void TestingAutomationProvider::ExecuteJavascriptInRenderViewFrame(
1004 const string16& frame_xpath,
1005 const string16& script,
1006 IPC::Message* reply_message,
1007 RenderViewHost* render_view_host) {
1008 // Set the routing id of this message with the controller.
1009 // This routing id needs to be remembered for the reverse
1010 // communication while sending back the response of
1011 // this javascript execution.
1012 render_view_host->ExecuteJavascriptInWebFrame(
1014 UTF8ToUTF16("window.domAutomationController.setAutomationId(0);"));
1015 render_view_host->ExecuteJavascriptInWebFrame(
1016 frame_xpath, script);
1019 void TestingAutomationProvider::ExecuteJavascript(
1021 const std::wstring& frame_xpath,
1022 const std::wstring& script,
1023 IPC::Message* reply_message) {
1024 WebContents* web_contents = GetWebContentsForHandle(handle, NULL);
1025 if (!web_contents) {
1026 AutomationMsg_DomOperation::WriteReplyParams(reply_message, std::string());
1027 Send(reply_message);
1031 new DomOperationMessageSender(this, reply_message, false);
1032 ExecuteJavascriptInRenderViewFrame(WideToUTF16Hack(frame_xpath),
1033 WideToUTF16Hack(script), reply_message,
1034 web_contents->GetRenderViewHost());
1037 // Sample json input: { "command": "OpenNewBrowserWindowWithNewProfile" }
1038 // Sample output: {}
1039 void TestingAutomationProvider::OpenNewBrowserWindowWithNewProfile(
1040 base::DictionaryValue* args, IPC::Message* reply_message) {
1041 ProfileManager* profile_manager = g_browser_process->profile_manager();
1042 new BrowserOpenedWithNewProfileNotificationObserver(this, reply_message);
1043 profile_manager->CreateMultiProfileAsync(
1044 string16(), string16(), ProfileManager::CreateCallback(), std::string());
1047 // Sample json input: { "command": "GetMultiProfileInfo" }
1048 // See GetMultiProfileInfo() in pyauto.py for sample output.
1049 void TestingAutomationProvider::GetMultiProfileInfo(
1050 base::DictionaryValue* args, IPC::Message* reply_message) {
1051 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
1052 ProfileManager* profile_manager = g_browser_process->profile_manager();
1053 const ProfileInfoCache& profile_info_cache =
1054 profile_manager->GetProfileInfoCache();
1055 return_value->SetBoolean("enabled", profiles::IsMultipleProfilesEnabled());
1057 ListValue* profiles = new ListValue;
1058 for (size_t index = 0; index < profile_info_cache.GetNumberOfProfiles();
1060 DictionaryValue* item = new DictionaryValue;
1061 item->SetString("name", profile_info_cache.GetNameOfProfileAtIndex(index));
1062 item->SetString("path",
1063 profile_info_cache.GetPathOfProfileAtIndex(index).value());
1064 profiles->Append(item);
1066 return_value->Set("profiles", profiles);
1067 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
1070 void TestingAutomationProvider::OpenNewBrowserWindowOfType(
1071 int type, bool show, IPC::Message* reply_message) {
1072 new BrowserOpenedNotificationObserver(this, reply_message, false);
1073 // We may have no current browser windows open so don't rely on
1074 // asking an existing browser to execute the IDC_NEWWINDOW command.
1075 Browser* browser = new Browser(
1076 Browser::CreateParams(static_cast<Browser::Type>(type), profile_,
1077 chrome::HOST_DESKTOP_TYPE_NATIVE));
1078 chrome::AddBlankTabAt(browser, -1, true);
1080 browser->window()->Show();
1083 void TestingAutomationProvider::OpenNewBrowserWindow(
1084 base::DictionaryValue* args,
1085 IPC::Message* reply_message) {
1087 if (!args->GetBoolean("show", &show)) {
1088 AutomationJSONReply(this, reply_message)
1089 .SendError("'show' missing or invalid.");
1092 new BrowserOpenedNotificationObserver(this, reply_message, true);
1093 Browser* browser = new Browser(
1094 Browser::CreateParams(Browser::TYPE_TABBED, profile_,
1095 chrome::HOST_DESKTOP_TYPE_NATIVE));
1096 chrome::AddBlankTabAt(browser, -1, true);
1098 browser->window()->Show();
1101 void TestingAutomationProvider::GetBrowserWindowCountJSON(
1102 base::DictionaryValue* args,
1103 IPC::Message* reply_message) {
1104 DictionaryValue dict;
1105 // The automation layer doesn't support non-native desktops.
1106 dict.SetInteger("count",
1107 static_cast<int>(BrowserList::GetInstance(
1108 chrome::HOST_DESKTOP_TYPE_NATIVE)->size()));
1109 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
1112 void TestingAutomationProvider::CloseBrowserWindow(
1113 base::DictionaryValue* args,
1114 IPC::Message* reply_message) {
1115 AutomationJSONReply reply(this, reply_message);
1117 std::string error_msg;
1118 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
1119 reply.SendError(error_msg);
1122 new BrowserClosedNotificationObserver(browser, this, reply_message, true);
1123 browser->window()->Close();
1126 void TestingAutomationProvider::OpenProfileWindow(
1127 base::DictionaryValue* args, IPC::Message* reply_message) {
1128 ProfileManager* profile_manager = g_browser_process->profile_manager();
1129 base::FilePath::StringType path;
1130 if (!args->GetString("path", &path)) {
1131 AutomationJSONReply(this, reply_message).SendError(
1132 "Invalid or missing arg: 'path'");
1135 Profile* profile = profile_manager->GetProfileByPath(base::FilePath(path));
1137 AutomationJSONReply(this, reply_message).SendError(
1138 base::StringPrintf("Invalid profile path: %s", path.c_str()));
1142 if (!args->GetInteger("num_loads", &num_loads)) {
1143 AutomationJSONReply(this, reply_message).SendError(
1144 "Invalid or missing arg: 'num_loads'");
1147 new BrowserOpenedWithExistingProfileNotificationObserver(
1148 this, reply_message, num_loads);
1149 profiles::FindOrCreateNewWindowForProfile(
1151 chrome::startup::IS_NOT_PROCESS_STARTUP,
1152 chrome::startup::IS_NOT_FIRST_RUN,
1153 chrome::HOST_DESKTOP_TYPE_NATIVE,
1157 void TestingAutomationProvider::GetWindowForBrowser(int browser_handle,
1163 if (browser_tracker_->ContainsHandle(browser_handle)) {
1164 Browser* browser = browser_tracker_->GetResource(browser_handle);
1165 gfx::NativeWindow win = browser->window()->GetNativeWindow();
1166 // Add() returns the existing handle for the resource if any.
1167 *handle = window_tracker_->Add(win);
1172 void TestingAutomationProvider::GetMetricEventDuration(
1173 const std::string& event_name,
1175 *duration_ms = metric_event_duration_observer_->GetEventDurationMs(
1179 void TestingAutomationProvider::BringBrowserToFront(int browser_handle,
1182 if (browser_tracker_->ContainsHandle(browser_handle)) {
1183 Browser* browser = browser_tracker_->GetResource(browser_handle);
1184 browser->window()->Activate();
1189 void TestingAutomationProvider::GetFindWindowVisibility(int handle,
1192 Browser* browser = browser_tracker_->GetResource(handle);
1194 FindBarTesting* find_bar =
1195 browser->GetFindBarController()->find_bar()->GetFindBarTesting();
1196 find_bar->GetFindBarWindowInfo(NULL, visible);
1200 // Bookmark bar visibility is based on the pref (e.g. is it in the toolbar).
1201 // Presence in the NTP is signalled in |detached|.
1202 void TestingAutomationProvider::GetBookmarkBarStatus(
1203 DictionaryValue* args,
1204 IPC::Message* reply_message) {
1205 AutomationJSONReply reply(this, reply_message);
1207 std::string error_msg;
1208 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
1209 reply.SendError(error_msg);
1212 // browser->window()->IsBookmarkBarVisible() is not consistent across
1213 // platforms. bookmark_bar_state() also follows prefs::kShowBookmarkBar
1214 // and has a shared implementation on all platforms.
1215 DictionaryValue dict;
1216 dict.SetBoolean("visible",
1217 browser->bookmark_bar_state() == BookmarkBar::SHOW);
1218 dict.SetBoolean("animating", browser->window()->IsBookmarkBarAnimating());
1219 dict.SetBoolean("detached",
1220 browser->bookmark_bar_state() == BookmarkBar::DETACHED);
1221 reply.SendSuccess(&dict);
1224 void TestingAutomationProvider::GetBookmarksAsJSON(
1225 DictionaryValue* args,
1226 IPC::Message* reply_message) {
1227 AutomationJSONReply reply(this, reply_message);
1229 std::string error_msg, bookmarks_as_json;
1230 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
1231 reply.SendError(error_msg);
1234 BookmarkModel* bookmark_model =
1235 BookmarkModelFactory::GetForProfile(browser->profile());
1236 if (!bookmark_model->loaded()) {
1237 reply.SendError("Bookmark model is not loaded");
1240 scoped_refptr<BookmarkStorage> storage(
1241 new BookmarkStorage(browser->profile(),
1243 browser->profile()->GetIOTaskRunner().get()));
1244 if (!storage->SerializeData(&bookmarks_as_json)) {
1245 reply.SendError("Failed to serialize bookmarks");
1248 DictionaryValue dict;
1249 dict.SetString("bookmarks_as_json", bookmarks_as_json);
1250 reply.SendSuccess(&dict);
1253 void TestingAutomationProvider::WaitForBookmarkModelToLoad(
1255 IPC::Message* reply_message) {
1256 if (browser_tracker_->ContainsHandle(handle)) {
1257 Browser* browser = browser_tracker_->GetResource(handle);
1258 BookmarkModel* model =
1259 BookmarkModelFactory::GetForProfile(browser->profile());
1260 AutomationProviderBookmarkModelObserver* observer =
1261 new AutomationProviderBookmarkModelObserver(this, reply_message,
1263 if (model->loaded()) {
1264 observer->ReleaseReply();
1266 AutomationMsg_WaitForBookmarkModelToLoad::WriteReplyParams(
1267 reply_message, true);
1268 Send(reply_message);
1273 void TestingAutomationProvider::WaitForBookmarkModelToLoadJSON(
1274 DictionaryValue* args,
1275 IPC::Message* reply_message) {
1277 std::string error_msg;
1278 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
1279 AutomationJSONReply(this, reply_message).SendError(error_msg);
1282 BookmarkModel* model =
1283 BookmarkModelFactory::GetForProfile(browser->profile());
1284 AutomationProviderBookmarkModelObserver* observer =
1285 new AutomationProviderBookmarkModelObserver(this, reply_message, model,
1287 if (model->loaded()) {
1288 observer->ReleaseReply();
1290 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
1295 void TestingAutomationProvider::AddBookmark(
1296 DictionaryValue* args,
1297 IPC::Message* reply_message) {
1298 AutomationJSONReply reply(this, reply_message);
1300 std::string error_msg, url;
1302 int parent_id, index;
1304 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
1305 reply.SendError(error_msg);
1308 if (!args->GetBoolean("is_folder", &folder)) {
1309 reply.SendError("'is_folder' missing or invalid");
1312 if (!folder && !args->GetString("url", &url)) {
1313 reply.SendError("'url' missing or invalid");
1316 if (!args->GetInteger("parent_id", &parent_id)) {
1317 reply.SendError("'parent_id' missing or invalid");
1320 if (!args->GetInteger("index", &index)) {
1321 reply.SendError("'index' missing or invalid");
1324 if (!args->GetString("title", &title)) {
1325 reply.SendError("'title' missing or invalid");
1328 BookmarkModel* model =
1329 BookmarkModelFactory::GetForProfile(browser->profile());
1330 if (!model->loaded()) {
1331 reply.SendError("Bookmark model is not loaded");
1334 const BookmarkNode* parent = model->GetNodeByID(parent_id);
1336 reply.SendError("Failed to get parent bookmark node");
1339 const BookmarkNode* child;
1341 child = model->AddFolder(parent, index, title);
1343 child = model->AddURL(parent, index, title, GURL(url));
1346 reply.SendError("Failed to add bookmark");
1349 reply.SendSuccess(NULL);
1352 void TestingAutomationProvider::ReparentBookmark(DictionaryValue* args,
1353 IPC::Message* reply_message) {
1354 AutomationJSONReply reply(this, reply_message);
1356 std::string error_msg;
1357 int new_parent_id, id, index;
1358 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
1359 reply.SendError(error_msg);
1362 if (!args->GetInteger("id", &id)) {
1363 reply.SendError("'id' missing or invalid");
1366 if (!args->GetInteger("new_parent_id", &new_parent_id)) {
1367 reply.SendError("'new_parent_id' missing or invalid");
1370 if (!args->GetInteger("index", &index)) {
1371 reply.SendError("'index' missing or invalid");
1374 BookmarkModel* model =
1375 BookmarkModelFactory::GetForProfile(browser->profile());
1376 if (!model->loaded()) {
1377 reply.SendError("Bookmark model is not loaded");
1380 const BookmarkNode* node = model->GetNodeByID(id);
1381 const BookmarkNode* new_parent = model->GetNodeByID(new_parent_id);
1383 reply.SendError("Failed to get bookmark node");
1387 reply.SendError("Failed to get new parent bookmark node");
1390 model->Move(node, new_parent, index);
1391 reply.SendSuccess(NULL);
1394 void TestingAutomationProvider::SetBookmarkTitle(DictionaryValue* args,
1395 IPC::Message* reply_message) {
1396 AutomationJSONReply reply(this, reply_message);
1398 std::string error_msg;
1401 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
1402 reply.SendError(error_msg);
1405 if (!args->GetInteger("id", &id)) {
1406 reply.SendError("'id' missing or invalid");
1409 if (!args->GetString("title", &title)) {
1410 reply.SendError("'title' missing or invalid");
1413 BookmarkModel* model =
1414 BookmarkModelFactory::GetForProfile(browser->profile());
1415 if (!model->loaded()) {
1416 reply.SendError("Bookmark model is not loaded");
1419 const BookmarkNode* node = model->GetNodeByID(id);
1421 reply.SendError("Failed to get bookmark node");
1424 model->SetTitle(node, title);
1425 reply.SendSuccess(NULL);
1428 void TestingAutomationProvider::SetBookmarkURL(DictionaryValue* args,
1429 IPC::Message* reply_message) {
1430 AutomationJSONReply reply(this, reply_message);
1432 std::string error_msg, url;
1434 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
1435 reply.SendError(error_msg);
1438 if (!args->GetInteger("id", &id)) {
1439 reply.SendError("'id' missing or invalid");
1442 if (!args->GetString("url", &url)) {
1443 reply.SendError("'url' missing or invalid");
1446 BookmarkModel* model =
1447 BookmarkModelFactory::GetForProfile(browser->profile());
1448 if (!model->loaded()) {
1449 reply.SendError("Bookmark model is not loaded");
1452 const BookmarkNode* node = model->GetNodeByID(id);
1454 reply.SendError("Failed to get bookmark node");
1457 model->SetURL(node, GURL(url));
1458 reply.SendSuccess(NULL);
1461 void TestingAutomationProvider::RemoveBookmark(DictionaryValue* args,
1462 IPC::Message* reply_message) {
1463 AutomationJSONReply reply(this, reply_message);
1465 std::string error_msg;
1467 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
1468 reply.SendError(error_msg);
1471 if (!args->GetInteger("id", &id)) {
1472 reply.SendError("'id' missing or invalid");
1475 BookmarkModel* model =
1476 BookmarkModelFactory::GetForProfile(browser->profile());
1477 if (!model->loaded()) {
1478 reply.SendError("Bookmark model is not loaded");
1481 const BookmarkNode* node = model->GetNodeByID(id);
1483 reply.SendError("Failed to get bookmark node");
1486 const BookmarkNode* parent = node->parent();
1488 reply.SendError("Failed to get parent bookmark node");
1491 model->Remove(parent, parent->GetIndexOf(node));
1492 reply.SendSuccess(NULL);
1495 void TestingAutomationProvider::WaitForBrowserWindowCountToBecome(
1497 IPC::Message* reply_message) {
1498 // The automation layer doesn't support non-native desktops.
1499 int current_count = static_cast<int>(BrowserList::GetInstance(
1500 chrome::HOST_DESKTOP_TYPE_NATIVE)->size());
1501 if (current_count == target_count) {
1502 AutomationMsg_WaitForBrowserWindowCountToBecome::WriteReplyParams(
1503 reply_message, true);
1504 Send(reply_message);
1508 // Set up an observer (it will delete itself).
1509 new BrowserCountChangeNotificationObserver(target_count, this, reply_message);
1512 void TestingAutomationProvider::GoBackBlockUntilNavigationsComplete(
1513 int handle, int number_of_navigations, IPC::Message* reply_message) {
1514 if (tab_tracker_->ContainsHandle(handle)) {
1515 NavigationController* tab = tab_tracker_->GetResource(handle);
1516 Browser* browser = FindAndActivateTab(tab);
1517 if (chrome::IsCommandEnabled(browser, IDC_BACK)) {
1518 new NavigationNotificationObserver(tab, this, reply_message,
1519 number_of_navigations, false, false);
1520 chrome::ExecuteCommand(browser, IDC_BACK);
1525 AutomationMsg_GoBackBlockUntilNavigationsComplete::WriteReplyParams(
1526 reply_message, AUTOMATION_MSG_NAVIGATION_ERROR);
1527 Send(reply_message);
1530 void TestingAutomationProvider::GoForwardBlockUntilNavigationsComplete(
1531 int handle, int number_of_navigations, IPC::Message* reply_message) {
1532 if (tab_tracker_->ContainsHandle(handle)) {
1533 NavigationController* tab = tab_tracker_->GetResource(handle);
1534 Browser* browser = FindAndActivateTab(tab);
1535 if (chrome::IsCommandEnabled(browser, IDC_FORWARD)) {
1536 new NavigationNotificationObserver(tab, this, reply_message,
1537 number_of_navigations, false, false);
1538 chrome::ExecuteCommand(browser, IDC_FORWARD);
1543 AutomationMsg_GoForwardBlockUntilNavigationsComplete::WriteReplyParams(
1544 reply_message, AUTOMATION_MSG_NAVIGATION_ERROR);
1545 Send(reply_message);
1548 void TestingAutomationProvider::BuildJSONHandlerMaps() {
1549 // Map json commands to their handlers.
1550 handler_map_["ApplyAccelerator"] =
1551 &TestingAutomationProvider::ExecuteBrowserCommandAsyncJSON;
1552 handler_map_["RunCommand"] =
1553 &TestingAutomationProvider::ExecuteBrowserCommandJSON;
1554 handler_map_["IsMenuCommandEnabled"] =
1555 &TestingAutomationProvider::IsMenuCommandEnabledJSON;
1556 handler_map_["ActivateTab"] =
1557 &TestingAutomationProvider::ActivateTabJSON;
1558 handler_map_["BringBrowserToFront"] =
1559 &TestingAutomationProvider::BringBrowserToFrontJSON;
1560 handler_map_["GetIndicesFromTab"] =
1561 &TestingAutomationProvider::GetIndicesFromTab;
1562 handler_map_["NavigateToURL"] =
1563 &TestingAutomationProvider::NavigateToURL;
1564 handler_map_["GetActiveTabIndex"] =
1565 &TestingAutomationProvider::GetActiveTabIndexJSON;
1566 handler_map_["AppendTab"] =
1567 &TestingAutomationProvider::AppendTabJSON;
1568 handler_map_["OpenNewBrowserWindow"] =
1569 &TestingAutomationProvider::OpenNewBrowserWindow;
1570 handler_map_["CloseBrowserWindow"] =
1571 &TestingAutomationProvider::CloseBrowserWindow;
1572 handler_map_["WaitUntilNavigationCompletes"] =
1573 &TestingAutomationProvider::WaitUntilNavigationCompletes;
1574 handler_map_["GetLocalStatePrefsInfo"] =
1575 &TestingAutomationProvider::GetLocalStatePrefsInfo;
1576 handler_map_["SetLocalStatePrefs"] =
1577 &TestingAutomationProvider::SetLocalStatePrefs;
1578 handler_map_["GetPrefsInfo"] = &TestingAutomationProvider::GetPrefsInfo;
1579 handler_map_["SetPrefs"] = &TestingAutomationProvider::SetPrefs;
1580 handler_map_["ExecuteJavascript"] =
1581 &TestingAutomationProvider::ExecuteJavascriptJSON;
1582 handler_map_["AddDomEventObserver"] =
1583 &TestingAutomationProvider::AddDomEventObserver;
1584 handler_map_["RemoveEventObserver"] =
1585 &TestingAutomationProvider::RemoveEventObserver;
1586 handler_map_["GetNextEvent"] =
1587 &TestingAutomationProvider::GetNextEvent;
1588 handler_map_["ClearEventQueue"] =
1589 &TestingAutomationProvider::ClearEventQueue;
1590 handler_map_["ExecuteJavascriptInRenderView"] =
1591 &TestingAutomationProvider::ExecuteJavascriptInRenderView;
1592 handler_map_["GoForward"] =
1593 &TestingAutomationProvider::GoForward;
1594 handler_map_["GoBack"] =
1595 &TestingAutomationProvider::GoBack;
1596 handler_map_["Reload"] =
1597 &TestingAutomationProvider::ReloadJSON;
1598 handler_map_["OpenFindInPage"] =
1599 &TestingAutomationProvider::OpenFindInPage;
1600 handler_map_["IsFindInPageVisible"] =
1601 &TestingAutomationProvider::IsFindInPageVisible;
1602 handler_map_["SetDownloadShelfVisible"] =
1603 &TestingAutomationProvider::SetDownloadShelfVisibleJSON;
1604 handler_map_["IsDownloadShelfVisible"] =
1605 &TestingAutomationProvider::IsDownloadShelfVisibleJSON;
1606 handler_map_["GetDownloadDirectory"] =
1607 &TestingAutomationProvider::GetDownloadDirectoryJSON;
1608 handler_map_["GetCookies"] =
1609 &TestingAutomationProvider::GetCookiesJSON;
1610 handler_map_["DeleteCookie"] =
1611 &TestingAutomationProvider::DeleteCookieJSON;
1612 handler_map_["SetCookie"] =
1613 &TestingAutomationProvider::SetCookieJSON;
1614 handler_map_["GetCookiesInBrowserContext"] =
1615 &TestingAutomationProvider::GetCookiesInBrowserContext;
1616 handler_map_["DeleteCookieInBrowserContext"] =
1617 &TestingAutomationProvider::DeleteCookieInBrowserContext;
1618 handler_map_["SetCookieInBrowserContext"] =
1619 &TestingAutomationProvider::SetCookieInBrowserContext;
1621 handler_map_["WaitForBookmarkModelToLoad"] =
1622 &TestingAutomationProvider::WaitForBookmarkModelToLoadJSON;
1623 handler_map_["GetBookmarksAsJSON"] =
1624 &TestingAutomationProvider::GetBookmarksAsJSON;
1625 handler_map_["GetBookmarkBarStatus"] =
1626 &TestingAutomationProvider::GetBookmarkBarStatus;
1627 handler_map_["AddBookmark"] =
1628 &TestingAutomationProvider::AddBookmark;
1629 handler_map_["ReparentBookmark"] =
1630 &TestingAutomationProvider::ReparentBookmark;
1631 handler_map_["SetBookmarkTitle"] =
1632 &TestingAutomationProvider::SetBookmarkTitle;
1633 handler_map_["SetBookmarkURL"] =
1634 &TestingAutomationProvider::SetBookmarkURL;
1635 handler_map_["RemoveBookmark"] =
1636 &TestingAutomationProvider::RemoveBookmark;
1638 handler_map_["GetTabIds"] =
1639 &TestingAutomationProvider::GetTabIds;
1640 handler_map_["IsTabIdValid"] =
1641 &TestingAutomationProvider::IsTabIdValid;
1642 handler_map_["CloseTab"] =
1643 &TestingAutomationProvider::CloseTabJSON;
1644 handler_map_["SetViewBounds"] =
1645 &TestingAutomationProvider::SetViewBounds;
1646 handler_map_["MaximizeView"] =
1647 &TestingAutomationProvider::MaximizeView;
1648 handler_map_["WebkitMouseMove"] =
1649 &TestingAutomationProvider::WebkitMouseMove;
1650 handler_map_["WebkitMouseClick"] =
1651 &TestingAutomationProvider::WebkitMouseClick;
1652 handler_map_["WebkitMouseDrag"] =
1653 &TestingAutomationProvider::WebkitMouseDrag;
1654 handler_map_["WebkitMouseButtonUp"] =
1655 &TestingAutomationProvider::WebkitMouseButtonUp;
1656 handler_map_["WebkitMouseButtonDown"] =
1657 &TestingAutomationProvider::WebkitMouseButtonDown;
1658 handler_map_["WebkitMouseDoubleClick"] =
1659 &TestingAutomationProvider::WebkitMouseDoubleClick;
1660 handler_map_["DragAndDropFilePaths"] =
1661 &TestingAutomationProvider::DragAndDropFilePaths;
1662 handler_map_["SendWebkitKeyEvent"] =
1663 &TestingAutomationProvider::SendWebkitKeyEvent;
1664 handler_map_["ActivateTab"] =
1665 &TestingAutomationProvider::ActivateTabJSON;
1666 handler_map_["GetAppModalDialogMessage"] =
1667 &TestingAutomationProvider::GetAppModalDialogMessage;
1668 handler_map_["AcceptOrDismissAppModalDialog"] =
1669 &TestingAutomationProvider::AcceptOrDismissAppModalDialog;
1670 handler_map_["ActionOnSSLBlockingPage"] =
1671 &TestingAutomationProvider::ActionOnSSLBlockingPage;
1672 handler_map_["GetSecurityState"] =
1673 &TestingAutomationProvider::GetSecurityState;
1674 handler_map_["IsPageActionVisible"] =
1675 &TestingAutomationProvider::IsPageActionVisible;
1676 handler_map_["CreateNewAutomationProvider"] =
1677 &TestingAutomationProvider::CreateNewAutomationProvider;
1678 handler_map_["GetBrowserWindowCount"] =
1679 &TestingAutomationProvider::GetBrowserWindowCountJSON;
1680 handler_map_["GetBrowserInfo"] =
1681 &TestingAutomationProvider::GetBrowserInfo;
1682 handler_map_["GetTabInfo"] =
1683 &TestingAutomationProvider::GetTabInfo;
1684 handler_map_["GetTabCount"] =
1685 &TestingAutomationProvider::GetTabCountJSON;
1686 handler_map_["OpenNewBrowserWindowWithNewProfile"] =
1687 &TestingAutomationProvider::OpenNewBrowserWindowWithNewProfile;
1688 handler_map_["GetMultiProfileInfo"] =
1689 &TestingAutomationProvider::GetMultiProfileInfo;
1690 handler_map_["OpenProfileWindow"] =
1691 &TestingAutomationProvider::OpenProfileWindow;
1692 handler_map_["GetProcessInfo"] =
1693 &TestingAutomationProvider::GetProcessInfo;
1694 handler_map_["RefreshPolicies"] =
1695 &TestingAutomationProvider::RefreshPolicies;
1696 handler_map_["InstallExtension"] =
1697 &TestingAutomationProvider::InstallExtension;
1698 handler_map_["GetExtensionsInfo"] =
1699 &TestingAutomationProvider::GetExtensionsInfo;
1700 handler_map_["UninstallExtensionById"] =
1701 &TestingAutomationProvider::UninstallExtensionById;
1702 handler_map_["SetExtensionStateById"] =
1703 &TestingAutomationProvider::SetExtensionStateById;
1704 handler_map_["TriggerPageActionById"] =
1705 &TestingAutomationProvider::TriggerPageActionById;
1706 handler_map_["TriggerBrowserActionById"] =
1707 &TestingAutomationProvider::TriggerBrowserActionById;
1708 handler_map_["UpdateExtensionsNow"] =
1709 &TestingAutomationProvider::UpdateExtensionsNow;
1710 handler_map_["OverrideGeoposition"] =
1711 &TestingAutomationProvider::OverrideGeoposition;
1712 handler_map_["SimulateAsanMemoryBug"] =
1713 &TestingAutomationProvider::SimulateAsanMemoryBug;
1715 #if defined(OS_CHROMEOS)
1716 handler_map_["AcceptOOBENetworkScreen"] =
1717 &TestingAutomationProvider::AcceptOOBENetworkScreen;
1718 handler_map_["AcceptOOBEEula"] = &TestingAutomationProvider::AcceptOOBEEula;
1719 handler_map_["CancelOOBEUpdate"] =
1720 &TestingAutomationProvider::CancelOOBEUpdate;
1721 handler_map_["PickUserImage"] = &TestingAutomationProvider::PickUserImage;
1722 handler_map_["SkipToLogin"] = &TestingAutomationProvider::SkipToLogin;
1723 handler_map_["GetOOBEScreenInfo"] =
1724 &TestingAutomationProvider::GetOOBEScreenInfo;
1726 handler_map_["GetLoginInfo"] = &TestingAutomationProvider::GetLoginInfo;
1727 handler_map_["ShowCreateAccountUI"] =
1728 &TestingAutomationProvider::ShowCreateAccountUI;
1729 handler_map_["ExecuteJavascriptInOOBEWebUI"] =
1730 &TestingAutomationProvider::ExecuteJavascriptInOOBEWebUI;
1731 handler_map_["LoginAsGuest"] = &TestingAutomationProvider::LoginAsGuest;
1732 handler_map_["SubmitLoginForm"] =
1733 &TestingAutomationProvider::SubmitLoginForm;
1734 handler_map_["AddLoginEventObserver"] =
1735 &TestingAutomationProvider::AddLoginEventObserver;
1736 handler_map_["SignOut"] = &TestingAutomationProvider::SignOut;
1738 handler_map_["LockScreen"] = &TestingAutomationProvider::LockScreen;
1739 handler_map_["UnlockScreen"] = &TestingAutomationProvider::UnlockScreen;
1740 handler_map_["SignoutInScreenLocker"] =
1741 &TestingAutomationProvider::SignoutInScreenLocker;
1743 handler_map_["GetBatteryInfo"] = &TestingAutomationProvider::GetBatteryInfo;
1745 handler_map_["EnableSpokenFeedback"] =
1746 &TestingAutomationProvider::EnableSpokenFeedback;
1747 handler_map_["IsSpokenFeedbackEnabled"] =
1748 &TestingAutomationProvider::IsSpokenFeedbackEnabled;
1750 handler_map_["GetTimeInfo"] = &TestingAutomationProvider::GetTimeInfo;
1751 handler_map_["SetTimezone"] = &TestingAutomationProvider::SetTimezone;
1753 handler_map_["UpdateCheck"] = &TestingAutomationProvider::UpdateCheck;
1755 handler_map_["GetVolumeInfo"] = &TestingAutomationProvider::GetVolumeInfo;
1756 handler_map_["SetVolume"] = &TestingAutomationProvider::SetVolume;
1757 handler_map_["SetMute"] = &TestingAutomationProvider::SetMute;
1759 handler_map_["OpenCrosh"] = &TestingAutomationProvider::OpenCrosh;
1761 browser_handler_map_["GetTimeInfo"] =
1762 &TestingAutomationProvider::GetTimeInfo;
1763 #endif // defined(OS_CHROMEOS)
1765 browser_handler_map_["DisablePlugin"] =
1766 &TestingAutomationProvider::DisablePlugin;
1767 browser_handler_map_["EnablePlugin"] =
1768 &TestingAutomationProvider::EnablePlugin;
1769 browser_handler_map_["GetPluginsInfo"] =
1770 &TestingAutomationProvider::GetPluginsInfo;
1772 browser_handler_map_["GetNavigationInfo"] =
1773 &TestingAutomationProvider::GetNavigationInfo;
1775 browser_handler_map_["PerformActionOnInfobar"] =
1776 &TestingAutomationProvider::PerformActionOnInfobar;
1778 browser_handler_map_["GetHistoryInfo"] =
1779 &TestingAutomationProvider::GetHistoryInfo;
1781 browser_handler_map_["GetOmniboxInfo"] =
1782 &TestingAutomationProvider::GetOmniboxInfo;
1783 browser_handler_map_["SetOmniboxText"] =
1784 &TestingAutomationProvider::SetOmniboxText;
1785 browser_handler_map_["OmniboxAcceptInput"] =
1786 &TestingAutomationProvider::OmniboxAcceptInput;
1787 browser_handler_map_["OmniboxMovePopupSelection"] =
1788 &TestingAutomationProvider::OmniboxMovePopupSelection;
1790 browser_handler_map_["LoadSearchEngineInfo"] =
1791 &TestingAutomationProvider::LoadSearchEngineInfo;
1792 browser_handler_map_["GetSearchEngineInfo"] =
1793 &TestingAutomationProvider::GetSearchEngineInfo;
1794 browser_handler_map_["AddOrEditSearchEngine"] =
1795 &TestingAutomationProvider::AddOrEditSearchEngine;
1796 browser_handler_map_["PerformActionOnSearchEngine"] =
1797 &TestingAutomationProvider::PerformActionOnSearchEngine;
1799 browser_handler_map_["SetWindowDimensions"] =
1800 &TestingAutomationProvider::SetWindowDimensions;
1802 browser_handler_map_["GetDownloadsInfo"] =
1803 &TestingAutomationProvider::GetDownloadsInfo;
1804 browser_handler_map_["WaitForAllDownloadsToComplete"] =
1805 &TestingAutomationProvider::WaitForAllDownloadsToComplete;
1806 browser_handler_map_["PerformActionOnDownload"] =
1807 &TestingAutomationProvider::PerformActionOnDownload;
1809 browser_handler_map_["GetInitialLoadTimes"] =
1810 &TestingAutomationProvider::GetInitialLoadTimes;
1812 browser_handler_map_["SaveTabContents"] =
1813 &TestingAutomationProvider::SaveTabContents;
1815 browser_handler_map_["AddSavedPassword"] =
1816 &TestingAutomationProvider::AddSavedPassword;
1817 browser_handler_map_["RemoveSavedPassword"] =
1818 &TestingAutomationProvider::RemoveSavedPassword;
1819 browser_handler_map_["GetSavedPasswords"] =
1820 &TestingAutomationProvider::GetSavedPasswords;
1822 browser_handler_map_["FindInPage"] = &TestingAutomationProvider::FindInPage;
1824 browser_handler_map_["GetAllNotifications"] =
1825 &TestingAutomationProvider::GetAllNotifications;
1826 browser_handler_map_["CloseNotification"] =
1827 &TestingAutomationProvider::CloseNotification;
1828 browser_handler_map_["WaitForNotificationCount"] =
1829 &TestingAutomationProvider::WaitForNotificationCount;
1831 browser_handler_map_["GetNTPInfo"] =
1832 &TestingAutomationProvider::GetNTPInfo;
1833 browser_handler_map_["RemoveNTPMostVisitedThumbnail"] =
1834 &TestingAutomationProvider::RemoveNTPMostVisitedThumbnail;
1835 browser_handler_map_["RestoreAllNTPMostVisitedThumbnails"] =
1836 &TestingAutomationProvider::RestoreAllNTPMostVisitedThumbnails;
1838 browser_handler_map_["KillRendererProcess"] =
1839 &TestingAutomationProvider::KillRendererProcess;
1841 browser_handler_map_["LaunchApp"] = &TestingAutomationProvider::LaunchApp;
1842 browser_handler_map_["SetAppLaunchType"] =
1843 &TestingAutomationProvider::SetAppLaunchType;
1845 browser_handler_map_["GetV8HeapStats"] =
1846 &TestingAutomationProvider::GetV8HeapStats;
1847 browser_handler_map_["GetFPS"] =
1848 &TestingAutomationProvider::GetFPS;
1850 browser_handler_map_["IsFullscreenForBrowser"] =
1851 &TestingAutomationProvider::IsFullscreenForBrowser;
1852 browser_handler_map_["IsFullscreenForTab"] =
1853 &TestingAutomationProvider::IsFullscreenForTab;
1854 browser_handler_map_["IsMouseLocked"] =
1855 &TestingAutomationProvider::IsMouseLocked;
1856 browser_handler_map_["IsMouseLockPermissionRequested"] =
1857 &TestingAutomationProvider::IsMouseLockPermissionRequested;
1858 browser_handler_map_["IsFullscreenPermissionRequested"] =
1859 &TestingAutomationProvider::IsFullscreenPermissionRequested;
1860 browser_handler_map_["IsFullscreenBubbleDisplayed"] =
1861 &TestingAutomationProvider::IsFullscreenBubbleDisplayed;
1862 browser_handler_map_["IsFullscreenBubbleDisplayingButtons"] =
1863 &TestingAutomationProvider::IsFullscreenBubbleDisplayingButtons;
1864 browser_handler_map_["AcceptCurrentFullscreenOrMouseLockRequest"] =
1865 &TestingAutomationProvider::AcceptCurrentFullscreenOrMouseLockRequest;
1866 browser_handler_map_["DenyCurrentFullscreenOrMouseLockRequest"] =
1867 &TestingAutomationProvider::DenyCurrentFullscreenOrMouseLockRequest;
1870 scoped_ptr<DictionaryValue> TestingAutomationProvider::ParseJSONRequestCommand(
1871 const std::string& json_request,
1872 std::string* command,
1873 std::string* error) {
1874 scoped_ptr<DictionaryValue> dict_value;
1875 scoped_ptr<Value> values(base::JSONReader::ReadAndReturnError(json_request,
1876 base::JSON_ALLOW_TRAILING_COMMAS, NULL, error));
1878 // Make sure input is a dict with a string command.
1879 if (values->GetType() != Value::TYPE_DICTIONARY) {
1880 *error = "Command dictionary is not a dictionary.";
1882 dict_value.reset(static_cast<DictionaryValue*>(values.release()));
1883 if (!dict_value->GetStringASCII("command", command)) {
1884 *error = "Command key string missing from dictionary.";
1885 dict_value.reset(NULL);
1889 return dict_value.Pass();
1892 void TestingAutomationProvider::SendJSONRequestWithBrowserHandle(
1894 const std::string& json_request,
1895 IPC::Message* reply_message) {
1896 Browser* browser = NULL;
1897 if (browser_tracker_->ContainsHandle(handle))
1898 browser = browser_tracker_->GetResource(handle);
1899 if (browser || handle < 0) {
1900 SendJSONRequest(browser, json_request, reply_message);
1902 AutomationJSONReply(this, reply_message).SendError(
1903 "The browser window does not exist.");
1907 void TestingAutomationProvider::SendJSONRequestWithBrowserIndex(
1909 const std::string& json_request,
1910 IPC::Message* reply_message) {
1911 Browser* browser = index < 0 ? NULL : automation_util::GetBrowserAt(index);
1912 if (!browser && index >= 0) {
1913 AutomationJSONReply(this, reply_message).SendError(base::StringPrintf(
1914 "Browser window with index=%d does not exist.", index));
1916 SendJSONRequest(browser, json_request, reply_message);
1920 void TestingAutomationProvider::SendJSONRequest(Browser* browser,
1921 const std::string& json_request,
1922 IPC::Message* reply_message) {
1923 std::string command, error_string;
1924 scoped_ptr<DictionaryValue> dict_value(
1925 ParseJSONRequestCommand(json_request, &command, &error_string));
1926 if (!dict_value.get() || command.empty()) {
1927 AutomationJSONReply(this, reply_message).SendError(error_string);
1931 if (handler_map_.empty() || browser_handler_map_.empty())
1932 BuildJSONHandlerMaps();
1934 // Look for command in handlers that take a Browser.
1935 if (browser_handler_map_.find(std::string(command)) !=
1936 browser_handler_map_.end() && browser) {
1937 (this->*browser_handler_map_[command])(browser, dict_value.get(),
1939 // Look for command in handlers that don't take a Browser.
1940 } else if (handler_map_.find(std::string(command)) != handler_map_.end()) {
1941 (this->*handler_map_[command])(dict_value.get(), reply_message);
1942 // Command has no handler.
1944 error_string = base::StringPrintf("Unknown command '%s'. Options: ",
1946 for (std::map<std::string, JsonHandler>::const_iterator it =
1947 handler_map_.begin(); it != handler_map_.end(); ++it) {
1948 error_string += it->first + ", ";
1950 for (std::map<std::string, BrowserJsonHandler>::const_iterator it =
1951 browser_handler_map_.begin(); it != browser_handler_map_.end(); ++it) {
1952 error_string += it->first + ", ";
1954 AutomationJSONReply(this, reply_message).SendError(error_string);
1958 void TestingAutomationProvider::BringBrowserToFrontJSON(
1959 DictionaryValue* args,
1960 IPC::Message* reply_message) {
1961 AutomationJSONReply reply(this, reply_message);
1963 std::string error_msg;
1964 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
1965 reply.SendError(error_msg);
1968 browser->window()->Activate();
1969 reply.SendSuccess(NULL);
1972 // Sample json input: { "command": "SetWindowDimensions",
1973 // "x": 20, # optional
1974 // "y": 20, # optional
1975 // "width": 800, # optional
1976 // "height": 600 } # optional
1977 void TestingAutomationProvider::SetWindowDimensions(
1979 DictionaryValue* args,
1980 IPC::Message* reply_message) {
1981 gfx::Rect rect = browser->window()->GetRestoredBounds();
1982 int x, y, width, height;
1983 if (args->GetInteger("x", &x))
1985 if (args->GetInteger("y", &y))
1987 if (args->GetInteger("width", &width))
1988 rect.set_width(width);
1989 if (args->GetInteger("height", &height))
1990 rect.set_height(height);
1991 browser->window()->SetBounds(rect);
1992 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
1995 ListValue* TestingAutomationProvider::GetInfobarsInfo(WebContents* wc) {
1996 // Each infobar may have different properties depending on the type.
1997 ListValue* infobars = new ListValue;
1998 InfoBarService* infobar_service = InfoBarService::FromWebContents(wc);
1999 for (size_t i = 0; i < infobar_service->infobar_count(); ++i) {
2000 DictionaryValue* infobar_item = new DictionaryValue;
2001 InfoBarDelegate* infobar = infobar_service->infobar_at(i);
2002 switch (infobar->GetInfoBarAutomationType()) {
2003 case InfoBarDelegate::CONFIRM_INFOBAR:
2004 infobar_item->SetString("type", "confirm_infobar");
2006 case InfoBarDelegate::PASSWORD_INFOBAR:
2007 infobar_item->SetString("type", "password_infobar");
2009 case InfoBarDelegate::RPH_INFOBAR:
2010 infobar_item->SetString("type", "rph_infobar");
2012 case InfoBarDelegate::UNKNOWN_INFOBAR:
2013 infobar_item->SetString("type", "unknown_infobar");
2016 if (infobar->AsConfirmInfoBarDelegate()) {
2017 // Also covers ThemeInstalledInfoBarDelegate.
2018 ConfirmInfoBarDelegate* confirm_infobar =
2019 infobar->AsConfirmInfoBarDelegate();
2020 infobar_item->SetString("text", confirm_infobar->GetMessageText());
2021 infobar_item->SetString("link_text", confirm_infobar->GetLinkText());
2022 ListValue* buttons_list = new ListValue;
2023 int buttons = confirm_infobar->GetButtons();
2024 if (buttons & ConfirmInfoBarDelegate::BUTTON_OK) {
2025 StringValue* button_label = new StringValue(
2026 confirm_infobar->GetButtonLabel(
2027 ConfirmInfoBarDelegate::BUTTON_OK));
2028 buttons_list->Append(button_label);
2030 if (buttons & ConfirmInfoBarDelegate::BUTTON_CANCEL) {
2031 StringValue* button_label = new StringValue(
2032 confirm_infobar->GetButtonLabel(
2033 ConfirmInfoBarDelegate::BUTTON_CANCEL));
2034 buttons_list->Append(button_label);
2036 infobar_item->Set("buttons", buttons_list);
2037 } else if (infobar->AsExtensionInfoBarDelegate()) {
2038 infobar_item->SetString("type", "extension_infobar");
2040 infobar_item->SetString("type", "unknown_infobar");
2042 infobars->Append(infobar_item);
2047 // Sample json input: { "command": "PerformActionOnInfobar",
2048 // "action": "dismiss",
2049 // "infobar_index": 0,
2051 // Sample output: {}
2052 void TestingAutomationProvider::PerformActionOnInfobar(
2054 DictionaryValue* args,
2055 IPC::Message* reply_message) {
2056 AutomationJSONReply reply(this, reply_message);
2058 int infobar_index_int;
2060 if (!args->GetInteger("tab_index", &tab_index) ||
2061 !args->GetInteger("infobar_index", &infobar_index_int) ||
2062 !args->GetString("action", &action)) {
2063 reply.SendError("Invalid or missing args");
2066 size_t infobar_index = static_cast<size_t>(infobar_index_int);
2068 WebContents* web_contents =
2069 browser->tab_strip_model()->GetWebContentsAt(tab_index);
2070 if (!web_contents) {
2071 reply.SendError(base::StringPrintf("No such tab at index %d", tab_index));
2075 InfoBarService* infobar_service =
2076 InfoBarService::FromWebContents(web_contents);
2077 if (infobar_index >= infobar_service->infobar_count()) {
2078 reply.SendError(base::StringPrintf("No such infobar at index %" PRIuS,
2082 InfoBarDelegate* infobar_delegate =
2083 infobar_service->infobar_at(infobar_index);
2085 if (action == "dismiss") {
2086 infobar_delegate->InfoBarDismissed();
2087 infobar_service->RemoveInfoBar(infobar_delegate);
2088 reply.SendSuccess(NULL);
2091 if ((action == "accept") || (action == "cancel")) {
2092 ConfirmInfoBarDelegate* confirm_infobar_delegate =
2093 infobar_delegate->AsConfirmInfoBarDelegate();
2094 if (!confirm_infobar_delegate) {
2095 reply.SendError("Not a confirm infobar");
2098 if ((action == "accept") ?
2099 confirm_infobar_delegate->Accept() : confirm_infobar_delegate->Cancel())
2100 infobar_service->RemoveInfoBar(infobar_delegate);
2101 reply.SendSuccess(NULL);
2105 reply.SendError("Invalid action");
2110 // Gets info about BrowserChildProcessHost. Must run on IO thread to
2111 // honor the semantics of BrowserChildProcessHostIterator.
2112 // Used by AutomationProvider::GetBrowserInfo().
2113 void GetChildProcessHostInfo(ListValue* child_processes) {
2114 for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
2115 // Only add processes which are already started, since we need their handle.
2116 if (iter.GetData().handle == base::kNullProcessHandle)
2118 DictionaryValue* item = new DictionaryValue;
2119 item->SetString("name", iter.GetData().name);
2122 content::GetProcessTypeNameInEnglish(iter.GetData().process_type));
2123 item->SetInteger("pid", base::GetProcId(iter.GetData().handle));
2124 child_processes->Append(item);
2130 // Sample json input: { "command": "GetBrowserInfo" }
2131 // Refer to GetBrowserInfo() in chrome/test/pyautolib/pyauto.py for
2132 // sample json output.
2133 void TestingAutomationProvider::GetBrowserInfo(
2134 DictionaryValue* args,
2135 IPC::Message* reply_message) {
2136 base::ThreadRestrictions::ScopedAllowIO allow_io; // needed for PathService
2137 DictionaryValue* properties = new DictionaryValue;
2138 properties->SetString("ChromeVersion", chrome::kChromeVersion);
2139 properties->SetString("BrowserProcessExecutableName",
2140 chrome::kBrowserProcessExecutableName);
2141 properties->SetString("HelperProcessExecutableName",
2142 chrome::kHelperProcessExecutableName);
2143 properties->SetString("BrowserProcessExecutablePath",
2144 chrome::kBrowserProcessExecutablePath);
2145 properties->SetString("HelperProcessExecutablePath",
2146 chrome::kHelperProcessExecutablePath);
2147 properties->SetString("command_line_string",
2148 CommandLine::ForCurrentProcess()->GetCommandLineString());
2149 base::FilePath dumps_path;
2150 PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path);
2151 properties->SetString("DIR_CRASH_DUMPS", dumps_path.value());
2152 #if defined(USE_AURA)
2153 properties->SetBoolean("aura", true);
2155 properties->SetBoolean("aura", false);
2158 std::string branding;
2159 #if defined(GOOGLE_CHROME_BUILD)
2160 branding = "Google Chrome";
2161 #elif defined(CHROMIUM_BUILD)
2162 branding = "Chromium";
2164 branding = "Unknown Branding";
2166 properties->SetString("branding", branding);
2168 bool is_official_build = false;
2169 #if defined(OFFICIAL_BUILD)
2170 is_official_build = true;
2172 properties->SetBoolean("is_official", is_official_build);
2174 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
2175 return_value->Set("properties", properties);
2177 return_value->SetInteger("browser_pid", base::GetCurrentProcId());
2178 // Add info about all windows in a list of dictionaries, one dictionary
2180 ListValue* windows = new ListValue;
2183 for (chrome::BrowserIterator it; !it.done(); it.Next(), ++windex) {
2184 DictionaryValue* browser_item = new DictionaryValue;
2185 Browser* browser = *it;
2186 browser_item->SetInteger("index", windex);
2187 // Window properties
2188 gfx::Rect rect = browser->window()->GetRestoredBounds();
2189 browser_item->SetInteger("x", rect.x());
2190 browser_item->SetInteger("y", rect.y());
2191 browser_item->SetInteger("width", rect.width());
2192 browser_item->SetInteger("height", rect.height());
2193 browser_item->SetBoolean("fullscreen",
2194 browser->window()->IsFullscreen());
2195 ListValue* visible_page_actions = new ListValue;
2196 // Add info about all visible page actions. Skipped on panels, which do not
2197 // have a location bar.
2198 LocationBar* loc_bar = browser->window()->GetLocationBar();
2200 LocationBarTesting* loc_bar_test =
2201 loc_bar->GetLocationBarForTesting();
2202 size_t page_action_visible_count =
2203 static_cast<size_t>(loc_bar_test->PageActionVisibleCount());
2204 for (size_t i = 0; i < page_action_visible_count; ++i) {
2205 StringValue* extension_id = new StringValue(
2206 loc_bar_test->GetVisiblePageAction(i)->extension_id());
2207 visible_page_actions->Append(extension_id);
2210 browser_item->Set("visible_page_actions", visible_page_actions);
2211 browser_item->SetInteger("selected_tab",
2212 browser->tab_strip_model()->active_index());
2213 browser_item->SetBoolean("incognito",
2214 browser->profile()->IsOffTheRecord());
2215 browser_item->SetString("profile_path",
2216 browser->profile()->GetPath().BaseName().MaybeAsASCII());
2218 switch (browser->type()) {
2219 case Browser::TYPE_TABBED:
2222 case Browser::TYPE_POPUP:
2229 browser_item->SetString("type", type);
2230 // For each window, add info about all tabs in a list of dictionaries,
2231 // one dictionary item per tab.
2232 ListValue* tabs = new ListValue;
2233 for (int i = 0; i < browser->tab_strip_model()->count(); ++i) {
2234 WebContents* wc = browser->tab_strip_model()->GetWebContentsAt(i);
2235 DictionaryValue* tab = new DictionaryValue;
2236 tab->SetInteger("index", i);
2237 tab->SetString("url", wc->GetURL().spec());
2238 tab->SetInteger("renderer_pid",
2239 base::GetProcId(wc->GetRenderProcessHost()->GetHandle()));
2240 tab->Set("infobars", GetInfobarsInfo(wc));
2241 tab->SetBoolean("pinned", browser->tab_strip_model()->IsTabPinned(i));
2244 browser_item->Set("tabs", tabs);
2246 windows->Append(browser_item);
2248 return_value->Set("windows", windows);
2250 #if defined(OS_LINUX)
2251 int flags = ChildProcessHost::CHILD_ALLOW_SELF;
2253 int flags = ChildProcessHost::CHILD_NORMAL;
2256 // Add all extension processes in a list of dictionaries, one dictionary
2257 // item per extension process.
2258 ListValue* extension_views = new ListValue;
2259 ProfileManager* profile_manager = g_browser_process->profile_manager();
2260 std::vector<Profile*> profiles(profile_manager->GetLoadedProfiles());
2261 for (size_t i = 0; i < profiles.size(); ++i) {
2262 ExtensionProcessManager* process_manager =
2263 extensions::ExtensionSystem::Get(profiles[i])->process_manager();
2264 if (!process_manager)
2266 const ExtensionProcessManager::ViewSet view_set =
2267 process_manager->GetAllViews();
2268 for (ExtensionProcessManager::ViewSet::const_iterator jt =
2270 jt != view_set.end(); ++jt) {
2271 content::RenderViewHost* render_view_host = *jt;
2272 // Don't add dead extension processes.
2273 if (!render_view_host->IsRenderViewLive())
2275 // Don't add views for which we can't obtain an extension.
2276 // TODO(benwells): work out why this happens. It only happens for one
2277 // test, and only on the bots.
2278 const Extension* extension =
2279 process_manager->GetExtensionForRenderViewHost(render_view_host);
2282 DictionaryValue* item = new DictionaryValue;
2283 item->SetString("name", extension->name());
2284 item->SetString("extension_id", extension->id());
2287 base::GetProcId(render_view_host->GetProcess()->GetHandle()));
2288 DictionaryValue* view = new DictionaryValue;
2290 "render_process_id",
2291 render_view_host->GetProcess()->GetID());
2294 render_view_host->GetRoutingID());
2295 item->Set("view", view);
2297 WebContents* web_contents =
2298 WebContents::FromRenderViewHost(render_view_host);
2299 extensions::ViewType view_type = extensions::GetViewType(web_contents);
2300 switch (view_type) {
2301 case extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE:
2302 type = "EXTENSION_BACKGROUND_PAGE";
2304 case extensions::VIEW_TYPE_EXTENSION_POPUP:
2305 type = "EXTENSION_POPUP";
2307 case extensions::VIEW_TYPE_EXTENSION_INFOBAR:
2308 type = "EXTENSION_INFOBAR";
2310 case extensions::VIEW_TYPE_EXTENSION_DIALOG:
2311 type = "EXTENSION_DIALOG";
2313 case extensions::VIEW_TYPE_APP_SHELL:
2316 case extensions::VIEW_TYPE_PANEL:
2323 item->SetString("view_type", type);
2324 item->SetString("url", web_contents->GetURL().spec());
2325 item->SetBoolean("loaded", !render_view_host->IsLoading());
2326 extension_views->Append(item);
2329 return_value->Set("extension_views", extension_views);
2331 return_value->SetString("child_process_path",
2332 ChildProcessHost::GetChildPath(flags).value());
2333 // Child processes are the processes for plugins and other workers.
2334 // Add all child processes in a list of dictionaries, one dictionary item
2335 // per child process.
2336 ListValue* child_processes = new ListValue;
2337 return_value->Set("child_processes", child_processes);
2338 BrowserThread::PostTaskAndReply(
2339 BrowserThread::IO, FROM_HERE,
2340 base::Bind(&GetChildProcessHostInfo, child_processes),
2341 base::Bind(&AutomationJSONReply::SendSuccess,
2342 base::Owned(new AutomationJSONReply(this, reply_message)),
2343 base::Owned(return_value.release())));
2346 // Sample json input: { "command": "GetProcessInfo" }
2347 // Refer to GetProcessInfo() in chrome/test/pyautolib/pyauto.py for
2348 // sample json output.
2349 void TestingAutomationProvider::GetProcessInfo(
2350 DictionaryValue* args,
2351 IPC::Message* reply_message) {
2352 scoped_refptr<ProcessInfoObserver>
2353 proc_observer(new ProcessInfoObserver(this, reply_message));
2354 // TODO(jamescook): Maybe this shouldn't update UMA stats?
2355 proc_observer->StartFetch(MemoryDetails::UPDATE_USER_METRICS);
2358 // Sample json input: { "command": "GetNavigationInfo" }
2359 // Refer to GetNavigationInfo() in chrome/test/pyautolib/pyauto.py for
2360 // sample json output.
2361 void TestingAutomationProvider::GetNavigationInfo(
2363 DictionaryValue* args,
2364 IPC::Message* reply_message) {
2365 AutomationJSONReply reply(this, reply_message);
2367 WebContents* web_contents = NULL;
2368 if (!args->GetInteger("tab_index", &tab_index) ||
2370 browser->tab_strip_model()->GetWebContentsAt(tab_index))) {
2371 reply.SendError("tab_index missing or invalid.");
2374 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
2375 const NavigationController& controller = web_contents->GetController();
2376 NavigationEntry* nav_entry = controller.GetActiveEntry();
2380 DictionaryValue* ssl = new DictionaryValue;
2381 std::map<content::SecurityStyle, std::string> style_to_string;
2382 style_to_string[content::SECURITY_STYLE_UNKNOWN] = "SECURITY_STYLE_UNKNOWN";
2383 style_to_string[content::SECURITY_STYLE_UNAUTHENTICATED] =
2384 "SECURITY_STYLE_UNAUTHENTICATED";
2385 style_to_string[content::SECURITY_STYLE_AUTHENTICATION_BROKEN] =
2386 "SECURITY_STYLE_AUTHENTICATION_BROKEN";
2387 style_to_string[content::SECURITY_STYLE_AUTHENTICATED] =
2388 "SECURITY_STYLE_AUTHENTICATED";
2390 SSLStatus ssl_status = nav_entry->GetSSL();
2391 ssl->SetString("security_style",
2392 style_to_string[ssl_status.security_style]);
2393 ssl->SetBoolean("ran_insecure_content",
2394 !!(ssl_status.content_status & SSLStatus::RAN_INSECURE_CONTENT));
2395 ssl->SetBoolean("displayed_insecure_content",
2396 !!(ssl_status.content_status & SSLStatus::DISPLAYED_INSECURE_CONTENT));
2397 return_value->Set("ssl", ssl);
2400 std::map<content::PageType, std::string> pagetype_to_string;
2401 pagetype_to_string[content::PAGE_TYPE_NORMAL] = "NORMAL_PAGE";
2402 pagetype_to_string[content::PAGE_TYPE_ERROR] = "ERROR_PAGE";
2403 pagetype_to_string[content::PAGE_TYPE_INTERSTITIAL] =
2404 "INTERSTITIAL_PAGE";
2405 return_value->SetString("page_type",
2406 pagetype_to_string[nav_entry->GetPageType()]);
2408 return_value->SetString("favicon_url", nav_entry->GetFavicon().url.spec());
2409 reply.SendSuccess(return_value.get());
2412 // Sample json input: { "command": "GetHistoryInfo",
2413 // "search_text": "some text" }
2414 // Refer chrome/test/pyautolib/history_info.py for sample json output.
2415 void TestingAutomationProvider::GetHistoryInfo(Browser* browser,
2416 DictionaryValue* args,
2417 IPC::Message* reply_message) {
2418 consumer_.CancelAllRequests();
2420 string16 search_text;
2421 args->GetString("search_text", &search_text);
2424 HistoryService* hs = HistoryServiceFactory::GetForProfile(
2425 browser->profile(), Profile::EXPLICIT_ACCESS);
2426 history::QueryOptions options;
2427 // The observer owns itself. It deletes itself after it fetches history.
2428 AutomationProviderHistoryObserver* history_observer =
2429 new AutomationProviderHistoryObserver(this, reply_message);
2434 base::Bind(&AutomationProviderHistoryObserver::HistoryQueryComplete,
2435 base::Unretained(history_observer)));
2438 // Sample json input: { "command": "GetDownloadsInfo" }
2439 // Refer chrome/test/pyautolib/download_info.py for sample json output.
2440 void TestingAutomationProvider::GetDownloadsInfo(Browser* browser,
2441 DictionaryValue* args,
2442 IPC::Message* reply_message) {
2443 AutomationJSONReply reply(this, reply_message);
2444 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
2445 ListValue* list_of_downloads = new ListValue;
2447 DownloadService* download_service(
2448 DownloadServiceFactory::GetForBrowserContext(browser->profile()));
2450 if (download_service->HasCreatedDownloadManager()) {
2451 std::vector<DownloadItem*> downloads;
2452 BrowserContext::GetDownloadManager(browser->profile())->GetAllDownloads(
2455 for (std::vector<DownloadItem*>::iterator it = downloads.begin();
2456 it != downloads.end();
2457 it++) { // Fill info about each download item.
2458 list_of_downloads->Append(GetDictionaryFromDownloadItem(
2459 *it, browser->profile()->IsOffTheRecord()));
2462 return_value->Set("downloads", list_of_downloads);
2463 reply.SendSuccess(return_value.get());
2466 void TestingAutomationProvider::WaitForAllDownloadsToComplete(
2468 DictionaryValue* args,
2469 IPC::Message* reply_message) {
2470 ListValue* pre_download_ids = NULL;
2472 if (!args->GetList("pre_download_ids", &pre_download_ids)) {
2473 AutomationJSONReply(this, reply_message)
2475 base::StringPrintf("List of IDs of previous downloads required."));
2479 DownloadService* download_service =
2480 DownloadServiceFactory::GetForBrowserContext(browser->profile());
2481 if (!download_service->HasCreatedDownloadManager()) {
2482 // No download manager, so no downloads to wait for.
2483 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
2487 // This observer will delete itself.
2488 new AllDownloadsCompleteObserver(
2489 this, reply_message,
2490 BrowserContext::GetDownloadManager(browser->profile()),
2494 // See PerformActionOnDownload() in chrome/test/pyautolib/pyauto.py for sample
2495 // json input and output.
2496 void TestingAutomationProvider::PerformActionOnDownload(
2498 DictionaryValue* args,
2499 IPC::Message* reply_message) {
2503 DownloadService* download_service =
2504 DownloadServiceFactory::GetForBrowserContext(browser->profile());
2505 if (!download_service->HasCreatedDownloadManager()) {
2506 AutomationJSONReply(this, reply_message).SendError("No download manager.");
2509 if (!args->GetInteger("id", &id) || !args->GetString("action", &action)) {
2510 AutomationJSONReply(this, reply_message)
2511 .SendError("Must include int id and string action.");
2515 DownloadManager* download_manager =
2516 BrowserContext::GetDownloadManager(browser->profile());
2517 DownloadItem* selected_item = download_manager->GetDownload(id);
2518 if (!selected_item) {
2519 AutomationJSONReply(this, reply_message)
2520 .SendError(base::StringPrintf("No download with an id of %d\n", id));
2524 DownloadItem::DownloadState download_state = selected_item->GetState();
2526 // We need to be IN_PROGRESS for these actions.
2527 if ((action == "pause" || action == "resume" || action == "cancel") &&
2528 download_state != DownloadItem::IN_PROGRESS) {
2529 AutomationJSONReply(this, reply_message)
2530 .SendError(base::StringPrintf(
2531 "Action '%s' called on download that is not in progress.",
2536 if (action == "open") {
2537 selected_item->AddObserver(
2538 new AutomationProviderDownloadUpdatedObserver(
2539 this, reply_message, true, browser->profile()->IsOffTheRecord()));
2540 selected_item->OpenDownload();
2541 } else if (action == "toggle_open_files_like_this") {
2542 DownloadPrefs* prefs =
2543 DownloadPrefs::FromBrowserContext(selected_item->GetBrowserContext());
2544 base::FilePath path = selected_item->GetTargetFilePath();
2545 if (!selected_item->ShouldOpenFileBasedOnExtension())
2546 prefs->EnableAutoOpenBasedOnExtension(path);
2548 prefs->DisableAutoOpenBasedOnExtension(path);
2549 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
2550 } else if (action == "remove") {
2551 new AutomationProviderDownloadModelChangedObserver(
2552 this, reply_message, download_manager);
2553 selected_item->Remove();
2554 } else if (action == "decline_dangerous_download") {
2555 new AutomationProviderDownloadModelChangedObserver(
2556 this, reply_message, download_manager);
2557 selected_item->Remove();
2558 } else if (action == "save_dangerous_download") {
2559 selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
2560 this, reply_message, false, browser->profile()->IsOffTheRecord()));
2561 selected_item->ValidateDangerousDownload();
2562 } else if (action == "pause") {
2563 if (selected_item->IsPaused()) {
2564 // Action would be a no-op; respond right from here. No-op implies
2565 // the test is poorly written or failing, so make it an error return.
2566 AutomationJSONReply(this, reply_message)
2567 .SendError("Action 'pause' called on already paused download.");
2569 selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
2570 this, reply_message, false, browser->profile()->IsOffTheRecord()));
2571 selected_item->Pause();
2573 } else if (action == "resume") {
2574 if (!selected_item->IsPaused()) {
2575 // Action would be a no-op; respond right from here. No-op implies
2576 // the test is poorly written or failing, so make it an error return.
2577 AutomationJSONReply(this, reply_message)
2578 .SendError("Action 'resume' called on unpaused download.");
2580 selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
2581 this, reply_message, false, browser->profile()->IsOffTheRecord()));
2582 selected_item->Resume();
2584 } else if (action == "cancel") {
2585 selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
2586 this, reply_message, false, browser->profile()->IsOffTheRecord()));
2587 selected_item->Cancel(true);
2589 AutomationJSONReply(this, reply_message)
2591 base::StringPrintf("Invalid action '%s' given.", action.c_str()));
2595 void TestingAutomationProvider::SetDownloadShelfVisibleJSON(
2596 DictionaryValue* args,
2597 IPC::Message* reply_message) {
2598 AutomationJSONReply reply(this, reply_message);
2600 std::string error_msg;
2602 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
2603 reply.SendError(error_msg);
2606 if (!args->GetBoolean("is_visible", &is_visible)) {
2607 reply.SendError("'is_visible' missing or invalid.");
2611 browser->window()->GetDownloadShelf()->Show();
2613 browser->window()->GetDownloadShelf()->Close(DownloadShelf::AUTOMATIC);
2615 reply.SendSuccess(NULL);
2618 void TestingAutomationProvider::IsDownloadShelfVisibleJSON(
2619 DictionaryValue* args,
2620 IPC::Message* reply_message) {
2621 AutomationJSONReply reply(this, reply_message);
2623 std::string error_msg;
2624 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
2625 reply.SendError(error_msg);
2628 DictionaryValue dict;
2629 dict.SetBoolean("is_visible", browser->window()->IsDownloadShelfVisible());
2630 reply.SendSuccess(&dict);
2633 void TestingAutomationProvider::GetDownloadDirectoryJSON(
2634 DictionaryValue* args,
2635 IPC::Message* reply_message) {
2636 AutomationJSONReply reply(this, reply_message);
2637 WebContents* web_contents;
2639 if (!GetTabFromJSONArgs(args, &web_contents, &error)) {
2640 reply.SendError(error);
2643 DownloadManager* dlm =
2644 BrowserContext::GetDownloadManager(
2645 web_contents->GetController().GetBrowserContext());
2646 DictionaryValue dict;
2647 dict.SetString("path",
2648 DownloadPrefs::FromDownloadManager(dlm)->DownloadPath().value());
2649 reply.SendSuccess(&dict);
2652 // Sample JSON input { "command": "LoadSearchEngineInfo" }
2653 void TestingAutomationProvider::LoadSearchEngineInfo(
2655 DictionaryValue* args,
2656 IPC::Message* reply_message) {
2657 TemplateURLService* url_model =
2658 TemplateURLServiceFactory::GetForProfile(browser->profile());
2659 if (url_model->loaded()) {
2660 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
2663 url_model->AddObserver(new AutomationProviderSearchEngineObserver(
2664 this, browser->profile(), reply_message));
2668 // Sample JSON input { "command": "GetSearchEngineInfo" }
2669 // Refer to pyauto.py for sample output.
2670 void TestingAutomationProvider::GetSearchEngineInfo(
2672 DictionaryValue* args,
2673 IPC::Message* reply_message) {
2674 TemplateURLService* url_model =
2675 TemplateURLServiceFactory::GetForProfile(browser->profile());
2676 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
2677 ListValue* search_engines = new ListValue;
2678 TemplateURLService::TemplateURLVector template_urls =
2679 url_model->GetTemplateURLs();
2680 for (TemplateURLService::TemplateURLVector::const_iterator it =
2681 template_urls.begin(); it != template_urls.end(); ++it) {
2682 DictionaryValue* search_engine = new DictionaryValue;
2683 search_engine->SetString("short_name", UTF16ToUTF8((*it)->short_name()));
2684 search_engine->SetString("keyword", UTF16ToUTF8((*it)->keyword()));
2685 search_engine->SetBoolean("in_default_list", (*it)->ShowInDefaultList());
2686 search_engine->SetBoolean("is_default",
2687 (*it) == url_model->GetDefaultSearchProvider());
2688 search_engine->SetBoolean("is_valid", (*it)->url_ref().IsValid());
2689 search_engine->SetBoolean("supports_replacement",
2690 (*it)->url_ref().SupportsReplacement());
2691 search_engine->SetString("url", (*it)->url());
2692 search_engine->SetString("host", (*it)->url_ref().GetHost());
2693 search_engine->SetString("path", (*it)->url_ref().GetPath());
2694 search_engine->SetString("display_url",
2695 UTF16ToUTF8((*it)->url_ref().DisplayURL()));
2696 search_engines->Append(search_engine);
2698 return_value->Set("search_engines", search_engines);
2699 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
2702 // Refer to pyauto.py for sample JSON input.
2703 void TestingAutomationProvider::AddOrEditSearchEngine(
2705 DictionaryValue* args,
2706 IPC::Message* reply_message) {
2707 TemplateURLService* url_model =
2708 TemplateURLServiceFactory::GetForProfile(browser->profile());
2710 string16 new_keyword;
2711 std::string new_url;
2712 std::string keyword;
2713 if (!args->GetString("new_title", &new_title) ||
2714 !args->GetString("new_keyword", &new_keyword) ||
2715 !args->GetString("new_url", &new_url)) {
2716 AutomationJSONReply(this, reply_message).SendError(
2717 "One or more inputs invalid");
2720 std::string new_ref_url = TemplateURLRef::DisplayURLToURLRef(
2721 UTF8ToUTF16(new_url));
2722 scoped_ptr<KeywordEditorController> controller(
2723 new KeywordEditorController(browser->profile()));
2724 if (args->GetString("keyword", &keyword)) {
2725 TemplateURL* template_url =
2726 url_model->GetTemplateURLForKeyword(UTF8ToUTF16(keyword));
2727 if (template_url == NULL) {
2728 AutomationJSONReply(this, reply_message).SendError(
2729 "No match for keyword: " + keyword);
2732 url_model->AddObserver(new AutomationProviderSearchEngineObserver(
2733 this, browser->profile(), reply_message));
2734 controller->ModifyTemplateURL(template_url, new_title, new_keyword,
2737 url_model->AddObserver(new AutomationProviderSearchEngineObserver(
2738 this, browser->profile(), reply_message));
2739 controller->AddTemplateURL(new_title, new_keyword, new_ref_url);
2743 // Sample json input: { "command": "PerformActionOnSearchEngine",
2744 // "keyword": keyword, "action": action }
2745 void TestingAutomationProvider::PerformActionOnSearchEngine(
2747 DictionaryValue* args,
2748 IPC::Message* reply_message) {
2749 TemplateURLService* url_model =
2750 TemplateURLServiceFactory::GetForProfile(browser->profile());
2751 std::string keyword;
2753 if (!args->GetString("keyword", &keyword) ||
2754 !args->GetString("action", &action)) {
2755 AutomationJSONReply(this, reply_message).SendError(
2756 "One or more inputs invalid");
2759 TemplateURL* template_url =
2760 url_model->GetTemplateURLForKeyword(UTF8ToUTF16(keyword));
2761 if (template_url == NULL) {
2762 AutomationJSONReply(this, reply_message).SendError(
2763 "No match for keyword: " + keyword);
2766 if (action == "delete") {
2767 url_model->AddObserver(new AutomationProviderSearchEngineObserver(
2768 this, browser->profile(), reply_message));
2769 url_model->Remove(template_url);
2770 } else if (action == "default") {
2771 url_model->AddObserver(new AutomationProviderSearchEngineObserver(
2772 this, browser->profile(), reply_message));
2773 url_model->SetDefaultSearchProvider(template_url);
2775 AutomationJSONReply(this, reply_message).SendError(
2776 "Invalid action: " + action);
2780 // Sample json input: { "command": "GetLocalStatePrefsInfo" }
2781 // Refer chrome/test/pyautolib/prefs_info.py for sample json output.
2782 void TestingAutomationProvider::GetLocalStatePrefsInfo(
2783 DictionaryValue* args,
2784 IPC::Message* reply_message) {
2785 scoped_ptr<DictionaryValue> items(
2786 g_browser_process->local_state()->GetPreferenceValues());
2787 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
2788 return_value->Set("prefs", items.release()); // return_value owns items.
2789 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
2792 // Sample json input: { "command": "SetLocalStatePrefs", "path": path,
2794 void TestingAutomationProvider::SetLocalStatePrefs(
2795 DictionaryValue* args,
2796 IPC::Message* reply_message) {
2799 AutomationJSONReply reply(this, reply_message);
2800 if (args->GetString("path", &path) && args->Get("value", &val)) {
2801 PrefService* pref_service = g_browser_process->local_state();
2802 const PrefService::Preference* pref =
2803 pref_service->FindPreference(path.c_str());
2804 if (!pref) { // Not a registered pref.
2805 reply.SendError("pref not registered.");
2807 } else if (pref->IsManaged()) { // Do not attempt to change a managed pref.
2808 reply.SendError("pref is managed. cannot be changed.");
2810 } else { // Set the pref.
2811 pref_service->Set(path.c_str(), *val);
2814 reply.SendError("no pref path or value given.");
2818 reply.SendSuccess(NULL);
2821 // Sample json input: { "command": "GetPrefsInfo", "windex": 0 }
2822 // Refer chrome/test/pyautolib/prefs_info.py for sample json output.
2823 void TestingAutomationProvider::GetPrefsInfo(DictionaryValue* args,
2824 IPC::Message* reply_message) {
2825 AutomationJSONReply reply(this, reply_message);
2827 std::string error_msg;
2828 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
2829 reply.SendError(error_msg);
2832 scoped_ptr<DictionaryValue> items(
2833 browser->profile()->GetPrefs()->GetPreferenceValues());
2835 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
2836 return_value->Set("prefs", items.release()); // return_value owns items.
2837 reply.SendSuccess(return_value.get());
2840 // Sample json input:
2841 // { "command": "SetPrefs",
2845 void TestingAutomationProvider::SetPrefs(DictionaryValue* args,
2846 IPC::Message* reply_message) {
2847 AutomationJSONReply reply(this, reply_message);
2849 std::string error_msg;
2850 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
2851 reply.SendError(error_msg);
2856 if (args->GetString("path", &path) && args->Get("value", &val)) {
2857 PrefService* pref_service = browser->profile()->GetPrefs();
2858 const PrefService::Preference* pref =
2859 pref_service->FindPreference(path.c_str());
2860 if (!pref) { // Not a registered pref.
2861 reply.SendError("pref not registered.");
2863 } else if (pref->IsManaged()) { // Do not attempt to change a managed pref.
2864 reply.SendError("pref is managed. cannot be changed.");
2866 } else { // Set the pref.
2867 pref_service->Set(path.c_str(), *val);
2870 reply.SendError("no pref path or value given.");
2874 reply.SendSuccess(NULL);
2877 // Sample json input: { "command": "GetOmniboxInfo" }
2878 // Refer chrome/test/pyautolib/omnibox_info.py for sample json output.
2879 void TestingAutomationProvider::GetOmniboxInfo(Browser* browser,
2880 DictionaryValue* args,
2881 IPC::Message* reply_message) {
2882 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
2883 AutomationJSONReply reply(this, reply_message);
2885 LocationBar* loc_bar = browser->window()->GetLocationBar();
2887 reply.SendError("The specified browser does not have a location bar.");
2890 const OmniboxView* omnibox_view = loc_bar->GetLocationEntry();
2891 const OmniboxEditModel* model = omnibox_view->model();
2894 ListValue* matches = new ListValue;
2895 const AutocompleteResult& result = model->result();
2896 for (AutocompleteResult::const_iterator i(result.begin()); i != result.end();
2898 const AutocompleteMatch& match = *i;
2899 DictionaryValue* item = new DictionaryValue; // owned by return_value
2900 item->SetString("type", AutocompleteMatchType::ToString(match.type));
2901 item->SetBoolean("starred", match.starred);
2902 item->SetString("destination_url", match.destination_url.spec());
2903 item->SetString("contents", match.contents);
2904 item->SetString("description", match.description);
2905 matches->Append(item);
2907 return_value->Set("matches", matches);
2909 // Fill up other properties.
2910 DictionaryValue* properties = new DictionaryValue; // owned by return_value
2911 properties->SetBoolean("has_focus", model->has_focus());
2912 properties->SetBoolean("query_in_progress",
2913 !model->autocomplete_controller()->done());
2914 properties->SetString("keyword", model->keyword());
2915 properties->SetString("text", omnibox_view->GetText());
2916 return_value->Set("properties", properties);
2918 reply.SendSuccess(return_value.get());
2921 // Sample json input: { "command": "SetOmniboxText",
2923 void TestingAutomationProvider::SetOmniboxText(Browser* browser,
2924 DictionaryValue* args,
2925 IPC::Message* reply_message) {
2927 AutomationJSONReply reply(this, reply_message);
2928 if (!args->GetString("text", &text)) {
2929 reply.SendError("text missing");
2932 chrome::FocusLocationBar(browser);
2933 LocationBar* loc_bar = browser->window()->GetLocationBar();
2935 reply.SendError("The specified browser does not have a location bar.");
2938 OmniboxView* omnibox_view = loc_bar->GetLocationEntry();
2939 omnibox_view->model()->OnSetFocus(false);
2940 omnibox_view->SetUserText(text);
2941 reply.SendSuccess(NULL);
2944 // Sample json input: { "command": "OmniboxMovePopupSelection",
2946 // Negative count implies up, positive implies down. Count values will be
2947 // capped by the size of the popup list.
2948 void TestingAutomationProvider::OmniboxMovePopupSelection(
2950 DictionaryValue* args,
2951 IPC::Message* reply_message) {
2953 AutomationJSONReply reply(this, reply_message);
2954 if (!args->GetInteger("count", &count)) {
2955 reply.SendError("count missing");
2958 LocationBar* loc_bar = browser->window()->GetLocationBar();
2960 reply.SendError("The specified browser does not have a location bar.");
2963 loc_bar->GetLocationEntry()->model()->OnUpOrDownKeyPressed(count);
2964 reply.SendSuccess(NULL);
2967 // Sample json input: { "command": "OmniboxAcceptInput" }
2968 void TestingAutomationProvider::OmniboxAcceptInput(
2970 DictionaryValue* args,
2971 IPC::Message* reply_message) {
2972 NavigationController& controller =
2973 browser->tab_strip_model()->GetActiveWebContents()->GetController();
2974 LocationBar* loc_bar = browser->window()->GetLocationBar();
2976 AutomationJSONReply(this, reply_message).SendError(
2977 "The specified browser does not have a location bar.");
2980 new OmniboxAcceptNotificationObserver(&controller, this, reply_message);
2981 loc_bar->AcceptInput();
2984 // Sample json input: { "command": "GetInitialLoadTimes" }
2985 // Refer to InitialLoadObserver::GetTimingInformation() for sample output.
2986 void TestingAutomationProvider::GetInitialLoadTimes(
2989 IPC::Message* reply_message) {
2990 scoped_ptr<DictionaryValue> return_value(
2991 initial_load_observer_->GetTimingInformation());
2993 std::string json_return;
2994 base::JSONWriter::Write(return_value.get(), &json_return);
2995 AutomationMsg_SendJSONRequest::WriteReplyParams(
2996 reply_message, json_return, true);
2997 Send(reply_message);
3000 // Sample json input: { "command": "GetPluginsInfo" }
3001 // Refer chrome/test/pyautolib/plugins_info.py for sample json output.
3002 void TestingAutomationProvider::GetPluginsInfo(
3004 DictionaryValue* args,
3005 IPC::Message* reply_message) {
3006 PluginService::GetInstance()->GetPlugins(
3007 base::Bind(&TestingAutomationProvider::GetPluginsInfoCallback,
3008 this, browser, args, reply_message));
3011 void TestingAutomationProvider::GetPluginsInfoCallback(
3013 DictionaryValue* args,
3014 IPC::Message* reply_message,
3015 const std::vector<content::WebPluginInfo>& plugins) {
3016 PluginPrefs* plugin_prefs =
3017 PluginPrefs::GetForProfile(browser->profile()).get();
3018 ListValue* items = new ListValue;
3019 for (std::vector<content::WebPluginInfo>::const_iterator it =
3021 it != plugins.end();
3023 DictionaryValue* item = new DictionaryValue;
3024 item->SetString("name", it->name);
3025 item->SetString("path", it->path.value());
3026 item->SetString("version", it->version);
3027 item->SetString("desc", it->desc);
3028 item->SetBoolean("enabled", plugin_prefs->IsPluginEnabled(*it));
3029 // Add info about mime types.
3030 ListValue* mime_types = new ListValue();
3031 for (std::vector<content::WebPluginMimeType>::const_iterator type_it =
3032 it->mime_types.begin();
3033 type_it != it->mime_types.end();
3035 DictionaryValue* mime_type = new DictionaryValue();
3036 mime_type->SetString("mimeType", type_it->mime_type);
3037 mime_type->SetString("description", type_it->description);
3039 ListValue* file_extensions = new ListValue();
3040 for (std::vector<std::string>::const_iterator ext_it =
3041 type_it->file_extensions.begin();
3042 ext_it != type_it->file_extensions.end();
3044 file_extensions->Append(new StringValue(*ext_it));
3046 mime_type->Set("fileExtensions", file_extensions);
3048 mime_types->Append(mime_type);
3050 item->Set("mimeTypes", mime_types);
3051 items->Append(item);
3053 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
3054 return_value->Set("plugins", items); // return_value owns items.
3056 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
3059 // Sample json input:
3060 // { "command": "EnablePlugin",
3061 // "path": "/Library/Internet Plug-Ins/Flash Player.plugin" }
3062 void TestingAutomationProvider::EnablePlugin(Browser* browser,
3063 DictionaryValue* args,
3064 IPC::Message* reply_message) {
3065 base::FilePath::StringType path;
3066 if (!args->GetString("path", &path)) {
3067 AutomationJSONReply(this, reply_message).SendError("path not specified.");
3070 PluginPrefs* plugin_prefs =
3071 PluginPrefs::GetForProfile(browser->profile()).get();
3072 plugin_prefs->EnablePlugin(
3074 base::FilePath(path),
3075 base::Bind(&DidEnablePlugin,
3079 "Could not enable plugin for path %s."));
3082 // Sample json input:
3083 // { "command": "DisablePlugin",
3084 // "path": "/Library/Internet Plug-Ins/Flash Player.plugin" }
3085 void TestingAutomationProvider::DisablePlugin(Browser* browser,
3086 DictionaryValue* args,
3087 IPC::Message* reply_message) {
3088 base::FilePath::StringType path;
3089 if (!args->GetString("path", &path)) {
3090 AutomationJSONReply(this, reply_message).SendError("path not specified.");
3093 PluginPrefs* plugin_prefs =
3094 PluginPrefs::GetForProfile(browser->profile()).get();
3095 plugin_prefs->EnablePlugin(
3097 base::FilePath(path),
3098 base::Bind(&DidEnablePlugin,
3102 "Could not disable plugin for path %s."));
3105 // Sample json input:
3106 // { "command": "SaveTabContents",
3108 // "filename": <a full pathname> }
3109 // Sample json output:
3111 void TestingAutomationProvider::SaveTabContents(
3113 DictionaryValue* args,
3114 IPC::Message* reply_message) {
3116 base::FilePath::StringType filename;
3117 base::FilePath::StringType parent_directory;
3118 WebContents* web_contents = NULL;
3120 if (!args->GetInteger("tab_index", &tab_index) ||
3121 !args->GetString("filename", &filename)) {
3122 AutomationJSONReply(this, reply_message)
3123 .SendError("tab_index or filename param missing");
3126 web_contents = browser->tab_strip_model()->GetWebContentsAt(tab_index);
3127 if (!web_contents) {
3128 AutomationJSONReply(this, reply_message).SendError("no tab at tab_index");
3132 // We're doing a SAVE_AS_ONLY_HTML so the the directory path isn't
3133 // used. Nevertheless, SavePackage requires it be valid. Sigh.
3134 parent_directory = base::FilePath(filename).DirName().value();
3135 if (!web_contents->SavePage(
3136 base::FilePath(filename),
3137 base::FilePath(parent_directory),
3138 content::SAVE_PAGE_TYPE_AS_ONLY_HTML)) {
3139 AutomationJSONReply(this, reply_message).SendError(
3140 "Could not initiate SavePage");
3143 // The observer will delete itself when done.
3144 new SavePackageNotificationObserver(
3145 BrowserContext::GetDownloadManager(browser->profile()),
3146 this, reply_message);
3151 // Translates a dictionary password to a PasswordForm struct.
3152 autofill::PasswordForm GetPasswordFormFromDict(
3153 const DictionaryValue& password_dict) {
3155 // If the time is specified, change time to the specified time.
3156 base::Time time = base::Time::Now();
3159 if (password_dict.GetInteger("time", &it))
3160 time = base::Time::FromTimeT(it);
3161 else if (password_dict.GetDouble("time", &dt))
3162 time = base::Time::FromDoubleT(dt);
3164 std::string signon_realm;
3165 string16 username_value;
3166 string16 password_value;
3167 string16 origin_url_text;
3168 string16 username_element;
3169 string16 password_element;
3170 string16 submit_element;
3171 string16 action_target_text;
3173 string16 old_password_element;
3174 string16 old_password_value;
3176 // We don't care if any of these fail - they are either optional or checked
3177 // before this function is called.
3178 password_dict.GetString("signon_realm", &signon_realm);
3179 password_dict.GetString("username_value", &username_value);
3180 password_dict.GetString("password_value", &password_value);
3181 password_dict.GetString("origin_url", &origin_url_text);
3182 password_dict.GetString("username_element", &username_element);
3183 password_dict.GetString("password_element", &password_element);
3184 password_dict.GetString("submit_element", &submit_element);
3185 password_dict.GetString("action_target", &action_target_text);
3186 if (!password_dict.GetBoolean("blacklist", &blacklist))
3189 GURL origin_gurl(origin_url_text);
3190 GURL action_target(action_target_text);
3192 autofill::PasswordForm password_form;
3193 password_form.signon_realm = signon_realm;
3194 password_form.username_value = username_value;
3195 password_form.password_value = password_value;
3196 password_form.origin = origin_gurl;
3197 password_form.username_element = username_element;
3198 password_form.password_element = password_element;
3199 password_form.submit_element = submit_element;
3200 password_form.action = action_target;
3201 password_form.blacklisted_by_user = blacklist;
3202 password_form.date_created = time;
3204 return password_form;
3209 // See AddSavedPassword() in chrome/test/functional/pyauto.py for sample json
3211 // Sample json output: { "password_added": true }
3212 void TestingAutomationProvider::AddSavedPassword(
3214 DictionaryValue* args,
3215 IPC::Message* reply_message) {
3216 DictionaryValue* password_dict = NULL;
3217 if (!args->GetDictionary("password", &password_dict)) {
3218 AutomationJSONReply(this, reply_message).SendError(
3219 "Must specify a password dictionary.");
3223 // The "signon realm" is effectively the primary key and must be included.
3224 // Check here before calling GetPasswordFormFromDict.
3225 if (!password_dict->HasKey("signon_realm")) {
3226 AutomationJSONReply(this, reply_message).SendError(
3227 "Password must include a value for 'signon_realm.'");
3231 autofill::PasswordForm new_password =
3232 GetPasswordFormFromDict(*password_dict);
3234 // Use IMPLICIT_ACCESS since new passwords aren't added in incognito mode.
3235 PasswordStore* password_store = PasswordStoreFactory::GetForProfile(
3236 browser->profile(), Profile::IMPLICIT_ACCESS).get();
3238 // The password store does not exist for an incognito window.
3239 if (password_store == NULL) {
3240 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
3241 return_value->SetBoolean("password_added", false);
3242 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
3246 // This observer will delete itself.
3247 PasswordStoreLoginsChangedObserver* observer =
3248 new PasswordStoreLoginsChangedObserver(this, reply_message,
3249 PasswordStoreChange::ADD,
3252 password_store->AddLogin(new_password);
3255 // See RemoveSavedPassword() in chrome/test/functional/pyauto.py for sample
3257 // Sample json output: {}
3258 void TestingAutomationProvider::RemoveSavedPassword(
3260 DictionaryValue* args,
3261 IPC::Message* reply_message) {
3262 DictionaryValue* password_dict = NULL;
3264 if (!args->GetDictionary("password", &password_dict)) {
3265 AutomationJSONReply(this, reply_message).SendError(
3266 "Must specify a password dictionary.");
3270 // The "signon realm" is effectively the primary key and must be included.
3271 // Check here before calling GetPasswordFormFromDict.
3272 if (!password_dict->HasKey("signon_realm")) {
3273 AutomationJSONReply(this, reply_message).SendError(
3274 "Password must include a value for 'signon_realm.'");
3277 autofill::PasswordForm to_remove =
3278 GetPasswordFormFromDict(*password_dict);
3280 // Use EXPLICIT_ACCESS since passwords can be removed in incognito mode.
3281 PasswordStore* password_store = PasswordStoreFactory::GetForProfile(
3282 browser->profile(), Profile::EXPLICIT_ACCESS).get();
3283 if (password_store == NULL) {
3284 AutomationJSONReply(this, reply_message).SendError(
3285 "Unable to get password store.");
3289 // This observer will delete itself.
3290 PasswordStoreLoginsChangedObserver* observer =
3291 new PasswordStoreLoginsChangedObserver(
3292 this, reply_message, PasswordStoreChange::REMOVE, std::string());
3295 password_store->RemoveLogin(to_remove);
3298 // Sample json input: { "command": "GetSavedPasswords" }
3299 // Refer to GetSavedPasswords() in chrome/test/pyautolib/pyauto.py for sample
3301 void TestingAutomationProvider::GetSavedPasswords(
3303 DictionaryValue* args,
3304 IPC::Message* reply_message) {
3305 // Use EXPLICIT_ACCESS since saved passwords can be retrieved in
3307 PasswordStore* password_store = PasswordStoreFactory::GetForProfile(
3308 browser->profile(), Profile::EXPLICIT_ACCESS).get();
3310 if (password_store == NULL) {
3311 AutomationJSONReply reply(this, reply_message);
3312 reply.SendError("Unable to get password store.");
3315 password_store->GetAutofillableLogins(
3316 new AutomationProviderGetPasswordsObserver(this, reply_message));
3317 // Observer deletes itself after sending the result.
3322 // Get the WebContents from a dictionary of arguments.
3323 WebContents* GetWebContentsFromDict(const Browser* browser,
3324 const DictionaryValue* args,
3325 std::string* error_message) {
3327 if (!args->GetInteger("tab_index", &tab_index)) {
3328 *error_message = "Must include tab_index.";
3332 WebContents* web_contents =
3333 browser->tab_strip_model()->GetWebContentsAt(tab_index);
3334 if (!web_contents) {
3335 *error_message = base::StringPrintf("No tab at index %d.", tab_index);
3338 return web_contents;
3343 void TestingAutomationProvider::FindInPage(
3345 DictionaryValue* args,
3346 IPC::Message* reply_message) {
3347 std::string error_message;
3348 WebContents* web_contents =
3349 GetWebContentsFromDict(browser, args, &error_message);
3350 if (!web_contents) {
3351 AutomationJSONReply(this, reply_message).SendError(error_message);
3354 string16 search_string;
3358 if (!args->GetString("search_string", &search_string)) {
3359 AutomationJSONReply(this, reply_message).
3360 SendError("Must include search_string string.");
3363 if (!args->GetBoolean("forward", &forward)) {
3364 AutomationJSONReply(this, reply_message).
3365 SendError("Must include forward boolean.");
3368 if (!args->GetBoolean("match_case", &match_case)) {
3369 AutomationJSONReply(this, reply_message).
3370 SendError("Must include match_case boolean.");
3373 if (!args->GetBoolean("find_next", &find_next)) {
3374 AutomationJSONReply(this, reply_message).
3375 SendError("Must include find_next boolean.");
3378 SendFindRequest(web_contents,
3387 void TestingAutomationProvider::OpenFindInPage(
3388 DictionaryValue* args,
3389 IPC::Message* reply_message) {
3390 AutomationJSONReply reply(this, reply_message);
3392 std::string error_msg;
3393 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
3394 reply.SendError(error_msg);
3397 chrome::FindInPage(browser, false, false);
3398 reply.SendSuccess(NULL);
3401 void TestingAutomationProvider::IsFindInPageVisible(
3402 DictionaryValue* args,
3403 IPC::Message* reply_message) {
3404 AutomationJSONReply reply(this, reply_message);
3407 std::string error_msg;
3408 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
3409 reply.SendError(error_msg);
3412 FindBarTesting* find_bar =
3413 browser->GetFindBarController()->find_bar()->GetFindBarTesting();
3414 find_bar->GetFindBarWindowInfo(NULL, &visible);
3415 DictionaryValue dict;
3416 dict.SetBoolean("is_visible", visible);
3417 reply.SendSuccess(&dict);
3420 void TestingAutomationProvider::InstallExtension(
3421 DictionaryValue* args, IPC::Message* reply_message) {
3422 base::FilePath::StringType path_string;
3424 bool from_webstore = false;
3426 content::WebContents* tab;
3427 std::string error_msg;
3428 if (!GetBrowserAndTabFromJSONArgs(args, &browser, &tab, &error_msg)) {
3429 AutomationJSONReply(this, reply_message).SendError(error_msg);
3432 if (!args->GetString("path", &path_string)) {
3433 AutomationJSONReply(this, reply_message).SendError(
3434 "Missing or invalid 'path'");
3437 if (!args->GetBoolean("with_ui", &with_ui)) {
3438 AutomationJSONReply(this, reply_message).SendError(
3439 "Missing or invalid 'with_ui'");
3442 args->GetBoolean("from_webstore", &from_webstore);
3444 ExtensionService* service = extensions::ExtensionSystem::Get(
3445 browser->profile())->extension_service();
3446 ExtensionProcessManager* manager =
3447 extensions::ExtensionSystem::Get(browser->profile())->process_manager();
3448 if (service && manager) {
3449 // The observer will delete itself when done.
3450 new ExtensionReadyNotificationObserver(
3456 base::FilePath extension_path(path_string);
3457 // If the given path has a 'crx' extension, assume it is a packed extension
3458 // and install it. Otherwise load it as an unpacked extension.
3459 if (extension_path.MatchesExtension(FILE_PATH_LITERAL(".crx"))) {
3460 scoped_ptr<ExtensionInstallPrompt> client(
3461 with_ui ? new ExtensionInstallPrompt(tab) : NULL);
3462 scoped_refptr<extensions::CrxInstaller> installer(
3463 extensions::CrxInstaller::Create(service, client.Pass()));
3465 installer->set_allow_silent_install(true);
3466 installer->set_install_cause(extension_misc::INSTALL_CAUSE_AUTOMATION);
3468 installer->set_creation_flags(Extension::FROM_WEBSTORE);
3469 installer->InstallCrx(extension_path);
3471 scoped_refptr<extensions::UnpackedInstaller> installer(
3472 extensions::UnpackedInstaller::Create(service));
3473 installer->set_prompt_for_plugins(with_ui);
3474 installer->Load(extension_path);
3477 AutomationJSONReply(this, reply_message).SendError(
3478 "Extensions service/process manager is not available");
3484 ListValue* GetHostPermissions(const Extension* ext, bool effective_perm) {
3485 extensions::URLPatternSet pattern_set;
3486 if (effective_perm) {
3488 extensions::PermissionsData::GetEffectiveHostPermissions(ext);
3490 pattern_set = ext->GetActivePermissions()->explicit_hosts();
3493 ListValue* permissions = new ListValue;
3494 for (extensions::URLPatternSet::const_iterator perm = pattern_set.begin();
3495 perm != pattern_set.end(); ++perm) {
3496 permissions->Append(new StringValue(perm->GetAsString()));
3502 ListValue* GetAPIPermissions(const Extension* ext) {
3503 ListValue* permissions = new ListValue;
3504 std::set<std::string> perm_list =
3505 ext->GetActivePermissions()->GetAPIsAsStrings();
3506 for (std::set<std::string>::const_iterator perm = perm_list.begin();
3507 perm != perm_list.end(); ++perm) {
3508 permissions->Append(new StringValue(perm->c_str()));
3515 // Sample json input: { "command": "GetExtensionsInfo" }
3516 // See GetExtensionsInfo() in chrome/test/pyautolib/pyauto.py for sample json
3518 void TestingAutomationProvider::GetExtensionsInfo(DictionaryValue* args,
3519 IPC::Message* reply_message) {
3520 AutomationJSONReply reply(this, reply_message);
3522 std::string error_msg;
3523 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
3524 reply.SendError(error_msg);
3527 ExtensionService* service = extensions::ExtensionSystem::Get(
3528 browser->profile())->extension_service();
3530 reply.SendError("No extensions service.");
3533 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
3534 ListValue* extensions_values = new ListValue;
3535 const ExtensionSet* extensions = service->extensions();
3536 const ExtensionSet* disabled_extensions = service->disabled_extensions();
3538 all.insert(all.end(),
3539 extensions->begin(),
3541 all.insert(all.end(),
3542 disabled_extensions->begin(),
3543 disabled_extensions->end());
3544 ExtensionActionManager* extension_action_manager =
3545 ExtensionActionManager::Get(browser->profile());
3546 for (ExtensionList::const_iterator it = all.begin();
3547 it != all.end(); ++it) {
3548 const Extension* extension = it->get();
3549 std::string id = extension->id();
3550 DictionaryValue* extension_value = new DictionaryValue;
3551 extension_value->SetString("id", id);
3552 extension_value->SetString("version", extension->VersionString());
3553 extension_value->SetString("name", extension->name());
3554 extension_value->SetString("public_key", extension->public_key());
3555 extension_value->SetString("description", extension->description());
3556 extension_value->SetString(
3558 extensions::BackgroundInfo::GetBackgroundURL(extension).spec());
3559 extension_value->SetString("options_url",
3560 extensions::ManifestURL::GetOptionsPage(extension).spec());
3561 extension_value->Set("host_permissions",
3562 GetHostPermissions(extension, false));
3563 extension_value->Set("effective_host_permissions",
3564 GetHostPermissions(extension, true));
3565 extension_value->Set("api_permissions", GetAPIPermissions(extension));
3566 Manifest::Location location = extension->location();
3567 extension_value->SetBoolean("is_component",
3568 location == Manifest::COMPONENT);
3569 extension_value->SetBoolean("is_internal",
3570 location == Manifest::INTERNAL);
3571 extension_value->SetBoolean("is_user_installed",
3572 location == Manifest::INTERNAL ||
3573 Manifest::IsUnpackedLocation(location));
3574 extension_value->SetBoolean("is_enabled", service->IsExtensionEnabled(id));
3575 extension_value->SetBoolean("allowed_in_incognito",
3576 extension_util::IsIncognitoEnabled(id, service));
3577 extension_value->SetBoolean(
3579 extension_action_manager->GetPageAction(*extension) != NULL);
3580 extensions_values->Append(extension_value);
3582 return_value->Set("extensions", extensions_values);
3583 reply.SendSuccess(return_value.get());
3586 // See UninstallExtensionById() in chrome/test/pyautolib/pyauto.py for sample
3588 // Sample json output: {}
3589 void TestingAutomationProvider::UninstallExtensionById(
3590 DictionaryValue* args,
3591 IPC::Message* reply_message) {
3592 const Extension* extension;
3595 if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
3596 AutomationJSONReply(this, reply_message).SendError(error);
3599 if (!GetExtensionFromJSONArgs(
3600 args, "id", browser->profile(), &extension, &error)) {
3601 AutomationJSONReply(this, reply_message).SendError(error);
3604 ExtensionService* service = extensions::ExtensionSystem::Get(
3605 browser->profile())->extension_service();
3607 AutomationJSONReply(this, reply_message).SendError(
3608 "No extensions service.");
3612 // Wait for a notification indicating that the extension with the given ID
3613 // has been uninstalled. This observer will delete itself.
3614 new ExtensionUninstallObserver(this, reply_message, extension->id());
3615 service->UninstallExtension(extension->id(), false, NULL);
3618 // See SetExtensionStateById() in chrome/test/pyautolib/pyauto.py
3619 // for sample json input.
3620 void TestingAutomationProvider::SetExtensionStateById(
3621 DictionaryValue* args,
3622 IPC::Message* reply_message) {
3623 const Extension* extension;
3626 if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
3627 AutomationJSONReply(this, reply_message).SendError(error);
3630 if (!GetExtensionFromJSONArgs(
3631 args, "id", browser->profile(), &extension, &error)) {
3632 AutomationJSONReply(this, reply_message).SendError(error);
3637 if (!args->GetBoolean("enable", &enable)) {
3638 AutomationJSONReply(this, reply_message)
3639 .SendError("Missing or invalid key: enable");
3643 bool allow_in_incognito;
3644 if (!args->GetBoolean("allow_in_incognito", &allow_in_incognito)) {
3645 AutomationJSONReply(this, reply_message)
3646 .SendError("Missing or invalid key: allow_in_incognito");
3650 if (allow_in_incognito && !enable) {
3651 AutomationJSONReply(this, reply_message)
3652 .SendError("Invalid state: Disabled extension "
3653 "cannot be allowed in incognito mode.");
3657 ExtensionService* service = extensions::ExtensionSystem::Get(
3658 browser->profile())->extension_service();
3659 ExtensionProcessManager* manager =
3660 extensions::ExtensionSystem::Get(browser->profile())->process_manager();
3662 AutomationJSONReply(this, reply_message)
3663 .SendError("No extensions service or process manager.");
3668 if (!service->IsExtensionEnabled(extension->id())) {
3669 new ExtensionReadyNotificationObserver(
3674 service->EnableExtension(extension->id());
3676 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
3679 service->DisableExtension(extension->id(),
3680 Extension::DISABLE_USER_ACTION);
3681 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
3684 extension_util::SetIsIncognitoEnabled(
3685 extension->id(), service, allow_in_incognito);
3688 // See TriggerPageActionById() in chrome/test/pyautolib/pyauto.py
3689 // for sample json input.
3690 void TestingAutomationProvider::TriggerPageActionById(
3691 DictionaryValue* args,
3692 IPC::Message* reply_message) {
3696 if (!GetBrowserAndTabFromJSONArgs(args, &browser, &tab, &error)) {
3697 AutomationJSONReply(this, reply_message).SendError(error);
3700 const Extension* extension;
3701 if (!GetEnabledExtensionFromJSONArgs(
3702 args, "id", browser->profile(), &extension, &error)) {
3703 AutomationJSONReply(this, reply_message).SendError(error);
3706 ExtensionAction* page_action =
3707 ExtensionActionManager::Get(browser->profile())->
3708 GetPageAction(*extension);
3710 AutomationJSONReply(this, reply_message).SendError(
3711 "Extension doesn't have any page action.");
3714 EnsureTabSelected(browser, tab);
3716 bool pressed = false;
3717 LocationBarTesting* loc_bar =
3718 browser->window()->GetLocationBar()->GetLocationBarForTesting();
3719 size_t page_action_visible_count =
3720 static_cast<size_t>(loc_bar->PageActionVisibleCount());
3721 for (size_t i = 0; i < page_action_visible_count; ++i) {
3722 if (loc_bar->GetVisiblePageAction(i) == page_action) {
3723 loc_bar->TestPageActionPressed(i);
3729 AutomationJSONReply(this, reply_message).SendError(
3730 "Extension's page action is not visible.");
3734 if (page_action->HasPopup(ExtensionTabUtil::GetTabId(tab))) {
3735 // This observer will delete itself.
3736 new ExtensionPopupObserver(
3737 this, reply_message, extension->id());
3739 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
3743 // See TriggerBrowserActionById() in chrome/test/pyautolib/pyauto.py
3744 // for sample json input.
3745 void TestingAutomationProvider::TriggerBrowserActionById(
3746 DictionaryValue* args,
3747 IPC::Message* reply_message) {
3751 if (!GetBrowserAndTabFromJSONArgs(args, &browser, &tab, &error)) {
3752 AutomationJSONReply(this, reply_message).SendError(error);
3755 const Extension* extension;
3756 if (!GetEnabledExtensionFromJSONArgs(
3757 args, "id", browser->profile(), &extension, &error)) {
3758 AutomationJSONReply(this, reply_message).SendError(error);
3761 ExtensionAction* action = ExtensionActionManager::Get(browser->profile())->
3762 GetBrowserAction(*extension);
3764 AutomationJSONReply(this, reply_message).SendError(
3765 "Extension doesn't have any browser action.");
3768 EnsureTabSelected(browser, tab);
3770 BrowserActionTestUtil browser_actions(browser);
3771 int num_browser_actions = browser_actions.NumberOfBrowserActions();
3772 int action_index = -1;
3773 #if defined(TOOLKIT_VIEWS)
3774 for (int i = 0; i < num_browser_actions; ++i) {
3775 if (extension->id() == browser_actions.GetExtensionId(i)) {
3781 // TODO(kkania): Implement the platform-specific GetExtensionId() in
3782 // BrowserActionTestUtil.
3783 if (num_browser_actions != 1) {
3784 AutomationJSONReply(this, reply_message).SendError(base::StringPrintf(
3785 "Found %d browser actions. Only one browser action must be active.",
3786 num_browser_actions));
3789 // This extension has a browser action, and there's only one action, so this
3790 // must be the first one.
3793 if (action_index == -1) {
3794 AutomationJSONReply(this, reply_message).SendError(
3795 "Extension's browser action is not visible.");
3798 browser_actions.Press(action_index);
3800 if (action->HasPopup(ExtensionTabUtil::GetTabId(tab))) {
3801 // This observer will delete itself.
3802 new ExtensionPopupObserver(
3803 this, reply_message, extension->id());
3805 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
3809 void TestingAutomationProvider::ActionOnSSLBlockingPage(
3810 DictionaryValue* args,
3811 IPC::Message* reply_message) {
3812 WebContents* web_contents;
3815 if (!GetTabFromJSONArgs(args, &web_contents, &error)) {
3816 AutomationJSONReply(this, reply_message).SendError(error);
3819 if (!args->GetBoolean("proceed", &proceed)) {
3820 AutomationJSONReply(this, reply_message).SendError(
3821 "'proceed' is missing or invalid");
3824 NavigationController& controller = web_contents->GetController();
3825 NavigationEntry* entry = controller.GetActiveEntry();
3826 if (entry->GetPageType() == content::PAGE_TYPE_INTERSTITIAL) {
3827 InterstitialPage* ssl_blocking_page =
3828 InterstitialPage::GetInterstitialPage(web_contents);
3829 if (ssl_blocking_page) {
3831 new NavigationNotificationObserver(&controller, this, reply_message, 1,
3833 ssl_blocking_page->Proceed();
3836 ssl_blocking_page->DontProceed();
3837 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
3841 AutomationJSONReply(this, reply_message).SendError(error);
3844 void TestingAutomationProvider::GetSecurityState(DictionaryValue* args,
3845 IPC::Message* reply_message) {
3846 AutomationJSONReply reply(this, reply_message);
3847 WebContents* web_contents;
3849 if (!GetTabFromJSONArgs(args, &web_contents, &error)) {
3850 reply.SendError(error);
3853 NavigationEntry* entry = web_contents->GetController().GetActiveEntry();
3854 DictionaryValue dict;
3855 dict.SetInteger("security_style",
3856 static_cast<int>(entry->GetSSL().security_style));
3857 dict.SetInteger("ssl_cert_status",
3858 static_cast<int>(entry->GetSSL().cert_status));
3859 dict.SetInteger("insecure_content_status",
3860 static_cast<int>(entry->GetSSL().content_status));
3861 reply.SendSuccess(&dict);
3864 // Sample json input: { "command": "UpdateExtensionsNow" }
3865 // Sample json output: {}
3866 void TestingAutomationProvider::UpdateExtensionsNow(
3867 DictionaryValue* args,
3868 IPC::Message* reply_message) {
3871 if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
3872 AutomationJSONReply(this, reply_message).SendError(error);
3875 ExtensionService* service = extensions::ExtensionSystem::Get(
3876 browser->profile())->extension_service();
3878 AutomationJSONReply(this, reply_message).SendError(
3879 "No extensions service.");
3883 extensions::ExtensionUpdater* updater = service->updater();
3885 AutomationJSONReply(this, reply_message).SendError(
3886 "No updater for extensions service.");
3890 ExtensionProcessManager* manager =
3891 extensions::ExtensionSystem::Get(browser->profile())->process_manager();
3893 AutomationJSONReply(this, reply_message).SendError(
3894 "No extension process manager.");
3898 // Create a new observer that waits until the extensions have been fully
3899 // updated (we should not send the reply until after all extensions have
3900 // been updated). This observer will delete itself.
3901 ExtensionsUpdatedObserver* observer = new ExtensionsUpdatedObserver(
3902 manager, this, reply_message);
3903 extensions::ExtensionUpdater::CheckParams params;
3904 params.install_immediately = true;
3905 params.callback = base::Bind(&ExtensionsUpdatedObserver::UpdateCheckFinished,
3906 base::Unretained(observer));
3907 updater->CheckNow(params);
3912 void SendSuccessIfAlive(
3913 base::WeakPtr<AutomationProvider> provider,
3914 IPC::Message* reply_message) {
3916 AutomationJSONReply(provider.get(), reply_message).SendSuccess(NULL);
3921 void TestingAutomationProvider::OverrideGeoposition(
3922 base::DictionaryValue* args,
3923 IPC::Message* reply_message) {
3924 double latitude, longitude, altitude;
3925 if (!args->GetDouble("latitude", &latitude) ||
3926 !args->GetDouble("longitude", &longitude) ||
3927 !args->GetDouble("altitude", &altitude)) {
3928 AutomationJSONReply(this, reply_message).SendError(
3929 "Missing or invalid geolocation parameters");
3932 content::Geoposition position;
3933 position.latitude = latitude;
3934 position.longitude = longitude;
3935 position.altitude = altitude;
3936 position.accuracy = 0.;
3937 position.timestamp = base::Time::Now();
3939 content::GeolocationProvider::OverrideLocationForTesting(
3941 base::Bind(&SendSuccessIfAlive, AsWeakPtr(), reply_message));
3944 // Refer to GetAllNotifications() in chrome/test/pyautolib/pyauto.py for
3945 // sample json input/output.
3946 void TestingAutomationProvider::GetAllNotifications(
3948 DictionaryValue* args,
3949 IPC::Message* reply_message) {
3950 new GetAllNotificationsObserver(this, reply_message);
3953 // Refer to CloseNotification() in chrome/test/pyautolib/pyauto.py for
3954 // sample json input.
3955 // Returns empty json message.
3956 void TestingAutomationProvider::CloseNotification(
3958 DictionaryValue* args,
3959 IPC::Message* reply_message) {
3961 if (!args->GetInteger("index", &index)) {
3962 AutomationJSONReply(this, reply_message)
3963 .SendError("'index' missing or invalid.");
3966 BalloonNotificationUIManager* manager =
3967 BalloonNotificationUIManager::GetInstanceForTesting();
3968 BalloonCollection* collection = manager->balloon_collection();
3969 const BalloonCollection::Balloons& balloons = collection->GetActiveBalloons();
3970 int balloon_count = static_cast<int>(balloons.size());
3971 if (index < 0 || index >= balloon_count) {
3972 AutomationJSONReply(this, reply_message)
3973 .SendError(base::StringPrintf("No notification at index %d", index));
3976 std::vector<const Notification*> queued_notes;
3977 manager->GetQueuedNotificationsForTesting(&queued_notes);
3978 if (queued_notes.empty()) {
3979 new OnNotificationBalloonCountObserver(
3980 this, reply_message, balloon_count - 1);
3982 new NewNotificationBalloonObserver(this, reply_message);
3984 manager->CancelById(balloons[index]->notification().notification_id());
3987 // Refer to WaitForNotificationCount() in chrome/test/pyautolib/pyauto.py for
3988 // sample json input.
3989 // Returns empty json message.
3990 void TestingAutomationProvider::WaitForNotificationCount(
3992 DictionaryValue* args,
3993 IPC::Message* reply_message) {
3995 if (!args->GetInteger("count", &count)) {
3996 AutomationJSONReply(this, reply_message)
3997 .SendError("'count' missing or invalid.");
4000 // This will delete itself when finished.
4001 new OnNotificationBalloonCountObserver(this, reply_message, count);
4004 // Sample JSON input: { "command": "GetNTPInfo" }
4005 // For output, refer to chrome/test/pyautolib/ntp_model.py.
4006 void TestingAutomationProvider::GetNTPInfo(
4008 DictionaryValue* args,
4009 IPC::Message* reply_message) {
4010 // This observer will delete itself.
4011 new NTPInfoObserver(this, reply_message);
4014 void TestingAutomationProvider::RemoveNTPMostVisitedThumbnail(
4016 DictionaryValue* args,
4017 IPC::Message* reply_message) {
4018 AutomationJSONReply reply(this, reply_message);
4020 if (!args->GetString("url", &url)) {
4021 reply.SendError("Missing or invalid 'url' key.");
4024 history::TopSites* top_sites = browser->profile()->GetTopSites();
4026 reply.SendError("TopSites service is not initialized.");
4029 top_sites->AddBlacklistedURL(GURL(url));
4030 reply.SendSuccess(NULL);
4033 void TestingAutomationProvider::RestoreAllNTPMostVisitedThumbnails(
4035 DictionaryValue* args,
4036 IPC::Message* reply_message) {
4037 AutomationJSONReply reply(this, reply_message);
4038 history::TopSites* top_sites = browser->profile()->GetTopSites();
4040 reply.SendError("TopSites service is not initialized.");
4043 top_sites->ClearBlacklistedURLs();
4044 reply.SendSuccess(NULL);
4047 void TestingAutomationProvider::KillRendererProcess(
4049 DictionaryValue* args,
4050 IPC::Message* reply_message) {
4052 uint32 kAccessFlags = base::kProcessAccessTerminate |
4053 base::kProcessAccessWaitForTermination |
4054 base::kProcessAccessQueryInformation;
4056 if (!args->GetInteger("pid", &pid)) {
4057 AutomationJSONReply(this, reply_message)
4058 .SendError("'pid' key missing or invalid.");
4061 base::ProcessHandle process;
4062 if (!base::OpenProcessHandleWithAccess(static_cast<base::ProcessId>(pid),
4065 AutomationJSONReply(this, reply_message).SendError(base::StringPrintf(
4066 "Failed to open process handle for pid %d", pid));
4069 new RendererProcessClosedObserver(this, reply_message);
4070 base::KillProcess(process, 0, false);
4071 base::CloseProcessHandle(process);
4074 bool TestingAutomationProvider::BuildWebKeyEventFromArgs(
4075 DictionaryValue* args,
4077 NativeWebKeyboardEvent* event) {
4078 int type, modifiers;
4080 string16 unmodified_text, text;
4081 std::string key_identifier;
4082 if (!args->GetInteger("type", &type)) {
4083 *error = "'type' missing or invalid.";
4086 if (!args->GetBoolean("isSystemKey", &is_system_key)) {
4087 *error = "'isSystemKey' missing or invalid.";
4090 if (!args->GetString("unmodifiedText", &unmodified_text)) {
4091 *error = "'unmodifiedText' missing or invalid.";
4094 if (!args->GetString("text", &text)) {
4095 *error = "'text' missing or invalid.";
4098 if (!args->GetInteger("nativeKeyCode", &event->nativeKeyCode)) {
4099 *error = "'nativeKeyCode' missing or invalid.";
4102 if (!args->GetInteger("windowsKeyCode", &event->windowsKeyCode)) {
4103 *error = "'windowsKeyCode' missing or invalid.";
4106 if (!args->GetInteger("modifiers", &modifiers)) {
4107 *error = "'modifiers' missing or invalid.";
4110 if (args->GetString("keyIdentifier", &key_identifier)) {
4111 base::strlcpy(event->keyIdentifier,
4112 key_identifier.c_str(),
4113 WebKit::WebKeyboardEvent::keyIdentifierLengthCap);
4115 *error = "'keyIdentifier' missing or invalid.";
4119 if (type == automation::kRawKeyDownType) {
4120 event->type = WebKit::WebInputEvent::RawKeyDown;
4121 } else if (type == automation::kKeyDownType) {
4122 event->type = WebKit::WebInputEvent::KeyDown;
4123 } else if (type == automation::kKeyUpType) {
4124 event->type = WebKit::WebInputEvent::KeyUp;
4125 } else if (type == automation::kCharType) {
4126 event->type = WebKit::WebInputEvent::Char;
4128 *error = "'type' refers to an unrecognized keyboard event type";
4132 string16 unmodified_text_truncated = unmodified_text.substr(
4133 0, WebKit::WebKeyboardEvent::textLengthCap - 1);
4134 memcpy(event->unmodifiedText,
4135 unmodified_text_truncated.c_str(),
4136 unmodified_text_truncated.length() + 1);
4137 string16 text_truncated = text.substr(
4138 0, WebKit::WebKeyboardEvent::textLengthCap - 1);
4139 memcpy(event->text, text_truncated.c_str(), text_truncated.length() + 1);
4141 event->modifiers = 0;
4142 if (modifiers & automation::kShiftKeyMask)
4143 event->modifiers |= WebKit::WebInputEvent::ShiftKey;
4144 if (modifiers & automation::kControlKeyMask)
4145 event->modifiers |= WebKit::WebInputEvent::ControlKey;
4146 if (modifiers & automation::kAltKeyMask)
4147 event->modifiers |= WebKit::WebInputEvent::AltKey;
4148 if (modifiers & automation::kMetaKeyMask)
4149 event->modifiers |= WebKit::WebInputEvent::MetaKey;
4151 event->isSystemKey = is_system_key;
4152 event->timeStampSeconds = base::Time::Now().ToDoubleT();
4153 event->skip_in_browser = true;
4157 void TestingAutomationProvider::SendWebkitKeyEvent(
4158 DictionaryValue* args,
4159 IPC::Message* reply_message) {
4160 if (SendErrorIfModalDialogActive(this, reply_message))
4163 NativeWebKeyboardEvent event;
4164 // In the event of an error, BuildWebKeyEventFromArgs handles telling what
4165 // went wrong and sending the reply message; if it fails, we just have to
4168 if (!BuildWebKeyEventFromArgs(args, &error, &event)) {
4169 AutomationJSONReply(this, reply_message).SendError(error);
4173 RenderViewHost* view;
4174 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
4175 AutomationJSONReply(this, reply_message).SendError(error);
4178 new InputEventAckNotificationObserver(this, reply_message, event.type, 1);
4179 view->ForwardKeyboardEvent(event);
4184 // Gets the active JavaScript modal dialog, or NULL if none.
4185 JavaScriptAppModalDialog* GetActiveJavaScriptModalDialog(
4186 std::string* error_msg) {
4187 AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance();
4188 if (!dialog_queue->HasActiveDialog() ||
4189 !dialog_queue->active_dialog()->IsJavaScriptModalDialog()) {
4190 *error_msg = "No JavaScriptModalDialog open";
4193 return static_cast<JavaScriptAppModalDialog*>(dialog_queue->active_dialog());
4198 void TestingAutomationProvider::GetAppModalDialogMessage(
4199 DictionaryValue* args, IPC::Message* reply_message) {
4200 AutomationJSONReply reply(this, reply_message);
4201 std::string error_msg;
4202 JavaScriptAppModalDialog* dialog = GetActiveJavaScriptModalDialog(&error_msg);
4204 reply.SendError(error_msg);
4207 DictionaryValue result_dict;
4208 result_dict.SetString("message", UTF16ToUTF8(dialog->message_text()));
4209 reply.SendSuccess(&result_dict);
4212 void TestingAutomationProvider::AcceptOrDismissAppModalDialog(
4213 DictionaryValue* args, IPC::Message* reply_message) {
4214 AutomationJSONReply reply(this, reply_message);
4216 if (!args->GetBoolean("accept", &accept)) {
4217 reply.SendError("Missing or invalid 'accept'");
4221 std::string error_msg;
4222 JavaScriptAppModalDialog* dialog = GetActiveJavaScriptModalDialog(&error_msg);
4224 reply.SendError(error_msg);
4228 std::string prompt_text;
4229 if (args->GetString("prompt_text", &prompt_text))
4230 dialog->SetOverridePromptText(UTF8ToUTF16(prompt_text));
4231 dialog->native_dialog()->AcceptAppModalDialog();
4233 dialog->native_dialog()->CancelAppModalDialog();
4235 reply.SendSuccess(NULL);
4238 // Sample JSON input: { "command": "LaunchApp",
4239 // "id": "ahfgeienlihckogmohjhadlkjgocpleb" }
4240 // Sample JSON output: {}
4241 void TestingAutomationProvider::LaunchApp(
4243 DictionaryValue* args,
4244 IPC::Message* reply_message) {
4246 if (!args->GetString("id", &id)) {
4247 AutomationJSONReply(this, reply_message).SendError(
4248 "Must include string id.");
4252 ExtensionService* service = extensions::ExtensionSystem::Get(
4253 browser->profile())->extension_service();
4255 AutomationJSONReply(this, reply_message).SendError(
4256 "No extensions service.");
4260 const Extension* extension = service->GetExtensionById(
4261 id, false /* do not include disabled extensions */);
4263 AutomationJSONReply(this, reply_message).SendError(
4265 "Extension with ID '%s' doesn't exist or is disabled.",
4270 WebContents* old_contents =
4271 browser->tab_strip_model()->GetActiveWebContents();
4272 if (!old_contents) {
4273 AutomationJSONReply(this, reply_message).SendError(
4274 "Cannot identify selected tab contents.");
4278 AppLaunchParams launch_params(profile(), extension, CURRENT_TAB);
4279 // This observer will delete itself.
4280 new AppLaunchObserver(&old_contents->GetController(), this, reply_message,
4281 launch_params.container);
4282 OpenApplication(launch_params);
4285 // Sample JSON input: { "command": "SetAppLaunchType",
4286 // "id": "ahfgeienlihckogmohjhadlkjgocpleb",
4287 // "launch_type": "pinned" }
4288 // Sample JSON output: {}
4289 void TestingAutomationProvider::SetAppLaunchType(
4291 DictionaryValue* args,
4292 IPC::Message* reply_message) {
4293 AutomationJSONReply reply(this, reply_message);
4296 if (!args->GetString("id", &id)) {
4297 reply.SendError("Must include string id.");
4301 std::string launch_type_str;
4302 if (!args->GetString("launch_type", &launch_type_str)) {
4303 reply.SendError("Must specify app launch type.");
4307 ExtensionService* service = extensions::ExtensionSystem::Get(
4308 browser->profile())->extension_service();
4310 reply.SendError("No extensions service.");
4314 const Extension* extension = service->GetExtensionById(
4315 id, true /* include disabled extensions */);
4317 reply.SendError(base::StringPrintf(
4318 "Extension with ID '%s' doesn't exist.", id.c_str()));
4322 extensions::ExtensionPrefs::LaunchType launch_type;
4323 if (launch_type_str == "pinned") {
4324 launch_type = extensions::ExtensionPrefs::LAUNCH_PINNED;
4325 } else if (launch_type_str == "regular") {
4326 launch_type = extensions::ExtensionPrefs::LAUNCH_REGULAR;
4327 } else if (launch_type_str == "fullscreen") {
4328 launch_type = extensions::ExtensionPrefs::LAUNCH_FULLSCREEN;
4329 } else if (launch_type_str == "window") {
4330 launch_type = extensions::ExtensionPrefs::LAUNCH_WINDOW;
4332 reply.SendError(base::StringPrintf(
4333 "Unexpected launch type '%s'.", launch_type_str.c_str()));
4337 service->extension_prefs()->SetLaunchType(extension->id(), launch_type);
4338 reply.SendSuccess(NULL);
4341 // Sample json input: { "command": "GetV8HeapStats",
4343 // Refer to GetV8HeapStats() in chrome/test/pyautolib/pyauto.py for
4344 // sample json output.
4345 void TestingAutomationProvider::GetV8HeapStats(
4347 DictionaryValue* args,
4348 IPC::Message* reply_message) {
4349 WebContents* web_contents;
4352 if (!args->GetInteger("tab_index", &tab_index)) {
4353 AutomationJSONReply(this, reply_message).SendError(
4354 "Missing 'tab_index' argument.");
4358 web_contents = browser->tab_strip_model()->GetWebContentsAt(tab_index);
4359 if (!web_contents) {
4360 AutomationJSONReply(this, reply_message).SendError(base::StringPrintf(
4361 "Could not get WebContents at tab index %d", tab_index));
4365 RenderViewHost* render_view = web_contents->GetRenderViewHost();
4367 // This observer will delete itself.
4368 new V8HeapStatsObserver(
4369 this, reply_message,
4370 base::GetProcId(render_view->GetProcess()->GetHandle()));
4371 render_view->Send(new ChromeViewMsg_GetV8HeapStats);
4374 // Sample json input: { "command": "GetFPS",
4376 // Refer to GetFPS() in chrome/test/pyautolib/pyauto.py for
4377 // sample json output.
4378 void TestingAutomationProvider::GetFPS(
4380 DictionaryValue* args,
4381 IPC::Message* reply_message) {
4382 WebContents* web_contents;
4385 if (!args->GetInteger("tab_index", &tab_index)) {
4386 AutomationJSONReply(this, reply_message).SendError(
4387 "Missing 'tab_index' argument.");
4391 web_contents = browser->tab_strip_model()->GetWebContentsAt(tab_index);
4392 if (!web_contents) {
4393 AutomationJSONReply(this, reply_message).SendError(base::StringPrintf(
4394 "Could not get WebContents at tab index %d", tab_index));
4398 RenderViewHost* render_view = web_contents->GetRenderViewHost();
4399 int routing_id = render_view->GetRoutingID();
4401 // This observer will delete itself.
4403 this, reply_message,
4404 base::GetProcId(render_view->GetProcess()->GetHandle()),
4406 render_view->Send(new ChromeViewMsg_GetFPS(routing_id));
4409 void TestingAutomationProvider::IsFullscreenForBrowser(Browser* browser,
4410 base::DictionaryValue* args,
4411 IPC::Message* reply_message) {
4412 DictionaryValue dict;
4413 dict.SetBoolean("result",
4414 browser->fullscreen_controller()->IsFullscreenForBrowser());
4415 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
4418 void TestingAutomationProvider::IsFullscreenForTab(Browser* browser,
4419 base::DictionaryValue* args,
4420 IPC::Message* reply_message) {
4421 DictionaryValue dict;
4422 dict.SetBoolean("result",
4423 browser->fullscreen_controller()->IsFullscreenForTabOrPending());
4424 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
4427 void TestingAutomationProvider::IsMouseLocked(Browser* browser,
4428 base::DictionaryValue* args,
4429 IPC::Message* reply_message) {
4430 DictionaryValue dict;
4431 dict.SetBoolean("result", browser->tab_strip_model()->GetActiveWebContents()->
4432 GetRenderViewHost()->GetView()->IsMouseLocked());
4433 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
4436 void TestingAutomationProvider::IsMouseLockPermissionRequested(
4438 base::DictionaryValue* args,
4439 IPC::Message* reply_message) {
4440 FullscreenExitBubbleType type =
4441 browser->fullscreen_controller()->GetFullscreenExitBubbleType();
4442 bool mouse_lock = false;
4443 fullscreen_bubble::PermissionRequestedByType(type, NULL, &mouse_lock);
4444 DictionaryValue dict;
4445 dict.SetBoolean("result", mouse_lock);
4446 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
4449 void TestingAutomationProvider::IsFullscreenPermissionRequested(
4451 base::DictionaryValue* args,
4452 IPC::Message* reply_message) {
4453 FullscreenExitBubbleType type =
4454 browser->fullscreen_controller()->GetFullscreenExitBubbleType();
4455 bool fullscreen = false;
4456 fullscreen_bubble::PermissionRequestedByType(type, &fullscreen, NULL);
4457 DictionaryValue dict;
4458 dict.SetBoolean("result", fullscreen);
4459 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
4462 void TestingAutomationProvider::IsFullscreenBubbleDisplayed(Browser* browser,
4463 base::DictionaryValue* args,
4464 IPC::Message* reply_message) {
4465 FullscreenExitBubbleType type =
4466 browser->fullscreen_controller()->GetFullscreenExitBubbleType();
4467 DictionaryValue dict;
4468 dict.SetBoolean("result",
4469 type != FEB_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION);
4470 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
4473 void TestingAutomationProvider::IsFullscreenBubbleDisplayingButtons(
4475 base::DictionaryValue* args,
4476 IPC::Message* reply_message) {
4477 FullscreenExitBubbleType type =
4478 browser->fullscreen_controller()->GetFullscreenExitBubbleType();
4479 DictionaryValue dict;
4480 dict.SetBoolean("result", fullscreen_bubble::ShowButtonsForType(type));
4481 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
4484 void TestingAutomationProvider::AcceptCurrentFullscreenOrMouseLockRequest(
4486 base::DictionaryValue* args,
4487 IPC::Message* reply_message) {
4488 browser->fullscreen_controller()->OnAcceptFullscreenPermission();
4489 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
4492 void TestingAutomationProvider::DenyCurrentFullscreenOrMouseLockRequest(
4494 base::DictionaryValue* args,
4495 IPC::Message* reply_message) {
4496 browser->fullscreen_controller()->OnDenyFullscreenPermission();
4497 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
4500 void TestingAutomationProvider::WaitForTabToBeRestored(
4501 DictionaryValue* args,
4502 IPC::Message* reply_message) {
4503 WebContents* web_contents;
4505 if (!GetTabFromJSONArgs(args, &web_contents, &error)) {
4506 AutomationJSONReply(this, reply_message).SendError(error);
4509 NavigationController& controller = web_contents->GetController();
4510 new NavigationControllerRestoredObserver(this, &controller, reply_message);
4513 void TestingAutomationProvider::RefreshPolicies(
4514 base::DictionaryValue* args,
4515 IPC::Message* reply_message) {
4516 #if !defined(ENABLE_CONFIGURATION_POLICY)
4517 AutomationJSONReply(this, reply_message).SendError(
4518 "Configuration Policy disabled");
4520 // Some policies (e.g. URLBlacklist) post tasks to other message loops
4521 // before they start enforcing updated policy values; make sure those tasks
4522 // have finished after a policy update.
4523 // Updates of the URLBlacklist are done on IO, after building the blacklist
4524 // on FILE, which is initiated from IO.
4525 base::Closure reply =
4526 base::Bind(SendSuccessReply, AsWeakPtr(), reply_message);
4527 g_browser_process->policy_service()->RefreshPolicies(
4528 base::Bind(PostTask, BrowserThread::IO,
4529 base::Bind(PostTask, BrowserThread::FILE,
4530 base::Bind(PostTask, BrowserThread::IO,
4531 base::Bind(PostTask, BrowserThread::UI, reply)))));
4535 static int AccessArray(const volatile int arr[], const volatile int *index) {
4539 void TestingAutomationProvider::SimulateAsanMemoryBug(
4540 base::DictionaryValue* args, IPC::Message* reply_message) {
4541 // This array is volatile not to let compiler optimize us out.
4542 volatile int testarray[3] = {0, 0, 0};
4544 // Send the reply while we can.
4545 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
4547 // Cause Address Sanitizer to abort this process.
4548 volatile int index = 5;
4549 AccessArray(testarray, &index);
4552 void TestingAutomationProvider::GetIndicesFromTab(
4553 DictionaryValue* args,
4554 IPC::Message* reply_message) {
4555 AutomationJSONReply reply(this, reply_message);
4556 int id_or_handle = 0;
4557 bool has_id = args->HasKey("tab_id");
4558 bool has_handle = args->HasKey("tab_handle");
4559 if (has_id && has_handle) {
4561 "Both 'tab_id' and 'tab_handle' were specified. Only one is allowed");
4563 } else if (!has_id && !has_handle) {
4564 reply.SendError("Either 'tab_id' or 'tab_handle' must be specified");
4567 if (has_id && !args->GetInteger("tab_id", &id_or_handle)) {
4568 reply.SendError("'tab_id' is invalid");
4571 if (has_handle && (!args->GetInteger("tab_handle", &id_or_handle) ||
4572 !tab_tracker_->ContainsHandle(id_or_handle))) {
4573 reply.SendError("'tab_handle' is invalid");
4576 int id = id_or_handle;
4578 SessionTabHelper* session_tab_helper =
4579 SessionTabHelper::FromWebContents(
4580 tab_tracker_->GetResource(id_or_handle)->GetWebContents());
4581 id = session_tab_helper->session_id().id();
4583 chrome::BrowserIterator it;
4584 int browser_index = 0;
4585 for (; !it.done(); it.Next(), ++browser_index) {
4586 Browser* browser = *it;
4587 for (int tab_index = 0;
4588 tab_index < browser->tab_strip_model()->count();
4591 browser->tab_strip_model()->GetWebContentsAt(tab_index);
4592 SessionTabHelper* session_tab_helper =
4593 SessionTabHelper::FromWebContents(tab);
4594 if (session_tab_helper->session_id().id() == id) {
4595 DictionaryValue dict;
4596 dict.SetInteger("windex", browser_index);
4597 dict.SetInteger("tab_index", tab_index);
4598 reply.SendSuccess(&dict);
4603 reply.SendError("Could not find tab among current browser windows");
4606 void TestingAutomationProvider::NavigateToURL(
4607 DictionaryValue* args,
4608 IPC::Message* reply_message) {
4609 if (SendErrorIfModalDialogActive(this, reply_message))
4612 int navigation_count;
4613 std::string url, error;
4615 WebContents* web_contents;
4616 if (!GetBrowserAndTabFromJSONArgs(args, &browser, &web_contents, &error)) {
4617 AutomationJSONReply(this, reply_message).SendError(error);
4620 if (!args->GetString("url", &url)) {
4621 AutomationJSONReply(this, reply_message)
4622 .SendError("'url' missing or invalid");
4625 if (!args->GetInteger("navigation_count", &navigation_count)) {
4626 AutomationJSONReply(this, reply_message)
4627 .SendError("'navigation_count' missing or invalid");
4630 if (navigation_count > 0) {
4631 new NavigationNotificationObserver(
4632 &web_contents->GetController(), this, reply_message,
4633 navigation_count, false, true);
4635 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
4637 OpenURLParams params(
4638 GURL(url), content::Referrer(), CURRENT_TAB,
4639 content::PageTransitionFromInt(
4640 content::PAGE_TRANSITION_TYPED |
4641 content::PAGE_TRANSITION_FROM_ADDRESS_BAR),
4643 browser->OpenURLFromTab(web_contents, params);
4646 void TestingAutomationProvider::GetActiveTabIndexJSON(
4647 DictionaryValue* args,
4648 IPC::Message* reply_message) {
4649 AutomationJSONReply reply(this, reply_message);
4651 std::string error_msg;
4652 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
4653 reply.SendError(error_msg);
4656 int tab_index = browser->tab_strip_model()->active_index();
4657 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
4658 return_value->SetInteger("tab_index", tab_index);
4659 reply.SendSuccess(return_value.get());
4662 void TestingAutomationProvider::AppendTabJSON(DictionaryValue* args,
4663 IPC::Message* reply_message) {
4664 TabAppendedNotificationObserver* observer = NULL;
4665 int append_tab_response = -1;
4667 std::string error_msg, url;
4668 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
4669 AutomationJSONReply(this, reply_message).SendError(error_msg);
4672 if (!args->GetString("url", &url)) {
4673 AutomationJSONReply(this, reply_message)
4674 .SendError("'url' missing or invalid");
4677 observer = new TabAppendedNotificationObserver(browser, this, reply_message,
4679 WebContents* contents =
4680 chrome::AddSelectedTabWithURL(browser, GURL(url),
4681 content::PAGE_TRANSITION_TYPED);
4683 append_tab_response = GetIndexForNavigationController(
4684 &contents->GetController(), browser);
4687 if (!contents || append_tab_response < 0) {
4689 observer->ReleaseReply();
4692 AutomationJSONReply(this, reply_message).SendError("Failed to append tab.");
4696 void TestingAutomationProvider::WaitUntilNavigationCompletes(
4697 DictionaryValue* args,
4698 IPC::Message* reply_message) {
4699 if (SendErrorIfModalDialogActive(this, reply_message))
4704 WebContents* web_contents;
4705 if (!GetBrowserAndTabFromJSONArgs(args, &browser, &web_contents, &error)) {
4706 AutomationJSONReply(this, reply_message).SendError(error);
4709 NavigationNotificationObserver* observer =
4710 new NavigationNotificationObserver(&web_contents->GetController(), this,
4711 reply_message, 1, true, true);
4712 if (!web_contents->IsLoading()) {
4713 observer->ConditionMet(AUTOMATION_MSG_NAVIGATION_SUCCESS);
4718 void TestingAutomationProvider::ExecuteJavascriptJSON(
4719 DictionaryValue* args,
4720 IPC::Message* reply_message) {
4721 if (SendErrorIfModalDialogActive(this, reply_message))
4724 string16 frame_xpath, javascript;
4726 RenderViewHost* render_view;
4727 if (!GetRenderViewFromJSONArgs(args, profile(), &render_view, &error)) {
4728 AutomationJSONReply(this, reply_message).SendError(error);
4731 if (!args->GetString("frame_xpath", &frame_xpath)) {
4732 AutomationJSONReply(this, reply_message)
4733 .SendError("'frame_xpath' missing or invalid");
4736 if (!args->GetString("javascript", &javascript)) {
4737 AutomationJSONReply(this, reply_message)
4738 .SendError("'javascript' missing or invalid");
4742 new DomOperationMessageSender(this, reply_message, true);
4743 ExecuteJavascriptInRenderViewFrame(frame_xpath, javascript, reply_message,
4747 void TestingAutomationProvider::ExecuteJavascriptInRenderView(
4748 DictionaryValue* args,
4749 IPC::Message* reply_message) {
4750 string16 frame_xpath, javascript, extension_id, url_text;
4751 int render_process_id, render_view_id;
4752 if (!args->GetString("frame_xpath", &frame_xpath)) {
4753 AutomationJSONReply(this, reply_message)
4754 .SendError("'frame_xpath' missing or invalid");
4757 if (!args->GetString("javascript", &javascript)) {
4758 AutomationJSONReply(this, reply_message)
4759 .SendError("'javascript' missing or invalid");
4762 if (!args->GetInteger("view.render_process_id", &render_process_id)) {
4763 AutomationJSONReply(this, reply_message)
4764 .SendError("'view.render_process_id' missing or invalid");
4767 if (!args->GetInteger("view.render_view_id", &render_view_id)) {
4768 AutomationJSONReply(this, reply_message)
4769 .SendError("'view.render_view_id' missing or invalid");
4773 RenderViewHost* rvh = RenderViewHost::FromID(render_process_id,
4776 AutomationJSONReply(this, reply_message).SendError(
4777 "A RenderViewHost object was not found with the given view ID.");
4781 new DomOperationMessageSender(this, reply_message, true);
4782 ExecuteJavascriptInRenderViewFrame(frame_xpath, javascript, reply_message,
4786 void TestingAutomationProvider::AddDomEventObserver(
4787 DictionaryValue* args,
4788 IPC::Message* reply_message) {
4789 if (SendErrorIfModalDialogActive(this, reply_message))
4792 AutomationJSONReply reply(this, reply_message);
4793 std::string event_name;
4796 if (!args->GetString("event_name", &event_name)) {
4797 reply.SendError("'event_name' missing or invalid");
4800 if (!args->GetInteger("automation_id", &automation_id)) {
4801 reply.SendError("'automation_id' missing or invalid");
4804 if (!args->GetBoolean("recurring", &recurring)) {
4805 reply.SendError("'recurring' missing or invalid");
4809 if (!automation_event_queue_.get())
4810 automation_event_queue_.reset(new AutomationEventQueue);
4812 int observer_id = automation_event_queue_->AddObserver(
4813 new DomEventObserver(automation_event_queue_.get(), event_name,
4814 automation_id, recurring));
4815 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
4816 return_value->SetInteger("observer_id", observer_id);
4817 reply.SendSuccess(return_value.get());
4820 void TestingAutomationProvider::RemoveEventObserver(
4821 DictionaryValue* args,
4822 IPC::Message* reply_message) {
4823 AutomationJSONReply reply(this, reply_message);
4825 if (!args->GetInteger("observer_id", &observer_id) ||
4826 !automation_event_queue_.get()) {
4827 reply.SendError("'observer_id' missing or invalid");
4830 if (automation_event_queue_->RemoveObserver(observer_id)) {
4831 reply.SendSuccess(NULL);
4834 reply.SendError("Invalid observer id.");
4837 void TestingAutomationProvider::ClearEventQueue(
4838 DictionaryValue* args,
4839 IPC::Message* reply_message) {
4840 automation_event_queue_.reset();
4841 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
4844 void TestingAutomationProvider::GetNextEvent(
4845 DictionaryValue* args,
4846 IPC::Message* reply_message) {
4847 scoped_ptr<AutomationJSONReply> reply(
4848 new AutomationJSONReply(this, reply_message));
4851 if (!args->GetInteger("observer_id", &observer_id)) {
4852 reply->SendError("'observer_id' missing or invalid");
4855 if (!args->GetBoolean("blocking", &blocking)) {
4856 reply->SendError("'blocking' missing or invalid");
4859 if (!automation_event_queue_.get()) {
4861 "No observers are attached to the queue. Did you create any?");
4865 // The reply will be freed once a matching event is added to the queue.
4866 automation_event_queue_->GetNextEvent(reply.release(), observer_id, blocking);
4869 void TestingAutomationProvider::GoForward(
4870 DictionaryValue* args,
4871 IPC::Message* reply_message) {
4872 if (SendErrorIfModalDialogActive(this, reply_message))
4875 WebContents* web_contents;
4877 if (!GetTabFromJSONArgs(args, &web_contents, &error)) {
4878 AutomationJSONReply(this, reply_message).SendError(error);
4881 NavigationController& controller = web_contents->GetController();
4882 if (!controller.CanGoForward()) {
4883 DictionaryValue dict;
4884 dict.SetBoolean("did_go_forward", false);
4885 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
4888 new NavigationNotificationObserver(&controller, this, reply_message,
4890 controller.GoForward();
4893 void TestingAutomationProvider::ExecuteBrowserCommandAsyncJSON(
4894 DictionaryValue* args,
4895 IPC::Message* reply_message) {
4896 AutomationJSONReply reply(this, reply_message);
4900 if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
4901 reply.SendError(error);
4904 if (!args->GetInteger("accelerator", &command)) {
4905 reply.SendError("'accelerator' missing or invalid.");
4908 if (!chrome::SupportsCommand(browser, command)) {
4909 reply.SendError(base::StringPrintf("Browser does not support command=%d.",
4913 if (!chrome::IsCommandEnabled(browser, command)) {
4914 reply.SendError(base::StringPrintf(
4915 "Browser command=%d not enabled.", command));
4918 chrome::ExecuteCommand(browser, command);
4919 reply.SendSuccess(NULL);
4922 void TestingAutomationProvider::ExecuteBrowserCommandJSON(
4923 DictionaryValue* args,
4924 IPC::Message* reply_message) {
4928 if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
4929 AutomationJSONReply(this, reply_message).SendError(error);
4932 if (!args->GetInteger("accelerator", &command)) {
4933 AutomationJSONReply(this, reply_message).SendError(
4934 "'accelerator' missing or invalid.");
4937 if (!chrome::SupportsCommand(browser, command)) {
4938 AutomationJSONReply(this, reply_message).SendError(
4939 base::StringPrintf("Browser does not support command=%d.", command));
4942 if (!chrome::IsCommandEnabled(browser, command)) {
4943 AutomationJSONReply(this, reply_message).SendError(
4944 base::StringPrintf("Browser command=%d not enabled.", command));
4947 // First check if we can handle the command without using an observer.
4948 for (size_t i = 0; i < arraysize(kSynchronousCommands); i++) {
4949 if (command == kSynchronousCommands[i]) {
4950 chrome::ExecuteCommand(browser, command);
4951 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
4955 // Use an observer if we have one, otherwise fail.
4956 if (ExecuteBrowserCommandObserver::CreateAndRegisterObserver(
4957 this, browser, command, reply_message, true)) {
4958 chrome::ExecuteCommand(browser, command);
4961 AutomationJSONReply(this, reply_message).SendError(base::StringPrintf(
4962 "Unable to register observer for browser command=%d.", command));
4965 void TestingAutomationProvider::IsMenuCommandEnabledJSON(
4966 DictionaryValue* args,
4967 IPC::Message* reply_message) {
4971 if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
4972 AutomationJSONReply(this, reply_message).SendError(error);
4975 if (!args->GetInteger("accelerator", &command)) {
4976 AutomationJSONReply(this, reply_message).SendError(
4977 "'accelerator' missing or invalid.");
4980 DictionaryValue dict;
4981 dict.SetBoolean("enabled", chrome::IsCommandEnabled(browser, command));
4982 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
4985 void TestingAutomationProvider::GetTabInfo(
4986 DictionaryValue* args,
4987 IPC::Message* reply_message) {
4988 AutomationJSONReply reply(this, reply_message);
4992 if (GetBrowserAndTabFromJSONArgs(args, &browser, &tab, &error)) {
4993 NavigationEntry* entry = tab->GetController().GetActiveEntry();
4995 reply.SendError("Unable to get active navigation entry");
4998 DictionaryValue dict;
4999 dict.SetString("title", entry->GetTitleForDisplay(std::string()));
5000 dict.SetString("url", entry->GetVirtualURL().spec());
5001 reply.SendSuccess(&dict);
5003 reply.SendError(error);
5007 void TestingAutomationProvider::GetTabCountJSON(
5008 DictionaryValue* args,
5009 IPC::Message* reply_message) {
5010 AutomationJSONReply reply(this, reply_message);
5013 if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
5014 reply.SendError(error);
5017 DictionaryValue dict;
5018 dict.SetInteger("tab_count", browser->tab_strip_model()->count());
5019 reply.SendSuccess(&dict);
5022 void TestingAutomationProvider::GoBack(
5023 DictionaryValue* args,
5024 IPC::Message* reply_message) {
5025 if (SendErrorIfModalDialogActive(this, reply_message))
5028 WebContents* web_contents;
5030 if (!GetTabFromJSONArgs(args, &web_contents, &error)) {
5031 AutomationJSONReply(this, reply_message).SendError(error);
5034 NavigationController& controller = web_contents->GetController();
5035 if (!controller.CanGoBack()) {
5036 DictionaryValue dict;
5037 dict.SetBoolean("did_go_back", false);
5038 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
5041 new NavigationNotificationObserver(&controller, this, reply_message,
5043 controller.GoBack();
5046 void TestingAutomationProvider::ReloadJSON(
5047 DictionaryValue* args,
5048 IPC::Message* reply_message) {
5049 if (SendErrorIfModalDialogActive(this, reply_message))
5052 WebContents* web_contents;
5054 if (!GetTabFromJSONArgs(args, &web_contents, &error)) {
5055 AutomationJSONReply(this, reply_message).SendError(error);
5058 NavigationController& controller = web_contents->GetController();
5059 new NavigationNotificationObserver(&controller, this, reply_message,
5061 controller.Reload(false);
5064 void TestingAutomationProvider::GetCookiesJSON(
5065 DictionaryValue* args, IPC::Message* reply_message) {
5066 automation_util::GetCookiesJSON(this, args, reply_message);
5069 void TestingAutomationProvider::DeleteCookieJSON(
5070 DictionaryValue* args, IPC::Message* reply_message) {
5071 automation_util::DeleteCookieJSON(this, args, reply_message);
5074 void TestingAutomationProvider::SetCookieJSON(
5075 DictionaryValue* args, IPC::Message* reply_message) {
5076 automation_util::SetCookieJSON(this, args, reply_message);
5079 void TestingAutomationProvider::GetCookiesInBrowserContext(
5080 DictionaryValue* args,
5081 IPC::Message* reply_message) {
5082 AutomationJSONReply reply(this, reply_message);
5083 WebContents* web_contents;
5084 std::string value, url_string;
5085 int windex, value_size;
5086 if (!args->GetInteger("windex", &windex)) {
5087 reply.SendError("'windex' missing or invalid.");
5090 web_contents = automation_util::GetWebContentsAt(windex, 0);
5091 if (!web_contents) {
5092 reply.SendError("'windex' does not refer to a browser window.");
5095 if (!args->GetString("url", &url_string)) {
5096 reply.SendError("'url' missing or invalid.");
5099 GURL url(url_string);
5100 if (!url.is_valid()) {
5101 reply.SendError("Invalid url.");
5104 automation_util::GetCookies(url, web_contents, &value_size, &value);
5105 if (value_size == -1) {
5107 base::StringPrintf("Unable to retrieve cookies for url=%s.",
5108 url_string.c_str()));
5111 DictionaryValue dict;
5112 dict.SetString("cookies", value);
5113 reply.SendSuccess(&dict);
5116 void TestingAutomationProvider::DeleteCookieInBrowserContext(
5117 DictionaryValue* args,
5118 IPC::Message* reply_message) {
5119 AutomationJSONReply reply(this, reply_message);
5120 WebContents* web_contents;
5121 std::string cookie_name, url_string;
5123 bool success = false;
5124 if (!args->GetInteger("windex", &windex)) {
5125 reply.SendError("'windex' missing or invalid.");
5128 web_contents = automation_util::GetWebContentsAt(windex, 0);
5129 if (!web_contents) {
5130 reply.SendError("'windex' does not refer to a browser window.");
5133 if (!args->GetString("cookie_name", &cookie_name)) {
5134 reply.SendError("'cookie_name' missing or invalid.");
5137 if (!args->GetString("url", &url_string)) {
5138 reply.SendError("'url' missing or invalid.");
5141 GURL url(url_string);
5142 if (!url.is_valid()) {
5143 reply.SendError("Invalid url.");
5146 automation_util::DeleteCookie(url, cookie_name, web_contents, &success);
5149 base::StringPrintf("Failed to delete cookie with name=%s for url=%s.",
5150 cookie_name.c_str(), url_string.c_str()));
5153 reply.SendSuccess(NULL);
5156 void TestingAutomationProvider::SetCookieInBrowserContext(
5157 DictionaryValue* args,
5158 IPC::Message* reply_message) {
5159 AutomationJSONReply reply(this, reply_message);
5160 WebContents* web_contents;
5161 std::string value, url_string;
5162 int windex, response_value = -1;
5163 if (!args->GetInteger("windex", &windex)) {
5164 reply.SendError("'windex' missing or invalid.");
5167 web_contents = automation_util::GetWebContentsAt(windex, 0);
5168 if (!web_contents) {
5169 reply.SendError("'windex' does not refer to a browser window.");
5172 if (!args->GetString("value", &value)) {
5173 reply.SendError("'value' missing or invalid.");
5176 if (!args->GetString("url", &url_string)) {
5177 reply.SendError("'url' missing or invalid.");
5180 GURL url(url_string);
5181 if (!url.is_valid()) {
5182 reply.SendError("Invalid url.");
5185 automation_util::SetCookie(url, value, web_contents, &response_value);
5186 if (response_value != 1) {
5187 reply.SendError(base::StringPrintf(
5188 "Unable set cookie for url=%s.", url_string.c_str()));
5191 reply.SendSuccess(NULL);
5194 void TestingAutomationProvider::GetTabIds(
5195 DictionaryValue* args, IPC::Message* reply_message) {
5196 ListValue* id_list = new ListValue();
5197 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
5198 Browser* browser = *it;
5199 for (int i = 0; i < browser->tab_strip_model()->count(); ++i) {
5200 int id = SessionTabHelper::FromWebContents(
5201 browser->tab_strip_model()->GetWebContentsAt(i))->session_id().id();
5202 id_list->Append(Value::CreateIntegerValue(id));
5205 DictionaryValue dict;
5206 dict.Set("ids", id_list);
5207 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
5210 void TestingAutomationProvider::IsTabIdValid(
5211 DictionaryValue* args, IPC::Message* reply_message) {
5212 AutomationJSONReply reply(this, reply_message);
5214 if (!args->GetInteger("id", &id)) {
5215 reply.SendError("'id' missing or invalid");
5218 bool is_valid = false;
5219 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
5220 Browser* browser = *it;
5221 for (int i = 0; i < browser->tab_strip_model()->count(); ++i) {
5222 WebContents* tab = browser->tab_strip_model()->GetWebContentsAt(i);
5223 SessionTabHelper* session_tab_helper =
5224 SessionTabHelper::FromWebContents(tab);
5225 if (session_tab_helper->session_id().id() == id) {
5231 DictionaryValue dict;
5232 dict.SetBoolean("is_valid", is_valid);
5233 reply.SendSuccess(&dict);
5236 void TestingAutomationProvider::CloseTabJSON(
5237 DictionaryValue* args, IPC::Message* reply_message) {
5241 bool wait_until_closed = false; // ChromeDriver does not use this.
5242 args->GetBoolean("wait_until_closed", &wait_until_closed);
5243 // Close tabs synchronously.
5244 if (GetBrowserAndTabFromJSONArgs(args, &browser, &tab, &error)) {
5245 if (wait_until_closed) {
5246 new TabClosedNotificationObserver(this, wait_until_closed, reply_message,
5249 chrome::CloseWebContents(browser, tab, false);
5250 if (!wait_until_closed)
5251 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
5254 // Close other types of views asynchronously.
5255 RenderViewHost* view;
5256 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
5257 AutomationJSONReply(this, reply_message).SendError(error);
5261 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
5264 void TestingAutomationProvider::SetViewBounds(
5265 base::DictionaryValue* args,
5266 IPC::Message* reply_message) {
5267 AutomationJSONReply reply(this, reply_message);
5268 int x, y, width, height;
5269 if (!args->GetInteger("bounds.x", &x) ||
5270 !args->GetInteger("bounds.y", &y) ||
5271 !args->GetInteger("bounds.width", &width) ||
5272 !args->GetInteger("bounds.height", &height)) {
5273 reply.SendError("Missing or invalid 'bounds'");
5278 if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
5279 reply.SendError(error);
5282 BrowserWindow* browser_window = browser->window();
5283 if (browser_window->IsMaximized()) {
5284 browser_window->Restore();
5286 browser_window->SetBounds(gfx::Rect(x, y, width, height));
5287 reply.SendSuccess(NULL);
5290 void TestingAutomationProvider::MaximizeView(
5291 base::DictionaryValue* args,
5292 IPC::Message* reply_message) {
5295 if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
5296 AutomationJSONReply(this, reply_message).SendError(error);
5300 #if defined(OS_LINUX)
5301 // Maximization on Linux is asynchronous, so create an observer object to be
5302 // notified upon maximization completion.
5303 new WindowMaximizedObserver(this, reply_message);
5304 #endif // defined(OS_LINUX)
5306 browser->window()->Maximize();
5308 #if !defined(OS_LINUX)
5309 // Send success reply right away for OS's with synchronous maximize command.
5310 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
5311 #endif // !defined(OS_LINUX)
5314 void TestingAutomationProvider::ActivateTabJSON(
5315 DictionaryValue* args,
5316 IPC::Message* reply_message) {
5317 if (SendErrorIfModalDialogActive(this, reply_message))
5320 AutomationJSONReply reply(this, reply_message);
5322 WebContents* web_contents;
5324 if (!GetBrowserAndTabFromJSONArgs(args, &browser, &web_contents, &error)) {
5325 reply.SendError(error);
5328 TabStripModel* tab_strip = browser->tab_strip_model();
5329 tab_strip->ActivateTabAt(tab_strip->GetIndexOfWebContents(web_contents),
5331 reply.SendSuccess(NULL);
5334 void TestingAutomationProvider::IsPageActionVisible(
5335 base::DictionaryValue* args,
5336 IPC::Message* reply_message) {
5337 AutomationJSONReply reply(this, reply_message);
5341 if (!GetTabFromJSONArgs(args, &tab, &error)) {
5342 reply.SendError(error);
5345 Browser* browser = automation_util::GetBrowserForTab(tab);
5347 reply.SendError("Tab does not belong to an open browser");
5350 const Extension* extension;
5351 if (!GetEnabledExtensionFromJSONArgs(
5352 args, "extension_id", browser->profile(), &extension, &error)) {
5353 reply.SendError(error);
5356 ExtensionAction* page_action =
5357 ExtensionActionManager::Get(browser->profile())->
5358 GetPageAction(*extension);
5360 reply.SendError("Extension doesn't have any page action");
5363 EnsureTabSelected(browser, tab);
5365 bool is_visible = false;
5366 LocationBarTesting* loc_bar =
5367 browser->window()->GetLocationBar()->GetLocationBarForTesting();
5368 size_t page_action_visible_count =
5369 static_cast<size_t>(loc_bar->PageActionVisibleCount());
5370 for (size_t i = 0; i < page_action_visible_count; ++i) {
5371 if (loc_bar->GetVisiblePageAction(i) == page_action) {
5376 DictionaryValue dict;
5377 dict.SetBoolean("is_visible", is_visible);
5378 reply.SendSuccess(&dict);
5381 void TestingAutomationProvider::CreateNewAutomationProvider(
5382 DictionaryValue* args,
5383 IPC::Message* reply_message) {
5384 AutomationJSONReply reply(this, reply_message);
5385 std::string channel_id;
5386 if (!args->GetString("channel_id", &channel_id)) {
5387 reply.SendError("'channel_id' missing or invalid");
5391 AutomationProvider* provider = new TestingAutomationProvider(profile_);
5392 provider->DisableInitialLoadObservers();
5393 // TODO(kkania): Remove this when crbug.com/91311 is fixed.
5394 // Named server channels should ideally be created and closed on the file
5395 // thread, within the IPC channel code.
5396 base::ThreadRestrictions::ScopedAllowIO allow_io;
5397 if (!provider->InitializeChannel(
5398 automation::kNamedInterfacePrefix + channel_id)) {
5399 reply.SendError("Failed to initialize channel: " + channel_id);
5402 DCHECK(g_browser_process);
5403 g_browser_process->GetAutomationProviderList()->AddProvider(provider);
5404 reply.SendSuccess(NULL);
5407 void TestingAutomationProvider::WaitForTabCountToBecome(
5409 int target_tab_count,
5410 IPC::Message* reply_message) {
5411 if (!browser_tracker_->ContainsHandle(browser_handle)) {
5412 AutomationMsg_WaitForTabCountToBecome::WriteReplyParams(reply_message,
5414 Send(reply_message);
5418 Browser* browser = browser_tracker_->GetResource(browser_handle);
5420 // The observer will delete itself.
5421 new TabCountChangeObserver(this, browser, reply_message, target_tab_count);
5424 void TestingAutomationProvider::WaitForInfoBarCount(
5426 size_t target_count,
5427 IPC::Message* reply_message) {
5428 if (!tab_tracker_->ContainsHandle(tab_handle)) {
5429 AutomationMsg_WaitForInfoBarCount::WriteReplyParams(reply_message_, false);
5430 Send(reply_message_);
5434 NavigationController* controller = tab_tracker_->GetResource(tab_handle);
5436 AutomationMsg_WaitForInfoBarCount::WriteReplyParams(reply_message_, false);
5437 Send(reply_message_);
5441 // The delegate will delete itself.
5442 new InfoBarCountObserver(this, reply_message,
5443 controller->GetWebContents(), target_count);
5446 void TestingAutomationProvider::WaitForProcessLauncherThreadToGoIdle(
5447 IPC::Message* reply_message) {
5448 new WaitForProcessLauncherThreadToGoIdleObserver(this, reply_message);
5451 void TestingAutomationProvider::OnRemoveProvider() {
5452 if (g_browser_process)
5453 g_browser_process->GetAutomationProviderList()->RemoveProvider(this);
5456 void TestingAutomationProvider::EnsureTabSelected(Browser* browser,
5458 TabStripModel* tab_strip = browser->tab_strip_model();
5459 if (tab_strip->GetActiveWebContents() != tab)
5460 tab_strip->ActivateTabAt(tab_strip->GetIndexOfWebContents(tab), true);