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 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: 126 AutomationInterstitialPage(TabContents* tab, 127 const GURL& url, 128 const std::string& contents) 129 : InterstitialPage(tab, true, url), 130 contents_(contents) { 131 } 132 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 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 154 TestingAutomationProvider::~TestingAutomationProvider() { 155 BrowserList::RemoveObserver(this); 156 } 157 158 void TestingAutomationProvider::OnBrowserAdded(const Browser* browser) { 159 } 160 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 574 void TestingAutomationProvider::NavigationAsync(int handle, 575 const GURL& url, 576 bool* status) { 577 NavigationAsyncWithDisposition(handle, url, CURRENT_TAB, status); 578 } 579 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 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 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 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 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 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 713 void TestingAutomationProvider::GetBrowserWindowCount(int* window_count) { 714 *window_count = static_cast<int>(BrowserList::size()); 715 } 716 717 void TestingAutomationProvider::GetNormalBrowserWindowCount(int* window_count) { 718 *window_count = static_cast<int>( 719 BrowserList::GetBrowserCountForType(profile_, Browser::TYPE_NORMAL)); 720 } 721 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 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 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 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 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 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 805 void TestingAutomationProvider::GetBrowserLocale(string16* locale) { 806 *locale = ASCIIToUTF16(g_browser_process->GetApplicationLocale()); 807 } 808 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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. 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 1978 void TestingAutomationProvider::SavePackageShouldPromptUser( 1979 bool should_prompt) { 1980 SavePackage::SetShouldPromptUser(should_prompt); 1981 } 1982 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 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 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 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 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: {} 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: 2439 GetChildProcessHostInfoTask(base::WaitableEvent* event, 2440 ListValue* child_processes) 2441 : event_(event), 2442 child_processes_(child_processes) {} 2443 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. 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. 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. 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. 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. 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 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 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. 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" } 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. 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. 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 } 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. 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 } 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. 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" } 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. 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" } 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" } 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. 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. 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" } 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" } 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 // {} 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: "{}" 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. 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 } 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: {} 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. 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: {} 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. 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. 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 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. 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: {} 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. 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. 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. 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 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 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. 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: {} 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. 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: {} 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 } 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']} 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 } 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 } 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 } 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 */ 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 */ 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> 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 ¤t_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 */ 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, ¤t_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> 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> 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. 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. 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. 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. 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 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 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 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 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 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 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 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 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 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. 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: {} 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", §ion_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. 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: {} 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", §ion_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: {} 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: {} 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 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 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 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 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 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 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 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 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 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 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 5254 void TestingAutomationProvider::GetCookiesJSON( 5255 DictionaryValue* args, IPC::Message* reply_message) { 5256 automation_util::GetCookiesJSON(this, args, reply_message); 5257 } 5258 5259 void TestingAutomationProvider::DeleteCookieJSON( 5260 DictionaryValue* args, IPC::Message* reply_message) { 5261 automation_util::DeleteCookieJSON(this, args, reply_message); 5262 } 5263 5264 void TestingAutomationProvider::SetCookieJSON( 5265 DictionaryValue* args, IPC::Message* reply_message) { 5266 automation_util::SetCookieJSON(this, args, reply_message); 5267 } 5268 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 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 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 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: {} 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 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 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 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. 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 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 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 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 5480 void TestingAutomationProvider::ResetToDefaultTheme() { 5481 ThemeServiceFactory::GetForProfile(profile_)->UseDefaultTheme(); 5482 } 5483 5484 void TestingAutomationProvider::WaitForProcessLauncherThreadToGoIdle( 5485 IPC::Message* reply_message) { 5486 new WaitForProcessLauncherThreadToGoIdleObserver(this, reply_message); 5487 } 5488 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 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 5527 void TestingAutomationProvider::OnRemoveProvider() { 5528 AutomationProviderList::GetInstance()->RemoveProvider(this); 5529 } 5530