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_service.h"
58 #include "chrome/browser/extensions/extension_system.h"
59 #include "chrome/browser/extensions/extension_tab_util.h"
60 #include "chrome/browser/extensions/extension_util.h"
61 #include "chrome/browser/extensions/launch_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.h"
68 #include "chrome/browser/infobars/infobar_service.h"
69 #include "chrome/browser/lifetime/application_lifetime.h"
70 #include "chrome/browser/notifications/balloon.h"
71 #include "chrome/browser/notifications/balloon_collection.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/extension_constants.h"
117 #include "chrome/common/extensions/manifest_url_handler.h"
118 #include "chrome/common/pref_names.h"
119 #include "chrome/common/render_messages.h"
120 #include "content/public/browser/browser_child_process_host_iterator.h"
121 #include "content/public/browser/child_process_data.h"
122 #include "content/public/browser/favicon_status.h"
123 #include "content/public/browser/geolocation_provider.h"
124 #include "content/public/browser/interstitial_page.h"
125 #include "content/public/browser/interstitial_page_delegate.h"
126 #include "content/public/browser/navigation_entry.h"
127 #include "content/public/browser/notification_service.h"
128 #include "content/public/browser/plugin_service.h"
129 #include "content/public/browser/render_process_host.h"
130 #include "content/public/browser/render_view_host.h"
131 #include "content/public/browser/render_widget_host_view.h"
132 #include "content/public/browser/web_contents.h"
133 #include "content/public/common/child_process_host.h"
134 #include "content/public/common/common_param_traits.h"
135 #include "content/public/common/drop_data.h"
136 #include "content/public/common/geoposition.h"
137 #include "content/public/common/ssl_status.h"
138 #include "content/public/common/webplugininfo.h"
139 #include "extensions/browser/process_manager.h"
140 #include "extensions/browser/view_type_utils.h"
141 #include "extensions/common/extension.h"
142 #include "extensions/common/extension_set.h"
143 #include "extensions/common/manifest_handlers/background_info.h"
144 #include "extensions/common/permissions/permission_set.h"
145 #include "extensions/common/permissions/permissions_data.h"
146 #include "extensions/common/url_pattern.h"
147 #include "extensions/common/url_pattern_set.h"
148 #include "net/cookies/cookie_store.h"
149 #include "third_party/WebKit/public/web/WebInputEvent.h"
150 #include "ui/base/ui_base_types.h"
151 #include "ui/events/event_constants.h"
152 #include "ui/events/keycodes/keyboard_codes.h"
154 #if defined(ENABLE_CONFIGURATION_POLICY)
155 #include "components/policy/core/common/policy_service.h"
158 #if defined(OS_CHROMEOS)
159 #include "chromeos/dbus/dbus_thread_manager.h"
161 #include "chrome/browser/notifications/balloon_notification_ui_manager.h"
164 #if defined(OS_MACOSX)
165 #include <mach/mach.h>
166 #include <mach/mach_vm.h>
169 using automation_util::SendErrorIfModalDialogActive;
170 using content::BrowserChildProcessHostIterator;
171 using content::BrowserContext;
172 using content::BrowserThread;
173 using content::ChildProcessHost;
174 using content::DownloadItem;
175 using content::DownloadManager;
176 using content::InterstitialPage;
177 using content::NativeWebKeyboardEvent;
178 using content::NavigationController;
179 using content::NavigationEntry;
180 using content::OpenURLParams;
181 using content::PluginService;
182 using content::Referrer;
183 using content::RenderViewHost;
184 using content::SSLStatus;
185 using content::WebContents;
186 using extensions::Extension;
187 using extensions::ExtensionActionManager;
188 using extensions::ExtensionList;
189 using extensions::Manifest;
193 // Helper to reply asynchronously if |automation| is still valid.
194 void SendSuccessReply(base::WeakPtr<AutomationProvider> automation,
195 IPC::Message* reply_message) {
196 if (automation.get())
197 AutomationJSONReply(automation.get(), reply_message).SendSuccess(NULL);
200 // Helper to process the result of CanEnablePlugin.
201 void DidEnablePlugin(base::WeakPtr<AutomationProvider> automation,
202 IPC::Message* reply_message,
203 const base::FilePath::StringType& path,
204 const std::string& error_msg,
207 SendSuccessReply(automation, reply_message);
209 if (automation.get()) {
210 AutomationJSONReply(automation.get(), reply_message)
211 .SendError(base::StringPrintf(error_msg.c_str(), path.c_str()));
216 // Helper to resolve the overloading of PostTask.
217 void PostTask(BrowserThread::ID id, const base::Closure& callback) {
218 BrowserThread::PostTask(id, FROM_HERE, callback);
221 class AutomationInterstitialPage : public content::InterstitialPageDelegate {
223 AutomationInterstitialPage(WebContents* tab,
225 const std::string& contents)
226 : contents_(contents) {
227 interstitial_page_ = InterstitialPage::Create(tab, true, url, this);
228 interstitial_page_->Show();
231 virtual std::string GetHTMLContents() OVERRIDE { return contents_; }
234 const std::string contents_;
235 InterstitialPage* interstitial_page_; // Owns us.
237 DISALLOW_COPY_AND_ASSIGN(AutomationInterstitialPage);
242 const int TestingAutomationProvider::kSynchronousCommands[] = {
245 IDC_SELECT_PREVIOUS_TAB,
246 IDC_SHOW_BOOKMARK_MANAGER,
249 TestingAutomationProvider::TestingAutomationProvider(Profile* profile)
250 : AutomationProvider(profile) {
251 BrowserList::AddObserver(this);
252 registrar_.Add(this, chrome::NOTIFICATION_SESSION_END,
253 content::NotificationService::AllSources());
254 #if defined(OS_CHROMEOS)
255 AddChromeosObservers();
259 TestingAutomationProvider::~TestingAutomationProvider() {
260 #if defined(OS_CHROMEOS)
261 RemoveChromeosObservers();
263 BrowserList::RemoveObserver(this);
266 IPC::Channel::Mode TestingAutomationProvider::GetChannelMode(
267 bool use_named_interface) {
268 if (use_named_interface)
269 #if defined(OS_POSIX)
270 return IPC::Channel::MODE_OPEN_NAMED_SERVER;
272 return IPC::Channel::MODE_NAMED_SERVER;
275 return IPC::Channel::MODE_CLIENT;
278 void TestingAutomationProvider::OnBrowserAdded(Browser* browser) {
281 void TestingAutomationProvider::OnBrowserRemoved(Browser* browser) {
282 #if !defined(OS_CHROMEOS) && !defined(OS_MACOSX)
283 // For backwards compatibility with the testing automation interface, we
284 // want the automation provider (and hence the process) to go away when the
285 // last browser goes away.
286 // The automation layer doesn't support non-native desktops.
287 if (BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE)->empty() &&
288 !CommandLine::ForCurrentProcess()->HasSwitch(
289 switches::kKeepAliveForTest)) {
290 // If you change this, update Observer for chrome::SESSION_END
292 base::MessageLoop::current()->PostTask(
294 base::Bind(&TestingAutomationProvider::OnRemoveProvider, this));
296 #endif // !defined(OS_CHROMEOS) && !defined(OS_MACOSX)
299 void TestingAutomationProvider::Observe(
301 const content::NotificationSource& source,
302 const content::NotificationDetails& details) {
303 DCHECK(type == chrome::NOTIFICATION_SESSION_END);
304 // OnBrowserRemoved does a ReleaseLater. When session end is received we exit
305 // before the task runs resulting in this object not being deleted. This
306 // Release balance out the Release scheduled by OnBrowserRemoved.
310 bool TestingAutomationProvider::OnMessageReceived(
311 const IPC::Message& message) {
312 base::ThreadRestrictions::ScopedAllowWait allow_wait;
314 bool deserialize_success = true;
315 IPC_BEGIN_MESSAGE_MAP_EX(TestingAutomationProvider,
318 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_CloseBrowser, CloseBrowser)
319 IPC_MESSAGE_HANDLER(AutomationMsg_ActivateTab, ActivateTab)
320 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_AppendTab, AppendTab)
321 IPC_MESSAGE_HANDLER(AutomationMsg_GetMachPortCount, GetMachPortCount)
322 IPC_MESSAGE_HANDLER(AutomationMsg_ActiveTabIndex, GetActiveTabIndex)
323 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_CloseTab, CloseTab)
324 IPC_MESSAGE_HANDLER(AutomationMsg_GetCookies, GetCookies)
325 IPC_MESSAGE_HANDLER_DELAY_REPLY(
326 AutomationMsg_NavigateToURLBlockUntilNavigationsComplete,
327 NavigateToURLBlockUntilNavigationsComplete)
328 IPC_MESSAGE_HANDLER(AutomationMsg_NavigationAsync, NavigationAsync)
329 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_Reload, Reload)
330 IPC_MESSAGE_HANDLER(AutomationMsg_BrowserWindowCount, GetBrowserWindowCount)
331 IPC_MESSAGE_HANDLER(AutomationMsg_NormalBrowserWindowCount,
332 GetNormalBrowserWindowCount)
333 IPC_MESSAGE_HANDLER(AutomationMsg_BrowserWindow, GetBrowserWindow)
334 IPC_MESSAGE_HANDLER(AutomationMsg_WindowExecuteCommandAsync,
335 ExecuteBrowserCommandAsync)
336 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WindowExecuteCommand,
337 ExecuteBrowserCommand)
338 IPC_MESSAGE_HANDLER(AutomationMsg_TerminateSession, TerminateSession)
339 IPC_MESSAGE_HANDLER(AutomationMsg_WindowViewBounds, WindowGetViewBounds)
340 IPC_MESSAGE_HANDLER(AutomationMsg_SetWindowBounds, SetWindowBounds)
341 IPC_MESSAGE_HANDLER(AutomationMsg_TabCount, GetTabCount)
342 IPC_MESSAGE_HANDLER(AutomationMsg_Type, GetType)
343 IPC_MESSAGE_HANDLER(AutomationMsg_Tab, GetTab)
344 IPC_MESSAGE_HANDLER(AutomationMsg_TabTitle, GetTabTitle)
345 IPC_MESSAGE_HANDLER(AutomationMsg_TabIndex, GetTabIndex)
346 IPC_MESSAGE_HANDLER(AutomationMsg_TabURL, GetTabURL)
347 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_DomOperation,
349 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_OpenNewBrowserWindowOfType,
350 OpenNewBrowserWindowOfType)
351 IPC_MESSAGE_HANDLER(AutomationMsg_WindowForBrowser, GetWindowForBrowser)
352 IPC_MESSAGE_HANDLER(AutomationMsg_GetMetricEventDuration,
353 GetMetricEventDuration)
354 IPC_MESSAGE_HANDLER(AutomationMsg_BringBrowserToFront, BringBrowserToFront)
355 IPC_MESSAGE_HANDLER(AutomationMsg_FindWindowVisibility,
356 GetFindWindowVisibility)
357 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForBookmarkModelToLoad,
358 WaitForBookmarkModelToLoad)
359 IPC_MESSAGE_HANDLER_DELAY_REPLY(
360 AutomationMsg_WaitForBrowserWindowCountToBecome,
361 WaitForBrowserWindowCountToBecome)
362 IPC_MESSAGE_HANDLER_DELAY_REPLY(
363 AutomationMsg_GoBackBlockUntilNavigationsComplete,
364 GoBackBlockUntilNavigationsComplete)
365 IPC_MESSAGE_HANDLER_DELAY_REPLY(
366 AutomationMsg_GoForwardBlockUntilNavigationsComplete,
367 GoForwardBlockUntilNavigationsComplete)
368 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_SendJSONRequest,
369 SendJSONRequestWithBrowserIndex)
370 IPC_MESSAGE_HANDLER_DELAY_REPLY(
371 AutomationMsg_SendJSONRequestWithBrowserHandle,
372 SendJSONRequestWithBrowserHandle)
373 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForTabCountToBecome,
374 WaitForTabCountToBecome)
375 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForInfoBarCount,
377 IPC_MESSAGE_HANDLER_DELAY_REPLY(
378 AutomationMsg_WaitForProcessLauncherThreadToGoIdle,
379 WaitForProcessLauncherThreadToGoIdle)
381 IPC_MESSAGE_UNHANDLED(
382 handled = AutomationProvider::OnMessageReceived(message))
383 IPC_END_MESSAGE_MAP_EX()
384 if (!deserialize_success)
385 OnMessageDeserializationFailure();
389 void TestingAutomationProvider::OnChannelError() {
390 if (!reinitialize_on_channel_error_ &&
391 browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID) {
392 chrome::AttemptExit();
394 AutomationProvider::OnChannelError();
397 void TestingAutomationProvider::CloseBrowser(int browser_handle,
398 IPC::Message* reply_message) {
399 if (!browser_tracker_->ContainsHandle(browser_handle))
402 Browser* browser = browser_tracker_->GetResource(browser_handle);
403 new BrowserClosedNotificationObserver(browser, this, reply_message, false);
404 browser->window()->Close();
407 void TestingAutomationProvider::ActivateTab(int handle,
411 if (browser_tracker_->ContainsHandle(handle) && at_index > -1) {
412 Browser* browser = browser_tracker_->GetResource(handle);
413 if (at_index >= 0 && at_index < browser->tab_strip_model()->count()) {
414 browser->tab_strip_model()->ActivateTabAt(at_index, true);
420 void TestingAutomationProvider::AppendTab(int handle,
422 IPC::Message* reply_message) {
423 int append_tab_response = -1; // -1 is the error code
424 TabAppendedNotificationObserver* observer = NULL;
426 if (browser_tracker_->ContainsHandle(handle)) {
427 Browser* browser = browser_tracker_->GetResource(handle);
428 observer = new TabAppendedNotificationObserver(browser, this,
429 reply_message, false);
430 WebContents* contents =
431 chrome::AddSelectedTabWithURL(browser, url,
432 content::PAGE_TRANSITION_TYPED);
434 append_tab_response = GetIndexForNavigationController(
435 &contents->GetController(), browser);
439 if (append_tab_response < 0) {
440 // Appending tab failed. Clean up and send failure response.
445 AutomationMsg_AppendTab::WriteReplyParams(reply_message,
446 append_tab_response);
451 void TestingAutomationProvider::GetMachPortCount(int* port_count) {
452 #if defined(OS_MACOSX)
453 mach_port_name_array_t names;
454 mach_msg_type_number_t names_count;
455 mach_port_type_array_t types;
456 mach_msg_type_number_t types_count;
458 mach_port_t port = mach_task_self();
460 // A friendlier interface would allow NULL buffers to only get the counts.
461 kern_return_t kr = mach_port_names(port, &names, &names_count,
462 &types, &types_count);
463 if (kr != KERN_SUCCESS) {
468 // The documentation states this is an invariant.
469 DCHECK_EQ(names_count, types_count);
470 *port_count = names_count;
472 mach_vm_deallocate(port, reinterpret_cast<mach_vm_address_t>(names),
473 names_count * sizeof(mach_port_name_array_t));
474 mach_vm_deallocate(port, reinterpret_cast<mach_vm_address_t>(types),
475 types_count * sizeof(mach_port_type_array_t));
481 void TestingAutomationProvider::GetActiveTabIndex(int handle,
482 int* active_tab_index) {
483 *active_tab_index = -1; // -1 is the error code
484 if (browser_tracker_->ContainsHandle(handle)) {
485 Browser* browser = browser_tracker_->GetResource(handle);
486 *active_tab_index = browser->tab_strip_model()->active_index();
490 void TestingAutomationProvider::CloseTab(int tab_handle,
491 bool wait_until_closed,
492 IPC::Message* reply_message) {
493 if (tab_tracker_->ContainsHandle(tab_handle)) {
494 NavigationController* controller = tab_tracker_->GetResource(tab_handle);
495 Browser* browser = chrome::FindBrowserWithWebContents(
496 controller->GetWebContents());
498 new TabClosedNotificationObserver(this, wait_until_closed, reply_message,
500 chrome::CloseWebContents(browser, controller->GetWebContents(), false);
504 AutomationMsg_CloseTab::WriteReplyParams(reply_message, false);
508 void TestingAutomationProvider::GetCookies(const GURL& url, int handle,
510 std::string* value) {
511 WebContents* contents = tab_tracker_->ContainsHandle(handle) ?
512 tab_tracker_->GetResource(handle)->GetWebContents() : NULL;
513 automation_util::GetCookies(url, contents, value_size, value);
516 void TestingAutomationProvider::NavigateToURLBlockUntilNavigationsComplete(
517 int handle, const GURL& url, int number_of_navigations,
518 IPC::Message* reply_message) {
519 if (tab_tracker_->ContainsHandle(handle)) {
520 NavigationController* tab = tab_tracker_->GetResource(handle);
522 // Simulate what a user would do. Activate the tab and then navigate.
523 // We could allow navigating in a background tab in future.
524 Browser* browser = FindAndActivateTab(tab);
527 new NavigationNotificationObserver(tab, this, reply_message,
528 number_of_navigations, false, false);
530 // TODO(darin): avoid conversion to GURL.
531 OpenURLParams params(
532 url, Referrer(), CURRENT_TAB,
533 content::PageTransitionFromInt(
534 content::PAGE_TRANSITION_TYPED |
535 content::PAGE_TRANSITION_FROM_ADDRESS_BAR),
537 browser->OpenURL(params);
542 AutomationMsg_NavigateToURLBlockUntilNavigationsComplete::WriteReplyParams(
543 reply_message, AUTOMATION_MSG_NAVIGATION_ERROR);
547 void TestingAutomationProvider::NavigationAsync(int handle,
552 if (tab_tracker_->ContainsHandle(handle)) {
553 NavigationController* tab = tab_tracker_->GetResource(handle);
555 // Simulate what a user would do. Activate the tab and then navigate.
556 // We could allow navigating in a background tab in future.
557 Browser* browser = FindAndActivateTab(tab);
560 // Don't add any listener unless a callback mechanism is desired.
561 // TODO(vibhor): Do this if such a requirement arises in future.
562 OpenURLParams params(
563 url, Referrer(), CURRENT_TAB,
564 content::PageTransitionFromInt(
565 content::PAGE_TRANSITION_TYPED |
566 content::PAGE_TRANSITION_FROM_ADDRESS_BAR),
568 browser->OpenURL(params);
574 void TestingAutomationProvider::Reload(int handle,
575 IPC::Message* reply_message) {
576 if (tab_tracker_->ContainsHandle(handle)) {
577 NavigationController* tab = tab_tracker_->GetResource(handle);
578 Browser* browser = FindAndActivateTab(tab);
579 if (chrome::IsCommandEnabled(browser, IDC_RELOAD)) {
580 new NavigationNotificationObserver(
581 tab, this, reply_message, 1, false, false);
582 chrome::ExecuteCommand(browser, IDC_RELOAD);
587 AutomationMsg_Reload::WriteReplyParams(
588 reply_message, AUTOMATION_MSG_NAVIGATION_ERROR);
592 void TestingAutomationProvider::GetBrowserWindowCount(int* window_count) {
593 // The automation layer doesn't support non-native desktops.
594 *window_count = static_cast<int>(BrowserList::GetInstance(
595 chrome::HOST_DESKTOP_TYPE_NATIVE)->size());
598 void TestingAutomationProvider::GetNormalBrowserWindowCount(int* window_count) {
599 *window_count = static_cast<int>(chrome::GetTabbedBrowserCount(
600 profile_, chrome::HOST_DESKTOP_TYPE_NATIVE));
603 void TestingAutomationProvider::GetBrowserWindow(int index, int* handle) {
605 Browser* browser = automation_util::GetBrowserAt(index);
607 *handle = browser_tracker_->Add(browser);
610 void TestingAutomationProvider::ExecuteBrowserCommandAsync(int handle,
614 if (!browser_tracker_->ContainsHandle(handle)) {
615 LOG(WARNING) << "Browser tracker does not contain handle: " << handle;
618 Browser* browser = browser_tracker_->GetResource(handle);
619 if (!chrome::SupportsCommand(browser, command)) {
620 LOG(WARNING) << "Browser does not support command: " << command;
623 if (!chrome::IsCommandEnabled(browser, command)) {
624 LOG(WARNING) << "Browser command not enabled: " << command;
627 chrome::ExecuteCommand(browser, command);
631 void TestingAutomationProvider::ExecuteBrowserCommand(
632 int handle, int command, IPC::Message* reply_message) {
633 if (browser_tracker_->ContainsHandle(handle)) {
634 Browser* browser = browser_tracker_->GetResource(handle);
635 if (chrome::SupportsCommand(browser, command) &&
636 chrome::IsCommandEnabled(browser, command)) {
637 // First check if we can handle the command without using an observer.
638 for (size_t i = 0; i < arraysize(kSynchronousCommands); i++) {
639 if (command == kSynchronousCommands[i]) {
640 chrome::ExecuteCommand(browser, command);
641 AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message,
648 // Use an observer if we have one, otherwise fail.
649 if (ExecuteBrowserCommandObserver::CreateAndRegisterObserver(
650 this, browser, command, reply_message, false)) {
651 chrome::ExecuteCommand(browser, command);
656 AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message, false);
660 void TestingAutomationProvider::WebkitMouseClick(base::DictionaryValue* args,
661 IPC::Message* reply_message) {
662 if (SendErrorIfModalDialogActive(this, reply_message))
665 RenderViewHost* view;
667 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
668 AutomationJSONReply(this, reply_message).SendError(error);
672 blink::WebMouseEvent mouse_event;
673 if (!args->GetInteger("x", &mouse_event.x) ||
674 !args->GetInteger("y", &mouse_event.y)) {
675 AutomationJSONReply(this, reply_message)
676 .SendError("(X,Y) coordinates missing or invalid");
681 if (!args->GetInteger("button", &button)) {
682 AutomationJSONReply(this, reply_message)
683 .SendError("Mouse button missing or invalid");
686 if (button == automation::kLeftButton) {
687 mouse_event.button = blink::WebMouseEvent::ButtonLeft;
688 } else if (button == automation::kRightButton) {
689 mouse_event.button = blink::WebMouseEvent::ButtonRight;
690 } else if (button == automation::kMiddleButton) {
691 mouse_event.button = blink::WebMouseEvent::ButtonMiddle;
693 AutomationJSONReply(this, reply_message)
694 .SendError("Invalid button press requested");
698 mouse_event.type = blink::WebInputEvent::MouseDown;
699 mouse_event.clickCount = 1;
701 view->ForwardMouseEvent(mouse_event);
703 mouse_event.type = blink::WebInputEvent::MouseUp;
704 new InputEventAckNotificationObserver(this, reply_message, mouse_event.type,
706 view->ForwardMouseEvent(mouse_event);
709 void TestingAutomationProvider::WebkitMouseMove(
710 base::DictionaryValue* args, IPC::Message* reply_message) {
711 if (SendErrorIfModalDialogActive(this, reply_message))
714 RenderViewHost* view;
716 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
717 AutomationJSONReply(this, reply_message).SendError(error);
721 blink::WebMouseEvent mouse_event;
722 if (!args->GetInteger("x", &mouse_event.x) ||
723 !args->GetInteger("y", &mouse_event.y)) {
724 AutomationJSONReply(this, reply_message)
725 .SendError("(X,Y) coordinates missing or invalid");
729 mouse_event.type = blink::WebInputEvent::MouseMove;
730 new InputEventAckNotificationObserver(this, reply_message, mouse_event.type,
732 view->ForwardMouseEvent(mouse_event);
735 void TestingAutomationProvider::WebkitMouseDrag(base::DictionaryValue* args,
736 IPC::Message* reply_message) {
737 if (SendErrorIfModalDialogActive(this, reply_message))
740 RenderViewHost* view;
742 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
743 AutomationJSONReply(this, reply_message).SendError(error);
747 blink::WebMouseEvent mouse_event;
748 int start_x, start_y, end_x, end_y;
749 if (!args->GetInteger("start_x", &start_x) ||
750 !args->GetInteger("start_y", &start_y) ||
751 !args->GetInteger("end_x", &end_x) ||
752 !args->GetInteger("end_y", &end_y)) {
753 AutomationJSONReply(this, reply_message)
754 .SendError("Invalid start/end positions");
758 mouse_event.type = blink::WebInputEvent::MouseMove;
759 // Step 1- Move the mouse to the start position.
760 mouse_event.x = start_x;
761 mouse_event.y = start_y;
762 view->ForwardMouseEvent(mouse_event);
764 // Step 2- Left click mouse down, the mouse button is fixed.
765 mouse_event.type = blink::WebInputEvent::MouseDown;
766 mouse_event.button = blink::WebMouseEvent::ButtonLeft;
767 mouse_event.clickCount = 1;
768 view->ForwardMouseEvent(mouse_event);
770 // Step 3 - Move the mouse to the end position.
771 mouse_event.type = blink::WebInputEvent::MouseMove;
772 mouse_event.x = end_x;
773 mouse_event.y = end_y;
774 mouse_event.clickCount = 0;
775 view->ForwardMouseEvent(mouse_event);
777 // Step 4 - Release the left mouse button.
778 mouse_event.type = blink::WebInputEvent::MouseUp;
779 mouse_event.clickCount = 1;
780 new InputEventAckNotificationObserver(this, reply_message, mouse_event.type,
782 view->ForwardMouseEvent(mouse_event);
785 void TestingAutomationProvider::WebkitMouseButtonDown(
786 base::DictionaryValue* args, IPC::Message* reply_message) {
787 if (SendErrorIfModalDialogActive(this, reply_message))
790 RenderViewHost* view;
792 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
793 AutomationJSONReply(this, reply_message).SendError(error);
797 blink::WebMouseEvent mouse_event;
798 if (!args->GetInteger("x", &mouse_event.x) ||
799 !args->GetInteger("y", &mouse_event.y)) {
800 AutomationJSONReply(this, reply_message)
801 .SendError("(X,Y) coordinates missing or invalid");
805 mouse_event.type = blink::WebInputEvent::MouseDown;
806 mouse_event.button = blink::WebMouseEvent::ButtonLeft;
807 mouse_event.clickCount = 1;
808 new InputEventAckNotificationObserver(this, reply_message, mouse_event.type,
810 view->ForwardMouseEvent(mouse_event);
813 void TestingAutomationProvider::WebkitMouseButtonUp(
814 base::DictionaryValue* args, IPC::Message* reply_message) {
815 if (SendErrorIfModalDialogActive(this, reply_message))
818 RenderViewHost* view;
820 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
821 AutomationJSONReply(this, reply_message).SendError(error);
825 blink::WebMouseEvent mouse_event;
826 if (!args->GetInteger("x", &mouse_event.x) ||
827 !args->GetInteger("y", &mouse_event.y)) {
828 AutomationJSONReply(this, reply_message)
829 .SendError("(X,Y) coordinates missing or invalid");
833 mouse_event.type = blink::WebInputEvent::MouseUp;
834 mouse_event.button = blink::WebMouseEvent::ButtonLeft;
835 mouse_event.clickCount = 1;
836 new InputEventAckNotificationObserver(this, reply_message, mouse_event.type,
838 view->ForwardMouseEvent(mouse_event);
841 void TestingAutomationProvider::WebkitMouseDoubleClick(
842 base::DictionaryValue* args, IPC::Message* reply_message) {
843 if (SendErrorIfModalDialogActive(this, reply_message))
846 RenderViewHost* view;
848 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
849 AutomationJSONReply(this, reply_message).SendError(error);
853 blink::WebMouseEvent mouse_event;
854 if (!args->GetInteger("x", &mouse_event.x) ||
855 !args->GetInteger("y", &mouse_event.y)) {
856 AutomationJSONReply(this, reply_message)
857 .SendError("(X,Y) coordinates missing or invalid");
861 mouse_event.type = blink::WebInputEvent::MouseDown;
862 mouse_event.button = blink::WebMouseEvent::ButtonLeft;
863 mouse_event.clickCount = 1;
864 view->ForwardMouseEvent(mouse_event);
866 mouse_event.type = blink::WebInputEvent::MouseUp;
867 new InputEventAckNotificationObserver(this, reply_message, mouse_event.type,
869 view->ForwardMouseEvent(mouse_event);
871 mouse_event.type = blink::WebInputEvent::MouseDown;
872 mouse_event.clickCount = 2;
873 view->ForwardMouseEvent(mouse_event);
875 mouse_event.type = blink::WebInputEvent::MouseUp;
876 view->ForwardMouseEvent(mouse_event);
879 void TestingAutomationProvider::DragAndDropFilePaths(
880 base::DictionaryValue* args, IPC::Message* reply_message) {
881 if (SendErrorIfModalDialogActive(this, reply_message))
884 RenderViewHost* view;
886 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
887 AutomationJSONReply(this, reply_message).SendError(error);
892 if (!args->GetInteger("x", &x) || !args->GetInteger("y", &y)) {
893 AutomationJSONReply(this, reply_message)
894 .SendError("(X,Y) coordinates missing or invalid");
898 base::ListValue* paths = NULL;
899 if (!args->GetList("paths", &paths)) {
900 AutomationJSONReply(this, reply_message)
901 .SendError("'paths' missing or invalid");
905 // Emulate drag and drop to set the file paths to the file upload control.
906 content::DropData drop_data;
907 for (size_t path_index = 0; path_index < paths->GetSize(); ++path_index) {
909 if (!paths->GetString(path_index, &path)) {
910 AutomationJSONReply(this, reply_message)
911 .SendError("'paths' contains a non-string type");
915 drop_data.filenames.push_back(
916 content::DropData::FileInfo(path, base::string16()));
919 const gfx::Point client(x, y);
920 // We don't set any values in screen variable because DragTarget*** ignore the
922 const gfx::Point screen;
925 operations |= blink::WebDragOperationCopy;
926 operations |= blink::WebDragOperationLink;
927 operations |= blink::WebDragOperationMove;
929 view->DragTargetDragEnter(
930 drop_data, client, screen,
931 static_cast<blink::WebDragOperationsMask>(operations), 0);
932 new DragTargetDropAckNotificationObserver(this, reply_message);
933 view->DragTargetDrop(client, screen, 0);
936 void TestingAutomationProvider::GetTabCount(int handle, int* tab_count) {
937 *tab_count = -1; // -1 is the error code
939 if (browser_tracker_->ContainsHandle(handle)) {
940 Browser* browser = browser_tracker_->GetResource(handle);
941 *tab_count = browser->tab_strip_model()->count();
945 void TestingAutomationProvider::GetType(int handle, int* type_as_int) {
946 *type_as_int = -1; // -1 is the error code
948 if (browser_tracker_->ContainsHandle(handle)) {
949 Browser* browser = browser_tracker_->GetResource(handle);
950 *type_as_int = static_cast<int>(browser->type());
954 void TestingAutomationProvider::GetTab(int win_handle,
958 if (browser_tracker_->ContainsHandle(win_handle) && (tab_index >= 0)) {
959 Browser* browser = browser_tracker_->GetResource(win_handle);
960 if (tab_index < browser->tab_strip_model()->count()) {
961 WebContents* web_contents =
962 browser->tab_strip_model()->GetWebContentsAt(tab_index);
963 *tab_handle = tab_tracker_->Add(&web_contents->GetController());
968 void TestingAutomationProvider::GetTabTitle(int handle,
969 int* title_string_size,
970 std::wstring* title) {
971 *title_string_size = -1; // -1 is the error code
972 if (tab_tracker_->ContainsHandle(handle)) {
973 NavigationController* tab = tab_tracker_->GetResource(handle);
974 NavigationEntry* entry = tab->GetActiveEntry();
976 *title = base::UTF16ToWideHack(entry->GetTitleForDisplay(std::string()));
978 *title = std::wstring();
980 *title_string_size = static_cast<int>(title->size());
984 void TestingAutomationProvider::GetTabIndex(int handle, int* tabstrip_index) {
985 *tabstrip_index = -1; // -1 is the error code
987 if (tab_tracker_->ContainsHandle(handle)) {
988 NavigationController* tab = tab_tracker_->GetResource(handle);
989 Browser* browser = chrome::FindBrowserWithWebContents(
990 tab->GetWebContents());
991 *tabstrip_index = browser->tab_strip_model()->GetIndexOfWebContents(
992 tab->GetWebContents());
996 void TestingAutomationProvider::GetTabURL(int handle,
1000 if (tab_tracker_->ContainsHandle(handle)) {
1001 NavigationController* tab = tab_tracker_->GetResource(handle);
1002 // Return what the user would see in the location bar.
1003 *url = tab->GetActiveEntry()->GetVirtualURL();
1008 void TestingAutomationProvider::ExecuteJavascriptInRenderViewFrame(
1009 const base::string16& frame_xpath,
1010 const base::string16& script,
1011 IPC::Message* reply_message,
1012 RenderViewHost* render_view_host) {
1013 // Set the routing id of this message with the controller.
1014 // This routing id needs to be remembered for the reverse
1015 // communication while sending back the response of
1016 // this javascript execution.
1017 render_view_host->ExecuteJavascriptInWebFrame(
1019 base::ASCIIToUTF16("window.domAutomationController.setAutomationId(0);"));
1020 render_view_host->ExecuteJavascriptInWebFrame(
1021 frame_xpath, script);
1024 void TestingAutomationProvider::ExecuteJavascript(
1026 const std::wstring& frame_xpath,
1027 const std::wstring& script,
1028 IPC::Message* reply_message) {
1029 WebContents* web_contents = GetWebContentsForHandle(handle, NULL);
1030 if (!web_contents) {
1031 AutomationMsg_DomOperation::WriteReplyParams(reply_message, std::string());
1032 Send(reply_message);
1036 new DomOperationMessageSender(this, reply_message, false);
1037 ExecuteJavascriptInRenderViewFrame(base::WideToUTF16Hack(frame_xpath),
1038 base::WideToUTF16Hack(script),
1040 web_contents->GetRenderViewHost());
1043 // Sample json input: { "command": "OpenNewBrowserWindowWithNewProfile" }
1044 // Sample output: {}
1045 void TestingAutomationProvider::OpenNewBrowserWindowWithNewProfile(
1046 base::DictionaryValue* args, IPC::Message* reply_message) {
1047 ProfileManager* profile_manager = g_browser_process->profile_manager();
1048 new BrowserOpenedWithNewProfileNotificationObserver(this, reply_message);
1049 profile_manager->CreateMultiProfileAsync(
1050 base::string16(), base::string16(),
1051 ProfileManager::CreateCallback(), std::string());
1054 // Sample json input: { "command": "GetMultiProfileInfo" }
1055 // See GetMultiProfileInfo() in pyauto.py for sample output.
1056 void TestingAutomationProvider::GetMultiProfileInfo(
1057 base::DictionaryValue* args, IPC::Message* reply_message) {
1058 scoped_ptr<base::DictionaryValue> return_value(new base::DictionaryValue);
1059 ProfileManager* profile_manager = g_browser_process->profile_manager();
1060 const ProfileInfoCache& profile_info_cache =
1061 profile_manager->GetProfileInfoCache();
1062 return_value->SetBoolean("enabled", profiles::IsMultipleProfilesEnabled());
1064 base::ListValue* profiles = new base::ListValue;
1065 for (size_t index = 0; index < profile_info_cache.GetNumberOfProfiles();
1067 base::DictionaryValue* item = new base::DictionaryValue;
1068 item->SetString("name", profile_info_cache.GetNameOfProfileAtIndex(index));
1069 item->SetString("path",
1070 profile_info_cache.GetPathOfProfileAtIndex(index).value());
1071 profiles->Append(item);
1073 return_value->Set("profiles", profiles);
1074 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
1077 void TestingAutomationProvider::OpenNewBrowserWindowOfType(
1078 int type, bool show, IPC::Message* reply_message) {
1079 new BrowserOpenedNotificationObserver(this, reply_message, false);
1080 // We may have no current browser windows open so don't rely on
1081 // asking an existing browser to execute the IDC_NEWWINDOW command.
1082 Browser* browser = new Browser(
1083 Browser::CreateParams(static_cast<Browser::Type>(type), profile_,
1084 chrome::HOST_DESKTOP_TYPE_NATIVE));
1085 chrome::AddTabAt(browser, GURL(), -1, true);
1087 browser->window()->Show();
1090 void TestingAutomationProvider::OpenNewBrowserWindow(
1091 base::DictionaryValue* args,
1092 IPC::Message* reply_message) {
1094 if (!args->GetBoolean("show", &show)) {
1095 AutomationJSONReply(this, reply_message)
1096 .SendError("'show' missing or invalid.");
1099 new BrowserOpenedNotificationObserver(this, reply_message, true);
1100 Browser* browser = new Browser(
1101 Browser::CreateParams(Browser::TYPE_TABBED, profile_,
1102 chrome::HOST_DESKTOP_TYPE_NATIVE));
1103 chrome::AddTabAt(browser, GURL(), -1, true);
1105 browser->window()->Show();
1108 void TestingAutomationProvider::GetBrowserWindowCountJSON(
1109 base::DictionaryValue* args,
1110 IPC::Message* reply_message) {
1111 base::DictionaryValue dict;
1112 // The automation layer doesn't support non-native desktops.
1113 dict.SetInteger("count",
1114 static_cast<int>(BrowserList::GetInstance(
1115 chrome::HOST_DESKTOP_TYPE_NATIVE)->size()));
1116 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
1119 void TestingAutomationProvider::CloseBrowserWindow(
1120 base::DictionaryValue* args,
1121 IPC::Message* reply_message) {
1122 AutomationJSONReply reply(this, reply_message);
1124 std::string error_msg;
1125 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
1126 reply.SendError(error_msg);
1129 new BrowserClosedNotificationObserver(browser, this, reply_message, true);
1130 browser->window()->Close();
1133 void TestingAutomationProvider::OpenProfileWindow(
1134 base::DictionaryValue* args, IPC::Message* reply_message) {
1135 ProfileManager* profile_manager = g_browser_process->profile_manager();
1136 base::FilePath::StringType path;
1137 if (!args->GetString("path", &path)) {
1138 AutomationJSONReply(this, reply_message).SendError(
1139 "Invalid or missing arg: 'path'");
1142 Profile* profile = profile_manager->GetProfileByPath(base::FilePath(path));
1144 AutomationJSONReply(this, reply_message).SendError(
1145 base::StringPrintf("Invalid profile path: %s", path.c_str()));
1149 if (!args->GetInteger("num_loads", &num_loads)) {
1150 AutomationJSONReply(this, reply_message).SendError(
1151 "Invalid or missing arg: 'num_loads'");
1154 new BrowserOpenedWithExistingProfileNotificationObserver(
1155 this, reply_message, num_loads);
1156 profiles::FindOrCreateNewWindowForProfile(
1158 chrome::startup::IS_NOT_PROCESS_STARTUP,
1159 chrome::startup::IS_NOT_FIRST_RUN,
1160 chrome::HOST_DESKTOP_TYPE_NATIVE,
1164 void TestingAutomationProvider::GetWindowForBrowser(int browser_handle,
1170 if (browser_tracker_->ContainsHandle(browser_handle)) {
1171 Browser* browser = browser_tracker_->GetResource(browser_handle);
1172 gfx::NativeWindow win = browser->window()->GetNativeWindow();
1173 // Add() returns the existing handle for the resource if any.
1174 *handle = window_tracker_->Add(win);
1179 void TestingAutomationProvider::GetMetricEventDuration(
1180 const std::string& event_name,
1182 *duration_ms = metric_event_duration_observer_->GetEventDurationMs(
1186 void TestingAutomationProvider::BringBrowserToFront(int browser_handle,
1189 if (browser_tracker_->ContainsHandle(browser_handle)) {
1190 Browser* browser = browser_tracker_->GetResource(browser_handle);
1191 browser->window()->Activate();
1196 void TestingAutomationProvider::GetFindWindowVisibility(int handle,
1199 Browser* browser = browser_tracker_->GetResource(handle);
1201 FindBarTesting* find_bar =
1202 browser->GetFindBarController()->find_bar()->GetFindBarTesting();
1203 find_bar->GetFindBarWindowInfo(NULL, visible);
1207 // Bookmark bar visibility is based on the pref (e.g. is it in the toolbar).
1208 // Presence in the NTP is signalled in |detached|.
1209 void TestingAutomationProvider::GetBookmarkBarStatus(
1210 base::DictionaryValue* args,
1211 IPC::Message* reply_message) {
1212 AutomationJSONReply reply(this, reply_message);
1214 std::string error_msg;
1215 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
1216 reply.SendError(error_msg);
1219 // browser->window()->IsBookmarkBarVisible() is not consistent across
1220 // platforms. bookmark_bar_state() also follows prefs::kShowBookmarkBar
1221 // and has a shared implementation on all platforms.
1222 base::DictionaryValue dict;
1223 dict.SetBoolean("visible",
1224 browser->bookmark_bar_state() == BookmarkBar::SHOW);
1225 dict.SetBoolean("animating", browser->window()->IsBookmarkBarAnimating());
1226 dict.SetBoolean("detached",
1227 browser->bookmark_bar_state() == BookmarkBar::DETACHED);
1228 reply.SendSuccess(&dict);
1231 void TestingAutomationProvider::GetBookmarksAsJSON(
1232 base::DictionaryValue* args,
1233 IPC::Message* reply_message) {
1234 AutomationJSONReply reply(this, reply_message);
1236 std::string error_msg, bookmarks_as_json;
1237 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
1238 reply.SendError(error_msg);
1241 BookmarkModel* bookmark_model =
1242 BookmarkModelFactory::GetForProfile(browser->profile());
1243 if (!bookmark_model->loaded()) {
1244 reply.SendError("Bookmark model is not loaded");
1247 scoped_refptr<BookmarkStorage> storage(
1248 new BookmarkStorage(browser->profile(),
1250 browser->profile()->GetIOTaskRunner().get()));
1251 if (!storage->SerializeData(&bookmarks_as_json)) {
1252 reply.SendError("Failed to serialize bookmarks");
1255 base::DictionaryValue dict;
1256 dict.SetString("bookmarks_as_json", bookmarks_as_json);
1257 reply.SendSuccess(&dict);
1260 void TestingAutomationProvider::WaitForBookmarkModelToLoad(
1262 IPC::Message* reply_message) {
1263 if (browser_tracker_->ContainsHandle(handle)) {
1264 Browser* browser = browser_tracker_->GetResource(handle);
1265 BookmarkModel* model =
1266 BookmarkModelFactory::GetForProfile(browser->profile());
1267 AutomationProviderBookmarkModelObserver* observer =
1268 new AutomationProviderBookmarkModelObserver(this, reply_message,
1270 if (model->loaded()) {
1271 observer->ReleaseReply();
1273 AutomationMsg_WaitForBookmarkModelToLoad::WriteReplyParams(
1274 reply_message, true);
1275 Send(reply_message);
1280 void TestingAutomationProvider::WaitForBookmarkModelToLoadJSON(
1281 base::DictionaryValue* args,
1282 IPC::Message* reply_message) {
1284 std::string error_msg;
1285 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
1286 AutomationJSONReply(this, reply_message).SendError(error_msg);
1289 BookmarkModel* model =
1290 BookmarkModelFactory::GetForProfile(browser->profile());
1291 AutomationProviderBookmarkModelObserver* observer =
1292 new AutomationProviderBookmarkModelObserver(this, reply_message, model,
1294 if (model->loaded()) {
1295 observer->ReleaseReply();
1297 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
1302 void TestingAutomationProvider::AddBookmark(
1303 base::DictionaryValue* args,
1304 IPC::Message* reply_message) {
1305 AutomationJSONReply reply(this, reply_message);
1307 std::string error_msg, url;
1308 base::string16 title;
1309 int parent_id, index;
1311 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
1312 reply.SendError(error_msg);
1315 if (!args->GetBoolean("is_folder", &folder)) {
1316 reply.SendError("'is_folder' missing or invalid");
1319 if (!folder && !args->GetString("url", &url)) {
1320 reply.SendError("'url' missing or invalid");
1323 if (!args->GetInteger("parent_id", &parent_id)) {
1324 reply.SendError("'parent_id' missing or invalid");
1327 if (!args->GetInteger("index", &index)) {
1328 reply.SendError("'index' missing or invalid");
1331 if (!args->GetString("title", &title)) {
1332 reply.SendError("'title' missing or invalid");
1335 BookmarkModel* model =
1336 BookmarkModelFactory::GetForProfile(browser->profile());
1337 if (!model->loaded()) {
1338 reply.SendError("Bookmark model is not loaded");
1341 const BookmarkNode* parent = model->GetNodeByID(parent_id);
1343 reply.SendError("Failed to get parent bookmark node");
1346 const BookmarkNode* child;
1348 child = model->AddFolder(parent, index, title);
1350 child = model->AddURL(parent, index, title, GURL(url));
1353 reply.SendError("Failed to add bookmark");
1356 reply.SendSuccess(NULL);
1359 void TestingAutomationProvider::ReparentBookmark(base::DictionaryValue* args,
1360 IPC::Message* reply_message) {
1361 AutomationJSONReply reply(this, reply_message);
1363 std::string error_msg;
1364 int new_parent_id, id, index;
1365 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
1366 reply.SendError(error_msg);
1369 if (!args->GetInteger("id", &id)) {
1370 reply.SendError("'id' missing or invalid");
1373 if (!args->GetInteger("new_parent_id", &new_parent_id)) {
1374 reply.SendError("'new_parent_id' missing or invalid");
1377 if (!args->GetInteger("index", &index)) {
1378 reply.SendError("'index' missing or invalid");
1381 BookmarkModel* model =
1382 BookmarkModelFactory::GetForProfile(browser->profile());
1383 if (!model->loaded()) {
1384 reply.SendError("Bookmark model is not loaded");
1387 const BookmarkNode* node = model->GetNodeByID(id);
1388 const BookmarkNode* new_parent = model->GetNodeByID(new_parent_id);
1390 reply.SendError("Failed to get bookmark node");
1394 reply.SendError("Failed to get new parent bookmark node");
1397 model->Move(node, new_parent, index);
1398 reply.SendSuccess(NULL);
1401 void TestingAutomationProvider::SetBookmarkTitle(base::DictionaryValue* args,
1402 IPC::Message* reply_message) {
1403 AutomationJSONReply reply(this, reply_message);
1405 std::string error_msg;
1406 base::string16 title;
1408 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
1409 reply.SendError(error_msg);
1412 if (!args->GetInteger("id", &id)) {
1413 reply.SendError("'id' missing or invalid");
1416 if (!args->GetString("title", &title)) {
1417 reply.SendError("'title' missing or invalid");
1420 BookmarkModel* model =
1421 BookmarkModelFactory::GetForProfile(browser->profile());
1422 if (!model->loaded()) {
1423 reply.SendError("Bookmark model is not loaded");
1426 const BookmarkNode* node = model->GetNodeByID(id);
1428 reply.SendError("Failed to get bookmark node");
1431 model->SetTitle(node, title);
1432 reply.SendSuccess(NULL);
1435 void TestingAutomationProvider::SetBookmarkURL(base::DictionaryValue* args,
1436 IPC::Message* reply_message) {
1437 AutomationJSONReply reply(this, reply_message);
1439 std::string error_msg, url;
1441 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
1442 reply.SendError(error_msg);
1445 if (!args->GetInteger("id", &id)) {
1446 reply.SendError("'id' missing or invalid");
1449 if (!args->GetString("url", &url)) {
1450 reply.SendError("'url' missing or invalid");
1453 BookmarkModel* model =
1454 BookmarkModelFactory::GetForProfile(browser->profile());
1455 if (!model->loaded()) {
1456 reply.SendError("Bookmark model is not loaded");
1459 const BookmarkNode* node = model->GetNodeByID(id);
1461 reply.SendError("Failed to get bookmark node");
1464 model->SetURL(node, GURL(url));
1465 reply.SendSuccess(NULL);
1468 void TestingAutomationProvider::RemoveBookmark(base::DictionaryValue* args,
1469 IPC::Message* reply_message) {
1470 AutomationJSONReply reply(this, reply_message);
1472 std::string error_msg;
1474 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
1475 reply.SendError(error_msg);
1478 if (!args->GetInteger("id", &id)) {
1479 reply.SendError("'id' missing or invalid");
1482 BookmarkModel* model =
1483 BookmarkModelFactory::GetForProfile(browser->profile());
1484 if (!model->loaded()) {
1485 reply.SendError("Bookmark model is not loaded");
1488 const BookmarkNode* node = model->GetNodeByID(id);
1490 reply.SendError("Failed to get bookmark node");
1493 const BookmarkNode* parent = node->parent();
1495 reply.SendError("Failed to get parent bookmark node");
1498 model->Remove(parent, parent->GetIndexOf(node));
1499 reply.SendSuccess(NULL);
1502 void TestingAutomationProvider::WaitForBrowserWindowCountToBecome(
1504 IPC::Message* reply_message) {
1505 // The automation layer doesn't support non-native desktops.
1506 int current_count = static_cast<int>(BrowserList::GetInstance(
1507 chrome::HOST_DESKTOP_TYPE_NATIVE)->size());
1508 if (current_count == target_count) {
1509 AutomationMsg_WaitForBrowserWindowCountToBecome::WriteReplyParams(
1510 reply_message, true);
1511 Send(reply_message);
1515 // Set up an observer (it will delete itself).
1516 new BrowserCountChangeNotificationObserver(target_count, this, reply_message);
1519 void TestingAutomationProvider::GoBackBlockUntilNavigationsComplete(
1520 int handle, int number_of_navigations, IPC::Message* reply_message) {
1521 if (tab_tracker_->ContainsHandle(handle)) {
1522 NavigationController* tab = tab_tracker_->GetResource(handle);
1523 Browser* browser = FindAndActivateTab(tab);
1524 if (chrome::IsCommandEnabled(browser, IDC_BACK)) {
1525 new NavigationNotificationObserver(tab, this, reply_message,
1526 number_of_navigations, false, false);
1527 chrome::ExecuteCommand(browser, IDC_BACK);
1532 AutomationMsg_GoBackBlockUntilNavigationsComplete::WriteReplyParams(
1533 reply_message, AUTOMATION_MSG_NAVIGATION_ERROR);
1534 Send(reply_message);
1537 void TestingAutomationProvider::GoForwardBlockUntilNavigationsComplete(
1538 int handle, int number_of_navigations, IPC::Message* reply_message) {
1539 if (tab_tracker_->ContainsHandle(handle)) {
1540 NavigationController* tab = tab_tracker_->GetResource(handle);
1541 Browser* browser = FindAndActivateTab(tab);
1542 if (chrome::IsCommandEnabled(browser, IDC_FORWARD)) {
1543 new NavigationNotificationObserver(tab, this, reply_message,
1544 number_of_navigations, false, false);
1545 chrome::ExecuteCommand(browser, IDC_FORWARD);
1550 AutomationMsg_GoForwardBlockUntilNavigationsComplete::WriteReplyParams(
1551 reply_message, AUTOMATION_MSG_NAVIGATION_ERROR);
1552 Send(reply_message);
1555 void TestingAutomationProvider::BuildJSONHandlerMaps() {
1556 // Map json commands to their handlers.
1557 handler_map_["ApplyAccelerator"] =
1558 &TestingAutomationProvider::ExecuteBrowserCommandAsyncJSON;
1559 handler_map_["RunCommand"] =
1560 &TestingAutomationProvider::ExecuteBrowserCommandJSON;
1561 handler_map_["IsMenuCommandEnabled"] =
1562 &TestingAutomationProvider::IsMenuCommandEnabledJSON;
1563 handler_map_["ActivateTab"] =
1564 &TestingAutomationProvider::ActivateTabJSON;
1565 handler_map_["BringBrowserToFront"] =
1566 &TestingAutomationProvider::BringBrowserToFrontJSON;
1567 handler_map_["GetIndicesFromTab"] =
1568 &TestingAutomationProvider::GetIndicesFromTab;
1569 handler_map_["NavigateToURL"] =
1570 &TestingAutomationProvider::NavigateToURL;
1571 handler_map_["GetActiveTabIndex"] =
1572 &TestingAutomationProvider::GetActiveTabIndexJSON;
1573 handler_map_["AppendTab"] =
1574 &TestingAutomationProvider::AppendTabJSON;
1575 handler_map_["OpenNewBrowserWindow"] =
1576 &TestingAutomationProvider::OpenNewBrowserWindow;
1577 handler_map_["CloseBrowserWindow"] =
1578 &TestingAutomationProvider::CloseBrowserWindow;
1579 handler_map_["WaitUntilNavigationCompletes"] =
1580 &TestingAutomationProvider::WaitUntilNavigationCompletes;
1581 handler_map_["GetLocalStatePrefsInfo"] =
1582 &TestingAutomationProvider::GetLocalStatePrefsInfo;
1583 handler_map_["SetLocalStatePrefs"] =
1584 &TestingAutomationProvider::SetLocalStatePrefs;
1585 handler_map_["GetPrefsInfo"] = &TestingAutomationProvider::GetPrefsInfo;
1586 handler_map_["SetPrefs"] = &TestingAutomationProvider::SetPrefs;
1587 handler_map_["ExecuteJavascript"] =
1588 &TestingAutomationProvider::ExecuteJavascriptJSON;
1589 handler_map_["AddDomEventObserver"] =
1590 &TestingAutomationProvider::AddDomEventObserver;
1591 handler_map_["RemoveEventObserver"] =
1592 &TestingAutomationProvider::RemoveEventObserver;
1593 handler_map_["GetNextEvent"] =
1594 &TestingAutomationProvider::GetNextEvent;
1595 handler_map_["ClearEventQueue"] =
1596 &TestingAutomationProvider::ClearEventQueue;
1597 handler_map_["ExecuteJavascriptInRenderView"] =
1598 &TestingAutomationProvider::ExecuteJavascriptInRenderView;
1599 handler_map_["GoForward"] =
1600 &TestingAutomationProvider::GoForward;
1601 handler_map_["GoBack"] =
1602 &TestingAutomationProvider::GoBack;
1603 handler_map_["Reload"] =
1604 &TestingAutomationProvider::ReloadJSON;
1605 handler_map_["OpenFindInPage"] =
1606 &TestingAutomationProvider::OpenFindInPage;
1607 handler_map_["IsFindInPageVisible"] =
1608 &TestingAutomationProvider::IsFindInPageVisible;
1609 handler_map_["SetDownloadShelfVisible"] =
1610 &TestingAutomationProvider::SetDownloadShelfVisibleJSON;
1611 handler_map_["IsDownloadShelfVisible"] =
1612 &TestingAutomationProvider::IsDownloadShelfVisibleJSON;
1613 handler_map_["GetDownloadDirectory"] =
1614 &TestingAutomationProvider::GetDownloadDirectoryJSON;
1615 handler_map_["GetCookies"] =
1616 &TestingAutomationProvider::GetCookiesJSON;
1617 handler_map_["DeleteCookie"] =
1618 &TestingAutomationProvider::DeleteCookieJSON;
1619 handler_map_["SetCookie"] =
1620 &TestingAutomationProvider::SetCookieJSON;
1621 handler_map_["GetCookiesInBrowserContext"] =
1622 &TestingAutomationProvider::GetCookiesInBrowserContext;
1623 handler_map_["DeleteCookieInBrowserContext"] =
1624 &TestingAutomationProvider::DeleteCookieInBrowserContext;
1625 handler_map_["SetCookieInBrowserContext"] =
1626 &TestingAutomationProvider::SetCookieInBrowserContext;
1628 handler_map_["WaitForBookmarkModelToLoad"] =
1629 &TestingAutomationProvider::WaitForBookmarkModelToLoadJSON;
1630 handler_map_["GetBookmarksAsJSON"] =
1631 &TestingAutomationProvider::GetBookmarksAsJSON;
1632 handler_map_["GetBookmarkBarStatus"] =
1633 &TestingAutomationProvider::GetBookmarkBarStatus;
1634 handler_map_["AddBookmark"] =
1635 &TestingAutomationProvider::AddBookmark;
1636 handler_map_["ReparentBookmark"] =
1637 &TestingAutomationProvider::ReparentBookmark;
1638 handler_map_["SetBookmarkTitle"] =
1639 &TestingAutomationProvider::SetBookmarkTitle;
1640 handler_map_["SetBookmarkURL"] =
1641 &TestingAutomationProvider::SetBookmarkURL;
1642 handler_map_["RemoveBookmark"] =
1643 &TestingAutomationProvider::RemoveBookmark;
1645 handler_map_["GetTabIds"] =
1646 &TestingAutomationProvider::GetTabIds;
1647 handler_map_["IsTabIdValid"] =
1648 &TestingAutomationProvider::IsTabIdValid;
1649 handler_map_["CloseTab"] =
1650 &TestingAutomationProvider::CloseTabJSON;
1651 handler_map_["SetViewBounds"] =
1652 &TestingAutomationProvider::SetViewBounds;
1653 handler_map_["MaximizeView"] =
1654 &TestingAutomationProvider::MaximizeView;
1655 handler_map_["WebkitMouseMove"] =
1656 &TestingAutomationProvider::WebkitMouseMove;
1657 handler_map_["WebkitMouseClick"] =
1658 &TestingAutomationProvider::WebkitMouseClick;
1659 handler_map_["WebkitMouseDrag"] =
1660 &TestingAutomationProvider::WebkitMouseDrag;
1661 handler_map_["WebkitMouseButtonUp"] =
1662 &TestingAutomationProvider::WebkitMouseButtonUp;
1663 handler_map_["WebkitMouseButtonDown"] =
1664 &TestingAutomationProvider::WebkitMouseButtonDown;
1665 handler_map_["WebkitMouseDoubleClick"] =
1666 &TestingAutomationProvider::WebkitMouseDoubleClick;
1667 handler_map_["DragAndDropFilePaths"] =
1668 &TestingAutomationProvider::DragAndDropFilePaths;
1669 handler_map_["SendWebkitKeyEvent"] =
1670 &TestingAutomationProvider::SendWebkitKeyEvent;
1671 handler_map_["ActivateTab"] =
1672 &TestingAutomationProvider::ActivateTabJSON;
1673 handler_map_["GetAppModalDialogMessage"] =
1674 &TestingAutomationProvider::GetAppModalDialogMessage;
1675 handler_map_["AcceptOrDismissAppModalDialog"] =
1676 &TestingAutomationProvider::AcceptOrDismissAppModalDialog;
1677 handler_map_["ActionOnSSLBlockingPage"] =
1678 &TestingAutomationProvider::ActionOnSSLBlockingPage;
1679 handler_map_["GetSecurityState"] =
1680 &TestingAutomationProvider::GetSecurityState;
1681 handler_map_["IsPageActionVisible"] =
1682 &TestingAutomationProvider::IsPageActionVisible;
1683 handler_map_["CreateNewAutomationProvider"] =
1684 &TestingAutomationProvider::CreateNewAutomationProvider;
1685 handler_map_["GetBrowserWindowCount"] =
1686 &TestingAutomationProvider::GetBrowserWindowCountJSON;
1687 handler_map_["GetBrowserInfo"] =
1688 &TestingAutomationProvider::GetBrowserInfo;
1689 handler_map_["GetTabInfo"] =
1690 &TestingAutomationProvider::GetTabInfo;
1691 handler_map_["GetTabCount"] =
1692 &TestingAutomationProvider::GetTabCountJSON;
1693 handler_map_["OpenNewBrowserWindowWithNewProfile"] =
1694 &TestingAutomationProvider::OpenNewBrowserWindowWithNewProfile;
1695 handler_map_["GetMultiProfileInfo"] =
1696 &TestingAutomationProvider::GetMultiProfileInfo;
1697 handler_map_["OpenProfileWindow"] =
1698 &TestingAutomationProvider::OpenProfileWindow;
1699 handler_map_["GetProcessInfo"] =
1700 &TestingAutomationProvider::GetProcessInfo;
1701 handler_map_["RefreshPolicies"] =
1702 &TestingAutomationProvider::RefreshPolicies;
1703 handler_map_["InstallExtension"] =
1704 &TestingAutomationProvider::InstallExtension;
1705 handler_map_["GetExtensionsInfo"] =
1706 &TestingAutomationProvider::GetExtensionsInfo;
1707 handler_map_["UninstallExtensionById"] =
1708 &TestingAutomationProvider::UninstallExtensionById;
1709 handler_map_["SetExtensionStateById"] =
1710 &TestingAutomationProvider::SetExtensionStateById;
1711 handler_map_["TriggerPageActionById"] =
1712 &TestingAutomationProvider::TriggerPageActionById;
1713 handler_map_["TriggerBrowserActionById"] =
1714 &TestingAutomationProvider::TriggerBrowserActionById;
1715 handler_map_["UpdateExtensionsNow"] =
1716 &TestingAutomationProvider::UpdateExtensionsNow;
1717 handler_map_["OverrideGeoposition"] =
1718 &TestingAutomationProvider::OverrideGeoposition;
1719 handler_map_["SimulateAsanMemoryBug"] =
1720 &TestingAutomationProvider::SimulateAsanMemoryBug;
1722 #if defined(OS_CHROMEOS)
1723 handler_map_["AcceptOOBENetworkScreen"] =
1724 &TestingAutomationProvider::AcceptOOBENetworkScreen;
1725 handler_map_["AcceptOOBEEula"] = &TestingAutomationProvider::AcceptOOBEEula;
1726 handler_map_["CancelOOBEUpdate"] =
1727 &TestingAutomationProvider::CancelOOBEUpdate;
1728 handler_map_["PickUserImage"] = &TestingAutomationProvider::PickUserImage;
1729 handler_map_["SkipToLogin"] = &TestingAutomationProvider::SkipToLogin;
1730 handler_map_["GetOOBEScreenInfo"] =
1731 &TestingAutomationProvider::GetOOBEScreenInfo;
1733 handler_map_["GetLoginInfo"] = &TestingAutomationProvider::GetLoginInfo;
1734 handler_map_["ShowCreateAccountUI"] =
1735 &TestingAutomationProvider::ShowCreateAccountUI;
1736 handler_map_["ExecuteJavascriptInOOBEWebUI"] =
1737 &TestingAutomationProvider::ExecuteJavascriptInOOBEWebUI;
1738 handler_map_["LoginAsGuest"] = &TestingAutomationProvider::LoginAsGuest;
1739 handler_map_["SubmitLoginForm"] =
1740 &TestingAutomationProvider::SubmitLoginForm;
1741 handler_map_["AddLoginEventObserver"] =
1742 &TestingAutomationProvider::AddLoginEventObserver;
1743 handler_map_["SignOut"] = &TestingAutomationProvider::SignOut;
1745 handler_map_["LockScreen"] = &TestingAutomationProvider::LockScreen;
1746 handler_map_["UnlockScreen"] = &TestingAutomationProvider::UnlockScreen;
1747 handler_map_["SignoutInScreenLocker"] =
1748 &TestingAutomationProvider::SignoutInScreenLocker;
1750 handler_map_["GetBatteryInfo"] = &TestingAutomationProvider::GetBatteryInfo;
1752 handler_map_["EnableSpokenFeedback"] =
1753 &TestingAutomationProvider::EnableSpokenFeedback;
1754 handler_map_["IsSpokenFeedbackEnabled"] =
1755 &TestingAutomationProvider::IsSpokenFeedbackEnabled;
1757 handler_map_["GetTimeInfo"] = &TestingAutomationProvider::GetTimeInfo;
1758 handler_map_["SetTimezone"] = &TestingAutomationProvider::SetTimezone;
1760 handler_map_["UpdateCheck"] = &TestingAutomationProvider::UpdateCheck;
1762 handler_map_["GetVolumeInfo"] = &TestingAutomationProvider::GetVolumeInfo;
1763 handler_map_["SetVolume"] = &TestingAutomationProvider::SetVolume;
1764 handler_map_["SetMute"] = &TestingAutomationProvider::SetMute;
1766 handler_map_["OpenCrosh"] = &TestingAutomationProvider::OpenCrosh;
1768 browser_handler_map_["GetTimeInfo"] =
1769 &TestingAutomationProvider::GetTimeInfo;
1770 #endif // defined(OS_CHROMEOS)
1772 browser_handler_map_["DisablePlugin"] =
1773 &TestingAutomationProvider::DisablePlugin;
1774 browser_handler_map_["EnablePlugin"] =
1775 &TestingAutomationProvider::EnablePlugin;
1776 browser_handler_map_["GetPluginsInfo"] =
1777 &TestingAutomationProvider::GetPluginsInfo;
1779 browser_handler_map_["GetNavigationInfo"] =
1780 &TestingAutomationProvider::GetNavigationInfo;
1782 browser_handler_map_["PerformActionOnInfobar"] =
1783 &TestingAutomationProvider::PerformActionOnInfobar;
1785 browser_handler_map_["GetHistoryInfo"] =
1786 &TestingAutomationProvider::GetHistoryInfo;
1788 browser_handler_map_["GetOmniboxInfo"] =
1789 &TestingAutomationProvider::GetOmniboxInfo;
1790 browser_handler_map_["SetOmniboxText"] =
1791 &TestingAutomationProvider::SetOmniboxText;
1792 browser_handler_map_["OmniboxAcceptInput"] =
1793 &TestingAutomationProvider::OmniboxAcceptInput;
1794 browser_handler_map_["OmniboxMovePopupSelection"] =
1795 &TestingAutomationProvider::OmniboxMovePopupSelection;
1797 browser_handler_map_["LoadSearchEngineInfo"] =
1798 &TestingAutomationProvider::LoadSearchEngineInfo;
1799 browser_handler_map_["GetSearchEngineInfo"] =
1800 &TestingAutomationProvider::GetSearchEngineInfo;
1801 browser_handler_map_["AddOrEditSearchEngine"] =
1802 &TestingAutomationProvider::AddOrEditSearchEngine;
1803 browser_handler_map_["PerformActionOnSearchEngine"] =
1804 &TestingAutomationProvider::PerformActionOnSearchEngine;
1806 browser_handler_map_["SetWindowDimensions"] =
1807 &TestingAutomationProvider::SetWindowDimensions;
1809 browser_handler_map_["GetDownloadsInfo"] =
1810 &TestingAutomationProvider::GetDownloadsInfo;
1811 browser_handler_map_["WaitForAllDownloadsToComplete"] =
1812 &TestingAutomationProvider::WaitForAllDownloadsToComplete;
1813 browser_handler_map_["PerformActionOnDownload"] =
1814 &TestingAutomationProvider::PerformActionOnDownload;
1816 browser_handler_map_["GetInitialLoadTimes"] =
1817 &TestingAutomationProvider::GetInitialLoadTimes;
1819 browser_handler_map_["SaveTabContents"] =
1820 &TestingAutomationProvider::SaveTabContents;
1822 browser_handler_map_["AddSavedPassword"] =
1823 &TestingAutomationProvider::AddSavedPassword;
1824 browser_handler_map_["RemoveSavedPassword"] =
1825 &TestingAutomationProvider::RemoveSavedPassword;
1826 browser_handler_map_["GetSavedPasswords"] =
1827 &TestingAutomationProvider::GetSavedPasswords;
1829 browser_handler_map_["FindInPage"] = &TestingAutomationProvider::FindInPage;
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<base::DictionaryValue>
1871 TestingAutomationProvider::ParseJSONRequestCommand(
1872 const std::string& json_request,
1873 std::string* command,
1874 std::string* error) {
1875 scoped_ptr<base::DictionaryValue> dict_value;
1876 scoped_ptr<base::Value> values(
1877 base::JSONReader::ReadAndReturnError(json_request,
1878 base::JSON_ALLOW_TRAILING_COMMAS, NULL, error));
1880 // Make sure input is a dict with a string command.
1881 if (values->GetType() != base::Value::TYPE_DICTIONARY) {
1882 *error = "Command dictionary is not a dictionary.";
1884 dict_value.reset(static_cast<base::DictionaryValue*>(values.release()));
1885 if (!dict_value->GetStringASCII("command", command)) {
1886 *error = "Command key string missing from dictionary.";
1887 dict_value.reset(NULL);
1891 return dict_value.Pass();
1894 void TestingAutomationProvider::SendJSONRequestWithBrowserHandle(
1896 const std::string& json_request,
1897 IPC::Message* reply_message) {
1898 Browser* browser = NULL;
1899 if (browser_tracker_->ContainsHandle(handle))
1900 browser = browser_tracker_->GetResource(handle);
1901 if (browser || handle < 0) {
1902 SendJSONRequest(browser, json_request, reply_message);
1904 AutomationJSONReply(this, reply_message).SendError(
1905 "The browser window does not exist.");
1909 void TestingAutomationProvider::SendJSONRequestWithBrowserIndex(
1911 const std::string& json_request,
1912 IPC::Message* reply_message) {
1913 Browser* browser = index < 0 ? NULL : automation_util::GetBrowserAt(index);
1914 if (!browser && index >= 0) {
1915 AutomationJSONReply(this, reply_message).SendError(base::StringPrintf(
1916 "Browser window with index=%d does not exist.", index));
1918 SendJSONRequest(browser, json_request, reply_message);
1922 void TestingAutomationProvider::SendJSONRequest(Browser* browser,
1923 const std::string& json_request,
1924 IPC::Message* reply_message) {
1925 std::string command, error_string;
1926 scoped_ptr<base::DictionaryValue> dict_value(
1927 ParseJSONRequestCommand(json_request, &command, &error_string));
1928 if (!dict_value.get() || command.empty()) {
1929 AutomationJSONReply(this, reply_message).SendError(error_string);
1933 if (handler_map_.empty() || browser_handler_map_.empty())
1934 BuildJSONHandlerMaps();
1936 // Look for command in handlers that take a Browser.
1937 if (browser_handler_map_.find(std::string(command)) !=
1938 browser_handler_map_.end() && browser) {
1939 (this->*browser_handler_map_[command])(browser, dict_value.get(),
1941 // Look for command in handlers that don't take a Browser.
1942 } else if (handler_map_.find(std::string(command)) != handler_map_.end()) {
1943 (this->*handler_map_[command])(dict_value.get(), reply_message);
1944 // Command has no handler.
1946 error_string = base::StringPrintf("Unknown command '%s'. Options: ",
1948 for (std::map<std::string, JsonHandler>::const_iterator it =
1949 handler_map_.begin(); it != handler_map_.end(); ++it) {
1950 error_string += it->first + ", ";
1952 for (std::map<std::string, BrowserJsonHandler>::const_iterator it =
1953 browser_handler_map_.begin(); it != browser_handler_map_.end(); ++it) {
1954 error_string += it->first + ", ";
1956 AutomationJSONReply(this, reply_message).SendError(error_string);
1960 void TestingAutomationProvider::BringBrowserToFrontJSON(
1961 base::DictionaryValue* args,
1962 IPC::Message* reply_message) {
1963 AutomationJSONReply reply(this, reply_message);
1965 std::string error_msg;
1966 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
1967 reply.SendError(error_msg);
1970 browser->window()->Activate();
1971 reply.SendSuccess(NULL);
1974 // Sample json input: { "command": "SetWindowDimensions",
1975 // "x": 20, # optional
1976 // "y": 20, # optional
1977 // "width": 800, # optional
1978 // "height": 600 } # optional
1979 void TestingAutomationProvider::SetWindowDimensions(
1981 base::DictionaryValue* args,
1982 IPC::Message* reply_message) {
1983 gfx::Rect rect = browser->window()->GetRestoredBounds();
1984 int x, y, width, height;
1985 if (args->GetInteger("x", &x))
1987 if (args->GetInteger("y", &y))
1989 if (args->GetInteger("width", &width))
1990 rect.set_width(width);
1991 if (args->GetInteger("height", &height))
1992 rect.set_height(height);
1993 browser->window()->SetBounds(rect);
1994 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
1997 base::ListValue* TestingAutomationProvider::GetInfobarsInfo(WebContents* wc) {
1998 // Each infobar may have different properties depending on the type.
1999 base::ListValue* infobars = new base::ListValue;
2000 InfoBarService* infobar_service = InfoBarService::FromWebContents(wc);
2001 for (size_t i = 0; i < infobar_service->infobar_count(); ++i) {
2002 base::DictionaryValue* infobar_item = new base::DictionaryValue;
2003 InfoBarDelegate* infobar = infobar_service->infobar_at(i)->delegate();
2004 switch (infobar->GetInfoBarAutomationType()) {
2005 case InfoBarDelegate::CONFIRM_INFOBAR:
2006 infobar_item->SetString("type", "confirm_infobar");
2008 case InfoBarDelegate::PASSWORD_INFOBAR:
2009 infobar_item->SetString("type", "password_infobar");
2011 case InfoBarDelegate::RPH_INFOBAR:
2012 infobar_item->SetString("type", "rph_infobar");
2014 case InfoBarDelegate::UNKNOWN_INFOBAR:
2015 infobar_item->SetString("type", "unknown_infobar");
2018 if (infobar->AsConfirmInfoBarDelegate()) {
2019 // Also covers ThemeInstalledInfoBarDelegate.
2020 ConfirmInfoBarDelegate* confirm_infobar =
2021 infobar->AsConfirmInfoBarDelegate();
2022 infobar_item->SetString("text", confirm_infobar->GetMessageText());
2023 infobar_item->SetString("link_text", confirm_infobar->GetLinkText());
2024 base::ListValue* buttons_list = new base::ListValue;
2025 int buttons = confirm_infobar->GetButtons();
2026 if (buttons & ConfirmInfoBarDelegate::BUTTON_OK) {
2027 base::StringValue* button_label = new base::StringValue(
2028 confirm_infobar->GetButtonLabel(
2029 ConfirmInfoBarDelegate::BUTTON_OK));
2030 buttons_list->Append(button_label);
2032 if (buttons & ConfirmInfoBarDelegate::BUTTON_CANCEL) {
2033 base::StringValue* button_label = new base::StringValue(
2034 confirm_infobar->GetButtonLabel(
2035 ConfirmInfoBarDelegate::BUTTON_CANCEL));
2036 buttons_list->Append(button_label);
2038 infobar_item->Set("buttons", buttons_list);
2039 } else if (infobar->AsExtensionInfoBarDelegate()) {
2040 infobar_item->SetString("type", "extension_infobar");
2042 infobar_item->SetString("type", "unknown_infobar");
2044 infobars->Append(infobar_item);
2049 // Sample json input: { "command": "PerformActionOnInfobar",
2050 // "action": "dismiss",
2051 // "infobar_index": 0,
2053 // Sample output: {}
2054 void TestingAutomationProvider::PerformActionOnInfobar(
2056 base::DictionaryValue* args,
2057 IPC::Message* reply_message) {
2058 AutomationJSONReply reply(this, reply_message);
2060 int infobar_index_int;
2062 if (!args->GetInteger("tab_index", &tab_index) ||
2063 !args->GetInteger("infobar_index", &infobar_index_int) ||
2064 !args->GetString("action", &action)) {
2065 reply.SendError("Invalid or missing args");
2068 size_t infobar_index = static_cast<size_t>(infobar_index_int);
2070 WebContents* web_contents =
2071 browser->tab_strip_model()->GetWebContentsAt(tab_index);
2072 if (!web_contents) {
2073 reply.SendError(base::StringPrintf("No such tab at index %d", tab_index));
2077 InfoBarService* infobar_service =
2078 InfoBarService::FromWebContents(web_contents);
2079 if (infobar_index >= infobar_service->infobar_count()) {
2080 reply.SendError(base::StringPrintf("No such infobar at index %" PRIuS,
2084 InfoBar* infobar = infobar_service->infobar_at(infobar_index);
2085 InfoBarDelegate* infobar_delegate = infobar->delegate();
2087 if (action == "dismiss") {
2088 infobar_delegate->InfoBarDismissed();
2089 infobar_service->RemoveInfoBar(infobar);
2090 reply.SendSuccess(NULL);
2093 if ((action == "accept") || (action == "cancel")) {
2094 ConfirmInfoBarDelegate* confirm_infobar_delegate =
2095 infobar_delegate->AsConfirmInfoBarDelegate();
2096 if (!confirm_infobar_delegate) {
2097 reply.SendError("Not a confirm infobar");
2100 if ((action == "accept") ?
2101 confirm_infobar_delegate->Accept() : confirm_infobar_delegate->Cancel())
2102 infobar_service->RemoveInfoBar(infobar);
2103 reply.SendSuccess(NULL);
2107 reply.SendError("Invalid action");
2112 // Gets info about BrowserChildProcessHost. Must run on IO thread to
2113 // honor the semantics of BrowserChildProcessHostIterator.
2114 // Used by AutomationProvider::GetBrowserInfo().
2115 void GetChildProcessHostInfo(base::ListValue* child_processes) {
2116 for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
2117 // Only add processes which are already started, since we need their handle.
2118 if (iter.GetData().handle == base::kNullProcessHandle)
2120 base::DictionaryValue* item = new base::DictionaryValue;
2121 item->SetString("name", iter.GetData().name);
2124 content::GetProcessTypeNameInEnglish(iter.GetData().process_type));
2125 item->SetInteger("pid", base::GetProcId(iter.GetData().handle));
2126 child_processes->Append(item);
2132 // Sample json input: { "command": "GetBrowserInfo" }
2133 // Refer to GetBrowserInfo() in chrome/test/pyautolib/pyauto.py for
2134 // sample json output.
2135 void TestingAutomationProvider::GetBrowserInfo(
2136 base::DictionaryValue* args,
2137 IPC::Message* reply_message) {
2138 base::ThreadRestrictions::ScopedAllowIO allow_io; // needed for PathService
2139 base::DictionaryValue* properties = new base::DictionaryValue;
2140 properties->SetString("ChromeVersion", chrome::kChromeVersion);
2141 properties->SetString("BrowserProcessExecutableName",
2142 chrome::kBrowserProcessExecutableName);
2143 properties->SetString("HelperProcessExecutableName",
2144 chrome::kHelperProcessExecutableName);
2145 properties->SetString("BrowserProcessExecutablePath",
2146 chrome::kBrowserProcessExecutablePath);
2147 properties->SetString("HelperProcessExecutablePath",
2148 chrome::kHelperProcessExecutablePath);
2149 properties->SetString("command_line_string",
2150 CommandLine::ForCurrentProcess()->GetCommandLineString());
2151 base::FilePath dumps_path;
2152 PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path);
2153 properties->SetString("DIR_CRASH_DUMPS", dumps_path.value());
2154 #if defined(USE_AURA)
2155 properties->SetBoolean("aura", true);
2157 properties->SetBoolean("aura", false);
2160 std::string branding;
2161 #if defined(GOOGLE_CHROME_BUILD)
2162 branding = "Google Chrome";
2163 #elif defined(CHROMIUM_BUILD)
2164 branding = "Chromium";
2166 branding = "Unknown Branding";
2168 properties->SetString("branding", branding);
2170 bool is_official_build = false;
2171 #if defined(OFFICIAL_BUILD)
2172 is_official_build = true;
2174 properties->SetBoolean("is_official", is_official_build);
2176 scoped_ptr<base::DictionaryValue> return_value(new base::DictionaryValue);
2177 return_value->Set("properties", properties);
2179 return_value->SetInteger("browser_pid", base::GetCurrentProcId());
2180 // Add info about all windows in a list of dictionaries, one dictionary
2182 base::ListValue* windows = new base::ListValue;
2185 for (chrome::BrowserIterator it; !it.done(); it.Next(), ++windex) {
2186 base::DictionaryValue* browser_item = new base::DictionaryValue;
2187 Browser* browser = *it;
2188 browser_item->SetInteger("index", windex);
2189 // Window properties
2190 gfx::Rect rect = browser->window()->GetRestoredBounds();
2191 browser_item->SetInteger("x", rect.x());
2192 browser_item->SetInteger("y", rect.y());
2193 browser_item->SetInteger("width", rect.width());
2194 browser_item->SetInteger("height", rect.height());
2195 browser_item->SetBoolean("fullscreen",
2196 browser->window()->IsFullscreen());
2197 base::ListValue* visible_page_actions = new base::ListValue;
2198 // Add info about all visible page actions. Skipped on panels, which do not
2199 // have a location bar.
2200 LocationBar* loc_bar = browser->window()->GetLocationBar();
2202 LocationBarTesting* loc_bar_test =
2203 loc_bar->GetLocationBarForTesting();
2204 size_t page_action_visible_count =
2205 static_cast<size_t>(loc_bar_test->PageActionVisibleCount());
2206 for (size_t i = 0; i < page_action_visible_count; ++i) {
2207 base::StringValue* extension_id = new base::StringValue(
2208 loc_bar_test->GetVisiblePageAction(i)->extension_id());
2209 visible_page_actions->Append(extension_id);
2212 browser_item->Set("visible_page_actions", visible_page_actions);
2213 browser_item->SetInteger("selected_tab",
2214 browser->tab_strip_model()->active_index());
2215 browser_item->SetBoolean("incognito",
2216 browser->profile()->IsOffTheRecord());
2217 browser_item->SetString("profile_path",
2218 browser->profile()->GetPath().BaseName().MaybeAsASCII());
2220 switch (browser->type()) {
2221 case Browser::TYPE_TABBED:
2224 case Browser::TYPE_POPUP:
2231 browser_item->SetString("type", type);
2232 // For each window, add info about all tabs in a list of dictionaries,
2233 // one dictionary item per tab.
2234 base::ListValue* tabs = new base::ListValue;
2235 for (int i = 0; i < browser->tab_strip_model()->count(); ++i) {
2236 WebContents* wc = browser->tab_strip_model()->GetWebContentsAt(i);
2237 base::DictionaryValue* tab = new base::DictionaryValue;
2238 tab->SetInteger("index", i);
2239 tab->SetString("url", wc->GetURL().spec());
2240 tab->SetInteger("renderer_pid",
2241 base::GetProcId(wc->GetRenderProcessHost()->GetHandle()));
2242 tab->Set("infobars", GetInfobarsInfo(wc));
2243 tab->SetBoolean("pinned", browser->tab_strip_model()->IsTabPinned(i));
2246 browser_item->Set("tabs", tabs);
2248 windows->Append(browser_item);
2250 return_value->Set("windows", windows);
2252 #if defined(OS_LINUX)
2253 int flags = ChildProcessHost::CHILD_ALLOW_SELF;
2255 int flags = ChildProcessHost::CHILD_NORMAL;
2258 // Add all extension processes in a list of dictionaries, one dictionary
2259 // item per extension process.
2260 base::ListValue* extension_views = new base::ListValue;
2261 ProfileManager* profile_manager = g_browser_process->profile_manager();
2262 std::vector<Profile*> profiles(profile_manager->GetLoadedProfiles());
2263 for (size_t i = 0; i < profiles.size(); ++i) {
2264 extensions::ProcessManager* process_manager =
2265 extensions::ExtensionSystem::Get(profiles[i])->process_manager();
2266 if (!process_manager)
2268 const extensions::ProcessManager::ViewSet view_set =
2269 process_manager->GetAllViews();
2270 for (extensions::ProcessManager::ViewSet::const_iterator jt =
2272 jt != view_set.end(); ++jt) {
2273 content::RenderViewHost* render_view_host = *jt;
2274 // Don't add dead extension processes.
2275 if (!render_view_host->IsRenderViewLive())
2277 // Don't add views for which we can't obtain an extension.
2278 // TODO(benwells): work out why this happens. It only happens for one
2279 // test, and only on the bots.
2280 const Extension* extension =
2281 process_manager->GetExtensionForRenderViewHost(render_view_host);
2284 base::DictionaryValue* item = new base::DictionaryValue;
2285 item->SetString("name", extension->name());
2286 item->SetString("extension_id", extension->id());
2289 base::GetProcId(render_view_host->GetProcess()->GetHandle()));
2290 base::DictionaryValue* view = new base::DictionaryValue;
2292 "render_process_id",
2293 render_view_host->GetProcess()->GetID());
2296 render_view_host->GetRoutingID());
2297 item->Set("view", view);
2299 WebContents* web_contents =
2300 WebContents::FromRenderViewHost(render_view_host);
2301 extensions::ViewType view_type = extensions::GetViewType(web_contents);
2302 switch (view_type) {
2303 case extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE:
2304 type = "EXTENSION_BACKGROUND_PAGE";
2306 case extensions::VIEW_TYPE_EXTENSION_POPUP:
2307 type = "EXTENSION_POPUP";
2309 case extensions::VIEW_TYPE_EXTENSION_INFOBAR:
2310 type = "EXTENSION_INFOBAR";
2312 case extensions::VIEW_TYPE_EXTENSION_DIALOG:
2313 type = "EXTENSION_DIALOG";
2315 case extensions::VIEW_TYPE_APP_SHELL:
2318 case extensions::VIEW_TYPE_PANEL:
2325 item->SetString("view_type", type);
2326 item->SetString("url", web_contents->GetURL().spec());
2327 item->SetBoolean("loaded", !render_view_host->IsLoading());
2328 extension_views->Append(item);
2331 return_value->Set("extension_views", extension_views);
2333 return_value->SetString("child_process_path",
2334 ChildProcessHost::GetChildPath(flags).value());
2335 // Child processes are the processes for plugins and other workers.
2336 // Add all child processes in a list of dictionaries, one dictionary item
2337 // per child process.
2338 base::ListValue* child_processes = new base::ListValue;
2339 return_value->Set("child_processes", child_processes);
2340 BrowserThread::PostTaskAndReply(
2341 BrowserThread::IO, FROM_HERE,
2342 base::Bind(&GetChildProcessHostInfo, child_processes),
2343 base::Bind(&AutomationJSONReply::SendSuccess,
2344 base::Owned(new AutomationJSONReply(this, reply_message)),
2345 base::Owned(return_value.release())));
2348 // Sample json input: { "command": "GetProcessInfo" }
2349 // Refer to GetProcessInfo() in chrome/test/pyautolib/pyauto.py for
2350 // sample json output.
2351 void TestingAutomationProvider::GetProcessInfo(
2352 base::DictionaryValue* args,
2353 IPC::Message* reply_message) {
2354 scoped_refptr<ProcessInfoObserver>
2355 proc_observer(new ProcessInfoObserver(this, reply_message));
2356 // TODO(jamescook): Maybe this shouldn't update UMA stats?
2357 proc_observer->StartFetch(MemoryDetails::UPDATE_USER_METRICS);
2360 // Sample json input: { "command": "GetNavigationInfo" }
2361 // Refer to GetNavigationInfo() in chrome/test/pyautolib/pyauto.py for
2362 // sample json output.
2363 void TestingAutomationProvider::GetNavigationInfo(
2365 base::DictionaryValue* args,
2366 IPC::Message* reply_message) {
2367 AutomationJSONReply reply(this, reply_message);
2369 WebContents* web_contents = NULL;
2370 if (!args->GetInteger("tab_index", &tab_index) ||
2372 browser->tab_strip_model()->GetWebContentsAt(tab_index))) {
2373 reply.SendError("tab_index missing or invalid.");
2376 scoped_ptr<base::DictionaryValue> return_value(new base::DictionaryValue);
2377 const NavigationController& controller = web_contents->GetController();
2378 NavigationEntry* nav_entry = controller.GetActiveEntry();
2382 base::DictionaryValue* ssl = new base::DictionaryValue;
2383 std::map<content::SecurityStyle, std::string> style_to_string;
2384 style_to_string[content::SECURITY_STYLE_UNKNOWN] = "SECURITY_STYLE_UNKNOWN";
2385 style_to_string[content::SECURITY_STYLE_UNAUTHENTICATED] =
2386 "SECURITY_STYLE_UNAUTHENTICATED";
2387 style_to_string[content::SECURITY_STYLE_AUTHENTICATION_BROKEN] =
2388 "SECURITY_STYLE_AUTHENTICATION_BROKEN";
2389 style_to_string[content::SECURITY_STYLE_AUTHENTICATED] =
2390 "SECURITY_STYLE_AUTHENTICATED";
2392 SSLStatus ssl_status = nav_entry->GetSSL();
2393 ssl->SetString("security_style",
2394 style_to_string[ssl_status.security_style]);
2395 ssl->SetBoolean("ran_insecure_content",
2396 !!(ssl_status.content_status & SSLStatus::RAN_INSECURE_CONTENT));
2397 ssl->SetBoolean("displayed_insecure_content",
2398 !!(ssl_status.content_status & SSLStatus::DISPLAYED_INSECURE_CONTENT));
2399 return_value->Set("ssl", ssl);
2402 std::map<content::PageType, std::string> pagetype_to_string;
2403 pagetype_to_string[content::PAGE_TYPE_NORMAL] = "NORMAL_PAGE";
2404 pagetype_to_string[content::PAGE_TYPE_ERROR] = "ERROR_PAGE";
2405 pagetype_to_string[content::PAGE_TYPE_INTERSTITIAL] =
2406 "INTERSTITIAL_PAGE";
2407 return_value->SetString("page_type",
2408 pagetype_to_string[nav_entry->GetPageType()]);
2410 return_value->SetString("favicon_url", nav_entry->GetFavicon().url.spec());
2411 reply.SendSuccess(return_value.get());
2414 // Sample json input: { "command": "GetHistoryInfo",
2415 // "search_text": "some text" }
2416 // Refer chrome/test/pyautolib/history_info.py for sample json output.
2417 void TestingAutomationProvider::GetHistoryInfo(Browser* browser,
2418 base::DictionaryValue* args,
2419 IPC::Message* reply_message) {
2420 consumer_.CancelAllRequests();
2422 base::string16 search_text;
2423 args->GetString("search_text", &search_text);
2426 HistoryService* hs = HistoryServiceFactory::GetForProfile(
2427 browser->profile(), Profile::EXPLICIT_ACCESS);
2428 history::QueryOptions options;
2429 // The observer owns itself. It deletes itself after it fetches history.
2430 AutomationProviderHistoryObserver* history_observer =
2431 new AutomationProviderHistoryObserver(this, reply_message);
2436 base::Bind(&AutomationProviderHistoryObserver::HistoryQueryComplete,
2437 base::Unretained(history_observer)));
2440 // Sample json input: { "command": "GetDownloadsInfo" }
2441 // Refer chrome/test/pyautolib/download_info.py for sample json output.
2442 void TestingAutomationProvider::GetDownloadsInfo(Browser* browser,
2443 base::DictionaryValue* args,
2444 IPC::Message* reply_message) {
2445 AutomationJSONReply reply(this, reply_message);
2446 scoped_ptr<base::DictionaryValue> return_value(new base::DictionaryValue);
2447 base::ListValue* list_of_downloads = new base::ListValue;
2449 DownloadService* download_service(
2450 DownloadServiceFactory::GetForBrowserContext(browser->profile()));
2452 if (download_service->HasCreatedDownloadManager()) {
2453 std::vector<DownloadItem*> downloads;
2454 BrowserContext::GetDownloadManager(browser->profile())->GetAllDownloads(
2457 for (std::vector<DownloadItem*>::iterator it = downloads.begin();
2458 it != downloads.end();
2459 it++) { // Fill info about each download item.
2460 list_of_downloads->Append(GetDictionaryFromDownloadItem(
2461 *it, browser->profile()->IsOffTheRecord()));
2464 return_value->Set("downloads", list_of_downloads);
2465 reply.SendSuccess(return_value.get());
2468 void TestingAutomationProvider::WaitForAllDownloadsToComplete(
2470 base::DictionaryValue* args,
2471 IPC::Message* reply_message) {
2472 base::ListValue* pre_download_ids = NULL;
2474 if (!args->GetList("pre_download_ids", &pre_download_ids)) {
2475 AutomationJSONReply(this, reply_message)
2477 base::StringPrintf("List of IDs of previous downloads required."));
2481 DownloadService* download_service =
2482 DownloadServiceFactory::GetForBrowserContext(browser->profile());
2483 if (!download_service->HasCreatedDownloadManager()) {
2484 // No download manager, so no downloads to wait for.
2485 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
2489 // This observer will delete itself.
2490 new AllDownloadsCompleteObserver(
2491 this, reply_message,
2492 BrowserContext::GetDownloadManager(browser->profile()),
2496 // See PerformActionOnDownload() in chrome/test/pyautolib/pyauto.py for sample
2497 // json input and output.
2498 void TestingAutomationProvider::PerformActionOnDownload(
2500 base::DictionaryValue* args,
2501 IPC::Message* reply_message) {
2505 DownloadService* download_service =
2506 DownloadServiceFactory::GetForBrowserContext(browser->profile());
2507 if (!download_service->HasCreatedDownloadManager()) {
2508 AutomationJSONReply(this, reply_message).SendError("No download manager.");
2511 if (!args->GetInteger("id", &id) || !args->GetString("action", &action)) {
2512 AutomationJSONReply(this, reply_message)
2513 .SendError("Must include int id and string action.");
2517 DownloadManager* download_manager =
2518 BrowserContext::GetDownloadManager(browser->profile());
2519 DownloadItem* selected_item = download_manager->GetDownload(id);
2520 if (!selected_item) {
2521 AutomationJSONReply(this, reply_message)
2522 .SendError(base::StringPrintf("No download with an id of %d\n", id));
2526 DownloadItem::DownloadState download_state = selected_item->GetState();
2528 // We need to be IN_PROGRESS for these actions.
2529 if ((action == "pause" || action == "resume" || action == "cancel") &&
2530 download_state != DownloadItem::IN_PROGRESS) {
2531 AutomationJSONReply(this, reply_message)
2532 .SendError(base::StringPrintf(
2533 "Action '%s' called on download that is not in progress.",
2538 if (action == "open") {
2539 selected_item->AddObserver(
2540 new AutomationProviderDownloadUpdatedObserver(
2541 this, reply_message, true, browser->profile()->IsOffTheRecord()));
2542 selected_item->OpenDownload();
2543 } else if (action == "toggle_open_files_like_this") {
2544 DownloadPrefs* prefs =
2545 DownloadPrefs::FromBrowserContext(selected_item->GetBrowserContext());
2546 base::FilePath path = selected_item->GetTargetFilePath();
2547 if (!selected_item->ShouldOpenFileBasedOnExtension())
2548 prefs->EnableAutoOpenBasedOnExtension(path);
2550 prefs->DisableAutoOpenBasedOnExtension(path);
2551 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
2552 } else if (action == "remove") {
2553 new AutomationProviderDownloadModelChangedObserver(
2554 this, reply_message, download_manager);
2555 selected_item->Remove();
2556 } else if (action == "decline_dangerous_download") {
2557 new AutomationProviderDownloadModelChangedObserver(
2558 this, reply_message, download_manager);
2559 selected_item->Remove();
2560 } else if (action == "save_dangerous_download") {
2561 selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
2562 this, reply_message, false, browser->profile()->IsOffTheRecord()));
2563 selected_item->ValidateDangerousDownload();
2564 } else if (action == "pause") {
2565 if (selected_item->IsPaused()) {
2566 // Action would be a no-op; respond right from here. No-op implies
2567 // the test is poorly written or failing, so make it an error return.
2568 AutomationJSONReply(this, reply_message)
2569 .SendError("Action 'pause' called on already paused download.");
2571 selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
2572 this, reply_message, false, browser->profile()->IsOffTheRecord()));
2573 selected_item->Pause();
2575 } else if (action == "resume") {
2576 if (!selected_item->IsPaused()) {
2577 // Action would be a no-op; respond right from here. No-op implies
2578 // the test is poorly written or failing, so make it an error return.
2579 AutomationJSONReply(this, reply_message)
2580 .SendError("Action 'resume' called on unpaused download.");
2582 selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
2583 this, reply_message, false, browser->profile()->IsOffTheRecord()));
2584 selected_item->Resume();
2586 } else if (action == "cancel") {
2587 selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
2588 this, reply_message, false, browser->profile()->IsOffTheRecord()));
2589 selected_item->Cancel(true);
2591 AutomationJSONReply(this, reply_message)
2593 base::StringPrintf("Invalid action '%s' given.", action.c_str()));
2597 void TestingAutomationProvider::SetDownloadShelfVisibleJSON(
2598 base::DictionaryValue* args,
2599 IPC::Message* reply_message) {
2600 AutomationJSONReply reply(this, reply_message);
2602 std::string error_msg;
2604 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
2605 reply.SendError(error_msg);
2608 if (!args->GetBoolean("is_visible", &is_visible)) {
2609 reply.SendError("'is_visible' missing or invalid.");
2613 browser->window()->GetDownloadShelf()->Show();
2615 browser->window()->GetDownloadShelf()->Close(DownloadShelf::AUTOMATIC);
2617 reply.SendSuccess(NULL);
2620 void TestingAutomationProvider::IsDownloadShelfVisibleJSON(
2621 base::DictionaryValue* args,
2622 IPC::Message* reply_message) {
2623 AutomationJSONReply reply(this, reply_message);
2625 std::string error_msg;
2626 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
2627 reply.SendError(error_msg);
2630 base::DictionaryValue dict;
2631 dict.SetBoolean("is_visible", browser->window()->IsDownloadShelfVisible());
2632 reply.SendSuccess(&dict);
2635 void TestingAutomationProvider::GetDownloadDirectoryJSON(
2636 base::DictionaryValue* args,
2637 IPC::Message* reply_message) {
2638 AutomationJSONReply reply(this, reply_message);
2639 WebContents* web_contents;
2641 if (!GetTabFromJSONArgs(args, &web_contents, &error)) {
2642 reply.SendError(error);
2645 DownloadManager* dlm =
2646 BrowserContext::GetDownloadManager(
2647 web_contents->GetController().GetBrowserContext());
2648 base::DictionaryValue dict;
2649 dict.SetString("path",
2650 DownloadPrefs::FromDownloadManager(dlm)->DownloadPath().value());
2651 reply.SendSuccess(&dict);
2654 // Sample JSON input { "command": "LoadSearchEngineInfo" }
2655 void TestingAutomationProvider::LoadSearchEngineInfo(
2657 base::DictionaryValue* args,
2658 IPC::Message* reply_message) {
2659 TemplateURLService* url_model =
2660 TemplateURLServiceFactory::GetForProfile(browser->profile());
2661 if (url_model->loaded()) {
2662 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
2665 url_model->AddObserver(new AutomationProviderSearchEngineObserver(
2666 this, browser->profile(), reply_message));
2670 // Sample JSON input { "command": "GetSearchEngineInfo" }
2671 // Refer to pyauto.py for sample output.
2672 void TestingAutomationProvider::GetSearchEngineInfo(
2674 base::DictionaryValue* args,
2675 IPC::Message* reply_message) {
2676 TemplateURLService* url_model =
2677 TemplateURLServiceFactory::GetForProfile(browser->profile());
2678 scoped_ptr<base::DictionaryValue> return_value(new base::DictionaryValue);
2679 base::ListValue* search_engines = new base::ListValue;
2680 TemplateURLService::TemplateURLVector template_urls =
2681 url_model->GetTemplateURLs();
2682 for (TemplateURLService::TemplateURLVector::const_iterator it =
2683 template_urls.begin(); it != template_urls.end(); ++it) {
2684 base::DictionaryValue* search_engine = new base::DictionaryValue;
2685 search_engine->SetString("short_name",
2686 base::UTF16ToUTF8((*it)->short_name()));
2687 search_engine->SetString("keyword", base::UTF16ToUTF8((*it)->keyword()));
2688 search_engine->SetBoolean("in_default_list", (*it)->ShowInDefaultList());
2689 search_engine->SetBoolean("is_default",
2690 (*it) == url_model->GetDefaultSearchProvider());
2691 search_engine->SetBoolean("is_valid", (*it)->url_ref().IsValid());
2692 search_engine->SetBoolean("supports_replacement",
2693 (*it)->url_ref().SupportsReplacement());
2694 search_engine->SetString("url", (*it)->url());
2695 search_engine->SetString("host", (*it)->url_ref().GetHost());
2696 search_engine->SetString("path", (*it)->url_ref().GetPath());
2697 search_engine->SetString("display_url",
2698 base::UTF16ToUTF8((*it)->url_ref().DisplayURL()));
2699 search_engines->Append(search_engine);
2701 return_value->Set("search_engines", search_engines);
2702 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
2705 // Refer to pyauto.py for sample JSON input.
2706 void TestingAutomationProvider::AddOrEditSearchEngine(
2708 base::DictionaryValue* args,
2709 IPC::Message* reply_message) {
2710 TemplateURLService* url_model =
2711 TemplateURLServiceFactory::GetForProfile(browser->profile());
2712 base::string16 new_title;
2713 base::string16 new_keyword;
2714 std::string new_url;
2715 std::string keyword;
2716 if (!args->GetString("new_title", &new_title) ||
2717 !args->GetString("new_keyword", &new_keyword) ||
2718 !args->GetString("new_url", &new_url)) {
2719 AutomationJSONReply(this, reply_message).SendError(
2720 "One or more inputs invalid");
2723 std::string new_ref_url = TemplateURLRef::DisplayURLToURLRef(
2724 base::UTF8ToUTF16(new_url));
2725 scoped_ptr<KeywordEditorController> controller(
2726 new KeywordEditorController(browser->profile()));
2727 if (args->GetString("keyword", &keyword)) {
2728 TemplateURL* template_url =
2729 url_model->GetTemplateURLForKeyword(base::UTF8ToUTF16(keyword));
2730 if (template_url == NULL) {
2731 AutomationJSONReply(this, reply_message).SendError(
2732 "No match for keyword: " + keyword);
2735 url_model->AddObserver(new AutomationProviderSearchEngineObserver(
2736 this, browser->profile(), reply_message));
2737 controller->ModifyTemplateURL(template_url, new_title, new_keyword,
2740 url_model->AddObserver(new AutomationProviderSearchEngineObserver(
2741 this, browser->profile(), reply_message));
2742 controller->AddTemplateURL(new_title, new_keyword, new_ref_url);
2746 // Sample json input: { "command": "PerformActionOnSearchEngine",
2747 // "keyword": keyword, "action": action }
2748 void TestingAutomationProvider::PerformActionOnSearchEngine(
2750 base::DictionaryValue* args,
2751 IPC::Message* reply_message) {
2752 TemplateURLService* url_model =
2753 TemplateURLServiceFactory::GetForProfile(browser->profile());
2754 std::string keyword;
2756 if (!args->GetString("keyword", &keyword) ||
2757 !args->GetString("action", &action)) {
2758 AutomationJSONReply(this, reply_message).SendError(
2759 "One or more inputs invalid");
2762 TemplateURL* template_url =
2763 url_model->GetTemplateURLForKeyword(base::UTF8ToUTF16(keyword));
2764 if (template_url == NULL) {
2765 AutomationJSONReply(this, reply_message).SendError(
2766 "No match for keyword: " + keyword);
2769 if (action == "delete") {
2770 url_model->AddObserver(new AutomationProviderSearchEngineObserver(
2771 this, browser->profile(), reply_message));
2772 url_model->Remove(template_url);
2773 } else if (action == "default") {
2774 url_model->AddObserver(new AutomationProviderSearchEngineObserver(
2775 this, browser->profile(), reply_message));
2776 url_model->SetDefaultSearchProvider(template_url);
2778 AutomationJSONReply(this, reply_message).SendError(
2779 "Invalid action: " + action);
2783 // Sample json input: { "command": "GetLocalStatePrefsInfo" }
2784 // Refer chrome/test/pyautolib/prefs_info.py for sample json output.
2785 void TestingAutomationProvider::GetLocalStatePrefsInfo(
2786 base::DictionaryValue* args,
2787 IPC::Message* reply_message) {
2788 scoped_ptr<base::DictionaryValue> items(
2789 g_browser_process->local_state()->GetPreferenceValues());
2790 scoped_ptr<base::DictionaryValue> return_value(new base::DictionaryValue);
2791 return_value->Set("prefs", items.release()); // return_value owns items.
2792 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
2795 // Sample json input: { "command": "SetLocalStatePrefs", "path": path,
2797 void TestingAutomationProvider::SetLocalStatePrefs(
2798 base::DictionaryValue* args,
2799 IPC::Message* reply_message) {
2801 base::Value* val = NULL;
2802 AutomationJSONReply reply(this, reply_message);
2803 if (args->GetString("path", &path) && args->Get("value", &val)) {
2804 PrefService* pref_service = g_browser_process->local_state();
2805 const PrefService::Preference* pref =
2806 pref_service->FindPreference(path.c_str());
2807 if (!pref) { // Not a registered pref.
2808 reply.SendError("pref not registered.");
2810 } else if (pref->IsManaged()) { // Do not attempt to change a managed pref.
2811 reply.SendError("pref is managed. cannot be changed.");
2813 } else { // Set the pref.
2814 pref_service->Set(path.c_str(), *val);
2817 reply.SendError("no pref path or value given.");
2821 reply.SendSuccess(NULL);
2824 // Sample json input: { "command": "GetPrefsInfo", "windex": 0 }
2825 // Refer chrome/test/pyautolib/prefs_info.py for sample json output.
2826 void TestingAutomationProvider::GetPrefsInfo(base::DictionaryValue* args,
2827 IPC::Message* reply_message) {
2828 AutomationJSONReply reply(this, reply_message);
2830 std::string error_msg;
2831 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
2832 reply.SendError(error_msg);
2835 scoped_ptr<base::DictionaryValue> items(
2836 browser->profile()->GetPrefs()->GetPreferenceValues());
2838 scoped_ptr<base::DictionaryValue> return_value(new base::DictionaryValue);
2839 return_value->Set("prefs", items.release()); // return_value owns items.
2840 reply.SendSuccess(return_value.get());
2843 // Sample json input:
2844 // { "command": "SetPrefs",
2848 void TestingAutomationProvider::SetPrefs(base::DictionaryValue* args,
2849 IPC::Message* reply_message) {
2850 AutomationJSONReply reply(this, reply_message);
2852 std::string error_msg;
2853 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
2854 reply.SendError(error_msg);
2858 base::Value* val = NULL;
2859 if (args->GetString("path", &path) && args->Get("value", &val)) {
2860 PrefService* pref_service = browser->profile()->GetPrefs();
2861 const PrefService::Preference* pref =
2862 pref_service->FindPreference(path.c_str());
2863 if (!pref) { // Not a registered pref.
2864 reply.SendError("pref not registered.");
2866 } else if (pref->IsManaged()) { // Do not attempt to change a managed pref.
2867 reply.SendError("pref is managed. cannot be changed.");
2869 } else { // Set the pref.
2870 pref_service->Set(path.c_str(), *val);
2873 reply.SendError("no pref path or value given.");
2877 reply.SendSuccess(NULL);
2880 // Sample json input: { "command": "GetOmniboxInfo" }
2881 // Refer chrome/test/pyautolib/omnibox_info.py for sample json output.
2882 void TestingAutomationProvider::GetOmniboxInfo(Browser* browser,
2883 base::DictionaryValue* args,
2884 IPC::Message* reply_message) {
2885 scoped_ptr<base::DictionaryValue> return_value(new base::DictionaryValue);
2886 AutomationJSONReply reply(this, reply_message);
2888 LocationBar* loc_bar = browser->window()->GetLocationBar();
2890 reply.SendError("The specified browser does not have a location bar.");
2893 const OmniboxView* omnibox_view = loc_bar->GetOmniboxView();
2894 const OmniboxEditModel* model = omnibox_view->model();
2897 base::ListValue* matches = new base::ListValue;
2898 const AutocompleteResult& result = model->result();
2899 for (AutocompleteResult::const_iterator i(result.begin()); i != result.end();
2901 const AutocompleteMatch& match = *i;
2902 base::DictionaryValue* item =
2903 new base::DictionaryValue; // owned by return_value
2904 item->SetString("type", AutocompleteMatchType::ToString(match.type));
2905 item->SetBoolean("starred", match.starred);
2906 item->SetString("destination_url", match.destination_url.spec());
2907 item->SetString("contents", match.contents);
2908 item->SetString("description", match.description);
2909 matches->Append(item);
2911 return_value->Set("matches", matches);
2913 // Fill up other properties.
2914 base::DictionaryValue* properties =
2915 new base::DictionaryValue; // owned by return_value
2916 properties->SetBoolean("has_focus", model->has_focus());
2917 properties->SetBoolean("query_in_progress",
2918 !model->autocomplete_controller()->done());
2919 properties->SetString("keyword", model->keyword());
2920 properties->SetString("text", omnibox_view->GetText());
2921 return_value->Set("properties", properties);
2923 reply.SendSuccess(return_value.get());
2926 // Sample json input: { "command": "SetOmniboxText",
2928 void TestingAutomationProvider::SetOmniboxText(Browser* browser,
2929 base::DictionaryValue* args,
2930 IPC::Message* reply_message) {
2931 base::string16 text;
2932 AutomationJSONReply reply(this, reply_message);
2933 if (!args->GetString("text", &text)) {
2934 reply.SendError("text missing");
2937 chrome::FocusLocationBar(browser);
2938 LocationBar* loc_bar = browser->window()->GetLocationBar();
2940 reply.SendError("The specified browser does not have a location bar.");
2943 OmniboxView* omnibox_view = loc_bar->GetOmniboxView();
2944 omnibox_view->model()->OnSetFocus(false);
2945 omnibox_view->SetUserText(text);
2946 reply.SendSuccess(NULL);
2949 // Sample json input: { "command": "OmniboxMovePopupSelection",
2951 // Negative count implies up, positive implies down. Count values will be
2952 // capped by the size of the popup list.
2953 void TestingAutomationProvider::OmniboxMovePopupSelection(
2955 base::DictionaryValue* args,
2956 IPC::Message* reply_message) {
2958 AutomationJSONReply reply(this, reply_message);
2959 if (!args->GetInteger("count", &count)) {
2960 reply.SendError("count missing");
2963 LocationBar* loc_bar = browser->window()->GetLocationBar();
2965 reply.SendError("The specified browser does not have a location bar.");
2968 loc_bar->GetOmniboxView()->model()->OnUpOrDownKeyPressed(count);
2969 reply.SendSuccess(NULL);
2972 // Sample json input: { "command": "OmniboxAcceptInput" }
2973 void TestingAutomationProvider::OmniboxAcceptInput(
2975 base::DictionaryValue* args,
2976 IPC::Message* reply_message) {
2977 NavigationController& controller =
2978 browser->tab_strip_model()->GetActiveWebContents()->GetController();
2979 LocationBar* loc_bar = browser->window()->GetLocationBar();
2981 AutomationJSONReply(this, reply_message).SendError(
2982 "The specified browser does not have a location bar.");
2985 new OmniboxAcceptNotificationObserver(&controller, this, reply_message);
2986 loc_bar->AcceptInput();
2989 // Sample json input: { "command": "GetInitialLoadTimes" }
2990 // Refer to InitialLoadObserver::GetTimingInformation() for sample output.
2991 void TestingAutomationProvider::GetInitialLoadTimes(
2993 base::DictionaryValue*,
2994 IPC::Message* reply_message) {
2995 scoped_ptr<base::DictionaryValue> return_value(
2996 initial_load_observer_->GetTimingInformation());
2998 std::string json_return;
2999 base::JSONWriter::Write(return_value.get(), &json_return);
3000 AutomationMsg_SendJSONRequest::WriteReplyParams(
3001 reply_message, json_return, true);
3002 Send(reply_message);
3005 // Sample json input: { "command": "GetPluginsInfo" }
3006 // Refer chrome/test/pyautolib/plugins_info.py for sample json output.
3007 void TestingAutomationProvider::GetPluginsInfo(
3009 base::DictionaryValue* args,
3010 IPC::Message* reply_message) {
3011 PluginService::GetInstance()->GetPlugins(
3012 base::Bind(&TestingAutomationProvider::GetPluginsInfoCallback,
3013 this, browser, args, reply_message));
3016 void TestingAutomationProvider::GetPluginsInfoCallback(
3018 base::DictionaryValue* args,
3019 IPC::Message* reply_message,
3020 const std::vector<content::WebPluginInfo>& plugins) {
3021 PluginPrefs* plugin_prefs =
3022 PluginPrefs::GetForProfile(browser->profile()).get();
3023 base::ListValue* items = new base::ListValue;
3024 for (std::vector<content::WebPluginInfo>::const_iterator it =
3026 it != plugins.end();
3028 base::DictionaryValue* item = new base::DictionaryValue;
3029 item->SetString("name", it->name);
3030 item->SetString("path", it->path.value());
3031 item->SetString("version", it->version);
3032 item->SetString("desc", it->desc);
3033 item->SetBoolean("enabled", plugin_prefs->IsPluginEnabled(*it));
3034 // Add info about mime types.
3035 base::ListValue* mime_types = new base::ListValue();
3036 for (std::vector<content::WebPluginMimeType>::const_iterator type_it =
3037 it->mime_types.begin();
3038 type_it != it->mime_types.end();
3040 base::DictionaryValue* mime_type = new base::DictionaryValue();
3041 mime_type->SetString("mimeType", type_it->mime_type);
3042 mime_type->SetString("description", type_it->description);
3044 base::ListValue* file_extensions = new base::ListValue();
3045 for (std::vector<std::string>::const_iterator ext_it =
3046 type_it->file_extensions.begin();
3047 ext_it != type_it->file_extensions.end();
3049 file_extensions->Append(new base::StringValue(*ext_it));
3051 mime_type->Set("fileExtensions", file_extensions);
3053 mime_types->Append(mime_type);
3055 item->Set("mimeTypes", mime_types);
3056 items->Append(item);
3058 scoped_ptr<base::DictionaryValue> return_value(new base::DictionaryValue);
3059 return_value->Set("plugins", items); // return_value owns items.
3061 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
3064 // Sample json input:
3065 // { "command": "EnablePlugin",
3066 // "path": "/Library/Internet Plug-Ins/Flash Player.plugin" }
3067 void TestingAutomationProvider::EnablePlugin(Browser* browser,
3068 base::DictionaryValue* args,
3069 IPC::Message* reply_message) {
3070 base::FilePath::StringType path;
3071 if (!args->GetString("path", &path)) {
3072 AutomationJSONReply(this, reply_message).SendError("path not specified.");
3075 PluginPrefs* plugin_prefs =
3076 PluginPrefs::GetForProfile(browser->profile()).get();
3077 plugin_prefs->EnablePlugin(
3079 base::FilePath(path),
3080 base::Bind(&DidEnablePlugin,
3084 "Could not enable plugin for path %s."));
3087 // Sample json input:
3088 // { "command": "DisablePlugin",
3089 // "path": "/Library/Internet Plug-Ins/Flash Player.plugin" }
3090 void TestingAutomationProvider::DisablePlugin(Browser* browser,
3091 base::DictionaryValue* args,
3092 IPC::Message* reply_message) {
3093 base::FilePath::StringType path;
3094 if (!args->GetString("path", &path)) {
3095 AutomationJSONReply(this, reply_message).SendError("path not specified.");
3098 PluginPrefs* plugin_prefs =
3099 PluginPrefs::GetForProfile(browser->profile()).get();
3100 plugin_prefs->EnablePlugin(
3102 base::FilePath(path),
3103 base::Bind(&DidEnablePlugin,
3107 "Could not disable plugin for path %s."));
3110 // Sample json input:
3111 // { "command": "SaveTabContents",
3113 // "filename": <a full pathname> }
3114 // Sample json output:
3116 void TestingAutomationProvider::SaveTabContents(
3118 base::DictionaryValue* args,
3119 IPC::Message* reply_message) {
3121 base::FilePath::StringType filename;
3122 base::FilePath::StringType parent_directory;
3123 WebContents* web_contents = NULL;
3125 if (!args->GetInteger("tab_index", &tab_index) ||
3126 !args->GetString("filename", &filename)) {
3127 AutomationJSONReply(this, reply_message)
3128 .SendError("tab_index or filename param missing");
3131 web_contents = browser->tab_strip_model()->GetWebContentsAt(tab_index);
3132 if (!web_contents) {
3133 AutomationJSONReply(this, reply_message).SendError("no tab at tab_index");
3137 // We're doing a SAVE_AS_ONLY_HTML so the the directory path isn't
3138 // used. Nevertheless, SavePackage requires it be valid. Sigh.
3139 parent_directory = base::FilePath(filename).DirName().value();
3140 if (!web_contents->SavePage(
3141 base::FilePath(filename),
3142 base::FilePath(parent_directory),
3143 content::SAVE_PAGE_TYPE_AS_ONLY_HTML)) {
3144 AutomationJSONReply(this, reply_message).SendError(
3145 "Could not initiate SavePage");
3148 // The observer will delete itself when done.
3149 new SavePackageNotificationObserver(
3150 BrowserContext::GetDownloadManager(browser->profile()),
3151 this, reply_message);
3156 // Translates a dictionary password to a PasswordForm struct.
3157 autofill::PasswordForm GetPasswordFormFromDict(
3158 const base::DictionaryValue& password_dict) {
3160 // If the time is specified, change time to the specified time.
3161 base::Time time = base::Time::Now();
3164 if (password_dict.GetInteger("time", &it))
3165 time = base::Time::FromTimeT(it);
3166 else if (password_dict.GetDouble("time", &dt))
3167 time = base::Time::FromDoubleT(dt);
3169 std::string signon_realm;
3170 base::string16 username_value;
3171 base::string16 password_value;
3172 base::string16 origin_url_text;
3173 base::string16 username_element;
3174 base::string16 password_element;
3175 base::string16 submit_element;
3176 base::string16 action_target_text;
3178 base::string16 old_password_element;
3179 base::string16 old_password_value;
3181 // We don't care if any of these fail - they are either optional or checked
3182 // before this function is called.
3183 password_dict.GetString("signon_realm", &signon_realm);
3184 password_dict.GetString("username_value", &username_value);
3185 password_dict.GetString("password_value", &password_value);
3186 password_dict.GetString("origin_url", &origin_url_text);
3187 password_dict.GetString("username_element", &username_element);
3188 password_dict.GetString("password_element", &password_element);
3189 password_dict.GetString("submit_element", &submit_element);
3190 password_dict.GetString("action_target", &action_target_text);
3191 if (!password_dict.GetBoolean("blacklist", &blacklist))
3194 GURL origin_gurl(origin_url_text);
3195 GURL action_target(action_target_text);
3197 autofill::PasswordForm password_form;
3198 password_form.signon_realm = signon_realm;
3199 password_form.username_value = username_value;
3200 password_form.password_value = password_value;
3201 password_form.origin = origin_gurl;
3202 password_form.username_element = username_element;
3203 password_form.password_element = password_element;
3204 password_form.submit_element = submit_element;
3205 password_form.action = action_target;
3206 password_form.blacklisted_by_user = blacklist;
3207 password_form.date_created = time;
3209 return password_form;
3214 // See AddSavedPassword() in chrome/test/functional/pyauto.py for sample json
3216 // Sample json output: { "password_added": true }
3217 void TestingAutomationProvider::AddSavedPassword(
3219 base::DictionaryValue* args,
3220 IPC::Message* reply_message) {
3221 base::DictionaryValue* password_dict = NULL;
3222 if (!args->GetDictionary("password", &password_dict)) {
3223 AutomationJSONReply(this, reply_message).SendError(
3224 "Must specify a password dictionary.");
3228 // The "signon realm" is effectively the primary key and must be included.
3229 // Check here before calling GetPasswordFormFromDict.
3230 if (!password_dict->HasKey("signon_realm")) {
3231 AutomationJSONReply(this, reply_message).SendError(
3232 "Password must include a value for 'signon_realm.'");
3236 autofill::PasswordForm new_password =
3237 GetPasswordFormFromDict(*password_dict);
3239 // Use IMPLICIT_ACCESS since new passwords aren't added in incognito mode.
3240 PasswordStore* password_store = PasswordStoreFactory::GetForProfile(
3241 browser->profile(), Profile::IMPLICIT_ACCESS).get();
3243 // The password store does not exist for an incognito window.
3244 if (password_store == NULL) {
3245 scoped_ptr<base::DictionaryValue> return_value(new base::DictionaryValue);
3246 return_value->SetBoolean("password_added", false);
3247 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
3251 // This observer will delete itself.
3252 PasswordStoreLoginsChangedObserver* observer =
3253 new PasswordStoreLoginsChangedObserver(this, reply_message,
3254 PasswordStoreChange::ADD,
3257 password_store->AddLogin(new_password);
3260 // See RemoveSavedPassword() in chrome/test/functional/pyauto.py for sample
3262 // Sample json output: {}
3263 void TestingAutomationProvider::RemoveSavedPassword(
3265 base::DictionaryValue* args,
3266 IPC::Message* reply_message) {
3267 base::DictionaryValue* password_dict = NULL;
3269 if (!args->GetDictionary("password", &password_dict)) {
3270 AutomationJSONReply(this, reply_message).SendError(
3271 "Must specify a password dictionary.");
3275 // The "signon realm" is effectively the primary key and must be included.
3276 // Check here before calling GetPasswordFormFromDict.
3277 if (!password_dict->HasKey("signon_realm")) {
3278 AutomationJSONReply(this, reply_message).SendError(
3279 "Password must include a value for 'signon_realm.'");
3282 autofill::PasswordForm to_remove =
3283 GetPasswordFormFromDict(*password_dict);
3285 // Use EXPLICIT_ACCESS since passwords can be removed in incognito mode.
3286 PasswordStore* password_store = PasswordStoreFactory::GetForProfile(
3287 browser->profile(), Profile::EXPLICIT_ACCESS).get();
3288 if (password_store == NULL) {
3289 AutomationJSONReply(this, reply_message).SendError(
3290 "Unable to get password store.");
3294 // This observer will delete itself.
3295 PasswordStoreLoginsChangedObserver* observer =
3296 new PasswordStoreLoginsChangedObserver(
3297 this, reply_message, PasswordStoreChange::REMOVE, std::string());
3300 password_store->RemoveLogin(to_remove);
3303 // Sample json input: { "command": "GetSavedPasswords" }
3304 // Refer to GetSavedPasswords() in chrome/test/pyautolib/pyauto.py for sample
3306 void TestingAutomationProvider::GetSavedPasswords(
3308 base::DictionaryValue* args,
3309 IPC::Message* reply_message) {
3310 // Use EXPLICIT_ACCESS since saved passwords can be retrieved in
3312 PasswordStore* password_store = PasswordStoreFactory::GetForProfile(
3313 browser->profile(), Profile::EXPLICIT_ACCESS).get();
3315 if (password_store == NULL) {
3316 AutomationJSONReply reply(this, reply_message);
3317 reply.SendError("Unable to get password store.");
3320 password_store->GetAutofillableLogins(
3321 new AutomationProviderGetPasswordsObserver(this, reply_message));
3322 // Observer deletes itself after sending the result.
3327 // Get the WebContents from a dictionary of arguments.
3328 WebContents* GetWebContentsFromDict(const Browser* browser,
3329 const base::DictionaryValue* args,
3330 std::string* error_message) {
3332 if (!args->GetInteger("tab_index", &tab_index)) {
3333 *error_message = "Must include tab_index.";
3337 WebContents* web_contents =
3338 browser->tab_strip_model()->GetWebContentsAt(tab_index);
3339 if (!web_contents) {
3340 *error_message = base::StringPrintf("No tab at index %d.", tab_index);
3343 return web_contents;
3348 void TestingAutomationProvider::FindInPage(
3350 base::DictionaryValue* args,
3351 IPC::Message* reply_message) {
3352 std::string error_message;
3353 WebContents* web_contents =
3354 GetWebContentsFromDict(browser, args, &error_message);
3355 if (!web_contents) {
3356 AutomationJSONReply(this, reply_message).SendError(error_message);
3359 base::string16 search_string;
3363 if (!args->GetString("search_string", &search_string)) {
3364 AutomationJSONReply(this, reply_message).
3365 SendError("Must include search_string string.");
3368 if (!args->GetBoolean("forward", &forward)) {
3369 AutomationJSONReply(this, reply_message).
3370 SendError("Must include forward boolean.");
3373 if (!args->GetBoolean("match_case", &match_case)) {
3374 AutomationJSONReply(this, reply_message).
3375 SendError("Must include match_case boolean.");
3378 if (!args->GetBoolean("find_next", &find_next)) {
3379 AutomationJSONReply(this, reply_message).
3380 SendError("Must include find_next boolean.");
3383 SendFindRequest(web_contents,
3392 void TestingAutomationProvider::OpenFindInPage(
3393 base::DictionaryValue* args,
3394 IPC::Message* reply_message) {
3395 AutomationJSONReply reply(this, reply_message);
3397 std::string error_msg;
3398 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
3399 reply.SendError(error_msg);
3402 chrome::FindInPage(browser, false, false);
3403 reply.SendSuccess(NULL);
3406 void TestingAutomationProvider::IsFindInPageVisible(
3407 base::DictionaryValue* args,
3408 IPC::Message* reply_message) {
3409 AutomationJSONReply reply(this, reply_message);
3412 std::string error_msg;
3413 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
3414 reply.SendError(error_msg);
3417 FindBarTesting* find_bar =
3418 browser->GetFindBarController()->find_bar()->GetFindBarTesting();
3419 find_bar->GetFindBarWindowInfo(NULL, &visible);
3420 base::DictionaryValue dict;
3421 dict.SetBoolean("is_visible", visible);
3422 reply.SendSuccess(&dict);
3425 void TestingAutomationProvider::InstallExtension(
3426 base::DictionaryValue* args, IPC::Message* reply_message) {
3427 base::FilePath::StringType path_string;
3429 bool from_webstore = false;
3431 content::WebContents* tab;
3432 std::string error_msg;
3433 if (!GetBrowserAndTabFromJSONArgs(args, &browser, &tab, &error_msg)) {
3434 AutomationJSONReply(this, reply_message).SendError(error_msg);
3437 if (!args->GetString("path", &path_string)) {
3438 AutomationJSONReply(this, reply_message).SendError(
3439 "Missing or invalid 'path'");
3442 if (!args->GetBoolean("with_ui", &with_ui)) {
3443 AutomationJSONReply(this, reply_message).SendError(
3444 "Missing or invalid 'with_ui'");
3447 args->GetBoolean("from_webstore", &from_webstore);
3449 extensions::ExtensionSystem* system =
3450 extensions::ExtensionSystem::Get(browser->profile());
3451 ExtensionService* service = system->extension_service();
3453 // The observer will delete itself when done.
3454 new ExtensionReadyNotificationObserver(
3459 base::FilePath extension_path(path_string);
3460 // If the given path has a 'crx' extension, assume it is a packed extension
3461 // and install it. Otherwise load it as an unpacked extension.
3462 if (extension_path.MatchesExtension(FILE_PATH_LITERAL(".crx"))) {
3463 scoped_ptr<ExtensionInstallPrompt> client(
3464 with_ui ? new ExtensionInstallPrompt(tab) : NULL);
3465 scoped_refptr<extensions::CrxInstaller> installer(
3466 extensions::CrxInstaller::Create(service, client.Pass()));
3468 installer->set_allow_silent_install(true);
3469 installer->set_install_cause(extension_misc::INSTALL_CAUSE_AUTOMATION);
3471 installer->set_creation_flags(Extension::FROM_WEBSTORE);
3472 installer->InstallCrx(extension_path);
3474 scoped_refptr<extensions::UnpackedInstaller> installer(
3475 extensions::UnpackedInstaller::Create(service));
3476 installer->set_prompt_for_plugins(with_ui);
3477 installer->Load(extension_path);
3480 AutomationJSONReply(this, reply_message).SendError(
3481 "Extensions service is not available");
3487 base::ListValue* GetHostPermissions(const Extension* ext, bool effective_perm) {
3488 extensions::URLPatternSet pattern_set;
3489 if (effective_perm) {
3491 extensions::PermissionsData::GetEffectiveHostPermissions(ext);
3493 pattern_set = ext->GetActivePermissions()->explicit_hosts();
3496 base::ListValue* permissions = new base::ListValue;
3497 for (extensions::URLPatternSet::const_iterator perm = pattern_set.begin();
3498 perm != pattern_set.end(); ++perm) {
3499 permissions->Append(new base::StringValue(perm->GetAsString()));
3505 base::ListValue* GetAPIPermissions(const Extension* ext) {
3506 base::ListValue* permissions = new base::ListValue;
3507 std::set<std::string> perm_list =
3508 ext->GetActivePermissions()->GetAPIsAsStrings();
3509 for (std::set<std::string>::const_iterator perm = perm_list.begin();
3510 perm != perm_list.end(); ++perm) {
3511 permissions->Append(new base::StringValue(perm->c_str()));
3518 // Sample json input: { "command": "GetExtensionsInfo" }
3519 // See GetExtensionsInfo() in chrome/test/pyautolib/pyauto.py for sample json
3521 void TestingAutomationProvider::GetExtensionsInfo(base::DictionaryValue* args,
3522 IPC::Message* reply_message) {
3523 AutomationJSONReply reply(this, reply_message);
3525 std::string error_msg;
3526 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
3527 reply.SendError(error_msg);
3530 ExtensionService* service = extensions::ExtensionSystem::Get(
3531 browser->profile())->extension_service();
3533 reply.SendError("No extensions service.");
3536 scoped_ptr<base::DictionaryValue> return_value(new base::DictionaryValue);
3537 base::ListValue* extensions_values = new base::ListValue;
3538 const extensions::ExtensionSet* extensions = service->extensions();
3539 const extensions::ExtensionSet* disabled_extensions =
3540 service->disabled_extensions();
3542 all.insert(all.end(),
3543 extensions->begin(),
3545 all.insert(all.end(),
3546 disabled_extensions->begin(),
3547 disabled_extensions->end());
3548 ExtensionActionManager* extension_action_manager =
3549 ExtensionActionManager::Get(browser->profile());
3550 for (ExtensionList::const_iterator it = all.begin();
3551 it != all.end(); ++it) {
3552 const Extension* extension = it->get();
3553 std::string id = extension->id();
3554 base::DictionaryValue* extension_value = new base::DictionaryValue;
3555 extension_value->SetString("id", id);
3556 extension_value->SetString("version", extension->VersionString());
3557 extension_value->SetString("name", extension->name());
3558 extension_value->SetString("public_key", extension->public_key());
3559 extension_value->SetString("description", extension->description());
3560 extension_value->SetString(
3562 extensions::BackgroundInfo::GetBackgroundURL(extension).spec());
3563 extension_value->SetString("options_url",
3564 extensions::ManifestURL::GetOptionsPage(extension).spec());
3565 extension_value->Set("host_permissions",
3566 GetHostPermissions(extension, false));
3567 extension_value->Set("effective_host_permissions",
3568 GetHostPermissions(extension, true));
3569 extension_value->Set("api_permissions", GetAPIPermissions(extension));
3570 Manifest::Location location = extension->location();
3571 extension_value->SetBoolean("is_component",
3572 location == Manifest::COMPONENT);
3573 extension_value->SetBoolean("is_internal",
3574 location == Manifest::INTERNAL);
3575 extension_value->SetBoolean("is_user_installed",
3576 location == Manifest::INTERNAL ||
3577 Manifest::IsUnpackedLocation(location));
3578 extension_value->SetBoolean("is_enabled", service->IsExtensionEnabled(id));
3579 extension_value->SetBoolean("allowed_in_incognito",
3580 extensions::util::IsIncognitoEnabled(id, browser->profile()));
3581 extension_value->SetBoolean(
3583 extension_action_manager->GetPageAction(*extension) != NULL);
3584 extensions_values->Append(extension_value);
3586 return_value->Set("extensions", extensions_values);
3587 reply.SendSuccess(return_value.get());
3590 // See UninstallExtensionById() in chrome/test/pyautolib/pyauto.py for sample
3592 // Sample json output: {}
3593 void TestingAutomationProvider::UninstallExtensionById(
3594 base::DictionaryValue* args,
3595 IPC::Message* reply_message) {
3596 const Extension* extension;
3599 if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
3600 AutomationJSONReply(this, reply_message).SendError(error);
3603 if (!GetExtensionFromJSONArgs(
3604 args, "id", browser->profile(), &extension, &error)) {
3605 AutomationJSONReply(this, reply_message).SendError(error);
3608 ExtensionService* service = extensions::ExtensionSystem::Get(
3609 browser->profile())->extension_service();
3611 AutomationJSONReply(this, reply_message).SendError(
3612 "No extensions service.");
3616 // Wait for a notification indicating that the extension with the given ID
3617 // has been uninstalled. This observer will delete itself.
3618 new ExtensionUninstallObserver(this, reply_message, extension->id());
3619 service->UninstallExtension(extension->id(), false, NULL);
3622 // See SetExtensionStateById() in chrome/test/pyautolib/pyauto.py
3623 // for sample json input.
3624 void TestingAutomationProvider::SetExtensionStateById(
3625 base::DictionaryValue* args,
3626 IPC::Message* reply_message) {
3627 const Extension* extension;
3630 if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
3631 AutomationJSONReply(this, reply_message).SendError(error);
3634 if (!GetExtensionFromJSONArgs(
3635 args, "id", browser->profile(), &extension, &error)) {
3636 AutomationJSONReply(this, reply_message).SendError(error);
3641 if (!args->GetBoolean("enable", &enable)) {
3642 AutomationJSONReply(this, reply_message)
3643 .SendError("Missing or invalid key: enable");
3647 bool allow_in_incognito;
3648 if (!args->GetBoolean("allow_in_incognito", &allow_in_incognito)) {
3649 AutomationJSONReply(this, reply_message)
3650 .SendError("Missing or invalid key: allow_in_incognito");
3654 if (allow_in_incognito && !enable) {
3655 AutomationJSONReply(this, reply_message)
3656 .SendError("Invalid state: Disabled extension "
3657 "cannot be allowed in incognito mode.");
3661 extensions::ExtensionSystem* system =
3662 extensions::ExtensionSystem::Get(browser->profile());
3663 ExtensionService* service = system->extension_service();
3665 AutomationJSONReply(this, reply_message)
3666 .SendError("No extensions service.");
3671 if (!service->IsExtensionEnabled(extension->id())) {
3672 new ExtensionReadyNotificationObserver(
3676 service->EnableExtension(extension->id());
3678 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
3681 service->DisableExtension(extension->id(),
3682 Extension::DISABLE_USER_ACTION);
3683 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
3686 extensions::util::SetIsIncognitoEnabled(
3687 extension->id(), browser->profile(), allow_in_incognito);
3690 // See TriggerPageActionById() in chrome/test/pyautolib/pyauto.py
3691 // for sample json input.
3692 void TestingAutomationProvider::TriggerPageActionById(
3693 base::DictionaryValue* args,
3694 IPC::Message* reply_message) {
3698 if (!GetBrowserAndTabFromJSONArgs(args, &browser, &tab, &error)) {
3699 AutomationJSONReply(this, reply_message).SendError(error);
3702 const Extension* extension;
3703 if (!GetEnabledExtensionFromJSONArgs(
3704 args, "id", browser->profile(), &extension, &error)) {
3705 AutomationJSONReply(this, reply_message).SendError(error);
3708 ExtensionAction* page_action =
3709 ExtensionActionManager::Get(browser->profile())->
3710 GetPageAction(*extension);
3712 AutomationJSONReply(this, reply_message).SendError(
3713 "Extension doesn't have any page action.");
3716 EnsureTabSelected(browser, tab);
3718 bool pressed = false;
3719 LocationBarTesting* loc_bar =
3720 browser->window()->GetLocationBar()->GetLocationBarForTesting();
3721 size_t page_action_visible_count =
3722 static_cast<size_t>(loc_bar->PageActionVisibleCount());
3723 for (size_t i = 0; i < page_action_visible_count; ++i) {
3724 if (loc_bar->GetVisiblePageAction(i) == page_action) {
3725 loc_bar->TestPageActionPressed(i);
3731 AutomationJSONReply(this, reply_message).SendError(
3732 "Extension's page action is not visible.");
3736 if (page_action->HasPopup(extensions::ExtensionTabUtil::GetTabId(tab))) {
3737 // This observer will delete itself.
3738 new ExtensionPopupObserver(
3739 this, reply_message, extension->id());
3741 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
3745 // See TriggerBrowserActionById() in chrome/test/pyautolib/pyauto.py
3746 // for sample json input.
3747 void TestingAutomationProvider::TriggerBrowserActionById(
3748 base::DictionaryValue* args,
3749 IPC::Message* reply_message) {
3753 if (!GetBrowserAndTabFromJSONArgs(args, &browser, &tab, &error)) {
3754 AutomationJSONReply(this, reply_message).SendError(error);
3757 const Extension* extension;
3758 if (!GetEnabledExtensionFromJSONArgs(
3759 args, "id", browser->profile(), &extension, &error)) {
3760 AutomationJSONReply(this, reply_message).SendError(error);
3763 ExtensionAction* action = ExtensionActionManager::Get(browser->profile())->
3764 GetBrowserAction(*extension);
3766 AutomationJSONReply(this, reply_message).SendError(
3767 "Extension doesn't have any browser action.");
3770 EnsureTabSelected(browser, tab);
3772 BrowserActionTestUtil browser_actions(browser);
3773 int num_browser_actions = browser_actions.NumberOfBrowserActions();
3774 int action_index = -1;
3775 #if defined(TOOLKIT_VIEWS)
3776 for (int i = 0; i < num_browser_actions; ++i) {
3777 if (extension->id() == browser_actions.GetExtensionId(i)) {
3783 // TODO(kkania): Implement the platform-specific GetExtensionId() in
3784 // BrowserActionTestUtil.
3785 if (num_browser_actions != 1) {
3786 AutomationJSONReply(this, reply_message).SendError(base::StringPrintf(
3787 "Found %d browser actions. Only one browser action must be active.",
3788 num_browser_actions));
3791 // This extension has a browser action, and there's only one action, so this
3792 // must be the first one.
3795 if (action_index == -1) {
3796 AutomationJSONReply(this, reply_message).SendError(
3797 "Extension's browser action is not visible.");
3800 browser_actions.Press(action_index);
3802 if (action->HasPopup(extensions::ExtensionTabUtil::GetTabId(tab))) {
3803 // This observer will delete itself.
3804 new ExtensionPopupObserver(
3805 this, reply_message, extension->id());
3807 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
3811 void TestingAutomationProvider::ActionOnSSLBlockingPage(
3812 base::DictionaryValue* args,
3813 IPC::Message* reply_message) {
3814 WebContents* web_contents;
3817 if (!GetTabFromJSONArgs(args, &web_contents, &error)) {
3818 AutomationJSONReply(this, reply_message).SendError(error);
3821 if (!args->GetBoolean("proceed", &proceed)) {
3822 AutomationJSONReply(this, reply_message).SendError(
3823 "'proceed' is missing or invalid");
3826 NavigationController& controller = web_contents->GetController();
3827 NavigationEntry* entry = controller.GetActiveEntry();
3828 if (entry->GetPageType() == content::PAGE_TYPE_INTERSTITIAL) {
3829 InterstitialPage* ssl_blocking_page =
3830 InterstitialPage::GetInterstitialPage(web_contents);
3831 if (ssl_blocking_page) {
3833 new NavigationNotificationObserver(&controller, this, reply_message, 1,
3835 ssl_blocking_page->Proceed();
3838 ssl_blocking_page->DontProceed();
3839 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
3843 AutomationJSONReply(this, reply_message).SendError(error);
3846 void TestingAutomationProvider::GetSecurityState(base::DictionaryValue* args,
3847 IPC::Message* reply_message) {
3848 AutomationJSONReply reply(this, reply_message);
3849 WebContents* web_contents;
3851 if (!GetTabFromJSONArgs(args, &web_contents, &error)) {
3852 reply.SendError(error);
3855 NavigationEntry* entry = web_contents->GetController().GetActiveEntry();
3856 base::DictionaryValue dict;
3857 dict.SetInteger("security_style",
3858 static_cast<int>(entry->GetSSL().security_style));
3859 dict.SetInteger("ssl_cert_status",
3860 static_cast<int>(entry->GetSSL().cert_status));
3861 dict.SetInteger("insecure_content_status",
3862 static_cast<int>(entry->GetSSL().content_status));
3863 reply.SendSuccess(&dict);
3866 // Sample json input: { "command": "UpdateExtensionsNow" }
3867 // Sample json output: {}
3868 void TestingAutomationProvider::UpdateExtensionsNow(
3869 base::DictionaryValue* args,
3870 IPC::Message* reply_message) {
3873 if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
3874 AutomationJSONReply(this, reply_message).SendError(error);
3877 ExtensionService* service = extensions::ExtensionSystem::Get(
3878 browser->profile())->extension_service();
3880 AutomationJSONReply(this, reply_message).SendError(
3881 "No extensions service.");
3885 extensions::ExtensionUpdater* updater = service->updater();
3887 AutomationJSONReply(this, reply_message).SendError(
3888 "No updater for extensions service.");
3892 extensions::ProcessManager* manager =
3893 extensions::ExtensionSystem::Get(browser->profile())->process_manager();
3895 AutomationJSONReply(this, reply_message).SendError(
3896 "No extension process manager.");
3900 // Create a new observer that waits until the extensions have been fully
3901 // updated (we should not send the reply until after all extensions have
3902 // been updated). This observer will delete itself.
3903 ExtensionsUpdatedObserver* observer = new ExtensionsUpdatedObserver(
3904 manager, this, reply_message);
3905 extensions::ExtensionUpdater::CheckParams params;
3906 params.install_immediately = true;
3907 params.callback = base::Bind(&ExtensionsUpdatedObserver::UpdateCheckFinished,
3908 base::Unretained(observer));
3909 updater->CheckNow(params);
3914 void SendSuccessIfAlive(
3915 base::WeakPtr<AutomationProvider> provider,
3916 IPC::Message* reply_message) {
3918 AutomationJSONReply(provider.get(), reply_message).SendSuccess(NULL);
3923 void TestingAutomationProvider::OverrideGeoposition(
3924 base::DictionaryValue* args,
3925 IPC::Message* reply_message) {
3926 double latitude, longitude, altitude;
3927 if (!args->GetDouble("latitude", &latitude) ||
3928 !args->GetDouble("longitude", &longitude) ||
3929 !args->GetDouble("altitude", &altitude)) {
3930 AutomationJSONReply(this, reply_message).SendError(
3931 "Missing or invalid geolocation parameters");
3934 content::Geoposition position;
3935 position.latitude = latitude;
3936 position.longitude = longitude;
3937 position.altitude = altitude;
3938 position.accuracy = 0.;
3939 position.timestamp = base::Time::Now();
3941 content::GeolocationProvider::OverrideLocationForTesting(
3943 base::Bind(&SendSuccessIfAlive, AsWeakPtr(), reply_message));
3946 // Sample JSON input: { "command": "GetNTPInfo" }
3947 // For output, refer to chrome/test/pyautolib/ntp_model.py.
3948 void TestingAutomationProvider::GetNTPInfo(
3950 base::DictionaryValue* args,
3951 IPC::Message* reply_message) {
3952 // This observer will delete itself.
3953 new NTPInfoObserver(this, reply_message);
3956 void TestingAutomationProvider::RemoveNTPMostVisitedThumbnail(
3958 base::DictionaryValue* args,
3959 IPC::Message* reply_message) {
3960 AutomationJSONReply reply(this, reply_message);
3962 if (!args->GetString("url", &url)) {
3963 reply.SendError("Missing or invalid 'url' key.");
3966 history::TopSites* top_sites = browser->profile()->GetTopSites();
3968 reply.SendError("TopSites service is not initialized.");
3971 top_sites->AddBlacklistedURL(GURL(url));
3972 reply.SendSuccess(NULL);
3975 void TestingAutomationProvider::RestoreAllNTPMostVisitedThumbnails(
3977 base::DictionaryValue* args,
3978 IPC::Message* reply_message) {
3979 AutomationJSONReply reply(this, reply_message);
3980 history::TopSites* top_sites = browser->profile()->GetTopSites();
3982 reply.SendError("TopSites service is not initialized.");
3985 top_sites->ClearBlacklistedURLs();
3986 reply.SendSuccess(NULL);
3989 void TestingAutomationProvider::KillRendererProcess(
3991 base::DictionaryValue* args,
3992 IPC::Message* reply_message) {
3994 uint32 kAccessFlags = base::kProcessAccessTerminate |
3995 base::kProcessAccessWaitForTermination |
3996 base::kProcessAccessQueryInformation;
3998 if (!args->GetInteger("pid", &pid)) {
3999 AutomationJSONReply(this, reply_message)
4000 .SendError("'pid' key missing or invalid.");
4003 base::ProcessHandle process;
4004 if (!base::OpenProcessHandleWithAccess(static_cast<base::ProcessId>(pid),
4007 AutomationJSONReply(this, reply_message).SendError(base::StringPrintf(
4008 "Failed to open process handle for pid %d", pid));
4011 new RendererProcessClosedObserver(this, reply_message);
4012 base::KillProcess(process, 0, false);
4013 base::CloseProcessHandle(process);
4016 bool TestingAutomationProvider::BuildWebKeyEventFromArgs(
4017 base::DictionaryValue* args,
4019 NativeWebKeyboardEvent* event) {
4020 int type, modifiers;
4022 base::string16 unmodified_text, text;
4023 std::string key_identifier;
4024 if (!args->GetInteger("type", &type)) {
4025 *error = "'type' missing or invalid.";
4028 if (!args->GetBoolean("isSystemKey", &is_system_key)) {
4029 *error = "'isSystemKey' missing or invalid.";
4032 if (!args->GetString("unmodifiedText", &unmodified_text)) {
4033 *error = "'unmodifiedText' missing or invalid.";
4036 if (!args->GetString("text", &text)) {
4037 *error = "'text' missing or invalid.";
4040 if (!args->GetInteger("nativeKeyCode", &event->nativeKeyCode)) {
4041 *error = "'nativeKeyCode' missing or invalid.";
4044 if (!args->GetInteger("windowsKeyCode", &event->windowsKeyCode)) {
4045 *error = "'windowsKeyCode' missing or invalid.";
4048 if (!args->GetInteger("modifiers", &modifiers)) {
4049 *error = "'modifiers' missing or invalid.";
4052 if (args->GetString("keyIdentifier", &key_identifier)) {
4053 base::strlcpy(event->keyIdentifier,
4054 key_identifier.c_str(),
4055 blink::WebKeyboardEvent::keyIdentifierLengthCap);
4057 *error = "'keyIdentifier' missing or invalid.";
4061 if (type == automation::kRawKeyDownType) {
4062 event->type = blink::WebInputEvent::RawKeyDown;
4063 } else if (type == automation::kKeyDownType) {
4064 event->type = blink::WebInputEvent::KeyDown;
4065 } else if (type == automation::kKeyUpType) {
4066 event->type = blink::WebInputEvent::KeyUp;
4067 } else if (type == automation::kCharType) {
4068 event->type = blink::WebInputEvent::Char;
4070 *error = "'type' refers to an unrecognized keyboard event type";
4074 base::string16 unmodified_text_truncated = unmodified_text.substr(
4075 0, blink::WebKeyboardEvent::textLengthCap - 1);
4076 memcpy(event->unmodifiedText,
4077 unmodified_text_truncated.c_str(),
4078 unmodified_text_truncated.length() + 1);
4079 base::string16 text_truncated = text.substr(
4080 0, blink::WebKeyboardEvent::textLengthCap - 1);
4081 memcpy(event->text, text_truncated.c_str(), text_truncated.length() + 1);
4083 event->modifiers = 0;
4084 if (modifiers & automation::kShiftKeyMask)
4085 event->modifiers |= blink::WebInputEvent::ShiftKey;
4086 if (modifiers & automation::kControlKeyMask)
4087 event->modifiers |= blink::WebInputEvent::ControlKey;
4088 if (modifiers & automation::kAltKeyMask)
4089 event->modifiers |= blink::WebInputEvent::AltKey;
4090 if (modifiers & automation::kMetaKeyMask)
4091 event->modifiers |= blink::WebInputEvent::MetaKey;
4093 event->isSystemKey = is_system_key;
4094 event->timeStampSeconds = base::Time::Now().ToDoubleT();
4095 event->skip_in_browser = true;
4099 void TestingAutomationProvider::SendWebkitKeyEvent(
4100 base::DictionaryValue* args,
4101 IPC::Message* reply_message) {
4102 if (SendErrorIfModalDialogActive(this, reply_message))
4105 NativeWebKeyboardEvent event;
4106 // In the event of an error, BuildWebKeyEventFromArgs handles telling what
4107 // went wrong and sending the reply message; if it fails, we just have to
4110 if (!BuildWebKeyEventFromArgs(args, &error, &event)) {
4111 AutomationJSONReply(this, reply_message).SendError(error);
4115 RenderViewHost* view;
4116 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
4117 AutomationJSONReply(this, reply_message).SendError(error);
4120 new InputEventAckNotificationObserver(this, reply_message, event.type, 1);
4121 view->ForwardKeyboardEvent(event);
4126 // Gets the active JavaScript modal dialog, or NULL if none.
4127 JavaScriptAppModalDialog* GetActiveJavaScriptModalDialog(
4128 std::string* error_msg) {
4129 AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance();
4130 if (!dialog_queue->HasActiveDialog() ||
4131 !dialog_queue->active_dialog()->IsJavaScriptModalDialog()) {
4132 *error_msg = "No JavaScriptModalDialog open";
4135 return static_cast<JavaScriptAppModalDialog*>(dialog_queue->active_dialog());
4140 void TestingAutomationProvider::GetAppModalDialogMessage(
4141 base::DictionaryValue* args, IPC::Message* reply_message) {
4142 AutomationJSONReply reply(this, reply_message);
4143 std::string error_msg;
4144 JavaScriptAppModalDialog* dialog = GetActiveJavaScriptModalDialog(&error_msg);
4146 reply.SendError(error_msg);
4149 base::DictionaryValue result_dict;
4150 result_dict.SetString("message", base::UTF16ToUTF8(dialog->message_text()));
4151 reply.SendSuccess(&result_dict);
4154 void TestingAutomationProvider::AcceptOrDismissAppModalDialog(
4155 base::DictionaryValue* args, IPC::Message* reply_message) {
4156 AutomationJSONReply reply(this, reply_message);
4158 if (!args->GetBoolean("accept", &accept)) {
4159 reply.SendError("Missing or invalid 'accept'");
4163 std::string error_msg;
4164 JavaScriptAppModalDialog* dialog = GetActiveJavaScriptModalDialog(&error_msg);
4166 reply.SendError(error_msg);
4170 std::string prompt_text;
4171 if (args->GetString("prompt_text", &prompt_text))
4172 dialog->SetOverridePromptText(base::UTF8ToUTF16(prompt_text));
4173 dialog->native_dialog()->AcceptAppModalDialog();
4175 dialog->native_dialog()->CancelAppModalDialog();
4177 reply.SendSuccess(NULL);
4180 // Sample JSON input: { "command": "LaunchApp",
4181 // "id": "ahfgeienlihckogmohjhadlkjgocpleb" }
4182 // Sample JSON output: {}
4183 void TestingAutomationProvider::LaunchApp(
4185 base::DictionaryValue* args,
4186 IPC::Message* reply_message) {
4188 if (!args->GetString("id", &id)) {
4189 AutomationJSONReply(this, reply_message).SendError(
4190 "Must include string id.");
4194 ExtensionService* service = extensions::ExtensionSystem::Get(
4195 browser->profile())->extension_service();
4197 AutomationJSONReply(this, reply_message).SendError(
4198 "No extensions service.");
4202 const Extension* extension = service->GetExtensionById(
4203 id, false /* do not include disabled extensions */);
4205 AutomationJSONReply(this, reply_message).SendError(
4207 "Extension with ID '%s' doesn't exist or is disabled.",
4212 WebContents* old_contents =
4213 browser->tab_strip_model()->GetActiveWebContents();
4214 if (!old_contents) {
4215 AutomationJSONReply(this, reply_message).SendError(
4216 "Cannot identify selected tab contents.");
4220 AppLaunchParams launch_params(profile(), extension, CURRENT_TAB);
4221 // This observer will delete itself.
4222 new AppLaunchObserver(&old_contents->GetController(), this, reply_message,
4223 launch_params.container);
4224 OpenApplication(launch_params);
4227 // Sample JSON input: { "command": "SetAppLaunchType",
4228 // "id": "ahfgeienlihckogmohjhadlkjgocpleb",
4229 // "launch_type": "pinned" }
4230 // Sample JSON output: {}
4231 void TestingAutomationProvider::SetAppLaunchType(
4233 base::DictionaryValue* args,
4234 IPC::Message* reply_message) {
4235 AutomationJSONReply reply(this, reply_message);
4238 if (!args->GetString("id", &id)) {
4239 reply.SendError("Must include string id.");
4243 std::string launch_type_str;
4244 if (!args->GetString("launch_type", &launch_type_str)) {
4245 reply.SendError("Must specify app launch type.");
4249 ExtensionService* service = extensions::ExtensionSystem::Get(
4250 browser->profile())->extension_service();
4252 reply.SendError("No extensions service.");
4256 const Extension* extension = service->GetExtensionById(
4257 id, true /* include disabled extensions */);
4259 reply.SendError(base::StringPrintf(
4260 "Extension with ID '%s' doesn't exist.", id.c_str()));
4264 extensions::LaunchType launch_type;
4265 if (launch_type_str == "pinned") {
4266 launch_type = extensions::LAUNCH_TYPE_PINNED;
4267 } else if (launch_type_str == "regular") {
4268 launch_type = extensions::LAUNCH_TYPE_REGULAR;
4269 } else if (launch_type_str == "fullscreen") {
4270 launch_type = extensions::LAUNCH_TYPE_FULLSCREEN;
4271 } else if (launch_type_str == "window") {
4272 launch_type = extensions::LAUNCH_TYPE_WINDOW;
4274 reply.SendError(base::StringPrintf(
4275 "Unexpected launch type '%s'.", launch_type_str.c_str()));
4279 extensions::SetLaunchType(service, extension->id(), launch_type);
4280 reply.SendSuccess(NULL);
4283 // Sample json input: { "command": "GetV8HeapStats",
4285 // Refer to GetV8HeapStats() in chrome/test/pyautolib/pyauto.py for
4286 // sample json output.
4287 void TestingAutomationProvider::GetV8HeapStats(
4289 base::DictionaryValue* args,
4290 IPC::Message* reply_message) {
4291 WebContents* web_contents;
4294 if (!args->GetInteger("tab_index", &tab_index)) {
4295 AutomationJSONReply(this, reply_message).SendError(
4296 "Missing 'tab_index' argument.");
4300 web_contents = browser->tab_strip_model()->GetWebContentsAt(tab_index);
4301 if (!web_contents) {
4302 AutomationJSONReply(this, reply_message).SendError(base::StringPrintf(
4303 "Could not get WebContents at tab index %d", tab_index));
4307 RenderViewHost* render_view = web_contents->GetRenderViewHost();
4309 // This observer will delete itself.
4310 new V8HeapStatsObserver(
4311 this, reply_message,
4312 base::GetProcId(render_view->GetProcess()->GetHandle()));
4313 render_view->Send(new ChromeViewMsg_GetV8HeapStats);
4316 // Sample json input: { "command": "GetFPS",
4318 // Refer to GetFPS() in chrome/test/pyautolib/pyauto.py for
4319 // sample json output.
4320 void TestingAutomationProvider::GetFPS(
4322 base::DictionaryValue* args,
4323 IPC::Message* reply_message) {
4324 WebContents* web_contents;
4327 if (!args->GetInteger("tab_index", &tab_index)) {
4328 AutomationJSONReply(this, reply_message).SendError(
4329 "Missing 'tab_index' argument.");
4333 web_contents = browser->tab_strip_model()->GetWebContentsAt(tab_index);
4334 if (!web_contents) {
4335 AutomationJSONReply(this, reply_message).SendError(base::StringPrintf(
4336 "Could not get WebContents at tab index %d", tab_index));
4340 RenderViewHost* render_view = web_contents->GetRenderViewHost();
4341 int routing_id = render_view->GetRoutingID();
4343 // This observer will delete itself.
4345 this, reply_message,
4346 base::GetProcId(render_view->GetProcess()->GetHandle()),
4348 render_view->Send(new ChromeViewMsg_GetFPS(routing_id));
4351 void TestingAutomationProvider::IsFullscreenForBrowser(Browser* browser,
4352 base::DictionaryValue* args,
4353 IPC::Message* reply_message) {
4354 base::DictionaryValue dict;
4355 dict.SetBoolean("result",
4356 browser->fullscreen_controller()->IsFullscreenForBrowser());
4357 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
4360 void TestingAutomationProvider::IsFullscreenForTab(Browser* browser,
4361 base::DictionaryValue* args,
4362 IPC::Message* reply_message) {
4363 base::DictionaryValue dict;
4364 dict.SetBoolean("result",
4365 browser->fullscreen_controller()->IsFullscreenForTabOrPending());
4366 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
4369 void TestingAutomationProvider::IsMouseLocked(Browser* browser,
4370 base::DictionaryValue* args,
4371 IPC::Message* reply_message) {
4372 base::DictionaryValue dict;
4373 dict.SetBoolean("result", browser->tab_strip_model()->GetActiveWebContents()->
4374 GetRenderViewHost()->GetView()->IsMouseLocked());
4375 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
4378 void TestingAutomationProvider::IsMouseLockPermissionRequested(
4380 base::DictionaryValue* args,
4381 IPC::Message* reply_message) {
4382 FullscreenExitBubbleType type =
4383 browser->fullscreen_controller()->GetFullscreenExitBubbleType();
4384 bool mouse_lock = false;
4385 fullscreen_bubble::PermissionRequestedByType(type, NULL, &mouse_lock);
4386 base::DictionaryValue dict;
4387 dict.SetBoolean("result", mouse_lock);
4388 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
4391 void TestingAutomationProvider::IsFullscreenPermissionRequested(
4393 base::DictionaryValue* args,
4394 IPC::Message* reply_message) {
4395 FullscreenExitBubbleType type =
4396 browser->fullscreen_controller()->GetFullscreenExitBubbleType();
4397 bool fullscreen = false;
4398 fullscreen_bubble::PermissionRequestedByType(type, &fullscreen, NULL);
4399 base::DictionaryValue dict;
4400 dict.SetBoolean("result", fullscreen);
4401 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
4404 void TestingAutomationProvider::IsFullscreenBubbleDisplayed(Browser* browser,
4405 base::DictionaryValue* args,
4406 IPC::Message* reply_message) {
4407 FullscreenExitBubbleType type =
4408 browser->fullscreen_controller()->GetFullscreenExitBubbleType();
4409 base::DictionaryValue dict;
4410 dict.SetBoolean("result",
4411 type != FEB_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION);
4412 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
4415 void TestingAutomationProvider::IsFullscreenBubbleDisplayingButtons(
4417 base::DictionaryValue* args,
4418 IPC::Message* reply_message) {
4419 FullscreenExitBubbleType type =
4420 browser->fullscreen_controller()->GetFullscreenExitBubbleType();
4421 base::DictionaryValue dict;
4422 dict.SetBoolean("result", fullscreen_bubble::ShowButtonsForType(type));
4423 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
4426 void TestingAutomationProvider::AcceptCurrentFullscreenOrMouseLockRequest(
4428 base::DictionaryValue* args,
4429 IPC::Message* reply_message) {
4430 browser->fullscreen_controller()->OnAcceptFullscreenPermission();
4431 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
4434 void TestingAutomationProvider::DenyCurrentFullscreenOrMouseLockRequest(
4436 base::DictionaryValue* args,
4437 IPC::Message* reply_message) {
4438 browser->fullscreen_controller()->OnDenyFullscreenPermission();
4439 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
4442 void TestingAutomationProvider::WaitForTabToBeRestored(
4443 base::DictionaryValue* args,
4444 IPC::Message* reply_message) {
4445 WebContents* web_contents;
4447 if (!GetTabFromJSONArgs(args, &web_contents, &error)) {
4448 AutomationJSONReply(this, reply_message).SendError(error);
4451 NavigationController& controller = web_contents->GetController();
4452 new NavigationControllerRestoredObserver(this, &controller, reply_message);
4455 void TestingAutomationProvider::RefreshPolicies(
4456 base::DictionaryValue* args,
4457 IPC::Message* reply_message) {
4458 #if !defined(ENABLE_CONFIGURATION_POLICY)
4459 AutomationJSONReply(this, reply_message).SendError(
4460 "Configuration Policy disabled");
4462 // Some policies (e.g. URLBlacklist) post tasks to other message loops
4463 // before they start enforcing updated policy values; make sure those tasks
4464 // have finished after a policy update.
4465 // Updates of the URLBlacklist are done on IO, after building the blacklist
4466 // on FILE, which is initiated from IO.
4467 base::Closure reply =
4468 base::Bind(SendSuccessReply, AsWeakPtr(), reply_message);
4469 g_browser_process->policy_service()->RefreshPolicies(
4470 base::Bind(PostTask, BrowserThread::IO,
4471 base::Bind(PostTask, BrowserThread::FILE,
4472 base::Bind(PostTask, BrowserThread::IO,
4473 base::Bind(PostTask, BrowserThread::UI, reply)))));
4477 static int AccessArray(const volatile int arr[], const volatile int *index) {
4481 void TestingAutomationProvider::SimulateAsanMemoryBug(
4482 base::DictionaryValue* args, IPC::Message* reply_message) {
4483 // This array is volatile not to let compiler optimize us out.
4484 volatile int testarray[3] = {0, 0, 0};
4486 // Send the reply while we can.
4487 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
4489 // Cause Address Sanitizer to abort this process.
4490 volatile int index = 5;
4491 AccessArray(testarray, &index);
4494 void TestingAutomationProvider::GetIndicesFromTab(
4495 base::DictionaryValue* args,
4496 IPC::Message* reply_message) {
4497 AutomationJSONReply reply(this, reply_message);
4498 int id_or_handle = 0;
4499 bool has_id = args->HasKey("tab_id");
4500 bool has_handle = args->HasKey("tab_handle");
4501 if (has_id && has_handle) {
4503 "Both 'tab_id' and 'tab_handle' were specified. Only one is allowed");
4505 } else if (!has_id && !has_handle) {
4506 reply.SendError("Either 'tab_id' or 'tab_handle' must be specified");
4509 if (has_id && !args->GetInteger("tab_id", &id_or_handle)) {
4510 reply.SendError("'tab_id' is invalid");
4513 if (has_handle && (!args->GetInteger("tab_handle", &id_or_handle) ||
4514 !tab_tracker_->ContainsHandle(id_or_handle))) {
4515 reply.SendError("'tab_handle' is invalid");
4518 int id = id_or_handle;
4520 SessionTabHelper* session_tab_helper =
4521 SessionTabHelper::FromWebContents(
4522 tab_tracker_->GetResource(id_or_handle)->GetWebContents());
4523 id = session_tab_helper->session_id().id();
4525 chrome::BrowserIterator it;
4526 int browser_index = 0;
4527 for (; !it.done(); it.Next(), ++browser_index) {
4528 Browser* browser = *it;
4529 for (int tab_index = 0;
4530 tab_index < browser->tab_strip_model()->count();
4533 browser->tab_strip_model()->GetWebContentsAt(tab_index);
4534 SessionTabHelper* session_tab_helper =
4535 SessionTabHelper::FromWebContents(tab);
4536 if (session_tab_helper->session_id().id() == id) {
4537 base::DictionaryValue dict;
4538 dict.SetInteger("windex", browser_index);
4539 dict.SetInteger("tab_index", tab_index);
4540 reply.SendSuccess(&dict);
4545 reply.SendError("Could not find tab among current browser windows");
4548 void TestingAutomationProvider::NavigateToURL(
4549 base::DictionaryValue* args,
4550 IPC::Message* reply_message) {
4551 if (SendErrorIfModalDialogActive(this, reply_message))
4554 int navigation_count;
4555 std::string url, error;
4557 WebContents* web_contents;
4558 if (!GetBrowserAndTabFromJSONArgs(args, &browser, &web_contents, &error)) {
4559 AutomationJSONReply(this, reply_message).SendError(error);
4562 if (!args->GetString("url", &url)) {
4563 AutomationJSONReply(this, reply_message)
4564 .SendError("'url' missing or invalid");
4567 if (!args->GetInteger("navigation_count", &navigation_count)) {
4568 AutomationJSONReply(this, reply_message)
4569 .SendError("'navigation_count' missing or invalid");
4572 if (navigation_count > 0) {
4573 new NavigationNotificationObserver(
4574 &web_contents->GetController(), this, reply_message,
4575 navigation_count, false, true);
4577 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
4579 OpenURLParams params(
4580 GURL(url), content::Referrer(), CURRENT_TAB,
4581 content::PageTransitionFromInt(
4582 content::PAGE_TRANSITION_TYPED |
4583 content::PAGE_TRANSITION_FROM_ADDRESS_BAR),
4585 browser->OpenURLFromTab(web_contents, params);
4588 void TestingAutomationProvider::GetActiveTabIndexJSON(
4589 base::DictionaryValue* args,
4590 IPC::Message* reply_message) {
4591 AutomationJSONReply reply(this, reply_message);
4593 std::string error_msg;
4594 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
4595 reply.SendError(error_msg);
4598 int tab_index = browser->tab_strip_model()->active_index();
4599 scoped_ptr<base::DictionaryValue> return_value(new base::DictionaryValue);
4600 return_value->SetInteger("tab_index", tab_index);
4601 reply.SendSuccess(return_value.get());
4604 void TestingAutomationProvider::AppendTabJSON(base::DictionaryValue* args,
4605 IPC::Message* reply_message) {
4606 TabAppendedNotificationObserver* observer = NULL;
4607 int append_tab_response = -1;
4609 std::string error_msg, url;
4610 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) {
4611 AutomationJSONReply(this, reply_message).SendError(error_msg);
4614 if (!args->GetString("url", &url)) {
4615 AutomationJSONReply(this, reply_message)
4616 .SendError("'url' missing or invalid");
4619 observer = new TabAppendedNotificationObserver(browser, this, reply_message,
4621 WebContents* contents =
4622 chrome::AddSelectedTabWithURL(browser, GURL(url),
4623 content::PAGE_TRANSITION_TYPED);
4625 append_tab_response = GetIndexForNavigationController(
4626 &contents->GetController(), browser);
4629 if (!contents || append_tab_response < 0) {
4631 observer->ReleaseReply();
4634 AutomationJSONReply(this, reply_message).SendError("Failed to append tab.");
4638 void TestingAutomationProvider::WaitUntilNavigationCompletes(
4639 base::DictionaryValue* args,
4640 IPC::Message* reply_message) {
4641 if (SendErrorIfModalDialogActive(this, reply_message))
4646 WebContents* web_contents;
4647 if (!GetBrowserAndTabFromJSONArgs(args, &browser, &web_contents, &error)) {
4648 AutomationJSONReply(this, reply_message).SendError(error);
4651 NavigationNotificationObserver* observer =
4652 new NavigationNotificationObserver(&web_contents->GetController(), this,
4653 reply_message, 1, true, true);
4654 if (!web_contents->IsLoading()) {
4655 observer->ConditionMet(AUTOMATION_MSG_NAVIGATION_SUCCESS);
4660 void TestingAutomationProvider::ExecuteJavascriptJSON(
4661 base::DictionaryValue* args,
4662 IPC::Message* reply_message) {
4663 if (SendErrorIfModalDialogActive(this, reply_message))
4666 base::string16 frame_xpath, javascript;
4668 RenderViewHost* render_view;
4669 if (!GetRenderViewFromJSONArgs(args, profile(), &render_view, &error)) {
4670 AutomationJSONReply(this, reply_message).SendError(error);
4673 if (!args->GetString("frame_xpath", &frame_xpath)) {
4674 AutomationJSONReply(this, reply_message)
4675 .SendError("'frame_xpath' missing or invalid");
4678 if (!args->GetString("javascript", &javascript)) {
4679 AutomationJSONReply(this, reply_message)
4680 .SendError("'javascript' missing or invalid");
4684 new DomOperationMessageSender(this, reply_message, true);
4685 ExecuteJavascriptInRenderViewFrame(frame_xpath, javascript, reply_message,
4689 void TestingAutomationProvider::ExecuteJavascriptInRenderView(
4690 base::DictionaryValue* args,
4691 IPC::Message* reply_message) {
4692 base::string16 frame_xpath, javascript, extension_id, url_text;
4693 int render_process_id, render_view_id;
4694 if (!args->GetString("frame_xpath", &frame_xpath)) {
4695 AutomationJSONReply(this, reply_message)
4696 .SendError("'frame_xpath' missing or invalid");
4699 if (!args->GetString("javascript", &javascript)) {
4700 AutomationJSONReply(this, reply_message)
4701 .SendError("'javascript' missing or invalid");
4704 if (!args->GetInteger("view.render_process_id", &render_process_id)) {
4705 AutomationJSONReply(this, reply_message)
4706 .SendError("'view.render_process_id' missing or invalid");
4709 if (!args->GetInteger("view.render_view_id", &render_view_id)) {
4710 AutomationJSONReply(this, reply_message)
4711 .SendError("'view.render_view_id' missing or invalid");
4715 RenderViewHost* rvh = RenderViewHost::FromID(render_process_id,
4718 AutomationJSONReply(this, reply_message).SendError(
4719 "A RenderViewHost object was not found with the given view ID.");
4723 new DomOperationMessageSender(this, reply_message, true);
4724 ExecuteJavascriptInRenderViewFrame(frame_xpath, javascript, reply_message,
4728 void TestingAutomationProvider::AddDomEventObserver(
4729 base::DictionaryValue* args,
4730 IPC::Message* reply_message) {
4731 if (SendErrorIfModalDialogActive(this, reply_message))
4734 AutomationJSONReply reply(this, reply_message);
4735 std::string event_name;
4738 if (!args->GetString("event_name", &event_name)) {
4739 reply.SendError("'event_name' missing or invalid");
4742 if (!args->GetInteger("automation_id", &automation_id)) {
4743 reply.SendError("'automation_id' missing or invalid");
4746 if (!args->GetBoolean("recurring", &recurring)) {
4747 reply.SendError("'recurring' missing or invalid");
4751 if (!automation_event_queue_.get())
4752 automation_event_queue_.reset(new AutomationEventQueue);
4754 int observer_id = automation_event_queue_->AddObserver(
4755 new DomEventObserver(automation_event_queue_.get(), event_name,
4756 automation_id, recurring));
4757 scoped_ptr<base::DictionaryValue> return_value(new base::DictionaryValue);
4758 return_value->SetInteger("observer_id", observer_id);
4759 reply.SendSuccess(return_value.get());
4762 void TestingAutomationProvider::RemoveEventObserver(
4763 base::DictionaryValue* args,
4764 IPC::Message* reply_message) {
4765 AutomationJSONReply reply(this, reply_message);
4767 if (!args->GetInteger("observer_id", &observer_id) ||
4768 !automation_event_queue_.get()) {
4769 reply.SendError("'observer_id' missing or invalid");
4772 if (automation_event_queue_->RemoveObserver(observer_id)) {
4773 reply.SendSuccess(NULL);
4776 reply.SendError("Invalid observer id.");
4779 void TestingAutomationProvider::ClearEventQueue(
4780 base::DictionaryValue* args,
4781 IPC::Message* reply_message) {
4782 automation_event_queue_.reset();
4783 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
4786 void TestingAutomationProvider::GetNextEvent(
4787 base::DictionaryValue* args,
4788 IPC::Message* reply_message) {
4789 scoped_ptr<AutomationJSONReply> reply(
4790 new AutomationJSONReply(this, reply_message));
4793 if (!args->GetInteger("observer_id", &observer_id)) {
4794 reply->SendError("'observer_id' missing or invalid");
4797 if (!args->GetBoolean("blocking", &blocking)) {
4798 reply->SendError("'blocking' missing or invalid");
4801 if (!automation_event_queue_.get()) {
4803 "No observers are attached to the queue. Did you create any?");
4807 // The reply will be freed once a matching event is added to the queue.
4808 automation_event_queue_->GetNextEvent(reply.release(), observer_id, blocking);
4811 void TestingAutomationProvider::GoForward(
4812 base::DictionaryValue* args,
4813 IPC::Message* reply_message) {
4814 if (SendErrorIfModalDialogActive(this, reply_message))
4817 WebContents* web_contents;
4819 if (!GetTabFromJSONArgs(args, &web_contents, &error)) {
4820 AutomationJSONReply(this, reply_message).SendError(error);
4823 NavigationController& controller = web_contents->GetController();
4824 if (!controller.CanGoForward()) {
4825 base::DictionaryValue dict;
4826 dict.SetBoolean("did_go_forward", false);
4827 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
4830 new NavigationNotificationObserver(&controller, this, reply_message,
4832 controller.GoForward();
4835 void TestingAutomationProvider::ExecuteBrowserCommandAsyncJSON(
4836 base::DictionaryValue* args,
4837 IPC::Message* reply_message) {
4838 AutomationJSONReply reply(this, reply_message);
4842 if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
4843 reply.SendError(error);
4846 if (!args->GetInteger("accelerator", &command)) {
4847 reply.SendError("'accelerator' missing or invalid.");
4850 if (!chrome::SupportsCommand(browser, command)) {
4851 reply.SendError(base::StringPrintf("Browser does not support command=%d.",
4855 if (!chrome::IsCommandEnabled(browser, command)) {
4856 reply.SendError(base::StringPrintf(
4857 "Browser command=%d not enabled.", command));
4860 chrome::ExecuteCommand(browser, command);
4861 reply.SendSuccess(NULL);
4864 void TestingAutomationProvider::ExecuteBrowserCommandJSON(
4865 base::DictionaryValue* args,
4866 IPC::Message* reply_message) {
4870 if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
4871 AutomationJSONReply(this, reply_message).SendError(error);
4874 if (!args->GetInteger("accelerator", &command)) {
4875 AutomationJSONReply(this, reply_message).SendError(
4876 "'accelerator' missing or invalid.");
4879 if (!chrome::SupportsCommand(browser, command)) {
4880 AutomationJSONReply(this, reply_message).SendError(
4881 base::StringPrintf("Browser does not support command=%d.", command));
4884 if (!chrome::IsCommandEnabled(browser, command)) {
4885 AutomationJSONReply(this, reply_message).SendError(
4886 base::StringPrintf("Browser command=%d not enabled.", command));
4889 // First check if we can handle the command without using an observer.
4890 for (size_t i = 0; i < arraysize(kSynchronousCommands); i++) {
4891 if (command == kSynchronousCommands[i]) {
4892 chrome::ExecuteCommand(browser, command);
4893 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
4897 // Use an observer if we have one, otherwise fail.
4898 if (ExecuteBrowserCommandObserver::CreateAndRegisterObserver(
4899 this, browser, command, reply_message, true)) {
4900 chrome::ExecuteCommand(browser, command);
4903 AutomationJSONReply(this, reply_message).SendError(base::StringPrintf(
4904 "Unable to register observer for browser command=%d.", command));
4907 void TestingAutomationProvider::IsMenuCommandEnabledJSON(
4908 base::DictionaryValue* args,
4909 IPC::Message* reply_message) {
4913 if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
4914 AutomationJSONReply(this, reply_message).SendError(error);
4917 if (!args->GetInteger("accelerator", &command)) {
4918 AutomationJSONReply(this, reply_message).SendError(
4919 "'accelerator' missing or invalid.");
4922 base::DictionaryValue dict;
4923 dict.SetBoolean("enabled", chrome::IsCommandEnabled(browser, command));
4924 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
4927 void TestingAutomationProvider::GetTabInfo(
4928 base::DictionaryValue* args,
4929 IPC::Message* reply_message) {
4930 AutomationJSONReply reply(this, reply_message);
4934 if (GetBrowserAndTabFromJSONArgs(args, &browser, &tab, &error)) {
4935 NavigationEntry* entry = tab->GetController().GetActiveEntry();
4937 reply.SendError("Unable to get active navigation entry");
4940 base::DictionaryValue dict;
4941 dict.SetString("title", entry->GetTitleForDisplay(std::string()));
4942 dict.SetString("url", entry->GetVirtualURL().spec());
4943 reply.SendSuccess(&dict);
4945 reply.SendError(error);
4949 void TestingAutomationProvider::GetTabCountJSON(
4950 base::DictionaryValue* args,
4951 IPC::Message* reply_message) {
4952 AutomationJSONReply reply(this, reply_message);
4955 if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
4956 reply.SendError(error);
4959 base::DictionaryValue dict;
4960 dict.SetInteger("tab_count", browser->tab_strip_model()->count());
4961 reply.SendSuccess(&dict);
4964 void TestingAutomationProvider::GoBack(
4965 base::DictionaryValue* args,
4966 IPC::Message* reply_message) {
4967 if (SendErrorIfModalDialogActive(this, reply_message))
4970 WebContents* web_contents;
4972 if (!GetTabFromJSONArgs(args, &web_contents, &error)) {
4973 AutomationJSONReply(this, reply_message).SendError(error);
4976 NavigationController& controller = web_contents->GetController();
4977 if (!controller.CanGoBack()) {
4978 base::DictionaryValue dict;
4979 dict.SetBoolean("did_go_back", false);
4980 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
4983 new NavigationNotificationObserver(&controller, this, reply_message,
4985 controller.GoBack();
4988 void TestingAutomationProvider::ReloadJSON(
4989 base::DictionaryValue* args,
4990 IPC::Message* reply_message) {
4991 if (SendErrorIfModalDialogActive(this, reply_message))
4994 WebContents* web_contents;
4996 if (!GetTabFromJSONArgs(args, &web_contents, &error)) {
4997 AutomationJSONReply(this, reply_message).SendError(error);
5000 NavigationController& controller = web_contents->GetController();
5001 new NavigationNotificationObserver(&controller, this, reply_message,
5003 controller.Reload(false);
5006 void TestingAutomationProvider::GetCookiesJSON(
5007 base::DictionaryValue* args, IPC::Message* reply_message) {
5008 automation_util::GetCookiesJSON(this, args, reply_message);
5011 void TestingAutomationProvider::DeleteCookieJSON(
5012 base::DictionaryValue* args, IPC::Message* reply_message) {
5013 automation_util::DeleteCookieJSON(this, args, reply_message);
5016 void TestingAutomationProvider::SetCookieJSON(
5017 base::DictionaryValue* args, IPC::Message* reply_message) {
5018 automation_util::SetCookieJSON(this, args, reply_message);
5021 void TestingAutomationProvider::GetCookiesInBrowserContext(
5022 base::DictionaryValue* args,
5023 IPC::Message* reply_message) {
5024 AutomationJSONReply reply(this, reply_message);
5025 WebContents* web_contents;
5026 std::string value, url_string;
5027 int windex, value_size;
5028 if (!args->GetInteger("windex", &windex)) {
5029 reply.SendError("'windex' missing or invalid.");
5032 web_contents = automation_util::GetWebContentsAt(windex, 0);
5033 if (!web_contents) {
5034 reply.SendError("'windex' does not refer to a browser window.");
5037 if (!args->GetString("url", &url_string)) {
5038 reply.SendError("'url' missing or invalid.");
5041 GURL url(url_string);
5042 if (!url.is_valid()) {
5043 reply.SendError("Invalid url.");
5046 automation_util::GetCookies(url, web_contents, &value_size, &value);
5047 if (value_size == -1) {
5049 base::StringPrintf("Unable to retrieve cookies for url=%s.",
5050 url_string.c_str()));
5053 base::DictionaryValue dict;
5054 dict.SetString("cookies", value);
5055 reply.SendSuccess(&dict);
5058 void TestingAutomationProvider::DeleteCookieInBrowserContext(
5059 base::DictionaryValue* args,
5060 IPC::Message* reply_message) {
5061 AutomationJSONReply reply(this, reply_message);
5062 WebContents* web_contents;
5063 std::string cookie_name, url_string;
5065 bool success = false;
5066 if (!args->GetInteger("windex", &windex)) {
5067 reply.SendError("'windex' missing or invalid.");
5070 web_contents = automation_util::GetWebContentsAt(windex, 0);
5071 if (!web_contents) {
5072 reply.SendError("'windex' does not refer to a browser window.");
5075 if (!args->GetString("cookie_name", &cookie_name)) {
5076 reply.SendError("'cookie_name' missing or invalid.");
5079 if (!args->GetString("url", &url_string)) {
5080 reply.SendError("'url' missing or invalid.");
5083 GURL url(url_string);
5084 if (!url.is_valid()) {
5085 reply.SendError("Invalid url.");
5088 automation_util::DeleteCookie(url, cookie_name, web_contents, &success);
5091 base::StringPrintf("Failed to delete cookie with name=%s for url=%s.",
5092 cookie_name.c_str(), url_string.c_str()));
5095 reply.SendSuccess(NULL);
5098 void TestingAutomationProvider::SetCookieInBrowserContext(
5099 base::DictionaryValue* args,
5100 IPC::Message* reply_message) {
5101 AutomationJSONReply reply(this, reply_message);
5102 WebContents* web_contents;
5103 std::string value, url_string;
5104 int windex, response_value = -1;
5105 if (!args->GetInteger("windex", &windex)) {
5106 reply.SendError("'windex' missing or invalid.");
5109 web_contents = automation_util::GetWebContentsAt(windex, 0);
5110 if (!web_contents) {
5111 reply.SendError("'windex' does not refer to a browser window.");
5114 if (!args->GetString("value", &value)) {
5115 reply.SendError("'value' missing or invalid.");
5118 if (!args->GetString("url", &url_string)) {
5119 reply.SendError("'url' missing or invalid.");
5122 GURL url(url_string);
5123 if (!url.is_valid()) {
5124 reply.SendError("Invalid url.");
5127 automation_util::SetCookie(url, value, web_contents, &response_value);
5128 if (response_value != 1) {
5129 reply.SendError(base::StringPrintf(
5130 "Unable set cookie for url=%s.", url_string.c_str()));
5133 reply.SendSuccess(NULL);
5136 void TestingAutomationProvider::GetTabIds(
5137 base::DictionaryValue* args, IPC::Message* reply_message) {
5138 base::ListValue* id_list = new base::ListValue();
5139 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
5140 Browser* browser = *it;
5141 for (int i = 0; i < browser->tab_strip_model()->count(); ++i) {
5142 int id = SessionTabHelper::FromWebContents(
5143 browser->tab_strip_model()->GetWebContentsAt(i))->session_id().id();
5144 id_list->Append(base::Value::CreateIntegerValue(id));
5147 base::DictionaryValue dict;
5148 dict.Set("ids", id_list);
5149 AutomationJSONReply(this, reply_message).SendSuccess(&dict);
5152 void TestingAutomationProvider::IsTabIdValid(
5153 base::DictionaryValue* args, IPC::Message* reply_message) {
5154 AutomationJSONReply reply(this, reply_message);
5156 if (!args->GetInteger("id", &id)) {
5157 reply.SendError("'id' missing or invalid");
5160 bool is_valid = false;
5161 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
5162 Browser* browser = *it;
5163 for (int i = 0; i < browser->tab_strip_model()->count(); ++i) {
5164 WebContents* tab = browser->tab_strip_model()->GetWebContentsAt(i);
5165 SessionTabHelper* session_tab_helper =
5166 SessionTabHelper::FromWebContents(tab);
5167 if (session_tab_helper->session_id().id() == id) {
5173 base::DictionaryValue dict;
5174 dict.SetBoolean("is_valid", is_valid);
5175 reply.SendSuccess(&dict);
5178 void TestingAutomationProvider::CloseTabJSON(
5179 base::DictionaryValue* args, IPC::Message* reply_message) {
5183 bool wait_until_closed = false; // ChromeDriver does not use this.
5184 args->GetBoolean("wait_until_closed", &wait_until_closed);
5185 // Close tabs synchronously.
5186 if (GetBrowserAndTabFromJSONArgs(args, &browser, &tab, &error)) {
5187 if (wait_until_closed) {
5188 new TabClosedNotificationObserver(this, wait_until_closed, reply_message,
5191 chrome::CloseWebContents(browser, tab, false);
5192 if (!wait_until_closed)
5193 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
5196 // Close other types of views asynchronously.
5197 RenderViewHost* view;
5198 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) {
5199 AutomationJSONReply(this, reply_message).SendError(error);
5203 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
5206 void TestingAutomationProvider::SetViewBounds(
5207 base::DictionaryValue* args,
5208 IPC::Message* reply_message) {
5209 AutomationJSONReply reply(this, reply_message);
5210 int x, y, width, height;
5211 if (!args->GetInteger("bounds.x", &x) ||
5212 !args->GetInteger("bounds.y", &y) ||
5213 !args->GetInteger("bounds.width", &width) ||
5214 !args->GetInteger("bounds.height", &height)) {
5215 reply.SendError("Missing or invalid 'bounds'");
5220 if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
5221 reply.SendError(error);
5224 BrowserWindow* browser_window = browser->window();
5225 if (browser_window->IsMaximized()) {
5226 browser_window->Restore();
5228 browser_window->SetBounds(gfx::Rect(x, y, width, height));
5229 reply.SendSuccess(NULL);
5232 void TestingAutomationProvider::MaximizeView(
5233 base::DictionaryValue* args,
5234 IPC::Message* reply_message) {
5237 if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
5238 AutomationJSONReply(this, reply_message).SendError(error);
5242 #if defined(OS_LINUX)
5243 // Maximization on Linux is asynchronous, so create an observer object to be
5244 // notified upon maximization completion.
5245 new WindowMaximizedObserver(this, reply_message);
5246 #endif // defined(OS_LINUX)
5248 browser->window()->Maximize();
5250 #if !defined(OS_LINUX)
5251 // Send success reply right away for OS's with synchronous maximize command.
5252 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
5253 #endif // !defined(OS_LINUX)
5256 void TestingAutomationProvider::ActivateTabJSON(
5257 base::DictionaryValue* args,
5258 IPC::Message* reply_message) {
5259 if (SendErrorIfModalDialogActive(this, reply_message))
5262 AutomationJSONReply reply(this, reply_message);
5264 WebContents* web_contents;
5266 if (!GetBrowserAndTabFromJSONArgs(args, &browser, &web_contents, &error)) {
5267 reply.SendError(error);
5270 TabStripModel* tab_strip = browser->tab_strip_model();
5271 tab_strip->ActivateTabAt(tab_strip->GetIndexOfWebContents(web_contents),
5273 reply.SendSuccess(NULL);
5276 void TestingAutomationProvider::IsPageActionVisible(
5277 base::DictionaryValue* args,
5278 IPC::Message* reply_message) {
5279 AutomationJSONReply reply(this, reply_message);
5283 if (!GetTabFromJSONArgs(args, &tab, &error)) {
5284 reply.SendError(error);
5287 Browser* browser = automation_util::GetBrowserForTab(tab);
5289 reply.SendError("Tab does not belong to an open browser");
5292 const Extension* extension;
5293 if (!GetEnabledExtensionFromJSONArgs(
5294 args, "extension_id", browser->profile(), &extension, &error)) {
5295 reply.SendError(error);
5298 ExtensionAction* page_action =
5299 ExtensionActionManager::Get(browser->profile())->
5300 GetPageAction(*extension);
5302 reply.SendError("Extension doesn't have any page action");
5305 EnsureTabSelected(browser, tab);
5307 bool is_visible = false;
5308 LocationBarTesting* loc_bar =
5309 browser->window()->GetLocationBar()->GetLocationBarForTesting();
5310 size_t page_action_visible_count =
5311 static_cast<size_t>(loc_bar->PageActionVisibleCount());
5312 for (size_t i = 0; i < page_action_visible_count; ++i) {
5313 if (loc_bar->GetVisiblePageAction(i) == page_action) {
5318 base::DictionaryValue dict;
5319 dict.SetBoolean("is_visible", is_visible);
5320 reply.SendSuccess(&dict);
5323 void TestingAutomationProvider::CreateNewAutomationProvider(
5324 base::DictionaryValue* args,
5325 IPC::Message* reply_message) {
5326 AutomationJSONReply reply(this, reply_message);
5327 std::string channel_id;
5328 if (!args->GetString("channel_id", &channel_id)) {
5329 reply.SendError("'channel_id' missing or invalid");
5333 AutomationProvider* provider = new TestingAutomationProvider(profile_);
5334 provider->DisableInitialLoadObservers();
5335 // TODO(kkania): Remove this when crbug.com/91311 is fixed.
5336 // Named server channels should ideally be created and closed on the file
5337 // thread, within the IPC channel code.
5338 base::ThreadRestrictions::ScopedAllowIO allow_io;
5339 if (!provider->InitializeChannel(
5340 automation::kNamedInterfacePrefix + channel_id)) {
5341 reply.SendError("Failed to initialize channel: " + channel_id);
5344 DCHECK(g_browser_process);
5345 g_browser_process->GetAutomationProviderList()->AddProvider(provider);
5346 reply.SendSuccess(NULL);
5349 void TestingAutomationProvider::WaitForTabCountToBecome(
5351 int target_tab_count,
5352 IPC::Message* reply_message) {
5353 if (!browser_tracker_->ContainsHandle(browser_handle)) {
5354 AutomationMsg_WaitForTabCountToBecome::WriteReplyParams(reply_message,
5356 Send(reply_message);
5360 Browser* browser = browser_tracker_->GetResource(browser_handle);
5362 // The observer will delete itself.
5363 new TabCountChangeObserver(this, browser, reply_message, target_tab_count);
5366 void TestingAutomationProvider::WaitForInfoBarCount(
5368 size_t target_count,
5369 IPC::Message* reply_message) {
5370 if (!tab_tracker_->ContainsHandle(tab_handle)) {
5371 AutomationMsg_WaitForInfoBarCount::WriteReplyParams(reply_message_, false);
5372 Send(reply_message_);
5376 NavigationController* controller = tab_tracker_->GetResource(tab_handle);
5378 AutomationMsg_WaitForInfoBarCount::WriteReplyParams(reply_message_, false);
5379 Send(reply_message_);
5383 // The delegate will delete itself.
5384 new InfoBarCountObserver(this, reply_message,
5385 controller->GetWebContents(), target_count);
5388 void TestingAutomationProvider::WaitForProcessLauncherThreadToGoIdle(
5389 IPC::Message* reply_message) {
5390 new WaitForProcessLauncherThreadToGoIdleObserver(this, reply_message);
5393 void TestingAutomationProvider::OnRemoveProvider() {
5394 if (g_browser_process)
5395 g_browser_process->GetAutomationProviderList()->RemoveProvider(this);
5398 void TestingAutomationProvider::EnsureTabSelected(Browser* browser,
5400 TabStripModel* tab_strip = browser->tab_strip_model();
5401 if (tab_strip->GetActiveWebContents() != tab)
5402 tab_strip->ActivateTabAt(tab_strip->GetIndexOfWebContents(tab), true);