• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/automation/testing_automation_provider.h"
6 
7 #include <map>
8 #include <set>
9 #include <string>
10 #include <vector>
11 
12 #include "base/command_line.h"
13 #include "base/file_path.h"
14 #include "base/json/json_reader.h"
15 #include "base/json/json_writer.h"
16 #include "base/json/string_escape.h"
17 #include "base/path_service.h"
18 #include "base/process.h"
19 #include "base/process_util.h"
20 #include "base/stringprintf.h"
21 #include "base/threading/thread_restrictions.h"
22 #include "base/time.h"
23 #include "base/utf_string_conversions.h"
24 #include "chrome/app/chrome_command_ids.h"
25 #include "chrome/browser/autocomplete/autocomplete.h"
26 #include "chrome/browser/autocomplete/autocomplete_edit.h"
27 #include "chrome/browser/autocomplete/autocomplete_match.h"
28 #include "chrome/browser/autofill/autofill_manager.h"
29 #include "chrome/browser/autofill/credit_card.h"
30 #include "chrome/browser/autofill/personal_data_manager.h"
31 #include "chrome/browser/automation/automation_autocomplete_edit_tracker.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/automation/ui_controls.h"
40 #include "chrome/browser/blocked_content_container.h"
41 #include "chrome/browser/bookmarks/bookmark_model.h"
42 #include "chrome/browser/bookmarks/bookmark_storage.h"
43 #include "chrome/browser/browser_process.h"
44 #include "chrome/browser/browser_shutdown.h"
45 #include "chrome/browser/debugger/devtools_manager.h"
46 #include "chrome/browser/download/download_prefs.h"
47 #include "chrome/browser/download/download_shelf.h"
48 #include "chrome/browser/download/save_package.h"
49 #include "chrome/browser/extensions/extension_host.h"
50 #include "chrome/browser/extensions/extension_service.h"
51 #include "chrome/browser/extensions/extension_updater.h"
52 #include "chrome/browser/history/top_sites.h"
53 #include "chrome/browser/importer/importer_host.h"
54 #include "chrome/browser/instant/instant_controller.h"
55 #include "chrome/browser/notifications/balloon.h"
56 #include "chrome/browser/notifications/balloon_collection.h"
57 #include "chrome/browser/notifications/notification.h"
58 #include "chrome/browser/notifications/notification_ui_manager.h"
59 #include "chrome/browser/password_manager/password_store.h"
60 #include "chrome/browser/platform_util.h"
61 #include "chrome/browser/prefs/pref_service.h"
62 #include "chrome/browser/profiles/profile.h"
63 #include "chrome/browser/profiles/profile_manager.h"
64 #include "chrome/browser/search_engines/template_url.h"
65 #include "chrome/browser/search_engines/template_url_model.h"
66 #include "chrome/browser/tab_contents/confirm_infobar_delegate.h"
67 #include "chrome/browser/tab_contents/link_infobar_delegate.h"
68 #include "chrome/browser/themes/theme_service.h"
69 #include "chrome/browser/themes/theme_service_factory.h"
70 #include "chrome/browser/translate/translate_infobar_delegate.h"
71 #include "chrome/browser/translate/translate_tab_helper.h"
72 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h"
73 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h"
74 #include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h"
75 #include "chrome/browser/ui/browser_window.h"
76 #include "chrome/browser/ui/download/download_tab_helper.h"
77 #include "chrome/browser/ui/find_bar/find_bar.h"
78 #include "chrome/browser/ui/login/login_prompt.h"
79 #include "chrome/browser/ui/omnibox/location_bar.h"
80 #include "chrome/browser/ui/search_engines/keyword_editor_controller.h"
81 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
82 #include "chrome/browser/ui/webui/active_downloads_ui.h"
83 #include "chrome/browser/ui/webui/shown_sections_handler.h"
84 #include "chrome/common/automation_messages.h"
85 #include "chrome/common/chrome_constants.h"
86 #include "chrome/common/chrome_paths.h"
87 #include "chrome/common/chrome_switches.h"
88 #include "chrome/common/extensions/extension.h"
89 #include "chrome/common/extensions/extension_extent.h"
90 #include "chrome/common/extensions/url_pattern.h"
91 #include "chrome/common/pref_names.h"
92 #include "chrome/common/url_constants.h"
93 #include "content/browser/renderer_host/render_process_host.h"
94 #include "content/browser/renderer_host/render_view_host.h"
95 #include "content/browser/tab_contents/interstitial_page.h"
96 #include "content/common/common_param_traits.h"
97 #include "content/common/notification_service.h"
98 #include "net/base/cookie_store.h"
99 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
100 #include "ui/base/events.h"
101 #include "ui/base/message_box_flags.h"
102 #include "webkit/plugins/npapi/plugin_list.h"
103 
104 namespace {
105 
SendMouseClick(int flags)106 void SendMouseClick(int flags) {
107   ui_controls::MouseButton button = ui_controls::LEFT;
108   if ((flags & ui::EF_LEFT_BUTTON_DOWN) ==
109       ui::EF_LEFT_BUTTON_DOWN) {
110     button = ui_controls::LEFT;
111   } else if ((flags & ui::EF_RIGHT_BUTTON_DOWN) ==
112              ui::EF_RIGHT_BUTTON_DOWN) {
113     button = ui_controls::RIGHT;
114   } else if ((flags & ui::EF_MIDDLE_BUTTON_DOWN) ==
115              ui::EF_MIDDLE_BUTTON_DOWN) {
116     button = ui_controls::MIDDLE;
117   } else {
118     NOTREACHED();
119   }
120 
121   ui_controls::SendMouseClick(button);
122 }
123 
124 class AutomationInterstitialPage : public InterstitialPage {
125  public:
AutomationInterstitialPage(TabContents * tab,const GURL & url,const std::string & contents)126   AutomationInterstitialPage(TabContents* tab,
127                              const GURL& url,
128                              const std::string& contents)
129       : InterstitialPage(tab, true, url),
130         contents_(contents) {
131   }
132 
GetHTMLContents()133   virtual std::string GetHTMLContents() { return contents_; }
134 
135  private:
136   const std::string contents_;
137 
138   DISALLOW_COPY_AND_ASSIGN(AutomationInterstitialPage);
139 };
140 
141 }  // namespace
142 
TestingAutomationProvider(Profile * profile)143 TestingAutomationProvider::TestingAutomationProvider(Profile* profile)
144     : AutomationProvider(profile),
145 #if defined(TOOLKIT_VIEWS)
146       popup_menu_waiter_(NULL),
147 #endif
148       redirect_query_(0) {
149   BrowserList::AddObserver(this);
150   registrar_.Add(this, NotificationType::SESSION_END,
151                  NotificationService::AllSources());
152 }
153 
~TestingAutomationProvider()154 TestingAutomationProvider::~TestingAutomationProvider() {
155   BrowserList::RemoveObserver(this);
156 }
157 
OnBrowserAdded(const Browser * browser)158 void TestingAutomationProvider::OnBrowserAdded(const Browser* browser) {
159 }
160 
OnBrowserRemoved(const Browser * browser)161 void TestingAutomationProvider::OnBrowserRemoved(const Browser* browser) {
162   // For backwards compatibility with the testing automation interface, we
163   // want the automation provider (and hence the process) to go away when the
164   // last browser goes away.
165   if (BrowserList::empty() && !CommandLine::ForCurrentProcess()->HasSwitch(
166           switches::kKeepAliveForTest)) {
167     // If you change this, update Observer for NotificationType::SESSION_END
168     // below.
169     MessageLoop::current()->PostTask(FROM_HERE,
170         NewRunnableMethod(this, &TestingAutomationProvider::OnRemoveProvider));
171   }
172 }
173 
OnSourceProfilesLoaded()174 void TestingAutomationProvider::OnSourceProfilesLoaded() {
175   DCHECK_NE(static_cast<ImporterList*>(NULL), importer_list_.get());
176 
177   // Get the correct profile based on the browser that the user provided.
178   importer::SourceProfile source_profile;
179   size_t i = 0;
180   size_t importers_count = importer_list_->count();
181   for ( ; i < importers_count; ++i) {
182     importer::SourceProfile profile = importer_list_->GetSourceProfileAt(i);
183     if (profile.importer_name == import_settings_data_.browser_name) {
184       source_profile = profile;
185       break;
186     }
187   }
188   // If we made it to the end of the loop, then the input was bad.
189   if (i == importers_count) {
190     AutomationJSONReply(this, import_settings_data_.reply_message)
191         .SendError("Invalid browser name string found.");
192     return;
193   }
194 
195   scoped_refptr<ImporterHost> importer_host(new ImporterHost);
196   importer_host->SetObserver(
197       new AutomationProviderImportSettingsObserver(
198           this, import_settings_data_.reply_message));
199 
200   Profile* target_profile = import_settings_data_.browser->profile();
201   importer_host->StartImportSettings(source_profile,
202                                      target_profile,
203                                      import_settings_data_.import_items,
204                                      new ProfileWriter(target_profile),
205                                      import_settings_data_.first_run);
206 }
207 
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)208 void TestingAutomationProvider::Observe(NotificationType type,
209                                         const NotificationSource& source,
210                                         const NotificationDetails& details) {
211   DCHECK(type == NotificationType::SESSION_END);
212   // OnBrowserRemoved does a ReleaseLater. When session end is received we exit
213   // before the task runs resulting in this object not being deleted. This
214   // Release balance out the Release scheduled by OnBrowserRemoved.
215   Release();
216 }
217 
OnMessageReceived(const IPC::Message & message)218 bool TestingAutomationProvider::OnMessageReceived(
219     const IPC::Message& message) {
220   bool handled = true;
221   bool deserialize_success = true;
222   IPC_BEGIN_MESSAGE_MAP_EX(TestingAutomationProvider,
223                            message,
224                            deserialize_success)
225     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_CloseBrowser, CloseBrowser)
226     IPC_MESSAGE_HANDLER(AutomationMsg_CloseBrowserRequestAsync,
227                         CloseBrowserAsync)
228     IPC_MESSAGE_HANDLER(AutomationMsg_ActivateTab, ActivateTab)
229     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_AppendTab, AppendTab)
230     IPC_MESSAGE_HANDLER(AutomationMsg_ActiveTabIndex, GetActiveTabIndex)
231     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_CloseTab, CloseTab)
232     IPC_MESSAGE_HANDLER(AutomationMsg_GetCookies, GetCookies)
233     IPC_MESSAGE_HANDLER(AutomationMsg_SetCookie, SetCookie)
234     IPC_MESSAGE_HANDLER(AutomationMsg_DeleteCookie, DeleteCookie)
235     IPC_MESSAGE_HANDLER(AutomationMsg_ShowCollectedCookiesDialog,
236                         ShowCollectedCookiesDialog)
237     IPC_MESSAGE_HANDLER_DELAY_REPLY(
238         AutomationMsg_NavigateToURLBlockUntilNavigationsComplete,
239         NavigateToURLBlockUntilNavigationsComplete)
240     IPC_MESSAGE_HANDLER(AutomationMsg_NavigationAsync, NavigationAsync)
241     IPC_MESSAGE_HANDLER(AutomationMsg_NavigationAsyncWithDisposition,
242                         NavigationAsyncWithDisposition)
243     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_Reload, Reload)
244     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_SetAuth, SetAuth)
245     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_CancelAuth, CancelAuth)
246     IPC_MESSAGE_HANDLER(AutomationMsg_NeedsAuth, NeedsAuth)
247     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_RedirectsFrom,
248                                     GetRedirectsFrom)
249     IPC_MESSAGE_HANDLER(AutomationMsg_BrowserWindowCount, GetBrowserWindowCount)
250     IPC_MESSAGE_HANDLER(AutomationMsg_NormalBrowserWindowCount,
251                         GetNormalBrowserWindowCount)
252     IPC_MESSAGE_HANDLER(AutomationMsg_BrowserWindow, GetBrowserWindow)
253     IPC_MESSAGE_HANDLER(AutomationMsg_GetBrowserLocale, GetBrowserLocale)
254     IPC_MESSAGE_HANDLER(AutomationMsg_LastActiveBrowserWindow,
255                         GetLastActiveBrowserWindow)
256     IPC_MESSAGE_HANDLER(AutomationMsg_ActiveWindow, GetActiveWindow)
257     IPC_MESSAGE_HANDLER(AutomationMsg_FindNormalBrowserWindow,
258                         FindNormalBrowserWindow)
259     IPC_MESSAGE_HANDLER(AutomationMsg_IsWindowActive, IsWindowActive)
260     IPC_MESSAGE_HANDLER(AutomationMsg_ActivateWindow, ActivateWindow)
261     IPC_MESSAGE_HANDLER(AutomationMsg_IsWindowMaximized, IsWindowMaximized)
262     IPC_MESSAGE_HANDLER(AutomationMsg_WindowExecuteCommandAsync,
263                         ExecuteBrowserCommandAsync)
264     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WindowExecuteCommand,
265                         ExecuteBrowserCommand)
266     IPC_MESSAGE_HANDLER(AutomationMsg_TerminateSession, TerminateSession)
267     IPC_MESSAGE_HANDLER(AutomationMsg_WindowViewBounds, WindowGetViewBounds)
268     IPC_MESSAGE_HANDLER(AutomationMsg_GetWindowBounds, GetWindowBounds)
269     IPC_MESSAGE_HANDLER(AutomationMsg_SetWindowBounds, SetWindowBounds)
270     IPC_MESSAGE_HANDLER(AutomationMsg_SetWindowVisible, SetWindowVisible)
271     IPC_MESSAGE_HANDLER(AutomationMsg_WindowClick, WindowSimulateClick)
272     IPC_MESSAGE_HANDLER(AutomationMsg_WindowMouseMove, WindowSimulateMouseMove)
273     IPC_MESSAGE_HANDLER(AutomationMsg_WindowKeyPress, WindowSimulateKeyPress)
274     IPC_MESSAGE_HANDLER(AutomationMsg_TabCount, GetTabCount)
275     IPC_MESSAGE_HANDLER(AutomationMsg_Type, GetType)
276     IPC_MESSAGE_HANDLER(AutomationMsg_Tab, GetTab)
277     IPC_MESSAGE_HANDLER(AutomationMsg_TabProcessID, GetTabProcessID)
278     IPC_MESSAGE_HANDLER(AutomationMsg_TabTitle, GetTabTitle)
279     IPC_MESSAGE_HANDLER(AutomationMsg_TabIndex, GetTabIndex)
280     IPC_MESSAGE_HANDLER(AutomationMsg_TabURL, GetTabURL)
281     IPC_MESSAGE_HANDLER(AutomationMsg_ShelfVisibility, GetShelfVisibility)
282     IPC_MESSAGE_HANDLER(AutomationMsg_IsFullscreen, IsFullscreen)
283     IPC_MESSAGE_HANDLER(AutomationMsg_IsFullscreenBubbleVisible,
284                         GetFullscreenBubbleVisibility)
285     IPC_MESSAGE_HANDLER(AutomationMsg_AutocompleteEditForBrowser,
286                         GetAutocompleteEditForBrowser)
287     IPC_MESSAGE_HANDLER(AutomationMsg_AutocompleteEditGetText,
288                         GetAutocompleteEditText)
289     IPC_MESSAGE_HANDLER(AutomationMsg_AutocompleteEditSetText,
290                         SetAutocompleteEditText)
291     IPC_MESSAGE_HANDLER(AutomationMsg_AutocompleteEditIsQueryInProgress,
292                         AutocompleteEditIsQueryInProgress)
293     IPC_MESSAGE_HANDLER(AutomationMsg_AutocompleteEditGetMatches,
294                         AutocompleteEditGetMatches)
295     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForAutocompleteEditFocus,
296                                     WaitForAutocompleteEditFocus)
297     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_DomOperation,
298                                     ExecuteJavascript)
299     IPC_MESSAGE_HANDLER(AutomationMsg_ConstrainedWindowCount,
300                         GetConstrainedWindowCount)
301 #if defined(TOOLKIT_VIEWS)
302     IPC_MESSAGE_HANDLER(AutomationMsg_GetFocusedViewID, GetFocusedViewID)
303     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForFocusedViewIDToChange,
304                                     WaitForFocusedViewIDToChange)
305     IPC_MESSAGE_HANDLER(AutomationMsg_StartTrackingPopupMenus,
306                         StartTrackingPopupMenus)
307     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForPopupMenuToOpen,
308                                     WaitForPopupMenuToOpen)
309 #endif  // defined(TOOLKIT_VIEWS)
310     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_InspectElement,
311                                     HandleInspectElementRequest)
312     IPC_MESSAGE_HANDLER(AutomationMsg_DownloadDirectory, GetDownloadDirectory)
313     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_OpenNewBrowserWindowOfType,
314                                     OpenNewBrowserWindowOfType)
315     IPC_MESSAGE_HANDLER(AutomationMsg_WindowForBrowser, GetWindowForBrowser)
316     IPC_MESSAGE_HANDLER(AutomationMsg_BrowserForWindow, GetBrowserForWindow)
317     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_ShowInterstitialPage,
318                                     ShowInterstitialPage)
319     IPC_MESSAGE_HANDLER(AutomationMsg_HideInterstitialPage,
320                         HideInterstitialPage)
321     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForTabToBeRestored,
322                                     WaitForTabToBeRestored)
323     IPC_MESSAGE_HANDLER(AutomationMsg_GetSecurityState, GetSecurityState)
324     IPC_MESSAGE_HANDLER(AutomationMsg_GetPageType, GetPageType)
325     IPC_MESSAGE_HANDLER(AutomationMsg_GetMetricEventDuration,
326                         GetMetricEventDuration)
327     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_ActionOnSSLBlockingPage,
328                                     ActionOnSSLBlockingPage)
329     IPC_MESSAGE_HANDLER(AutomationMsg_BringBrowserToFront, BringBrowserToFront)
330     IPC_MESSAGE_HANDLER(AutomationMsg_IsMenuCommandEnabled,
331                         IsMenuCommandEnabled)
332     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_PrintNow, PrintNow)
333     IPC_MESSAGE_HANDLER(AutomationMsg_SavePage, SavePage)
334     IPC_MESSAGE_HANDLER(AutomationMsg_OpenFindInPage,
335                         HandleOpenFindInPageRequest)
336     IPC_MESSAGE_HANDLER(AutomationMsg_FindWindowVisibility,
337                         GetFindWindowVisibility)
338     IPC_MESSAGE_HANDLER(AutomationMsg_FindWindowLocation,
339                         HandleFindWindowLocationRequest)
340     IPC_MESSAGE_HANDLER(AutomationMsg_BookmarkBarVisibility,
341                         GetBookmarkBarVisibility)
342     IPC_MESSAGE_HANDLER(AutomationMsg_GetBookmarksAsJSON,
343                         GetBookmarksAsJSON)
344     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForBookmarkModelToLoad,
345                                     WaitForBookmarkModelToLoad)
346     IPC_MESSAGE_HANDLER(AutomationMsg_AddBookmarkGroup,
347                         AddBookmarkGroup)
348     IPC_MESSAGE_HANDLER(AutomationMsg_AddBookmarkURL,
349                         AddBookmarkURL)
350     IPC_MESSAGE_HANDLER(AutomationMsg_ReparentBookmark,
351                         ReparentBookmark)
352     IPC_MESSAGE_HANDLER(AutomationMsg_SetBookmarkTitle,
353                         SetBookmarkTitle)
354     IPC_MESSAGE_HANDLER(AutomationMsg_SetBookmarkURL,
355                         SetBookmarkURL)
356     IPC_MESSAGE_HANDLER(AutomationMsg_RemoveBookmark,
357                         RemoveBookmark)
358     IPC_MESSAGE_HANDLER(AutomationMsg_GetInfoBarCount, GetInfoBarCount)
359     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_ClickInfoBarAccept,
360                                     ClickInfoBarAccept)
361     IPC_MESSAGE_HANDLER(AutomationMsg_GetLastNavigationTime,
362                         GetLastNavigationTime)
363     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForNavigation,
364                                     WaitForNavigation)
365     IPC_MESSAGE_HANDLER(AutomationMsg_SetIntPreference, SetIntPreference)
366     IPC_MESSAGE_HANDLER(AutomationMsg_ShowingAppModalDialog,
367                         GetShowingAppModalDialog)
368     IPC_MESSAGE_HANDLER(AutomationMsg_ClickAppModalDialogButton,
369                         ClickAppModalDialogButton)
370     IPC_MESSAGE_HANDLER(AutomationMsg_SetStringPreference, SetStringPreference)
371     IPC_MESSAGE_HANDLER(AutomationMsg_GetBooleanPreference,
372                         GetBooleanPreference)
373     IPC_MESSAGE_HANDLER(AutomationMsg_SetBooleanPreference,
374                         SetBooleanPreference)
375     IPC_MESSAGE_HANDLER_DELAY_REPLY(
376         AutomationMsg_WaitForBrowserWindowCountToBecome,
377         WaitForBrowserWindowCountToBecome)
378     IPC_MESSAGE_HANDLER_DELAY_REPLY(
379         AutomationMsg_WaitForAppModalDialogToBeShown,
380         WaitForAppModalDialogToBeShown)
381     IPC_MESSAGE_HANDLER_DELAY_REPLY(
382         AutomationMsg_GoBackBlockUntilNavigationsComplete,
383         GoBackBlockUntilNavigationsComplete)
384     IPC_MESSAGE_HANDLER_DELAY_REPLY(
385         AutomationMsg_GoForwardBlockUntilNavigationsComplete,
386         GoForwardBlockUntilNavigationsComplete)
387     IPC_MESSAGE_HANDLER(AutomationMsg_SavePackageShouldPromptUser,
388                         SavePackageShouldPromptUser)
389     IPC_MESSAGE_HANDLER(AutomationMsg_WindowTitle, GetWindowTitle)
390     IPC_MESSAGE_HANDLER(AutomationMsg_SetShelfVisibility, SetShelfVisibility)
391     IPC_MESSAGE_HANDLER(AutomationMsg_BlockedPopupCount, GetBlockedPopupCount)
392     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_SendJSONRequest,
393                                     SendJSONRequest)
394     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForTabCountToBecome,
395                                     WaitForTabCountToBecome)
396     IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForInfoBarCount,
397                                     WaitForInfoBarCount)
398     IPC_MESSAGE_HANDLER(AutomationMsg_GetPageCurrentEncoding,
399                         GetPageCurrentEncoding)
400     IPC_MESSAGE_HANDLER(AutomationMsg_ShutdownSessionService,
401                         ShutdownSessionService)
402     IPC_MESSAGE_HANDLER(AutomationMsg_SetContentSetting, SetContentSetting)
403     IPC_MESSAGE_HANDLER(AutomationMsg_LoadBlockedPlugins, LoadBlockedPlugins)
404     IPC_MESSAGE_HANDLER(AutomationMsg_ResetToDefaultTheme, ResetToDefaultTheme)
405     IPC_MESSAGE_HANDLER_DELAY_REPLY(
406         AutomationMsg_WaitForProcessLauncherThreadToGoIdle,
407         WaitForProcessLauncherThreadToGoIdle)
408     IPC_MESSAGE_HANDLER(AutomationMsg_GetParentBrowserOfTab,
409                         GetParentBrowserOfTab)
410 
411     IPC_MESSAGE_UNHANDLED(
412         handled = AutomationProvider::OnMessageReceived(message))
413   IPC_END_MESSAGE_MAP_EX()
414   if (!deserialize_success)
415     OnMessageDeserializationFailure();
416   return handled;
417 }
418 
OnChannelError()419 void TestingAutomationProvider::OnChannelError() {
420   if (!reinitialize_on_channel_error_ &&
421       browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID)
422     BrowserList::CloseAllBrowsersAndExit();
423   AutomationProvider::OnChannelError();
424 }
425 
CloseBrowser(int browser_handle,IPC::Message * reply_message)426 void TestingAutomationProvider::CloseBrowser(int browser_handle,
427                                              IPC::Message* reply_message) {
428   if (!browser_tracker_->ContainsHandle(browser_handle))
429     return;
430 
431   Browser* browser = browser_tracker_->GetResource(browser_handle);
432   new BrowserClosedNotificationObserver(browser, this, reply_message);
433   browser->window()->Close();
434 }
435 
CloseBrowserAsync(int browser_handle)436 void TestingAutomationProvider::CloseBrowserAsync(int browser_handle) {
437   if (!browser_tracker_->ContainsHandle(browser_handle))
438     return;
439 
440   Browser* browser = browser_tracker_->GetResource(browser_handle);
441   browser->window()->Close();
442 }
443 
ActivateTab(int handle,int at_index,int * status)444 void TestingAutomationProvider::ActivateTab(int handle,
445                                             int at_index,
446                                             int* status) {
447   *status = -1;
448   if (browser_tracker_->ContainsHandle(handle) && at_index > -1) {
449     Browser* browser = browser_tracker_->GetResource(handle);
450     if (at_index >= 0 && at_index < browser->tab_count()) {
451       browser->ActivateTabAt(at_index, true);
452       *status = 0;
453     }
454   }
455 }
456 
AppendTab(int handle,const GURL & url,IPC::Message * reply_message)457 void TestingAutomationProvider::AppendTab(int handle,
458                                           const GURL& url,
459                                           IPC::Message* reply_message) {
460   int append_tab_response = -1;  // -1 is the error code
461   NotificationObserver* observer = NULL;
462 
463   if (browser_tracker_->ContainsHandle(handle)) {
464     Browser* browser = browser_tracker_->GetResource(handle);
465     observer = new TabAppendedNotificationObserver(browser, this,
466                                                    reply_message);
467     TabContentsWrapper* contents =
468         browser->AddSelectedTabWithURL(url, PageTransition::TYPED);
469     if (contents) {
470       append_tab_response =
471           GetIndexForNavigationController(&contents->controller(), browser);
472     }
473   }
474 
475   if (append_tab_response < 0) {
476     // Appending tab failed. Clean up and send failure response.
477 
478     if (observer)
479       delete observer;
480 
481     AutomationMsg_AppendTab::WriteReplyParams(reply_message,
482                                               append_tab_response);
483     Send(reply_message);
484   }
485 }
486 
GetActiveTabIndex(int handle,int * active_tab_index)487 void TestingAutomationProvider::GetActiveTabIndex(int handle,
488                                                   int* active_tab_index) {
489   *active_tab_index = -1;  // -1 is the error code
490   if (browser_tracker_->ContainsHandle(handle)) {
491     Browser* browser = browser_tracker_->GetResource(handle);
492     *active_tab_index = browser->active_index();
493   }
494 }
495 
CloseTab(int tab_handle,bool wait_until_closed,IPC::Message * reply_message)496 void TestingAutomationProvider::CloseTab(int tab_handle,
497                                          bool wait_until_closed,
498                                          IPC::Message* reply_message) {
499   if (tab_tracker_->ContainsHandle(tab_handle)) {
500     NavigationController* controller = tab_tracker_->GetResource(tab_handle);
501     int index;
502     Browser* browser = Browser::GetBrowserForController(controller, &index);
503     DCHECK(browser);
504     new TabClosedNotificationObserver(this, wait_until_closed, reply_message);
505     browser->CloseTabContents(controller->tab_contents());
506     return;
507   }
508 
509   AutomationMsg_CloseTab::WriteReplyParams(reply_message, false);
510   Send(reply_message);
511 }
512 
GetCookies(const GURL & url,int handle,int * value_size,std::string * value)513 void TestingAutomationProvider::GetCookies(const GURL& url, int handle,
514                                            int* value_size,
515                                            std::string* value) {
516   TabContents *contents = tab_tracker_->ContainsHandle(handle) ?
517       tab_tracker_->GetResource(handle)->tab_contents() : NULL;
518   automation_util::GetCookies(url, contents, value_size, value);
519 }
520 
SetCookie(const GURL & url,const std::string & value,int handle,int * response_value)521 void TestingAutomationProvider::SetCookie(const GURL& url,
522                                           const std::string& value,
523                                           int handle,
524                                           int* response_value) {
525   TabContents *contents = tab_tracker_->ContainsHandle(handle) ?
526       tab_tracker_->GetResource(handle)->tab_contents() : NULL;
527   automation_util::SetCookie(url, value, contents, response_value);
528 }
529 
DeleteCookie(const GURL & url,const std::string & cookie_name,int handle,bool * success)530 void TestingAutomationProvider::DeleteCookie(const GURL& url,
531                                              const std::string& cookie_name,
532                                              int handle, bool* success) {
533   TabContents *contents = tab_tracker_->ContainsHandle(handle) ?
534       tab_tracker_->GetResource(handle)->tab_contents() : NULL;
535   automation_util::DeleteCookie(url, cookie_name, contents, success);
536 }
537 
ShowCollectedCookiesDialog(int handle,bool * success)538 void TestingAutomationProvider::ShowCollectedCookiesDialog(
539     int handle, bool* success) {
540   *success = false;
541   if (tab_tracker_->ContainsHandle(handle)) {
542     TabContents* tab_contents =
543         tab_tracker_->GetResource(handle)->tab_contents();
544     tab_contents->delegate()->ShowCollectedCookiesDialog(tab_contents);
545     *success = true;
546   }
547 }
548 
NavigateToURLBlockUntilNavigationsComplete(int handle,const GURL & url,int number_of_navigations,IPC::Message * reply_message)549 void TestingAutomationProvider::NavigateToURLBlockUntilNavigationsComplete(
550     int handle, const GURL& url, int number_of_navigations,
551     IPC::Message* reply_message) {
552   if (tab_tracker_->ContainsHandle(handle)) {
553     NavigationController* tab = tab_tracker_->GetResource(handle);
554 
555     // Simulate what a user would do. Activate the tab and then navigate.
556     // We could allow navigating in a background tab in future.
557     Browser* browser = FindAndActivateTab(tab);
558 
559     if (browser) {
560       new NavigationNotificationObserver(tab, this, reply_message,
561                                          number_of_navigations, false, false);
562 
563       // TODO(darin): avoid conversion to GURL.
564       browser->OpenURL(url, GURL(), CURRENT_TAB, PageTransition::TYPED);
565       return;
566     }
567   }
568 
569   AutomationMsg_NavigateToURLBlockUntilNavigationsComplete::WriteReplyParams(
570       reply_message, AUTOMATION_MSG_NAVIGATION_ERROR);
571   Send(reply_message);
572 }
573 
NavigationAsync(int handle,const GURL & url,bool * status)574 void TestingAutomationProvider::NavigationAsync(int handle,
575                                                 const GURL& url,
576                                                 bool* status) {
577   NavigationAsyncWithDisposition(handle, url, CURRENT_TAB, status);
578 }
579 
NavigationAsyncWithDisposition(int handle,const GURL & url,WindowOpenDisposition disposition,bool * status)580 void TestingAutomationProvider::NavigationAsyncWithDisposition(
581     int handle,
582     const GURL& url,
583     WindowOpenDisposition disposition,
584     bool* status) {
585   *status = false;
586 
587   if (tab_tracker_->ContainsHandle(handle)) {
588     NavigationController* tab = tab_tracker_->GetResource(handle);
589 
590     // Simulate what a user would do. Activate the tab and then navigate.
591     // We could allow navigating in a background tab in future.
592     Browser* browser = FindAndActivateTab(tab);
593 
594     if (browser) {
595       // Don't add any listener unless a callback mechanism is desired.
596       // TODO(vibhor): Do this if such a requirement arises in future.
597       browser->OpenURL(url, GURL(), disposition, PageTransition::TYPED);
598       *status = true;
599     }
600   }
601 }
602 
Reload(int handle,IPC::Message * reply_message)603 void TestingAutomationProvider::Reload(int handle,
604                                        IPC::Message* reply_message) {
605   if (tab_tracker_->ContainsHandle(handle)) {
606     NavigationController* tab = tab_tracker_->GetResource(handle);
607     Browser* browser = FindAndActivateTab(tab);
608     if (browser && browser->command_updater()->IsCommandEnabled(IDC_RELOAD)) {
609       new NavigationNotificationObserver(
610           tab, this, reply_message, 1, false, false);
611       browser->Reload(CURRENT_TAB);
612       return;
613     }
614   }
615 
616   AutomationMsg_Reload::WriteReplyParams(
617       reply_message, AUTOMATION_MSG_NAVIGATION_ERROR);
618   Send(reply_message);
619 }
620 
SetAuth(int tab_handle,const std::wstring & username,const std::wstring & password,IPC::Message * reply_message)621 void TestingAutomationProvider::SetAuth(int tab_handle,
622                                         const std::wstring& username,
623                                         const std::wstring& password,
624                                         IPC::Message* reply_message) {
625   if (tab_tracker_->ContainsHandle(tab_handle)) {
626     NavigationController* tab = tab_tracker_->GetResource(tab_handle);
627     LoginHandlerMap::iterator iter = login_handler_map_.find(tab);
628 
629     if (iter != login_handler_map_.end()) {
630       // If auth is needed again after this, assume login has failed.  This is
631       // not strictly correct, because a navigation can require both proxy and
632       // server auth, but it should be OK for now.
633       LoginHandler* handler = iter->second;
634       new NavigationNotificationObserver(
635           tab, this, reply_message, 1, false, false);
636       handler->SetAuth(WideToUTF16Hack(username), WideToUTF16Hack(password));
637       return;
638     }
639   }
640 
641   AutomationMsg_SetAuth::WriteReplyParams(
642       reply_message, AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED);
643   Send(reply_message);
644 }
645 
CancelAuth(int tab_handle,IPC::Message * reply_message)646 void TestingAutomationProvider::CancelAuth(int tab_handle,
647                                            IPC::Message* reply_message) {
648   if (tab_tracker_->ContainsHandle(tab_handle)) {
649     NavigationController* tab = tab_tracker_->GetResource(tab_handle);
650     LoginHandlerMap::iterator iter = login_handler_map_.find(tab);
651 
652     if (iter != login_handler_map_.end()) {
653       // If auth is needed again after this, something is screwy.
654       LoginHandler* handler = iter->second;
655       new NavigationNotificationObserver(
656           tab, this, reply_message, 1, false, false);
657       handler->CancelAuth();
658       return;
659     }
660   }
661 
662   AutomationMsg_CancelAuth::WriteReplyParams(
663       reply_message, AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED);
664   Send(reply_message);
665 }
666 
NeedsAuth(int tab_handle,bool * needs_auth)667 void TestingAutomationProvider::NeedsAuth(int tab_handle, bool* needs_auth) {
668   *needs_auth = false;
669 
670   if (tab_tracker_->ContainsHandle(tab_handle)) {
671     NavigationController* tab = tab_tracker_->GetResource(tab_handle);
672     LoginHandlerMap::iterator iter = login_handler_map_.find(tab);
673 
674     if (iter != login_handler_map_.end()) {
675       // The LoginHandler will be in our map IFF the tab needs auth.
676       *needs_auth = true;
677     }
678   }
679 }
680 
GetRedirectsFrom(int tab_handle,const GURL & source_url,IPC::Message * reply_message)681 void TestingAutomationProvider::GetRedirectsFrom(int tab_handle,
682                                                  const GURL& source_url,
683                                                  IPC::Message* reply_message) {
684   if (redirect_query_) {
685     LOG(ERROR) << "Can only handle one redirect query at once.";
686   } else if (tab_tracker_->ContainsHandle(tab_handle)) {
687     NavigationController* tab = tab_tracker_->GetResource(tab_handle);
688     HistoryService* history_service =
689         tab->profile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
690 
691     DCHECK(history_service) << "Tab " << tab_handle << "'s profile " <<
692                                "has no history service";
693     if (history_service) {
694       DCHECK(!reply_message_);
695       reply_message_ = reply_message;
696       // Schedule a history query for redirects. The response will be sent
697       // asynchronously from the callback the history system uses to notify us
698       // that it's done: OnRedirectQueryComplete.
699       redirect_query_ = history_service->QueryRedirectsFrom(
700           source_url, &consumer_,
701           NewCallback(this,
702                       &TestingAutomationProvider::OnRedirectQueryComplete));
703       return;  // Response will be sent when query completes.
704     }
705   }
706 
707   // Send failure response.
708   std::vector<GURL> empty;
709   AutomationMsg_RedirectsFrom::WriteReplyParams(reply_message, false, empty);
710   Send(reply_message);
711 }
712 
GetBrowserWindowCount(int * window_count)713 void TestingAutomationProvider::GetBrowserWindowCount(int* window_count) {
714   *window_count = static_cast<int>(BrowserList::size());
715 }
716 
GetNormalBrowserWindowCount(int * window_count)717 void TestingAutomationProvider::GetNormalBrowserWindowCount(int* window_count) {
718   *window_count = static_cast<int>(
719       BrowserList::GetBrowserCountForType(profile_, Browser::TYPE_NORMAL));
720 }
721 
GetBrowserWindow(int index,int * handle)722 void TestingAutomationProvider::GetBrowserWindow(int index, int* handle) {
723   *handle = 0;
724   Browser* browser = automation_util::GetBrowserAt(index);
725   if (browser)
726     *handle = browser_tracker_->Add(browser);
727 }
728 
FindNormalBrowserWindow(int * handle)729 void TestingAutomationProvider::FindNormalBrowserWindow(int* handle) {
730   *handle = 0;
731   Browser* browser = BrowserList::FindBrowserWithType(profile_,
732                                                       Browser::TYPE_NORMAL,
733                                                       false);
734   if (browser)
735     *handle = browser_tracker_->Add(browser);
736 }
737 
GetLastActiveBrowserWindow(int * handle)738 void TestingAutomationProvider::GetLastActiveBrowserWindow(int* handle) {
739   *handle = 0;
740   Browser* browser = BrowserList::GetLastActive();
741   if (browser)
742     *handle = browser_tracker_->Add(browser);
743 }
744 
GetActiveWindow(int * handle)745 void TestingAutomationProvider::GetActiveWindow(int* handle) {
746   *handle = 0;
747   Browser* browser = BrowserList::GetLastActive();
748   if (browser) {
749     gfx::NativeWindow window = browser->window()->GetNativeHandle();
750     *handle = window_tracker_->Add(window);
751   }
752 }
753 
ExecuteBrowserCommandAsync(int handle,int command,bool * success)754 void TestingAutomationProvider::ExecuteBrowserCommandAsync(int handle,
755                                                            int command,
756                                                            bool* success) {
757   *success = false;
758   if (browser_tracker_->ContainsHandle(handle)) {
759     Browser* browser = browser_tracker_->GetResource(handle);
760     if (browser->command_updater()->SupportsCommand(command) &&
761         browser->command_updater()->IsCommandEnabled(command)) {
762       browser->ExecuteCommand(command);
763       *success = true;
764     }
765   }
766 }
767 
ExecuteBrowserCommand(int handle,int command,IPC::Message * reply_message)768 void TestingAutomationProvider::ExecuteBrowserCommand(
769     int handle, int command, IPC::Message* reply_message) {
770   // List of commands which just finish synchronously and don't require
771   // setting up an observer.
772   static const int kSynchronousCommands[] = {
773     IDC_HOME,
774     IDC_SELECT_NEXT_TAB,
775     IDC_SELECT_PREVIOUS_TAB,
776     IDC_SHOW_BOOKMARK_MANAGER,
777   };
778   if (browser_tracker_->ContainsHandle(handle)) {
779     Browser* browser = browser_tracker_->GetResource(handle);
780     if (browser->command_updater()->SupportsCommand(command) &&
781         browser->command_updater()->IsCommandEnabled(command)) {
782       // First check if we can handle the command without using an observer.
783       for (size_t i = 0; i < arraysize(kSynchronousCommands); i++) {
784         if (command == kSynchronousCommands[i]) {
785           browser->ExecuteCommand(command);
786           AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message,
787                                                                true);
788           Send(reply_message);
789           return;
790         }
791       }
792 
793       // Use an observer if we have one, otherwise fail.
794       if (ExecuteBrowserCommandObserver::CreateAndRegisterObserver(
795           this, browser, command, reply_message)) {
796         browser->ExecuteCommand(command);
797         return;
798       }
799     }
800   }
801   AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message, false);
802   Send(reply_message);
803 }
804 
GetBrowserLocale(string16 * locale)805 void TestingAutomationProvider::GetBrowserLocale(string16* locale) {
806   *locale = ASCIIToUTF16(g_browser_process->GetApplicationLocale());
807 }
808 
IsWindowActive(int handle,bool * success,bool * is_active)809 void TestingAutomationProvider::IsWindowActive(int handle,
810                                                bool* success,
811                                                bool* is_active) {
812   if (window_tracker_->ContainsHandle(handle)) {
813     *is_active =
814         platform_util::IsWindowActive(window_tracker_->GetResource(handle));
815     *success = true;
816   } else {
817     *success = false;
818     *is_active = false;
819   }
820 }
821 
WindowSimulateClick(const IPC::Message & message,int handle,const gfx::Point & click,int flags)822 void TestingAutomationProvider::WindowSimulateClick(const IPC::Message& message,
823                                                     int handle,
824                                                     const gfx::Point& click,
825                                                     int flags) {
826   if (window_tracker_->ContainsHandle(handle)) {
827     // TODO(phajdan.jr): This is flaky. We should wait for the final click.
828     ui_controls::SendMouseMoveNotifyWhenDone(
829         click.x(), click.y(), NewRunnableFunction(&SendMouseClick, flags));
830   }
831 }
832 
WindowSimulateMouseMove(const IPC::Message & message,int handle,const gfx::Point & location)833 void TestingAutomationProvider::WindowSimulateMouseMove(
834     const IPC::Message& message,
835     int handle,
836     const gfx::Point& location) {
837   if (window_tracker_->ContainsHandle(handle))
838     ui_controls::SendMouseMove(location.x(), location.y());
839 }
840 
WindowSimulateKeyPress(const IPC::Message & message,int handle,int key,int flags)841 void TestingAutomationProvider::WindowSimulateKeyPress(
842     const IPC::Message& message,
843     int handle,
844     int key,
845     int flags) {
846   if (!window_tracker_->ContainsHandle(handle))
847     return;
848 
849   gfx::NativeWindow window = window_tracker_->GetResource(handle);
850   // The key event is sent to whatever window is active.
851   ui_controls::SendKeyPress(window, static_cast<ui::KeyboardCode>(key),
852                             ((flags & ui::EF_CONTROL_DOWN) ==
853                              ui::EF_CONTROL_DOWN),
854                             ((flags & ui::EF_SHIFT_DOWN) ==
855                              ui::EF_SHIFT_DOWN),
856                             ((flags & ui::EF_ALT_DOWN) ==
857                              ui::EF_ALT_DOWN),
858                             ((flags & ui::EF_COMMAND_DOWN) ==
859                              ui::EF_COMMAND_DOWN));
860 }
861 
WebkitMouseClick(DictionaryValue * args,IPC::Message * reply_message)862 void TestingAutomationProvider::WebkitMouseClick(DictionaryValue* args,
863                                                  IPC::Message* reply_message) {
864   TabContents* tab_contents;
865   std::string error;
866   if (!GetTabFromJSONArgs(args, &tab_contents, &error)) {
867     AutomationJSONReply(this, reply_message).SendError(error);
868     return;
869   }
870 
871   WebKit::WebMouseEvent mouse_event;
872   if (!args->GetInteger("x", &mouse_event.x) ||
873       !args->GetInteger("y", &mouse_event.y)) {
874     AutomationJSONReply(this, reply_message)
875         .SendError("(X,Y) coordinates missing or invalid");
876     return;
877   }
878 
879   int button;
880   if (!args->GetInteger("button", &button)) {
881     AutomationJSONReply(this, reply_message)
882         .SendError("Mouse button missing or invalid");
883     return;
884   }
885   if (button == automation::kLeftButton) {
886     mouse_event.button = WebKit::WebMouseEvent::ButtonLeft;
887   } else if (button == automation::kRightButton) {
888     mouse_event.button = WebKit::WebMouseEvent::ButtonRight;
889   } else if (button == automation::kMiddleButton) {
890     mouse_event.button = WebKit::WebMouseEvent::ButtonMiddle;
891   } else {
892     AutomationJSONReply(this, reply_message)
893         .SendError("Invalid button press requested");
894     return;
895   }
896 
897   mouse_event.type = WebKit::WebInputEvent::MouseDown;
898   mouse_event.clickCount = 1;
899 
900   tab_contents->render_view_host()->ForwardMouseEvent(mouse_event);
901 
902   mouse_event.type = WebKit::WebInputEvent::MouseUp;
903   new InputEventAckNotificationObserver(this, reply_message, mouse_event.type);
904   tab_contents->render_view_host()->ForwardMouseEvent(mouse_event);
905 }
906 
WebkitMouseMove(DictionaryValue * args,IPC::Message * reply_message)907 void TestingAutomationProvider::WebkitMouseMove(
908     DictionaryValue* args, IPC::Message* reply_message) {
909   TabContents* tab_contents;
910   std::string error;
911   if (!GetTabFromJSONArgs(args, &tab_contents, &error)) {
912     AutomationJSONReply(this, reply_message).SendError(error);
913     return;
914   }
915 
916   WebKit::WebMouseEvent mouse_event;
917   if (!args->GetInteger("x", &mouse_event.x) ||
918       !args->GetInteger("y", &mouse_event.y)) {
919     AutomationJSONReply(this, reply_message)
920         .SendError("(X,Y) coordinates missing or invalid");
921     return;
922   }
923 
924   mouse_event.type = WebKit::WebInputEvent::MouseMove;
925   new InputEventAckNotificationObserver(this, reply_message, mouse_event.type);
926   tab_contents->render_view_host()->ForwardMouseEvent(mouse_event);
927 }
928 
WebkitMouseDrag(DictionaryValue * args,IPC::Message * reply_message)929 void TestingAutomationProvider::WebkitMouseDrag(DictionaryValue* args,
930                                                 IPC::Message* reply_message) {
931   TabContents* tab_contents;
932   std::string error;
933   if (!GetTabFromJSONArgs(args, &tab_contents, &error)) {
934     AutomationJSONReply(this, reply_message).SendError(error);
935     return;
936   }
937 
938   WebKit::WebMouseEvent mouse_event;
939   int start_x, start_y, end_x, end_y;
940   if (!args->GetInteger("start_x", &start_x) ||
941       !args->GetInteger("start_y", &start_y) ||
942       !args->GetInteger("end_x", &end_x) ||
943       !args->GetInteger("end_y", &end_y)) {
944     AutomationJSONReply(this, reply_message)
945         .SendError("Invalid start/end positions");
946     return;
947   }
948 
949   mouse_event.type = WebKit::WebInputEvent::MouseMove;
950   // Step 1- Move the mouse to the start position.
951   mouse_event.x = start_x;
952   mouse_event.y = start_y;
953   tab_contents->render_view_host()->ForwardMouseEvent(mouse_event);
954 
955   // Step 2- Left click mouse down, the mouse button is fixed.
956   mouse_event.type = WebKit::WebInputEvent::MouseDown;
957   mouse_event.button = WebKit::WebMouseEvent::ButtonLeft;
958   mouse_event.clickCount = 1;
959   tab_contents->render_view_host()->ForwardMouseEvent(mouse_event);
960 
961   // Step 3 - Move the mouse to the end position.
962   // TODO(JMikhail): See if we should simulate the by not making such
963   // a drastic jump by placing incrmental stops along the way.
964   mouse_event.type = WebKit::WebInputEvent::MouseMove;
965   mouse_event.x = end_x;
966   mouse_event.y = end_y;
967   mouse_event.clickCount = 0;
968   tab_contents->render_view_host()->ForwardMouseEvent(mouse_event);
969 
970   // Step 4 - Release the left mouse button.
971   mouse_event.type = WebKit::WebInputEvent::MouseUp;
972   mouse_event.clickCount = 1;
973   new InputEventAckNotificationObserver(this, reply_message, mouse_event.type);
974   tab_contents->render_view_host()->ForwardMouseEvent(mouse_event);
975 }
976 
GetTabCount(int handle,int * tab_count)977 void TestingAutomationProvider::GetTabCount(int handle, int* tab_count) {
978   *tab_count = -1;  // -1 is the error code
979 
980   if (browser_tracker_->ContainsHandle(handle)) {
981     Browser* browser = browser_tracker_->GetResource(handle);
982     *tab_count = browser->tab_count();
983   }
984 }
985 
GetType(int handle,int * type_as_int)986 void TestingAutomationProvider::GetType(int handle, int* type_as_int) {
987   *type_as_int = -1;  // -1 is the error code
988 
989   if (browser_tracker_->ContainsHandle(handle)) {
990     Browser* browser = browser_tracker_->GetResource(handle);
991     *type_as_int = static_cast<int>(browser->type());
992   }
993 }
994 
GetTab(int win_handle,int tab_index,int * tab_handle)995 void TestingAutomationProvider::GetTab(int win_handle,
996                                        int tab_index,
997                                        int* tab_handle) {
998   *tab_handle = 0;
999   if (browser_tracker_->ContainsHandle(win_handle) && (tab_index >= 0)) {
1000     Browser* browser = browser_tracker_->GetResource(win_handle);
1001     if (tab_index < browser->tab_count()) {
1002       TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
1003       *tab_handle = tab_tracker_->Add(&tab_contents->controller());
1004     }
1005   }
1006 }
1007 
GetTabProcessID(int handle,int * process_id)1008 void TestingAutomationProvider::GetTabProcessID(int handle, int* process_id) {
1009   *process_id = -1;
1010 
1011   if (tab_tracker_->ContainsHandle(handle)) {
1012     *process_id = 0;
1013     TabContents* tab_contents =
1014         tab_tracker_->GetResource(handle)->tab_contents();
1015     RenderProcessHost* rph = tab_contents->GetRenderProcessHost();
1016     if (rph)
1017       *process_id = base::GetProcId(rph->GetHandle());
1018   }
1019 }
1020 
GetTabTitle(int handle,int * title_string_size,std::wstring * title)1021 void TestingAutomationProvider::GetTabTitle(int handle,
1022                                             int* title_string_size,
1023                                             std::wstring* title) {
1024   *title_string_size = -1;  // -1 is the error code
1025   if (tab_tracker_->ContainsHandle(handle)) {
1026     NavigationController* tab = tab_tracker_->GetResource(handle);
1027     NavigationEntry* entry = tab->GetActiveEntry();
1028     if (entry != NULL) {
1029       *title = UTF16ToWideHack(entry->GetTitleForDisplay(""));
1030     } else {
1031       *title = std::wstring();
1032     }
1033     *title_string_size = static_cast<int>(title->size());
1034   }
1035 }
1036 
GetTabIndex(int handle,int * tabstrip_index)1037 void TestingAutomationProvider::GetTabIndex(int handle, int* tabstrip_index) {
1038   *tabstrip_index = -1;  // -1 is the error code
1039 
1040   if (tab_tracker_->ContainsHandle(handle)) {
1041     NavigationController* tab = tab_tracker_->GetResource(handle);
1042     Browser* browser = Browser::GetBrowserForController(tab, NULL);
1043     *tabstrip_index = browser->tabstrip_model()->GetIndexOfController(tab);
1044   }
1045 }
1046 
GetTabURL(int handle,bool * success,GURL * url)1047 void TestingAutomationProvider::GetTabURL(int handle,
1048                                           bool* success,
1049                                           GURL* url) {
1050   *success = false;
1051   if (tab_tracker_->ContainsHandle(handle)) {
1052     NavigationController* tab = tab_tracker_->GetResource(handle);
1053     // Return what the user would see in the location bar.
1054     *url = tab->GetActiveEntry()->virtual_url();
1055     *success = true;
1056   }
1057 }
1058 
GetShelfVisibility(int handle,bool * visible)1059 void TestingAutomationProvider::GetShelfVisibility(int handle, bool* visible) {
1060   *visible = false;
1061 
1062   if (browser_tracker_->ContainsHandle(handle)) {
1063     Browser* browser = browser_tracker_->GetResource(handle);
1064     if (browser) {
1065 #if defined(OS_CHROMEOS)
1066       *visible = ActiveDownloadsUI::GetPopup(browser->profile());
1067 #else
1068       *visible = browser->window()->IsDownloadShelfVisible();
1069 #endif
1070     }
1071   }
1072 }
1073 
IsFullscreen(int handle,bool * visible)1074 void TestingAutomationProvider::IsFullscreen(int handle, bool* visible) {
1075   *visible = false;
1076 
1077   if (browser_tracker_->ContainsHandle(handle)) {
1078     Browser* browser = browser_tracker_->GetResource(handle);
1079     if (browser)
1080       *visible = browser->window()->IsFullscreen();
1081   }
1082 }
1083 
GetFullscreenBubbleVisibility(int handle,bool * visible)1084 void TestingAutomationProvider::GetFullscreenBubbleVisibility(int handle,
1085                                                               bool* visible) {
1086   *visible = false;
1087 
1088   if (browser_tracker_->ContainsHandle(handle)) {
1089     Browser* browser = browser_tracker_->GetResource(handle);
1090     if (browser)
1091       *visible = browser->window()->IsFullscreenBubbleVisible();
1092   }
1093 }
1094 
GetAutocompleteEditText(int autocomplete_edit_handle,bool * success,string16 * text)1095 void TestingAutomationProvider::GetAutocompleteEditText(
1096     int autocomplete_edit_handle,
1097     bool* success,
1098     string16* text) {
1099   *success = false;
1100   if (autocomplete_edit_tracker_->ContainsHandle(autocomplete_edit_handle)) {
1101     *text = autocomplete_edit_tracker_->GetResource(autocomplete_edit_handle)->
1102         GetText();
1103     *success = true;
1104   }
1105 }
1106 
SetAutocompleteEditText(int autocomplete_edit_handle,const string16 & text,bool * success)1107 void TestingAutomationProvider::SetAutocompleteEditText(
1108     int autocomplete_edit_handle,
1109     const string16& text,
1110     bool* success) {
1111   *success = false;
1112   if (autocomplete_edit_tracker_->ContainsHandle(autocomplete_edit_handle)) {
1113     autocomplete_edit_tracker_->GetResource(autocomplete_edit_handle)->
1114         SetUserText(text);
1115     *success = true;
1116   }
1117 }
1118 
AutocompleteEditGetMatches(int autocomplete_edit_handle,bool * success,std::vector<AutocompleteMatchData> * matches)1119 void TestingAutomationProvider::AutocompleteEditGetMatches(
1120     int autocomplete_edit_handle,
1121     bool* success,
1122     std::vector<AutocompleteMatchData>* matches) {
1123   *success = false;
1124   if (autocomplete_edit_tracker_->ContainsHandle(autocomplete_edit_handle)) {
1125     const AutocompleteResult& result = autocomplete_edit_tracker_->
1126         GetResource(autocomplete_edit_handle)->model()->result();
1127     for (AutocompleteResult::const_iterator i = result.begin();
1128         i != result.end(); ++i)
1129       matches->push_back(AutocompleteMatchData(*i));
1130     *success = true;
1131   }
1132 }
1133 
1134 // Waits for the autocomplete edit to receive focus
WaitForAutocompleteEditFocus(int autocomplete_edit_handle,IPC::Message * reply_message)1135 void  TestingAutomationProvider::WaitForAutocompleteEditFocus(
1136     int autocomplete_edit_handle,
1137     IPC::Message* reply_message) {
1138   if (!autocomplete_edit_tracker_->ContainsHandle(autocomplete_edit_handle)) {
1139     AutomationMsg_WaitForAutocompleteEditFocus::WriteReplyParams(
1140         reply_message_, false);
1141     Send(reply_message);
1142     return;
1143   }
1144 
1145   AutocompleteEditModel* model = autocomplete_edit_tracker_->
1146       GetResource(autocomplete_edit_handle)-> model();
1147   if (model->has_focus()) {
1148     AutomationMsg_WaitForAutocompleteEditFocus::WriteReplyParams(
1149         reply_message, true);
1150     Send(reply_message);
1151     return;
1152   }
1153 
1154   // The observer deletes itself when the notification arrives.
1155   new AutocompleteEditFocusedObserver(this, model, reply_message);
1156 }
1157 
GetAutocompleteEditForBrowser(int browser_handle,bool * success,int * autocomplete_edit_handle)1158 void TestingAutomationProvider::GetAutocompleteEditForBrowser(
1159     int browser_handle,
1160     bool* success,
1161     int* autocomplete_edit_handle) {
1162   *success = false;
1163   *autocomplete_edit_handle = 0;
1164 
1165   if (browser_tracker_->ContainsHandle(browser_handle)) {
1166     Browser* browser = browser_tracker_->GetResource(browser_handle);
1167     LocationBar* loc_bar = browser->window()->GetLocationBar();
1168     AutocompleteEditView* edit_view = loc_bar->location_entry();
1169     // Add() returns the existing handle for the resource if any.
1170     *autocomplete_edit_handle = autocomplete_edit_tracker_->Add(edit_view);
1171     *success = true;
1172   }
1173 }
1174 
AutocompleteEditIsQueryInProgress(int autocomplete_edit_handle,bool * success,bool * query_in_progress)1175 void TestingAutomationProvider::AutocompleteEditIsQueryInProgress(
1176     int autocomplete_edit_handle,
1177     bool* success,
1178     bool* query_in_progress) {
1179   *success = false;
1180   *query_in_progress = false;
1181   if (autocomplete_edit_tracker_->ContainsHandle(autocomplete_edit_handle)) {
1182     *query_in_progress = !autocomplete_edit_tracker_->
1183         GetResource(autocomplete_edit_handle)->model()->
1184         autocomplete_controller()->done();
1185     *success = true;
1186   }
1187 }
1188 
ExecuteJavascript(int handle,const std::wstring & frame_xpath,const std::wstring & script,IPC::Message * reply_message)1189 void TestingAutomationProvider::ExecuteJavascript(
1190     int handle,
1191     const std::wstring& frame_xpath,
1192     const std::wstring& script,
1193     IPC::Message* reply_message) {
1194   TabContents* tab_contents = GetTabContentsForHandle(handle, NULL);
1195   if (!tab_contents) {
1196     AutomationMsg_DomOperation::WriteReplyParams(reply_message, std::string());
1197     Send(reply_message);
1198     return;
1199   }
1200 
1201   // Set the routing id of this message with the controller.
1202   // This routing id needs to be remembered for the reverse
1203   // communication while sending back the response of
1204   // this javascript execution.
1205   std::string set_automation_id;
1206   base::SStringPrintf(&set_automation_id,
1207                       "window.domAutomationController.setAutomationId(%d);",
1208                       reply_message->routing_id());
1209 
1210   new DomOperationMessageSender(this, reply_message, false);
1211   tab_contents->render_view_host()->ExecuteJavascriptInWebFrame(
1212       WideToUTF16Hack(frame_xpath), UTF8ToUTF16(set_automation_id));
1213   tab_contents->render_view_host()->ExecuteJavascriptInWebFrame(
1214       WideToUTF16Hack(frame_xpath), WideToUTF16Hack(script));
1215 }
1216 
GetConstrainedWindowCount(int handle,int * count)1217 void TestingAutomationProvider::GetConstrainedWindowCount(int handle,
1218                                                           int* count) {
1219   *count = -1;  // -1 is the error code
1220   if (tab_tracker_->ContainsHandle(handle)) {
1221     NavigationController* nav_controller = tab_tracker_->GetResource(handle);
1222     TabContents* tab_contents = nav_controller->tab_contents();
1223     if (tab_contents)
1224       *count = static_cast<int>(tab_contents->child_windows_.size());
1225   }
1226 }
1227 
HandleInspectElementRequest(int handle,int x,int y,IPC::Message * reply_message)1228 void TestingAutomationProvider::HandleInspectElementRequest(
1229     int handle, int x, int y, IPC::Message* reply_message) {
1230   TabContents* tab_contents = GetTabContentsForHandle(handle, NULL);
1231   if (tab_contents) {
1232     DCHECK(!reply_message_);
1233     reply_message_ = reply_message;
1234 
1235     DevToolsManager::GetInstance()->InspectElement(
1236         tab_contents->render_view_host(), x, y);
1237   } else {
1238     AutomationMsg_InspectElement::WriteReplyParams(reply_message, -1);
1239     Send(reply_message);
1240   }
1241 }
1242 
GetDownloadDirectory(int handle,FilePath * download_directory)1243 void TestingAutomationProvider::GetDownloadDirectory(
1244     int handle, FilePath* download_directory) {
1245   if (tab_tracker_->ContainsHandle(handle)) {
1246     NavigationController* tab = tab_tracker_->GetResource(handle);
1247     DownloadManager* dlm = tab->profile()->GetDownloadManager();
1248     *download_directory = dlm->download_prefs()->download_path();
1249   }
1250 }
1251 
OpenNewBrowserWindowOfType(int type,bool show,IPC::Message * reply_message)1252 void TestingAutomationProvider::OpenNewBrowserWindowOfType(
1253     int type, bool show, IPC::Message* reply_message) {
1254   new BrowserOpenedNotificationObserver(this, reply_message);
1255   // We may have no current browser windows open so don't rely on
1256   // asking an existing browser to execute the IDC_NEWWINDOW command
1257   Browser* browser = new Browser(static_cast<Browser::Type>(type), profile_);
1258   browser->InitBrowserWindow();
1259   browser->AddBlankTab(true);
1260   if (show)
1261     browser->window()->Show();
1262 }
1263 
GetWindowForBrowser(int browser_handle,bool * success,int * handle)1264 void TestingAutomationProvider::GetWindowForBrowser(int browser_handle,
1265                                                     bool* success,
1266                                                     int* handle) {
1267   *success = false;
1268   *handle = 0;
1269 
1270   if (browser_tracker_->ContainsHandle(browser_handle)) {
1271     Browser* browser = browser_tracker_->GetResource(browser_handle);
1272     gfx::NativeWindow win = browser->window()->GetNativeHandle();
1273     // Add() returns the existing handle for the resource if any.
1274     *handle = window_tracker_->Add(win);
1275     *success = true;
1276   }
1277 }
1278 
GetBrowserForWindow(int window_handle,bool * success,int * browser_handle)1279 void TestingAutomationProvider::GetBrowserForWindow(int window_handle,
1280                                                     bool* success,
1281                                                     int* browser_handle) {
1282   *success = false;
1283   *browser_handle = 0;
1284 
1285   gfx::NativeWindow window = window_tracker_->GetResource(window_handle);
1286   if (!window)
1287     return;
1288 
1289   BrowserList::const_iterator iter = BrowserList::begin();
1290   for (;iter != BrowserList::end(); ++iter) {
1291     gfx::NativeWindow this_window = (*iter)->window()->GetNativeHandle();
1292     if (window == this_window) {
1293       // Add() returns the existing handle for the resource if any.
1294       *browser_handle = browser_tracker_->Add(*iter);
1295       *success = true;
1296       return;
1297     }
1298   }
1299 }
1300 
ShowInterstitialPage(int tab_handle,const std::string & html_text,IPC::Message * reply_message)1301 void TestingAutomationProvider::ShowInterstitialPage(
1302     int tab_handle,
1303     const std::string& html_text,
1304     IPC::Message* reply_message) {
1305   if (tab_tracker_->ContainsHandle(tab_handle)) {
1306     NavigationController* controller = tab_tracker_->GetResource(tab_handle);
1307     TabContents* tab_contents = controller->tab_contents();
1308 
1309     new NavigationNotificationObserver(controller, this, reply_message, 1,
1310                                        false, false);
1311 
1312     AutomationInterstitialPage* interstitial =
1313         new AutomationInterstitialPage(tab_contents,
1314                                        GURL("about:interstitial"),
1315                                        html_text);
1316     interstitial->Show();
1317     return;
1318   }
1319 
1320   AutomationMsg_ShowInterstitialPage::WriteReplyParams(
1321       reply_message, AUTOMATION_MSG_NAVIGATION_ERROR);
1322   Send(reply_message);
1323 }
1324 
HideInterstitialPage(int tab_handle,bool * success)1325 void TestingAutomationProvider::HideInterstitialPage(int tab_handle,
1326                                                      bool* success) {
1327   *success = false;
1328   TabContents* tab_contents = GetTabContentsForHandle(tab_handle, NULL);
1329   if (tab_contents && tab_contents->interstitial_page()) {
1330     tab_contents->interstitial_page()->DontProceed();
1331     *success = true;
1332   }
1333 }
1334 
WaitForTabToBeRestored(int tab_handle,IPC::Message * reply_message)1335 void TestingAutomationProvider::WaitForTabToBeRestored(
1336     int tab_handle,
1337     IPC::Message* reply_message) {
1338   if (tab_tracker_->ContainsHandle(tab_handle)) {
1339     NavigationController* tab = tab_tracker_->GetResource(tab_handle);
1340     restore_tracker_.reset(
1341         new NavigationControllerRestoredObserver(this, tab, reply_message));
1342   } else {
1343     AutomationMsg_WaitForTabToBeRestored::WriteReplyParams(
1344         reply_message, false);
1345     Send(reply_message);
1346   }
1347 }
1348 
GetSecurityState(int handle,bool * success,SecurityStyle * security_style,int * ssl_cert_status,int * insecure_content_status)1349 void TestingAutomationProvider::GetSecurityState(int handle,
1350                                                  bool* success,
1351                                                  SecurityStyle* security_style,
1352                                                  int* ssl_cert_status,
1353                                                  int* insecure_content_status) {
1354   if (tab_tracker_->ContainsHandle(handle)) {
1355     NavigationController* tab = tab_tracker_->GetResource(handle);
1356     NavigationEntry* entry = tab->GetActiveEntry();
1357     *success = true;
1358     *security_style = entry->ssl().security_style();
1359     *ssl_cert_status = entry->ssl().cert_status();
1360     *insecure_content_status = entry->ssl().content_status();
1361   } else {
1362     *success = false;
1363     *security_style = SECURITY_STYLE_UNKNOWN;
1364     *ssl_cert_status = 0;
1365     *insecure_content_status = 0;
1366   }
1367 }
1368 
GetPageType(int handle,bool * success,PageType * page_type)1369 void TestingAutomationProvider::GetPageType(
1370     int handle,
1371     bool* success,
1372     PageType* page_type) {
1373   if (tab_tracker_->ContainsHandle(handle)) {
1374     NavigationController* tab = tab_tracker_->GetResource(handle);
1375     NavigationEntry* entry = tab->GetActiveEntry();
1376     *page_type = entry->page_type();
1377     *success = true;
1378     // In order to return the proper result when an interstitial is shown and
1379     // no navigation entry were created for it we need to ask the TabContents.
1380     if (*page_type == NORMAL_PAGE &&
1381         tab->tab_contents()->showing_interstitial_page())
1382       *page_type = INTERSTITIAL_PAGE;
1383   } else {
1384     *success = false;
1385     *page_type = NORMAL_PAGE;
1386   }
1387 }
1388 
GetMetricEventDuration(const std::string & event_name,int * duration_ms)1389 void TestingAutomationProvider::GetMetricEventDuration(
1390     const std::string& event_name,
1391     int* duration_ms) {
1392   *duration_ms = metric_event_duration_observer_->GetEventDurationMs(
1393       event_name);
1394 }
1395 
ActionOnSSLBlockingPage(int handle,bool proceed,IPC::Message * reply_message)1396 void TestingAutomationProvider::ActionOnSSLBlockingPage(
1397     int handle,
1398     bool proceed,
1399     IPC::Message* reply_message) {
1400   if (tab_tracker_->ContainsHandle(handle)) {
1401     NavigationController* tab = tab_tracker_->GetResource(handle);
1402     NavigationEntry* entry = tab->GetActiveEntry();
1403     if (entry->page_type() == INTERSTITIAL_PAGE) {
1404       TabContents* tab_contents = tab->tab_contents();
1405       InterstitialPage* ssl_blocking_page =
1406           InterstitialPage::GetInterstitialPage(tab_contents);
1407       if (ssl_blocking_page) {
1408         if (proceed) {
1409           new NavigationNotificationObserver(tab, this, reply_message, 1,
1410                                              false, false);
1411           ssl_blocking_page->Proceed();
1412           return;
1413         }
1414         ssl_blocking_page->DontProceed();
1415         AutomationMsg_ActionOnSSLBlockingPage::WriteReplyParams(
1416             reply_message, AUTOMATION_MSG_NAVIGATION_SUCCESS);
1417         Send(reply_message);
1418         return;
1419       }
1420     }
1421   }
1422   // We failed.
1423   AutomationMsg_ActionOnSSLBlockingPage::WriteReplyParams(
1424       reply_message, AUTOMATION_MSG_NAVIGATION_ERROR);
1425   Send(reply_message);
1426 }
1427 
BringBrowserToFront(int browser_handle,bool * success)1428 void TestingAutomationProvider::BringBrowserToFront(int browser_handle,
1429                                                     bool* success) {
1430   *success = false;
1431   if (browser_tracker_->ContainsHandle(browser_handle)) {
1432     Browser* browser = browser_tracker_->GetResource(browser_handle);
1433     browser->window()->Activate();
1434     *success = true;
1435   }
1436 }
1437 
IsMenuCommandEnabled(int browser_handle,int message_num,bool * menu_item_enabled)1438 void TestingAutomationProvider::IsMenuCommandEnabled(int browser_handle,
1439                                                      int message_num,
1440                                                      bool* menu_item_enabled) {
1441   *menu_item_enabled = false;
1442   if (browser_tracker_->ContainsHandle(browser_handle)) {
1443     Browser* browser = browser_tracker_->GetResource(browser_handle);
1444     *menu_item_enabled =
1445         browser->command_updater()->IsCommandEnabled(message_num);
1446   }
1447 }
1448 
PrintNow(int tab_handle,IPC::Message * reply_message)1449 void TestingAutomationProvider::PrintNow(int tab_handle,
1450                                          IPC::Message* reply_message) {
1451   NavigationController* tab = NULL;
1452   TabContents* tab_contents = GetTabContentsForHandle(tab_handle, &tab);
1453   if (tab_contents) {
1454     FindAndActivateTab(tab);
1455 
1456     NotificationObserver* observer =
1457         new DocumentPrintedNotificationObserver(this, reply_message);
1458 
1459     TabContentsWrapper* wrapper =
1460         TabContentsWrapper::GetCurrentWrapperForContents(tab_contents);
1461     if (!wrapper->print_view_manager()->PrintNow()) {
1462       // Clean up the observer. It will send the reply message.
1463       delete observer;
1464     }
1465 
1466     // Return now to avoid sending reply message twice.
1467     return;
1468   }
1469 
1470   AutomationMsg_PrintNow::WriteReplyParams(reply_message, false);
1471   Send(reply_message);
1472 }
1473 
SavePage(int tab_handle,const FilePath & file_name,const FilePath & dir_path,int type,bool * success)1474 void TestingAutomationProvider::SavePage(int tab_handle,
1475                                          const FilePath& file_name,
1476                                          const FilePath& dir_path,
1477                                          int type,
1478                                          bool* success) {
1479   SavePackage::SavePackageType save_type =
1480       static_cast<SavePackage::SavePackageType>(type);
1481   if (save_type < SavePackage::SAVE_AS_ONLY_HTML ||
1482       save_type > SavePackage::SAVE_AS_COMPLETE_HTML) {
1483     *success = false;
1484     return;
1485   }
1486 
1487   if (!tab_tracker_->ContainsHandle(tab_handle)) {
1488     *success = false;
1489     return;
1490   }
1491 
1492   NavigationController* nav = tab_tracker_->GetResource(tab_handle);
1493   Browser* browser = FindAndActivateTab(nav);
1494   if (!browser->command_updater()->IsCommandEnabled(IDC_SAVE_PAGE)) {
1495     *success = false;
1496     return;
1497   }
1498 
1499   TabContentsWrapper* wrapper =
1500       TabContentsWrapper::GetCurrentWrapperForContents(nav->tab_contents());
1501   wrapper->download_tab_helper()->SavePage(file_name, dir_path, save_type);
1502   *success = true;
1503 }
1504 
HandleOpenFindInPageRequest(const IPC::Message & message,int handle)1505 void TestingAutomationProvider::HandleOpenFindInPageRequest(
1506     const IPC::Message& message, int handle) {
1507   if (browser_tracker_->ContainsHandle(handle)) {
1508     Browser* browser = browser_tracker_->GetResource(handle);
1509     browser->FindInPage(false, false);
1510   }
1511 }
1512 
GetFindWindowVisibility(int handle,bool * visible)1513 void TestingAutomationProvider::GetFindWindowVisibility(int handle,
1514                                                         bool* visible) {
1515   *visible = false;
1516   Browser* browser = browser_tracker_->GetResource(handle);
1517   if (browser) {
1518     FindBarTesting* find_bar =
1519         browser->GetFindBarController()->find_bar()->GetFindBarTesting();
1520     find_bar->GetFindBarWindowInfo(NULL, visible);
1521   }
1522 }
1523 
HandleFindWindowLocationRequest(int handle,int * x,int * y)1524 void TestingAutomationProvider::HandleFindWindowLocationRequest(int handle,
1525                                                                 int* x,
1526                                                                 int* y) {
1527   gfx::Point position(0, 0);
1528   bool visible = false;
1529   if (browser_tracker_->ContainsHandle(handle)) {
1530      Browser* browser = browser_tracker_->GetResource(handle);
1531      FindBarTesting* find_bar =
1532        browser->GetFindBarController()->find_bar()->GetFindBarTesting();
1533      find_bar->GetFindBarWindowInfo(&position, &visible);
1534   }
1535 
1536   *x = position.x();
1537   *y = position.y();
1538 }
1539 
1540 // Bookmark bar visibility is based on the pref (e.g. is it in the toolbar).
1541 // Presence in the NTP is NOT considered visible by this call.
GetBookmarkBarVisibility(int handle,bool * visible,bool * animating)1542 void TestingAutomationProvider::GetBookmarkBarVisibility(int handle,
1543                                                          bool* visible,
1544                                                          bool* animating) {
1545   *visible = false;
1546   *animating = false;
1547 
1548   if (browser_tracker_->ContainsHandle(handle)) {
1549     Browser* browser = browser_tracker_->GetResource(handle);
1550     if (browser) {
1551 #if 0  // defined(TOOLKIT_VIEWS) && defined(OS_LINUX)
1552       // TODO(jrg): Was removed in rev43789 for perf. Need to investigate.
1553 
1554       // IsBookmarkBarVisible() line looks correct but is not
1555       // consistent across platforms.  Specifically, on Mac/Linux, it
1556       // returns false if the bar is hidden in a pref (even if visible
1557       // on the NTP).  On ChromeOS, it returned true if on NTP
1558       // independent of the pref.  Making the code more consistent
1559       // caused a perf bot regression on Windows (which shares views).
1560       // See http://crbug.com/40225
1561       *visible = browser->profile()->GetPrefs()->GetBoolean(
1562           prefs::kShowBookmarkBar);
1563 #else
1564       *visible = browser->window()->IsBookmarkBarVisible();
1565 #endif
1566       *animating = browser->window()->IsBookmarkBarAnimating();
1567     }
1568   }
1569 }
1570 
GetBookmarksAsJSON(int handle,std::string * bookmarks_as_json,bool * success)1571 void TestingAutomationProvider::GetBookmarksAsJSON(
1572     int handle,
1573     std::string* bookmarks_as_json,
1574     bool *success) {
1575   *success = false;
1576   if (browser_tracker_->ContainsHandle(handle)) {
1577     Browser* browser = browser_tracker_->GetResource(handle);
1578     if (browser) {
1579       if (!browser->profile()->GetBookmarkModel()->IsLoaded()) {
1580         return;
1581       }
1582       scoped_refptr<BookmarkStorage> storage(new BookmarkStorage(
1583           browser->profile(),
1584           browser->profile()->GetBookmarkModel()));
1585       *success = storage->SerializeData(bookmarks_as_json);
1586     }
1587   }
1588 }
1589 
WaitForBookmarkModelToLoad(int handle,IPC::Message * reply_message)1590 void TestingAutomationProvider::WaitForBookmarkModelToLoad(
1591     int handle,
1592     IPC::Message* reply_message) {
1593   if (browser_tracker_->ContainsHandle(handle)) {
1594     Browser* browser = browser_tracker_->GetResource(handle);
1595     BookmarkModel* model = browser->profile()->GetBookmarkModel();
1596     if (model->IsLoaded()) {
1597       AutomationMsg_WaitForBookmarkModelToLoad::WriteReplyParams(
1598           reply_message, true);
1599       Send(reply_message);
1600     } else {
1601       // The observer will delete itself when done.
1602       new AutomationProviderBookmarkModelObserver(this, reply_message,
1603                                                   model);
1604     }
1605   }
1606 }
1607 
AddBookmarkGroup(int handle,int64 parent_id,int index,std::wstring title,bool * success)1608 void TestingAutomationProvider::AddBookmarkGroup(int handle,
1609                                                  int64 parent_id,
1610                                                  int index,
1611                                                  std::wstring title,
1612                                                  bool* success) {
1613   if (browser_tracker_->ContainsHandle(handle)) {
1614     Browser* browser = browser_tracker_->GetResource(handle);
1615     if (browser) {
1616       BookmarkModel* model = browser->profile()->GetBookmarkModel();
1617       if (!model->IsLoaded()) {
1618         *success = false;
1619         return;
1620       }
1621       const BookmarkNode* parent = model->GetNodeByID(parent_id);
1622       DCHECK(parent);
1623       if (parent) {
1624         const BookmarkNode* child = model->AddFolder(parent, index,
1625                                                      WideToUTF16Hack(title));
1626         DCHECK(child);
1627         if (child)
1628           *success = true;
1629       }
1630     }
1631   }
1632   *success = false;
1633 }
1634 
AddBookmarkURL(int handle,int64 parent_id,int index,std::wstring title,const GURL & url,bool * success)1635 void TestingAutomationProvider::AddBookmarkURL(int handle,
1636                                                int64 parent_id,
1637                                                int index,
1638                                                std::wstring title,
1639                                                const GURL& url,
1640                                                bool* success) {
1641   if (browser_tracker_->ContainsHandle(handle)) {
1642     Browser* browser = browser_tracker_->GetResource(handle);
1643     if (browser) {
1644       BookmarkModel* model = browser->profile()->GetBookmarkModel();
1645       if (!model->IsLoaded()) {
1646         *success = false;
1647         return;
1648       }
1649       const BookmarkNode* parent = model->GetNodeByID(parent_id);
1650       DCHECK(parent);
1651       if (parent) {
1652         const BookmarkNode* child = model->AddURL(parent, index,
1653                                                   WideToUTF16Hack(title), url);
1654         DCHECK(child);
1655         if (child)
1656           *success = true;
1657       }
1658     }
1659   }
1660   *success = false;
1661 }
1662 
ReparentBookmark(int handle,int64 id,int64 new_parent_id,int index,bool * success)1663 void TestingAutomationProvider::ReparentBookmark(int handle,
1664                                                  int64 id,
1665                                                  int64 new_parent_id,
1666                                                  int index,
1667                                                  bool* success) {
1668   if (browser_tracker_->ContainsHandle(handle)) {
1669     Browser* browser = browser_tracker_->GetResource(handle);
1670     if (browser) {
1671       BookmarkModel* model = browser->profile()->GetBookmarkModel();
1672       if (!model->IsLoaded()) {
1673         *success = false;
1674         return;
1675       }
1676       const BookmarkNode* node = model->GetNodeByID(id);
1677       DCHECK(node);
1678       const BookmarkNode* new_parent = model->GetNodeByID(new_parent_id);
1679       DCHECK(new_parent);
1680       if (node && new_parent) {
1681         model->Move(node, new_parent, index);
1682         *success = true;
1683       }
1684     }
1685   }
1686   *success = false;
1687 }
1688 
SetBookmarkTitle(int handle,int64 id,std::wstring title,bool * success)1689 void TestingAutomationProvider::SetBookmarkTitle(int handle,
1690                                                  int64 id,
1691                                                  std::wstring title,
1692                                                  bool* success) {
1693   if (browser_tracker_->ContainsHandle(handle)) {
1694     Browser* browser = browser_tracker_->GetResource(handle);
1695     if (browser) {
1696       BookmarkModel* model = browser->profile()->GetBookmarkModel();
1697       if (!model->IsLoaded()) {
1698         *success = false;
1699         return;
1700       }
1701       const BookmarkNode* node = model->GetNodeByID(id);
1702       DCHECK(node);
1703       if (node) {
1704         model->SetTitle(node, WideToUTF16Hack(title));
1705         *success = true;
1706       }
1707     }
1708   }
1709   *success = false;
1710 }
1711 
SetBookmarkURL(int handle,int64 id,const GURL & url,bool * success)1712 void TestingAutomationProvider::SetBookmarkURL(int handle,
1713                                                int64 id,
1714                                                const GURL& url,
1715                                                bool* success) {
1716   if (browser_tracker_->ContainsHandle(handle)) {
1717     Browser* browser = browser_tracker_->GetResource(handle);
1718     if (browser) {
1719       BookmarkModel* model = browser->profile()->GetBookmarkModel();
1720       if (!model->IsLoaded()) {
1721         *success = false;
1722         return;
1723       }
1724       const BookmarkNode* node = model->GetNodeByID(id);
1725       DCHECK(node);
1726       if (node) {
1727         model->SetURL(node, url);
1728         *success = true;
1729       }
1730     }
1731   }
1732   *success = false;
1733 }
1734 
RemoveBookmark(int handle,int64 id,bool * success)1735 void TestingAutomationProvider::RemoveBookmark(int handle,
1736                                                int64 id,
1737                                                bool* success) {
1738   if (browser_tracker_->ContainsHandle(handle)) {
1739     Browser* browser = browser_tracker_->GetResource(handle);
1740     if (browser) {
1741       BookmarkModel* model = browser->profile()->GetBookmarkModel();
1742       if (!model->IsLoaded()) {
1743         *success = false;
1744         return;
1745       }
1746       const BookmarkNode* node = model->GetNodeByID(id);
1747       DCHECK(node);
1748       if (node) {
1749         const BookmarkNode* parent = node->parent();
1750         DCHECK(parent);
1751         model->Remove(parent, parent->GetIndexOf(node));
1752         *success = true;
1753       }
1754     }
1755   }
1756   *success = false;
1757 }
1758 
GetInfoBarCount(int handle,size_t * count)1759 void TestingAutomationProvider::GetInfoBarCount(int handle, size_t* count) {
1760   *count = static_cast<size_t>(-1);  // -1 means error.
1761   if (tab_tracker_->ContainsHandle(handle)) {
1762     NavigationController* nav_controller = tab_tracker_->GetResource(handle);
1763     if (nav_controller)
1764       *count = nav_controller->tab_contents()->infobar_count();
1765   }
1766 }
1767 
ClickInfoBarAccept(int handle,size_t info_bar_index,bool wait_for_navigation,IPC::Message * reply_message)1768 void TestingAutomationProvider::ClickInfoBarAccept(
1769     int handle,
1770     size_t info_bar_index,
1771     bool wait_for_navigation,
1772     IPC::Message* reply_message) {
1773   bool success = false;
1774   if (tab_tracker_->ContainsHandle(handle)) {
1775     NavigationController* nav_controller = tab_tracker_->GetResource(handle);
1776     if (nav_controller) {
1777       if (info_bar_index < nav_controller->tab_contents()->infobar_count()) {
1778         if (wait_for_navigation) {
1779           new NavigationNotificationObserver(nav_controller, this,
1780                                              reply_message, 1, false, false);
1781         }
1782         InfoBarDelegate* delegate =
1783             nav_controller->tab_contents()->GetInfoBarDelegateAt(
1784                 info_bar_index);
1785         if (delegate->AsConfirmInfoBarDelegate())
1786           delegate->AsConfirmInfoBarDelegate()->Accept();
1787         success = true;
1788       }
1789     }
1790   }
1791 
1792   // This "!wait_for_navigation || !success condition" logic looks suspicious.
1793   // It will send a failure message when success is true but
1794   // |wait_for_navigation| is false.
1795   // TODO(phajdan.jr): investgate whether the reply param (currently
1796   // AUTOMATION_MSG_NAVIGATION_ERROR) should depend on success.
1797   if (!wait_for_navigation || !success)
1798     AutomationMsg_ClickInfoBarAccept::WriteReplyParams(
1799         reply_message, AUTOMATION_MSG_NAVIGATION_ERROR);
1800 }
1801 
GetLastNavigationTime(int handle,int64 * last_navigation_time)1802 void TestingAutomationProvider::GetLastNavigationTime(
1803     int handle,
1804     int64* last_navigation_time) {
1805   base::Time time(tab_tracker_->GetLastNavigationTime(handle));
1806   *last_navigation_time = time.ToInternalValue();
1807 }
1808 
WaitForNavigation(int handle,int64 last_navigation_time,IPC::Message * reply_message)1809 void TestingAutomationProvider::WaitForNavigation(int handle,
1810                                                   int64 last_navigation_time,
1811                                                   IPC::Message* reply_message) {
1812   NavigationController* controller = tab_tracker_->GetResource(handle);
1813   base::Time time(tab_tracker_->GetLastNavigationTime(handle));
1814 
1815   if (time.ToInternalValue() > last_navigation_time || !controller) {
1816     AutomationMsg_WaitForNavigation::WriteReplyParams(reply_message,
1817         controller == NULL ? AUTOMATION_MSG_NAVIGATION_ERROR :
1818                              AUTOMATION_MSG_NAVIGATION_SUCCESS);
1819     Send(reply_message);
1820     return;
1821   }
1822 
1823   new NavigationNotificationObserver(
1824       controller, this, reply_message, 1, true, false);
1825 }
1826 
SetIntPreference(int handle,const std::string & name,int value,bool * success)1827 void TestingAutomationProvider::SetIntPreference(int handle,
1828                                                  const std::string& name,
1829                                                  int value,
1830                                                  bool* success) {
1831   *success = false;
1832   if (browser_tracker_->ContainsHandle(handle)) {
1833     Browser* browser = browser_tracker_->GetResource(handle);
1834     browser->profile()->GetPrefs()->SetInteger(name.c_str(), value);
1835     *success = true;
1836   }
1837 }
1838 
SetStringPreference(int handle,const std::string & name,const std::string & value,bool * success)1839 void TestingAutomationProvider::SetStringPreference(int handle,
1840                                                     const std::string& name,
1841                                                     const std::string& value,
1842                                                     bool* success) {
1843   *success = false;
1844   if (browser_tracker_->ContainsHandle(handle)) {
1845     Browser* browser = browser_tracker_->GetResource(handle);
1846     browser->profile()->GetPrefs()->SetString(name.c_str(), value);
1847     *success = true;
1848   }
1849 }
1850 
GetBooleanPreference(int handle,const std::string & name,bool * success,bool * value)1851 void TestingAutomationProvider::GetBooleanPreference(int handle,
1852                                                      const std::string& name,
1853                                                      bool* success,
1854                                                      bool* value) {
1855   *success = false;
1856   *value = false;
1857   if (browser_tracker_->ContainsHandle(handle)) {
1858     Browser* browser = browser_tracker_->GetResource(handle);
1859     *value = browser->profile()->GetPrefs()->GetBoolean(name.c_str());
1860     *success = true;
1861   }
1862 }
1863 
SetBooleanPreference(int handle,const std::string & name,bool value,bool * success)1864 void TestingAutomationProvider::SetBooleanPreference(int handle,
1865                                                      const std::string& name,
1866                                                      bool value,
1867                                                      bool* success) {
1868   *success = false;
1869   if (browser_tracker_->ContainsHandle(handle)) {
1870     Browser* browser = browser_tracker_->GetResource(handle);
1871     browser->profile()->GetPrefs()->SetBoolean(name.c_str(), value);
1872     *success = true;
1873   }
1874 }
1875 
GetShowingAppModalDialog(bool * showing_dialog,int * dialog_button)1876 void TestingAutomationProvider::GetShowingAppModalDialog(bool* showing_dialog,
1877                                                          int* dialog_button) {
1878   AppModalDialog* active_dialog =
1879       AppModalDialogQueue::GetInstance()->active_dialog();
1880   if (!active_dialog) {
1881     *showing_dialog = false;
1882     *dialog_button = ui::MessageBoxFlags::DIALOGBUTTON_NONE;
1883     return;
1884   }
1885   NativeAppModalDialog* native_dialog = active_dialog->native_dialog();
1886   *showing_dialog = (native_dialog != NULL);
1887   if (*showing_dialog)
1888     *dialog_button = native_dialog->GetAppModalDialogButtons();
1889   else
1890     *dialog_button = ui::MessageBoxFlags::DIALOGBUTTON_NONE;
1891 }
1892 
ClickAppModalDialogButton(int button,bool * success)1893 void TestingAutomationProvider::ClickAppModalDialogButton(int button,
1894                                                           bool* success) {
1895   *success = false;
1896 
1897   NativeAppModalDialog* native_dialog =
1898       AppModalDialogQueue::GetInstance()->active_dialog()->native_dialog();
1899   if (native_dialog &&
1900       (native_dialog->GetAppModalDialogButtons() & button) == button) {
1901     if ((button & ui::MessageBoxFlags::DIALOGBUTTON_OK) ==
1902         ui::MessageBoxFlags::DIALOGBUTTON_OK) {
1903       native_dialog->AcceptAppModalDialog();
1904       *success =  true;
1905     }
1906     if ((button & ui::MessageBoxFlags::DIALOGBUTTON_CANCEL) ==
1907         ui::MessageBoxFlags::DIALOGBUTTON_CANCEL) {
1908       DCHECK(!*success) << "invalid param, OK and CANCEL specified";
1909       native_dialog->CancelAppModalDialog();
1910       *success =  true;
1911     }
1912   }
1913 }
1914 
WaitForBrowserWindowCountToBecome(int target_count,IPC::Message * reply_message)1915 void TestingAutomationProvider::WaitForBrowserWindowCountToBecome(
1916     int target_count,
1917     IPC::Message* reply_message) {
1918   if (static_cast<int>(BrowserList::size()) == target_count) {
1919     AutomationMsg_WaitForBrowserWindowCountToBecome::WriteReplyParams(
1920         reply_message, true);
1921     Send(reply_message);
1922     return;
1923   }
1924 
1925   // Set up an observer (it will delete itself).
1926   new BrowserCountChangeNotificationObserver(target_count, this, reply_message);
1927 }
1928 
WaitForAppModalDialogToBeShown(IPC::Message * reply_message)1929 void TestingAutomationProvider::WaitForAppModalDialogToBeShown(
1930     IPC::Message* reply_message) {
1931   if (AppModalDialogQueue::GetInstance()->HasActiveDialog()) {
1932     AutomationMsg_WaitForAppModalDialogToBeShown::WriteReplyParams(
1933         reply_message, true);
1934     Send(reply_message);
1935     return;
1936   }
1937 
1938   // Set up an observer (it will delete itself).
1939   new AppModalDialogShownObserver(this, reply_message);
1940 }
1941 
GoBackBlockUntilNavigationsComplete(int handle,int number_of_navigations,IPC::Message * reply_message)1942 void TestingAutomationProvider::GoBackBlockUntilNavigationsComplete(
1943     int handle, int number_of_navigations, IPC::Message* reply_message) {
1944   if (tab_tracker_->ContainsHandle(handle)) {
1945     NavigationController* tab = tab_tracker_->GetResource(handle);
1946     Browser* browser = FindAndActivateTab(tab);
1947     if (browser && browser->command_updater()->IsCommandEnabled(IDC_BACK)) {
1948       new NavigationNotificationObserver(tab, this, reply_message,
1949                                          number_of_navigations, false, false);
1950       browser->GoBack(CURRENT_TAB);
1951       return;
1952     }
1953   }
1954 
1955   AutomationMsg_GoBackBlockUntilNavigationsComplete::WriteReplyParams(
1956       reply_message, AUTOMATION_MSG_NAVIGATION_ERROR);
1957   Send(reply_message);
1958 }
1959 
GoForwardBlockUntilNavigationsComplete(int handle,int number_of_navigations,IPC::Message * reply_message)1960 void TestingAutomationProvider::GoForwardBlockUntilNavigationsComplete(
1961     int handle, int number_of_navigations, IPC::Message* reply_message) {
1962   if (tab_tracker_->ContainsHandle(handle)) {
1963     NavigationController* tab = tab_tracker_->GetResource(handle);
1964     Browser* browser = FindAndActivateTab(tab);
1965     if (browser && browser->command_updater()->IsCommandEnabled(IDC_FORWARD)) {
1966       new NavigationNotificationObserver(tab, this, reply_message,
1967                                          number_of_navigations, false, false);
1968       browser->GoForward(CURRENT_TAB);
1969       return;
1970     }
1971   }
1972 
1973   AutomationMsg_GoForwardBlockUntilNavigationsComplete::WriteReplyParams(
1974       reply_message, AUTOMATION_MSG_NAVIGATION_ERROR);
1975   Send(reply_message);
1976 }
1977 
SavePackageShouldPromptUser(bool should_prompt)1978 void TestingAutomationProvider::SavePackageShouldPromptUser(
1979     bool should_prompt) {
1980   SavePackage::SetShouldPromptUser(should_prompt);
1981 }
1982 
SetShelfVisibility(int handle,bool visible)1983 void TestingAutomationProvider::SetShelfVisibility(int handle, bool visible) {
1984   if (browser_tracker_->ContainsHandle(handle)) {
1985     Browser* browser = browser_tracker_->GetResource(handle);
1986     if (browser) {
1987 #if defined(OS_CHROMEOS)
1988       Browser* popup_browser =
1989           ActiveDownloadsUI::GetPopup(browser->profile());
1990       if (!popup_browser && visible)
1991         ActiveDownloadsUI::OpenPopup(browser->profile());
1992       if (popup_browser && !visible)
1993         popup_browser->CloseWindow();
1994 #else
1995       if (visible)
1996         browser->window()->GetDownloadShelf()->Show();
1997       else
1998         browser->window()->GetDownloadShelf()->Close();
1999 #endif
2000     }
2001   }
2002 }
2003 
GetBlockedPopupCount(int handle,int * count)2004 void TestingAutomationProvider::GetBlockedPopupCount(int handle, int* count) {
2005   *count = -1;  // -1 is the error code
2006   if (tab_tracker_->ContainsHandle(handle)) {
2007       NavigationController* nav_controller = tab_tracker_->GetResource(handle);
2008       TabContents* tab_contents = nav_controller->tab_contents();
2009       if (tab_contents) {
2010         BlockedContentContainer* container =
2011             tab_contents->blocked_content_container();
2012         if (container) {
2013           *count = static_cast<int>(container->GetBlockedContentsCount());
2014         } else {
2015           // If we don't have a container, we don't have any blocked popups to
2016           // contain!
2017           *count = 0;
2018         }
2019       }
2020   }
2021 }
2022 
SendJSONRequest(int handle,const std::string & json_request,IPC::Message * reply_message)2023 void TestingAutomationProvider::SendJSONRequest(int handle,
2024                                                 const std::string& json_request,
2025                                                 IPC::Message* reply_message) {
2026   scoped_ptr<Value> values;
2027   base::JSONReader reader;
2028   std::string error;
2029   values.reset(reader.ReadAndReturnError(json_request, true, NULL, &error));
2030   if (!error.empty()) {
2031     AutomationJSONReply(this, reply_message).SendError(error);
2032     return;
2033   }
2034 
2035   // Make sure input is a dict with a string command.
2036   std::string command;
2037   DictionaryValue* dict_value = NULL;
2038   if (values->GetType() != Value::TYPE_DICTIONARY) {
2039     AutomationJSONReply(this, reply_message).SendError("not a dict");
2040     return;
2041   }
2042   // Ownership remains with "values" variable.
2043   dict_value = static_cast<DictionaryValue*>(values.get());
2044   if (!dict_value->GetStringASCII(std::string("command"), &command)) {
2045     AutomationJSONReply(this, reply_message)
2046         .SendError("no command key in dict or not a string command");
2047     return;
2048   }
2049 
2050   // Map json commands to their handlers.
2051   std::map<std::string, JsonHandler> handler_map;
2052   handler_map["WaitForAllTabsToStopLoading"] =
2053       &TestingAutomationProvider::WaitForAllTabsToStopLoading;
2054   handler_map["GetIndicesFromTab"] =
2055       &TestingAutomationProvider::GetIndicesFromTab;
2056   handler_map["NavigateToURL"] =
2057       &TestingAutomationProvider::NavigateToURL;
2058   handler_map["ExecuteJavascript"] =
2059       &TestingAutomationProvider::ExecuteJavascriptJSON;
2060   handler_map["GoForward"] =
2061       &TestingAutomationProvider::GoForward;
2062   handler_map["GoBack"] =
2063       &TestingAutomationProvider::GoBack;
2064   handler_map["Reload"] =
2065       &TestingAutomationProvider::ReloadJSON;
2066   handler_map["GetTabURL"] =
2067       &TestingAutomationProvider::GetTabURLJSON;
2068   handler_map["GetTabTitle"] =
2069       &TestingAutomationProvider::GetTabTitleJSON;
2070   handler_map["CaptureEntirePage"] =
2071       &TestingAutomationProvider::CaptureEntirePageJSON;
2072   handler_map["GetCookies"] =
2073       &TestingAutomationProvider::GetCookiesJSON;
2074   handler_map["DeleteCookie"] =
2075       &TestingAutomationProvider::DeleteCookieJSON;
2076   handler_map["SetCookie"] =
2077       &TestingAutomationProvider::SetCookieJSON;
2078   handler_map["GetTabIds"] =
2079       &TestingAutomationProvider::GetTabIds;
2080   handler_map["IsTabIdValid"] =
2081       &TestingAutomationProvider::IsTabIdValid;
2082   handler_map["CloseTab"] =
2083       &TestingAutomationProvider::CloseTabJSON;
2084   handler_map["WebkitMouseMove"] =
2085       &TestingAutomationProvider::WebkitMouseMove;
2086   handler_map["WebkitMouseClick"] =
2087       &TestingAutomationProvider::WebkitMouseClick;
2088   handler_map["WebkitMouseDrag"] =
2089       &TestingAutomationProvider::WebkitMouseDrag;
2090   handler_map["SendWebkitKeyEvent"] =
2091       &TestingAutomationProvider::SendWebkitKeyEvent;
2092   handler_map["SendOSLevelKeyEventToTab"] =
2093       &TestingAutomationProvider::SendOSLevelKeyEventToTab;
2094   handler_map["ActivateTab"] =
2095       &TestingAutomationProvider::ActivateTabJSON;
2096   handler_map["UpdateExtensionsNow"] =
2097       &TestingAutomationProvider::UpdateExtensionsNow;
2098   handler_map["GetChromeDriverAutomationVersion"] =
2099       &TestingAutomationProvider::GetChromeDriverAutomationVersion;
2100 #if defined(OS_CHROMEOS)
2101   handler_map["GetLoginInfo"] = &TestingAutomationProvider::GetLoginInfo;
2102   handler_map["LoginAsGuest"] = &TestingAutomationProvider::LoginAsGuest;
2103   handler_map["Login"] = &TestingAutomationProvider::Login;
2104 
2105   handler_map["LockScreen"] = &TestingAutomationProvider::LockScreen;
2106   handler_map["UnlockScreen"] = &TestingAutomationProvider::UnlockScreen;
2107   handler_map["SignoutInScreenLocker"] =
2108       &TestingAutomationProvider::SignoutInScreenLocker;
2109 
2110   handler_map["GetBatteryInfo"] = &TestingAutomationProvider::GetBatteryInfo;
2111 
2112   handler_map["GetNetworkInfo"] = &TestingAutomationProvider::GetNetworkInfo;
2113   handler_map["NetworkScan"] = &TestingAutomationProvider::NetworkScan;
2114   handler_map["GetProxySettings"] =
2115       &TestingAutomationProvider::GetProxySettings;
2116   handler_map["SetProxySettings"] =
2117       &TestingAutomationProvider::SetProxySettings;
2118   handler_map["ConnectToWifiNetwork"] =
2119       &TestingAutomationProvider::ConnectToWifiNetwork;
2120   handler_map["ConnectToHiddenWifiNetwork"] =
2121       &TestingAutomationProvider::ConnectToHiddenWifiNetwork;
2122   handler_map["DisconnectFromWifiNetwork"] =
2123       &TestingAutomationProvider::DisconnectFromWifiNetwork;
2124 
2125   handler_map["GetUpdateInfo"] = &TestingAutomationProvider::GetUpdateInfo;
2126   handler_map["UpdateCheck"] = &TestingAutomationProvider::UpdateCheck;
2127   handler_map["SetReleaseTrack"] = &TestingAutomationProvider::SetReleaseTrack;
2128 #endif  // defined(OS_CHROMEOS)
2129 
2130   std::map<std::string, BrowserJsonHandler> browser_handler_map;
2131   browser_handler_map["DisablePlugin"] =
2132       &TestingAutomationProvider::DisablePlugin;
2133   browser_handler_map["EnablePlugin"] =
2134       &TestingAutomationProvider::EnablePlugin;
2135   browser_handler_map["GetPluginsInfo"] =
2136       &TestingAutomationProvider::GetPluginsInfo;
2137 
2138   browser_handler_map["GetBrowserInfo"] =
2139       &TestingAutomationProvider::GetBrowserInfo;
2140 
2141   browser_handler_map["GetNavigationInfo"] =
2142       &TestingAutomationProvider::GetNavigationInfo;
2143 
2144   browser_handler_map["PerformActionOnInfobar"] =
2145       &TestingAutomationProvider::PerformActionOnInfobar;
2146 
2147   browser_handler_map["GetHistoryInfo"] =
2148       &TestingAutomationProvider::GetHistoryInfo;
2149   browser_handler_map["AddHistoryItem"] =
2150       &TestingAutomationProvider::AddHistoryItem;
2151 
2152   browser_handler_map["GetOmniboxInfo"] =
2153       &TestingAutomationProvider::GetOmniboxInfo;
2154   browser_handler_map["SetOmniboxText"] =
2155       &TestingAutomationProvider::SetOmniboxText;
2156   browser_handler_map["OmniboxAcceptInput"] =
2157       &TestingAutomationProvider::OmniboxAcceptInput;
2158   browser_handler_map["OmniboxMovePopupSelection"] =
2159       &TestingAutomationProvider::OmniboxMovePopupSelection;
2160 
2161   browser_handler_map["GetInstantInfo"] =
2162       &TestingAutomationProvider::GetInstantInfo;
2163 
2164   browser_handler_map["LoadSearchEngineInfo"] =
2165       &TestingAutomationProvider::LoadSearchEngineInfo;
2166   browser_handler_map["GetSearchEngineInfo"] =
2167       &TestingAutomationProvider::GetSearchEngineInfo;
2168   browser_handler_map["AddOrEditSearchEngine"] =
2169       &TestingAutomationProvider::AddOrEditSearchEngine;
2170   browser_handler_map["PerformActionOnSearchEngine"] =
2171       &TestingAutomationProvider::PerformActionOnSearchEngine;
2172 
2173   browser_handler_map["GetPrefsInfo"] =
2174       &TestingAutomationProvider::GetPrefsInfo;
2175   browser_handler_map["SetPrefs"] = &TestingAutomationProvider::SetPrefs;
2176 
2177   browser_handler_map["SetWindowDimensions"] =
2178       &TestingAutomationProvider::SetWindowDimensions;
2179 
2180   browser_handler_map["GetDownloadsInfo"] =
2181       &TestingAutomationProvider::GetDownloadsInfo;
2182   browser_handler_map["WaitForAllDownloadsToComplete"] =
2183       &TestingAutomationProvider::WaitForDownloadsToComplete;
2184   browser_handler_map["PerformActionOnDownload"] =
2185       &TestingAutomationProvider::PerformActionOnDownload;
2186 
2187   browser_handler_map["GetInitialLoadTimes"] =
2188       &TestingAutomationProvider::GetInitialLoadTimes;
2189 
2190   browser_handler_map["SaveTabContents"] =
2191       &TestingAutomationProvider::SaveTabContents;
2192 
2193   browser_handler_map["ImportSettings"] =
2194       &TestingAutomationProvider::ImportSettings;
2195 
2196   browser_handler_map["AddSavedPassword"] =
2197       &TestingAutomationProvider::AddSavedPassword;
2198   browser_handler_map["RemoveSavedPassword"] =
2199       &TestingAutomationProvider::RemoveSavedPassword;
2200   browser_handler_map["GetSavedPasswords"] =
2201       &TestingAutomationProvider::GetSavedPasswords;
2202 
2203   browser_handler_map["ClearBrowsingData"] =
2204       &TestingAutomationProvider::ClearBrowsingData;
2205 
2206   browser_handler_map["GetBlockedPopupsInfo"] =
2207       &TestingAutomationProvider::GetBlockedPopupsInfo;
2208   browser_handler_map["UnblockAndLaunchBlockedPopup"] =
2209       &TestingAutomationProvider::UnblockAndLaunchBlockedPopup;
2210 
2211   // SetTheme() implemented using InstallExtension().
2212   browser_handler_map["GetThemeInfo"] =
2213       &TestingAutomationProvider::GetThemeInfo;
2214 
2215   // InstallExtension() present in pyauto.py.
2216   browser_handler_map["GetExtensionsInfo"] =
2217       &TestingAutomationProvider::GetExtensionsInfo;
2218   browser_handler_map["UninstallExtensionById"] =
2219       &TestingAutomationProvider::UninstallExtensionById;
2220 
2221   browser_handler_map["FindInPage"] = &TestingAutomationProvider::FindInPage;
2222 
2223   browser_handler_map["SelectTranslateOption"] =
2224       &TestingAutomationProvider::SelectTranslateOption;
2225   browser_handler_map["GetTranslateInfo"] =
2226       &TestingAutomationProvider::GetTranslateInfo;
2227 
2228   browser_handler_map["GetAutofillProfile"] =
2229       &TestingAutomationProvider::GetAutofillProfile;
2230   browser_handler_map["FillAutofillProfile"] =
2231       &TestingAutomationProvider::FillAutofillProfile;
2232 
2233   browser_handler_map["GetActiveNotifications"] =
2234       &TestingAutomationProvider::GetActiveNotifications;
2235   browser_handler_map["CloseNotification"] =
2236       &TestingAutomationProvider::CloseNotification;
2237   browser_handler_map["WaitForNotificationCount"] =
2238       &TestingAutomationProvider::WaitForNotificationCount;
2239 
2240   browser_handler_map["SignInToSync"] =
2241       &TestingAutomationProvider::SignInToSync;
2242   browser_handler_map["GetSyncInfo"] = &TestingAutomationProvider::GetSyncInfo;
2243   browser_handler_map["AwaitSyncCycleCompletion"] =
2244       &TestingAutomationProvider::AwaitSyncCycleCompletion;
2245   browser_handler_map["EnableSyncForDatatypes"] =
2246       &TestingAutomationProvider::EnableSyncForDatatypes;
2247   browser_handler_map["DisableSyncForDatatypes"] =
2248       &TestingAutomationProvider::DisableSyncForDatatypes;
2249 
2250   browser_handler_map["GetNTPInfo"] =
2251       &TestingAutomationProvider::GetNTPInfo;
2252   browser_handler_map["MoveNTPMostVisitedThumbnail"] =
2253       &TestingAutomationProvider::MoveNTPMostVisitedThumbnail;
2254   browser_handler_map["RemoveNTPMostVisitedThumbnail"] =
2255       &TestingAutomationProvider::RemoveNTPMostVisitedThumbnail;
2256   browser_handler_map["UnpinNTPMostVisitedThumbnail"] =
2257       &TestingAutomationProvider::UnpinNTPMostVisitedThumbnail;
2258   browser_handler_map["RestoreAllNTPMostVisitedThumbnails"] =
2259       &TestingAutomationProvider::RestoreAllNTPMostVisitedThumbnails;
2260 
2261   browser_handler_map["KillRendererProcess"] =
2262       &TestingAutomationProvider::KillRendererProcess;
2263 
2264   browser_handler_map["GetNTPThumbnailMode"] =
2265       &TestingAutomationProvider::GetNTPThumbnailMode;
2266   browser_handler_map["SetNTPThumbnailMode"] =
2267       &TestingAutomationProvider::SetNTPThumbnailMode;
2268   browser_handler_map["GetNTPMenuMode"] =
2269       &TestingAutomationProvider::GetNTPMenuMode;
2270   browser_handler_map["SetNTPMenuMode"] =
2271       &TestingAutomationProvider::SetNTPMenuMode;
2272 
2273   browser_handler_map["LaunchApp"] = &TestingAutomationProvider::LaunchApp;
2274   browser_handler_map["SetAppLaunchType"] =
2275       &TestingAutomationProvider::SetAppLaunchType;
2276 
2277   if (handler_map.find(std::string(command)) != handler_map.end()) {
2278     (this->*handler_map[command])(dict_value, reply_message);
2279   } else if (browser_handler_map.find(std::string(command)) !=
2280              browser_handler_map.end()) {
2281     Browser* browser = NULL;
2282     if (!browser_tracker_->ContainsHandle(handle) ||
2283         !(browser = browser_tracker_->GetResource(handle))) {
2284       AutomationJSONReply(this, reply_message).SendError("No browser object.");
2285       return;
2286     }
2287     (this->*browser_handler_map[command])(browser, dict_value, reply_message);
2288   } else {
2289     std::string error_string = "Unknown command. Options: ";
2290     for (std::map<std::string, JsonHandler>::const_iterator it =
2291          handler_map.begin(); it != handler_map.end(); ++it) {
2292       error_string += it->first + ", ";
2293     }
2294     for (std::map<std::string, BrowserJsonHandler>::const_iterator it =
2295          browser_handler_map.begin(); it != browser_handler_map.end(); ++it) {
2296       error_string += it->first + ", ";
2297     }
2298     AutomationJSONReply(this, reply_message).SendError(error_string);
2299   }
2300 }
2301 
2302 // Sample json input: { "command": "SetWindowDimensions",
2303 //                      "x": 20,         # optional
2304 //                      "y": 20,         # optional
2305 //                      "width": 800,    # optional
2306 //                      "height": 600 }  # optional
SetWindowDimensions(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)2307 void TestingAutomationProvider::SetWindowDimensions(
2308     Browser* browser,
2309     DictionaryValue* args,
2310     IPC::Message* reply_message) {
2311   gfx::Rect rect = browser->window()->GetRestoredBounds();
2312   int x, y, width, height;
2313   if (args->GetInteger("x", &x))
2314     rect.set_x(x);
2315   if (args->GetInteger("y", &y))
2316     rect.set_y(y);
2317   if (args->GetInteger("width", &width))
2318     rect.set_width(width);
2319   if (args->GetInteger("height", &height))
2320     rect.set_height(height);
2321   browser->window()->SetBounds(rect);
2322   AutomationJSONReply(this, reply_message).SendSuccess(NULL);
2323 }
2324 
GetInfobarsInfo(TabContents * tc)2325 ListValue* TestingAutomationProvider::GetInfobarsInfo(TabContents* tc) {
2326   // Each infobar may have different properties depending on the type.
2327   ListValue* infobars = new ListValue;
2328   for (size_t i = 0; i < tc->infobar_count(); ++i) {
2329     DictionaryValue* infobar_item = new DictionaryValue;
2330     InfoBarDelegate* infobar = tc->GetInfoBarDelegateAt(i);
2331     if (infobar->AsConfirmInfoBarDelegate()) {
2332       // Also covers ThemeInstalledInfoBarDelegate.
2333       infobar_item->SetString("type", "confirm_infobar");
2334       ConfirmInfoBarDelegate* confirm_infobar =
2335         infobar->AsConfirmInfoBarDelegate();
2336       infobar_item->SetString("text", confirm_infobar->GetMessageText());
2337       infobar_item->SetString("link_text", confirm_infobar->GetLinkText());
2338       ListValue* buttons_list = new ListValue;
2339       int buttons = confirm_infobar->GetButtons();
2340       if (buttons & ConfirmInfoBarDelegate::BUTTON_OK) {
2341         StringValue* button_label = new StringValue(
2342             confirm_infobar->GetButtonLabel(
2343               ConfirmInfoBarDelegate::BUTTON_OK));
2344         buttons_list->Append(button_label);
2345       }
2346       if (buttons & ConfirmInfoBarDelegate::BUTTON_CANCEL) {
2347         StringValue* button_label = new StringValue(
2348             confirm_infobar->GetButtonLabel(
2349               ConfirmInfoBarDelegate::BUTTON_CANCEL));
2350         buttons_list->Append(button_label);
2351       }
2352       infobar_item->Set("buttons", buttons_list);
2353     } else if (infobar->AsLinkInfoBarDelegate()) {
2354       infobar_item->SetString("type", "link_infobar");
2355       LinkInfoBarDelegate* link_infobar = infobar->AsLinkInfoBarDelegate();
2356       infobar_item->SetString("link_text", link_infobar->GetLinkText());
2357     } else if (infobar->AsTranslateInfoBarDelegate()) {
2358       infobar_item->SetString("type", "translate_infobar");
2359       TranslateInfoBarDelegate* translate_infobar =
2360           infobar->AsTranslateInfoBarDelegate();
2361       infobar_item->SetString("original_lang_code",
2362                               translate_infobar->GetOriginalLanguageCode());
2363       infobar_item->SetString("target_lang_code",
2364                               translate_infobar->GetTargetLanguageCode());
2365     } else if (infobar->AsExtensionInfoBarDelegate()) {
2366       infobar_item->SetString("type", "extension_infobar");
2367     } else {
2368       infobar_item->SetString("type", "unknown_infobar");
2369     }
2370     infobars->Append(infobar_item);
2371   }
2372   return infobars;
2373 }
2374 
2375 // Sample json input: { "command": "PerformActionOnInfobar",
2376 //                      "action": "dismiss",
2377 //                      "infobar_index": 0,
2378 //                      "tab_index": 0 }
2379 // Sample output: {}
PerformActionOnInfobar(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)2380 void TestingAutomationProvider::PerformActionOnInfobar(
2381     Browser* browser,
2382     DictionaryValue* args,
2383     IPC::Message* reply_message) {
2384   AutomationJSONReply reply(this, reply_message);
2385   int tab_index;
2386   int infobar_index_int;
2387   std::string action;
2388   if (!args->GetInteger("tab_index", &tab_index) ||
2389       !args->GetInteger("infobar_index", &infobar_index_int) ||
2390       !args->GetString("action", &action)) {
2391     reply.SendError("Invalid or missing args");
2392     return;
2393   }
2394   TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
2395   if (!tab_contents) {
2396     reply.SendError(StringPrintf("No such tab at index %d", tab_index));
2397     return;
2398   }
2399   InfoBarDelegate* infobar = NULL;
2400   size_t infobar_index = static_cast<size_t>(infobar_index_int);
2401   if (infobar_index >= tab_contents->infobar_count() ||
2402       !(infobar = tab_contents->GetInfoBarDelegateAt(infobar_index))) {
2403     reply.SendError(StringPrintf("No such infobar at index %" PRIuS,
2404                                  infobar_index));
2405     return;
2406   }
2407   if ("dismiss" == action) {
2408     infobar->InfoBarDismissed();
2409     tab_contents->RemoveInfoBar(infobar);
2410     reply.SendSuccess(NULL);
2411     return;
2412   }
2413   if ("accept" == action || "cancel" == action) {
2414     ConfirmInfoBarDelegate* confirm_infobar;
2415     if (!(confirm_infobar = infobar->AsConfirmInfoBarDelegate())) {
2416       reply.SendError("Not a confirm infobar");
2417       return;
2418     }
2419     if ("accept" == action) {
2420       if (confirm_infobar->Accept())
2421         tab_contents->RemoveInfoBar(infobar);
2422     } else if ("cancel" == action) {
2423       if (confirm_infobar->Cancel())
2424         tab_contents->RemoveInfoBar(infobar);
2425     }
2426     reply.SendSuccess(NULL);
2427     return;
2428   }
2429   reply.SendError("Invalid action");
2430 }
2431 
2432 namespace {
2433 
2434 // Task to get info about BrowserChildProcessHost. Must run on IO thread to
2435 // honor the semantics of BrowserChildProcessHost.
2436 // Used by AutomationProvider::GetBrowserInfo().
2437 class GetChildProcessHostInfoTask : public Task {
2438  public:
GetChildProcessHostInfoTask(base::WaitableEvent * event,ListValue * child_processes)2439   GetChildProcessHostInfoTask(base::WaitableEvent* event,
2440                               ListValue* child_processes)
2441     : event_(event),
2442       child_processes_(child_processes) {}
2443 
Run()2444   virtual void Run() {
2445     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
2446     for (BrowserChildProcessHost::Iterator iter; !iter.Done(); ++iter) {
2447       // Only add processes which are already started,
2448       // since we need their handle.
2449       if ((*iter)->handle() == base::kNullProcessHandle) {
2450         continue;
2451       }
2452       ChildProcessInfo* info = *iter;
2453       DictionaryValue* item = new DictionaryValue;
2454       item->SetString("name", WideToUTF16Hack(info->name()));
2455       item->SetString("type",
2456                       ChildProcessInfo::GetTypeNameInEnglish(info->type()));
2457       item->SetInteger("pid", base::GetProcId(info->handle()));
2458       child_processes_->Append(item);
2459     }
2460     event_->Signal();
2461   }
2462 
2463  private:
2464   base::WaitableEvent* const event_;  // weak
2465   ListValue* child_processes_;
2466 
2467   DISALLOW_COPY_AND_ASSIGN(GetChildProcessHostInfoTask);
2468 };
2469 
2470 }  // namespace
2471 
2472 // Sample json input: { "command": "GetBrowserInfo" }
2473 // Refer to GetBrowserInfo() in chrome/test/pyautolib/pyauto.py for
2474 // sample json output.
GetBrowserInfo(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)2475 void TestingAutomationProvider::GetBrowserInfo(
2476     Browser* browser,
2477     DictionaryValue* args,
2478     IPC::Message* reply_message) {
2479   base::ThreadRestrictions::ScopedAllowIO allow_io;  // needed for PathService
2480   DictionaryValue* properties = new DictionaryValue;
2481   properties->SetString("ChromeVersion", chrome::kChromeVersion);
2482   properties->SetString("BrowserProcessExecutableName",
2483                         chrome::kBrowserProcessExecutableName);
2484   properties->SetString("HelperProcessExecutableName",
2485                         chrome::kHelperProcessExecutableName);
2486   properties->SetString("BrowserProcessExecutablePath",
2487                         chrome::kBrowserProcessExecutablePath);
2488   properties->SetString("HelperProcessExecutablePath",
2489                         chrome::kHelperProcessExecutablePath);
2490   properties->SetString("command_line_string",
2491       CommandLine::ForCurrentProcess()->command_line_string());
2492   FilePath dumps_path;
2493   PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path);
2494   properties->SetString("DIR_CRASH_DUMPS", dumps_path.value());
2495 
2496   std::string branding;
2497 #if defined(GOOGLE_CHROME_BUILD)
2498   branding = "Google Chrome";
2499 #elif defined(CHROMIUM_BUILD)
2500   branding = "Chromium";
2501 #else
2502   branding = "Unknown Branding";
2503 #endif
2504   properties->SetString("branding", branding);
2505 
2506   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
2507   return_value->Set("properties", properties);
2508 
2509   return_value->SetInteger("browser_pid", base::GetCurrentProcId());
2510   // Add info about all windows in a list of dictionaries, one dictionary
2511   // item per window.
2512   ListValue* windows = new ListValue;
2513   int windex = 0;
2514   for (BrowserList::const_iterator it = BrowserList::begin();
2515        it != BrowserList::end();
2516        ++it, ++windex) {
2517     DictionaryValue* browser_item = new DictionaryValue;
2518     browser = *it;
2519     browser_item->SetInteger("index", windex);
2520     // Window properties
2521     gfx::Rect rect = browser->window()->GetRestoredBounds();
2522     browser_item->SetInteger("x", rect.x());
2523     browser_item->SetInteger("y", rect.y());
2524     browser_item->SetInteger("width", rect.width());
2525     browser_item->SetInteger("height", rect.height());
2526     browser_item->SetBoolean("fullscreen",
2527                              browser->window()->IsFullscreen());
2528     browser_item->SetInteger("selected_tab", browser->active_index());
2529     browser_item->SetBoolean("incognito",
2530                              browser->profile()->IsOffTheRecord());
2531     // For each window, add info about all tabs in a list of dictionaries,
2532     // one dictionary item per tab.
2533     ListValue* tabs = new ListValue;
2534     for (int i = 0; i < browser->tab_count(); ++i) {
2535       TabContents* tc = browser->GetTabContentsAt(i);
2536       DictionaryValue* tab = new DictionaryValue;
2537       tab->SetInteger("index", i);
2538       tab->SetString("url", tc->GetURL().spec());
2539       tab->SetInteger("renderer_pid",
2540                       base::GetProcId(tc->GetRenderProcessHost()->GetHandle()));
2541       tab->Set("infobars", GetInfobarsInfo(tc));
2542       tab->SetBoolean("pinned", browser->IsTabPinned(i));
2543       tabs->Append(tab);
2544     }
2545     browser_item->Set("tabs", tabs);
2546 
2547     windows->Append(browser_item);
2548   }
2549   return_value->Set("windows", windows);
2550 
2551   return_value->SetString("child_process_path",
2552                           ChildProcessHost::GetChildPath(true).value());
2553   // Child processes are the processes for plugins and other workers.
2554   // Add all child processes in a list of dictionaries, one dictionary item
2555   // per child process.
2556   ListValue* child_processes = new ListValue;
2557   base::WaitableEvent event(true   /* manual reset */,
2558                             false  /* not initially signaled */);
2559   CHECK(BrowserThread::PostTask(
2560       BrowserThread::IO, FROM_HERE,
2561       new GetChildProcessHostInfoTask(&event, child_processes)));
2562   event.Wait();
2563   return_value->Set("child_processes", child_processes);
2564 
2565   // Add all extension processes in a list of dictionaries, one dictionary
2566   // item per extension process.
2567   ListValue* extension_processes = new ListValue;
2568   ProfileManager* profile_manager = g_browser_process->profile_manager();
2569   std::vector<Profile*> profiles(profile_manager->GetLoadedProfiles());
2570   for (size_t i = 0; i < profiles.size(); ++i) {
2571     ExtensionProcessManager* process_manager =
2572         profiles[i]->GetExtensionProcessManager();
2573     if (!process_manager)
2574       continue;
2575     ExtensionProcessManager::const_iterator jt;
2576     for (jt = process_manager->begin(); jt != process_manager->end(); ++jt) {
2577       ExtensionHost* ex_host = *jt;
2578       // Don't add dead extension processes.
2579       if (!ex_host->IsRenderViewLive())
2580         continue;
2581       DictionaryValue* item = new DictionaryValue;
2582       item->SetString("name", ex_host->extension()->name());
2583       item->SetInteger(
2584           "pid",
2585           base::GetProcId(ex_host->render_process_host()->GetHandle()));
2586       extension_processes->Append(item);
2587     }
2588   }
2589   return_value->Set("extension_processes", extension_processes);
2590   AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
2591 }
2592 
2593 // Sample json input: { "command": "GetNavigationInfo" }
2594 // Refer to GetNavigationInfo() in chrome/test/pyautolib/pyauto.py for
2595 // sample json output.
GetNavigationInfo(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)2596 void TestingAutomationProvider::GetNavigationInfo(
2597     Browser* browser,
2598     DictionaryValue* args,
2599     IPC::Message* reply_message) {
2600   AutomationJSONReply reply(this, reply_message);
2601   int tab_index;
2602   TabContents* tab_contents = NULL;
2603   if (!args->GetInteger("tab_index", &tab_index) ||
2604       !(tab_contents = browser->GetTabContentsAt(tab_index))) {
2605     reply.SendError("tab_index missing or invalid.");
2606     return;
2607   }
2608   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
2609   const NavigationController& controller = tab_contents->controller();
2610   NavigationEntry* nav_entry = controller.GetActiveEntry();
2611   DCHECK(nav_entry);
2612 
2613   // Security info.
2614   DictionaryValue* ssl = new DictionaryValue;
2615   std::map<SecurityStyle, std::string> style_to_string;
2616   style_to_string[SECURITY_STYLE_UNKNOWN] = "SECURITY_STYLE_UNKNOWN";
2617   style_to_string[SECURITY_STYLE_UNAUTHENTICATED] =
2618       "SECURITY_STYLE_UNAUTHENTICATED";
2619   style_to_string[SECURITY_STYLE_AUTHENTICATION_BROKEN] =
2620       "SECURITY_STYLE_AUTHENTICATION_BROKEN";
2621   style_to_string[SECURITY_STYLE_AUTHENTICATED] =
2622       "SECURITY_STYLE_AUTHENTICATED";
2623 
2624   NavigationEntry::SSLStatus ssl_status = nav_entry->ssl();
2625   ssl->SetString("security_style",
2626                  style_to_string[ssl_status.security_style()]);
2627   ssl->SetBoolean("ran_insecure_content", ssl_status.ran_insecure_content());
2628   ssl->SetBoolean("displayed_insecure_content",
2629                   ssl_status.displayed_insecure_content());
2630   return_value->Set("ssl", ssl);
2631 
2632   // Page type.
2633   std::map<PageType, std::string> pagetype_to_string;
2634   pagetype_to_string[NORMAL_PAGE] = "NORMAL_PAGE";
2635   pagetype_to_string[ERROR_PAGE] = "ERROR_PAGE";
2636   pagetype_to_string[INTERSTITIAL_PAGE] = "INTERSTITIAL_PAGE";
2637   return_value->SetString("page_type",
2638                           pagetype_to_string[nav_entry->page_type()]);
2639 
2640   return_value->SetString("favicon_url", nav_entry->favicon().url().spec());
2641   reply.SendSuccess(return_value.get());
2642 }
2643 
2644 // Sample json input: { "command": "GetHistoryInfo",
2645 //                      "search_text": "some text" }
2646 // Refer chrome/test/pyautolib/history_info.py for sample json output.
GetHistoryInfo(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)2647 void TestingAutomationProvider::GetHistoryInfo(Browser* browser,
2648                                                DictionaryValue* args,
2649                                                IPC::Message* reply_message) {
2650   consumer_.CancelAllRequests();
2651 
2652   string16 search_text;
2653   args->GetString("search_text", &search_text);
2654 
2655   // Fetch history.
2656   HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
2657   history::QueryOptions options;
2658   // The observer owns itself.  It deletes itself after it fetches history.
2659   AutomationProviderHistoryObserver* history_observer =
2660       new AutomationProviderHistoryObserver(this, reply_message);
2661   hs->QueryHistory(
2662       search_text,
2663       options,
2664       &consumer_,
2665       NewCallback(history_observer,
2666                   &AutomationProviderHistoryObserver::HistoryQueryComplete));
2667 }
2668 
2669 // Sample json input: { "command": "AddHistoryItem",
2670 //                      "item": { "URL": "http://www.google.com",
2671 //                                "title": "Google",   # optional
2672 //                                "time": 12345        # optional (time_t)
2673 //                               } }
2674 // Refer chrome/test/pyautolib/pyauto.py for details on input.
AddHistoryItem(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)2675 void TestingAutomationProvider::AddHistoryItem(Browser* browser,
2676                                                DictionaryValue* args,
2677                                                IPC::Message* reply_message) {
2678   DictionaryValue* item = NULL;
2679   args->GetDictionary("item", &item);
2680   string16 url_text;
2681   string16 title;
2682   base::Time time = base::Time::Now();
2683   AutomationJSONReply reply(this, reply_message);
2684 
2685   if (!item->GetString("url", &url_text)) {
2686     reply.SendError("bad args (no URL in dict?)");
2687     return;
2688   }
2689   GURL gurl(url_text);
2690   item->GetString("title", &title);  // Don't care if it fails.
2691   int it;
2692   double dt;
2693   if (item->GetInteger("time", &it))
2694     time = base::Time::FromTimeT(it);
2695   else if (item->GetDouble("time", &dt))
2696     time = base::Time::FromDoubleT(dt);
2697 
2698   // Ideas for "dummy" values (e.g. id_scope) came from
2699   // chrome/browser/autocomplete/history_contents_provider_unittest.cc
2700   HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
2701   const void* id_scope = reinterpret_cast<void*>(1);
2702   hs->AddPage(gurl, time,
2703               id_scope,
2704               0,
2705               GURL(),
2706               PageTransition::LINK,
2707               history::RedirectList(),
2708               history::SOURCE_BROWSED,
2709               false);
2710   if (title.length())
2711     hs->SetPageTitle(gurl, title);
2712   reply.SendSuccess(NULL);
2713 }
2714 
2715 // Sample json input: { "command": "GetDownloadsInfo" }
2716 // Refer chrome/test/pyautolib/download_info.py for sample json output.
GetDownloadsInfo(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)2717 void TestingAutomationProvider::GetDownloadsInfo(Browser* browser,
2718                                                  DictionaryValue* args,
2719                                                  IPC::Message* reply_message) {
2720   AutomationJSONReply reply(this, reply_message);
2721   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
2722   ListValue* list_of_downloads = new ListValue;
2723 
2724   if (browser->profile()->HasCreatedDownloadManager()) {
2725     std::vector<DownloadItem*> downloads;
2726     browser->profile()->GetDownloadManager()->
2727         GetAllDownloads(FilePath(), &downloads);
2728 
2729     for (std::vector<DownloadItem*>::iterator it = downloads.begin();
2730          it != downloads.end();
2731          it++) {  // Fill info about each download item.
2732       list_of_downloads->Append(GetDictionaryFromDownloadItem(*it));
2733     }
2734   }
2735   return_value->Set("downloads", list_of_downloads);
2736   reply.SendSuccess(return_value.get());
2737 }
2738 
WaitForDownloadsToComplete(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)2739 void TestingAutomationProvider::WaitForDownloadsToComplete(
2740     Browser* browser,
2741     DictionaryValue* args,
2742     IPC::Message* reply_message) {
2743 
2744   // Look for a quick return.
2745   if (!browser->profile()->HasCreatedDownloadManager()) {
2746     // No download manager.
2747     AutomationJSONReply(this, reply_message).SendSuccess(NULL);
2748     return;
2749   }
2750   std::vector<DownloadItem*> downloads;
2751   browser->profile()->GetDownloadManager()->
2752       GetCurrentDownloads(FilePath(), &downloads);
2753   if (downloads.empty()) {
2754     AutomationJSONReply(this, reply_message).SendSuccess(NULL);
2755     return;
2756   }
2757   // The observer owns itself.  When the last observed item pings, it
2758   // deletes itself.
2759   AutomationProviderDownloadItemObserver* item_observer =
2760       new AutomationProviderDownloadItemObserver(
2761           this, reply_message, downloads.size());
2762   for (std::vector<DownloadItem*>::iterator i = downloads.begin();
2763        i != downloads.end();
2764        i++) {
2765     (*i)->AddObserver(item_observer);
2766   }
2767 }
2768 
2769 namespace {
2770 
GetDownloadItemFromId(int id,DownloadManager * download_manager)2771 DownloadItem* GetDownloadItemFromId(int id, DownloadManager* download_manager) {
2772   std::vector<DownloadItem*> downloads;
2773   download_manager->GetAllDownloads(FilePath(), &downloads);
2774   DownloadItem* selected_item = NULL;
2775 
2776   for (std::vector<DownloadItem*>::iterator it = downloads.begin();
2777        it != downloads.end();
2778        it++) {
2779     DownloadItem* curr_item = *it;
2780     if (curr_item->id() == id) {
2781       selected_item = curr_item;
2782       break;
2783     }
2784   }
2785   return selected_item;
2786 }
2787 
2788 }  // namespace
2789 
2790 // See PerformActionOnDownload() in chrome/test/pyautolib/pyauto.py for sample
2791 // json input and output.
PerformActionOnDownload(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)2792 void TestingAutomationProvider::PerformActionOnDownload(
2793     Browser* browser,
2794     DictionaryValue* args,
2795     IPC::Message* reply_message) {
2796   int id;
2797   std::string action;
2798 
2799   if (!browser->profile()->HasCreatedDownloadManager()) {
2800     AutomationJSONReply(this, reply_message).SendError("No download manager.");
2801     return;
2802   }
2803   if (!args->GetInteger("id", &id) || !args->GetString("action", &action)) {
2804     AutomationJSONReply(this, reply_message)
2805         .SendError("Must include int id and string action.");
2806     return;
2807   }
2808 
2809   DownloadManager* download_manager = browser->profile()->GetDownloadManager();
2810   DownloadItem* selected_item = GetDownloadItemFromId(id, download_manager);
2811   if (!selected_item) {
2812     AutomationJSONReply(this, reply_message)
2813         .SendError(StringPrintf("No download with an id of %d\n", id));
2814     return;
2815   }
2816 
2817   if (action == "open") {
2818     selected_item->AddObserver(
2819         new AutomationProviderDownloadUpdatedObserver(
2820             this, reply_message, true));
2821     selected_item->OpenDownload();
2822   } else if (action == "toggle_open_files_like_this") {
2823     selected_item->OpenFilesBasedOnExtension(
2824         !selected_item->ShouldOpenFileBasedOnExtension());
2825     AutomationJSONReply(this, reply_message).SendSuccess(NULL);
2826   } else if (action == "remove") {
2827     download_manager->AddObserver(
2828         new AutomationProviderDownloadModelChangedObserver(
2829             this, reply_message, download_manager));
2830     selected_item->Remove();
2831   } else if (action == "decline_dangerous_download") {
2832     download_manager->AddObserver(
2833         new AutomationProviderDownloadModelChangedObserver(
2834             this, reply_message, download_manager));
2835     selected_item->Delete(DownloadItem::DELETE_DUE_TO_USER_DISCARD);
2836   } else if (action == "save_dangerous_download") {
2837     selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
2838         this, reply_message, false));
2839     selected_item->DangerousDownloadValidated();
2840   } else if (action == "toggle_pause") {
2841     selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
2842         this, reply_message, false));
2843     // This will still return if download has already completed.
2844     selected_item->TogglePause();
2845   } else if (action == "cancel") {
2846     selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
2847         this, reply_message, false));
2848     selected_item->Cancel(true);
2849   } else {
2850     AutomationJSONReply(this, reply_message)
2851         .SendError(StringPrintf("Invalid action '%s' given.", action.c_str()));
2852   }
2853 }
2854 
2855 // Sample JSON input { "command": "LoadSearchEngineInfo" }
LoadSearchEngineInfo(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)2856 void TestingAutomationProvider::LoadSearchEngineInfo(
2857     Browser* browser,
2858     DictionaryValue* args,
2859     IPC::Message* reply_message) {
2860   TemplateURLModel* url_model(profile_->GetTemplateURLModel());
2861   if (url_model->loaded()) {
2862     AutomationJSONReply(this, reply_message).SendSuccess(NULL);
2863     return;
2864   }
2865   url_model->AddObserver(new AutomationProviderSearchEngineObserver(
2866       this, reply_message));
2867   url_model->Load();
2868 }
2869 
2870 // Sample JSON input { "command": "GetSearchEngineInfo" }
2871 // Refer to pyauto.py for sample output.
GetSearchEngineInfo(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)2872 void TestingAutomationProvider::GetSearchEngineInfo(
2873     Browser* browser,
2874     DictionaryValue* args,
2875     IPC::Message* reply_message) {
2876   TemplateURLModel* url_model(profile_->GetTemplateURLModel());
2877   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
2878   ListValue* search_engines = new ListValue;
2879   std::vector<const TemplateURL*> template_urls = url_model->GetTemplateURLs();
2880   for (std::vector<const TemplateURL*>::const_iterator it =
2881        template_urls.begin(); it != template_urls.end(); ++it) {
2882     DictionaryValue* search_engine = new DictionaryValue;
2883     search_engine->SetString("short_name", UTF16ToUTF8((*it)->short_name()));
2884     search_engine->SetString("description", UTF16ToUTF8((*it)->description()));
2885     search_engine->SetString("keyword", UTF16ToUTF8((*it)->keyword()));
2886     search_engine->SetBoolean("in_default_list", (*it)->ShowInDefaultList());
2887     search_engine->SetBoolean("is_default",
2888         (*it) == url_model->GetDefaultSearchProvider());
2889     search_engine->SetBoolean("is_valid", (*it)->url()->IsValid());
2890     search_engine->SetBoolean("supports_replacement",
2891                               (*it)->url()->SupportsReplacement());
2892     search_engine->SetString("url", (*it)->url()->url());
2893     search_engine->SetString("host", (*it)->url()->GetHost());
2894     search_engine->SetString("path", (*it)->url()->GetPath());
2895     search_engine->SetString("display_url",
2896                              UTF16ToUTF8((*it)->url()->DisplayURL()));
2897     search_engines->Append(search_engine);
2898   }
2899   return_value->Set("search_engines", search_engines);
2900   AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
2901 }
2902 
2903 // Refer to pyauto.py for sample JSON input.
AddOrEditSearchEngine(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)2904 void TestingAutomationProvider::AddOrEditSearchEngine(
2905     Browser* browser,
2906     DictionaryValue* args,
2907     IPC::Message* reply_message) {
2908   TemplateURLModel* url_model(profile_->GetTemplateURLModel());
2909   const TemplateURL* template_url;
2910   string16 new_title;
2911   string16 new_keyword;
2912   std::string new_url;
2913   std::string keyword;
2914   if (!args->GetString("new_title", &new_title) ||
2915       !args->GetString("new_keyword", &new_keyword) ||
2916       !args->GetString("new_url", &new_url)) {
2917     AutomationJSONReply(this, reply_message)
2918         .SendError("One or more inputs invalid");
2919     return;
2920   }
2921   std::string new_ref_url = TemplateURLRef::DisplayURLToURLRef(
2922       UTF8ToUTF16(new_url));
2923   scoped_ptr<KeywordEditorController> controller(
2924       new KeywordEditorController(profile_));
2925   if (args->GetString("keyword", &keyword)) {
2926     template_url = url_model->GetTemplateURLForKeyword(UTF8ToUTF16(keyword));
2927     if (template_url == NULL) {
2928       AutomationJSONReply(this, reply_message)
2929           .SendError(StringPrintf("No match for keyword: %s", keyword.c_str()));
2930       return;
2931     }
2932     url_model->AddObserver(new AutomationProviderSearchEngineObserver(
2933         this, reply_message));
2934     controller->ModifyTemplateURL(template_url, new_title, new_keyword,
2935                                   new_ref_url);
2936   } else {
2937     url_model->AddObserver(new AutomationProviderSearchEngineObserver(
2938         this, reply_message));
2939     controller->AddTemplateURL(new_title, new_keyword, new_ref_url);
2940   }
2941 }
2942 
2943 // Sample json input: { "command": "PerformActionOnSearchEngine",
2944 //                      "keyword": keyword, "action": action }
PerformActionOnSearchEngine(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)2945 void TestingAutomationProvider::PerformActionOnSearchEngine(
2946     Browser* browser,
2947     DictionaryValue* args,
2948     IPC::Message* reply_message) {
2949   TemplateURLModel* url_model(profile_->GetTemplateURLModel());
2950   std::string keyword;
2951   std::string action;
2952   if (!args->GetString("keyword", &keyword) ||
2953       !args->GetString("action", &action)) {
2954     AutomationJSONReply(this, reply_message).SendError(
2955         "One or more inputs invalid");
2956     return;
2957   }
2958   const TemplateURL* template_url(
2959       url_model->GetTemplateURLForKeyword(UTF8ToUTF16(keyword)));
2960   if (template_url == NULL) {
2961     AutomationJSONReply(this, reply_message)
2962         .SendError(StringPrintf("No match for keyword: %s", keyword.c_str()));
2963     return;
2964   }
2965   if (action == "delete") {
2966     url_model->AddObserver(new AutomationProviderSearchEngineObserver(
2967       this, reply_message));
2968     url_model->Remove(template_url);
2969   } else if (action == "default") {
2970     url_model->AddObserver(new AutomationProviderSearchEngineObserver(
2971       this, reply_message));
2972     url_model->SetDefaultSearchProvider(template_url);
2973   } else {
2974     AutomationJSONReply(this, reply_message)
2975         .SendError(StringPrintf("Invalid action: %s", action.c_str()));
2976   }
2977 }
2978 
2979 // Sample json input: { "command": "GetPrefsInfo" }
2980 // Refer chrome/test/pyautolib/prefs_info.py for sample json output.
GetPrefsInfo(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)2981 void TestingAutomationProvider::GetPrefsInfo(Browser* browser,
2982                                              DictionaryValue* args,
2983                                              IPC::Message* reply_message) {
2984   DictionaryValue* items = profile_->GetPrefs()->GetPreferenceValues();
2985 
2986   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
2987   return_value->Set("prefs", items);  // return_value owns items.
2988   AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
2989 }
2990 
2991 // Sample json input: { "command": "SetPrefs", "path": path, "value": value }
SetPrefs(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)2992 void TestingAutomationProvider::SetPrefs(Browser* browser,
2993                                          DictionaryValue* args,
2994                                          IPC::Message* reply_message) {
2995   std::string path;
2996   Value* val;
2997   AutomationJSONReply reply(this, reply_message);
2998   if (args->GetString("path", &path) && args->Get("value", &val)) {
2999     PrefService* pref_service = profile_->GetPrefs();
3000     const PrefService::Preference* pref =
3001         pref_service->FindPreference(path.c_str());
3002     if (!pref) {  // Not a registered pref.
3003       reply.SendError("pref not registered.");
3004       return;
3005     } else if (pref->IsManaged()) {  // Do not attempt to change a managed pref.
3006       reply.SendError("pref is managed. cannot be changed.");
3007       return;
3008     } else {  // Set the pref.
3009       pref_service->Set(path.c_str(), *val);
3010     }
3011   } else {
3012     reply.SendError("no pref path or value given.");
3013     return;
3014   }
3015 
3016   reply.SendSuccess(NULL);
3017 }
3018 
3019 // Sample json input: { "command": "GetOmniboxInfo" }
3020 // Refer chrome/test/pyautolib/omnibox_info.py for sample json output.
GetOmniboxInfo(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3021 void TestingAutomationProvider::GetOmniboxInfo(Browser* browser,
3022                                                DictionaryValue* args,
3023                                                IPC::Message* reply_message) {
3024   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
3025 
3026   LocationBar* loc_bar = browser->window()->GetLocationBar();
3027   AutocompleteEditView* edit_view = loc_bar->location_entry();
3028   AutocompleteEditModel* model = edit_view->model();
3029 
3030   // Fill up matches.
3031   ListValue* matches = new ListValue;
3032   const AutocompleteResult& result = model->result();
3033   for (AutocompleteResult::const_iterator i = result.begin();
3034        i != result.end(); ++i) {
3035     const AutocompleteMatch& match = *i;
3036     DictionaryValue* item = new DictionaryValue;  // owned by return_value
3037     item->SetString("type", AutocompleteMatch::TypeToString(match.type));
3038     item->SetBoolean("starred", match.starred);
3039     item->SetString("destination_url", match.destination_url.spec());
3040     item->SetString("contents", match.contents);
3041     item->SetString("description", match.description);
3042     matches->Append(item);
3043   }
3044   return_value->Set("matches", matches);
3045 
3046   // Fill up other properties.
3047   DictionaryValue* properties = new DictionaryValue;  // owned by return_value
3048   properties->SetBoolean("has_focus", model->has_focus());
3049   properties->SetBoolean("query_in_progress",
3050                          !model->autocomplete_controller()->done());
3051   properties->SetString("keyword", model->keyword());
3052   properties->SetString("text", edit_view->GetText());
3053   return_value->Set("properties", properties);
3054 
3055   AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
3056 }
3057 
3058 // Sample json input: { "command": "SetOmniboxText",
3059 //                      "text": "goog" }
SetOmniboxText(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3060 void TestingAutomationProvider::SetOmniboxText(Browser* browser,
3061                                                DictionaryValue* args,
3062                                                IPC::Message* reply_message) {
3063   string16 text;
3064   AutomationJSONReply reply(this, reply_message);
3065   if (!args->GetString("text", &text)) {
3066     reply.SendError("text missing");
3067     return;
3068   }
3069   browser->FocusLocationBar();
3070   LocationBar* loc_bar = browser->window()->GetLocationBar();
3071   AutocompleteEditView* edit_view = loc_bar->location_entry();
3072   edit_view->model()->OnSetFocus(false);
3073   edit_view->SetUserText(text);
3074   reply.SendSuccess(NULL);
3075 }
3076 
3077 // Sample json input: { "command": "OmniboxMovePopupSelection",
3078 //                      "count": 1 }
3079 // Negative count implies up, positive implies down. Count values will be
3080 // capped by the size of the popup list.
OmniboxMovePopupSelection(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3081 void TestingAutomationProvider::OmniboxMovePopupSelection(
3082     Browser* browser,
3083     DictionaryValue* args,
3084     IPC::Message* reply_message) {
3085   int count;
3086   AutomationJSONReply reply(this, reply_message);
3087   if (!args->GetInteger("count", &count)) {
3088     reply.SendError("count missing");
3089     return;
3090   }
3091   LocationBar* loc_bar = browser->window()->GetLocationBar();
3092   AutocompleteEditModel* model = loc_bar->location_entry()->model();
3093   model->OnUpOrDownKeyPressed(count);
3094   reply.SendSuccess(NULL);
3095 }
3096 
3097 // Sample json input: { "command": "OmniboxAcceptInput" }
OmniboxAcceptInput(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3098 void TestingAutomationProvider::OmniboxAcceptInput(
3099     Browser* browser,
3100     DictionaryValue* args,
3101     IPC::Message* reply_message) {
3102   NavigationController& controller =
3103       browser->GetSelectedTabContents()->controller();
3104   new OmniboxAcceptNotificationObserver(&controller, this, reply_message);
3105   browser->window()->GetLocationBar()->AcceptInput();
3106 }
3107 
3108 // Sample json input: { "command": "GetInstantInfo" }
GetInstantInfo(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3109 void TestingAutomationProvider::GetInstantInfo(Browser* browser,
3110                                                DictionaryValue* args,
3111                                                IPC::Message* reply_message) {
3112   DictionaryValue* info = new DictionaryValue;
3113   if (browser->instant()) {
3114     InstantController* instant = browser->instant();
3115     info->SetBoolean("enabled", true);
3116     info->SetBoolean("showing", instant->IsShowingInstant());
3117     info->SetBoolean("active", instant->is_active());
3118     info->SetBoolean("current", instant->IsCurrent());
3119     if (instant->GetPreviewContents() &&
3120         instant->GetPreviewContents()->tab_contents()) {
3121       TabContents* contents = instant->GetPreviewContents()->tab_contents();
3122       info->SetBoolean("loading", contents->is_loading());
3123       info->SetString("location", contents->GetURL().spec());
3124       info->SetString("title", contents->GetTitle());
3125     }
3126   } else {
3127     info->SetBoolean("enabled", false);
3128   }
3129   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
3130   return_value->Set("instant", info);
3131   AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
3132 }
3133 
3134 // Sample json input: { "command": "GetInitialLoadTimes" }
3135 // Refer to InitialLoadObserver::GetTimingInformation() for sample output.
GetInitialLoadTimes(Browser *,DictionaryValue *,IPC::Message * reply_message)3136 void TestingAutomationProvider::GetInitialLoadTimes(
3137     Browser*,
3138     DictionaryValue*,
3139     IPC::Message* reply_message) {
3140   scoped_ptr<DictionaryValue> return_value(
3141       initial_load_observer_->GetTimingInformation());
3142 
3143   std::string json_return;
3144   base::JSONWriter::Write(return_value.get(), false, &json_return);
3145   AutomationMsg_SendJSONRequest::WriteReplyParams(
3146       reply_message, json_return, true);
3147   Send(reply_message);
3148 }
3149 
3150 // Sample json input: { "command": "GetPluginsInfo" }
3151 // Refer chrome/test/pyautolib/plugins_info.py for sample json output.
GetPluginsInfo(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3152 void TestingAutomationProvider::GetPluginsInfo(
3153     Browser* browser,
3154     DictionaryValue* args,
3155     IPC::Message* reply_message) {
3156   std::vector<webkit::npapi::WebPluginInfo> plugins;
3157   webkit::npapi::PluginList::Singleton()->GetPlugins(false, &plugins);
3158   ListValue* items = new ListValue;
3159   for (std::vector<webkit::npapi::WebPluginInfo>::const_iterator it =
3160            plugins.begin();
3161        it != plugins.end();
3162        ++it) {
3163     DictionaryValue* item = new DictionaryValue;
3164     item->SetString("name", it->name);
3165     item->SetString("path", it->path.value());
3166     item->SetString("version", it->version);
3167     item->SetString("desc", it->desc);
3168     item->SetBoolean("enabled", webkit::npapi::IsPluginEnabled(*it));
3169     // Add info about mime types.
3170     ListValue* mime_types = new ListValue();
3171     for (std::vector<webkit::npapi::WebPluginMimeType>::const_iterator type_it =
3172              it->mime_types.begin();
3173          type_it != it->mime_types.end();
3174          ++type_it) {
3175       DictionaryValue* mime_type = new DictionaryValue();
3176       mime_type->SetString("mimeType", type_it->mime_type);
3177       mime_type->SetString("description", type_it->description);
3178 
3179       ListValue* file_extensions = new ListValue();
3180       for (std::vector<std::string>::const_iterator ext_it =
3181                type_it->file_extensions.begin();
3182            ext_it != type_it->file_extensions.end();
3183            ++ext_it) {
3184         file_extensions->Append(new StringValue(*ext_it));
3185       }
3186       mime_type->Set("fileExtensions", file_extensions);
3187 
3188       mime_types->Append(mime_type);
3189     }
3190     item->Set("mimeTypes", mime_types);
3191     items->Append(item);
3192   }
3193   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
3194   return_value->Set("plugins", items);  // return_value owns items.
3195 
3196   AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
3197 }
3198 
3199 // Sample json input:
3200 //    { "command": "EnablePlugin",
3201 //      "path": "/Library/Internet Plug-Ins/Flash Player.plugin" }
EnablePlugin(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3202 void TestingAutomationProvider::EnablePlugin(Browser* browser,
3203                                              DictionaryValue* args,
3204                                              IPC::Message* reply_message) {
3205   FilePath::StringType path;
3206   AutomationJSONReply reply(this, reply_message);
3207   if (!args->GetString("path", &path)) {
3208     reply.SendError("path not specified.");
3209     return;
3210   } else if (!webkit::npapi::PluginList::Singleton()->EnablePlugin(
3211         FilePath(path))) {
3212     reply.SendError(StringPrintf("Could not enable plugin for path %s.",
3213                                  path.c_str()));
3214     return;
3215   }
3216   reply.SendSuccess(NULL);
3217 }
3218 
3219 // Sample json input:
3220 //    { "command": "DisablePlugin",
3221 //      "path": "/Library/Internet Plug-Ins/Flash Player.plugin" }
DisablePlugin(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3222 void TestingAutomationProvider::DisablePlugin(Browser* browser,
3223                                               DictionaryValue* args,
3224                                               IPC::Message* reply_message) {
3225   FilePath::StringType path;
3226   AutomationJSONReply reply(this, reply_message);
3227   if (!args->GetString("path", &path)) {
3228     reply.SendError("path not specified.");
3229     return;
3230   } else if (!webkit::npapi::PluginList::Singleton()->DisablePlugin(
3231         FilePath(path))) {
3232     reply.SendError(StringPrintf("Could not disable plugin for path %s.",
3233                                  path.c_str()));
3234     return;
3235   }
3236   reply.SendSuccess(NULL);
3237 }
3238 
3239 // Sample json input:
3240 //    { "command": "SaveTabContents",
3241 //      "tab_index": 0,
3242 //      "filename": <a full pathname> }
3243 // Sample json output:
3244 //    {}
SaveTabContents(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3245 void TestingAutomationProvider::SaveTabContents(
3246     Browser* browser,
3247     DictionaryValue* args,
3248     IPC::Message* reply_message) {
3249   int tab_index = 0;
3250   FilePath::StringType filename;
3251   FilePath::StringType parent_directory;
3252   TabContentsWrapper* tab_contents = NULL;
3253 
3254   if (!args->GetInteger("tab_index", &tab_index) ||
3255       !args->GetString("filename", &filename)) {
3256     AutomationJSONReply(this, reply_message)
3257         .SendError("tab_index or filename param missing");
3258     return;
3259   } else {
3260     tab_contents = browser->GetTabContentsWrapperAt(tab_index);
3261     if (!tab_contents) {
3262       AutomationJSONReply(this, reply_message).SendError("no tab at tab_index");
3263       return;
3264     }
3265   }
3266   // We're doing a SAVE_AS_ONLY_HTML so the the directory path isn't
3267   // used.  Nevertheless, SavePackage requires it be valid.  Sigh.
3268   parent_directory = FilePath(filename).DirName().value();
3269   if (!tab_contents->download_tab_helper()->SavePage(
3270           FilePath(filename),
3271           FilePath(parent_directory),
3272           SavePackage::SAVE_AS_ONLY_HTML)) {
3273     AutomationJSONReply(this, reply_message).SendError(
3274         "Could not initiate SavePage");
3275     return;
3276   }
3277   // The observer will delete itself when done.
3278   new SavePackageNotificationObserver(
3279       tab_contents->download_tab_helper()->save_package(), this, reply_message);
3280 }
3281 
3282 // Refer to ImportSettings() in chrome/test/pyautolib/pyauto.py for sample
3283 // json input.
3284 // Sample json output: "{}"
ImportSettings(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3285 void TestingAutomationProvider::ImportSettings(Browser* browser,
3286                                                DictionaryValue* args,
3287                                                IPC::Message* reply_message) {
3288   // Map from the json string passed over to the import item masks.
3289   std::map<std::string, importer::ImportItem> string_to_import_item;
3290   string_to_import_item["HISTORY"] = importer::HISTORY;
3291   string_to_import_item["FAVORITES"] = importer::FAVORITES;
3292   string_to_import_item["COOKIES"] = importer::COOKIES;
3293   string_to_import_item["PASSWORDS"] = importer::PASSWORDS;
3294   string_to_import_item["SEARCH_ENGINES"] = importer::SEARCH_ENGINES;
3295   string_to_import_item["HOME_PAGE"] = importer::HOME_PAGE;
3296   string_to_import_item["ALL"] = importer::ALL;
3297 
3298   ListValue* import_items_list = NULL;
3299   if (!args->GetString("import_from", &import_settings_data_.browser_name) ||
3300       !args->GetBoolean("first_run", &import_settings_data_.first_run) ||
3301       !args->GetList("import_items", &import_items_list)) {
3302     AutomationJSONReply(this, reply_message)
3303         .SendError("Incorrect type for one or more of the arguments.");
3304     return;
3305   }
3306 
3307   import_settings_data_.import_items = 0;
3308   int num_items = import_items_list->GetSize();
3309   for (int i = 0; i < num_items; i++) {
3310     std::string item;
3311     import_items_list->GetString(i, &item);
3312     // If the provided string is not part of the map, error out.
3313     if (!ContainsKey(string_to_import_item, item)) {
3314       AutomationJSONReply(this, reply_message)
3315           .SendError("Invalid item string found in import_items.");
3316       return;
3317     }
3318     import_settings_data_.import_items |= string_to_import_item[item];
3319   }
3320 
3321   import_settings_data_.browser = browser;
3322   import_settings_data_.reply_message = reply_message;
3323 
3324   importer_list_ = new ImporterList;
3325   importer_list_->DetectSourceProfiles(this);
3326 }
3327 
3328 namespace {
3329 
3330 // Translates a dictionary password to a PasswordForm struct.
GetPasswordFormFromDict(const DictionaryValue & password_dict)3331 webkit_glue::PasswordForm GetPasswordFormFromDict(
3332     const DictionaryValue& password_dict) {
3333 
3334   // If the time is specified, change time to the specified time.
3335   base::Time time = base::Time::Now();
3336   int it;
3337   double dt;
3338   if (password_dict.GetInteger("time", &it))
3339     time = base::Time::FromTimeT(it);
3340   else if (password_dict.GetDouble("time", &dt))
3341     time = base::Time::FromDoubleT(dt);
3342 
3343   std::string signon_realm;
3344   string16 username_value;
3345   string16 password_value;
3346   string16 origin_url_text;
3347   string16 username_element;
3348   string16 password_element;
3349   string16 submit_element;
3350   string16 action_target_text;
3351   bool blacklist = false;
3352   string16 old_password_element;
3353   string16 old_password_value;
3354 
3355   // We don't care if any of these fail - they are either optional or checked
3356   // before this function is called.
3357   password_dict.GetString("signon_realm", &signon_realm);
3358   password_dict.GetString("username_value", &username_value);
3359   password_dict.GetString("password_value", &password_value);
3360   password_dict.GetString("origin_url", &origin_url_text);
3361   password_dict.GetString("username_element", &username_element);
3362   password_dict.GetString("password_element", &password_element);
3363   password_dict.GetString("submit_element", &submit_element);
3364   password_dict.GetString("action_target", &action_target_text);
3365   password_dict.GetBoolean("blacklist", &blacklist);
3366 
3367   GURL origin_gurl(origin_url_text);
3368   GURL action_target(action_target_text);
3369 
3370   webkit_glue::PasswordForm password_form;
3371   password_form.signon_realm = signon_realm;
3372   password_form.username_value = username_value;
3373   password_form.password_value = password_value;
3374   password_form.origin = origin_gurl;
3375   password_form.username_element = username_element;
3376   password_form.password_element = password_element;
3377   password_form.submit_element = submit_element;
3378   password_form.action = action_target;
3379   password_form.blacklisted_by_user = blacklist;
3380   password_form.date_created = time;
3381 
3382   return password_form;
3383 }
3384 
3385 }  // namespace
3386 
3387 // See AddSavedPassword() in chrome/test/functional/pyauto.py for sample json
3388 // input.
3389 // Sample json output: { "password_added": true }
AddSavedPassword(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3390 void TestingAutomationProvider::AddSavedPassword(
3391     Browser* browser,
3392     DictionaryValue* args,
3393     IPC::Message* reply_message) {
3394   AutomationJSONReply reply(this, reply_message);
3395   DictionaryValue* password_dict = NULL;
3396 
3397   if (!args->GetDictionary("password", &password_dict)) {
3398     reply.SendError("Password must be a dictionary.");
3399     return;
3400   }
3401 
3402   // The signon realm is effectively the primary key and must be included.
3403   // Check here before calling GetPasswordFormFromDict.
3404   if (!password_dict->HasKey("signon_realm")) {
3405     reply.SendError("Password must include signon_realm.");
3406     return;
3407   }
3408   webkit_glue::PasswordForm new_password =
3409       GetPasswordFormFromDict(*password_dict);
3410 
3411   Profile* profile = browser->profile();
3412   // Use IMPLICIT_ACCESS since new passwords aren't added in incognito mode.
3413   PasswordStore* password_store =
3414       profile->GetPasswordStore(Profile::IMPLICIT_ACCESS);
3415 
3416   // Set the return based on whether setting the password succeeded.
3417   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
3418 
3419   // It will be null if it's accessed in an incognito window.
3420   if (password_store != NULL) {
3421     password_store->AddLogin(new_password);
3422     return_value->SetBoolean("password_added", true);
3423   } else {
3424     return_value->SetBoolean("password_added", false);
3425   }
3426 
3427   reply.SendSuccess(return_value.get());
3428 }
3429 
3430 // See RemoveSavedPassword() in chrome/test/functional/pyauto.py for sample
3431 // json input.
3432 // Sample json output: {}
RemoveSavedPassword(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3433 void TestingAutomationProvider::RemoveSavedPassword(
3434     Browser* browser,
3435     DictionaryValue* args,
3436     IPC::Message* reply_message) {
3437   AutomationJSONReply reply(this, reply_message);
3438   DictionaryValue* password_dict = NULL;
3439 
3440   if (!args->GetDictionary("password", &password_dict)) {
3441     reply.SendError("Password must be a dictionary.");
3442     return;
3443   }
3444 
3445   // The signon realm is effectively the primary key and must be included.
3446   // Check here before calling GetPasswordFormFromDict.
3447   if (!password_dict->HasKey("signon_realm")) {
3448     reply.SendError("Password must include signon_realm.");
3449     return;
3450   }
3451   webkit_glue::PasswordForm to_remove =
3452       GetPasswordFormFromDict(*password_dict);
3453 
3454   Profile* profile = browser->profile();
3455   // Use EXPLICIT_ACCESS since passwords can be removed in incognito mode.
3456   PasswordStore* password_store =
3457       profile->GetPasswordStore(Profile::EXPLICIT_ACCESS);
3458 
3459   password_store->RemoveLogin(to_remove);
3460   reply.SendSuccess(NULL);
3461 }
3462 
3463 // Sample json input: { "command": "GetSavedPasswords" }
3464 // Refer to GetSavedPasswords() in chrome/test/pyautolib/pyauto.py for sample
3465 // json output.
GetSavedPasswords(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3466 void TestingAutomationProvider::GetSavedPasswords(
3467     Browser* browser,
3468     DictionaryValue* args,
3469     IPC::Message* reply_message) {
3470   Profile* profile = browser->profile();
3471   // Use EXPLICIT_ACCESS since saved passwords can be retrieved in
3472   // incognito mode.
3473   PasswordStore* password_store =
3474       profile->GetPasswordStore(Profile::EXPLICIT_ACCESS);
3475   password_store->GetAutofillableLogins(
3476       new AutomationProviderGetPasswordsObserver(this, reply_message));
3477   // Observer deletes itself after returning.
3478 }
3479 
3480 // Refer to ClearBrowsingData() in chrome/test/pyautolib/pyauto.py for sample
3481 // json input.
3482 // Sample json output: {}
ClearBrowsingData(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3483 void TestingAutomationProvider::ClearBrowsingData(
3484     Browser* browser,
3485     DictionaryValue* args,
3486     IPC::Message* reply_message) {
3487   std::map<std::string, BrowsingDataRemover::TimePeriod> string_to_time_period;
3488   string_to_time_period["LAST_HOUR"] = BrowsingDataRemover::LAST_HOUR;
3489   string_to_time_period["LAST_DAY"] = BrowsingDataRemover::LAST_DAY;
3490   string_to_time_period["LAST_WEEK"] = BrowsingDataRemover::LAST_WEEK;
3491   string_to_time_period["FOUR_WEEKS"] = BrowsingDataRemover::FOUR_WEEKS;
3492   string_to_time_period["EVERYTHING"] = BrowsingDataRemover::EVERYTHING;
3493 
3494   std::map<std::string, int> string_to_mask_value;
3495   string_to_mask_value["HISTORY"] = BrowsingDataRemover::REMOVE_HISTORY;
3496   string_to_mask_value["DOWNLOADS"] = BrowsingDataRemover::REMOVE_DOWNLOADS;
3497   string_to_mask_value["COOKIES"] = BrowsingDataRemover::REMOVE_COOKIES;
3498   string_to_mask_value["PASSWORDS"] = BrowsingDataRemover::REMOVE_PASSWORDS;
3499   string_to_mask_value["FORM_DATA"] = BrowsingDataRemover::REMOVE_FORM_DATA;
3500   string_to_mask_value["CACHE"] = BrowsingDataRemover::REMOVE_CACHE;
3501 
3502   std::string time_period;
3503   ListValue* to_remove;
3504   if (!args->GetString("time_period", &time_period) ||
3505       !args->GetList("to_remove", &to_remove)) {
3506     AutomationJSONReply(this, reply_message)
3507         .SendError("time_period must be a string and to_remove a list.");
3508     return;
3509   }
3510 
3511   int remove_mask = 0;
3512   int num_removals = to_remove->GetSize();
3513   for (int i = 0; i < num_removals; i++) {
3514     std::string removal;
3515     to_remove->GetString(i, &removal);
3516     // If the provided string is not part of the map, then error out.
3517     if (!ContainsKey(string_to_mask_value, removal)) {
3518       AutomationJSONReply(this, reply_message)
3519           .SendError("Invalid browsing data string found in to_remove.");
3520       return;
3521     }
3522     remove_mask |= string_to_mask_value[removal];
3523   }
3524 
3525   if (!ContainsKey(string_to_time_period, time_period)) {
3526     AutomationJSONReply(this, reply_message)
3527         .SendError("Invalid string for time_period.");
3528     return;
3529   }
3530 
3531   BrowsingDataRemover* remover = new BrowsingDataRemover(
3532       profile(), string_to_time_period[time_period], base::Time());
3533 
3534   remover->AddObserver(
3535       new AutomationProviderBrowsingDataObserver(this, reply_message));
3536   remover->Remove(remove_mask);
3537   // BrowsingDataRemover deletes itself using DeleteTask.
3538   // The observer also deletes itself after sending the reply.
3539 }
3540 
3541 namespace {
3542 
3543   // Get the TabContents from a dictionary of arguments.
GetTabContentsFromDict(const Browser * browser,const DictionaryValue * args,std::string * error_message)3544   TabContents* GetTabContentsFromDict(const Browser* browser,
3545                                       const DictionaryValue* args,
3546                                       std::string* error_message) {
3547     int tab_index;
3548     if (!args->GetInteger("tab_index", &tab_index)) {
3549       *error_message = "Must include tab_index.";
3550       return NULL;
3551     }
3552 
3553     TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
3554     if (!tab_contents) {
3555       *error_message = StringPrintf("No tab at index %d.", tab_index);
3556       return NULL;
3557     }
3558     return tab_contents;
3559   }
3560 
3561   // Get the TranslateInfoBarDelegate from TabContents.
GetTranslateInfoBarDelegate(TabContents * tab_contents)3562   TranslateInfoBarDelegate* GetTranslateInfoBarDelegate(
3563       TabContents* tab_contents) {
3564     for (size_t i = 0; i < tab_contents->infobar_count(); i++) {
3565       InfoBarDelegate* infobar = tab_contents->GetInfoBarDelegateAt(i);
3566       if (infobar->AsTranslateInfoBarDelegate())
3567         return infobar->AsTranslateInfoBarDelegate();
3568     }
3569     // No translate infobar.
3570     return NULL;
3571   }
3572 }  // namespace
3573 
FindInPage(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3574 void TestingAutomationProvider::FindInPage(
3575     Browser* browser,
3576     DictionaryValue* args,
3577     IPC::Message* reply_message) {
3578   std::string error_message;
3579   TabContents* tab_contents = GetTabContentsFromDict(browser, args,
3580                                                      &error_message);
3581   if (!tab_contents) {
3582     AutomationJSONReply(this, reply_message).SendError(error_message);
3583     return;
3584   }
3585   string16 search_string;
3586   bool forward;
3587   bool match_case;
3588   bool find_next;
3589   if (!args->GetString("search_string", &search_string)) {
3590     AutomationJSONReply(this, reply_message).
3591         SendError("Must include search_string string.");
3592     return;
3593   }
3594   if (!args->GetBoolean("forward", &forward)) {
3595     AutomationJSONReply(this, reply_message).
3596         SendError("Must include forward boolean.");
3597     return;
3598   }
3599   if (!args->GetBoolean("match_case", &match_case)) {
3600     AutomationJSONReply(this, reply_message).
3601         SendError("Must include match_case boolean.");
3602     return;
3603   }
3604   if (!args->GetBoolean("find_next", &find_next)) {
3605     AutomationJSONReply(this, reply_message).
3606         SendError("Must include find_next boolean.");
3607     return;
3608   }
3609   SendFindRequest(tab_contents,
3610                   true,
3611                   search_string,
3612                   forward,
3613                   match_case,
3614                   find_next,
3615                   reply_message);
3616 }
3617 
3618 // See GetTranslateInfo() in chrome/test/pyautolib/pyauto.py for sample json
3619 // input and output.
GetTranslateInfo(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3620 void TestingAutomationProvider::GetTranslateInfo(
3621     Browser* browser,
3622     DictionaryValue* args,
3623     IPC::Message* reply_message) {
3624   std::string error_message;
3625   TabContents* tab_contents = GetTabContentsFromDict(browser, args,
3626                                                      &error_message);
3627   if (!tab_contents) {
3628     AutomationJSONReply(this, reply_message).SendError(error_message);
3629     return;
3630   }
3631 
3632   // Get the translate bar if there is one and pass it to the observer.
3633   // The observer will check for null and populate the information accordingly.
3634   TranslateInfoBarDelegate* translate_bar =
3635       GetTranslateInfoBarDelegate(tab_contents);
3636 
3637   TabLanguageDeterminedObserver* observer = new TabLanguageDeterminedObserver(
3638       this, reply_message, tab_contents, translate_bar);
3639   // If the language for the page hasn't been loaded yet, then just make
3640   // the observer, otherwise call observe directly.
3641   TranslateTabHelper* helper = TabContentsWrapper::GetCurrentWrapperForContents(
3642       tab_contents)->translate_tab_helper();
3643   std::string language = helper->language_state().original_language();
3644   if (!language.empty()) {
3645     observer->Observe(NotificationType::TAB_LANGUAGE_DETERMINED,
3646                       Source<TabContents>(tab_contents),
3647                       Details<std::string>(&language));
3648   }
3649 }
3650 
3651 // See SelectTranslateOption() in chrome/test/pyautolib/pyauto.py for sample
3652 // json input.
3653 // Sample json output: {}
SelectTranslateOption(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3654 void TestingAutomationProvider::SelectTranslateOption(
3655     Browser* browser,
3656     DictionaryValue* args,
3657     IPC::Message* reply_message) {
3658   std::string option;
3659   std::string error_message;
3660   TabContents* tab_contents = GetTabContentsFromDict(browser, args,
3661                                                      &error_message);
3662   if (!tab_contents) {
3663     AutomationJSONReply(this, reply_message).SendError(error_message);
3664     return;
3665   }
3666 
3667   TranslateInfoBarDelegate* translate_bar =
3668       GetTranslateInfoBarDelegate(tab_contents);
3669   if (!translate_bar) {
3670     AutomationJSONReply(this, reply_message)
3671         .SendError("There is no translate bar open.");
3672     return;
3673   }
3674 
3675   if (!args->GetString("option", &option)) {
3676     AutomationJSONReply(this, reply_message).SendError("Must include option");
3677     return;
3678   }
3679 
3680   if (option == "translate_page") {
3681     // Make a new notification observer which will send the reply.
3682     new PageTranslatedObserver(this, reply_message, tab_contents);
3683     translate_bar->Translate();
3684     return;
3685   } else if (option == "set_target_language") {
3686     string16 target_language;
3687     if (!args->GetString("target_language", &target_language)) {
3688        AutomationJSONReply(this, reply_message)
3689            .SendError("Must include target_language string.");
3690       return;
3691     }
3692     // Get the target language index based off of the language name.
3693     size_t target_language_index = TranslateInfoBarDelegate::kNoIndex;
3694     for (size_t i = 0; i < translate_bar->GetLanguageCount(); i++) {
3695       if (translate_bar->GetLanguageDisplayableNameAt(i) == target_language) {
3696         target_language_index = i;
3697         break;
3698       }
3699     }
3700     if (target_language_index == TranslateInfoBarDelegate::kNoIndex) {
3701        AutomationJSONReply(this, reply_message)
3702            .SendError("Invalid target language string.");
3703        return;
3704     }
3705     // If the page has already been translated it will be translated again to
3706     // the new language. The observer will wait until the page has been
3707     // translated to reply.
3708     if (translate_bar->type() == TranslateInfoBarDelegate::AFTER_TRANSLATE) {
3709       new PageTranslatedObserver(this, reply_message, tab_contents);
3710       translate_bar->SetTargetLanguage(target_language_index);
3711       return;
3712     }
3713     // Otherwise just send the reply back immediately.
3714     translate_bar->SetTargetLanguage(target_language_index);
3715     scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
3716     return_value->SetBoolean("translation_success", true);
3717     AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
3718     return;
3719   } else if (option == "click_always_translate_lang_button") {
3720     if (!translate_bar->ShouldShowAlwaysTranslateButton()) {
3721       AutomationJSONReply(this, reply_message)
3722           .SendError("Always translate button not showing.");
3723       return;
3724     }
3725     // Clicking 'Always Translate' triggers a translation. The observer will
3726     // wait until the translation is complete before sending the reply.
3727     new PageTranslatedObserver(this, reply_message, tab_contents);
3728     translate_bar->AlwaysTranslatePageLanguage();
3729     return;
3730   }
3731 
3732   AutomationJSONReply reply(this, reply_message);
3733   if (option == "never_translate_language") {
3734     if (translate_bar->IsLanguageBlacklisted()) {
3735       reply.SendError("The language was already blacklisted.");
3736       return;
3737     }
3738     translate_bar->ToggleLanguageBlacklist();
3739     reply.SendSuccess(NULL);
3740   } else if (option == "never_translate_site") {
3741     if (translate_bar->IsSiteBlacklisted()) {
3742       reply.SendError("The site was already blacklisted.");
3743       return;
3744     }
3745     translate_bar->ToggleSiteBlacklist();
3746     reply.SendSuccess(NULL);
3747   } else if (option == "toggle_always_translate") {
3748     translate_bar->ToggleAlwaysTranslate();
3749     reply.SendSuccess(NULL);
3750   } else if (option == "revert_translation") {
3751     translate_bar->RevertTranslation();
3752     reply.SendSuccess(NULL);
3753   } else if (option == "click_never_translate_lang_button") {
3754     if (!translate_bar->ShouldShowNeverTranslateButton()) {
3755       reply.SendError("Always translate button not showing.");
3756       return;
3757     }
3758     translate_bar->NeverTranslatePageLanguage();
3759     reply.SendSuccess(NULL);
3760   } else if (option == "decline_translation") {
3761     // This is the function called when an infobar is dismissed or when the
3762     // user clicks the 'Nope' translate button.
3763     translate_bar->TranslationDeclined();
3764     tab_contents->RemoveInfoBar(translate_bar);
3765     reply.SendSuccess(NULL);
3766   } else {
3767     reply.SendError("Invalid string found for option.");
3768   }
3769 }
3770 
3771 // Sample json input: { "command": "GetBlockedPopupsInfo",
3772 //                      "tab_index": 1 }
3773 // Refer GetBlockedPopupsInfo() in pyauto.py for sample output.
GetBlockedPopupsInfo(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3774 void TestingAutomationProvider::GetBlockedPopupsInfo(
3775     Browser* browser,
3776     DictionaryValue* args,
3777     IPC::Message* reply_message) {
3778   AutomationJSONReply reply(this, reply_message);
3779   std::string error_message;
3780   TabContents* tab_contents = GetTabContentsFromDict(
3781       browser, args, &error_message);
3782   if (!tab_contents) {
3783     reply.SendError(error_message);
3784     return;
3785   }
3786   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
3787   BlockedContentContainer* popup_container =
3788       tab_contents->blocked_content_container();
3789   ListValue* blocked_popups_list = new ListValue;
3790   if (popup_container) {
3791     std::vector<TabContents*> blocked_contents;
3792     popup_container->GetBlockedContents(&blocked_contents);
3793     for (std::vector<TabContents*>::const_iterator it =
3794              blocked_contents.begin(); it != blocked_contents.end(); ++it) {
3795       DictionaryValue* item = new DictionaryValue;
3796       item->SetString("url", (*it)->GetURL().spec());
3797       item->SetString("title", (*it)->GetTitle());
3798       blocked_popups_list->Append(item);
3799     }
3800   }
3801   return_value->Set("blocked_popups", blocked_popups_list);
3802   reply.SendSuccess(return_value.get());
3803 }
3804 
3805 // Refer UnblockAndLaunchBlockedPopup() in pyauto.py for sample input.
UnblockAndLaunchBlockedPopup(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3806 void TestingAutomationProvider::UnblockAndLaunchBlockedPopup(
3807     Browser* browser,
3808     DictionaryValue* args,
3809     IPC::Message* reply_message) {
3810   AutomationJSONReply reply(this, reply_message);
3811   std::string error_message;
3812   TabContents* tab_contents = GetTabContentsFromDict(
3813       browser, args, &error_message);
3814   if (!tab_contents) {
3815     reply.SendError(error_message);
3816     return;
3817   }
3818   int popup_index;
3819   if (!args->GetInteger("popup_index", &popup_index)) {
3820     reply.SendError("Need popup_index arg");
3821     return;
3822   }
3823   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
3824   BlockedContentContainer* content_container =
3825       tab_contents->blocked_content_container();
3826   if (!content_container ||
3827       popup_index >= (int)content_container->GetBlockedContentsCount()) {
3828     reply.SendError(StringPrintf("No popup at index %d", popup_index));
3829     return;
3830   }
3831   std::vector<TabContents*> blocked_contents;
3832   content_container->GetBlockedContents(&blocked_contents);
3833   content_container->LaunchForContents(blocked_contents[popup_index]);
3834   reply.SendSuccess(NULL);
3835 }
3836 
3837 // Sample json input: { "command": "GetThemeInfo" }
3838 // Refer GetThemeInfo() in chrome/test/pyautolib/pyauto.py for sample output.
GetThemeInfo(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3839 void TestingAutomationProvider::GetThemeInfo(
3840     Browser* browser,
3841     DictionaryValue* args,
3842     IPC::Message* reply_message) {
3843   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
3844   const Extension* theme = ThemeServiceFactory::GetThemeForProfile(profile());
3845   if (theme) {
3846     return_value->SetString("name", theme->name());
3847     return_value->Set("images", theme->GetThemeImages()->DeepCopy());
3848     return_value->Set("colors", theme->GetThemeColors()->DeepCopy());
3849     return_value->Set("tints", theme->GetThemeTints()->DeepCopy());
3850   }
3851   AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
3852 }
3853 
3854 namespace {
3855 
GetHostPermissions(const Extension * ext)3856 ListValue* GetHostPermissions(const Extension* ext) {
3857   ListValue* permissions = new ListValue;
3858   const URLPatternList pattern_list =
3859       ext->GetEffectiveHostPermissions().patterns();
3860   for (URLPatternList::const_iterator perm = pattern_list.begin();
3861        perm != pattern_list.end(); ++perm) {
3862     permissions->Append(new StringValue(perm->GetAsString()));
3863   }
3864   return permissions;
3865 }
3866 
GetAPIPermissions(const Extension * ext)3867 ListValue* GetAPIPermissions(const Extension* ext) {
3868   ListValue* permissions = new ListValue;
3869   std::set<std::string> perm_list = ext->api_permissions();
3870   for (std::set<std::string>::const_iterator perm = perm_list.begin();
3871        perm != perm_list.end(); ++perm) {
3872     permissions->Append(new StringValue(perm->c_str()));
3873   }
3874   return permissions;
3875 }
3876 
3877 }  // namespace
3878 
3879 // Sample json input: { "command": "GetExtensionsInfo" }
3880 // See GetExtensionsInfo() in chrome/test/pyautolib/pyauto.py for sample json
3881 // output.
GetExtensionsInfo(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3882 void TestingAutomationProvider::GetExtensionsInfo(
3883     Browser* browser,
3884     DictionaryValue* args,
3885     IPC::Message* reply_message) {
3886   AutomationJSONReply reply(this, reply_message);
3887   ExtensionService* service = profile()->GetExtensionService();
3888   if (!service) {
3889     reply.SendError("No extensions service.");
3890   }
3891   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
3892   ListValue* extensions_values = new ListValue;
3893   const ExtensionList* extensions = service->extensions();
3894   for (ExtensionList::const_iterator it = extensions->begin();
3895        it != extensions->end(); ++it) {
3896     const Extension* extension = *it;
3897     DictionaryValue* extension_value = new DictionaryValue;
3898     extension_value->SetString("id", extension->id());
3899     extension_value->SetString("version", extension->VersionString());
3900     extension_value->SetString("name", extension->name());
3901     extension_value->SetString("public_key", extension->public_key());
3902     extension_value->SetString("description", extension->description());
3903     extension_value->SetString("background_url",
3904                                extension->background_url().spec());
3905     extension_value->SetString("options_url",
3906                                extension->options_url().spec());
3907     extension_value->Set("host_permissions", GetHostPermissions(extension));
3908     extension_value->Set("api_permissions", GetAPIPermissions(extension));
3909     extensions_values->Append(extension_value);
3910   }
3911   return_value->Set("extensions", extensions_values);
3912   reply.SendSuccess(return_value.get());
3913 }
3914 
3915 // See UninstallExtensionById() in chrome/test/pyautolib/pyauto.py for sample
3916 // json input.
3917 // Sample json output: {}
UninstallExtensionById(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3918 void TestingAutomationProvider::UninstallExtensionById(
3919     Browser* browser,
3920     DictionaryValue* args,
3921     IPC::Message* reply_message) {
3922   std::string id;
3923   if (!args->GetString("id", &id)) {
3924     AutomationJSONReply(this, reply_message).SendError(
3925         "Must include string id.");
3926     return;
3927   }
3928   ExtensionService* service = profile()->GetExtensionService();
3929   if (!service) {
3930     AutomationJSONReply(this, reply_message).SendError(
3931         "No extensions service.");
3932     return;
3933   }
3934 
3935   if (!service->GetExtensionById(id, true) &&
3936       !service->GetTerminatedExtension(id)) {
3937     // The extension ID does not correspond to any extension, whether crashed
3938     // or not.
3939     AutomationJSONReply(this, reply_message).SendError(base::StringPrintf(
3940         "Extension does not exist: %s.", id.c_str()));
3941     return;
3942   }
3943 
3944   // Wait for a notification indicating that the extension with the given ID
3945   // has been uninstalled.  This observer will delete itself.
3946   new ExtensionUninstallObserver(this, reply_message, id);
3947   service->UninstallExtension(id, false, NULL);
3948 }
3949 
3950 // Sample json input:
3951 //    { "command": "GetAutofillProfile" }
3952 // Refer to GetAutofillProfile() in chrome/test/pyautolib/pyauto.py for sample
3953 // json output.
GetAutofillProfile(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3954 void TestingAutomationProvider::GetAutofillProfile(
3955     Browser* browser,
3956     DictionaryValue* args,
3957     IPC::Message* reply_message) {
3958   AutomationJSONReply reply(this, reply_message);
3959   // Get the AutofillProfiles currently in the database.
3960   int tab_index = 0;
3961   if (!args->GetInteger("tab_index", &tab_index)) {
3962     reply.SendError("Invalid or missing tab_index integer value.");
3963     return;
3964   }
3965 
3966   TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
3967   if (tab_contents) {
3968     PersonalDataManager* pdm = tab_contents->profile()->GetOriginalProfile()
3969         ->GetPersonalDataManager();
3970     if (pdm) {
3971       std::vector<AutofillProfile*> autofill_profiles = pdm->profiles();
3972       std::vector<CreditCard*> credit_cards = pdm->credit_cards();
3973 
3974       ListValue* profiles = GetListFromAutofillProfiles(autofill_profiles);
3975       ListValue* cards = GetListFromCreditCards(credit_cards);
3976 
3977       scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
3978 
3979       return_value->Set("profiles", profiles);
3980       return_value->Set("credit_cards", cards);
3981       reply.SendSuccess(return_value.get());
3982     } else {
3983       reply.SendError("No PersonalDataManager.");
3984       return;
3985     }
3986   } else {
3987     reply.SendError("No tab at that index.");
3988     return;
3989   }
3990 }
3991 
3992 // Refer to FillAutofillProfile() in chrome/test/pyautolib/pyauto.py for sample
3993 // json input.
3994 // Sample json output: {}
FillAutofillProfile(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)3995 void TestingAutomationProvider::FillAutofillProfile(
3996     Browser* browser,
3997     DictionaryValue* args,
3998     IPC::Message* reply_message) {
3999   AutomationJSONReply reply(this, reply_message);
4000   ListValue* profiles = NULL;
4001   ListValue* cards = NULL;
4002 
4003   // It's ok for profiles/credit_cards elements to be missing.
4004   args->GetList("profiles", &profiles);
4005   args->GetList("credit_cards", &cards);
4006 
4007   std::string error_mesg;
4008 
4009   std::vector<AutofillProfile> autofill_profiles;
4010   std::vector<CreditCard> credit_cards;
4011   // Create an AutofillProfile for each of the dictionary profiles.
4012   if (profiles) {
4013     autofill_profiles = GetAutofillProfilesFromList(*profiles, &error_mesg);
4014   }
4015   // Create a CreditCard for each of the dictionary values.
4016   if (cards) {
4017     credit_cards = GetCreditCardsFromList(*cards, &error_mesg);
4018   }
4019   if (!error_mesg.empty()) {
4020     reply.SendError(error_mesg);
4021     return;
4022   }
4023 
4024   // Save the AutofillProfiles.
4025   int tab_index = 0;
4026   if (!args->GetInteger("tab_index", &tab_index)) {
4027     reply.SendError("Invalid or missing tab_index integer");
4028     return;
4029   }
4030 
4031   TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
4032 
4033   if (tab_contents) {
4034     PersonalDataManager* pdm = tab_contents->profile()
4035         ->GetPersonalDataManager();
4036     if (pdm) {
4037       if (profiles)
4038         pdm->SetProfiles(&autofill_profiles);
4039       if (cards)
4040         pdm->SetCreditCards(&credit_cards);
4041     } else {
4042       reply.SendError("No PersonalDataManager.");
4043       return;
4044     }
4045   } else {
4046     reply.SendError("No tab at that index.");
4047     return;
4048   }
4049   reply.SendSuccess(NULL);
4050 }
4051 
4052 // Sample json output: { "success": true }
SignInToSync(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)4053 void TestingAutomationProvider::SignInToSync(Browser* browser,
4054                                              DictionaryValue* args,
4055                                              IPC::Message* reply_message) {
4056   AutomationJSONReply reply(this, reply_message);
4057   std::string username;
4058   std::string password;
4059   if (!args->GetString("username", &username) ||
4060       !args->GetString("password", &password)) {
4061       reply.SendError("Invalid or missing args");
4062       return;
4063   }
4064   if (sync_waiter_.get() == NULL) {
4065     sync_waiter_.reset(new ProfileSyncServiceHarness(
4066         browser->profile(), username, password, 0));
4067   } else {
4068     sync_waiter_->SetCredentials(username, password);
4069   }
4070   if (sync_waiter_->SetupSync()) {
4071     scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
4072     return_value->SetBoolean("success", true);
4073     reply.SendSuccess(return_value.get());
4074   } else {
4075     reply.SendError("Signing in to sync was unsuccessful");
4076   }
4077 }
4078 
4079 // Sample json output:
4080 // {u'summary': u'SYNC DISABLED'}
4081 //
4082 // { u'authenticated': True,
4083 //   u'last synced': u'Just now',
4084 //   u'summary': u'READY',
4085 //   u'sync url': u'clients4.google.com',
4086 //   u'updates received': 42,
4087 //   u'synced datatypes': [ u'Bookmarks',
4088 //                          u'Preferences',
4089 //                          u'Passwords',
4090 //                          u'Autofill',
4091 //                          u'Themes',
4092 //                          u'Extensions',
4093 //                          u'Apps']}
GetSyncInfo(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)4094 void TestingAutomationProvider::GetSyncInfo(Browser* browser,
4095                                             DictionaryValue* args,
4096                                             IPC::Message* reply_message) {
4097   AutomationJSONReply reply(this, reply_message);
4098   DictionaryValue* sync_info = new DictionaryValue;
4099   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
4100   if (sync_waiter_.get() == NULL) {
4101     sync_waiter_.reset(
4102         ProfileSyncServiceHarness::CreateAndAttach(browser->profile()));
4103   }
4104   if (!sync_waiter_->IsSyncAlreadySetup()) {
4105     sync_info->SetString("summary", "SYNC DISABLED");
4106   } else {
4107     ProfileSyncService* service = sync_waiter_->service();
4108     ProfileSyncService::Status status = sync_waiter_->GetStatus();
4109     sync_info->SetString("summary",
4110         ProfileSyncService::BuildSyncStatusSummaryText(status.summary));
4111     sync_info->SetString("sync url", service->sync_service_url().host());
4112     sync_info->SetBoolean("authenticated", status.authenticated);
4113     sync_info->SetString("last synced", service->GetLastSyncedTimeString());
4114     sync_info->SetInteger("updates received", status.updates_received);
4115     ListValue* synced_datatype_list = new ListValue;
4116     syncable::ModelTypeSet synced_datatypes;
4117     service->GetPreferredDataTypes(&synced_datatypes);
4118     for (syncable::ModelTypeSet::iterator it = synced_datatypes.begin();
4119          it != synced_datatypes.end(); ++it) {
4120       synced_datatype_list->Append(
4121           new StringValue(syncable::ModelTypeToString(*it)));
4122     }
4123     sync_info->Set("synced datatypes", synced_datatype_list);
4124   }
4125   return_value->Set("sync_info", sync_info);
4126   reply.SendSuccess(return_value.get());
4127 }
4128 
4129 // Sample json output: { "success": true }
AwaitSyncCycleCompletion(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)4130 void TestingAutomationProvider::AwaitSyncCycleCompletion(
4131     Browser* browser,
4132     DictionaryValue* args,
4133     IPC::Message* reply_message) {
4134   AutomationJSONReply reply(this, reply_message);
4135   if (sync_waiter_.get() == NULL) {
4136     sync_waiter_.reset(
4137         ProfileSyncServiceHarness::CreateAndAttach(browser->profile()));
4138   }
4139   if (!sync_waiter_->IsSyncAlreadySetup()) {
4140     reply.SendError("Not signed in to sync");
4141     return;
4142   }
4143   // Ensure that the profile sync service is initialized before waiting for sync
4144   // to complete. In cases where the browser is restarted with sync enabled,
4145   // the sync service may take a while to get reinitialized.
4146   if (!browser->profile()->GetProfileSyncService()) {
4147     reply.SendError("ProfileSyncService not initialized.");
4148     return;
4149   }
4150   sync_waiter_->AwaitSyncCycleCompletion("Waiting for sync cycle");
4151   ProfileSyncService::Status status = sync_waiter_->GetStatus();
4152   if (status.summary == ProfileSyncService::Status::READY) {
4153     scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
4154     return_value->SetBoolean("success", true);
4155     reply.SendSuccess(return_value.get());
4156   } else {
4157     std::string error_msg = "Wait for sync cycle was unsuccessful. "
4158                             "Sync status: ";
4159     error_msg.append(
4160         ProfileSyncService::BuildSyncStatusSummaryText(status.summary));
4161     reply.SendError(error_msg);
4162   }
4163 }
4164 
4165 // Refer to EnableSyncForDatatypes() in chrome/test/pyautolib/pyauto.py for
4166 // sample json input. Sample json output: { "success": true }
EnableSyncForDatatypes(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)4167 void TestingAutomationProvider::EnableSyncForDatatypes(
4168     Browser* browser,
4169     DictionaryValue* args,
4170     IPC::Message* reply_message) {
4171   AutomationJSONReply reply(this, reply_message);
4172   if (sync_waiter_.get() == NULL) {
4173     sync_waiter_.reset(
4174         ProfileSyncServiceHarness::CreateAndAttach(browser->profile()));
4175   }
4176   if (!sync_waiter_->IsSyncAlreadySetup()) {
4177     reply.SendError("Not signed in to sync");
4178     return;
4179   }
4180   ListValue* datatypes = NULL;
4181   if (!args->GetList("datatypes", &datatypes)) {
4182     reply.SendError("Invalid or missing args");
4183     return;
4184   }
4185   std::string first_datatype;
4186   datatypes->GetString(0, &first_datatype);
4187   if (first_datatype == "All") {
4188     sync_waiter_->EnableSyncForAllDatatypes();
4189   } else {
4190     int num_datatypes = datatypes->GetSize();
4191     for (int i = 0; i < num_datatypes; ++i) {
4192       std::string datatype_string;
4193       datatypes->GetString(i, &datatype_string);
4194       syncable::ModelType datatype =
4195           syncable::ModelTypeFromString(datatype_string);
4196       if (datatype == syncable::UNSPECIFIED) {
4197         AutomationJSONReply(this, reply_message).SendError(StringPrintf(
4198             "Invalid datatype string: %s.", datatype_string.c_str()));
4199         return;
4200       }
4201       sync_waiter_->EnableSyncForDatatype(datatype);
4202       sync_waiter_->AwaitSyncCycleCompletion(StringPrintf(
4203           "Enabling datatype: %s", datatype_string.c_str()));
4204     }
4205   }
4206   ProfileSyncService::Status status = sync_waiter_->GetStatus();
4207   if (status.summary == ProfileSyncService::Status::READY ||
4208       status.summary == ProfileSyncService::Status::SYNCING) {
4209     scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
4210     return_value->SetBoolean("success", true);
4211     reply.SendSuccess(return_value.get());
4212   } else {
4213     reply.SendError("Enabling sync for given datatypes was unsuccessful");
4214   }
4215 }
4216 
4217 // Refer to DisableSyncForDatatypes() in chrome/test/pyautolib/pyauto.py for
4218 // sample json input. Sample json output: { "success": true }
DisableSyncForDatatypes(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)4219 void TestingAutomationProvider::DisableSyncForDatatypes(
4220     Browser* browser,
4221     DictionaryValue* args,
4222     IPC::Message* reply_message) {
4223   AutomationJSONReply reply(this, reply_message);
4224   if (sync_waiter_.get() == NULL) {
4225     sync_waiter_.reset(
4226         ProfileSyncServiceHarness::CreateAndAttach(browser->profile()));
4227   }
4228   if (!sync_waiter_->IsSyncAlreadySetup()) {
4229     reply.SendError("Not signed in to sync");
4230     return;
4231   }
4232   ListValue* datatypes = NULL;
4233   if (!args->GetList("datatypes", &datatypes)) {
4234     reply.SendError("Invalid or missing args");
4235     return;
4236   }
4237   std::string first_datatype;
4238   if (!datatypes->GetString(0, &first_datatype)) {
4239     reply.SendError("Invalid or missing string");
4240     return;
4241   }
4242   if (first_datatype == "All") {
4243     sync_waiter_->DisableSyncForAllDatatypes();
4244     ProfileSyncService::Status status = sync_waiter_->GetStatus();
4245     if (status.summary != ProfileSyncService::Status::READY &&
4246         status.summary != ProfileSyncService::Status::SYNCING) {
4247       scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
4248       return_value->SetBoolean("success", true);
4249       reply.SendSuccess(return_value.get());
4250     } else {
4251       reply.SendError("Disabling all sync datatypes was unsuccessful");
4252     }
4253   } else {
4254     int num_datatypes = datatypes->GetSize();
4255     for (int i = 0; i < num_datatypes; i++) {
4256       std::string datatype_string;
4257       datatypes->GetString(i, &datatype_string);
4258       syncable::ModelType datatype =
4259           syncable::ModelTypeFromString(datatype_string);
4260       if (datatype == syncable::UNSPECIFIED) {
4261         AutomationJSONReply(this, reply_message).SendError(StringPrintf(
4262             "Invalid datatype string: %s.", datatype_string.c_str()));
4263         return;
4264       }
4265       sync_waiter_->DisableSyncForDatatype(datatype);
4266       sync_waiter_->AwaitSyncCycleCompletion(StringPrintf(
4267           "Disabling datatype: %s", datatype_string.c_str()));
4268     }
4269     ProfileSyncService::Status status = sync_waiter_->GetStatus();
4270     if (status.summary == ProfileSyncService::Status::READY ||
4271         status.summary == ProfileSyncService::Status::SYNCING) {
4272       scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
4273       return_value->SetBoolean("success", true);
4274       reply.SendSuccess(return_value.get());
4275     } else {
4276       reply.SendError("Disabling sync for given datatypes was unsuccessful");
4277     }
4278   }
4279 }
4280 
4281 /* static */
GetListFromAutofillProfiles(const std::vector<AutofillProfile * > & autofill_profiles)4282 ListValue* TestingAutomationProvider::GetListFromAutofillProfiles(
4283     const std::vector<AutofillProfile*>& autofill_profiles) {
4284   ListValue* profiles = new ListValue;
4285 
4286   std::map<AutofillFieldType, std::string> autofill_type_to_string
4287       = GetAutofillFieldToStringMap();
4288 
4289   // For each AutofillProfile, transform it to a dictionary object to return.
4290   for (std::vector<AutofillProfile*>::const_iterator it =
4291            autofill_profiles.begin();
4292        it != autofill_profiles.end(); ++it) {
4293     AutofillProfile* profile = *it;
4294     DictionaryValue* profile_info = new DictionaryValue;
4295     // For each of the types, if it has a value, add it to the dictionary.
4296     for (std::map<AutofillFieldType, std::string>::iterator
4297          type_it = autofill_type_to_string.begin();
4298          type_it != autofill_type_to_string.end(); ++type_it) {
4299       string16 value = profile->GetInfo(type_it->first);
4300       if (value.length()) {  // If there was something stored for that value.
4301         profile_info->SetString(type_it->second, value);
4302       }
4303     }
4304     profiles->Append(profile_info);
4305   }
4306   return profiles;
4307 }
4308 
4309 /* static */
GetListFromCreditCards(const std::vector<CreditCard * > & credit_cards)4310 ListValue* TestingAutomationProvider::GetListFromCreditCards(
4311     const std::vector<CreditCard*>& credit_cards) {
4312   ListValue* cards = new ListValue;
4313 
4314   std::map<AutofillFieldType, std::string> credit_card_type_to_string =
4315       GetCreditCardFieldToStringMap();
4316 
4317   // For each AutofillProfile, transform it to a dictionary object to return.
4318   for (std::vector<CreditCard*>::const_iterator it =
4319            credit_cards.begin();
4320        it != credit_cards.end(); ++it) {
4321     CreditCard* card = *it;
4322     DictionaryValue* card_info = new DictionaryValue;
4323     // For each of the types, if it has a value, add it to the dictionary.
4324     for (std::map<AutofillFieldType, std::string>::iterator type_it =
4325         credit_card_type_to_string.begin();
4326         type_it != credit_card_type_to_string.end(); ++type_it) {
4327       string16 value = card->GetInfo(type_it->first);
4328       // If there was something stored for that value.
4329       if (value.length()) {
4330         card_info->SetString(type_it->second, value);
4331       }
4332     }
4333     cards->Append(card_info);
4334   }
4335   return cards;
4336 }
4337 
4338 /* static */
4339 std::vector<AutofillProfile>
GetAutofillProfilesFromList(const ListValue & profiles,std::string * error_message)4340 TestingAutomationProvider::GetAutofillProfilesFromList(
4341     const ListValue& profiles, std::string* error_message) {
4342   std::vector<AutofillProfile> autofill_profiles;
4343   DictionaryValue* profile_info = NULL;
4344   string16 current_value;
4345 
4346   std::map<AutofillFieldType, std::string> autofill_type_to_string =
4347       GetAutofillFieldToStringMap();
4348 
4349   int num_profiles = profiles.GetSize();
4350   for (int i = 0; i < num_profiles; i++) {
4351     profiles.GetDictionary(i, &profile_info);
4352     AutofillProfile profile;
4353     // Loop through the possible profile types and add those provided.
4354     for (std::map<AutofillFieldType, std::string>::iterator type_it =
4355          autofill_type_to_string.begin();
4356          type_it != autofill_type_to_string.end(); ++type_it) {
4357       if (profile_info->HasKey(type_it->second)) {
4358         if (profile_info->GetString(type_it->second,
4359                                     &current_value)) {
4360           profile.SetInfo(type_it->first, current_value);
4361         } else {
4362           *error_message= "All values must be strings";
4363           break;
4364         }
4365       }
4366     }
4367     autofill_profiles.push_back(profile);
4368   }
4369   return autofill_profiles;
4370 }
4371 
4372 /* static */
GetCreditCardsFromList(const ListValue & cards,std::string * error_message)4373 std::vector<CreditCard> TestingAutomationProvider::GetCreditCardsFromList(
4374     const ListValue& cards, std::string* error_message) {
4375   std::vector<CreditCard> credit_cards;
4376   DictionaryValue* card_info = NULL;
4377   string16 current_value;
4378 
4379   std::map<AutofillFieldType, std::string> credit_card_type_to_string =
4380       GetCreditCardFieldToStringMap();
4381 
4382   int num_credit_cards = cards.GetSize();
4383   for (int i = 0; i < num_credit_cards; i++) {
4384     cards.GetDictionary(i, &card_info);
4385     CreditCard card;
4386     // Loop through the possible credit card fields and add those provided.
4387     for (std::map<AutofillFieldType, std::string>::iterator type_it =
4388         credit_card_type_to_string.begin();
4389         type_it != credit_card_type_to_string.end(); ++type_it) {
4390       if (card_info->HasKey(type_it->second)) {
4391         if (card_info->GetString(type_it->second, &current_value)) {
4392           card.SetInfo(type_it->first, current_value);
4393         } else {
4394           *error_message= "All values must be strings";
4395           break;
4396         }
4397       }
4398     }
4399     credit_cards.push_back(card);
4400   }
4401   return credit_cards;
4402 }
4403 
4404 /* static */
4405 std::map<AutofillFieldType, std::string>
GetAutofillFieldToStringMap()4406     TestingAutomationProvider::GetAutofillFieldToStringMap() {
4407   std::map<AutofillFieldType, std::string> autofill_type_to_string;
4408   // Strings ordered by order of fields when adding a profile in Autofill prefs.
4409   autofill_type_to_string[NAME_FIRST] = "NAME_FIRST";
4410   autofill_type_to_string[NAME_MIDDLE] = "NAME_MIDDLE";
4411   autofill_type_to_string[NAME_LAST] = "NAME_LAST";
4412   autofill_type_to_string[COMPANY_NAME] = "COMPANY_NAME";
4413   autofill_type_to_string[EMAIL_ADDRESS] = "EMAIL_ADDRESS";
4414   autofill_type_to_string[ADDRESS_HOME_LINE1] = "ADDRESS_HOME_LINE1";
4415   autofill_type_to_string[ADDRESS_HOME_LINE2] = "ADDRESS_HOME_LINE2";
4416   autofill_type_to_string[ADDRESS_HOME_CITY] = "ADDRESS_HOME_CITY";
4417   autofill_type_to_string[ADDRESS_HOME_STATE] = "ADDRESS_HOME_STATE";
4418   autofill_type_to_string[ADDRESS_HOME_ZIP] = "ADDRESS_HOME_ZIP";
4419   autofill_type_to_string[ADDRESS_HOME_COUNTRY] = "ADDRESS_HOME_COUNTRY";
4420   autofill_type_to_string[PHONE_HOME_COUNTRY_CODE] =
4421       "PHONE_HOME_COUNTRY_CODE";
4422   autofill_type_to_string[PHONE_HOME_CITY_CODE] = "PHONE_HOME_CITY_CODE";
4423   autofill_type_to_string[PHONE_HOME_WHOLE_NUMBER] =
4424       "PHONE_HOME_WHOLE_NUMBER";
4425   autofill_type_to_string[PHONE_FAX_COUNTRY_CODE] = "PHONE_FAX_COUNTRY_CODE";
4426   autofill_type_to_string[PHONE_FAX_CITY_CODE] = "PHONE_FAX_CITY_CODE";
4427   autofill_type_to_string[PHONE_FAX_WHOLE_NUMBER] = "PHONE_FAX_WHOLE_NUMBER";
4428   return autofill_type_to_string;
4429 }
4430 
4431 /* static */
4432 std::map<AutofillFieldType, std::string>
GetCreditCardFieldToStringMap()4433     TestingAutomationProvider::GetCreditCardFieldToStringMap() {
4434   std::map<AutofillFieldType, std::string> credit_card_type_to_string;
4435   credit_card_type_to_string[CREDIT_CARD_NAME] = "CREDIT_CARD_NAME";
4436   credit_card_type_to_string[CREDIT_CARD_NUMBER] = "CREDIT_CARD_NUMBER";
4437   credit_card_type_to_string[CREDIT_CARD_EXP_MONTH] = "CREDIT_CARD_EXP_MONTH";
4438   credit_card_type_to_string[CREDIT_CARD_EXP_4_DIGIT_YEAR] =
4439       "CREDIT_CARD_EXP_4_DIGIT_YEAR";
4440   return credit_card_type_to_string;
4441 }
4442 
4443 // Refer to GetActiveNotifications() in chrome/test/pyautolib/pyauto.py for
4444 // sample json input/output.
GetActiveNotifications(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)4445 void TestingAutomationProvider::GetActiveNotifications(
4446     Browser* browser,
4447     DictionaryValue* args,
4448     IPC::Message* reply_message) {
4449   new GetActiveNotificationsObserver(this, reply_message);
4450 }
4451 
4452 // Refer to CloseNotification() in chrome/test/pyautolib/pyauto.py for
4453 // sample json input.
4454 // Returns empty json message.
CloseNotification(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)4455 void TestingAutomationProvider::CloseNotification(
4456     Browser* browser,
4457     DictionaryValue* args,
4458     IPC::Message* reply_message) {
4459   int index;
4460   if (!args->GetInteger("index", &index)) {
4461     AutomationJSONReply(this, reply_message)
4462         .SendError("'index' missing or invalid.");
4463     return;
4464   }
4465   NotificationUIManager* manager = g_browser_process->notification_ui_manager();
4466   BalloonCollection* collection = manager->balloon_collection();
4467   const BalloonCollection::Balloons& balloons = collection->GetActiveBalloons();
4468   int balloon_count = static_cast<int>(balloons.size());
4469   if (index < 0 || index >= balloon_count) {
4470     AutomationJSONReply(this, reply_message)
4471         .SendError(StringPrintf("No notification at index %d", index));
4472     return;
4473   }
4474   // This will delete itself when finished.
4475   new OnNotificationBalloonCountObserver(
4476       this, reply_message, collection, balloon_count - 1);
4477   manager->CancelById(balloons[index]->notification().notification_id());
4478 }
4479 
4480 // Refer to WaitForNotificationCount() in chrome/test/pyautolib/pyauto.py for
4481 // sample json input.
4482 // Returns empty json message.
WaitForNotificationCount(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)4483 void TestingAutomationProvider::WaitForNotificationCount(
4484     Browser* browser,
4485     DictionaryValue* args,
4486     IPC::Message* reply_message) {
4487   int count;
4488   if (!args->GetInteger("count", &count)) {
4489     AutomationJSONReply(this, reply_message)
4490         .SendError("'count' missing or invalid.");
4491     return;
4492   }
4493   NotificationUIManager* manager = g_browser_process->notification_ui_manager();
4494   BalloonCollection* collection = manager->balloon_collection();
4495   const BalloonCollection::Balloons& balloons = collection->GetActiveBalloons();
4496   if (static_cast<int>(balloons.size()) == count) {
4497     AutomationJSONReply(this, reply_message).SendSuccess(NULL);
4498     return;
4499   }
4500   // This will delete itself when finished.
4501   new OnNotificationBalloonCountObserver(
4502       this, reply_message, collection, count);
4503 }
4504 
4505 // Sample JSON input: { "command": "GetNTPInfo" }
4506 // For output, refer to chrome/test/pyautolib/ntp_model.py.
GetNTPInfo(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)4507 void TestingAutomationProvider::GetNTPInfo(
4508     Browser* browser,
4509     DictionaryValue* args,
4510     IPC::Message* reply_message) {
4511   // This observer will delete itself.
4512   new NTPInfoObserver(this, reply_message, &consumer_);
4513 }
4514 
MoveNTPMostVisitedThumbnail(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)4515 void TestingAutomationProvider::MoveNTPMostVisitedThumbnail(
4516     Browser* browser,
4517     DictionaryValue* args,
4518     IPC::Message* reply_message) {
4519   AutomationJSONReply reply(this, reply_message);
4520   std::string url, error;
4521   int index, old_index;
4522   if (!args->GetString("url", &url)) {
4523     reply.SendError("Missing or invalid 'url' key.");
4524     return;
4525   }
4526   if (!args->GetInteger("index", &index)) {
4527     reply.SendError("Missing or invalid 'index' key.");
4528     return;
4529   }
4530   if (!args->GetInteger("old_index", &old_index)) {
4531     reply.SendError("Missing or invalid 'old_index' key");
4532     return;
4533   }
4534   history::TopSites* top_sites = browser->profile()->GetTopSites();
4535   if (!top_sites) {
4536     reply.SendError("TopSites service is not initialized.");
4537     return;
4538   }
4539   GURL swapped;
4540   // If thumbnail A is switching positions with a pinned thumbnail B, B
4541   // should be pinned in the old index of A.
4542   if (top_sites->GetPinnedURLAtIndex(index, &swapped)) {
4543     top_sites->AddPinnedURL(swapped, old_index);
4544   }
4545   top_sites->AddPinnedURL(GURL(url), index);
4546   reply.SendSuccess(NULL);
4547 }
4548 
RemoveNTPMostVisitedThumbnail(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)4549 void TestingAutomationProvider::RemoveNTPMostVisitedThumbnail(
4550     Browser* browser,
4551     DictionaryValue* args,
4552     IPC::Message* reply_message) {
4553   AutomationJSONReply reply(this, reply_message);
4554   std::string url;
4555   if (!args->GetString("url", &url)) {
4556     reply.SendError("Missing or invalid 'url' key.");
4557     return;
4558   }
4559   history::TopSites* top_sites = browser->profile()->GetTopSites();
4560   if (!top_sites) {
4561     reply.SendError("TopSites service is not initialized.");
4562     return;
4563   }
4564   top_sites->AddBlacklistedURL(GURL(url));
4565   reply.SendSuccess(NULL);
4566 }
4567 
UnpinNTPMostVisitedThumbnail(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)4568 void TestingAutomationProvider::UnpinNTPMostVisitedThumbnail(
4569     Browser* browser,
4570     DictionaryValue* args,
4571     IPC::Message* reply_message) {
4572   AutomationJSONReply reply(this, reply_message);
4573   std::string url;
4574   if (!args->GetString("url", &url)) {
4575     reply.SendError("Missing or invalid 'url' key.");
4576     return;
4577   }
4578   history::TopSites* top_sites = browser->profile()->GetTopSites();
4579   if (!top_sites) {
4580     reply.SendError("TopSites service is not initialized.");
4581     return;
4582   }
4583   top_sites->RemovePinnedURL(GURL(url));
4584   reply.SendSuccess(NULL);
4585 }
4586 
RestoreAllNTPMostVisitedThumbnails(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)4587 void TestingAutomationProvider::RestoreAllNTPMostVisitedThumbnails(
4588     Browser* browser,
4589     DictionaryValue* args,
4590     IPC::Message* reply_message) {
4591   AutomationJSONReply reply(this, reply_message);
4592   history::TopSites* top_sites = browser->profile()->GetTopSites();
4593   if (!top_sites) {
4594     reply.SendError("TopSites service is not initialized.");
4595     return;
4596   }
4597   top_sites->ClearBlacklistedURLs();
4598   reply.SendSuccess(NULL);
4599 }
4600 
KillRendererProcess(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)4601 void TestingAutomationProvider::KillRendererProcess(
4602     Browser* browser,
4603     DictionaryValue* args,
4604     IPC::Message* reply_message) {
4605   int pid;
4606   if (!args->GetInteger("pid", &pid)) {
4607     AutomationJSONReply(this, reply_message)
4608         .SendError("'pid' key missing or invalid.");
4609     return;
4610   }
4611   base::ProcessHandle process;
4612   if (!base::OpenProcessHandle(static_cast<base::ProcessId>(pid), &process)) {
4613     AutomationJSONReply(this, reply_message).SendError(base::StringPrintf(
4614         "Failed to open process handle for pid %d", pid));
4615     return;
4616   }
4617   new RendererProcessClosedObserver(this, reply_message);
4618   base::KillProcess(process, 0, false);
4619   base::CloseProcessHandle(process);
4620 }
4621 
BuildWebKeyEventFromArgs(DictionaryValue * args,std::string * error,NativeWebKeyboardEvent * event)4622 bool TestingAutomationProvider::BuildWebKeyEventFromArgs(
4623     DictionaryValue* args,
4624     std::string* error,
4625     NativeWebKeyboardEvent* event) {
4626   int type, modifiers;
4627   bool is_system_key;
4628   string16 unmodified_text, text;
4629   std::string key_identifier;
4630   if (!args->GetInteger("type", &type)) {
4631     *error = "'type' missing or invalid.";
4632     return false;
4633   }
4634   if (!args->GetBoolean("isSystemKey", &is_system_key)) {
4635     *error = "'isSystemKey' missing or invalid.";
4636     return false;
4637   }
4638   if (!args->GetString("unmodifiedText", &unmodified_text)) {
4639     *error = "'unmodifiedText' missing or invalid.";
4640     return false;
4641   }
4642   if (!args->GetString("text", &text)) {
4643     *error = "'text' missing or invalid.";
4644     return false;
4645   }
4646   if (!args->GetInteger("nativeKeyCode", &event->nativeKeyCode)) {
4647     *error = "'nativeKeyCode' missing or invalid.";
4648     return false;
4649   }
4650   if (!args->GetInteger("windowsKeyCode", &event->windowsKeyCode)) {
4651     *error = "'windowsKeyCode' missing or invalid.";
4652     return false;
4653   }
4654   if (!args->GetInteger("modifiers", &modifiers)) {
4655     *error = "'modifiers' missing or invalid.";
4656     return false;
4657   }
4658   if (args->GetString("keyIdentifier", &key_identifier)) {
4659     base::strlcpy(event->keyIdentifier,
4660                   key_identifier.c_str(),
4661                   WebKit::WebKeyboardEvent::keyIdentifierLengthCap);
4662   } else {
4663     event->setKeyIdentifierFromWindowsKeyCode();
4664   }
4665 
4666   if (type == automation::kRawKeyDownType) {
4667     event->type = WebKit::WebInputEvent::RawKeyDown;
4668   } else if (type == automation::kKeyDownType) {
4669     event->type = WebKit::WebInputEvent::KeyDown;
4670   } else if (type == automation::kKeyUpType) {
4671     event->type = WebKit::WebInputEvent::KeyUp;
4672   } else if (type == automation::kCharType) {
4673     event->type = WebKit::WebInputEvent::Char;
4674   } else {
4675     *error = "'type' refers to an unrecognized keyboard event type";
4676     return false;
4677   }
4678 
4679   string16 unmodified_text_truncated = unmodified_text.substr(
4680       0, WebKit::WebKeyboardEvent::textLengthCap - 1);
4681   memcpy(event->unmodifiedText,
4682          unmodified_text_truncated.c_str(),
4683          unmodified_text_truncated.length() + 1);
4684   string16 text_truncated = text.substr(
4685       0, WebKit::WebKeyboardEvent::textLengthCap - 1);
4686   memcpy(event->text, text_truncated.c_str(), text_truncated.length() + 1);
4687 
4688   event->modifiers = 0;
4689   if (modifiers & automation::kShiftKeyMask)
4690     event->modifiers |= WebKit::WebInputEvent::ShiftKey;
4691   if (modifiers & automation::kControlKeyMask)
4692     event->modifiers |= WebKit::WebInputEvent::ControlKey;
4693   if (modifiers & automation::kAltKeyMask)
4694     event->modifiers |= WebKit::WebInputEvent::AltKey;
4695   if (modifiers & automation::kMetaKeyMask)
4696     event->modifiers |= WebKit::WebInputEvent::MetaKey;
4697 
4698   event->isSystemKey = is_system_key;
4699   event->timeStampSeconds = base::Time::Now().ToDoubleT();
4700   event->skip_in_browser = true;
4701   return true;
4702 }
4703 
SendWebkitKeyEvent(DictionaryValue * args,IPC::Message * reply_message)4704 void TestingAutomationProvider::SendWebkitKeyEvent(
4705     DictionaryValue* args,
4706     IPC::Message* reply_message) {
4707   NativeWebKeyboardEvent event;
4708   // BuildWebKeyEventFromArgs handles telling what when wrong and sending
4709   // the reply message, if it failed we just have to stop here.
4710   std::string error;
4711   if (!BuildWebKeyEventFromArgs(args, &error, &event)) {
4712     AutomationJSONReply(this, reply_message).SendError(error);
4713     return;
4714   }
4715 
4716   TabContents* tab_contents;
4717   if (!GetTabFromJSONArgs(args, &tab_contents, &error)) {
4718     AutomationJSONReply(this, reply_message).SendError(error);
4719     return;
4720   }
4721   new InputEventAckNotificationObserver(this, reply_message, event.type);
4722   tab_contents->render_view_host()->ForwardKeyboardEvent(event);
4723 }
4724 
SendOSLevelKeyEventToTab(DictionaryValue * args,IPC::Message * reply_message)4725 void TestingAutomationProvider::SendOSLevelKeyEventToTab(
4726     DictionaryValue* args,
4727     IPC::Message* reply_message) {
4728   int modifiers, keycode;
4729   if (!args->GetInteger("keyCode", &keycode)) {
4730     AutomationJSONReply(this, reply_message)
4731         .SendError("'keyCode' missing or invalid.");
4732     return;
4733   }
4734   if (!args->GetInteger("modifiers", &modifiers)) {
4735     AutomationJSONReply(this, reply_message)
4736         .SendError("'modifiers' missing or invalid.");
4737     return;
4738   }
4739 
4740   std::string error;
4741   Browser* browser;
4742   TabContents* tab_contents;
4743   if (!GetBrowserAndTabFromJSONArgs(args, &browser, &tab_contents, &error)) {
4744     AutomationJSONReply(this, reply_message).SendError(error);
4745     return;
4746   }
4747   // The key events will be sent to the browser window, we need the current tab
4748   // containing the element we send the text in to be shown.
4749   browser->ActivateTabAt(
4750       browser->GetIndexOfController(&tab_contents->controller()), true);
4751 
4752   BrowserWindow* browser_window = browser->window();
4753   if (!browser_window) {
4754     AutomationJSONReply(this, reply_message)
4755         .SendError("Could not get the browser window");
4756     return;
4757   }
4758   gfx::NativeWindow window = browser_window->GetNativeHandle();
4759   if (!window) {
4760     AutomationJSONReply(this, reply_message)
4761         .SendError("Could not get the browser window handle");
4762     return;
4763   }
4764 
4765   bool control = !!(modifiers & automation::kControlKeyMask);
4766   bool shift = !!(modifiers & automation::kShiftKeyMask);
4767   bool alt = !!(modifiers & automation::kAltKeyMask);
4768   bool meta = !!(modifiers & automation::kMetaKeyMask);
4769   if (!ui_controls::SendKeyPressNotifyWhenDone(
4770           window, static_cast<ui::KeyboardCode>(keycode),
4771           control, shift, alt, meta,
4772           NewRunnableMethod(this,
4773               &TestingAutomationProvider::SendSuccessReply, reply_message))) {
4774     AutomationJSONReply(this, reply_message)
4775         .SendError("Could not send the native key event");
4776   }
4777 }
4778 
SendSuccessReply(IPC::Message * reply_message)4779 void TestingAutomationProvider::SendSuccessReply(IPC::Message* reply_message) {
4780   AutomationJSONReply(this, reply_message).SendSuccess(NULL);
4781 }
4782 
4783 // Sample JSON input: { "command": "GetNTPThumbnailMode" }
4784 // For output, refer to GetNTPThumbnailMode() in
4785 // chrome/test/pyautolib/pyauto.py.
GetNTPThumbnailMode(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)4786 void TestingAutomationProvider::GetNTPThumbnailMode(
4787     Browser* browser,
4788     DictionaryValue* args,
4789     IPC::Message* reply_message) {
4790   const int shown_sections = ShownSectionsHandler::GetShownSections(
4791       browser->profile()->GetPrefs());
4792 
4793   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
4794   return_value->SetBoolean("apps", shown_sections & APPS ? true : false);
4795   return_value->SetBoolean("most_visited",
4796                            shown_sections & THUMB ? true : false);
4797 
4798   AutomationJSONReply reply(this, reply_message);
4799   reply.SendSuccess(return_value.get());
4800 }
4801 
4802 // Sample JSON input: { "command": "SetNTPThumbnailMode", "section": "apps",
4803 //                      "turn_on": true }
4804 // Refer to SetNTPThumbnailMode() in chrome/test/pyautolib/pyauto.py for
4805 // all possible input values.
4806 // Sample JSON output: {}
SetNTPThumbnailMode(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)4807 void TestingAutomationProvider::SetNTPThumbnailMode(
4808     Browser* browser,
4809     DictionaryValue* args,
4810     IPC::Message* reply_message) {
4811   AutomationJSONReply reply(this, reply_message);
4812   std::string section_name;
4813   bool turn_on;
4814   if (!args->GetString("section", &section_name) ||
4815       !args->GetBoolean("turn_on", &turn_on)) {
4816     reply.SendError("Invalid or missing args");
4817     return;
4818   }
4819 
4820   PrefService* prefs = browser->profile()->GetPrefs();
4821   Section section;
4822   if (section_name.compare("apps") == 0) {
4823     section = APPS;
4824   } else if (section_name.compare("most_visited") == 0) {
4825     section = THUMB;
4826   } else if (section_name.compare("recently_closed") == 0) {
4827     reply.SendError("Thumbnail mode does not apply to the recently closed "
4828                     "section.");
4829     return;
4830   } else {
4831     reply.SendError(StringPrintf("Unexpected section name: '%s'",
4832                                  section_name.c_str()));
4833     return;
4834   }
4835 
4836   if (turn_on) {
4837     ShownSectionsHandler::SetShownSection(prefs, section);
4838   } else {
4839     int shown_sections = ShownSectionsHandler::GetShownSections(prefs);
4840     // Change the bit for the relevant section in the bitmask to 0.
4841     shown_sections &= ~(0xFFFFFFFF & section);
4842     prefs->SetInteger(prefs::kNTPShownSections, shown_sections);
4843   }
4844 
4845   reply.SendSuccess(NULL);
4846 }
4847 
4848 // Sample JSON input: { "command": "GetNTPMenuMode" }
4849 // For output, refer to GetNTPMenuMode() in
4850 // chrome/test/pyautolib/pyauto.py.
GetNTPMenuMode(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)4851 void TestingAutomationProvider::GetNTPMenuMode(
4852     Browser* browser,
4853     DictionaryValue* args,
4854     IPC::Message* reply_message) {
4855   const int shown_sections = ShownSectionsHandler::GetShownSections(
4856       browser->profile()->GetPrefs());
4857 
4858   scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
4859   return_value->SetBoolean("apps", shown_sections & MENU_APPS ? true : false);
4860   return_value->SetBoolean("most_visited",
4861                            shown_sections & MENU_THUMB ? true : false);
4862   return_value->SetBoolean("recently_closed",
4863                            shown_sections & MENU_RECENT ? true : false);
4864 
4865   AutomationJSONReply reply(this, reply_message);
4866   reply.SendSuccess(return_value.get());
4867 }
4868 
4869 // Sample JSON input: { "command": "SetNTPMenuMode", "section": "apps",
4870 //                      "turn_on": false }
4871 // Refer to SetNTPMenuMode() in chrome/test/pyautolib/pyauto.py for all possible
4872 // input values.
4873 // Sample JSON output: {}
SetNTPMenuMode(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)4874 void TestingAutomationProvider::SetNTPMenuMode(
4875     Browser* browser,
4876     DictionaryValue* args,
4877     IPC::Message* reply_message) {
4878   AutomationJSONReply reply(this, reply_message);
4879   std::string section_name;
4880   bool turn_on;
4881   if (!args->GetString("section", &section_name) ||
4882       !args->GetBoolean("turn_on", &turn_on)) {
4883     reply.SendError("Invalid or missing args");
4884     return;
4885   }
4886 
4887   PrefService* prefs = browser->profile()->GetPrefs();
4888   Section section;
4889   if (section_name.compare("apps") == 0) {
4890     section = MENU_APPS;
4891   } else if (section_name.compare("most_visited") == 0) {
4892     section = MENU_THUMB;
4893   } else if (section_name.compare("recently_closed") == 0) {
4894     section = MENU_RECENT;
4895   } else {
4896     reply.SendError(StringPrintf("Unexpected section name: '%s'",
4897                                  section_name.c_str()));
4898     return;
4899   }
4900 
4901   int shown_sections = ShownSectionsHandler::GetShownSections(prefs);
4902   if (turn_on) {
4903     // Change the bit for the relevant section in the bitmask to 1.
4904     shown_sections |= section;
4905   } else {
4906     // Change the bit for the relevant section in the bitmask to 0.
4907     shown_sections &= ~(0xFFFFFFFF & section);
4908   }
4909   prefs->SetInteger(prefs::kNTPShownSections, shown_sections);
4910 
4911   reply.SendSuccess(NULL);
4912 }
4913 
4914 // Sample JSON input: { "command": "LaunchApp",
4915 //                      "id": "ahfgeienlihckogmohjhadlkjgocpleb" }
4916 // Sample JSON output: {}
LaunchApp(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)4917 void TestingAutomationProvider::LaunchApp(
4918     Browser* browser,
4919     DictionaryValue* args,
4920     IPC::Message* reply_message) {
4921   std::string id;
4922   if (!args->GetString("id", &id)) {
4923     AutomationJSONReply(this, reply_message).SendError(
4924         "Must include string id.");
4925     return;
4926   }
4927 
4928   ExtensionService* service = browser->profile()->GetExtensionService();
4929   if (!service) {
4930     AutomationJSONReply(this, reply_message).SendError(
4931         "No extensions service.");
4932     return;
4933   }
4934 
4935   const Extension* extension = service->GetExtensionById(
4936       id, false  /* do not include disabled extensions */);
4937   if (!extension) {
4938     AutomationJSONReply(this, reply_message).SendError(
4939         StringPrintf("Extension with ID '%s' doesn't exist or is disabled.",
4940                      id.c_str()));
4941     return;
4942   }
4943 
4944   // Look at preferences to find the right launch container.  If no preference
4945   // is set, launch as a regular tab.
4946   extension_misc::LaunchContainer launch_container =
4947       service->extension_prefs()->GetLaunchContainer(
4948           extension, ExtensionPrefs::LAUNCH_REGULAR);
4949 
4950   TabContents* old_contents = browser->GetSelectedTabContents();
4951   if (!old_contents) {
4952     AutomationJSONReply(this, reply_message).SendError(
4953         "Cannot identify selected tab contents.");
4954     return;
4955   }
4956 
4957   // This observer will delete itself.
4958   new AppLaunchObserver(&old_contents->controller(), this, reply_message,
4959                         launch_container);
4960   Browser::OpenApplication(profile(), extension, launch_container,
4961                            old_contents);
4962 }
4963 
4964 // Sample JSON input: { "command": "SetAppLaunchType",
4965 //                      "id": "ahfgeienlihckogmohjhadlkjgocpleb",
4966 //                      "launch_type": "pinned" }
4967 // Sample JSON output: {}
SetAppLaunchType(Browser * browser,DictionaryValue * args,IPC::Message * reply_message)4968 void TestingAutomationProvider::SetAppLaunchType(
4969     Browser* browser,
4970     DictionaryValue* args,
4971     IPC::Message* reply_message) {
4972   AutomationJSONReply reply(this, reply_message);
4973 
4974   std::string id;
4975   if (!args->GetString("id", &id)) {
4976     reply.SendError("Must include string id.");
4977     return;
4978   }
4979 
4980   std::string launch_type_str;
4981   if (!args->GetString("launch_type", &launch_type_str)) {
4982     reply.SendError("Must specify app launch type.");
4983     return;
4984   }
4985 
4986   ExtensionService* service = browser->profile()->GetExtensionService();
4987   if (!service) {
4988     reply.SendError("No extensions service.");
4989     return;
4990   }
4991 
4992   const Extension* extension = service->GetExtensionById(
4993       id, true  /* include disabled extensions */);
4994   if (!extension) {
4995     reply.SendError(
4996         StringPrintf("Extension with ID '%s' doesn't exist.", id.c_str()));
4997     return;
4998   }
4999 
5000   ExtensionPrefs::LaunchType launch_type;
5001   if (launch_type_str == "pinned") {
5002     launch_type = ExtensionPrefs::LAUNCH_PINNED;
5003   } else if (launch_type_str == "regular") {
5004     launch_type = ExtensionPrefs::LAUNCH_REGULAR;
5005   } else if (launch_type_str == "fullscreen") {
5006     launch_type = ExtensionPrefs::LAUNCH_FULLSCREEN;
5007   } else if (launch_type_str == "window") {
5008     launch_type = ExtensionPrefs::LAUNCH_WINDOW;
5009   } else {
5010     reply.SendError(
5011         StringPrintf("Unexpected launch type '%s'.", launch_type_str.c_str()));
5012     return;
5013   }
5014 
5015   service->extension_prefs()->SetLaunchType(extension->id(), launch_type);
5016   reply.SendSuccess(NULL);
5017 }
5018 
WaitForAllTabsToStopLoading(DictionaryValue * args,IPC::Message * reply_message)5019 void TestingAutomationProvider::WaitForAllTabsToStopLoading(
5020     DictionaryValue* args,
5021     IPC::Message* reply_message) {
5022   // This class will send the message immediately if no tab is loading.
5023   new AllTabsStoppedLoadingObserver(this, reply_message);
5024 }
5025 
GetIndicesFromTab(DictionaryValue * args,IPC::Message * reply_message)5026 void TestingAutomationProvider::GetIndicesFromTab(
5027     DictionaryValue* args,
5028     IPC::Message* reply_message) {
5029   AutomationJSONReply reply(this, reply_message);
5030   int id_or_handle = 0;
5031   bool has_id = args->HasKey("tab_id");
5032   bool has_handle = args->HasKey("tab_handle");
5033   if (has_id && has_handle) {
5034     reply.SendError(
5035         "Both 'tab_id' and 'tab_handle' were specified. Only one is allowed");
5036     return;
5037   } else if (!has_id && !has_handle) {
5038     reply.SendError("Either 'tab_id' or 'tab_handle' must be specified");
5039     return;
5040   }
5041   if (has_id && !args->GetInteger("tab_id", &id_or_handle)) {
5042     reply.SendError("'tab_id' is invalid");
5043     return;
5044   }
5045   if (has_handle && (!args->GetInteger("tab_handle", &id_or_handle) ||
5046                      !tab_tracker_->ContainsHandle(id_or_handle))) {
5047     reply.SendError("'tab_handle' is invalid");
5048     return;
5049   }
5050   int id = id_or_handle;
5051   if (has_handle)
5052     id = tab_tracker_->GetResource(id_or_handle)->session_id().id();
5053   BrowserList::const_iterator iter = BrowserList::begin();
5054   int browser_index = 0;
5055   for (; iter != BrowserList::end(); ++iter, ++browser_index) {
5056     Browser* browser = *iter;
5057     for (int tab_index = 0; tab_index < browser->tab_count(); ++tab_index) {
5058       TabContents* tab = browser->GetTabContentsAt(tab_index);
5059       if (tab->controller().session_id().id() == id) {
5060         DictionaryValue dict;
5061         dict.SetInteger("windex", browser_index);
5062         dict.SetInteger("tab_index", tab_index);
5063         reply.SendSuccess(&dict);
5064         return;
5065       }
5066     }
5067   }
5068   reply.SendError("Could not find tab among current browser windows");
5069 }
5070 
NavigateToURL(DictionaryValue * args,IPC::Message * reply_message)5071 void TestingAutomationProvider::NavigateToURL(
5072     DictionaryValue* args,
5073     IPC::Message* reply_message) {
5074   int navigation_count;
5075   std::string url, error;
5076   Browser* browser;
5077   TabContents* tab_contents;
5078   if (!GetBrowserAndTabFromJSONArgs(args, &browser, &tab_contents, &error)) {
5079     AutomationJSONReply(this, reply_message).SendError(error);
5080     return;
5081   }
5082   if (!args->GetString("url", &url)) {
5083     AutomationJSONReply(this, reply_message)
5084         .SendError("'url' missing or invalid");
5085     return;
5086   }
5087   if (!args->GetInteger("navigation_count", &navigation_count)) {
5088     AutomationJSONReply(this, reply_message)
5089         .SendError("'navigation_count' missing or invalid");
5090     return;
5091   }
5092   new NavigationNotificationObserver(
5093       &tab_contents->controller(), this, reply_message,
5094       navigation_count, false, true);
5095   browser->OpenURLFromTab(
5096       tab_contents, GURL(url), GURL(), CURRENT_TAB, PageTransition::TYPED);
5097 }
5098 
ExecuteJavascriptJSON(DictionaryValue * args,IPC::Message * reply_message)5099 void TestingAutomationProvider::ExecuteJavascriptJSON(
5100     DictionaryValue* args,
5101     IPC::Message* reply_message) {
5102   string16 frame_xpath, javascript;
5103   std::string error;
5104   TabContents* tab_contents;
5105   if (!GetTabFromJSONArgs(args, &tab_contents, &error)) {
5106     AutomationJSONReply(this, reply_message).SendError(error);
5107     return;
5108   }
5109   if (!args->GetString("frame_xpath", &frame_xpath)) {
5110     AutomationJSONReply(this, reply_message)
5111         .SendError("'frame_xpath' missing or invalid");
5112     return;
5113   }
5114   if (!args->GetString("javascript", &javascript)) {
5115     AutomationJSONReply(this, reply_message)
5116         .SendError("'javascript' missing or invalid");
5117     return;
5118   }
5119 
5120   // Set the routing id of this message with the controller.
5121   // This routing id needs to be remembered for the reverse
5122   // communication while sending back the response of
5123   // this javascript execution.
5124   std::string set_automation_id;
5125   base::SStringPrintf(&set_automation_id,
5126                       "window.domAutomationController.setAutomationId(%d);",
5127                       reply_message->routing_id());
5128 
5129   new DomOperationMessageSender(this, reply_message, true);
5130   tab_contents->render_view_host()->ExecuteJavascriptInWebFrame(
5131       frame_xpath, UTF8ToUTF16(set_automation_id));
5132   tab_contents->render_view_host()->ExecuteJavascriptInWebFrame(
5133       frame_xpath, javascript);
5134 }
5135 
GoForward(DictionaryValue * args,IPC::Message * reply_message)5136 void TestingAutomationProvider::GoForward(
5137     DictionaryValue* args,
5138     IPC::Message* reply_message) {
5139   TabContents* tab_contents;
5140   std::string error;
5141   if (!GetTabFromJSONArgs(args, &tab_contents, &error)) {
5142     AutomationJSONReply(this, reply_message).SendError(error);
5143     return;
5144   }
5145   NavigationController& controller = tab_contents->controller();
5146   if (!controller.CanGoForward()) {
5147     DictionaryValue dict;
5148     dict.SetBoolean("did_go_forward", false);
5149     AutomationJSONReply(this, reply_message).SendSuccess(&dict);
5150     return;
5151   }
5152   new NavigationNotificationObserver(&controller, this, reply_message,
5153                                      1, false, true);
5154   controller.GoForward();
5155 }
5156 
GoBack(DictionaryValue * args,IPC::Message * reply_message)5157 void TestingAutomationProvider::GoBack(
5158     DictionaryValue* args,
5159     IPC::Message* reply_message) {
5160   TabContents* tab_contents;
5161   std::string error;
5162   if (!GetTabFromJSONArgs(args, &tab_contents, &error)) {
5163     AutomationJSONReply(this, reply_message).SendError(error);
5164     return;
5165   }
5166   NavigationController& controller = tab_contents->controller();
5167   if (!controller.CanGoBack()) {
5168     DictionaryValue dict;
5169     dict.SetBoolean("did_go_back", false);
5170     AutomationJSONReply(this, reply_message).SendSuccess(&dict);
5171     return;
5172   }
5173   new NavigationNotificationObserver(&controller, this, reply_message,
5174                                      1, false, true);
5175   controller.GoBack();
5176 }
5177 
ReloadJSON(DictionaryValue * args,IPC::Message * reply_message)5178 void TestingAutomationProvider::ReloadJSON(
5179     DictionaryValue* args,
5180     IPC::Message* reply_message) {
5181   TabContents* tab_contents;
5182   std::string error;
5183   if (!GetTabFromJSONArgs(args, &tab_contents, &error)) {
5184     AutomationJSONReply(this, reply_message).SendError(error);
5185     return;
5186   }
5187   NavigationController& controller = tab_contents->controller();
5188   new NavigationNotificationObserver(&controller, this, reply_message,
5189                                      1, false, true);
5190   controller.Reload(false);
5191 }
5192 
GetTabURLJSON(DictionaryValue * args,IPC::Message * reply_message)5193 void TestingAutomationProvider::GetTabURLJSON(
5194     DictionaryValue* args,
5195     IPC::Message* reply_message) {
5196   AutomationJSONReply reply(this, reply_message);
5197   TabContents* tab_contents;
5198   std::string error;
5199   if (!GetTabFromJSONArgs(args, &tab_contents, &error)) {
5200     reply.SendError(error);
5201     return;
5202   }
5203   DictionaryValue dict;
5204   dict.SetString("url", tab_contents->GetURL().possibly_invalid_spec());
5205   reply.SendSuccess(&dict);
5206 }
5207 
GetTabTitleJSON(DictionaryValue * args,IPC::Message * reply_message)5208 void TestingAutomationProvider::GetTabTitleJSON(
5209     DictionaryValue* args,
5210     IPC::Message* reply_message) {
5211   AutomationJSONReply reply(this, reply_message);
5212   TabContents* tab_contents;
5213   std::string error;
5214   if (!GetTabFromJSONArgs(args, &tab_contents, &error)) {
5215     reply.SendError(error);
5216     return;
5217   }
5218   DictionaryValue dict;
5219   dict.SetString("title", tab_contents->GetTitle());
5220   reply.SendSuccess(&dict);
5221 }
5222 
CaptureEntirePageJSON(DictionaryValue * args,IPC::Message * reply_message)5223 void TestingAutomationProvider::CaptureEntirePageJSON(
5224     DictionaryValue* args,
5225     IPC::Message* reply_message) {
5226   TabContents* tab_contents;
5227   std::string error;
5228 
5229   if (!GetTabFromJSONArgs(args, &tab_contents, &error)) {
5230     AutomationJSONReply(this, reply_message).SendError(error);
5231     return;
5232   }
5233 
5234   FilePath::StringType path_str;
5235   if (!args->GetString("path", &path_str)) {
5236     AutomationJSONReply(this, reply_message)
5237         .SendError("'path' missing or invalid");
5238     return;
5239   }
5240 
5241   RenderViewHost* render_view = tab_contents->render_view_host();
5242   if (render_view) {
5243     FilePath path(path_str);
5244     // This will delete itself when finished.
5245     PageSnapshotTaker* snapshot_taker = new PageSnapshotTaker(
5246         this, reply_message, render_view, path);
5247     snapshot_taker->Start();
5248   } else {
5249     AutomationJSONReply(this, reply_message)
5250         .SendError("Tab has no associated RenderViewHost");
5251   }
5252 }
5253 
GetCookiesJSON(DictionaryValue * args,IPC::Message * reply_message)5254 void TestingAutomationProvider::GetCookiesJSON(
5255     DictionaryValue* args, IPC::Message* reply_message) {
5256   automation_util::GetCookiesJSON(this, args, reply_message);
5257 }
5258 
DeleteCookieJSON(DictionaryValue * args,IPC::Message * reply_message)5259 void TestingAutomationProvider::DeleteCookieJSON(
5260     DictionaryValue* args, IPC::Message* reply_message) {
5261   automation_util::DeleteCookieJSON(this, args, reply_message);
5262 }
5263 
SetCookieJSON(DictionaryValue * args,IPC::Message * reply_message)5264 void TestingAutomationProvider::SetCookieJSON(
5265     DictionaryValue* args, IPC::Message* reply_message) {
5266   automation_util::SetCookieJSON(this, args, reply_message);
5267 }
5268 
GetTabIds(DictionaryValue * args,IPC::Message * reply_message)5269 void TestingAutomationProvider::GetTabIds(
5270     DictionaryValue* args, IPC::Message* reply_message) {
5271   ListValue* id_list = new ListValue();
5272   BrowserList::const_iterator iter = BrowserList::begin();
5273   for (; iter != BrowserList::end(); ++iter) {
5274     Browser* browser = *iter;
5275     for (int i = 0; i < browser->tab_count(); ++i) {
5276       int id = browser->GetTabContentsAt(i)->controller().session_id().id();
5277       id_list->Append(Value::CreateIntegerValue(id));
5278     }
5279   }
5280   DictionaryValue dict;
5281   dict.Set("ids", id_list);
5282   AutomationJSONReply(this, reply_message).SendSuccess(&dict);
5283 }
5284 
IsTabIdValid(DictionaryValue * args,IPC::Message * reply_message)5285 void TestingAutomationProvider::IsTabIdValid(
5286     DictionaryValue* args, IPC::Message* reply_message) {
5287   AutomationJSONReply reply(this, reply_message);
5288   int id;
5289   if (!args->GetInteger("id", &id)) {
5290     reply.SendError("'id' missing or invalid");
5291     return;
5292   }
5293   bool is_valid = false;
5294   BrowserList::const_iterator iter = BrowserList::begin();
5295   for (; iter != BrowserList::end(); ++iter) {
5296     Browser* browser = *iter;
5297     for (int i = 0; i < browser->tab_count(); ++i) {
5298       TabContents* tab = browser->GetTabContentsAt(i);
5299       if (tab->controller().session_id().id() == id) {
5300         is_valid = true;
5301         break;
5302       }
5303     }
5304   }
5305   DictionaryValue dict;
5306   dict.SetBoolean("is_valid", is_valid);
5307   reply.SendSuccess(&dict);
5308 }
5309 
CloseTabJSON(DictionaryValue * args,IPC::Message * reply_message)5310 void TestingAutomationProvider::CloseTabJSON(
5311     DictionaryValue* args, IPC::Message* reply_message) {
5312   AutomationJSONReply reply(this, reply_message);
5313   Browser* browser;
5314   TabContents* tab_contents;
5315   std::string error;
5316   if (!GetBrowserAndTabFromJSONArgs(args, &browser, &tab_contents, &error)) {
5317     reply.SendError(error);
5318     return;
5319   }
5320   browser->CloseTabContents(tab_contents);
5321   reply.SendSuccess(NULL);
5322 }
5323 
ActivateTabJSON(DictionaryValue * args,IPC::Message * reply_message)5324 void TestingAutomationProvider::ActivateTabJSON(
5325     DictionaryValue* args,
5326     IPC::Message* reply_message) {
5327   AutomationJSONReply reply(this, reply_message);
5328   Browser* browser;
5329   TabContents* tab_contents;
5330   std::string error;
5331   if (!GetBrowserAndTabFromJSONArgs(args, &browser, &tab_contents, &error)) {
5332     reply.SendError(error);
5333     return;
5334   }
5335   browser->ActivateTabAt(
5336       browser->GetIndexOfController(&tab_contents->controller()), true);
5337   reply.SendSuccess(NULL);
5338 }
5339 
5340 // Sample json input: { "command": "UpdateExtensionsNow" }
5341 // Sample json output: {}
UpdateExtensionsNow(DictionaryValue * args,IPC::Message * reply_message)5342 void TestingAutomationProvider::UpdateExtensionsNow(
5343     DictionaryValue* args,
5344     IPC::Message* reply_message) {
5345   ExtensionService* service = profile()->GetExtensionService();
5346   if (!service) {
5347     AutomationJSONReply(this, reply_message).SendError(
5348         "No extensions service.");
5349     return;
5350   }
5351 
5352   ExtensionUpdater* updater = service->updater();
5353   if (!updater) {
5354     AutomationJSONReply(this, reply_message).SendError(
5355         "No updater for extensions service.");
5356     return;
5357   }
5358 
5359   ExtensionProcessManager* manager = profile()->GetExtensionProcessManager();
5360   if (!manager) {
5361     AutomationJSONReply(this, reply_message).SendError(
5362         "No extension process manager.");
5363     return;
5364   }
5365 
5366   // Create a new observer that waits until the extensions have been fully
5367   // updated (we should not send the reply until after all extensions have
5368   // been updated).  This observer will delete itself.
5369   new ExtensionsUpdatedObserver(manager, this, reply_message);
5370   updater->CheckNow();
5371 }
5372 
GetChromeDriverAutomationVersion(DictionaryValue * args,IPC::Message * reply_message)5373 void TestingAutomationProvider::GetChromeDriverAutomationVersion(
5374     DictionaryValue* args,
5375     IPC::Message* reply_message) {
5376   DictionaryValue reply_dict;
5377   reply_dict.SetInteger("version", automation::kChromeDriverAutomationVersion);
5378   AutomationJSONReply(this, reply_message).SendSuccess(&reply_dict);
5379 }
5380 
WaitForTabCountToBecome(int browser_handle,int target_tab_count,IPC::Message * reply_message)5381 void TestingAutomationProvider::WaitForTabCountToBecome(
5382     int browser_handle,
5383     int target_tab_count,
5384     IPC::Message* reply_message) {
5385   if (!browser_tracker_->ContainsHandle(browser_handle)) {
5386     AutomationMsg_WaitForTabCountToBecome::WriteReplyParams(reply_message,
5387                                                             false);
5388     Send(reply_message);
5389     return;
5390   }
5391 
5392   Browser* browser = browser_tracker_->GetResource(browser_handle);
5393 
5394   // The observer will delete itself.
5395   new TabCountChangeObserver(this, browser, reply_message, target_tab_count);
5396 }
5397 
WaitForInfoBarCount(int tab_handle,size_t target_count,IPC::Message * reply_message)5398 void TestingAutomationProvider::WaitForInfoBarCount(
5399     int tab_handle,
5400     size_t target_count,
5401     IPC::Message* reply_message) {
5402   if (!tab_tracker_->ContainsHandle(tab_handle)) {
5403     AutomationMsg_WaitForInfoBarCount::WriteReplyParams(reply_message_, false);
5404     Send(reply_message_);
5405     return;
5406   }
5407 
5408   NavigationController* controller = tab_tracker_->GetResource(tab_handle);
5409   if (!controller) {
5410     AutomationMsg_WaitForInfoBarCount::WriteReplyParams(reply_message_, false);
5411     Send(reply_message_);
5412     return;
5413   }
5414 
5415   // The delegate will delete itself.
5416   new InfoBarCountObserver(this, reply_message, controller->tab_contents(),
5417                            target_count);
5418 }
5419 
5420 // Gets the current used encoding name of the page in the specified tab.
GetPageCurrentEncoding(int tab_handle,std::string * current_encoding)5421 void TestingAutomationProvider::GetPageCurrentEncoding(
5422     int tab_handle, std::string* current_encoding) {
5423   if (tab_tracker_->ContainsHandle(tab_handle)) {
5424     NavigationController* nav = tab_tracker_->GetResource(tab_handle);
5425     Browser* browser = FindAndActivateTab(nav);
5426     DCHECK(browser);
5427 
5428     if (browser->command_updater()->IsCommandEnabled(IDC_ENCODING_MENU))
5429       *current_encoding = nav->tab_contents()->encoding();
5430   }
5431 }
5432 
ShutdownSessionService(int handle,bool * result)5433 void TestingAutomationProvider::ShutdownSessionService(int handle,
5434                                                        bool* result) {
5435   if (browser_tracker_->ContainsHandle(handle)) {
5436     Browser* browser = browser_tracker_->GetResource(handle);
5437     browser->profile()->ShutdownSessionService();
5438     *result = true;
5439   } else {
5440     *result = false;
5441   }
5442 }
5443 
SetContentSetting(int handle,const std::string & host,ContentSettingsType content_type,ContentSetting setting,bool * success)5444 void TestingAutomationProvider::SetContentSetting(
5445     int handle,
5446     const std::string& host,
5447     ContentSettingsType content_type,
5448     ContentSetting setting,
5449     bool* success) {
5450   *success = false;
5451   if (browser_tracker_->ContainsHandle(handle)) {
5452     Browser* browser = browser_tracker_->GetResource(handle);
5453     HostContentSettingsMap* map =
5454         browser->profile()->GetHostContentSettingsMap();
5455     if (host.empty()) {
5456       map->SetDefaultContentSetting(content_type, setting);
5457     } else {
5458       map->SetContentSetting(ContentSettingsPattern(host),
5459                              content_type, "", setting);
5460     }
5461     *success = true;
5462   }
5463 }
5464 
LoadBlockedPlugins(int tab_handle,bool * success)5465 void TestingAutomationProvider::LoadBlockedPlugins(int tab_handle,
5466                                                    bool* success) {
5467   *success = false;
5468   if (tab_tracker_->ContainsHandle(tab_handle)) {
5469     NavigationController* nav = tab_tracker_->GetResource(tab_handle);
5470     if (!nav)
5471       return;
5472     TabContents* contents = nav->tab_contents();
5473     if (!contents)
5474       return;
5475     contents->render_view_host()->LoadBlockedPlugins();
5476     *success = true;
5477   }
5478 }
5479 
ResetToDefaultTheme()5480 void TestingAutomationProvider::ResetToDefaultTheme() {
5481   ThemeServiceFactory::GetForProfile(profile_)->UseDefaultTheme();
5482 }
5483 
WaitForProcessLauncherThreadToGoIdle(IPC::Message * reply_message)5484 void TestingAutomationProvider::WaitForProcessLauncherThreadToGoIdle(
5485     IPC::Message* reply_message) {
5486   new WaitForProcessLauncherThreadToGoIdleObserver(this, reply_message);
5487 }
5488 
GetParentBrowserOfTab(int tab_handle,int * browser_handle,bool * success)5489 void TestingAutomationProvider::GetParentBrowserOfTab(int tab_handle,
5490                                                       int* browser_handle,
5491                                                       bool* success) {
5492   *success = false;
5493   if (tab_tracker_->ContainsHandle(tab_handle)) {
5494     NavigationController* controller = tab_tracker_->GetResource(tab_handle);
5495     int index;
5496     Browser* browser = Browser::GetBrowserForController(controller, &index);
5497     if (browser) {
5498       *browser_handle = browser_tracker_->Add(browser);
5499       *success = true;
5500     }
5501   }
5502 }
5503 
5504 // TODO(brettw) change this to accept GURLs when history supports it
OnRedirectQueryComplete(HistoryService::Handle request_handle,GURL from_url,bool success,history::RedirectList * redirects)5505 void TestingAutomationProvider::OnRedirectQueryComplete(
5506     HistoryService::Handle request_handle,
5507     GURL from_url,
5508     bool success,
5509     history::RedirectList* redirects) {
5510   DCHECK_EQ(redirect_query_, request_handle);
5511   DCHECK(reply_message_ != NULL);
5512 
5513   std::vector<GURL> redirects_gurl;
5514   reply_message_->WriteBool(success);
5515   if (success) {
5516     for (size_t i = 0; i < redirects->size(); i++)
5517       redirects_gurl.push_back(redirects->at(i));
5518   }
5519 
5520   IPC::ParamTraits<std::vector<GURL> >::Write(reply_message_, redirects_gurl);
5521 
5522   Send(reply_message_);
5523   redirect_query_ = 0;
5524   reply_message_ = NULL;
5525 }
5526 
OnRemoveProvider()5527 void TestingAutomationProvider::OnRemoveProvider() {
5528   AutomationProviderList::GetInstance()->RemoveProvider(this);
5529 }
5530