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/balloon_notification_ui_manager.h"
73 #include "chrome/browser/notifications/notification.h"
74 #include "chrome/browser/password_manager/password_store.h"
75 #include "chrome/browser/password_manager/password_store_change.h"
76 #include "chrome/browser/password_manager/password_store_factory.h"
77 #include "chrome/browser/platform_util.h"
78 #include "chrome/browser/plugins/plugin_prefs.h"
79 #include "chrome/browser/profiles/profile.h"
80 #include "chrome/browser/profiles/profile_info_cache.h"
81 #include "chrome/browser/profiles/profile_manager.h"
82 #include "chrome/browser/profiles/profile_window.h"
83 #include "chrome/browser/profiles/profiles_state.h"
84 #include "chrome/browser/search_engines/template_url.h"
85 #include "chrome/browser/search_engines/template_url_service.h"
86 #include "chrome/browser/search_engines/template_url_service_factory.h"
87 #include "chrome/browser/sessions/session_service_factory.h"
88 #include "chrome/browser/sessions/session_tab_helper.h"
89 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h"
90 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h"
91 #include "chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h"
92 #include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h"
93 #include "chrome/browser/ui/bookmarks/bookmark_bar.h"
94 #include "chrome/browser/ui/browser_commands.h"
95 #include "chrome/browser/ui/browser_finder.h"
96 #include "chrome/browser/ui/browser_iterator.h"
97 #include "chrome/browser/ui/browser_list.h"
98 #include "chrome/browser/ui/browser_tabstrip.h"
99 #include "chrome/browser/ui/browser_window.h"
100 #include "chrome/browser/ui/extensions/application_launch.h"
101 #include "chrome/browser/ui/find_bar/find_bar.h"
102 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
103 #include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
104 #include "chrome/browser/ui/fullscreen/fullscreen_exit_bubble_type.h"
105 #include "chrome/browser/ui/host_desktop.h"
106 #include "chrome/browser/ui/login/login_prompt.h"
107 #include "chrome/browser/ui/omnibox/location_bar.h"
108 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
109 #include "chrome/browser/ui/omnibox/omnibox_view.h"
110 #include "chrome/browser/ui/search_engines/keyword_editor_controller.h"
111 #include "chrome/browser/ui/startup/startup_types.h"
112 #include "chrome/common/automation_constants.h"
113 #include "chrome/common/automation_messages.h"
114 #include "chrome/common/chrome_constants.h"
115 #include "chrome/common/chrome_paths.h"
116 #include "chrome/common/chrome_switches.h"
117 #include "chrome/common/extensions/extension_constants.h"
118 #include "chrome/common/extensions/manifest_url_handler.h"
119 #include "chrome/common/pref_names.h"
120 #include "chrome/common/render_messages.h"
121 #include "content/public/browser/browser_child_process_host_iterator.h"
122 #include "content/public/browser/child_process_data.h"
123 #include "content/public/browser/favicon_status.h"
124 #include "content/public/browser/geolocation_provider.h"
125 #include "content/public/browser/interstitial_page.h"
126 #include "content/public/browser/interstitial_page_delegate.h"
127 #include "content/public/browser/navigation_entry.h"
128 #include "content/public/browser/notification_service.h"
129 #include "content/public/browser/plugin_service.h"
130 #include "content/public/browser/render_process_host.h"
131 #include "content/public/browser/render_view_host.h"
132 #include "content/public/browser/render_widget_host_view.h"
133 #include "content/public/browser/web_contents.h"
134 #include "content/public/common/child_process_host.h"
135 #include "content/public/common/common_param_traits.h"
136 #include "content/public/common/drop_data.h"
137 #include "content/public/common/geoposition.h"
138 #include "content/public/common/ssl_status.h"
139 #include "content/public/common/webplugininfo.h"
140 #include "extensions/browser/process_manager.h"
141 #include "extensions/browser/view_type_utils.h"
142 #include "extensions/common/extension.h"
143 #include "extensions/common/extension_set.h"
144 #include "extensions/common/manifest_handlers/background_info.h"
145 #include "extensions/common/permissions/permission_set.h"
146 #include "extensions/common/permissions/permissions_data.h"
147 #include "extensions/common/url_pattern.h"
148 #include "extensions/common/url_pattern_set.h"
149 #include "net/cookies/cookie_store.h"
150 #include "third_party/WebKit/public/web/WebInputEvent.h"
151 #include "ui/base/ui_base_types.h"
152 #include "ui/events/event_constants.h"
153 #include "ui/events/keycodes/keyboard_codes.h"
155 #if defined(ENABLE_CONFIGURATION_POLICY)
156 #include "components/policy/core/common/policy_service.h"
159 #if defined(OS_CHROMEOS)
160 #include "chromeos/dbus/dbus_thread_manager.h"
163 #if defined(OS_MACOSX)
164 #include <mach/mach.h>
165 #include <mach/mach_vm.h>
168 using automation_util::SendErrorIfModalDialogActive
;
169 using content::BrowserChildProcessHostIterator
;
170 using content::BrowserContext
;
171 using content::BrowserThread
;
172 using content::ChildProcessHost
;
173 using content::DownloadItem
;
174 using content::DownloadManager
;
175 using content::InterstitialPage
;
176 using content::NativeWebKeyboardEvent
;
177 using content::NavigationController
;
178 using content::NavigationEntry
;
179 using content::OpenURLParams
;
180 using content::PluginService
;
181 using content::Referrer
;
182 using content::RenderViewHost
;
183 using content::SSLStatus
;
184 using content::WebContents
;
185 using extensions::Extension
;
186 using extensions::ExtensionActionManager
;
187 using extensions::ExtensionList
;
188 using extensions::Manifest
;
192 // Helper to reply asynchronously if |automation| is still valid.
193 void SendSuccessReply(base::WeakPtr
<AutomationProvider
> automation
,
194 IPC::Message
* reply_message
) {
195 if (automation
.get())
196 AutomationJSONReply(automation
.get(), reply_message
).SendSuccess(NULL
);
199 // Helper to process the result of CanEnablePlugin.
200 void DidEnablePlugin(base::WeakPtr
<AutomationProvider
> automation
,
201 IPC::Message
* reply_message
,
202 const base::FilePath::StringType
& path
,
203 const std::string
& error_msg
,
206 SendSuccessReply(automation
, reply_message
);
208 if (automation
.get()) {
209 AutomationJSONReply(automation
.get(), reply_message
)
210 .SendError(base::StringPrintf(error_msg
.c_str(), path
.c_str()));
215 // Helper to resolve the overloading of PostTask.
216 void PostTask(BrowserThread::ID id
, const base::Closure
& callback
) {
217 BrowserThread::PostTask(id
, FROM_HERE
, callback
);
220 class AutomationInterstitialPage
: public content::InterstitialPageDelegate
{
222 AutomationInterstitialPage(WebContents
* tab
,
224 const std::string
& contents
)
225 : contents_(contents
) {
226 interstitial_page_
= InterstitialPage::Create(tab
, true, url
, this);
227 interstitial_page_
->Show();
230 virtual std::string
GetHTMLContents() OVERRIDE
{ return contents_
; }
233 const std::string contents_
;
234 InterstitialPage
* interstitial_page_
; // Owns us.
236 DISALLOW_COPY_AND_ASSIGN(AutomationInterstitialPage
);
241 const int TestingAutomationProvider::kSynchronousCommands
[] = {
244 IDC_SELECT_PREVIOUS_TAB
,
245 IDC_SHOW_BOOKMARK_MANAGER
,
248 TestingAutomationProvider::TestingAutomationProvider(Profile
* profile
)
249 : AutomationProvider(profile
) {
250 BrowserList::AddObserver(this);
251 registrar_
.Add(this, chrome::NOTIFICATION_SESSION_END
,
252 content::NotificationService::AllSources());
253 #if defined(OS_CHROMEOS)
254 AddChromeosObservers();
258 TestingAutomationProvider::~TestingAutomationProvider() {
259 #if defined(OS_CHROMEOS)
260 RemoveChromeosObservers();
262 BrowserList::RemoveObserver(this);
265 IPC::Channel::Mode
TestingAutomationProvider::GetChannelMode(
266 bool use_named_interface
) {
267 if (use_named_interface
)
268 #if defined(OS_POSIX)
269 return IPC::Channel::MODE_OPEN_NAMED_SERVER
;
271 return IPC::Channel::MODE_NAMED_SERVER
;
274 return IPC::Channel::MODE_CLIENT
;
277 void TestingAutomationProvider::OnBrowserAdded(Browser
* browser
) {
280 void TestingAutomationProvider::OnBrowserRemoved(Browser
* browser
) {
281 #if !defined(OS_CHROMEOS) && !defined(OS_MACOSX)
282 // For backwards compatibility with the testing automation interface, we
283 // want the automation provider (and hence the process) to go away when the
284 // last browser goes away.
285 // The automation layer doesn't support non-native desktops.
286 if (BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE
)->empty() &&
287 !CommandLine::ForCurrentProcess()->HasSwitch(
288 switches::kKeepAliveForTest
)) {
289 // If you change this, update Observer for chrome::SESSION_END
291 base::MessageLoop::current()->PostTask(
293 base::Bind(&TestingAutomationProvider::OnRemoveProvider
, this));
295 #endif // !defined(OS_CHROMEOS) && !defined(OS_MACOSX)
298 void TestingAutomationProvider::Observe(
300 const content::NotificationSource
& source
,
301 const content::NotificationDetails
& details
) {
302 DCHECK(type
== chrome::NOTIFICATION_SESSION_END
);
303 // OnBrowserRemoved does a ReleaseLater. When session end is received we exit
304 // before the task runs resulting in this object not being deleted. This
305 // Release balance out the Release scheduled by OnBrowserRemoved.
309 bool TestingAutomationProvider::OnMessageReceived(
310 const IPC::Message
& message
) {
311 base::ThreadRestrictions::ScopedAllowWait allow_wait
;
313 bool deserialize_success
= true;
314 IPC_BEGIN_MESSAGE_MAP_EX(TestingAutomationProvider
,
317 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_CloseBrowser
, CloseBrowser
)
318 IPC_MESSAGE_HANDLER(AutomationMsg_ActivateTab
, ActivateTab
)
319 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_AppendTab
, AppendTab
)
320 IPC_MESSAGE_HANDLER(AutomationMsg_GetMachPortCount
, GetMachPortCount
)
321 IPC_MESSAGE_HANDLER(AutomationMsg_ActiveTabIndex
, GetActiveTabIndex
)
322 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_CloseTab
, CloseTab
)
323 IPC_MESSAGE_HANDLER(AutomationMsg_GetCookies
, GetCookies
)
324 IPC_MESSAGE_HANDLER_DELAY_REPLY(
325 AutomationMsg_NavigateToURLBlockUntilNavigationsComplete
,
326 NavigateToURLBlockUntilNavigationsComplete
)
327 IPC_MESSAGE_HANDLER(AutomationMsg_NavigationAsync
, NavigationAsync
)
328 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_Reload
, Reload
)
329 IPC_MESSAGE_HANDLER(AutomationMsg_BrowserWindowCount
, GetBrowserWindowCount
)
330 IPC_MESSAGE_HANDLER(AutomationMsg_NormalBrowserWindowCount
,
331 GetNormalBrowserWindowCount
)
332 IPC_MESSAGE_HANDLER(AutomationMsg_BrowserWindow
, GetBrowserWindow
)
333 IPC_MESSAGE_HANDLER(AutomationMsg_WindowExecuteCommandAsync
,
334 ExecuteBrowserCommandAsync
)
335 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WindowExecuteCommand
,
336 ExecuteBrowserCommand
)
337 IPC_MESSAGE_HANDLER(AutomationMsg_TerminateSession
, TerminateSession
)
338 IPC_MESSAGE_HANDLER(AutomationMsg_WindowViewBounds
, WindowGetViewBounds
)
339 IPC_MESSAGE_HANDLER(AutomationMsg_SetWindowBounds
, SetWindowBounds
)
340 IPC_MESSAGE_HANDLER(AutomationMsg_TabCount
, GetTabCount
)
341 IPC_MESSAGE_HANDLER(AutomationMsg_Type
, GetType
)
342 IPC_MESSAGE_HANDLER(AutomationMsg_Tab
, GetTab
)
343 IPC_MESSAGE_HANDLER(AutomationMsg_TabTitle
, GetTabTitle
)
344 IPC_MESSAGE_HANDLER(AutomationMsg_TabIndex
, GetTabIndex
)
345 IPC_MESSAGE_HANDLER(AutomationMsg_TabURL
, GetTabURL
)
346 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_DomOperation
,
348 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_OpenNewBrowserWindowOfType
,
349 OpenNewBrowserWindowOfType
)
350 IPC_MESSAGE_HANDLER(AutomationMsg_WindowForBrowser
, GetWindowForBrowser
)
351 IPC_MESSAGE_HANDLER(AutomationMsg_GetMetricEventDuration
,
352 GetMetricEventDuration
)
353 IPC_MESSAGE_HANDLER(AutomationMsg_BringBrowserToFront
, BringBrowserToFront
)
354 IPC_MESSAGE_HANDLER(AutomationMsg_FindWindowVisibility
,
355 GetFindWindowVisibility
)
356 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForBookmarkModelToLoad
,
357 WaitForBookmarkModelToLoad
)
358 IPC_MESSAGE_HANDLER_DELAY_REPLY(
359 AutomationMsg_WaitForBrowserWindowCountToBecome
,
360 WaitForBrowserWindowCountToBecome
)
361 IPC_MESSAGE_HANDLER_DELAY_REPLY(
362 AutomationMsg_GoBackBlockUntilNavigationsComplete
,
363 GoBackBlockUntilNavigationsComplete
)
364 IPC_MESSAGE_HANDLER_DELAY_REPLY(
365 AutomationMsg_GoForwardBlockUntilNavigationsComplete
,
366 GoForwardBlockUntilNavigationsComplete
)
367 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_SendJSONRequest
,
368 SendJSONRequestWithBrowserIndex
)
369 IPC_MESSAGE_HANDLER_DELAY_REPLY(
370 AutomationMsg_SendJSONRequestWithBrowserHandle
,
371 SendJSONRequestWithBrowserHandle
)
372 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForTabCountToBecome
,
373 WaitForTabCountToBecome
)
374 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForInfoBarCount
,
376 IPC_MESSAGE_HANDLER_DELAY_REPLY(
377 AutomationMsg_WaitForProcessLauncherThreadToGoIdle
,
378 WaitForProcessLauncherThreadToGoIdle
)
380 IPC_MESSAGE_UNHANDLED(
381 handled
= AutomationProvider::OnMessageReceived(message
))
382 IPC_END_MESSAGE_MAP_EX()
383 if (!deserialize_success
)
384 OnMessageDeserializationFailure();
388 void TestingAutomationProvider::OnChannelError() {
389 if (!reinitialize_on_channel_error_
&&
390 browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID
) {
391 chrome::AttemptExit();
393 AutomationProvider::OnChannelError();
396 void TestingAutomationProvider::CloseBrowser(int browser_handle
,
397 IPC::Message
* reply_message
) {
398 if (!browser_tracker_
->ContainsHandle(browser_handle
))
401 Browser
* browser
= browser_tracker_
->GetResource(browser_handle
);
402 new BrowserClosedNotificationObserver(browser
, this, reply_message
, false);
403 browser
->window()->Close();
406 void TestingAutomationProvider::ActivateTab(int handle
,
410 if (browser_tracker_
->ContainsHandle(handle
) && at_index
> -1) {
411 Browser
* browser
= browser_tracker_
->GetResource(handle
);
412 if (at_index
>= 0 && at_index
< browser
->tab_strip_model()->count()) {
413 browser
->tab_strip_model()->ActivateTabAt(at_index
, true);
419 void TestingAutomationProvider::AppendTab(int handle
,
421 IPC::Message
* reply_message
) {
422 int append_tab_response
= -1; // -1 is the error code
423 TabAppendedNotificationObserver
* observer
= NULL
;
425 if (browser_tracker_
->ContainsHandle(handle
)) {
426 Browser
* browser
= browser_tracker_
->GetResource(handle
);
427 observer
= new TabAppendedNotificationObserver(browser
, this,
428 reply_message
, false);
429 WebContents
* contents
=
430 chrome::AddSelectedTabWithURL(browser
, url
,
431 content::PAGE_TRANSITION_TYPED
);
433 append_tab_response
= GetIndexForNavigationController(
434 &contents
->GetController(), browser
);
438 if (append_tab_response
< 0) {
439 // Appending tab failed. Clean up and send failure response.
444 AutomationMsg_AppendTab::WriteReplyParams(reply_message
,
445 append_tab_response
);
450 void TestingAutomationProvider::GetMachPortCount(int* port_count
) {
451 #if defined(OS_MACOSX)
452 mach_port_name_array_t names
;
453 mach_msg_type_number_t names_count
;
454 mach_port_type_array_t types
;
455 mach_msg_type_number_t types_count
;
457 mach_port_t port
= mach_task_self();
459 // A friendlier interface would allow NULL buffers to only get the counts.
460 kern_return_t kr
= mach_port_names(port
, &names
, &names_count
,
461 &types
, &types_count
);
462 if (kr
!= KERN_SUCCESS
) {
467 // The documentation states this is an invariant.
468 DCHECK_EQ(names_count
, types_count
);
469 *port_count
= names_count
;
471 mach_vm_deallocate(port
, reinterpret_cast<mach_vm_address_t
>(names
),
472 names_count
* sizeof(mach_port_name_array_t
));
473 mach_vm_deallocate(port
, reinterpret_cast<mach_vm_address_t
>(types
),
474 types_count
* sizeof(mach_port_type_array_t
));
480 void TestingAutomationProvider::GetActiveTabIndex(int handle
,
481 int* active_tab_index
) {
482 *active_tab_index
= -1; // -1 is the error code
483 if (browser_tracker_
->ContainsHandle(handle
)) {
484 Browser
* browser
= browser_tracker_
->GetResource(handle
);
485 *active_tab_index
= browser
->tab_strip_model()->active_index();
489 void TestingAutomationProvider::CloseTab(int tab_handle
,
490 bool wait_until_closed
,
491 IPC::Message
* reply_message
) {
492 if (tab_tracker_
->ContainsHandle(tab_handle
)) {
493 NavigationController
* controller
= tab_tracker_
->GetResource(tab_handle
);
494 Browser
* browser
= chrome::FindBrowserWithWebContents(
495 controller
->GetWebContents());
497 new TabClosedNotificationObserver(this, wait_until_closed
, reply_message
,
499 chrome::CloseWebContents(browser
, controller
->GetWebContents(), false);
503 AutomationMsg_CloseTab::WriteReplyParams(reply_message
, false);
507 void TestingAutomationProvider::GetCookies(const GURL
& url
, int handle
,
509 std::string
* value
) {
510 WebContents
* contents
= tab_tracker_
->ContainsHandle(handle
) ?
511 tab_tracker_
->GetResource(handle
)->GetWebContents() : NULL
;
512 automation_util::GetCookies(url
, contents
, value_size
, value
);
515 void TestingAutomationProvider::NavigateToURLBlockUntilNavigationsComplete(
516 int handle
, const GURL
& url
, int number_of_navigations
,
517 IPC::Message
* reply_message
) {
518 if (tab_tracker_
->ContainsHandle(handle
)) {
519 NavigationController
* tab
= tab_tracker_
->GetResource(handle
);
521 // Simulate what a user would do. Activate the tab and then navigate.
522 // We could allow navigating in a background tab in future.
523 Browser
* browser
= FindAndActivateTab(tab
);
526 new NavigationNotificationObserver(tab
, this, reply_message
,
527 number_of_navigations
, false, false);
529 // TODO(darin): avoid conversion to GURL.
530 OpenURLParams
params(
531 url
, Referrer(), CURRENT_TAB
,
532 content::PageTransitionFromInt(
533 content::PAGE_TRANSITION_TYPED
|
534 content::PAGE_TRANSITION_FROM_ADDRESS_BAR
),
536 browser
->OpenURL(params
);
541 AutomationMsg_NavigateToURLBlockUntilNavigationsComplete::WriteReplyParams(
542 reply_message
, AUTOMATION_MSG_NAVIGATION_ERROR
);
546 void TestingAutomationProvider::NavigationAsync(int handle
,
551 if (tab_tracker_
->ContainsHandle(handle
)) {
552 NavigationController
* tab
= tab_tracker_
->GetResource(handle
);
554 // Simulate what a user would do. Activate the tab and then navigate.
555 // We could allow navigating in a background tab in future.
556 Browser
* browser
= FindAndActivateTab(tab
);
559 // Don't add any listener unless a callback mechanism is desired.
560 // TODO(vibhor): Do this if such a requirement arises in future.
561 OpenURLParams
params(
562 url
, Referrer(), CURRENT_TAB
,
563 content::PageTransitionFromInt(
564 content::PAGE_TRANSITION_TYPED
|
565 content::PAGE_TRANSITION_FROM_ADDRESS_BAR
),
567 browser
->OpenURL(params
);
573 void TestingAutomationProvider::Reload(int handle
,
574 IPC::Message
* reply_message
) {
575 if (tab_tracker_
->ContainsHandle(handle
)) {
576 NavigationController
* tab
= tab_tracker_
->GetResource(handle
);
577 Browser
* browser
= FindAndActivateTab(tab
);
578 if (chrome::IsCommandEnabled(browser
, IDC_RELOAD
)) {
579 new NavigationNotificationObserver(
580 tab
, this, reply_message
, 1, false, false);
581 chrome::ExecuteCommand(browser
, IDC_RELOAD
);
586 AutomationMsg_Reload::WriteReplyParams(
587 reply_message
, AUTOMATION_MSG_NAVIGATION_ERROR
);
591 void TestingAutomationProvider::GetBrowserWindowCount(int* window_count
) {
592 // The automation layer doesn't support non-native desktops.
593 *window_count
= static_cast<int>(BrowserList::GetInstance(
594 chrome::HOST_DESKTOP_TYPE_NATIVE
)->size());
597 void TestingAutomationProvider::GetNormalBrowserWindowCount(int* window_count
) {
598 *window_count
= static_cast<int>(chrome::GetTabbedBrowserCount(
599 profile_
, chrome::HOST_DESKTOP_TYPE_NATIVE
));
602 void TestingAutomationProvider::GetBrowserWindow(int index
, int* handle
) {
604 Browser
* browser
= automation_util::GetBrowserAt(index
);
606 *handle
= browser_tracker_
->Add(browser
);
609 void TestingAutomationProvider::ExecuteBrowserCommandAsync(int handle
,
613 if (!browser_tracker_
->ContainsHandle(handle
)) {
614 LOG(WARNING
) << "Browser tracker does not contain handle: " << handle
;
617 Browser
* browser
= browser_tracker_
->GetResource(handle
);
618 if (!chrome::SupportsCommand(browser
, command
)) {
619 LOG(WARNING
) << "Browser does not support command: " << command
;
622 if (!chrome::IsCommandEnabled(browser
, command
)) {
623 LOG(WARNING
) << "Browser command not enabled: " << command
;
626 chrome::ExecuteCommand(browser
, command
);
630 void TestingAutomationProvider::ExecuteBrowserCommand(
631 int handle
, int command
, IPC::Message
* reply_message
) {
632 if (browser_tracker_
->ContainsHandle(handle
)) {
633 Browser
* browser
= browser_tracker_
->GetResource(handle
);
634 if (chrome::SupportsCommand(browser
, command
) &&
635 chrome::IsCommandEnabled(browser
, command
)) {
636 // First check if we can handle the command without using an observer.
637 for (size_t i
= 0; i
< arraysize(kSynchronousCommands
); i
++) {
638 if (command
== kSynchronousCommands
[i
]) {
639 chrome::ExecuteCommand(browser
, command
);
640 AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message
,
647 // Use an observer if we have one, otherwise fail.
648 if (ExecuteBrowserCommandObserver::CreateAndRegisterObserver(
649 this, browser
, command
, reply_message
, false)) {
650 chrome::ExecuteCommand(browser
, command
);
655 AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message
, false);
659 void TestingAutomationProvider::WebkitMouseClick(base::DictionaryValue
* args
,
660 IPC::Message
* reply_message
) {
661 if (SendErrorIfModalDialogActive(this, reply_message
))
664 RenderViewHost
* view
;
666 if (!GetRenderViewFromJSONArgs(args
, profile(), &view
, &error
)) {
667 AutomationJSONReply(this, reply_message
).SendError(error
);
671 blink::WebMouseEvent mouse_event
;
672 if (!args
->GetInteger("x", &mouse_event
.x
) ||
673 !args
->GetInteger("y", &mouse_event
.y
)) {
674 AutomationJSONReply(this, reply_message
)
675 .SendError("(X,Y) coordinates missing or invalid");
680 if (!args
->GetInteger("button", &button
)) {
681 AutomationJSONReply(this, reply_message
)
682 .SendError("Mouse button missing or invalid");
685 if (button
== automation::kLeftButton
) {
686 mouse_event
.button
= blink::WebMouseEvent::ButtonLeft
;
687 } else if (button
== automation::kRightButton
) {
688 mouse_event
.button
= blink::WebMouseEvent::ButtonRight
;
689 } else if (button
== automation::kMiddleButton
) {
690 mouse_event
.button
= blink::WebMouseEvent::ButtonMiddle
;
692 AutomationJSONReply(this, reply_message
)
693 .SendError("Invalid button press requested");
697 mouse_event
.type
= blink::WebInputEvent::MouseDown
;
698 mouse_event
.clickCount
= 1;
700 view
->ForwardMouseEvent(mouse_event
);
702 mouse_event
.type
= blink::WebInputEvent::MouseUp
;
703 new InputEventAckNotificationObserver(this, reply_message
, mouse_event
.type
,
705 view
->ForwardMouseEvent(mouse_event
);
708 void TestingAutomationProvider::WebkitMouseMove(
709 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
710 if (SendErrorIfModalDialogActive(this, reply_message
))
713 RenderViewHost
* view
;
715 if (!GetRenderViewFromJSONArgs(args
, profile(), &view
, &error
)) {
716 AutomationJSONReply(this, reply_message
).SendError(error
);
720 blink::WebMouseEvent mouse_event
;
721 if (!args
->GetInteger("x", &mouse_event
.x
) ||
722 !args
->GetInteger("y", &mouse_event
.y
)) {
723 AutomationJSONReply(this, reply_message
)
724 .SendError("(X,Y) coordinates missing or invalid");
728 mouse_event
.type
= blink::WebInputEvent::MouseMove
;
729 new InputEventAckNotificationObserver(this, reply_message
, mouse_event
.type
,
731 view
->ForwardMouseEvent(mouse_event
);
734 void TestingAutomationProvider::WebkitMouseDrag(base::DictionaryValue
* args
,
735 IPC::Message
* reply_message
) {
736 if (SendErrorIfModalDialogActive(this, reply_message
))
739 RenderViewHost
* view
;
741 if (!GetRenderViewFromJSONArgs(args
, profile(), &view
, &error
)) {
742 AutomationJSONReply(this, reply_message
).SendError(error
);
746 blink::WebMouseEvent mouse_event
;
747 int start_x
, start_y
, end_x
, end_y
;
748 if (!args
->GetInteger("start_x", &start_x
) ||
749 !args
->GetInteger("start_y", &start_y
) ||
750 !args
->GetInteger("end_x", &end_x
) ||
751 !args
->GetInteger("end_y", &end_y
)) {
752 AutomationJSONReply(this, reply_message
)
753 .SendError("Invalid start/end positions");
757 mouse_event
.type
= blink::WebInputEvent::MouseMove
;
758 // Step 1- Move the mouse to the start position.
759 mouse_event
.x
= start_x
;
760 mouse_event
.y
= start_y
;
761 view
->ForwardMouseEvent(mouse_event
);
763 // Step 2- Left click mouse down, the mouse button is fixed.
764 mouse_event
.type
= blink::WebInputEvent::MouseDown
;
765 mouse_event
.button
= blink::WebMouseEvent::ButtonLeft
;
766 mouse_event
.clickCount
= 1;
767 view
->ForwardMouseEvent(mouse_event
);
769 // Step 3 - Move the mouse to the end position.
770 mouse_event
.type
= blink::WebInputEvent::MouseMove
;
771 mouse_event
.x
= end_x
;
772 mouse_event
.y
= end_y
;
773 mouse_event
.clickCount
= 0;
774 view
->ForwardMouseEvent(mouse_event
);
776 // Step 4 - Release the left mouse button.
777 mouse_event
.type
= blink::WebInputEvent::MouseUp
;
778 mouse_event
.clickCount
= 1;
779 new InputEventAckNotificationObserver(this, reply_message
, mouse_event
.type
,
781 view
->ForwardMouseEvent(mouse_event
);
784 void TestingAutomationProvider::WebkitMouseButtonDown(
785 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
786 if (SendErrorIfModalDialogActive(this, reply_message
))
789 RenderViewHost
* view
;
791 if (!GetRenderViewFromJSONArgs(args
, profile(), &view
, &error
)) {
792 AutomationJSONReply(this, reply_message
).SendError(error
);
796 blink::WebMouseEvent mouse_event
;
797 if (!args
->GetInteger("x", &mouse_event
.x
) ||
798 !args
->GetInteger("y", &mouse_event
.y
)) {
799 AutomationJSONReply(this, reply_message
)
800 .SendError("(X,Y) coordinates missing or invalid");
804 mouse_event
.type
= blink::WebInputEvent::MouseDown
;
805 mouse_event
.button
= blink::WebMouseEvent::ButtonLeft
;
806 mouse_event
.clickCount
= 1;
807 new InputEventAckNotificationObserver(this, reply_message
, mouse_event
.type
,
809 view
->ForwardMouseEvent(mouse_event
);
812 void TestingAutomationProvider::WebkitMouseButtonUp(
813 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
814 if (SendErrorIfModalDialogActive(this, reply_message
))
817 RenderViewHost
* view
;
819 if (!GetRenderViewFromJSONArgs(args
, profile(), &view
, &error
)) {
820 AutomationJSONReply(this, reply_message
).SendError(error
);
824 blink::WebMouseEvent mouse_event
;
825 if (!args
->GetInteger("x", &mouse_event
.x
) ||
826 !args
->GetInteger("y", &mouse_event
.y
)) {
827 AutomationJSONReply(this, reply_message
)
828 .SendError("(X,Y) coordinates missing or invalid");
832 mouse_event
.type
= blink::WebInputEvent::MouseUp
;
833 mouse_event
.button
= blink::WebMouseEvent::ButtonLeft
;
834 mouse_event
.clickCount
= 1;
835 new InputEventAckNotificationObserver(this, reply_message
, mouse_event
.type
,
837 view
->ForwardMouseEvent(mouse_event
);
840 void TestingAutomationProvider::WebkitMouseDoubleClick(
841 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
842 if (SendErrorIfModalDialogActive(this, reply_message
))
845 RenderViewHost
* view
;
847 if (!GetRenderViewFromJSONArgs(args
, profile(), &view
, &error
)) {
848 AutomationJSONReply(this, reply_message
).SendError(error
);
852 blink::WebMouseEvent mouse_event
;
853 if (!args
->GetInteger("x", &mouse_event
.x
) ||
854 !args
->GetInteger("y", &mouse_event
.y
)) {
855 AutomationJSONReply(this, reply_message
)
856 .SendError("(X,Y) coordinates missing or invalid");
860 mouse_event
.type
= blink::WebInputEvent::MouseDown
;
861 mouse_event
.button
= blink::WebMouseEvent::ButtonLeft
;
862 mouse_event
.clickCount
= 1;
863 view
->ForwardMouseEvent(mouse_event
);
865 mouse_event
.type
= blink::WebInputEvent::MouseUp
;
866 new InputEventAckNotificationObserver(this, reply_message
, mouse_event
.type
,
868 view
->ForwardMouseEvent(mouse_event
);
870 mouse_event
.type
= blink::WebInputEvent::MouseDown
;
871 mouse_event
.clickCount
= 2;
872 view
->ForwardMouseEvent(mouse_event
);
874 mouse_event
.type
= blink::WebInputEvent::MouseUp
;
875 view
->ForwardMouseEvent(mouse_event
);
878 void TestingAutomationProvider::DragAndDropFilePaths(
879 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
880 if (SendErrorIfModalDialogActive(this, reply_message
))
883 RenderViewHost
* view
;
885 if (!GetRenderViewFromJSONArgs(args
, profile(), &view
, &error
)) {
886 AutomationJSONReply(this, reply_message
).SendError(error
);
891 if (!args
->GetInteger("x", &x
) || !args
->GetInteger("y", &y
)) {
892 AutomationJSONReply(this, reply_message
)
893 .SendError("(X,Y) coordinates missing or invalid");
897 base::ListValue
* paths
= NULL
;
898 if (!args
->GetList("paths", &paths
)) {
899 AutomationJSONReply(this, reply_message
)
900 .SendError("'paths' missing or invalid");
904 // Emulate drag and drop to set the file paths to the file upload control.
905 content::DropData drop_data
;
906 for (size_t path_index
= 0; path_index
< paths
->GetSize(); ++path_index
) {
908 if (!paths
->GetString(path_index
, &path
)) {
909 AutomationJSONReply(this, reply_message
)
910 .SendError("'paths' contains a non-string type");
914 drop_data
.filenames
.push_back(
915 content::DropData::FileInfo(path
, base::string16()));
918 const gfx::Point
client(x
, y
);
919 // We don't set any values in screen variable because DragTarget*** ignore the
921 const gfx::Point screen
;
924 operations
|= blink::WebDragOperationCopy
;
925 operations
|= blink::WebDragOperationLink
;
926 operations
|= blink::WebDragOperationMove
;
928 view
->DragTargetDragEnter(
929 drop_data
, client
, screen
,
930 static_cast<blink::WebDragOperationsMask
>(operations
), 0);
931 new DragTargetDropAckNotificationObserver(this, reply_message
);
932 view
->DragTargetDrop(client
, screen
, 0);
935 void TestingAutomationProvider::GetTabCount(int handle
, int* tab_count
) {
936 *tab_count
= -1; // -1 is the error code
938 if (browser_tracker_
->ContainsHandle(handle
)) {
939 Browser
* browser
= browser_tracker_
->GetResource(handle
);
940 *tab_count
= browser
->tab_strip_model()->count();
944 void TestingAutomationProvider::GetType(int handle
, int* type_as_int
) {
945 *type_as_int
= -1; // -1 is the error code
947 if (browser_tracker_
->ContainsHandle(handle
)) {
948 Browser
* browser
= browser_tracker_
->GetResource(handle
);
949 *type_as_int
= static_cast<int>(browser
->type());
953 void TestingAutomationProvider::GetTab(int win_handle
,
957 if (browser_tracker_
->ContainsHandle(win_handle
) && (tab_index
>= 0)) {
958 Browser
* browser
= browser_tracker_
->GetResource(win_handle
);
959 if (tab_index
< browser
->tab_strip_model()->count()) {
960 WebContents
* web_contents
=
961 browser
->tab_strip_model()->GetWebContentsAt(tab_index
);
962 *tab_handle
= tab_tracker_
->Add(&web_contents
->GetController());
967 void TestingAutomationProvider::GetTabTitle(int handle
,
968 int* title_string_size
,
969 std::wstring
* title
) {
970 *title_string_size
= -1; // -1 is the error code
971 if (tab_tracker_
->ContainsHandle(handle
)) {
972 NavigationController
* tab
= tab_tracker_
->GetResource(handle
);
973 NavigationEntry
* entry
= tab
->GetActiveEntry();
975 *title
= base::UTF16ToWideHack(entry
->GetTitleForDisplay(std::string()));
977 *title
= std::wstring();
979 *title_string_size
= static_cast<int>(title
->size());
983 void TestingAutomationProvider::GetTabIndex(int handle
, int* tabstrip_index
) {
984 *tabstrip_index
= -1; // -1 is the error code
986 if (tab_tracker_
->ContainsHandle(handle
)) {
987 NavigationController
* tab
= tab_tracker_
->GetResource(handle
);
988 Browser
* browser
= chrome::FindBrowserWithWebContents(
989 tab
->GetWebContents());
990 *tabstrip_index
= browser
->tab_strip_model()->GetIndexOfWebContents(
991 tab
->GetWebContents());
995 void TestingAutomationProvider::GetTabURL(int handle
,
999 if (tab_tracker_
->ContainsHandle(handle
)) {
1000 NavigationController
* tab
= tab_tracker_
->GetResource(handle
);
1001 // Return what the user would see in the location bar.
1002 *url
= tab
->GetActiveEntry()->GetVirtualURL();
1007 void TestingAutomationProvider::ExecuteJavascriptInRenderViewFrame(
1008 const base::string16
& frame_xpath
,
1009 const base::string16
& script
,
1010 IPC::Message
* reply_message
,
1011 RenderViewHost
* render_view_host
) {
1012 // Set the routing id of this message with the controller.
1013 // This routing id needs to be remembered for the reverse
1014 // communication while sending back the response of
1015 // this javascript execution.
1016 render_view_host
->ExecuteJavascriptInWebFrame(
1018 base::ASCIIToUTF16("window.domAutomationController.setAutomationId(0);"));
1019 render_view_host
->ExecuteJavascriptInWebFrame(
1020 frame_xpath
, script
);
1023 void TestingAutomationProvider::ExecuteJavascript(
1025 const std::wstring
& frame_xpath
,
1026 const std::wstring
& script
,
1027 IPC::Message
* reply_message
) {
1028 WebContents
* web_contents
= GetWebContentsForHandle(handle
, NULL
);
1029 if (!web_contents
) {
1030 AutomationMsg_DomOperation::WriteReplyParams(reply_message
, std::string());
1031 Send(reply_message
);
1035 new DomOperationMessageSender(this, reply_message
, false);
1036 ExecuteJavascriptInRenderViewFrame(base::WideToUTF16Hack(frame_xpath
),
1037 base::WideToUTF16Hack(script
),
1039 web_contents
->GetRenderViewHost());
1042 // Sample json input: { "command": "OpenNewBrowserWindowWithNewProfile" }
1043 // Sample output: {}
1044 void TestingAutomationProvider::OpenNewBrowserWindowWithNewProfile(
1045 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
1046 ProfileManager
* profile_manager
= g_browser_process
->profile_manager();
1047 new BrowserOpenedWithNewProfileNotificationObserver(this, reply_message
);
1048 profile_manager
->CreateMultiProfileAsync(
1049 base::string16(), base::string16(),
1050 ProfileManager::CreateCallback(), std::string());
1053 // Sample json input: { "command": "GetMultiProfileInfo" }
1054 // See GetMultiProfileInfo() in pyauto.py for sample output.
1055 void TestingAutomationProvider::GetMultiProfileInfo(
1056 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
1057 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
1058 ProfileManager
* profile_manager
= g_browser_process
->profile_manager();
1059 const ProfileInfoCache
& profile_info_cache
=
1060 profile_manager
->GetProfileInfoCache();
1061 return_value
->SetBoolean("enabled", profiles::IsMultipleProfilesEnabled());
1063 base::ListValue
* profiles
= new base::ListValue
;
1064 for (size_t index
= 0; index
< profile_info_cache
.GetNumberOfProfiles();
1066 base::DictionaryValue
* item
= new base::DictionaryValue
;
1067 item
->SetString("name", profile_info_cache
.GetNameOfProfileAtIndex(index
));
1068 item
->SetString("path",
1069 profile_info_cache
.GetPathOfProfileAtIndex(index
).value());
1070 profiles
->Append(item
);
1072 return_value
->Set("profiles", profiles
);
1073 AutomationJSONReply(this, reply_message
).SendSuccess(return_value
.get());
1076 void TestingAutomationProvider::OpenNewBrowserWindowOfType(
1077 int type
, bool show
, IPC::Message
* reply_message
) {
1078 new BrowserOpenedNotificationObserver(this, reply_message
, false);
1079 // We may have no current browser windows open so don't rely on
1080 // asking an existing browser to execute the IDC_NEWWINDOW command.
1081 Browser
* browser
= new Browser(
1082 Browser::CreateParams(static_cast<Browser::Type
>(type
), profile_
,
1083 chrome::HOST_DESKTOP_TYPE_NATIVE
));
1084 chrome::AddTabAt(browser
, GURL(), -1, true);
1086 browser
->window()->Show();
1089 void TestingAutomationProvider::OpenNewBrowserWindow(
1090 base::DictionaryValue
* args
,
1091 IPC::Message
* reply_message
) {
1093 if (!args
->GetBoolean("show", &show
)) {
1094 AutomationJSONReply(this, reply_message
)
1095 .SendError("'show' missing or invalid.");
1098 new BrowserOpenedNotificationObserver(this, reply_message
, true);
1099 Browser
* browser
= new Browser(
1100 Browser::CreateParams(Browser::TYPE_TABBED
, profile_
,
1101 chrome::HOST_DESKTOP_TYPE_NATIVE
));
1102 chrome::AddTabAt(browser
, GURL(), -1, true);
1104 browser
->window()->Show();
1107 void TestingAutomationProvider::GetBrowserWindowCountJSON(
1108 base::DictionaryValue
* args
,
1109 IPC::Message
* reply_message
) {
1110 base::DictionaryValue dict
;
1111 // The automation layer doesn't support non-native desktops.
1112 dict
.SetInteger("count",
1113 static_cast<int>(BrowserList::GetInstance(
1114 chrome::HOST_DESKTOP_TYPE_NATIVE
)->size()));
1115 AutomationJSONReply(this, reply_message
).SendSuccess(&dict
);
1118 void TestingAutomationProvider::CloseBrowserWindow(
1119 base::DictionaryValue
* args
,
1120 IPC::Message
* reply_message
) {
1121 AutomationJSONReply
reply(this, reply_message
);
1123 std::string error_msg
;
1124 if (!GetBrowserFromJSONArgs(args
, &browser
, &error_msg
)) {
1125 reply
.SendError(error_msg
);
1128 new BrowserClosedNotificationObserver(browser
, this, reply_message
, true);
1129 browser
->window()->Close();
1132 void TestingAutomationProvider::OpenProfileWindow(
1133 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
1134 ProfileManager
* profile_manager
= g_browser_process
->profile_manager();
1135 base::FilePath::StringType path
;
1136 if (!args
->GetString("path", &path
)) {
1137 AutomationJSONReply(this, reply_message
).SendError(
1138 "Invalid or missing arg: 'path'");
1141 Profile
* profile
= profile_manager
->GetProfileByPath(base::FilePath(path
));
1143 AutomationJSONReply(this, reply_message
).SendError(
1144 base::StringPrintf("Invalid profile path: %s", path
.c_str()));
1148 if (!args
->GetInteger("num_loads", &num_loads
)) {
1149 AutomationJSONReply(this, reply_message
).SendError(
1150 "Invalid or missing arg: 'num_loads'");
1153 new BrowserOpenedWithExistingProfileNotificationObserver(
1154 this, reply_message
, num_loads
);
1155 profiles::FindOrCreateNewWindowForProfile(
1157 chrome::startup::IS_NOT_PROCESS_STARTUP
,
1158 chrome::startup::IS_NOT_FIRST_RUN
,
1159 chrome::HOST_DESKTOP_TYPE_NATIVE
,
1163 void TestingAutomationProvider::GetWindowForBrowser(int browser_handle
,
1169 if (browser_tracker_
->ContainsHandle(browser_handle
)) {
1170 Browser
* browser
= browser_tracker_
->GetResource(browser_handle
);
1171 gfx::NativeWindow win
= browser
->window()->GetNativeWindow();
1172 // Add() returns the existing handle for the resource if any.
1173 *handle
= window_tracker_
->Add(win
);
1178 void TestingAutomationProvider::GetMetricEventDuration(
1179 const std::string
& event_name
,
1181 *duration_ms
= metric_event_duration_observer_
->GetEventDurationMs(
1185 void TestingAutomationProvider::BringBrowserToFront(int browser_handle
,
1188 if (browser_tracker_
->ContainsHandle(browser_handle
)) {
1189 Browser
* browser
= browser_tracker_
->GetResource(browser_handle
);
1190 browser
->window()->Activate();
1195 void TestingAutomationProvider::GetFindWindowVisibility(int handle
,
1198 Browser
* browser
= browser_tracker_
->GetResource(handle
);
1200 FindBarTesting
* find_bar
=
1201 browser
->GetFindBarController()->find_bar()->GetFindBarTesting();
1202 find_bar
->GetFindBarWindowInfo(NULL
, visible
);
1206 // Bookmark bar visibility is based on the pref (e.g. is it in the toolbar).
1207 // Presence in the NTP is signalled in |detached|.
1208 void TestingAutomationProvider::GetBookmarkBarStatus(
1209 base::DictionaryValue
* args
,
1210 IPC::Message
* reply_message
) {
1211 AutomationJSONReply
reply(this, reply_message
);
1213 std::string error_msg
;
1214 if (!GetBrowserFromJSONArgs(args
, &browser
, &error_msg
)) {
1215 reply
.SendError(error_msg
);
1218 // browser->window()->IsBookmarkBarVisible() is not consistent across
1219 // platforms. bookmark_bar_state() also follows prefs::kShowBookmarkBar
1220 // and has a shared implementation on all platforms.
1221 base::DictionaryValue dict
;
1222 dict
.SetBoolean("visible",
1223 browser
->bookmark_bar_state() == BookmarkBar::SHOW
);
1224 dict
.SetBoolean("animating", browser
->window()->IsBookmarkBarAnimating());
1225 dict
.SetBoolean("detached",
1226 browser
->bookmark_bar_state() == BookmarkBar::DETACHED
);
1227 reply
.SendSuccess(&dict
);
1230 void TestingAutomationProvider::GetBookmarksAsJSON(
1231 base::DictionaryValue
* args
,
1232 IPC::Message
* reply_message
) {
1233 AutomationJSONReply
reply(this, reply_message
);
1235 std::string error_msg
, bookmarks_as_json
;
1236 if (!GetBrowserFromJSONArgs(args
, &browser
, &error_msg
)) {
1237 reply
.SendError(error_msg
);
1240 BookmarkModel
* bookmark_model
=
1241 BookmarkModelFactory::GetForProfile(browser
->profile());
1242 if (!bookmark_model
->loaded()) {
1243 reply
.SendError("Bookmark model is not loaded");
1246 scoped_refptr
<BookmarkStorage
> storage(
1247 new BookmarkStorage(browser
->profile(),
1249 browser
->profile()->GetIOTaskRunner().get()));
1250 if (!storage
->SerializeData(&bookmarks_as_json
)) {
1251 reply
.SendError("Failed to serialize bookmarks");
1254 base::DictionaryValue dict
;
1255 dict
.SetString("bookmarks_as_json", bookmarks_as_json
);
1256 reply
.SendSuccess(&dict
);
1259 void TestingAutomationProvider::WaitForBookmarkModelToLoad(
1261 IPC::Message
* reply_message
) {
1262 if (browser_tracker_
->ContainsHandle(handle
)) {
1263 Browser
* browser
= browser_tracker_
->GetResource(handle
);
1264 BookmarkModel
* model
=
1265 BookmarkModelFactory::GetForProfile(browser
->profile());
1266 AutomationProviderBookmarkModelObserver
* observer
=
1267 new AutomationProviderBookmarkModelObserver(this, reply_message
,
1269 if (model
->loaded()) {
1270 observer
->ReleaseReply();
1272 AutomationMsg_WaitForBookmarkModelToLoad::WriteReplyParams(
1273 reply_message
, true);
1274 Send(reply_message
);
1279 void TestingAutomationProvider::WaitForBookmarkModelToLoadJSON(
1280 base::DictionaryValue
* args
,
1281 IPC::Message
* reply_message
) {
1283 std::string error_msg
;
1284 if (!GetBrowserFromJSONArgs(args
, &browser
, &error_msg
)) {
1285 AutomationJSONReply(this, reply_message
).SendError(error_msg
);
1288 BookmarkModel
* model
=
1289 BookmarkModelFactory::GetForProfile(browser
->profile());
1290 AutomationProviderBookmarkModelObserver
* observer
=
1291 new AutomationProviderBookmarkModelObserver(this, reply_message
, model
,
1293 if (model
->loaded()) {
1294 observer
->ReleaseReply();
1296 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
1301 void TestingAutomationProvider::AddBookmark(
1302 base::DictionaryValue
* args
,
1303 IPC::Message
* reply_message
) {
1304 AutomationJSONReply
reply(this, reply_message
);
1306 std::string error_msg
, url
;
1307 base::string16 title
;
1308 int parent_id
, index
;
1310 if (!GetBrowserFromJSONArgs(args
, &browser
, &error_msg
)) {
1311 reply
.SendError(error_msg
);
1314 if (!args
->GetBoolean("is_folder", &folder
)) {
1315 reply
.SendError("'is_folder' missing or invalid");
1318 if (!folder
&& !args
->GetString("url", &url
)) {
1319 reply
.SendError("'url' missing or invalid");
1322 if (!args
->GetInteger("parent_id", &parent_id
)) {
1323 reply
.SendError("'parent_id' missing or invalid");
1326 if (!args
->GetInteger("index", &index
)) {
1327 reply
.SendError("'index' missing or invalid");
1330 if (!args
->GetString("title", &title
)) {
1331 reply
.SendError("'title' missing or invalid");
1334 BookmarkModel
* model
=
1335 BookmarkModelFactory::GetForProfile(browser
->profile());
1336 if (!model
->loaded()) {
1337 reply
.SendError("Bookmark model is not loaded");
1340 const BookmarkNode
* parent
= model
->GetNodeByID(parent_id
);
1342 reply
.SendError("Failed to get parent bookmark node");
1345 const BookmarkNode
* child
;
1347 child
= model
->AddFolder(parent
, index
, title
);
1349 child
= model
->AddURL(parent
, index
, title
, GURL(url
));
1352 reply
.SendError("Failed to add bookmark");
1355 reply
.SendSuccess(NULL
);
1358 void TestingAutomationProvider::ReparentBookmark(base::DictionaryValue
* args
,
1359 IPC::Message
* reply_message
) {
1360 AutomationJSONReply
reply(this, reply_message
);
1362 std::string error_msg
;
1363 int new_parent_id
, id
, index
;
1364 if (!GetBrowserFromJSONArgs(args
, &browser
, &error_msg
)) {
1365 reply
.SendError(error_msg
);
1368 if (!args
->GetInteger("id", &id
)) {
1369 reply
.SendError("'id' missing or invalid");
1372 if (!args
->GetInteger("new_parent_id", &new_parent_id
)) {
1373 reply
.SendError("'new_parent_id' missing or invalid");
1376 if (!args
->GetInteger("index", &index
)) {
1377 reply
.SendError("'index' missing or invalid");
1380 BookmarkModel
* model
=
1381 BookmarkModelFactory::GetForProfile(browser
->profile());
1382 if (!model
->loaded()) {
1383 reply
.SendError("Bookmark model is not loaded");
1386 const BookmarkNode
* node
= model
->GetNodeByID(id
);
1387 const BookmarkNode
* new_parent
= model
->GetNodeByID(new_parent_id
);
1389 reply
.SendError("Failed to get bookmark node");
1393 reply
.SendError("Failed to get new parent bookmark node");
1396 model
->Move(node
, new_parent
, index
);
1397 reply
.SendSuccess(NULL
);
1400 void TestingAutomationProvider::SetBookmarkTitle(base::DictionaryValue
* args
,
1401 IPC::Message
* reply_message
) {
1402 AutomationJSONReply
reply(this, reply_message
);
1404 std::string error_msg
;
1405 base::string16 title
;
1407 if (!GetBrowserFromJSONArgs(args
, &browser
, &error_msg
)) {
1408 reply
.SendError(error_msg
);
1411 if (!args
->GetInteger("id", &id
)) {
1412 reply
.SendError("'id' missing or invalid");
1415 if (!args
->GetString("title", &title
)) {
1416 reply
.SendError("'title' missing or invalid");
1419 BookmarkModel
* model
=
1420 BookmarkModelFactory::GetForProfile(browser
->profile());
1421 if (!model
->loaded()) {
1422 reply
.SendError("Bookmark model is not loaded");
1425 const BookmarkNode
* node
= model
->GetNodeByID(id
);
1427 reply
.SendError("Failed to get bookmark node");
1430 model
->SetTitle(node
, title
);
1431 reply
.SendSuccess(NULL
);
1434 void TestingAutomationProvider::SetBookmarkURL(base::DictionaryValue
* args
,
1435 IPC::Message
* reply_message
) {
1436 AutomationJSONReply
reply(this, reply_message
);
1438 std::string error_msg
, url
;
1440 if (!GetBrowserFromJSONArgs(args
, &browser
, &error_msg
)) {
1441 reply
.SendError(error_msg
);
1444 if (!args
->GetInteger("id", &id
)) {
1445 reply
.SendError("'id' missing or invalid");
1448 if (!args
->GetString("url", &url
)) {
1449 reply
.SendError("'url' missing or invalid");
1452 BookmarkModel
* model
=
1453 BookmarkModelFactory::GetForProfile(browser
->profile());
1454 if (!model
->loaded()) {
1455 reply
.SendError("Bookmark model is not loaded");
1458 const BookmarkNode
* node
= model
->GetNodeByID(id
);
1460 reply
.SendError("Failed to get bookmark node");
1463 model
->SetURL(node
, GURL(url
));
1464 reply
.SendSuccess(NULL
);
1467 void TestingAutomationProvider::RemoveBookmark(base::DictionaryValue
* args
,
1468 IPC::Message
* reply_message
) {
1469 AutomationJSONReply
reply(this, reply_message
);
1471 std::string error_msg
;
1473 if (!GetBrowserFromJSONArgs(args
, &browser
, &error_msg
)) {
1474 reply
.SendError(error_msg
);
1477 if (!args
->GetInteger("id", &id
)) {
1478 reply
.SendError("'id' missing or invalid");
1481 BookmarkModel
* model
=
1482 BookmarkModelFactory::GetForProfile(browser
->profile());
1483 if (!model
->loaded()) {
1484 reply
.SendError("Bookmark model is not loaded");
1487 const BookmarkNode
* node
= model
->GetNodeByID(id
);
1489 reply
.SendError("Failed to get bookmark node");
1492 const BookmarkNode
* parent
= node
->parent();
1494 reply
.SendError("Failed to get parent bookmark node");
1497 model
->Remove(parent
, parent
->GetIndexOf(node
));
1498 reply
.SendSuccess(NULL
);
1501 void TestingAutomationProvider::WaitForBrowserWindowCountToBecome(
1503 IPC::Message
* reply_message
) {
1504 // The automation layer doesn't support non-native desktops.
1505 int current_count
= static_cast<int>(BrowserList::GetInstance(
1506 chrome::HOST_DESKTOP_TYPE_NATIVE
)->size());
1507 if (current_count
== target_count
) {
1508 AutomationMsg_WaitForBrowserWindowCountToBecome::WriteReplyParams(
1509 reply_message
, true);
1510 Send(reply_message
);
1514 // Set up an observer (it will delete itself).
1515 new BrowserCountChangeNotificationObserver(target_count
, this, reply_message
);
1518 void TestingAutomationProvider::GoBackBlockUntilNavigationsComplete(
1519 int handle
, int number_of_navigations
, IPC::Message
* reply_message
) {
1520 if (tab_tracker_
->ContainsHandle(handle
)) {
1521 NavigationController
* tab
= tab_tracker_
->GetResource(handle
);
1522 Browser
* browser
= FindAndActivateTab(tab
);
1523 if (chrome::IsCommandEnabled(browser
, IDC_BACK
)) {
1524 new NavigationNotificationObserver(tab
, this, reply_message
,
1525 number_of_navigations
, false, false);
1526 chrome::ExecuteCommand(browser
, IDC_BACK
);
1531 AutomationMsg_GoBackBlockUntilNavigationsComplete::WriteReplyParams(
1532 reply_message
, AUTOMATION_MSG_NAVIGATION_ERROR
);
1533 Send(reply_message
);
1536 void TestingAutomationProvider::GoForwardBlockUntilNavigationsComplete(
1537 int handle
, int number_of_navigations
, IPC::Message
* reply_message
) {
1538 if (tab_tracker_
->ContainsHandle(handle
)) {
1539 NavigationController
* tab
= tab_tracker_
->GetResource(handle
);
1540 Browser
* browser
= FindAndActivateTab(tab
);
1541 if (chrome::IsCommandEnabled(browser
, IDC_FORWARD
)) {
1542 new NavigationNotificationObserver(tab
, this, reply_message
,
1543 number_of_navigations
, false, false);
1544 chrome::ExecuteCommand(browser
, IDC_FORWARD
);
1549 AutomationMsg_GoForwardBlockUntilNavigationsComplete::WriteReplyParams(
1550 reply_message
, AUTOMATION_MSG_NAVIGATION_ERROR
);
1551 Send(reply_message
);
1554 void TestingAutomationProvider::BuildJSONHandlerMaps() {
1555 // Map json commands to their handlers.
1556 handler_map_
["ApplyAccelerator"] =
1557 &TestingAutomationProvider::ExecuteBrowserCommandAsyncJSON
;
1558 handler_map_
["RunCommand"] =
1559 &TestingAutomationProvider::ExecuteBrowserCommandJSON
;
1560 handler_map_
["IsMenuCommandEnabled"] =
1561 &TestingAutomationProvider::IsMenuCommandEnabledJSON
;
1562 handler_map_
["ActivateTab"] =
1563 &TestingAutomationProvider::ActivateTabJSON
;
1564 handler_map_
["BringBrowserToFront"] =
1565 &TestingAutomationProvider::BringBrowserToFrontJSON
;
1566 handler_map_
["GetIndicesFromTab"] =
1567 &TestingAutomationProvider::GetIndicesFromTab
;
1568 handler_map_
["NavigateToURL"] =
1569 &TestingAutomationProvider::NavigateToURL
;
1570 handler_map_
["GetActiveTabIndex"] =
1571 &TestingAutomationProvider::GetActiveTabIndexJSON
;
1572 handler_map_
["AppendTab"] =
1573 &TestingAutomationProvider::AppendTabJSON
;
1574 handler_map_
["OpenNewBrowserWindow"] =
1575 &TestingAutomationProvider::OpenNewBrowserWindow
;
1576 handler_map_
["CloseBrowserWindow"] =
1577 &TestingAutomationProvider::CloseBrowserWindow
;
1578 handler_map_
["WaitUntilNavigationCompletes"] =
1579 &TestingAutomationProvider::WaitUntilNavigationCompletes
;
1580 handler_map_
["GetLocalStatePrefsInfo"] =
1581 &TestingAutomationProvider::GetLocalStatePrefsInfo
;
1582 handler_map_
["SetLocalStatePrefs"] =
1583 &TestingAutomationProvider::SetLocalStatePrefs
;
1584 handler_map_
["GetPrefsInfo"] = &TestingAutomationProvider::GetPrefsInfo
;
1585 handler_map_
["SetPrefs"] = &TestingAutomationProvider::SetPrefs
;
1586 handler_map_
["ExecuteJavascript"] =
1587 &TestingAutomationProvider::ExecuteJavascriptJSON
;
1588 handler_map_
["AddDomEventObserver"] =
1589 &TestingAutomationProvider::AddDomEventObserver
;
1590 handler_map_
["RemoveEventObserver"] =
1591 &TestingAutomationProvider::RemoveEventObserver
;
1592 handler_map_
["GetNextEvent"] =
1593 &TestingAutomationProvider::GetNextEvent
;
1594 handler_map_
["ClearEventQueue"] =
1595 &TestingAutomationProvider::ClearEventQueue
;
1596 handler_map_
["ExecuteJavascriptInRenderView"] =
1597 &TestingAutomationProvider::ExecuteJavascriptInRenderView
;
1598 handler_map_
["GoForward"] =
1599 &TestingAutomationProvider::GoForward
;
1600 handler_map_
["GoBack"] =
1601 &TestingAutomationProvider::GoBack
;
1602 handler_map_
["Reload"] =
1603 &TestingAutomationProvider::ReloadJSON
;
1604 handler_map_
["OpenFindInPage"] =
1605 &TestingAutomationProvider::OpenFindInPage
;
1606 handler_map_
["IsFindInPageVisible"] =
1607 &TestingAutomationProvider::IsFindInPageVisible
;
1608 handler_map_
["SetDownloadShelfVisible"] =
1609 &TestingAutomationProvider::SetDownloadShelfVisibleJSON
;
1610 handler_map_
["IsDownloadShelfVisible"] =
1611 &TestingAutomationProvider::IsDownloadShelfVisibleJSON
;
1612 handler_map_
["GetDownloadDirectory"] =
1613 &TestingAutomationProvider::GetDownloadDirectoryJSON
;
1614 handler_map_
["GetCookies"] =
1615 &TestingAutomationProvider::GetCookiesJSON
;
1616 handler_map_
["DeleteCookie"] =
1617 &TestingAutomationProvider::DeleteCookieJSON
;
1618 handler_map_
["SetCookie"] =
1619 &TestingAutomationProvider::SetCookieJSON
;
1620 handler_map_
["GetCookiesInBrowserContext"] =
1621 &TestingAutomationProvider::GetCookiesInBrowserContext
;
1622 handler_map_
["DeleteCookieInBrowserContext"] =
1623 &TestingAutomationProvider::DeleteCookieInBrowserContext
;
1624 handler_map_
["SetCookieInBrowserContext"] =
1625 &TestingAutomationProvider::SetCookieInBrowserContext
;
1627 handler_map_
["WaitForBookmarkModelToLoad"] =
1628 &TestingAutomationProvider::WaitForBookmarkModelToLoadJSON
;
1629 handler_map_
["GetBookmarksAsJSON"] =
1630 &TestingAutomationProvider::GetBookmarksAsJSON
;
1631 handler_map_
["GetBookmarkBarStatus"] =
1632 &TestingAutomationProvider::GetBookmarkBarStatus
;
1633 handler_map_
["AddBookmark"] =
1634 &TestingAutomationProvider::AddBookmark
;
1635 handler_map_
["ReparentBookmark"] =
1636 &TestingAutomationProvider::ReparentBookmark
;
1637 handler_map_
["SetBookmarkTitle"] =
1638 &TestingAutomationProvider::SetBookmarkTitle
;
1639 handler_map_
["SetBookmarkURL"] =
1640 &TestingAutomationProvider::SetBookmarkURL
;
1641 handler_map_
["RemoveBookmark"] =
1642 &TestingAutomationProvider::RemoveBookmark
;
1644 handler_map_
["GetTabIds"] =
1645 &TestingAutomationProvider::GetTabIds
;
1646 handler_map_
["IsTabIdValid"] =
1647 &TestingAutomationProvider::IsTabIdValid
;
1648 handler_map_
["CloseTab"] =
1649 &TestingAutomationProvider::CloseTabJSON
;
1650 handler_map_
["SetViewBounds"] =
1651 &TestingAutomationProvider::SetViewBounds
;
1652 handler_map_
["MaximizeView"] =
1653 &TestingAutomationProvider::MaximizeView
;
1654 handler_map_
["WebkitMouseMove"] =
1655 &TestingAutomationProvider::WebkitMouseMove
;
1656 handler_map_
["WebkitMouseClick"] =
1657 &TestingAutomationProvider::WebkitMouseClick
;
1658 handler_map_
["WebkitMouseDrag"] =
1659 &TestingAutomationProvider::WebkitMouseDrag
;
1660 handler_map_
["WebkitMouseButtonUp"] =
1661 &TestingAutomationProvider::WebkitMouseButtonUp
;
1662 handler_map_
["WebkitMouseButtonDown"] =
1663 &TestingAutomationProvider::WebkitMouseButtonDown
;
1664 handler_map_
["WebkitMouseDoubleClick"] =
1665 &TestingAutomationProvider::WebkitMouseDoubleClick
;
1666 handler_map_
["DragAndDropFilePaths"] =
1667 &TestingAutomationProvider::DragAndDropFilePaths
;
1668 handler_map_
["SendWebkitKeyEvent"] =
1669 &TestingAutomationProvider::SendWebkitKeyEvent
;
1670 handler_map_
["ActivateTab"] =
1671 &TestingAutomationProvider::ActivateTabJSON
;
1672 handler_map_
["GetAppModalDialogMessage"] =
1673 &TestingAutomationProvider::GetAppModalDialogMessage
;
1674 handler_map_
["AcceptOrDismissAppModalDialog"] =
1675 &TestingAutomationProvider::AcceptOrDismissAppModalDialog
;
1676 handler_map_
["ActionOnSSLBlockingPage"] =
1677 &TestingAutomationProvider::ActionOnSSLBlockingPage
;
1678 handler_map_
["GetSecurityState"] =
1679 &TestingAutomationProvider::GetSecurityState
;
1680 handler_map_
["IsPageActionVisible"] =
1681 &TestingAutomationProvider::IsPageActionVisible
;
1682 handler_map_
["CreateNewAutomationProvider"] =
1683 &TestingAutomationProvider::CreateNewAutomationProvider
;
1684 handler_map_
["GetBrowserWindowCount"] =
1685 &TestingAutomationProvider::GetBrowserWindowCountJSON
;
1686 handler_map_
["GetBrowserInfo"] =
1687 &TestingAutomationProvider::GetBrowserInfo
;
1688 handler_map_
["GetTabInfo"] =
1689 &TestingAutomationProvider::GetTabInfo
;
1690 handler_map_
["GetTabCount"] =
1691 &TestingAutomationProvider::GetTabCountJSON
;
1692 handler_map_
["OpenNewBrowserWindowWithNewProfile"] =
1693 &TestingAutomationProvider::OpenNewBrowserWindowWithNewProfile
;
1694 handler_map_
["GetMultiProfileInfo"] =
1695 &TestingAutomationProvider::GetMultiProfileInfo
;
1696 handler_map_
["OpenProfileWindow"] =
1697 &TestingAutomationProvider::OpenProfileWindow
;
1698 handler_map_
["GetProcessInfo"] =
1699 &TestingAutomationProvider::GetProcessInfo
;
1700 handler_map_
["RefreshPolicies"] =
1701 &TestingAutomationProvider::RefreshPolicies
;
1702 handler_map_
["InstallExtension"] =
1703 &TestingAutomationProvider::InstallExtension
;
1704 handler_map_
["GetExtensionsInfo"] =
1705 &TestingAutomationProvider::GetExtensionsInfo
;
1706 handler_map_
["UninstallExtensionById"] =
1707 &TestingAutomationProvider::UninstallExtensionById
;
1708 handler_map_
["SetExtensionStateById"] =
1709 &TestingAutomationProvider::SetExtensionStateById
;
1710 handler_map_
["TriggerPageActionById"] =
1711 &TestingAutomationProvider::TriggerPageActionById
;
1712 handler_map_
["TriggerBrowserActionById"] =
1713 &TestingAutomationProvider::TriggerBrowserActionById
;
1714 handler_map_
["UpdateExtensionsNow"] =
1715 &TestingAutomationProvider::UpdateExtensionsNow
;
1716 handler_map_
["OverrideGeoposition"] =
1717 &TestingAutomationProvider::OverrideGeoposition
;
1718 handler_map_
["SimulateAsanMemoryBug"] =
1719 &TestingAutomationProvider::SimulateAsanMemoryBug
;
1721 #if defined(OS_CHROMEOS)
1722 handler_map_
["AcceptOOBENetworkScreen"] =
1723 &TestingAutomationProvider::AcceptOOBENetworkScreen
;
1724 handler_map_
["AcceptOOBEEula"] = &TestingAutomationProvider::AcceptOOBEEula
;
1725 handler_map_
["CancelOOBEUpdate"] =
1726 &TestingAutomationProvider::CancelOOBEUpdate
;
1727 handler_map_
["PickUserImage"] = &TestingAutomationProvider::PickUserImage
;
1728 handler_map_
["SkipToLogin"] = &TestingAutomationProvider::SkipToLogin
;
1729 handler_map_
["GetOOBEScreenInfo"] =
1730 &TestingAutomationProvider::GetOOBEScreenInfo
;
1732 handler_map_
["GetLoginInfo"] = &TestingAutomationProvider::GetLoginInfo
;
1733 handler_map_
["ShowCreateAccountUI"] =
1734 &TestingAutomationProvider::ShowCreateAccountUI
;
1735 handler_map_
["ExecuteJavascriptInOOBEWebUI"] =
1736 &TestingAutomationProvider::ExecuteJavascriptInOOBEWebUI
;
1737 handler_map_
["LoginAsGuest"] = &TestingAutomationProvider::LoginAsGuest
;
1738 handler_map_
["SubmitLoginForm"] =
1739 &TestingAutomationProvider::SubmitLoginForm
;
1740 handler_map_
["AddLoginEventObserver"] =
1741 &TestingAutomationProvider::AddLoginEventObserver
;
1742 handler_map_
["SignOut"] = &TestingAutomationProvider::SignOut
;
1744 handler_map_
["LockScreen"] = &TestingAutomationProvider::LockScreen
;
1745 handler_map_
["UnlockScreen"] = &TestingAutomationProvider::UnlockScreen
;
1746 handler_map_
["SignoutInScreenLocker"] =
1747 &TestingAutomationProvider::SignoutInScreenLocker
;
1749 handler_map_
["GetBatteryInfo"] = &TestingAutomationProvider::GetBatteryInfo
;
1751 handler_map_
["EnableSpokenFeedback"] =
1752 &TestingAutomationProvider::EnableSpokenFeedback
;
1753 handler_map_
["IsSpokenFeedbackEnabled"] =
1754 &TestingAutomationProvider::IsSpokenFeedbackEnabled
;
1756 handler_map_
["GetTimeInfo"] = &TestingAutomationProvider::GetTimeInfo
;
1757 handler_map_
["SetTimezone"] = &TestingAutomationProvider::SetTimezone
;
1759 handler_map_
["UpdateCheck"] = &TestingAutomationProvider::UpdateCheck
;
1761 handler_map_
["GetVolumeInfo"] = &TestingAutomationProvider::GetVolumeInfo
;
1762 handler_map_
["SetVolume"] = &TestingAutomationProvider::SetVolume
;
1763 handler_map_
["SetMute"] = &TestingAutomationProvider::SetMute
;
1765 handler_map_
["OpenCrosh"] = &TestingAutomationProvider::OpenCrosh
;
1767 browser_handler_map_
["GetTimeInfo"] =
1768 &TestingAutomationProvider::GetTimeInfo
;
1769 #endif // defined(OS_CHROMEOS)
1771 browser_handler_map_
["DisablePlugin"] =
1772 &TestingAutomationProvider::DisablePlugin
;
1773 browser_handler_map_
["EnablePlugin"] =
1774 &TestingAutomationProvider::EnablePlugin
;
1775 browser_handler_map_
["GetPluginsInfo"] =
1776 &TestingAutomationProvider::GetPluginsInfo
;
1778 browser_handler_map_
["GetNavigationInfo"] =
1779 &TestingAutomationProvider::GetNavigationInfo
;
1781 browser_handler_map_
["PerformActionOnInfobar"] =
1782 &TestingAutomationProvider::PerformActionOnInfobar
;
1784 browser_handler_map_
["GetHistoryInfo"] =
1785 &TestingAutomationProvider::GetHistoryInfo
;
1787 browser_handler_map_
["GetOmniboxInfo"] =
1788 &TestingAutomationProvider::GetOmniboxInfo
;
1789 browser_handler_map_
["SetOmniboxText"] =
1790 &TestingAutomationProvider::SetOmniboxText
;
1791 browser_handler_map_
["OmniboxAcceptInput"] =
1792 &TestingAutomationProvider::OmniboxAcceptInput
;
1793 browser_handler_map_
["OmniboxMovePopupSelection"] =
1794 &TestingAutomationProvider::OmniboxMovePopupSelection
;
1796 browser_handler_map_
["LoadSearchEngineInfo"] =
1797 &TestingAutomationProvider::LoadSearchEngineInfo
;
1798 browser_handler_map_
["GetSearchEngineInfo"] =
1799 &TestingAutomationProvider::GetSearchEngineInfo
;
1800 browser_handler_map_
["AddOrEditSearchEngine"] =
1801 &TestingAutomationProvider::AddOrEditSearchEngine
;
1802 browser_handler_map_
["PerformActionOnSearchEngine"] =
1803 &TestingAutomationProvider::PerformActionOnSearchEngine
;
1805 browser_handler_map_
["SetWindowDimensions"] =
1806 &TestingAutomationProvider::SetWindowDimensions
;
1808 browser_handler_map_
["GetDownloadsInfo"] =
1809 &TestingAutomationProvider::GetDownloadsInfo
;
1810 browser_handler_map_
["WaitForAllDownloadsToComplete"] =
1811 &TestingAutomationProvider::WaitForAllDownloadsToComplete
;
1812 browser_handler_map_
["PerformActionOnDownload"] =
1813 &TestingAutomationProvider::PerformActionOnDownload
;
1815 browser_handler_map_
["GetInitialLoadTimes"] =
1816 &TestingAutomationProvider::GetInitialLoadTimes
;
1818 browser_handler_map_
["SaveTabContents"] =
1819 &TestingAutomationProvider::SaveTabContents
;
1821 browser_handler_map_
["AddSavedPassword"] =
1822 &TestingAutomationProvider::AddSavedPassword
;
1823 browser_handler_map_
["RemoveSavedPassword"] =
1824 &TestingAutomationProvider::RemoveSavedPassword
;
1825 browser_handler_map_
["GetSavedPasswords"] =
1826 &TestingAutomationProvider::GetSavedPasswords
;
1828 browser_handler_map_
["FindInPage"] = &TestingAutomationProvider::FindInPage
;
1830 browser_handler_map_
["GetAllNotifications"] =
1831 &TestingAutomationProvider::GetAllNotifications
;
1832 browser_handler_map_
["CloseNotification"] =
1833 &TestingAutomationProvider::CloseNotification
;
1834 browser_handler_map_
["WaitForNotificationCount"] =
1835 &TestingAutomationProvider::WaitForNotificationCount
;
1837 browser_handler_map_
["GetNTPInfo"] =
1838 &TestingAutomationProvider::GetNTPInfo
;
1839 browser_handler_map_
["RemoveNTPMostVisitedThumbnail"] =
1840 &TestingAutomationProvider::RemoveNTPMostVisitedThumbnail
;
1841 browser_handler_map_
["RestoreAllNTPMostVisitedThumbnails"] =
1842 &TestingAutomationProvider::RestoreAllNTPMostVisitedThumbnails
;
1844 browser_handler_map_
["KillRendererProcess"] =
1845 &TestingAutomationProvider::KillRendererProcess
;
1847 browser_handler_map_
["LaunchApp"] = &TestingAutomationProvider::LaunchApp
;
1848 browser_handler_map_
["SetAppLaunchType"] =
1849 &TestingAutomationProvider::SetAppLaunchType
;
1851 browser_handler_map_
["GetV8HeapStats"] =
1852 &TestingAutomationProvider::GetV8HeapStats
;
1853 browser_handler_map_
["GetFPS"] =
1854 &TestingAutomationProvider::GetFPS
;
1856 browser_handler_map_
["IsFullscreenForBrowser"] =
1857 &TestingAutomationProvider::IsFullscreenForBrowser
;
1858 browser_handler_map_
["IsFullscreenForTab"] =
1859 &TestingAutomationProvider::IsFullscreenForTab
;
1860 browser_handler_map_
["IsMouseLocked"] =
1861 &TestingAutomationProvider::IsMouseLocked
;
1862 browser_handler_map_
["IsMouseLockPermissionRequested"] =
1863 &TestingAutomationProvider::IsMouseLockPermissionRequested
;
1864 browser_handler_map_
["IsFullscreenPermissionRequested"] =
1865 &TestingAutomationProvider::IsFullscreenPermissionRequested
;
1866 browser_handler_map_
["IsFullscreenBubbleDisplayed"] =
1867 &TestingAutomationProvider::IsFullscreenBubbleDisplayed
;
1868 browser_handler_map_
["IsFullscreenBubbleDisplayingButtons"] =
1869 &TestingAutomationProvider::IsFullscreenBubbleDisplayingButtons
;
1870 browser_handler_map_
["AcceptCurrentFullscreenOrMouseLockRequest"] =
1871 &TestingAutomationProvider::AcceptCurrentFullscreenOrMouseLockRequest
;
1872 browser_handler_map_
["DenyCurrentFullscreenOrMouseLockRequest"] =
1873 &TestingAutomationProvider::DenyCurrentFullscreenOrMouseLockRequest
;
1876 scoped_ptr
<base::DictionaryValue
>
1877 TestingAutomationProvider::ParseJSONRequestCommand(
1878 const std::string
& json_request
,
1879 std::string
* command
,
1880 std::string
* error
) {
1881 scoped_ptr
<base::DictionaryValue
> dict_value
;
1882 scoped_ptr
<base::Value
> values(
1883 base::JSONReader::ReadAndReturnError(json_request
,
1884 base::JSON_ALLOW_TRAILING_COMMAS
, NULL
, error
));
1886 // Make sure input is a dict with a string command.
1887 if (values
->GetType() != base::Value::TYPE_DICTIONARY
) {
1888 *error
= "Command dictionary is not a dictionary.";
1890 dict_value
.reset(static_cast<base::DictionaryValue
*>(values
.release()));
1891 if (!dict_value
->GetStringASCII("command", command
)) {
1892 *error
= "Command key string missing from dictionary.";
1893 dict_value
.reset(NULL
);
1897 return dict_value
.Pass();
1900 void TestingAutomationProvider::SendJSONRequestWithBrowserHandle(
1902 const std::string
& json_request
,
1903 IPC::Message
* reply_message
) {
1904 Browser
* browser
= NULL
;
1905 if (browser_tracker_
->ContainsHandle(handle
))
1906 browser
= browser_tracker_
->GetResource(handle
);
1907 if (browser
|| handle
< 0) {
1908 SendJSONRequest(browser
, json_request
, reply_message
);
1910 AutomationJSONReply(this, reply_message
).SendError(
1911 "The browser window does not exist.");
1915 void TestingAutomationProvider::SendJSONRequestWithBrowserIndex(
1917 const std::string
& json_request
,
1918 IPC::Message
* reply_message
) {
1919 Browser
* browser
= index
< 0 ? NULL
: automation_util::GetBrowserAt(index
);
1920 if (!browser
&& index
>= 0) {
1921 AutomationJSONReply(this, reply_message
).SendError(base::StringPrintf(
1922 "Browser window with index=%d does not exist.", index
));
1924 SendJSONRequest(browser
, json_request
, reply_message
);
1928 void TestingAutomationProvider::SendJSONRequest(Browser
* browser
,
1929 const std::string
& json_request
,
1930 IPC::Message
* reply_message
) {
1931 std::string command
, error_string
;
1932 scoped_ptr
<base::DictionaryValue
> dict_value(
1933 ParseJSONRequestCommand(json_request
, &command
, &error_string
));
1934 if (!dict_value
.get() || command
.empty()) {
1935 AutomationJSONReply(this, reply_message
).SendError(error_string
);
1939 if (handler_map_
.empty() || browser_handler_map_
.empty())
1940 BuildJSONHandlerMaps();
1942 // Look for command in handlers that take a Browser.
1943 if (browser_handler_map_
.find(std::string(command
)) !=
1944 browser_handler_map_
.end() && browser
) {
1945 (this->*browser_handler_map_
[command
])(browser
, dict_value
.get(),
1947 // Look for command in handlers that don't take a Browser.
1948 } else if (handler_map_
.find(std::string(command
)) != handler_map_
.end()) {
1949 (this->*handler_map_
[command
])(dict_value
.get(), reply_message
);
1950 // Command has no handler.
1952 error_string
= base::StringPrintf("Unknown command '%s'. Options: ",
1954 for (std::map
<std::string
, JsonHandler
>::const_iterator it
=
1955 handler_map_
.begin(); it
!= handler_map_
.end(); ++it
) {
1956 error_string
+= it
->first
+ ", ";
1958 for (std::map
<std::string
, BrowserJsonHandler
>::const_iterator it
=
1959 browser_handler_map_
.begin(); it
!= browser_handler_map_
.end(); ++it
) {
1960 error_string
+= it
->first
+ ", ";
1962 AutomationJSONReply(this, reply_message
).SendError(error_string
);
1966 void TestingAutomationProvider::BringBrowserToFrontJSON(
1967 base::DictionaryValue
* args
,
1968 IPC::Message
* reply_message
) {
1969 AutomationJSONReply
reply(this, reply_message
);
1971 std::string error_msg
;
1972 if (!GetBrowserFromJSONArgs(args
, &browser
, &error_msg
)) {
1973 reply
.SendError(error_msg
);
1976 browser
->window()->Activate();
1977 reply
.SendSuccess(NULL
);
1980 // Sample json input: { "command": "SetWindowDimensions",
1981 // "x": 20, # optional
1982 // "y": 20, # optional
1983 // "width": 800, # optional
1984 // "height": 600 } # optional
1985 void TestingAutomationProvider::SetWindowDimensions(
1987 base::DictionaryValue
* args
,
1988 IPC::Message
* reply_message
) {
1989 gfx::Rect rect
= browser
->window()->GetRestoredBounds();
1990 int x
, y
, width
, height
;
1991 if (args
->GetInteger("x", &x
))
1993 if (args
->GetInteger("y", &y
))
1995 if (args
->GetInteger("width", &width
))
1996 rect
.set_width(width
);
1997 if (args
->GetInteger("height", &height
))
1998 rect
.set_height(height
);
1999 browser
->window()->SetBounds(rect
);
2000 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
2003 base::ListValue
* TestingAutomationProvider::GetInfobarsInfo(WebContents
* wc
) {
2004 // Each infobar may have different properties depending on the type.
2005 base::ListValue
* infobars
= new base::ListValue
;
2006 InfoBarService
* infobar_service
= InfoBarService::FromWebContents(wc
);
2007 for (size_t i
= 0; i
< infobar_service
->infobar_count(); ++i
) {
2008 base::DictionaryValue
* infobar_item
= new base::DictionaryValue
;
2009 InfoBarDelegate
* infobar
= infobar_service
->infobar_at(i
)->delegate();
2010 switch (infobar
->GetInfoBarAutomationType()) {
2011 case InfoBarDelegate::CONFIRM_INFOBAR
:
2012 infobar_item
->SetString("type", "confirm_infobar");
2014 case InfoBarDelegate::PASSWORD_INFOBAR
:
2015 infobar_item
->SetString("type", "password_infobar");
2017 case InfoBarDelegate::RPH_INFOBAR
:
2018 infobar_item
->SetString("type", "rph_infobar");
2020 case InfoBarDelegate::UNKNOWN_INFOBAR
:
2021 infobar_item
->SetString("type", "unknown_infobar");
2024 if (infobar
->AsConfirmInfoBarDelegate()) {
2025 // Also covers ThemeInstalledInfoBarDelegate.
2026 ConfirmInfoBarDelegate
* confirm_infobar
=
2027 infobar
->AsConfirmInfoBarDelegate();
2028 infobar_item
->SetString("text", confirm_infobar
->GetMessageText());
2029 infobar_item
->SetString("link_text", confirm_infobar
->GetLinkText());
2030 base::ListValue
* buttons_list
= new base::ListValue
;
2031 int buttons
= confirm_infobar
->GetButtons();
2032 if (buttons
& ConfirmInfoBarDelegate::BUTTON_OK
) {
2033 base::StringValue
* button_label
= new base::StringValue(
2034 confirm_infobar
->GetButtonLabel(
2035 ConfirmInfoBarDelegate::BUTTON_OK
));
2036 buttons_list
->Append(button_label
);
2038 if (buttons
& ConfirmInfoBarDelegate::BUTTON_CANCEL
) {
2039 base::StringValue
* button_label
= new base::StringValue(
2040 confirm_infobar
->GetButtonLabel(
2041 ConfirmInfoBarDelegate::BUTTON_CANCEL
));
2042 buttons_list
->Append(button_label
);
2044 infobar_item
->Set("buttons", buttons_list
);
2045 } else if (infobar
->AsExtensionInfoBarDelegate()) {
2046 infobar_item
->SetString("type", "extension_infobar");
2048 infobar_item
->SetString("type", "unknown_infobar");
2050 infobars
->Append(infobar_item
);
2055 // Sample json input: { "command": "PerformActionOnInfobar",
2056 // "action": "dismiss",
2057 // "infobar_index": 0,
2059 // Sample output: {}
2060 void TestingAutomationProvider::PerformActionOnInfobar(
2062 base::DictionaryValue
* args
,
2063 IPC::Message
* reply_message
) {
2064 AutomationJSONReply
reply(this, reply_message
);
2066 int infobar_index_int
;
2068 if (!args
->GetInteger("tab_index", &tab_index
) ||
2069 !args
->GetInteger("infobar_index", &infobar_index_int
) ||
2070 !args
->GetString("action", &action
)) {
2071 reply
.SendError("Invalid or missing args");
2074 size_t infobar_index
= static_cast<size_t>(infobar_index_int
);
2076 WebContents
* web_contents
=
2077 browser
->tab_strip_model()->GetWebContentsAt(tab_index
);
2078 if (!web_contents
) {
2079 reply
.SendError(base::StringPrintf("No such tab at index %d", tab_index
));
2083 InfoBarService
* infobar_service
=
2084 InfoBarService::FromWebContents(web_contents
);
2085 if (infobar_index
>= infobar_service
->infobar_count()) {
2086 reply
.SendError(base::StringPrintf("No such infobar at index %" PRIuS
,
2090 InfoBar
* infobar
= infobar_service
->infobar_at(infobar_index
);
2091 InfoBarDelegate
* infobar_delegate
= infobar
->delegate();
2093 if (action
== "dismiss") {
2094 infobar_delegate
->InfoBarDismissed();
2095 infobar_service
->RemoveInfoBar(infobar
);
2096 reply
.SendSuccess(NULL
);
2099 if ((action
== "accept") || (action
== "cancel")) {
2100 ConfirmInfoBarDelegate
* confirm_infobar_delegate
=
2101 infobar_delegate
->AsConfirmInfoBarDelegate();
2102 if (!confirm_infobar_delegate
) {
2103 reply
.SendError("Not a confirm infobar");
2106 if ((action
== "accept") ?
2107 confirm_infobar_delegate
->Accept() : confirm_infobar_delegate
->Cancel())
2108 infobar_service
->RemoveInfoBar(infobar
);
2109 reply
.SendSuccess(NULL
);
2113 reply
.SendError("Invalid action");
2118 // Gets info about BrowserChildProcessHost. Must run on IO thread to
2119 // honor the semantics of BrowserChildProcessHostIterator.
2120 // Used by AutomationProvider::GetBrowserInfo().
2121 void GetChildProcessHostInfo(base::ListValue
* child_processes
) {
2122 for (BrowserChildProcessHostIterator iter
; !iter
.Done(); ++iter
) {
2123 // Only add processes which are already started, since we need their handle.
2124 if (iter
.GetData().handle
== base::kNullProcessHandle
)
2126 base::DictionaryValue
* item
= new base::DictionaryValue
;
2127 item
->SetString("name", iter
.GetData().name
);
2130 content::GetProcessTypeNameInEnglish(iter
.GetData().process_type
));
2131 item
->SetInteger("pid", base::GetProcId(iter
.GetData().handle
));
2132 child_processes
->Append(item
);
2138 // Sample json input: { "command": "GetBrowserInfo" }
2139 // Refer to GetBrowserInfo() in chrome/test/pyautolib/pyauto.py for
2140 // sample json output.
2141 void TestingAutomationProvider::GetBrowserInfo(
2142 base::DictionaryValue
* args
,
2143 IPC::Message
* reply_message
) {
2144 base::ThreadRestrictions::ScopedAllowIO allow_io
; // needed for PathService
2145 base::DictionaryValue
* properties
= new base::DictionaryValue
;
2146 properties
->SetString("ChromeVersion", chrome::kChromeVersion
);
2147 properties
->SetString("BrowserProcessExecutableName",
2148 chrome::kBrowserProcessExecutableName
);
2149 properties
->SetString("HelperProcessExecutableName",
2150 chrome::kHelperProcessExecutableName
);
2151 properties
->SetString("BrowserProcessExecutablePath",
2152 chrome::kBrowserProcessExecutablePath
);
2153 properties
->SetString("HelperProcessExecutablePath",
2154 chrome::kHelperProcessExecutablePath
);
2155 properties
->SetString("command_line_string",
2156 CommandLine::ForCurrentProcess()->GetCommandLineString());
2157 base::FilePath dumps_path
;
2158 PathService::Get(chrome::DIR_CRASH_DUMPS
, &dumps_path
);
2159 properties
->SetString("DIR_CRASH_DUMPS", dumps_path
.value());
2160 #if defined(USE_AURA)
2161 properties
->SetBoolean("aura", true);
2163 properties
->SetBoolean("aura", false);
2166 std::string branding
;
2167 #if defined(GOOGLE_CHROME_BUILD)
2168 branding
= "Google Chrome";
2169 #elif defined(CHROMIUM_BUILD)
2170 branding
= "Chromium";
2172 branding
= "Unknown Branding";
2174 properties
->SetString("branding", branding
);
2176 bool is_official_build
= false;
2177 #if defined(OFFICIAL_BUILD)
2178 is_official_build
= true;
2180 properties
->SetBoolean("is_official", is_official_build
);
2182 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
2183 return_value
->Set("properties", properties
);
2185 return_value
->SetInteger("browser_pid", base::GetCurrentProcId());
2186 // Add info about all windows in a list of dictionaries, one dictionary
2188 base::ListValue
* windows
= new base::ListValue
;
2191 for (chrome::BrowserIterator it
; !it
.done(); it
.Next(), ++windex
) {
2192 base::DictionaryValue
* browser_item
= new base::DictionaryValue
;
2193 Browser
* browser
= *it
;
2194 browser_item
->SetInteger("index", windex
);
2195 // Window properties
2196 gfx::Rect rect
= browser
->window()->GetRestoredBounds();
2197 browser_item
->SetInteger("x", rect
.x());
2198 browser_item
->SetInteger("y", rect
.y());
2199 browser_item
->SetInteger("width", rect
.width());
2200 browser_item
->SetInteger("height", rect
.height());
2201 browser_item
->SetBoolean("fullscreen",
2202 browser
->window()->IsFullscreen());
2203 base::ListValue
* visible_page_actions
= new base::ListValue
;
2204 // Add info about all visible page actions. Skipped on panels, which do not
2205 // have a location bar.
2206 LocationBar
* loc_bar
= browser
->window()->GetLocationBar();
2208 LocationBarTesting
* loc_bar_test
=
2209 loc_bar
->GetLocationBarForTesting();
2210 size_t page_action_visible_count
=
2211 static_cast<size_t>(loc_bar_test
->PageActionVisibleCount());
2212 for (size_t i
= 0; i
< page_action_visible_count
; ++i
) {
2213 base::StringValue
* extension_id
= new base::StringValue(
2214 loc_bar_test
->GetVisiblePageAction(i
)->extension_id());
2215 visible_page_actions
->Append(extension_id
);
2218 browser_item
->Set("visible_page_actions", visible_page_actions
);
2219 browser_item
->SetInteger("selected_tab",
2220 browser
->tab_strip_model()->active_index());
2221 browser_item
->SetBoolean("incognito",
2222 browser
->profile()->IsOffTheRecord());
2223 browser_item
->SetString("profile_path",
2224 browser
->profile()->GetPath().BaseName().MaybeAsASCII());
2226 switch (browser
->type()) {
2227 case Browser::TYPE_TABBED
:
2230 case Browser::TYPE_POPUP
:
2237 browser_item
->SetString("type", type
);
2238 // For each window, add info about all tabs in a list of dictionaries,
2239 // one dictionary item per tab.
2240 base::ListValue
* tabs
= new base::ListValue
;
2241 for (int i
= 0; i
< browser
->tab_strip_model()->count(); ++i
) {
2242 WebContents
* wc
= browser
->tab_strip_model()->GetWebContentsAt(i
);
2243 base::DictionaryValue
* tab
= new base::DictionaryValue
;
2244 tab
->SetInteger("index", i
);
2245 tab
->SetString("url", wc
->GetURL().spec());
2246 tab
->SetInteger("renderer_pid",
2247 base::GetProcId(wc
->GetRenderProcessHost()->GetHandle()));
2248 tab
->Set("infobars", GetInfobarsInfo(wc
));
2249 tab
->SetBoolean("pinned", browser
->tab_strip_model()->IsTabPinned(i
));
2252 browser_item
->Set("tabs", tabs
);
2254 windows
->Append(browser_item
);
2256 return_value
->Set("windows", windows
);
2258 #if defined(OS_LINUX)
2259 int flags
= ChildProcessHost::CHILD_ALLOW_SELF
;
2261 int flags
= ChildProcessHost::CHILD_NORMAL
;
2264 // Add all extension processes in a list of dictionaries, one dictionary
2265 // item per extension process.
2266 base::ListValue
* extension_views
= new base::ListValue
;
2267 ProfileManager
* profile_manager
= g_browser_process
->profile_manager();
2268 std::vector
<Profile
*> profiles(profile_manager
->GetLoadedProfiles());
2269 for (size_t i
= 0; i
< profiles
.size(); ++i
) {
2270 extensions::ProcessManager
* process_manager
=
2271 extensions::ExtensionSystem::Get(profiles
[i
])->process_manager();
2272 if (!process_manager
)
2274 const extensions::ProcessManager::ViewSet view_set
=
2275 process_manager
->GetAllViews();
2276 for (extensions::ProcessManager::ViewSet::const_iterator jt
=
2278 jt
!= view_set
.end(); ++jt
) {
2279 content::RenderViewHost
* render_view_host
= *jt
;
2280 // Don't add dead extension processes.
2281 if (!render_view_host
->IsRenderViewLive())
2283 // Don't add views for which we can't obtain an extension.
2284 // TODO(benwells): work out why this happens. It only happens for one
2285 // test, and only on the bots.
2286 const Extension
* extension
=
2287 process_manager
->GetExtensionForRenderViewHost(render_view_host
);
2290 base::DictionaryValue
* item
= new base::DictionaryValue
;
2291 item
->SetString("name", extension
->name());
2292 item
->SetString("extension_id", extension
->id());
2295 base::GetProcId(render_view_host
->GetProcess()->GetHandle()));
2296 base::DictionaryValue
* view
= new base::DictionaryValue
;
2298 "render_process_id",
2299 render_view_host
->GetProcess()->GetID());
2302 render_view_host
->GetRoutingID());
2303 item
->Set("view", view
);
2305 WebContents
* web_contents
=
2306 WebContents::FromRenderViewHost(render_view_host
);
2307 extensions::ViewType view_type
= extensions::GetViewType(web_contents
);
2308 switch (view_type
) {
2309 case extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE
:
2310 type
= "EXTENSION_BACKGROUND_PAGE";
2312 case extensions::VIEW_TYPE_EXTENSION_POPUP
:
2313 type
= "EXTENSION_POPUP";
2315 case extensions::VIEW_TYPE_EXTENSION_INFOBAR
:
2316 type
= "EXTENSION_INFOBAR";
2318 case extensions::VIEW_TYPE_EXTENSION_DIALOG
:
2319 type
= "EXTENSION_DIALOG";
2321 case extensions::VIEW_TYPE_APP_SHELL
:
2324 case extensions::VIEW_TYPE_PANEL
:
2331 item
->SetString("view_type", type
);
2332 item
->SetString("url", web_contents
->GetURL().spec());
2333 item
->SetBoolean("loaded", !render_view_host
->IsLoading());
2334 extension_views
->Append(item
);
2337 return_value
->Set("extension_views", extension_views
);
2339 return_value
->SetString("child_process_path",
2340 ChildProcessHost::GetChildPath(flags
).value());
2341 // Child processes are the processes for plugins and other workers.
2342 // Add all child processes in a list of dictionaries, one dictionary item
2343 // per child process.
2344 base::ListValue
* child_processes
= new base::ListValue
;
2345 return_value
->Set("child_processes", child_processes
);
2346 BrowserThread::PostTaskAndReply(
2347 BrowserThread::IO
, FROM_HERE
,
2348 base::Bind(&GetChildProcessHostInfo
, child_processes
),
2349 base::Bind(&AutomationJSONReply::SendSuccess
,
2350 base::Owned(new AutomationJSONReply(this, reply_message
)),
2351 base::Owned(return_value
.release())));
2354 // Sample json input: { "command": "GetProcessInfo" }
2355 // Refer to GetProcessInfo() in chrome/test/pyautolib/pyauto.py for
2356 // sample json output.
2357 void TestingAutomationProvider::GetProcessInfo(
2358 base::DictionaryValue
* args
,
2359 IPC::Message
* reply_message
) {
2360 scoped_refptr
<ProcessInfoObserver
>
2361 proc_observer(new ProcessInfoObserver(this, reply_message
));
2362 // TODO(jamescook): Maybe this shouldn't update UMA stats?
2363 proc_observer
->StartFetch(MemoryDetails::UPDATE_USER_METRICS
);
2366 // Sample json input: { "command": "GetNavigationInfo" }
2367 // Refer to GetNavigationInfo() in chrome/test/pyautolib/pyauto.py for
2368 // sample json output.
2369 void TestingAutomationProvider::GetNavigationInfo(
2371 base::DictionaryValue
* args
,
2372 IPC::Message
* reply_message
) {
2373 AutomationJSONReply
reply(this, reply_message
);
2375 WebContents
* web_contents
= NULL
;
2376 if (!args
->GetInteger("tab_index", &tab_index
) ||
2378 browser
->tab_strip_model()->GetWebContentsAt(tab_index
))) {
2379 reply
.SendError("tab_index missing or invalid.");
2382 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
2383 const NavigationController
& controller
= web_contents
->GetController();
2384 NavigationEntry
* nav_entry
= controller
.GetActiveEntry();
2388 base::DictionaryValue
* ssl
= new base::DictionaryValue
;
2389 std::map
<content::SecurityStyle
, std::string
> style_to_string
;
2390 style_to_string
[content::SECURITY_STYLE_UNKNOWN
] = "SECURITY_STYLE_UNKNOWN";
2391 style_to_string
[content::SECURITY_STYLE_UNAUTHENTICATED
] =
2392 "SECURITY_STYLE_UNAUTHENTICATED";
2393 style_to_string
[content::SECURITY_STYLE_AUTHENTICATION_BROKEN
] =
2394 "SECURITY_STYLE_AUTHENTICATION_BROKEN";
2395 style_to_string
[content::SECURITY_STYLE_AUTHENTICATED
] =
2396 "SECURITY_STYLE_AUTHENTICATED";
2398 SSLStatus ssl_status
= nav_entry
->GetSSL();
2399 ssl
->SetString("security_style",
2400 style_to_string
[ssl_status
.security_style
]);
2401 ssl
->SetBoolean("ran_insecure_content",
2402 !!(ssl_status
.content_status
& SSLStatus::RAN_INSECURE_CONTENT
));
2403 ssl
->SetBoolean("displayed_insecure_content",
2404 !!(ssl_status
.content_status
& SSLStatus::DISPLAYED_INSECURE_CONTENT
));
2405 return_value
->Set("ssl", ssl
);
2408 std::map
<content::PageType
, std::string
> pagetype_to_string
;
2409 pagetype_to_string
[content::PAGE_TYPE_NORMAL
] = "NORMAL_PAGE";
2410 pagetype_to_string
[content::PAGE_TYPE_ERROR
] = "ERROR_PAGE";
2411 pagetype_to_string
[content::PAGE_TYPE_INTERSTITIAL
] =
2412 "INTERSTITIAL_PAGE";
2413 return_value
->SetString("page_type",
2414 pagetype_to_string
[nav_entry
->GetPageType()]);
2416 return_value
->SetString("favicon_url", nav_entry
->GetFavicon().url
.spec());
2417 reply
.SendSuccess(return_value
.get());
2420 // Sample json input: { "command": "GetHistoryInfo",
2421 // "search_text": "some text" }
2422 // Refer chrome/test/pyautolib/history_info.py for sample json output.
2423 void TestingAutomationProvider::GetHistoryInfo(Browser
* browser
,
2424 base::DictionaryValue
* args
,
2425 IPC::Message
* reply_message
) {
2426 consumer_
.CancelAllRequests();
2428 base::string16 search_text
;
2429 args
->GetString("search_text", &search_text
);
2432 HistoryService
* hs
= HistoryServiceFactory::GetForProfile(
2433 browser
->profile(), Profile::EXPLICIT_ACCESS
);
2434 history::QueryOptions options
;
2435 // The observer owns itself. It deletes itself after it fetches history.
2436 AutomationProviderHistoryObserver
* history_observer
=
2437 new AutomationProviderHistoryObserver(this, reply_message
);
2442 base::Bind(&AutomationProviderHistoryObserver::HistoryQueryComplete
,
2443 base::Unretained(history_observer
)));
2446 // Sample json input: { "command": "GetDownloadsInfo" }
2447 // Refer chrome/test/pyautolib/download_info.py for sample json output.
2448 void TestingAutomationProvider::GetDownloadsInfo(Browser
* browser
,
2449 base::DictionaryValue
* args
,
2450 IPC::Message
* reply_message
) {
2451 AutomationJSONReply
reply(this, reply_message
);
2452 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
2453 base::ListValue
* list_of_downloads
= new base::ListValue
;
2455 DownloadService
* download_service(
2456 DownloadServiceFactory::GetForBrowserContext(browser
->profile()));
2458 if (download_service
->HasCreatedDownloadManager()) {
2459 std::vector
<DownloadItem
*> downloads
;
2460 BrowserContext::GetDownloadManager(browser
->profile())->GetAllDownloads(
2463 for (std::vector
<DownloadItem
*>::iterator it
= downloads
.begin();
2464 it
!= downloads
.end();
2465 it
++) { // Fill info about each download item.
2466 list_of_downloads
->Append(GetDictionaryFromDownloadItem(
2467 *it
, browser
->profile()->IsOffTheRecord()));
2470 return_value
->Set("downloads", list_of_downloads
);
2471 reply
.SendSuccess(return_value
.get());
2474 void TestingAutomationProvider::WaitForAllDownloadsToComplete(
2476 base::DictionaryValue
* args
,
2477 IPC::Message
* reply_message
) {
2478 base::ListValue
* pre_download_ids
= NULL
;
2480 if (!args
->GetList("pre_download_ids", &pre_download_ids
)) {
2481 AutomationJSONReply(this, reply_message
)
2483 base::StringPrintf("List of IDs of previous downloads required."));
2487 DownloadService
* download_service
=
2488 DownloadServiceFactory::GetForBrowserContext(browser
->profile());
2489 if (!download_service
->HasCreatedDownloadManager()) {
2490 // No download manager, so no downloads to wait for.
2491 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
2495 // This observer will delete itself.
2496 new AllDownloadsCompleteObserver(
2497 this, reply_message
,
2498 BrowserContext::GetDownloadManager(browser
->profile()),
2502 // See PerformActionOnDownload() in chrome/test/pyautolib/pyauto.py for sample
2503 // json input and output.
2504 void TestingAutomationProvider::PerformActionOnDownload(
2506 base::DictionaryValue
* args
,
2507 IPC::Message
* reply_message
) {
2511 DownloadService
* download_service
=
2512 DownloadServiceFactory::GetForBrowserContext(browser
->profile());
2513 if (!download_service
->HasCreatedDownloadManager()) {
2514 AutomationJSONReply(this, reply_message
).SendError("No download manager.");
2517 if (!args
->GetInteger("id", &id
) || !args
->GetString("action", &action
)) {
2518 AutomationJSONReply(this, reply_message
)
2519 .SendError("Must include int id and string action.");
2523 DownloadManager
* download_manager
=
2524 BrowserContext::GetDownloadManager(browser
->profile());
2525 DownloadItem
* selected_item
= download_manager
->GetDownload(id
);
2526 if (!selected_item
) {
2527 AutomationJSONReply(this, reply_message
)
2528 .SendError(base::StringPrintf("No download with an id of %d\n", id
));
2532 DownloadItem::DownloadState download_state
= selected_item
->GetState();
2534 // We need to be IN_PROGRESS for these actions.
2535 if ((action
== "pause" || action
== "resume" || action
== "cancel") &&
2536 download_state
!= DownloadItem::IN_PROGRESS
) {
2537 AutomationJSONReply(this, reply_message
)
2538 .SendError(base::StringPrintf(
2539 "Action '%s' called on download that is not in progress.",
2544 if (action
== "open") {
2545 selected_item
->AddObserver(
2546 new AutomationProviderDownloadUpdatedObserver(
2547 this, reply_message
, true, browser
->profile()->IsOffTheRecord()));
2548 selected_item
->OpenDownload();
2549 } else if (action
== "toggle_open_files_like_this") {
2550 DownloadPrefs
* prefs
=
2551 DownloadPrefs::FromBrowserContext(selected_item
->GetBrowserContext());
2552 base::FilePath path
= selected_item
->GetTargetFilePath();
2553 if (!selected_item
->ShouldOpenFileBasedOnExtension())
2554 prefs
->EnableAutoOpenBasedOnExtension(path
);
2556 prefs
->DisableAutoOpenBasedOnExtension(path
);
2557 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
2558 } else if (action
== "remove") {
2559 new AutomationProviderDownloadModelChangedObserver(
2560 this, reply_message
, download_manager
);
2561 selected_item
->Remove();
2562 } else if (action
== "decline_dangerous_download") {
2563 new AutomationProviderDownloadModelChangedObserver(
2564 this, reply_message
, download_manager
);
2565 selected_item
->Remove();
2566 } else if (action
== "save_dangerous_download") {
2567 selected_item
->AddObserver(new AutomationProviderDownloadUpdatedObserver(
2568 this, reply_message
, false, browser
->profile()->IsOffTheRecord()));
2569 selected_item
->ValidateDangerousDownload();
2570 } else if (action
== "pause") {
2571 if (selected_item
->IsPaused()) {
2572 // Action would be a no-op; respond right from here. No-op implies
2573 // the test is poorly written or failing, so make it an error return.
2574 AutomationJSONReply(this, reply_message
)
2575 .SendError("Action 'pause' called on already paused download.");
2577 selected_item
->AddObserver(new AutomationProviderDownloadUpdatedObserver(
2578 this, reply_message
, false, browser
->profile()->IsOffTheRecord()));
2579 selected_item
->Pause();
2581 } else if (action
== "resume") {
2582 if (!selected_item
->IsPaused()) {
2583 // Action would be a no-op; respond right from here. No-op implies
2584 // the test is poorly written or failing, so make it an error return.
2585 AutomationJSONReply(this, reply_message
)
2586 .SendError("Action 'resume' called on unpaused download.");
2588 selected_item
->AddObserver(new AutomationProviderDownloadUpdatedObserver(
2589 this, reply_message
, false, browser
->profile()->IsOffTheRecord()));
2590 selected_item
->Resume();
2592 } else if (action
== "cancel") {
2593 selected_item
->AddObserver(new AutomationProviderDownloadUpdatedObserver(
2594 this, reply_message
, false, browser
->profile()->IsOffTheRecord()));
2595 selected_item
->Cancel(true);
2597 AutomationJSONReply(this, reply_message
)
2599 base::StringPrintf("Invalid action '%s' given.", action
.c_str()));
2603 void TestingAutomationProvider::SetDownloadShelfVisibleJSON(
2604 base::DictionaryValue
* args
,
2605 IPC::Message
* reply_message
) {
2606 AutomationJSONReply
reply(this, reply_message
);
2608 std::string error_msg
;
2610 if (!GetBrowserFromJSONArgs(args
, &browser
, &error_msg
)) {
2611 reply
.SendError(error_msg
);
2614 if (!args
->GetBoolean("is_visible", &is_visible
)) {
2615 reply
.SendError("'is_visible' missing or invalid.");
2619 browser
->window()->GetDownloadShelf()->Show();
2621 browser
->window()->GetDownloadShelf()->Close(DownloadShelf::AUTOMATIC
);
2623 reply
.SendSuccess(NULL
);
2626 void TestingAutomationProvider::IsDownloadShelfVisibleJSON(
2627 base::DictionaryValue
* args
,
2628 IPC::Message
* reply_message
) {
2629 AutomationJSONReply
reply(this, reply_message
);
2631 std::string error_msg
;
2632 if (!GetBrowserFromJSONArgs(args
, &browser
, &error_msg
)) {
2633 reply
.SendError(error_msg
);
2636 base::DictionaryValue dict
;
2637 dict
.SetBoolean("is_visible", browser
->window()->IsDownloadShelfVisible());
2638 reply
.SendSuccess(&dict
);
2641 void TestingAutomationProvider::GetDownloadDirectoryJSON(
2642 base::DictionaryValue
* args
,
2643 IPC::Message
* reply_message
) {
2644 AutomationJSONReply
reply(this, reply_message
);
2645 WebContents
* web_contents
;
2647 if (!GetTabFromJSONArgs(args
, &web_contents
, &error
)) {
2648 reply
.SendError(error
);
2651 DownloadManager
* dlm
=
2652 BrowserContext::GetDownloadManager(
2653 web_contents
->GetController().GetBrowserContext());
2654 base::DictionaryValue dict
;
2655 dict
.SetString("path",
2656 DownloadPrefs::FromDownloadManager(dlm
)->DownloadPath().value());
2657 reply
.SendSuccess(&dict
);
2660 // Sample JSON input { "command": "LoadSearchEngineInfo" }
2661 void TestingAutomationProvider::LoadSearchEngineInfo(
2663 base::DictionaryValue
* args
,
2664 IPC::Message
* reply_message
) {
2665 TemplateURLService
* url_model
=
2666 TemplateURLServiceFactory::GetForProfile(browser
->profile());
2667 if (url_model
->loaded()) {
2668 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
2671 url_model
->AddObserver(new AutomationProviderSearchEngineObserver(
2672 this, browser
->profile(), reply_message
));
2676 // Sample JSON input { "command": "GetSearchEngineInfo" }
2677 // Refer to pyauto.py for sample output.
2678 void TestingAutomationProvider::GetSearchEngineInfo(
2680 base::DictionaryValue
* args
,
2681 IPC::Message
* reply_message
) {
2682 TemplateURLService
* url_model
=
2683 TemplateURLServiceFactory::GetForProfile(browser
->profile());
2684 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
2685 base::ListValue
* search_engines
= new base::ListValue
;
2686 TemplateURLService::TemplateURLVector template_urls
=
2687 url_model
->GetTemplateURLs();
2688 for (TemplateURLService::TemplateURLVector::const_iterator it
=
2689 template_urls
.begin(); it
!= template_urls
.end(); ++it
) {
2690 base::DictionaryValue
* search_engine
= new base::DictionaryValue
;
2691 search_engine
->SetString("short_name",
2692 base::UTF16ToUTF8((*it
)->short_name()));
2693 search_engine
->SetString("keyword", base::UTF16ToUTF8((*it
)->keyword()));
2694 search_engine
->SetBoolean("in_default_list", (*it
)->ShowInDefaultList());
2695 search_engine
->SetBoolean("is_default",
2696 (*it
) == url_model
->GetDefaultSearchProvider());
2697 search_engine
->SetBoolean("is_valid", (*it
)->url_ref().IsValid());
2698 search_engine
->SetBoolean("supports_replacement",
2699 (*it
)->url_ref().SupportsReplacement());
2700 search_engine
->SetString("url", (*it
)->url());
2701 search_engine
->SetString("host", (*it
)->url_ref().GetHost());
2702 search_engine
->SetString("path", (*it
)->url_ref().GetPath());
2703 search_engine
->SetString("display_url",
2704 base::UTF16ToUTF8((*it
)->url_ref().DisplayURL()));
2705 search_engines
->Append(search_engine
);
2707 return_value
->Set("search_engines", search_engines
);
2708 AutomationJSONReply(this, reply_message
).SendSuccess(return_value
.get());
2711 // Refer to pyauto.py for sample JSON input.
2712 void TestingAutomationProvider::AddOrEditSearchEngine(
2714 base::DictionaryValue
* args
,
2715 IPC::Message
* reply_message
) {
2716 TemplateURLService
* url_model
=
2717 TemplateURLServiceFactory::GetForProfile(browser
->profile());
2718 base::string16 new_title
;
2719 base::string16 new_keyword
;
2720 std::string new_url
;
2721 std::string keyword
;
2722 if (!args
->GetString("new_title", &new_title
) ||
2723 !args
->GetString("new_keyword", &new_keyword
) ||
2724 !args
->GetString("new_url", &new_url
)) {
2725 AutomationJSONReply(this, reply_message
).SendError(
2726 "One or more inputs invalid");
2729 std::string new_ref_url
= TemplateURLRef::DisplayURLToURLRef(
2730 base::UTF8ToUTF16(new_url
));
2731 scoped_ptr
<KeywordEditorController
> controller(
2732 new KeywordEditorController(browser
->profile()));
2733 if (args
->GetString("keyword", &keyword
)) {
2734 TemplateURL
* template_url
=
2735 url_model
->GetTemplateURLForKeyword(base::UTF8ToUTF16(keyword
));
2736 if (template_url
== NULL
) {
2737 AutomationJSONReply(this, reply_message
).SendError(
2738 "No match for keyword: " + keyword
);
2741 url_model
->AddObserver(new AutomationProviderSearchEngineObserver(
2742 this, browser
->profile(), reply_message
));
2743 controller
->ModifyTemplateURL(template_url
, new_title
, new_keyword
,
2746 url_model
->AddObserver(new AutomationProviderSearchEngineObserver(
2747 this, browser
->profile(), reply_message
));
2748 controller
->AddTemplateURL(new_title
, new_keyword
, new_ref_url
);
2752 // Sample json input: { "command": "PerformActionOnSearchEngine",
2753 // "keyword": keyword, "action": action }
2754 void TestingAutomationProvider::PerformActionOnSearchEngine(
2756 base::DictionaryValue
* args
,
2757 IPC::Message
* reply_message
) {
2758 TemplateURLService
* url_model
=
2759 TemplateURLServiceFactory::GetForProfile(browser
->profile());
2760 std::string keyword
;
2762 if (!args
->GetString("keyword", &keyword
) ||
2763 !args
->GetString("action", &action
)) {
2764 AutomationJSONReply(this, reply_message
).SendError(
2765 "One or more inputs invalid");
2768 TemplateURL
* template_url
=
2769 url_model
->GetTemplateURLForKeyword(base::UTF8ToUTF16(keyword
));
2770 if (template_url
== NULL
) {
2771 AutomationJSONReply(this, reply_message
).SendError(
2772 "No match for keyword: " + keyword
);
2775 if (action
== "delete") {
2776 url_model
->AddObserver(new AutomationProviderSearchEngineObserver(
2777 this, browser
->profile(), reply_message
));
2778 url_model
->Remove(template_url
);
2779 } else if (action
== "default") {
2780 url_model
->AddObserver(new AutomationProviderSearchEngineObserver(
2781 this, browser
->profile(), reply_message
));
2782 url_model
->SetDefaultSearchProvider(template_url
);
2784 AutomationJSONReply(this, reply_message
).SendError(
2785 "Invalid action: " + action
);
2789 // Sample json input: { "command": "GetLocalStatePrefsInfo" }
2790 // Refer chrome/test/pyautolib/prefs_info.py for sample json output.
2791 void TestingAutomationProvider::GetLocalStatePrefsInfo(
2792 base::DictionaryValue
* args
,
2793 IPC::Message
* reply_message
) {
2794 scoped_ptr
<base::DictionaryValue
> items(
2795 g_browser_process
->local_state()->GetPreferenceValues());
2796 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
2797 return_value
->Set("prefs", items
.release()); // return_value owns items.
2798 AutomationJSONReply(this, reply_message
).SendSuccess(return_value
.get());
2801 // Sample json input: { "command": "SetLocalStatePrefs", "path": path,
2803 void TestingAutomationProvider::SetLocalStatePrefs(
2804 base::DictionaryValue
* args
,
2805 IPC::Message
* reply_message
) {
2807 base::Value
* val
= NULL
;
2808 AutomationJSONReply
reply(this, reply_message
);
2809 if (args
->GetString("path", &path
) && args
->Get("value", &val
)) {
2810 PrefService
* pref_service
= g_browser_process
->local_state();
2811 const PrefService::Preference
* pref
=
2812 pref_service
->FindPreference(path
.c_str());
2813 if (!pref
) { // Not a registered pref.
2814 reply
.SendError("pref not registered.");
2816 } else if (pref
->IsManaged()) { // Do not attempt to change a managed pref.
2817 reply
.SendError("pref is managed. cannot be changed.");
2819 } else { // Set the pref.
2820 pref_service
->Set(path
.c_str(), *val
);
2823 reply
.SendError("no pref path or value given.");
2827 reply
.SendSuccess(NULL
);
2830 // Sample json input: { "command": "GetPrefsInfo", "windex": 0 }
2831 // Refer chrome/test/pyautolib/prefs_info.py for sample json output.
2832 void TestingAutomationProvider::GetPrefsInfo(base::DictionaryValue
* args
,
2833 IPC::Message
* reply_message
) {
2834 AutomationJSONReply
reply(this, reply_message
);
2836 std::string error_msg
;
2837 if (!GetBrowserFromJSONArgs(args
, &browser
, &error_msg
)) {
2838 reply
.SendError(error_msg
);
2841 scoped_ptr
<base::DictionaryValue
> items(
2842 browser
->profile()->GetPrefs()->GetPreferenceValues());
2844 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
2845 return_value
->Set("prefs", items
.release()); // return_value owns items.
2846 reply
.SendSuccess(return_value
.get());
2849 // Sample json input:
2850 // { "command": "SetPrefs",
2854 void TestingAutomationProvider::SetPrefs(base::DictionaryValue
* args
,
2855 IPC::Message
* reply_message
) {
2856 AutomationJSONReply
reply(this, reply_message
);
2858 std::string error_msg
;
2859 if (!GetBrowserFromJSONArgs(args
, &browser
, &error_msg
)) {
2860 reply
.SendError(error_msg
);
2864 base::Value
* val
= NULL
;
2865 if (args
->GetString("path", &path
) && args
->Get("value", &val
)) {
2866 PrefService
* pref_service
= browser
->profile()->GetPrefs();
2867 const PrefService::Preference
* pref
=
2868 pref_service
->FindPreference(path
.c_str());
2869 if (!pref
) { // Not a registered pref.
2870 reply
.SendError("pref not registered.");
2872 } else if (pref
->IsManaged()) { // Do not attempt to change a managed pref.
2873 reply
.SendError("pref is managed. cannot be changed.");
2875 } else { // Set the pref.
2876 pref_service
->Set(path
.c_str(), *val
);
2879 reply
.SendError("no pref path or value given.");
2883 reply
.SendSuccess(NULL
);
2886 // Sample json input: { "command": "GetOmniboxInfo" }
2887 // Refer chrome/test/pyautolib/omnibox_info.py for sample json output.
2888 void TestingAutomationProvider::GetOmniboxInfo(Browser
* browser
,
2889 base::DictionaryValue
* args
,
2890 IPC::Message
* reply_message
) {
2891 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
2892 AutomationJSONReply
reply(this, reply_message
);
2894 LocationBar
* loc_bar
= browser
->window()->GetLocationBar();
2896 reply
.SendError("The specified browser does not have a location bar.");
2899 const OmniboxView
* omnibox_view
= loc_bar
->GetOmniboxView();
2900 const OmniboxEditModel
* model
= omnibox_view
->model();
2903 base::ListValue
* matches
= new base::ListValue
;
2904 const AutocompleteResult
& result
= model
->result();
2905 for (AutocompleteResult::const_iterator
i(result
.begin()); i
!= result
.end();
2907 const AutocompleteMatch
& match
= *i
;
2908 base::DictionaryValue
* item
=
2909 new base::DictionaryValue
; // owned by return_value
2910 item
->SetString("type", AutocompleteMatchType::ToString(match
.type
));
2911 item
->SetBoolean("starred", match
.starred
);
2912 item
->SetString("destination_url", match
.destination_url
.spec());
2913 item
->SetString("contents", match
.contents
);
2914 item
->SetString("description", match
.description
);
2915 matches
->Append(item
);
2917 return_value
->Set("matches", matches
);
2919 // Fill up other properties.
2920 base::DictionaryValue
* properties
=
2921 new base::DictionaryValue
; // owned by return_value
2922 properties
->SetBoolean("has_focus", model
->has_focus());
2923 properties
->SetBoolean("query_in_progress",
2924 !model
->autocomplete_controller()->done());
2925 properties
->SetString("keyword", model
->keyword());
2926 properties
->SetString("text", omnibox_view
->GetText());
2927 return_value
->Set("properties", properties
);
2929 reply
.SendSuccess(return_value
.get());
2932 // Sample json input: { "command": "SetOmniboxText",
2934 void TestingAutomationProvider::SetOmniboxText(Browser
* browser
,
2935 base::DictionaryValue
* args
,
2936 IPC::Message
* reply_message
) {
2937 base::string16 text
;
2938 AutomationJSONReply
reply(this, reply_message
);
2939 if (!args
->GetString("text", &text
)) {
2940 reply
.SendError("text missing");
2943 chrome::FocusLocationBar(browser
);
2944 LocationBar
* loc_bar
= browser
->window()->GetLocationBar();
2946 reply
.SendError("The specified browser does not have a location bar.");
2949 OmniboxView
* omnibox_view
= loc_bar
->GetOmniboxView();
2950 omnibox_view
->model()->OnSetFocus(false);
2951 omnibox_view
->SetUserText(text
);
2952 reply
.SendSuccess(NULL
);
2955 // Sample json input: { "command": "OmniboxMovePopupSelection",
2957 // Negative count implies up, positive implies down. Count values will be
2958 // capped by the size of the popup list.
2959 void TestingAutomationProvider::OmniboxMovePopupSelection(
2961 base::DictionaryValue
* args
,
2962 IPC::Message
* reply_message
) {
2964 AutomationJSONReply
reply(this, reply_message
);
2965 if (!args
->GetInteger("count", &count
)) {
2966 reply
.SendError("count missing");
2969 LocationBar
* loc_bar
= browser
->window()->GetLocationBar();
2971 reply
.SendError("The specified browser does not have a location bar.");
2974 loc_bar
->GetOmniboxView()->model()->OnUpOrDownKeyPressed(count
);
2975 reply
.SendSuccess(NULL
);
2978 // Sample json input: { "command": "OmniboxAcceptInput" }
2979 void TestingAutomationProvider::OmniboxAcceptInput(
2981 base::DictionaryValue
* args
,
2982 IPC::Message
* reply_message
) {
2983 NavigationController
& controller
=
2984 browser
->tab_strip_model()->GetActiveWebContents()->GetController();
2985 LocationBar
* loc_bar
= browser
->window()->GetLocationBar();
2987 AutomationJSONReply(this, reply_message
).SendError(
2988 "The specified browser does not have a location bar.");
2991 new OmniboxAcceptNotificationObserver(&controller
, this, reply_message
);
2992 loc_bar
->AcceptInput();
2995 // Sample json input: { "command": "GetInitialLoadTimes" }
2996 // Refer to InitialLoadObserver::GetTimingInformation() for sample output.
2997 void TestingAutomationProvider::GetInitialLoadTimes(
2999 base::DictionaryValue
*,
3000 IPC::Message
* reply_message
) {
3001 scoped_ptr
<base::DictionaryValue
> return_value(
3002 initial_load_observer_
->GetTimingInformation());
3004 std::string json_return
;
3005 base::JSONWriter::Write(return_value
.get(), &json_return
);
3006 AutomationMsg_SendJSONRequest::WriteReplyParams(
3007 reply_message
, json_return
, true);
3008 Send(reply_message
);
3011 // Sample json input: { "command": "GetPluginsInfo" }
3012 // Refer chrome/test/pyautolib/plugins_info.py for sample json output.
3013 void TestingAutomationProvider::GetPluginsInfo(
3015 base::DictionaryValue
* args
,
3016 IPC::Message
* reply_message
) {
3017 PluginService::GetInstance()->GetPlugins(
3018 base::Bind(&TestingAutomationProvider::GetPluginsInfoCallback
,
3019 this, browser
, args
, reply_message
));
3022 void TestingAutomationProvider::GetPluginsInfoCallback(
3024 base::DictionaryValue
* args
,
3025 IPC::Message
* reply_message
,
3026 const std::vector
<content::WebPluginInfo
>& plugins
) {
3027 PluginPrefs
* plugin_prefs
=
3028 PluginPrefs::GetForProfile(browser
->profile()).get();
3029 base::ListValue
* items
= new base::ListValue
;
3030 for (std::vector
<content::WebPluginInfo
>::const_iterator it
=
3032 it
!= plugins
.end();
3034 base::DictionaryValue
* item
= new base::DictionaryValue
;
3035 item
->SetString("name", it
->name
);
3036 item
->SetString("path", it
->path
.value());
3037 item
->SetString("version", it
->version
);
3038 item
->SetString("desc", it
->desc
);
3039 item
->SetBoolean("enabled", plugin_prefs
->IsPluginEnabled(*it
));
3040 // Add info about mime types.
3041 base::ListValue
* mime_types
= new base::ListValue();
3042 for (std::vector
<content::WebPluginMimeType
>::const_iterator type_it
=
3043 it
->mime_types
.begin();
3044 type_it
!= it
->mime_types
.end();
3046 base::DictionaryValue
* mime_type
= new base::DictionaryValue();
3047 mime_type
->SetString("mimeType", type_it
->mime_type
);
3048 mime_type
->SetString("description", type_it
->description
);
3050 base::ListValue
* file_extensions
= new base::ListValue();
3051 for (std::vector
<std::string
>::const_iterator ext_it
=
3052 type_it
->file_extensions
.begin();
3053 ext_it
!= type_it
->file_extensions
.end();
3055 file_extensions
->Append(new base::StringValue(*ext_it
));
3057 mime_type
->Set("fileExtensions", file_extensions
);
3059 mime_types
->Append(mime_type
);
3061 item
->Set("mimeTypes", mime_types
);
3062 items
->Append(item
);
3064 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
3065 return_value
->Set("plugins", items
); // return_value owns items.
3067 AutomationJSONReply(this, reply_message
).SendSuccess(return_value
.get());
3070 // Sample json input:
3071 // { "command": "EnablePlugin",
3072 // "path": "/Library/Internet Plug-Ins/Flash Player.plugin" }
3073 void TestingAutomationProvider::EnablePlugin(Browser
* browser
,
3074 base::DictionaryValue
* args
,
3075 IPC::Message
* reply_message
) {
3076 base::FilePath::StringType path
;
3077 if (!args
->GetString("path", &path
)) {
3078 AutomationJSONReply(this, reply_message
).SendError("path not specified.");
3081 PluginPrefs
* plugin_prefs
=
3082 PluginPrefs::GetForProfile(browser
->profile()).get();
3083 plugin_prefs
->EnablePlugin(
3085 base::FilePath(path
),
3086 base::Bind(&DidEnablePlugin
,
3090 "Could not enable plugin for path %s."));
3093 // Sample json input:
3094 // { "command": "DisablePlugin",
3095 // "path": "/Library/Internet Plug-Ins/Flash Player.plugin" }
3096 void TestingAutomationProvider::DisablePlugin(Browser
* browser
,
3097 base::DictionaryValue
* args
,
3098 IPC::Message
* reply_message
) {
3099 base::FilePath::StringType path
;
3100 if (!args
->GetString("path", &path
)) {
3101 AutomationJSONReply(this, reply_message
).SendError("path not specified.");
3104 PluginPrefs
* plugin_prefs
=
3105 PluginPrefs::GetForProfile(browser
->profile()).get();
3106 plugin_prefs
->EnablePlugin(
3108 base::FilePath(path
),
3109 base::Bind(&DidEnablePlugin
,
3113 "Could not disable plugin for path %s."));
3116 // Sample json input:
3117 // { "command": "SaveTabContents",
3119 // "filename": <a full pathname> }
3120 // Sample json output:
3122 void TestingAutomationProvider::SaveTabContents(
3124 base::DictionaryValue
* args
,
3125 IPC::Message
* reply_message
) {
3127 base::FilePath::StringType filename
;
3128 base::FilePath::StringType parent_directory
;
3129 WebContents
* web_contents
= NULL
;
3131 if (!args
->GetInteger("tab_index", &tab_index
) ||
3132 !args
->GetString("filename", &filename
)) {
3133 AutomationJSONReply(this, reply_message
)
3134 .SendError("tab_index or filename param missing");
3137 web_contents
= browser
->tab_strip_model()->GetWebContentsAt(tab_index
);
3138 if (!web_contents
) {
3139 AutomationJSONReply(this, reply_message
).SendError("no tab at tab_index");
3143 // We're doing a SAVE_AS_ONLY_HTML so the the directory path isn't
3144 // used. Nevertheless, SavePackage requires it be valid. Sigh.
3145 parent_directory
= base::FilePath(filename
).DirName().value();
3146 if (!web_contents
->SavePage(
3147 base::FilePath(filename
),
3148 base::FilePath(parent_directory
),
3149 content::SAVE_PAGE_TYPE_AS_ONLY_HTML
)) {
3150 AutomationJSONReply(this, reply_message
).SendError(
3151 "Could not initiate SavePage");
3154 // The observer will delete itself when done.
3155 new SavePackageNotificationObserver(
3156 BrowserContext::GetDownloadManager(browser
->profile()),
3157 this, reply_message
);
3162 // Translates a dictionary password to a PasswordForm struct.
3163 autofill::PasswordForm
GetPasswordFormFromDict(
3164 const base::DictionaryValue
& password_dict
) {
3166 // If the time is specified, change time to the specified time.
3167 base::Time time
= base::Time::Now();
3170 if (password_dict
.GetInteger("time", &it
))
3171 time
= base::Time::FromTimeT(it
);
3172 else if (password_dict
.GetDouble("time", &dt
))
3173 time
= base::Time::FromDoubleT(dt
);
3175 std::string signon_realm
;
3176 base::string16 username_value
;
3177 base::string16 password_value
;
3178 base::string16 origin_url_text
;
3179 base::string16 username_element
;
3180 base::string16 password_element
;
3181 base::string16 submit_element
;
3182 base::string16 action_target_text
;
3184 base::string16 old_password_element
;
3185 base::string16 old_password_value
;
3187 // We don't care if any of these fail - they are either optional or checked
3188 // before this function is called.
3189 password_dict
.GetString("signon_realm", &signon_realm
);
3190 password_dict
.GetString("username_value", &username_value
);
3191 password_dict
.GetString("password_value", &password_value
);
3192 password_dict
.GetString("origin_url", &origin_url_text
);
3193 password_dict
.GetString("username_element", &username_element
);
3194 password_dict
.GetString("password_element", &password_element
);
3195 password_dict
.GetString("submit_element", &submit_element
);
3196 password_dict
.GetString("action_target", &action_target_text
);
3197 if (!password_dict
.GetBoolean("blacklist", &blacklist
))
3200 GURL
origin_gurl(origin_url_text
);
3201 GURL
action_target(action_target_text
);
3203 autofill::PasswordForm password_form
;
3204 password_form
.signon_realm
= signon_realm
;
3205 password_form
.username_value
= username_value
;
3206 password_form
.password_value
= password_value
;
3207 password_form
.origin
= origin_gurl
;
3208 password_form
.username_element
= username_element
;
3209 password_form
.password_element
= password_element
;
3210 password_form
.submit_element
= submit_element
;
3211 password_form
.action
= action_target
;
3212 password_form
.blacklisted_by_user
= blacklist
;
3213 password_form
.date_created
= time
;
3215 return password_form
;
3220 // See AddSavedPassword() in chrome/test/functional/pyauto.py for sample json
3222 // Sample json output: { "password_added": true }
3223 void TestingAutomationProvider::AddSavedPassword(
3225 base::DictionaryValue
* args
,
3226 IPC::Message
* reply_message
) {
3227 base::DictionaryValue
* password_dict
= NULL
;
3228 if (!args
->GetDictionary("password", &password_dict
)) {
3229 AutomationJSONReply(this, reply_message
).SendError(
3230 "Must specify a password dictionary.");
3234 // The "signon realm" is effectively the primary key and must be included.
3235 // Check here before calling GetPasswordFormFromDict.
3236 if (!password_dict
->HasKey("signon_realm")) {
3237 AutomationJSONReply(this, reply_message
).SendError(
3238 "Password must include a value for 'signon_realm.'");
3242 autofill::PasswordForm new_password
=
3243 GetPasswordFormFromDict(*password_dict
);
3245 // Use IMPLICIT_ACCESS since new passwords aren't added in incognito mode.
3246 PasswordStore
* password_store
= PasswordStoreFactory::GetForProfile(
3247 browser
->profile(), Profile::IMPLICIT_ACCESS
).get();
3249 // The password store does not exist for an incognito window.
3250 if (password_store
== NULL
) {
3251 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
3252 return_value
->SetBoolean("password_added", false);
3253 AutomationJSONReply(this, reply_message
).SendSuccess(return_value
.get());
3257 // This observer will delete itself.
3258 PasswordStoreLoginsChangedObserver
* observer
=
3259 new PasswordStoreLoginsChangedObserver(this, reply_message
,
3260 PasswordStoreChange::ADD
,
3263 password_store
->AddLogin(new_password
);
3266 // See RemoveSavedPassword() in chrome/test/functional/pyauto.py for sample
3268 // Sample json output: {}
3269 void TestingAutomationProvider::RemoveSavedPassword(
3271 base::DictionaryValue
* args
,
3272 IPC::Message
* reply_message
) {
3273 base::DictionaryValue
* password_dict
= NULL
;
3275 if (!args
->GetDictionary("password", &password_dict
)) {
3276 AutomationJSONReply(this, reply_message
).SendError(
3277 "Must specify a password dictionary.");
3281 // The "signon realm" is effectively the primary key and must be included.
3282 // Check here before calling GetPasswordFormFromDict.
3283 if (!password_dict
->HasKey("signon_realm")) {
3284 AutomationJSONReply(this, reply_message
).SendError(
3285 "Password must include a value for 'signon_realm.'");
3288 autofill::PasswordForm to_remove
=
3289 GetPasswordFormFromDict(*password_dict
);
3291 // Use EXPLICIT_ACCESS since passwords can be removed in incognito mode.
3292 PasswordStore
* password_store
= PasswordStoreFactory::GetForProfile(
3293 browser
->profile(), Profile::EXPLICIT_ACCESS
).get();
3294 if (password_store
== NULL
) {
3295 AutomationJSONReply(this, reply_message
).SendError(
3296 "Unable to get password store.");
3300 // This observer will delete itself.
3301 PasswordStoreLoginsChangedObserver
* observer
=
3302 new PasswordStoreLoginsChangedObserver(
3303 this, reply_message
, PasswordStoreChange::REMOVE
, std::string());
3306 password_store
->RemoveLogin(to_remove
);
3309 // Sample json input: { "command": "GetSavedPasswords" }
3310 // Refer to GetSavedPasswords() in chrome/test/pyautolib/pyauto.py for sample
3312 void TestingAutomationProvider::GetSavedPasswords(
3314 base::DictionaryValue
* args
,
3315 IPC::Message
* reply_message
) {
3316 // Use EXPLICIT_ACCESS since saved passwords can be retrieved in
3318 PasswordStore
* password_store
= PasswordStoreFactory::GetForProfile(
3319 browser
->profile(), Profile::EXPLICIT_ACCESS
).get();
3321 if (password_store
== NULL
) {
3322 AutomationJSONReply
reply(this, reply_message
);
3323 reply
.SendError("Unable to get password store.");
3326 password_store
->GetAutofillableLogins(
3327 new AutomationProviderGetPasswordsObserver(this, reply_message
));
3328 // Observer deletes itself after sending the result.
3333 // Get the WebContents from a dictionary of arguments.
3334 WebContents
* GetWebContentsFromDict(const Browser
* browser
,
3335 const base::DictionaryValue
* args
,
3336 std::string
* error_message
) {
3338 if (!args
->GetInteger("tab_index", &tab_index
)) {
3339 *error_message
= "Must include tab_index.";
3343 WebContents
* web_contents
=
3344 browser
->tab_strip_model()->GetWebContentsAt(tab_index
);
3345 if (!web_contents
) {
3346 *error_message
= base::StringPrintf("No tab at index %d.", tab_index
);
3349 return web_contents
;
3354 void TestingAutomationProvider::FindInPage(
3356 base::DictionaryValue
* args
,
3357 IPC::Message
* reply_message
) {
3358 std::string error_message
;
3359 WebContents
* web_contents
=
3360 GetWebContentsFromDict(browser
, args
, &error_message
);
3361 if (!web_contents
) {
3362 AutomationJSONReply(this, reply_message
).SendError(error_message
);
3365 base::string16 search_string
;
3369 if (!args
->GetString("search_string", &search_string
)) {
3370 AutomationJSONReply(this, reply_message
).
3371 SendError("Must include search_string string.");
3374 if (!args
->GetBoolean("forward", &forward
)) {
3375 AutomationJSONReply(this, reply_message
).
3376 SendError("Must include forward boolean.");
3379 if (!args
->GetBoolean("match_case", &match_case
)) {
3380 AutomationJSONReply(this, reply_message
).
3381 SendError("Must include match_case boolean.");
3384 if (!args
->GetBoolean("find_next", &find_next
)) {
3385 AutomationJSONReply(this, reply_message
).
3386 SendError("Must include find_next boolean.");
3389 SendFindRequest(web_contents
,
3398 void TestingAutomationProvider::OpenFindInPage(
3399 base::DictionaryValue
* args
,
3400 IPC::Message
* reply_message
) {
3401 AutomationJSONReply
reply(this, reply_message
);
3403 std::string error_msg
;
3404 if (!GetBrowserFromJSONArgs(args
, &browser
, &error_msg
)) {
3405 reply
.SendError(error_msg
);
3408 chrome::FindInPage(browser
, false, false);
3409 reply
.SendSuccess(NULL
);
3412 void TestingAutomationProvider::IsFindInPageVisible(
3413 base::DictionaryValue
* args
,
3414 IPC::Message
* reply_message
) {
3415 AutomationJSONReply
reply(this, reply_message
);
3418 std::string error_msg
;
3419 if (!GetBrowserFromJSONArgs(args
, &browser
, &error_msg
)) {
3420 reply
.SendError(error_msg
);
3423 FindBarTesting
* find_bar
=
3424 browser
->GetFindBarController()->find_bar()->GetFindBarTesting();
3425 find_bar
->GetFindBarWindowInfo(NULL
, &visible
);
3426 base::DictionaryValue dict
;
3427 dict
.SetBoolean("is_visible", visible
);
3428 reply
.SendSuccess(&dict
);
3431 void TestingAutomationProvider::InstallExtension(
3432 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
3433 base::FilePath::StringType path_string
;
3435 bool from_webstore
= false;
3437 content::WebContents
* tab
;
3438 std::string error_msg
;
3439 if (!GetBrowserAndTabFromJSONArgs(args
, &browser
, &tab
, &error_msg
)) {
3440 AutomationJSONReply(this, reply_message
).SendError(error_msg
);
3443 if (!args
->GetString("path", &path_string
)) {
3444 AutomationJSONReply(this, reply_message
).SendError(
3445 "Missing or invalid 'path'");
3448 if (!args
->GetBoolean("with_ui", &with_ui
)) {
3449 AutomationJSONReply(this, reply_message
).SendError(
3450 "Missing or invalid 'with_ui'");
3453 args
->GetBoolean("from_webstore", &from_webstore
);
3455 ExtensionService
* service
= extensions::ExtensionSystem::Get(
3456 browser
->profile())->extension_service();
3457 extensions::ProcessManager
* manager
=
3458 extensions::ExtensionSystem::Get(browser
->profile())->process_manager();
3459 if (service
&& manager
) {
3460 // The observer will delete itself when done.
3461 new ExtensionReadyNotificationObserver(
3467 base::FilePath
extension_path(path_string
);
3468 // If the given path has a 'crx' extension, assume it is a packed extension
3469 // and install it. Otherwise load it as an unpacked extension.
3470 if (extension_path
.MatchesExtension(FILE_PATH_LITERAL(".crx"))) {
3471 scoped_ptr
<ExtensionInstallPrompt
> client(
3472 with_ui
? new ExtensionInstallPrompt(tab
) : NULL
);
3473 scoped_refptr
<extensions::CrxInstaller
> installer(
3474 extensions::CrxInstaller::Create(service
, client
.Pass()));
3476 installer
->set_allow_silent_install(true);
3477 installer
->set_install_cause(extension_misc::INSTALL_CAUSE_AUTOMATION
);
3479 installer
->set_creation_flags(Extension::FROM_WEBSTORE
);
3480 installer
->InstallCrx(extension_path
);
3482 scoped_refptr
<extensions::UnpackedInstaller
> installer(
3483 extensions::UnpackedInstaller::Create(service
));
3484 installer
->set_prompt_for_plugins(with_ui
);
3485 installer
->Load(extension_path
);
3488 AutomationJSONReply(this, reply_message
).SendError(
3489 "Extensions service/process manager is not available");
3495 base::ListValue
* GetHostPermissions(const Extension
* ext
, bool effective_perm
) {
3496 extensions::URLPatternSet pattern_set
;
3497 if (effective_perm
) {
3499 extensions::PermissionsData::GetEffectiveHostPermissions(ext
);
3501 pattern_set
= ext
->GetActivePermissions()->explicit_hosts();
3504 base::ListValue
* permissions
= new base::ListValue
;
3505 for (extensions::URLPatternSet::const_iterator perm
= pattern_set
.begin();
3506 perm
!= pattern_set
.end(); ++perm
) {
3507 permissions
->Append(new base::StringValue(perm
->GetAsString()));
3513 base::ListValue
* GetAPIPermissions(const Extension
* ext
) {
3514 base::ListValue
* permissions
= new base::ListValue
;
3515 std::set
<std::string
> perm_list
=
3516 ext
->GetActivePermissions()->GetAPIsAsStrings();
3517 for (std::set
<std::string
>::const_iterator perm
= perm_list
.begin();
3518 perm
!= perm_list
.end(); ++perm
) {
3519 permissions
->Append(new base::StringValue(perm
->c_str()));
3526 // Sample json input: { "command": "GetExtensionsInfo" }
3527 // See GetExtensionsInfo() in chrome/test/pyautolib/pyauto.py for sample json
3529 void TestingAutomationProvider::GetExtensionsInfo(base::DictionaryValue
* args
,
3530 IPC::Message
* reply_message
) {
3531 AutomationJSONReply
reply(this, reply_message
);
3533 std::string error_msg
;
3534 if (!GetBrowserFromJSONArgs(args
, &browser
, &error_msg
)) {
3535 reply
.SendError(error_msg
);
3538 ExtensionService
* service
= extensions::ExtensionSystem::Get(
3539 browser
->profile())->extension_service();
3541 reply
.SendError("No extensions service.");
3544 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
3545 base::ListValue
* extensions_values
= new base::ListValue
;
3546 const extensions::ExtensionSet
* extensions
= service
->extensions();
3547 const extensions::ExtensionSet
* disabled_extensions
=
3548 service
->disabled_extensions();
3550 all
.insert(all
.end(),
3551 extensions
->begin(),
3553 all
.insert(all
.end(),
3554 disabled_extensions
->begin(),
3555 disabled_extensions
->end());
3556 ExtensionActionManager
* extension_action_manager
=
3557 ExtensionActionManager::Get(browser
->profile());
3558 for (ExtensionList::const_iterator it
= all
.begin();
3559 it
!= all
.end(); ++it
) {
3560 const Extension
* extension
= it
->get();
3561 std::string id
= extension
->id();
3562 base::DictionaryValue
* extension_value
= new base::DictionaryValue
;
3563 extension_value
->SetString("id", id
);
3564 extension_value
->SetString("version", extension
->VersionString());
3565 extension_value
->SetString("name", extension
->name());
3566 extension_value
->SetString("public_key", extension
->public_key());
3567 extension_value
->SetString("description", extension
->description());
3568 extension_value
->SetString(
3570 extensions::BackgroundInfo::GetBackgroundURL(extension
).spec());
3571 extension_value
->SetString("options_url",
3572 extensions::ManifestURL::GetOptionsPage(extension
).spec());
3573 extension_value
->Set("host_permissions",
3574 GetHostPermissions(extension
, false));
3575 extension_value
->Set("effective_host_permissions",
3576 GetHostPermissions(extension
, true));
3577 extension_value
->Set("api_permissions", GetAPIPermissions(extension
));
3578 Manifest::Location location
= extension
->location();
3579 extension_value
->SetBoolean("is_component",
3580 location
== Manifest::COMPONENT
);
3581 extension_value
->SetBoolean("is_internal",
3582 location
== Manifest::INTERNAL
);
3583 extension_value
->SetBoolean("is_user_installed",
3584 location
== Manifest::INTERNAL
||
3585 Manifest::IsUnpackedLocation(location
));
3586 extension_value
->SetBoolean("is_enabled", service
->IsExtensionEnabled(id
));
3587 extension_value
->SetBoolean("allowed_in_incognito",
3588 extension_util::IsIncognitoEnabled(id
, service
));
3589 extension_value
->SetBoolean(
3591 extension_action_manager
->GetPageAction(*extension
) != NULL
);
3592 extensions_values
->Append(extension_value
);
3594 return_value
->Set("extensions", extensions_values
);
3595 reply
.SendSuccess(return_value
.get());
3598 // See UninstallExtensionById() in chrome/test/pyautolib/pyauto.py for sample
3600 // Sample json output: {}
3601 void TestingAutomationProvider::UninstallExtensionById(
3602 base::DictionaryValue
* args
,
3603 IPC::Message
* reply_message
) {
3604 const Extension
* extension
;
3607 if (!GetBrowserFromJSONArgs(args
, &browser
, &error
)) {
3608 AutomationJSONReply(this, reply_message
).SendError(error
);
3611 if (!GetExtensionFromJSONArgs(
3612 args
, "id", browser
->profile(), &extension
, &error
)) {
3613 AutomationJSONReply(this, reply_message
).SendError(error
);
3616 ExtensionService
* service
= extensions::ExtensionSystem::Get(
3617 browser
->profile())->extension_service();
3619 AutomationJSONReply(this, reply_message
).SendError(
3620 "No extensions service.");
3624 // Wait for a notification indicating that the extension with the given ID
3625 // has been uninstalled. This observer will delete itself.
3626 new ExtensionUninstallObserver(this, reply_message
, extension
->id());
3627 service
->UninstallExtension(extension
->id(), false, NULL
);
3630 // See SetExtensionStateById() in chrome/test/pyautolib/pyauto.py
3631 // for sample json input.
3632 void TestingAutomationProvider::SetExtensionStateById(
3633 base::DictionaryValue
* args
,
3634 IPC::Message
* reply_message
) {
3635 const Extension
* extension
;
3638 if (!GetBrowserFromJSONArgs(args
, &browser
, &error
)) {
3639 AutomationJSONReply(this, reply_message
).SendError(error
);
3642 if (!GetExtensionFromJSONArgs(
3643 args
, "id", browser
->profile(), &extension
, &error
)) {
3644 AutomationJSONReply(this, reply_message
).SendError(error
);
3649 if (!args
->GetBoolean("enable", &enable
)) {
3650 AutomationJSONReply(this, reply_message
)
3651 .SendError("Missing or invalid key: enable");
3655 bool allow_in_incognito
;
3656 if (!args
->GetBoolean("allow_in_incognito", &allow_in_incognito
)) {
3657 AutomationJSONReply(this, reply_message
)
3658 .SendError("Missing or invalid key: allow_in_incognito");
3662 if (allow_in_incognito
&& !enable
) {
3663 AutomationJSONReply(this, reply_message
)
3664 .SendError("Invalid state: Disabled extension "
3665 "cannot be allowed in incognito mode.");
3669 ExtensionService
* service
= extensions::ExtensionSystem::Get(
3670 browser
->profile())->extension_service();
3671 extensions::ProcessManager
* manager
=
3672 extensions::ExtensionSystem::Get(browser
->profile())->process_manager();
3674 AutomationJSONReply(this, reply_message
)
3675 .SendError("No extensions service or process manager.");
3680 if (!service
->IsExtensionEnabled(extension
->id())) {
3681 new ExtensionReadyNotificationObserver(
3686 service
->EnableExtension(extension
->id());
3688 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
3691 service
->DisableExtension(extension
->id(),
3692 Extension::DISABLE_USER_ACTION
);
3693 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
3696 extension_util::SetIsIncognitoEnabled(
3697 extension
->id(), service
, allow_in_incognito
);
3700 // See TriggerPageActionById() in chrome/test/pyautolib/pyauto.py
3701 // for sample json input.
3702 void TestingAutomationProvider::TriggerPageActionById(
3703 base::DictionaryValue
* args
,
3704 IPC::Message
* reply_message
) {
3708 if (!GetBrowserAndTabFromJSONArgs(args
, &browser
, &tab
, &error
)) {
3709 AutomationJSONReply(this, reply_message
).SendError(error
);
3712 const Extension
* extension
;
3713 if (!GetEnabledExtensionFromJSONArgs(
3714 args
, "id", browser
->profile(), &extension
, &error
)) {
3715 AutomationJSONReply(this, reply_message
).SendError(error
);
3718 ExtensionAction
* page_action
=
3719 ExtensionActionManager::Get(browser
->profile())->
3720 GetPageAction(*extension
);
3722 AutomationJSONReply(this, reply_message
).SendError(
3723 "Extension doesn't have any page action.");
3726 EnsureTabSelected(browser
, tab
);
3728 bool pressed
= false;
3729 LocationBarTesting
* loc_bar
=
3730 browser
->window()->GetLocationBar()->GetLocationBarForTesting();
3731 size_t page_action_visible_count
=
3732 static_cast<size_t>(loc_bar
->PageActionVisibleCount());
3733 for (size_t i
= 0; i
< page_action_visible_count
; ++i
) {
3734 if (loc_bar
->GetVisiblePageAction(i
) == page_action
) {
3735 loc_bar
->TestPageActionPressed(i
);
3741 AutomationJSONReply(this, reply_message
).SendError(
3742 "Extension's page action is not visible.");
3746 if (page_action
->HasPopup(extensions::ExtensionTabUtil::GetTabId(tab
))) {
3747 // This observer will delete itself.
3748 new ExtensionPopupObserver(
3749 this, reply_message
, extension
->id());
3751 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
3755 // See TriggerBrowserActionById() in chrome/test/pyautolib/pyauto.py
3756 // for sample json input.
3757 void TestingAutomationProvider::TriggerBrowserActionById(
3758 base::DictionaryValue
* args
,
3759 IPC::Message
* reply_message
) {
3763 if (!GetBrowserAndTabFromJSONArgs(args
, &browser
, &tab
, &error
)) {
3764 AutomationJSONReply(this, reply_message
).SendError(error
);
3767 const Extension
* extension
;
3768 if (!GetEnabledExtensionFromJSONArgs(
3769 args
, "id", browser
->profile(), &extension
, &error
)) {
3770 AutomationJSONReply(this, reply_message
).SendError(error
);
3773 ExtensionAction
* action
= ExtensionActionManager::Get(browser
->profile())->
3774 GetBrowserAction(*extension
);
3776 AutomationJSONReply(this, reply_message
).SendError(
3777 "Extension doesn't have any browser action.");
3780 EnsureTabSelected(browser
, tab
);
3782 BrowserActionTestUtil
browser_actions(browser
);
3783 int num_browser_actions
= browser_actions
.NumberOfBrowserActions();
3784 int action_index
= -1;
3785 #if defined(TOOLKIT_VIEWS)
3786 for (int i
= 0; i
< num_browser_actions
; ++i
) {
3787 if (extension
->id() == browser_actions
.GetExtensionId(i
)) {
3793 // TODO(kkania): Implement the platform-specific GetExtensionId() in
3794 // BrowserActionTestUtil.
3795 if (num_browser_actions
!= 1) {
3796 AutomationJSONReply(this, reply_message
).SendError(base::StringPrintf(
3797 "Found %d browser actions. Only one browser action must be active.",
3798 num_browser_actions
));
3801 // This extension has a browser action, and there's only one action, so this
3802 // must be the first one.
3805 if (action_index
== -1) {
3806 AutomationJSONReply(this, reply_message
).SendError(
3807 "Extension's browser action is not visible.");
3810 browser_actions
.Press(action_index
);
3812 if (action
->HasPopup(extensions::ExtensionTabUtil::GetTabId(tab
))) {
3813 // This observer will delete itself.
3814 new ExtensionPopupObserver(
3815 this, reply_message
, extension
->id());
3817 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
3821 void TestingAutomationProvider::ActionOnSSLBlockingPage(
3822 base::DictionaryValue
* args
,
3823 IPC::Message
* reply_message
) {
3824 WebContents
* web_contents
;
3827 if (!GetTabFromJSONArgs(args
, &web_contents
, &error
)) {
3828 AutomationJSONReply(this, reply_message
).SendError(error
);
3831 if (!args
->GetBoolean("proceed", &proceed
)) {
3832 AutomationJSONReply(this, reply_message
).SendError(
3833 "'proceed' is missing or invalid");
3836 NavigationController
& controller
= web_contents
->GetController();
3837 NavigationEntry
* entry
= controller
.GetActiveEntry();
3838 if (entry
->GetPageType() == content::PAGE_TYPE_INTERSTITIAL
) {
3839 InterstitialPage
* ssl_blocking_page
=
3840 InterstitialPage::GetInterstitialPage(web_contents
);
3841 if (ssl_blocking_page
) {
3843 new NavigationNotificationObserver(&controller
, this, reply_message
, 1,
3845 ssl_blocking_page
->Proceed();
3848 ssl_blocking_page
->DontProceed();
3849 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
3853 AutomationJSONReply(this, reply_message
).SendError(error
);
3856 void TestingAutomationProvider::GetSecurityState(base::DictionaryValue
* args
,
3857 IPC::Message
* reply_message
) {
3858 AutomationJSONReply
reply(this, reply_message
);
3859 WebContents
* web_contents
;
3861 if (!GetTabFromJSONArgs(args
, &web_contents
, &error
)) {
3862 reply
.SendError(error
);
3865 NavigationEntry
* entry
= web_contents
->GetController().GetActiveEntry();
3866 base::DictionaryValue dict
;
3867 dict
.SetInteger("security_style",
3868 static_cast<int>(entry
->GetSSL().security_style
));
3869 dict
.SetInteger("ssl_cert_status",
3870 static_cast<int>(entry
->GetSSL().cert_status
));
3871 dict
.SetInteger("insecure_content_status",
3872 static_cast<int>(entry
->GetSSL().content_status
));
3873 reply
.SendSuccess(&dict
);
3876 // Sample json input: { "command": "UpdateExtensionsNow" }
3877 // Sample json output: {}
3878 void TestingAutomationProvider::UpdateExtensionsNow(
3879 base::DictionaryValue
* args
,
3880 IPC::Message
* reply_message
) {
3883 if (!GetBrowserFromJSONArgs(args
, &browser
, &error
)) {
3884 AutomationJSONReply(this, reply_message
).SendError(error
);
3887 ExtensionService
* service
= extensions::ExtensionSystem::Get(
3888 browser
->profile())->extension_service();
3890 AutomationJSONReply(this, reply_message
).SendError(
3891 "No extensions service.");
3895 extensions::ExtensionUpdater
* updater
= service
->updater();
3897 AutomationJSONReply(this, reply_message
).SendError(
3898 "No updater for extensions service.");
3902 extensions::ProcessManager
* manager
=
3903 extensions::ExtensionSystem::Get(browser
->profile())->process_manager();
3905 AutomationJSONReply(this, reply_message
).SendError(
3906 "No extension process manager.");
3910 // Create a new observer that waits until the extensions have been fully
3911 // updated (we should not send the reply until after all extensions have
3912 // been updated). This observer will delete itself.
3913 ExtensionsUpdatedObserver
* observer
= new ExtensionsUpdatedObserver(
3914 manager
, this, reply_message
);
3915 extensions::ExtensionUpdater::CheckParams params
;
3916 params
.install_immediately
= true;
3917 params
.callback
= base::Bind(&ExtensionsUpdatedObserver::UpdateCheckFinished
,
3918 base::Unretained(observer
));
3919 updater
->CheckNow(params
);
3924 void SendSuccessIfAlive(
3925 base::WeakPtr
<AutomationProvider
> provider
,
3926 IPC::Message
* reply_message
) {
3928 AutomationJSONReply(provider
.get(), reply_message
).SendSuccess(NULL
);
3933 void TestingAutomationProvider::OverrideGeoposition(
3934 base::DictionaryValue
* args
,
3935 IPC::Message
* reply_message
) {
3936 double latitude
, longitude
, altitude
;
3937 if (!args
->GetDouble("latitude", &latitude
) ||
3938 !args
->GetDouble("longitude", &longitude
) ||
3939 !args
->GetDouble("altitude", &altitude
)) {
3940 AutomationJSONReply(this, reply_message
).SendError(
3941 "Missing or invalid geolocation parameters");
3944 content::Geoposition position
;
3945 position
.latitude
= latitude
;
3946 position
.longitude
= longitude
;
3947 position
.altitude
= altitude
;
3948 position
.accuracy
= 0.;
3949 position
.timestamp
= base::Time::Now();
3951 content::GeolocationProvider::OverrideLocationForTesting(
3953 base::Bind(&SendSuccessIfAlive
, AsWeakPtr(), reply_message
));
3956 // Refer to GetAllNotifications() in chrome/test/pyautolib/pyauto.py for
3957 // sample json input/output.
3958 void TestingAutomationProvider::GetAllNotifications(
3960 base::DictionaryValue
* args
,
3961 IPC::Message
* reply_message
) {
3962 new GetAllNotificationsObserver(this, reply_message
);
3965 // Refer to CloseNotification() in chrome/test/pyautolib/pyauto.py for
3966 // sample json input.
3967 // Returns empty json message.
3968 void TestingAutomationProvider::CloseNotification(
3970 base::DictionaryValue
* args
,
3971 IPC::Message
* reply_message
) {
3973 if (!args
->GetInteger("index", &index
)) {
3974 AutomationJSONReply(this, reply_message
)
3975 .SendError("'index' missing or invalid.");
3978 BalloonNotificationUIManager
* manager
=
3979 BalloonNotificationUIManager::GetInstanceForTesting();
3980 BalloonCollection
* collection
= manager
->balloon_collection();
3981 const BalloonCollection::Balloons
& balloons
= collection
->GetActiveBalloons();
3982 int balloon_count
= static_cast<int>(balloons
.size());
3983 if (index
< 0 || index
>= balloon_count
) {
3984 AutomationJSONReply(this, reply_message
)
3985 .SendError(base::StringPrintf("No notification at index %d", index
));
3988 std::vector
<const Notification
*> queued_notes
;
3989 manager
->GetQueuedNotificationsForTesting(&queued_notes
);
3990 if (queued_notes
.empty()) {
3991 new OnNotificationBalloonCountObserver(
3992 this, reply_message
, balloon_count
- 1);
3994 new NewNotificationBalloonObserver(this, reply_message
);
3996 manager
->CancelById(balloons
[index
]->notification().notification_id());
3999 // Refer to WaitForNotificationCount() in chrome/test/pyautolib/pyauto.py for
4000 // sample json input.
4001 // Returns empty json message.
4002 void TestingAutomationProvider::WaitForNotificationCount(
4004 base::DictionaryValue
* args
,
4005 IPC::Message
* reply_message
) {
4007 if (!args
->GetInteger("count", &count
)) {
4008 AutomationJSONReply(this, reply_message
)
4009 .SendError("'count' missing or invalid.");
4012 // This will delete itself when finished.
4013 new OnNotificationBalloonCountObserver(this, reply_message
, count
);
4016 // Sample JSON input: { "command": "GetNTPInfo" }
4017 // For output, refer to chrome/test/pyautolib/ntp_model.py.
4018 void TestingAutomationProvider::GetNTPInfo(
4020 base::DictionaryValue
* args
,
4021 IPC::Message
* reply_message
) {
4022 // This observer will delete itself.
4023 new NTPInfoObserver(this, reply_message
);
4026 void TestingAutomationProvider::RemoveNTPMostVisitedThumbnail(
4028 base::DictionaryValue
* args
,
4029 IPC::Message
* reply_message
) {
4030 AutomationJSONReply
reply(this, reply_message
);
4032 if (!args
->GetString("url", &url
)) {
4033 reply
.SendError("Missing or invalid 'url' key.");
4036 history::TopSites
* top_sites
= browser
->profile()->GetTopSites();
4038 reply
.SendError("TopSites service is not initialized.");
4041 top_sites
->AddBlacklistedURL(GURL(url
));
4042 reply
.SendSuccess(NULL
);
4045 void TestingAutomationProvider::RestoreAllNTPMostVisitedThumbnails(
4047 base::DictionaryValue
* args
,
4048 IPC::Message
* reply_message
) {
4049 AutomationJSONReply
reply(this, reply_message
);
4050 history::TopSites
* top_sites
= browser
->profile()->GetTopSites();
4052 reply
.SendError("TopSites service is not initialized.");
4055 top_sites
->ClearBlacklistedURLs();
4056 reply
.SendSuccess(NULL
);
4059 void TestingAutomationProvider::KillRendererProcess(
4061 base::DictionaryValue
* args
,
4062 IPC::Message
* reply_message
) {
4064 uint32 kAccessFlags
= base::kProcessAccessTerminate
|
4065 base::kProcessAccessWaitForTermination
|
4066 base::kProcessAccessQueryInformation
;
4068 if (!args
->GetInteger("pid", &pid
)) {
4069 AutomationJSONReply(this, reply_message
)
4070 .SendError("'pid' key missing or invalid.");
4073 base::ProcessHandle process
;
4074 if (!base::OpenProcessHandleWithAccess(static_cast<base::ProcessId
>(pid
),
4077 AutomationJSONReply(this, reply_message
).SendError(base::StringPrintf(
4078 "Failed to open process handle for pid %d", pid
));
4081 new RendererProcessClosedObserver(this, reply_message
);
4082 base::KillProcess(process
, 0, false);
4083 base::CloseProcessHandle(process
);
4086 bool TestingAutomationProvider::BuildWebKeyEventFromArgs(
4087 base::DictionaryValue
* args
,
4089 NativeWebKeyboardEvent
* event
) {
4090 int type
, modifiers
;
4092 base::string16 unmodified_text
, text
;
4093 std::string key_identifier
;
4094 if (!args
->GetInteger("type", &type
)) {
4095 *error
= "'type' missing or invalid.";
4098 if (!args
->GetBoolean("isSystemKey", &is_system_key
)) {
4099 *error
= "'isSystemKey' missing or invalid.";
4102 if (!args
->GetString("unmodifiedText", &unmodified_text
)) {
4103 *error
= "'unmodifiedText' missing or invalid.";
4106 if (!args
->GetString("text", &text
)) {
4107 *error
= "'text' missing or invalid.";
4110 if (!args
->GetInteger("nativeKeyCode", &event
->nativeKeyCode
)) {
4111 *error
= "'nativeKeyCode' missing or invalid.";
4114 if (!args
->GetInteger("windowsKeyCode", &event
->windowsKeyCode
)) {
4115 *error
= "'windowsKeyCode' missing or invalid.";
4118 if (!args
->GetInteger("modifiers", &modifiers
)) {
4119 *error
= "'modifiers' missing or invalid.";
4122 if (args
->GetString("keyIdentifier", &key_identifier
)) {
4123 base::strlcpy(event
->keyIdentifier
,
4124 key_identifier
.c_str(),
4125 blink::WebKeyboardEvent::keyIdentifierLengthCap
);
4127 *error
= "'keyIdentifier' missing or invalid.";
4131 if (type
== automation::kRawKeyDownType
) {
4132 event
->type
= blink::WebInputEvent::RawKeyDown
;
4133 } else if (type
== automation::kKeyDownType
) {
4134 event
->type
= blink::WebInputEvent::KeyDown
;
4135 } else if (type
== automation::kKeyUpType
) {
4136 event
->type
= blink::WebInputEvent::KeyUp
;
4137 } else if (type
== automation::kCharType
) {
4138 event
->type
= blink::WebInputEvent::Char
;
4140 *error
= "'type' refers to an unrecognized keyboard event type";
4144 base::string16 unmodified_text_truncated
= unmodified_text
.substr(
4145 0, blink::WebKeyboardEvent::textLengthCap
- 1);
4146 memcpy(event
->unmodifiedText
,
4147 unmodified_text_truncated
.c_str(),
4148 unmodified_text_truncated
.length() + 1);
4149 base::string16 text_truncated
= text
.substr(
4150 0, blink::WebKeyboardEvent::textLengthCap
- 1);
4151 memcpy(event
->text
, text_truncated
.c_str(), text_truncated
.length() + 1);
4153 event
->modifiers
= 0;
4154 if (modifiers
& automation::kShiftKeyMask
)
4155 event
->modifiers
|= blink::WebInputEvent::ShiftKey
;
4156 if (modifiers
& automation::kControlKeyMask
)
4157 event
->modifiers
|= blink::WebInputEvent::ControlKey
;
4158 if (modifiers
& automation::kAltKeyMask
)
4159 event
->modifiers
|= blink::WebInputEvent::AltKey
;
4160 if (modifiers
& automation::kMetaKeyMask
)
4161 event
->modifiers
|= blink::WebInputEvent::MetaKey
;
4163 event
->isSystemKey
= is_system_key
;
4164 event
->timeStampSeconds
= base::Time::Now().ToDoubleT();
4165 event
->skip_in_browser
= true;
4169 void TestingAutomationProvider::SendWebkitKeyEvent(
4170 base::DictionaryValue
* args
,
4171 IPC::Message
* reply_message
) {
4172 if (SendErrorIfModalDialogActive(this, reply_message
))
4175 NativeWebKeyboardEvent event
;
4176 // In the event of an error, BuildWebKeyEventFromArgs handles telling what
4177 // went wrong and sending the reply message; if it fails, we just have to
4180 if (!BuildWebKeyEventFromArgs(args
, &error
, &event
)) {
4181 AutomationJSONReply(this, reply_message
).SendError(error
);
4185 RenderViewHost
* view
;
4186 if (!GetRenderViewFromJSONArgs(args
, profile(), &view
, &error
)) {
4187 AutomationJSONReply(this, reply_message
).SendError(error
);
4190 new InputEventAckNotificationObserver(this, reply_message
, event
.type
, 1);
4191 view
->ForwardKeyboardEvent(event
);
4196 // Gets the active JavaScript modal dialog, or NULL if none.
4197 JavaScriptAppModalDialog
* GetActiveJavaScriptModalDialog(
4198 std::string
* error_msg
) {
4199 AppModalDialogQueue
* dialog_queue
= AppModalDialogQueue::GetInstance();
4200 if (!dialog_queue
->HasActiveDialog() ||
4201 !dialog_queue
->active_dialog()->IsJavaScriptModalDialog()) {
4202 *error_msg
= "No JavaScriptModalDialog open";
4205 return static_cast<JavaScriptAppModalDialog
*>(dialog_queue
->active_dialog());
4210 void TestingAutomationProvider::GetAppModalDialogMessage(
4211 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
4212 AutomationJSONReply
reply(this, reply_message
);
4213 std::string error_msg
;
4214 JavaScriptAppModalDialog
* dialog
= GetActiveJavaScriptModalDialog(&error_msg
);
4216 reply
.SendError(error_msg
);
4219 base::DictionaryValue result_dict
;
4220 result_dict
.SetString("message", base::UTF16ToUTF8(dialog
->message_text()));
4221 reply
.SendSuccess(&result_dict
);
4224 void TestingAutomationProvider::AcceptOrDismissAppModalDialog(
4225 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
4226 AutomationJSONReply
reply(this, reply_message
);
4228 if (!args
->GetBoolean("accept", &accept
)) {
4229 reply
.SendError("Missing or invalid 'accept'");
4233 std::string error_msg
;
4234 JavaScriptAppModalDialog
* dialog
= GetActiveJavaScriptModalDialog(&error_msg
);
4236 reply
.SendError(error_msg
);
4240 std::string prompt_text
;
4241 if (args
->GetString("prompt_text", &prompt_text
))
4242 dialog
->SetOverridePromptText(base::UTF8ToUTF16(prompt_text
));
4243 dialog
->native_dialog()->AcceptAppModalDialog();
4245 dialog
->native_dialog()->CancelAppModalDialog();
4247 reply
.SendSuccess(NULL
);
4250 // Sample JSON input: { "command": "LaunchApp",
4251 // "id": "ahfgeienlihckogmohjhadlkjgocpleb" }
4252 // Sample JSON output: {}
4253 void TestingAutomationProvider::LaunchApp(
4255 base::DictionaryValue
* args
,
4256 IPC::Message
* reply_message
) {
4258 if (!args
->GetString("id", &id
)) {
4259 AutomationJSONReply(this, reply_message
).SendError(
4260 "Must include string id.");
4264 ExtensionService
* service
= extensions::ExtensionSystem::Get(
4265 browser
->profile())->extension_service();
4267 AutomationJSONReply(this, reply_message
).SendError(
4268 "No extensions service.");
4272 const Extension
* extension
= service
->GetExtensionById(
4273 id
, false /* do not include disabled extensions */);
4275 AutomationJSONReply(this, reply_message
).SendError(
4277 "Extension with ID '%s' doesn't exist or is disabled.",
4282 WebContents
* old_contents
=
4283 browser
->tab_strip_model()->GetActiveWebContents();
4284 if (!old_contents
) {
4285 AutomationJSONReply(this, reply_message
).SendError(
4286 "Cannot identify selected tab contents.");
4290 AppLaunchParams
launch_params(profile(), extension
, CURRENT_TAB
);
4291 // This observer will delete itself.
4292 new AppLaunchObserver(&old_contents
->GetController(), this, reply_message
,
4293 launch_params
.container
);
4294 OpenApplication(launch_params
);
4297 // Sample JSON input: { "command": "SetAppLaunchType",
4298 // "id": "ahfgeienlihckogmohjhadlkjgocpleb",
4299 // "launch_type": "pinned" }
4300 // Sample JSON output: {}
4301 void TestingAutomationProvider::SetAppLaunchType(
4303 base::DictionaryValue
* args
,
4304 IPC::Message
* reply_message
) {
4305 AutomationJSONReply
reply(this, reply_message
);
4308 if (!args
->GetString("id", &id
)) {
4309 reply
.SendError("Must include string id.");
4313 std::string launch_type_str
;
4314 if (!args
->GetString("launch_type", &launch_type_str
)) {
4315 reply
.SendError("Must specify app launch type.");
4319 ExtensionService
* service
= extensions::ExtensionSystem::Get(
4320 browser
->profile())->extension_service();
4322 reply
.SendError("No extensions service.");
4326 const Extension
* extension
= service
->GetExtensionById(
4327 id
, true /* include disabled extensions */);
4329 reply
.SendError(base::StringPrintf(
4330 "Extension with ID '%s' doesn't exist.", id
.c_str()));
4334 extensions::LaunchType launch_type
;
4335 if (launch_type_str
== "pinned") {
4336 launch_type
= extensions::LAUNCH_TYPE_PINNED
;
4337 } else if (launch_type_str
== "regular") {
4338 launch_type
= extensions::LAUNCH_TYPE_REGULAR
;
4339 } else if (launch_type_str
== "fullscreen") {
4340 launch_type
= extensions::LAUNCH_TYPE_FULLSCREEN
;
4341 } else if (launch_type_str
== "window") {
4342 launch_type
= extensions::LAUNCH_TYPE_WINDOW
;
4344 reply
.SendError(base::StringPrintf(
4345 "Unexpected launch type '%s'.", launch_type_str
.c_str()));
4349 extensions::SetLaunchType(service
, extension
->id(), launch_type
);
4350 reply
.SendSuccess(NULL
);
4353 // Sample json input: { "command": "GetV8HeapStats",
4355 // Refer to GetV8HeapStats() in chrome/test/pyautolib/pyauto.py for
4356 // sample json output.
4357 void TestingAutomationProvider::GetV8HeapStats(
4359 base::DictionaryValue
* args
,
4360 IPC::Message
* reply_message
) {
4361 WebContents
* web_contents
;
4364 if (!args
->GetInteger("tab_index", &tab_index
)) {
4365 AutomationJSONReply(this, reply_message
).SendError(
4366 "Missing 'tab_index' argument.");
4370 web_contents
= browser
->tab_strip_model()->GetWebContentsAt(tab_index
);
4371 if (!web_contents
) {
4372 AutomationJSONReply(this, reply_message
).SendError(base::StringPrintf(
4373 "Could not get WebContents at tab index %d", tab_index
));
4377 RenderViewHost
* render_view
= web_contents
->GetRenderViewHost();
4379 // This observer will delete itself.
4380 new V8HeapStatsObserver(
4381 this, reply_message
,
4382 base::GetProcId(render_view
->GetProcess()->GetHandle()));
4383 render_view
->Send(new ChromeViewMsg_GetV8HeapStats
);
4386 // Sample json input: { "command": "GetFPS",
4388 // Refer to GetFPS() in chrome/test/pyautolib/pyauto.py for
4389 // sample json output.
4390 void TestingAutomationProvider::GetFPS(
4392 base::DictionaryValue
* args
,
4393 IPC::Message
* reply_message
) {
4394 WebContents
* web_contents
;
4397 if (!args
->GetInteger("tab_index", &tab_index
)) {
4398 AutomationJSONReply(this, reply_message
).SendError(
4399 "Missing 'tab_index' argument.");
4403 web_contents
= browser
->tab_strip_model()->GetWebContentsAt(tab_index
);
4404 if (!web_contents
) {
4405 AutomationJSONReply(this, reply_message
).SendError(base::StringPrintf(
4406 "Could not get WebContents at tab index %d", tab_index
));
4410 RenderViewHost
* render_view
= web_contents
->GetRenderViewHost();
4411 int routing_id
= render_view
->GetRoutingID();
4413 // This observer will delete itself.
4415 this, reply_message
,
4416 base::GetProcId(render_view
->GetProcess()->GetHandle()),
4418 render_view
->Send(new ChromeViewMsg_GetFPS(routing_id
));
4421 void TestingAutomationProvider::IsFullscreenForBrowser(Browser
* browser
,
4422 base::DictionaryValue
* args
,
4423 IPC::Message
* reply_message
) {
4424 base::DictionaryValue dict
;
4425 dict
.SetBoolean("result",
4426 browser
->fullscreen_controller()->IsFullscreenForBrowser());
4427 AutomationJSONReply(this, reply_message
).SendSuccess(&dict
);
4430 void TestingAutomationProvider::IsFullscreenForTab(Browser
* browser
,
4431 base::DictionaryValue
* args
,
4432 IPC::Message
* reply_message
) {
4433 base::DictionaryValue dict
;
4434 dict
.SetBoolean("result",
4435 browser
->fullscreen_controller()->IsFullscreenForTabOrPending());
4436 AutomationJSONReply(this, reply_message
).SendSuccess(&dict
);
4439 void TestingAutomationProvider::IsMouseLocked(Browser
* browser
,
4440 base::DictionaryValue
* args
,
4441 IPC::Message
* reply_message
) {
4442 base::DictionaryValue dict
;
4443 dict
.SetBoolean("result", browser
->tab_strip_model()->GetActiveWebContents()->
4444 GetRenderViewHost()->GetView()->IsMouseLocked());
4445 AutomationJSONReply(this, reply_message
).SendSuccess(&dict
);
4448 void TestingAutomationProvider::IsMouseLockPermissionRequested(
4450 base::DictionaryValue
* args
,
4451 IPC::Message
* reply_message
) {
4452 FullscreenExitBubbleType type
=
4453 browser
->fullscreen_controller()->GetFullscreenExitBubbleType();
4454 bool mouse_lock
= false;
4455 fullscreen_bubble::PermissionRequestedByType(type
, NULL
, &mouse_lock
);
4456 base::DictionaryValue dict
;
4457 dict
.SetBoolean("result", mouse_lock
);
4458 AutomationJSONReply(this, reply_message
).SendSuccess(&dict
);
4461 void TestingAutomationProvider::IsFullscreenPermissionRequested(
4463 base::DictionaryValue
* args
,
4464 IPC::Message
* reply_message
) {
4465 FullscreenExitBubbleType type
=
4466 browser
->fullscreen_controller()->GetFullscreenExitBubbleType();
4467 bool fullscreen
= false;
4468 fullscreen_bubble::PermissionRequestedByType(type
, &fullscreen
, NULL
);
4469 base::DictionaryValue dict
;
4470 dict
.SetBoolean("result", fullscreen
);
4471 AutomationJSONReply(this, reply_message
).SendSuccess(&dict
);
4474 void TestingAutomationProvider::IsFullscreenBubbleDisplayed(Browser
* browser
,
4475 base::DictionaryValue
* args
,
4476 IPC::Message
* reply_message
) {
4477 FullscreenExitBubbleType type
=
4478 browser
->fullscreen_controller()->GetFullscreenExitBubbleType();
4479 base::DictionaryValue dict
;
4480 dict
.SetBoolean("result",
4481 type
!= FEB_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION
);
4482 AutomationJSONReply(this, reply_message
).SendSuccess(&dict
);
4485 void TestingAutomationProvider::IsFullscreenBubbleDisplayingButtons(
4487 base::DictionaryValue
* args
,
4488 IPC::Message
* reply_message
) {
4489 FullscreenExitBubbleType type
=
4490 browser
->fullscreen_controller()->GetFullscreenExitBubbleType();
4491 base::DictionaryValue dict
;
4492 dict
.SetBoolean("result", fullscreen_bubble::ShowButtonsForType(type
));
4493 AutomationJSONReply(this, reply_message
).SendSuccess(&dict
);
4496 void TestingAutomationProvider::AcceptCurrentFullscreenOrMouseLockRequest(
4498 base::DictionaryValue
* args
,
4499 IPC::Message
* reply_message
) {
4500 browser
->fullscreen_controller()->OnAcceptFullscreenPermission();
4501 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
4504 void TestingAutomationProvider::DenyCurrentFullscreenOrMouseLockRequest(
4506 base::DictionaryValue
* args
,
4507 IPC::Message
* reply_message
) {
4508 browser
->fullscreen_controller()->OnDenyFullscreenPermission();
4509 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
4512 void TestingAutomationProvider::WaitForTabToBeRestored(
4513 base::DictionaryValue
* args
,
4514 IPC::Message
* reply_message
) {
4515 WebContents
* web_contents
;
4517 if (!GetTabFromJSONArgs(args
, &web_contents
, &error
)) {
4518 AutomationJSONReply(this, reply_message
).SendError(error
);
4521 NavigationController
& controller
= web_contents
->GetController();
4522 new NavigationControllerRestoredObserver(this, &controller
, reply_message
);
4525 void TestingAutomationProvider::RefreshPolicies(
4526 base::DictionaryValue
* args
,
4527 IPC::Message
* reply_message
) {
4528 #if !defined(ENABLE_CONFIGURATION_POLICY)
4529 AutomationJSONReply(this, reply_message
).SendError(
4530 "Configuration Policy disabled");
4532 // Some policies (e.g. URLBlacklist) post tasks to other message loops
4533 // before they start enforcing updated policy values; make sure those tasks
4534 // have finished after a policy update.
4535 // Updates of the URLBlacklist are done on IO, after building the blacklist
4536 // on FILE, which is initiated from IO.
4537 base::Closure reply
=
4538 base::Bind(SendSuccessReply
, AsWeakPtr(), reply_message
);
4539 g_browser_process
->policy_service()->RefreshPolicies(
4540 base::Bind(PostTask
, BrowserThread::IO
,
4541 base::Bind(PostTask
, BrowserThread::FILE,
4542 base::Bind(PostTask
, BrowserThread::IO
,
4543 base::Bind(PostTask
, BrowserThread::UI
, reply
)))));
4547 static int AccessArray(const volatile int arr
[], const volatile int *index
) {
4551 void TestingAutomationProvider::SimulateAsanMemoryBug(
4552 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
4553 // This array is volatile not to let compiler optimize us out.
4554 volatile int testarray
[3] = {0, 0, 0};
4556 // Send the reply while we can.
4557 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
4559 // Cause Address Sanitizer to abort this process.
4560 volatile int index
= 5;
4561 AccessArray(testarray
, &index
);
4564 void TestingAutomationProvider::GetIndicesFromTab(
4565 base::DictionaryValue
* args
,
4566 IPC::Message
* reply_message
) {
4567 AutomationJSONReply
reply(this, reply_message
);
4568 int id_or_handle
= 0;
4569 bool has_id
= args
->HasKey("tab_id");
4570 bool has_handle
= args
->HasKey("tab_handle");
4571 if (has_id
&& has_handle
) {
4573 "Both 'tab_id' and 'tab_handle' were specified. Only one is allowed");
4575 } else if (!has_id
&& !has_handle
) {
4576 reply
.SendError("Either 'tab_id' or 'tab_handle' must be specified");
4579 if (has_id
&& !args
->GetInteger("tab_id", &id_or_handle
)) {
4580 reply
.SendError("'tab_id' is invalid");
4583 if (has_handle
&& (!args
->GetInteger("tab_handle", &id_or_handle
) ||
4584 !tab_tracker_
->ContainsHandle(id_or_handle
))) {
4585 reply
.SendError("'tab_handle' is invalid");
4588 int id
= id_or_handle
;
4590 SessionTabHelper
* session_tab_helper
=
4591 SessionTabHelper::FromWebContents(
4592 tab_tracker_
->GetResource(id_or_handle
)->GetWebContents());
4593 id
= session_tab_helper
->session_id().id();
4595 chrome::BrowserIterator it
;
4596 int browser_index
= 0;
4597 for (; !it
.done(); it
.Next(), ++browser_index
) {
4598 Browser
* browser
= *it
;
4599 for (int tab_index
= 0;
4600 tab_index
< browser
->tab_strip_model()->count();
4603 browser
->tab_strip_model()->GetWebContentsAt(tab_index
);
4604 SessionTabHelper
* session_tab_helper
=
4605 SessionTabHelper::FromWebContents(tab
);
4606 if (session_tab_helper
->session_id().id() == id
) {
4607 base::DictionaryValue dict
;
4608 dict
.SetInteger("windex", browser_index
);
4609 dict
.SetInteger("tab_index", tab_index
);
4610 reply
.SendSuccess(&dict
);
4615 reply
.SendError("Could not find tab among current browser windows");
4618 void TestingAutomationProvider::NavigateToURL(
4619 base::DictionaryValue
* args
,
4620 IPC::Message
* reply_message
) {
4621 if (SendErrorIfModalDialogActive(this, reply_message
))
4624 int navigation_count
;
4625 std::string url
, error
;
4627 WebContents
* web_contents
;
4628 if (!GetBrowserAndTabFromJSONArgs(args
, &browser
, &web_contents
, &error
)) {
4629 AutomationJSONReply(this, reply_message
).SendError(error
);
4632 if (!args
->GetString("url", &url
)) {
4633 AutomationJSONReply(this, reply_message
)
4634 .SendError("'url' missing or invalid");
4637 if (!args
->GetInteger("navigation_count", &navigation_count
)) {
4638 AutomationJSONReply(this, reply_message
)
4639 .SendError("'navigation_count' missing or invalid");
4642 if (navigation_count
> 0) {
4643 new NavigationNotificationObserver(
4644 &web_contents
->GetController(), this, reply_message
,
4645 navigation_count
, false, true);
4647 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
4649 OpenURLParams
params(
4650 GURL(url
), content::Referrer(), CURRENT_TAB
,
4651 content::PageTransitionFromInt(
4652 content::PAGE_TRANSITION_TYPED
|
4653 content::PAGE_TRANSITION_FROM_ADDRESS_BAR
),
4655 browser
->OpenURLFromTab(web_contents
, params
);
4658 void TestingAutomationProvider::GetActiveTabIndexJSON(
4659 base::DictionaryValue
* args
,
4660 IPC::Message
* reply_message
) {
4661 AutomationJSONReply
reply(this, reply_message
);
4663 std::string error_msg
;
4664 if (!GetBrowserFromJSONArgs(args
, &browser
, &error_msg
)) {
4665 reply
.SendError(error_msg
);
4668 int tab_index
= browser
->tab_strip_model()->active_index();
4669 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
4670 return_value
->SetInteger("tab_index", tab_index
);
4671 reply
.SendSuccess(return_value
.get());
4674 void TestingAutomationProvider::AppendTabJSON(base::DictionaryValue
* args
,
4675 IPC::Message
* reply_message
) {
4676 TabAppendedNotificationObserver
* observer
= NULL
;
4677 int append_tab_response
= -1;
4679 std::string error_msg
, url
;
4680 if (!GetBrowserFromJSONArgs(args
, &browser
, &error_msg
)) {
4681 AutomationJSONReply(this, reply_message
).SendError(error_msg
);
4684 if (!args
->GetString("url", &url
)) {
4685 AutomationJSONReply(this, reply_message
)
4686 .SendError("'url' missing or invalid");
4689 observer
= new TabAppendedNotificationObserver(browser
, this, reply_message
,
4691 WebContents
* contents
=
4692 chrome::AddSelectedTabWithURL(browser
, GURL(url
),
4693 content::PAGE_TRANSITION_TYPED
);
4695 append_tab_response
= GetIndexForNavigationController(
4696 &contents
->GetController(), browser
);
4699 if (!contents
|| append_tab_response
< 0) {
4701 observer
->ReleaseReply();
4704 AutomationJSONReply(this, reply_message
).SendError("Failed to append tab.");
4708 void TestingAutomationProvider::WaitUntilNavigationCompletes(
4709 base::DictionaryValue
* args
,
4710 IPC::Message
* reply_message
) {
4711 if (SendErrorIfModalDialogActive(this, reply_message
))
4716 WebContents
* web_contents
;
4717 if (!GetBrowserAndTabFromJSONArgs(args
, &browser
, &web_contents
, &error
)) {
4718 AutomationJSONReply(this, reply_message
).SendError(error
);
4721 NavigationNotificationObserver
* observer
=
4722 new NavigationNotificationObserver(&web_contents
->GetController(), this,
4723 reply_message
, 1, true, true);
4724 if (!web_contents
->IsLoading()) {
4725 observer
->ConditionMet(AUTOMATION_MSG_NAVIGATION_SUCCESS
);
4730 void TestingAutomationProvider::ExecuteJavascriptJSON(
4731 base::DictionaryValue
* args
,
4732 IPC::Message
* reply_message
) {
4733 if (SendErrorIfModalDialogActive(this, reply_message
))
4736 base::string16 frame_xpath
, javascript
;
4738 RenderViewHost
* render_view
;
4739 if (!GetRenderViewFromJSONArgs(args
, profile(), &render_view
, &error
)) {
4740 AutomationJSONReply(this, reply_message
).SendError(error
);
4743 if (!args
->GetString("frame_xpath", &frame_xpath
)) {
4744 AutomationJSONReply(this, reply_message
)
4745 .SendError("'frame_xpath' missing or invalid");
4748 if (!args
->GetString("javascript", &javascript
)) {
4749 AutomationJSONReply(this, reply_message
)
4750 .SendError("'javascript' missing or invalid");
4754 new DomOperationMessageSender(this, reply_message
, true);
4755 ExecuteJavascriptInRenderViewFrame(frame_xpath
, javascript
, reply_message
,
4759 void TestingAutomationProvider::ExecuteJavascriptInRenderView(
4760 base::DictionaryValue
* args
,
4761 IPC::Message
* reply_message
) {
4762 base::string16 frame_xpath
, javascript
, extension_id
, url_text
;
4763 int render_process_id
, render_view_id
;
4764 if (!args
->GetString("frame_xpath", &frame_xpath
)) {
4765 AutomationJSONReply(this, reply_message
)
4766 .SendError("'frame_xpath' missing or invalid");
4769 if (!args
->GetString("javascript", &javascript
)) {
4770 AutomationJSONReply(this, reply_message
)
4771 .SendError("'javascript' missing or invalid");
4774 if (!args
->GetInteger("view.render_process_id", &render_process_id
)) {
4775 AutomationJSONReply(this, reply_message
)
4776 .SendError("'view.render_process_id' missing or invalid");
4779 if (!args
->GetInteger("view.render_view_id", &render_view_id
)) {
4780 AutomationJSONReply(this, reply_message
)
4781 .SendError("'view.render_view_id' missing or invalid");
4785 RenderViewHost
* rvh
= RenderViewHost::FromID(render_process_id
,
4788 AutomationJSONReply(this, reply_message
).SendError(
4789 "A RenderViewHost object was not found with the given view ID.");
4793 new DomOperationMessageSender(this, reply_message
, true);
4794 ExecuteJavascriptInRenderViewFrame(frame_xpath
, javascript
, reply_message
,
4798 void TestingAutomationProvider::AddDomEventObserver(
4799 base::DictionaryValue
* args
,
4800 IPC::Message
* reply_message
) {
4801 if (SendErrorIfModalDialogActive(this, reply_message
))
4804 AutomationJSONReply
reply(this, reply_message
);
4805 std::string event_name
;
4808 if (!args
->GetString("event_name", &event_name
)) {
4809 reply
.SendError("'event_name' missing or invalid");
4812 if (!args
->GetInteger("automation_id", &automation_id
)) {
4813 reply
.SendError("'automation_id' missing or invalid");
4816 if (!args
->GetBoolean("recurring", &recurring
)) {
4817 reply
.SendError("'recurring' missing or invalid");
4821 if (!automation_event_queue_
.get())
4822 automation_event_queue_
.reset(new AutomationEventQueue
);
4824 int observer_id
= automation_event_queue_
->AddObserver(
4825 new DomEventObserver(automation_event_queue_
.get(), event_name
,
4826 automation_id
, recurring
));
4827 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
4828 return_value
->SetInteger("observer_id", observer_id
);
4829 reply
.SendSuccess(return_value
.get());
4832 void TestingAutomationProvider::RemoveEventObserver(
4833 base::DictionaryValue
* args
,
4834 IPC::Message
* reply_message
) {
4835 AutomationJSONReply
reply(this, reply_message
);
4837 if (!args
->GetInteger("observer_id", &observer_id
) ||
4838 !automation_event_queue_
.get()) {
4839 reply
.SendError("'observer_id' missing or invalid");
4842 if (automation_event_queue_
->RemoveObserver(observer_id
)) {
4843 reply
.SendSuccess(NULL
);
4846 reply
.SendError("Invalid observer id.");
4849 void TestingAutomationProvider::ClearEventQueue(
4850 base::DictionaryValue
* args
,
4851 IPC::Message
* reply_message
) {
4852 automation_event_queue_
.reset();
4853 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
4856 void TestingAutomationProvider::GetNextEvent(
4857 base::DictionaryValue
* args
,
4858 IPC::Message
* reply_message
) {
4859 scoped_ptr
<AutomationJSONReply
> reply(
4860 new AutomationJSONReply(this, reply_message
));
4863 if (!args
->GetInteger("observer_id", &observer_id
)) {
4864 reply
->SendError("'observer_id' missing or invalid");
4867 if (!args
->GetBoolean("blocking", &blocking
)) {
4868 reply
->SendError("'blocking' missing or invalid");
4871 if (!automation_event_queue_
.get()) {
4873 "No observers are attached to the queue. Did you create any?");
4877 // The reply will be freed once a matching event is added to the queue.
4878 automation_event_queue_
->GetNextEvent(reply
.release(), observer_id
, blocking
);
4881 void TestingAutomationProvider::GoForward(
4882 base::DictionaryValue
* args
,
4883 IPC::Message
* reply_message
) {
4884 if (SendErrorIfModalDialogActive(this, reply_message
))
4887 WebContents
* web_contents
;
4889 if (!GetTabFromJSONArgs(args
, &web_contents
, &error
)) {
4890 AutomationJSONReply(this, reply_message
).SendError(error
);
4893 NavigationController
& controller
= web_contents
->GetController();
4894 if (!controller
.CanGoForward()) {
4895 base::DictionaryValue dict
;
4896 dict
.SetBoolean("did_go_forward", false);
4897 AutomationJSONReply(this, reply_message
).SendSuccess(&dict
);
4900 new NavigationNotificationObserver(&controller
, this, reply_message
,
4902 controller
.GoForward();
4905 void TestingAutomationProvider::ExecuteBrowserCommandAsyncJSON(
4906 base::DictionaryValue
* args
,
4907 IPC::Message
* reply_message
) {
4908 AutomationJSONReply
reply(this, reply_message
);
4912 if (!GetBrowserFromJSONArgs(args
, &browser
, &error
)) {
4913 reply
.SendError(error
);
4916 if (!args
->GetInteger("accelerator", &command
)) {
4917 reply
.SendError("'accelerator' missing or invalid.");
4920 if (!chrome::SupportsCommand(browser
, command
)) {
4921 reply
.SendError(base::StringPrintf("Browser does not support command=%d.",
4925 if (!chrome::IsCommandEnabled(browser
, command
)) {
4926 reply
.SendError(base::StringPrintf(
4927 "Browser command=%d not enabled.", command
));
4930 chrome::ExecuteCommand(browser
, command
);
4931 reply
.SendSuccess(NULL
);
4934 void TestingAutomationProvider::ExecuteBrowserCommandJSON(
4935 base::DictionaryValue
* args
,
4936 IPC::Message
* reply_message
) {
4940 if (!GetBrowserFromJSONArgs(args
, &browser
, &error
)) {
4941 AutomationJSONReply(this, reply_message
).SendError(error
);
4944 if (!args
->GetInteger("accelerator", &command
)) {
4945 AutomationJSONReply(this, reply_message
).SendError(
4946 "'accelerator' missing or invalid.");
4949 if (!chrome::SupportsCommand(browser
, command
)) {
4950 AutomationJSONReply(this, reply_message
).SendError(
4951 base::StringPrintf("Browser does not support command=%d.", command
));
4954 if (!chrome::IsCommandEnabled(browser
, command
)) {
4955 AutomationJSONReply(this, reply_message
).SendError(
4956 base::StringPrintf("Browser command=%d not enabled.", command
));
4959 // First check if we can handle the command without using an observer.
4960 for (size_t i
= 0; i
< arraysize(kSynchronousCommands
); i
++) {
4961 if (command
== kSynchronousCommands
[i
]) {
4962 chrome::ExecuteCommand(browser
, command
);
4963 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
4967 // Use an observer if we have one, otherwise fail.
4968 if (ExecuteBrowserCommandObserver::CreateAndRegisterObserver(
4969 this, browser
, command
, reply_message
, true)) {
4970 chrome::ExecuteCommand(browser
, command
);
4973 AutomationJSONReply(this, reply_message
).SendError(base::StringPrintf(
4974 "Unable to register observer for browser command=%d.", command
));
4977 void TestingAutomationProvider::IsMenuCommandEnabledJSON(
4978 base::DictionaryValue
* args
,
4979 IPC::Message
* reply_message
) {
4983 if (!GetBrowserFromJSONArgs(args
, &browser
, &error
)) {
4984 AutomationJSONReply(this, reply_message
).SendError(error
);
4987 if (!args
->GetInteger("accelerator", &command
)) {
4988 AutomationJSONReply(this, reply_message
).SendError(
4989 "'accelerator' missing or invalid.");
4992 base::DictionaryValue dict
;
4993 dict
.SetBoolean("enabled", chrome::IsCommandEnabled(browser
, command
));
4994 AutomationJSONReply(this, reply_message
).SendSuccess(&dict
);
4997 void TestingAutomationProvider::GetTabInfo(
4998 base::DictionaryValue
* args
,
4999 IPC::Message
* reply_message
) {
5000 AutomationJSONReply
reply(this, reply_message
);
5004 if (GetBrowserAndTabFromJSONArgs(args
, &browser
, &tab
, &error
)) {
5005 NavigationEntry
* entry
= tab
->GetController().GetActiveEntry();
5007 reply
.SendError("Unable to get active navigation entry");
5010 base::DictionaryValue dict
;
5011 dict
.SetString("title", entry
->GetTitleForDisplay(std::string()));
5012 dict
.SetString("url", entry
->GetVirtualURL().spec());
5013 reply
.SendSuccess(&dict
);
5015 reply
.SendError(error
);
5019 void TestingAutomationProvider::GetTabCountJSON(
5020 base::DictionaryValue
* args
,
5021 IPC::Message
* reply_message
) {
5022 AutomationJSONReply
reply(this, reply_message
);
5025 if (!GetBrowserFromJSONArgs(args
, &browser
, &error
)) {
5026 reply
.SendError(error
);
5029 base::DictionaryValue dict
;
5030 dict
.SetInteger("tab_count", browser
->tab_strip_model()->count());
5031 reply
.SendSuccess(&dict
);
5034 void TestingAutomationProvider::GoBack(
5035 base::DictionaryValue
* args
,
5036 IPC::Message
* reply_message
) {
5037 if (SendErrorIfModalDialogActive(this, reply_message
))
5040 WebContents
* web_contents
;
5042 if (!GetTabFromJSONArgs(args
, &web_contents
, &error
)) {
5043 AutomationJSONReply(this, reply_message
).SendError(error
);
5046 NavigationController
& controller
= web_contents
->GetController();
5047 if (!controller
.CanGoBack()) {
5048 base::DictionaryValue dict
;
5049 dict
.SetBoolean("did_go_back", false);
5050 AutomationJSONReply(this, reply_message
).SendSuccess(&dict
);
5053 new NavigationNotificationObserver(&controller
, this, reply_message
,
5055 controller
.GoBack();
5058 void TestingAutomationProvider::ReloadJSON(
5059 base::DictionaryValue
* args
,
5060 IPC::Message
* reply_message
) {
5061 if (SendErrorIfModalDialogActive(this, reply_message
))
5064 WebContents
* web_contents
;
5066 if (!GetTabFromJSONArgs(args
, &web_contents
, &error
)) {
5067 AutomationJSONReply(this, reply_message
).SendError(error
);
5070 NavigationController
& controller
= web_contents
->GetController();
5071 new NavigationNotificationObserver(&controller
, this, reply_message
,
5073 controller
.Reload(false);
5076 void TestingAutomationProvider::GetCookiesJSON(
5077 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
5078 automation_util::GetCookiesJSON(this, args
, reply_message
);
5081 void TestingAutomationProvider::DeleteCookieJSON(
5082 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
5083 automation_util::DeleteCookieJSON(this, args
, reply_message
);
5086 void TestingAutomationProvider::SetCookieJSON(
5087 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
5088 automation_util::SetCookieJSON(this, args
, reply_message
);
5091 void TestingAutomationProvider::GetCookiesInBrowserContext(
5092 base::DictionaryValue
* args
,
5093 IPC::Message
* reply_message
) {
5094 AutomationJSONReply
reply(this, reply_message
);
5095 WebContents
* web_contents
;
5096 std::string value
, url_string
;
5097 int windex
, value_size
;
5098 if (!args
->GetInteger("windex", &windex
)) {
5099 reply
.SendError("'windex' missing or invalid.");
5102 web_contents
= automation_util::GetWebContentsAt(windex
, 0);
5103 if (!web_contents
) {
5104 reply
.SendError("'windex' does not refer to a browser window.");
5107 if (!args
->GetString("url", &url_string
)) {
5108 reply
.SendError("'url' missing or invalid.");
5111 GURL
url(url_string
);
5112 if (!url
.is_valid()) {
5113 reply
.SendError("Invalid url.");
5116 automation_util::GetCookies(url
, web_contents
, &value_size
, &value
);
5117 if (value_size
== -1) {
5119 base::StringPrintf("Unable to retrieve cookies for url=%s.",
5120 url_string
.c_str()));
5123 base::DictionaryValue dict
;
5124 dict
.SetString("cookies", value
);
5125 reply
.SendSuccess(&dict
);
5128 void TestingAutomationProvider::DeleteCookieInBrowserContext(
5129 base::DictionaryValue
* args
,
5130 IPC::Message
* reply_message
) {
5131 AutomationJSONReply
reply(this, reply_message
);
5132 WebContents
* web_contents
;
5133 std::string cookie_name
, url_string
;
5135 bool success
= false;
5136 if (!args
->GetInteger("windex", &windex
)) {
5137 reply
.SendError("'windex' missing or invalid.");
5140 web_contents
= automation_util::GetWebContentsAt(windex
, 0);
5141 if (!web_contents
) {
5142 reply
.SendError("'windex' does not refer to a browser window.");
5145 if (!args
->GetString("cookie_name", &cookie_name
)) {
5146 reply
.SendError("'cookie_name' missing or invalid.");
5149 if (!args
->GetString("url", &url_string
)) {
5150 reply
.SendError("'url' missing or invalid.");
5153 GURL
url(url_string
);
5154 if (!url
.is_valid()) {
5155 reply
.SendError("Invalid url.");
5158 automation_util::DeleteCookie(url
, cookie_name
, web_contents
, &success
);
5161 base::StringPrintf("Failed to delete cookie with name=%s for url=%s.",
5162 cookie_name
.c_str(), url_string
.c_str()));
5165 reply
.SendSuccess(NULL
);
5168 void TestingAutomationProvider::SetCookieInBrowserContext(
5169 base::DictionaryValue
* args
,
5170 IPC::Message
* reply_message
) {
5171 AutomationJSONReply
reply(this, reply_message
);
5172 WebContents
* web_contents
;
5173 std::string value
, url_string
;
5174 int windex
, response_value
= -1;
5175 if (!args
->GetInteger("windex", &windex
)) {
5176 reply
.SendError("'windex' missing or invalid.");
5179 web_contents
= automation_util::GetWebContentsAt(windex
, 0);
5180 if (!web_contents
) {
5181 reply
.SendError("'windex' does not refer to a browser window.");
5184 if (!args
->GetString("value", &value
)) {
5185 reply
.SendError("'value' missing or invalid.");
5188 if (!args
->GetString("url", &url_string
)) {
5189 reply
.SendError("'url' missing or invalid.");
5192 GURL
url(url_string
);
5193 if (!url
.is_valid()) {
5194 reply
.SendError("Invalid url.");
5197 automation_util::SetCookie(url
, value
, web_contents
, &response_value
);
5198 if (response_value
!= 1) {
5199 reply
.SendError(base::StringPrintf(
5200 "Unable set cookie for url=%s.", url_string
.c_str()));
5203 reply
.SendSuccess(NULL
);
5206 void TestingAutomationProvider::GetTabIds(
5207 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
5208 base::ListValue
* id_list
= new base::ListValue();
5209 for (chrome::BrowserIterator it
; !it
.done(); it
.Next()) {
5210 Browser
* browser
= *it
;
5211 for (int i
= 0; i
< browser
->tab_strip_model()->count(); ++i
) {
5212 int id
= SessionTabHelper::FromWebContents(
5213 browser
->tab_strip_model()->GetWebContentsAt(i
))->session_id().id();
5214 id_list
->Append(base::Value::CreateIntegerValue(id
));
5217 base::DictionaryValue dict
;
5218 dict
.Set("ids", id_list
);
5219 AutomationJSONReply(this, reply_message
).SendSuccess(&dict
);
5222 void TestingAutomationProvider::IsTabIdValid(
5223 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
5224 AutomationJSONReply
reply(this, reply_message
);
5226 if (!args
->GetInteger("id", &id
)) {
5227 reply
.SendError("'id' missing or invalid");
5230 bool is_valid
= false;
5231 for (chrome::BrowserIterator it
; !it
.done(); it
.Next()) {
5232 Browser
* browser
= *it
;
5233 for (int i
= 0; i
< browser
->tab_strip_model()->count(); ++i
) {
5234 WebContents
* tab
= browser
->tab_strip_model()->GetWebContentsAt(i
);
5235 SessionTabHelper
* session_tab_helper
=
5236 SessionTabHelper::FromWebContents(tab
);
5237 if (session_tab_helper
->session_id().id() == id
) {
5243 base::DictionaryValue dict
;
5244 dict
.SetBoolean("is_valid", is_valid
);
5245 reply
.SendSuccess(&dict
);
5248 void TestingAutomationProvider::CloseTabJSON(
5249 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
5253 bool wait_until_closed
= false; // ChromeDriver does not use this.
5254 args
->GetBoolean("wait_until_closed", &wait_until_closed
);
5255 // Close tabs synchronously.
5256 if (GetBrowserAndTabFromJSONArgs(args
, &browser
, &tab
, &error
)) {
5257 if (wait_until_closed
) {
5258 new TabClosedNotificationObserver(this, wait_until_closed
, reply_message
,
5261 chrome::CloseWebContents(browser
, tab
, false);
5262 if (!wait_until_closed
)
5263 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
5266 // Close other types of views asynchronously.
5267 RenderViewHost
* view
;
5268 if (!GetRenderViewFromJSONArgs(args
, profile(), &view
, &error
)) {
5269 AutomationJSONReply(this, reply_message
).SendError(error
);
5273 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
5276 void TestingAutomationProvider::SetViewBounds(
5277 base::DictionaryValue
* args
,
5278 IPC::Message
* reply_message
) {
5279 AutomationJSONReply
reply(this, reply_message
);
5280 int x
, y
, width
, height
;
5281 if (!args
->GetInteger("bounds.x", &x
) ||
5282 !args
->GetInteger("bounds.y", &y
) ||
5283 !args
->GetInteger("bounds.width", &width
) ||
5284 !args
->GetInteger("bounds.height", &height
)) {
5285 reply
.SendError("Missing or invalid 'bounds'");
5290 if (!GetBrowserFromJSONArgs(args
, &browser
, &error
)) {
5291 reply
.SendError(error
);
5294 BrowserWindow
* browser_window
= browser
->window();
5295 if (browser_window
->IsMaximized()) {
5296 browser_window
->Restore();
5298 browser_window
->SetBounds(gfx::Rect(x
, y
, width
, height
));
5299 reply
.SendSuccess(NULL
);
5302 void TestingAutomationProvider::MaximizeView(
5303 base::DictionaryValue
* args
,
5304 IPC::Message
* reply_message
) {
5307 if (!GetBrowserFromJSONArgs(args
, &browser
, &error
)) {
5308 AutomationJSONReply(this, reply_message
).SendError(error
);
5312 #if defined(OS_LINUX)
5313 // Maximization on Linux is asynchronous, so create an observer object to be
5314 // notified upon maximization completion.
5315 new WindowMaximizedObserver(this, reply_message
);
5316 #endif // defined(OS_LINUX)
5318 browser
->window()->Maximize();
5320 #if !defined(OS_LINUX)
5321 // Send success reply right away for OS's with synchronous maximize command.
5322 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
5323 #endif // !defined(OS_LINUX)
5326 void TestingAutomationProvider::ActivateTabJSON(
5327 base::DictionaryValue
* args
,
5328 IPC::Message
* reply_message
) {
5329 if (SendErrorIfModalDialogActive(this, reply_message
))
5332 AutomationJSONReply
reply(this, reply_message
);
5334 WebContents
* web_contents
;
5336 if (!GetBrowserAndTabFromJSONArgs(args
, &browser
, &web_contents
, &error
)) {
5337 reply
.SendError(error
);
5340 TabStripModel
* tab_strip
= browser
->tab_strip_model();
5341 tab_strip
->ActivateTabAt(tab_strip
->GetIndexOfWebContents(web_contents
),
5343 reply
.SendSuccess(NULL
);
5346 void TestingAutomationProvider::IsPageActionVisible(
5347 base::DictionaryValue
* args
,
5348 IPC::Message
* reply_message
) {
5349 AutomationJSONReply
reply(this, reply_message
);
5353 if (!GetTabFromJSONArgs(args
, &tab
, &error
)) {
5354 reply
.SendError(error
);
5357 Browser
* browser
= automation_util::GetBrowserForTab(tab
);
5359 reply
.SendError("Tab does not belong to an open browser");
5362 const Extension
* extension
;
5363 if (!GetEnabledExtensionFromJSONArgs(
5364 args
, "extension_id", browser
->profile(), &extension
, &error
)) {
5365 reply
.SendError(error
);
5368 ExtensionAction
* page_action
=
5369 ExtensionActionManager::Get(browser
->profile())->
5370 GetPageAction(*extension
);
5372 reply
.SendError("Extension doesn't have any page action");
5375 EnsureTabSelected(browser
, tab
);
5377 bool is_visible
= false;
5378 LocationBarTesting
* loc_bar
=
5379 browser
->window()->GetLocationBar()->GetLocationBarForTesting();
5380 size_t page_action_visible_count
=
5381 static_cast<size_t>(loc_bar
->PageActionVisibleCount());
5382 for (size_t i
= 0; i
< page_action_visible_count
; ++i
) {
5383 if (loc_bar
->GetVisiblePageAction(i
) == page_action
) {
5388 base::DictionaryValue dict
;
5389 dict
.SetBoolean("is_visible", is_visible
);
5390 reply
.SendSuccess(&dict
);
5393 void TestingAutomationProvider::CreateNewAutomationProvider(
5394 base::DictionaryValue
* args
,
5395 IPC::Message
* reply_message
) {
5396 AutomationJSONReply
reply(this, reply_message
);
5397 std::string channel_id
;
5398 if (!args
->GetString("channel_id", &channel_id
)) {
5399 reply
.SendError("'channel_id' missing or invalid");
5403 AutomationProvider
* provider
= new TestingAutomationProvider(profile_
);
5404 provider
->DisableInitialLoadObservers();
5405 // TODO(kkania): Remove this when crbug.com/91311 is fixed.
5406 // Named server channels should ideally be created and closed on the file
5407 // thread, within the IPC channel code.
5408 base::ThreadRestrictions::ScopedAllowIO allow_io
;
5409 if (!provider
->InitializeChannel(
5410 automation::kNamedInterfacePrefix
+ channel_id
)) {
5411 reply
.SendError("Failed to initialize channel: " + channel_id
);
5414 DCHECK(g_browser_process
);
5415 g_browser_process
->GetAutomationProviderList()->AddProvider(provider
);
5416 reply
.SendSuccess(NULL
);
5419 void TestingAutomationProvider::WaitForTabCountToBecome(
5421 int target_tab_count
,
5422 IPC::Message
* reply_message
) {
5423 if (!browser_tracker_
->ContainsHandle(browser_handle
)) {
5424 AutomationMsg_WaitForTabCountToBecome::WriteReplyParams(reply_message
,
5426 Send(reply_message
);
5430 Browser
* browser
= browser_tracker_
->GetResource(browser_handle
);
5432 // The observer will delete itself.
5433 new TabCountChangeObserver(this, browser
, reply_message
, target_tab_count
);
5436 void TestingAutomationProvider::WaitForInfoBarCount(
5438 size_t target_count
,
5439 IPC::Message
* reply_message
) {
5440 if (!tab_tracker_
->ContainsHandle(tab_handle
)) {
5441 AutomationMsg_WaitForInfoBarCount::WriteReplyParams(reply_message_
, false);
5442 Send(reply_message_
);
5446 NavigationController
* controller
= tab_tracker_
->GetResource(tab_handle
);
5448 AutomationMsg_WaitForInfoBarCount::WriteReplyParams(reply_message_
, false);
5449 Send(reply_message_
);
5453 // The delegate will delete itself.
5454 new InfoBarCountObserver(this, reply_message
,
5455 controller
->GetWebContents(), target_count
);
5458 void TestingAutomationProvider::WaitForProcessLauncherThreadToGoIdle(
5459 IPC::Message
* reply_message
) {
5460 new WaitForProcessLauncherThreadToGoIdleObserver(this, reply_message
);
5463 void TestingAutomationProvider::OnRemoveProvider() {
5464 if (g_browser_process
)
5465 g_browser_process
->GetAutomationProviderList()->RemoveProvider(this);
5468 void TestingAutomationProvider::EnsureTabSelected(Browser
* browser
,
5470 TabStripModel
* tab_strip
= browser
->tab_strip_model();
5471 if (tab_strip
->GetActiveWebContents() != tab
)
5472 tab_strip
->ActivateTabAt(tab_strip
->GetIndexOfWebContents(tab
), true);