1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 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/bind.h" 13 #include "base/bind_helpers.h" 14 #include "base/command_line.h" 15 #include "base/files/file_path.h" 16 #include "base/json/json_reader.h" 17 #include "base/json/json_writer.h" 18 #include "base/json/string_escape.h" 19 #include "base/path_service.h" 20 #include "base/prefs/pref_service.h" 21 #include "base/process/process.h" 22 #include "base/process/process_iterator.h" 23 #include "base/sequenced_task_runner.h" 24 #include "base/strings/stringprintf.h" 25 #include "base/strings/utf_string_conversions.h" 26 #include "base/threading/thread_restrictions.h" 27 #include "base/time/time.h" 28 #include "chrome/app/chrome_command_ids.h" 29 #include "chrome/browser/autocomplete/autocomplete_controller.h" 30 #include "chrome/browser/autocomplete/autocomplete_match.h" 31 #include "chrome/browser/autocomplete/autocomplete_result.h" 32 #include "chrome/browser/automation/automation_browser_tracker.h" 33 #include "chrome/browser/automation/automation_provider_json.h" 34 #include "chrome/browser/automation/automation_provider_list.h" 35 #include "chrome/browser/automation/automation_provider_observers.h" 36 #include "chrome/browser/automation/automation_tab_tracker.h" 37 #include "chrome/browser/automation/automation_util.h" 38 #include "chrome/browser/automation/automation_window_tracker.h" 39 #include "chrome/browser/bookmarks/bookmark_model.h" 40 #include "chrome/browser/bookmarks/bookmark_model_factory.h" 41 #include "chrome/browser/bookmarks/bookmark_storage.h" 42 #include "chrome/browser/browser_process.h" 43 #include "chrome/browser/browser_shutdown.h" 44 #include "chrome/browser/chrome_notification_types.h" 45 #include "chrome/browser/content_settings/host_content_settings_map.h" 46 #include "chrome/browser/devtools/devtools_window.h" 47 #include "chrome/browser/download/download_prefs.h" 48 #include "chrome/browser/download/download_service.h" 49 #include "chrome/browser/download/download_service_factory.h" 50 #include "chrome/browser/download/download_shelf.h" 51 #include "chrome/browser/download/save_package_file_picker.h" 52 #include "chrome/browser/extensions/browser_action_test_util.h" 53 #include "chrome/browser/extensions/crx_installer.h" 54 #include "chrome/browser/extensions/extension_action.h" 55 #include "chrome/browser/extensions/extension_action_manager.h" 56 #include "chrome/browser/extensions/extension_host.h" 57 #include "chrome/browser/extensions/extension_process_manager.h" 58 #include "chrome/browser/extensions/extension_service.h" 59 #include "chrome/browser/extensions/extension_system.h" 60 #include "chrome/browser/extensions/extension_tab_util.h" 61 #include "chrome/browser/extensions/unpacked_installer.h" 62 #include "chrome/browser/extensions/updater/extension_updater.h" 63 #include "chrome/browser/history/history_service_factory.h" 64 #include "chrome/browser/history/top_sites.h" 65 #include "chrome/browser/infobars/confirm_infobar_delegate.h" 66 #include "chrome/browser/infobars/infobar_service.h" 67 #include "chrome/browser/lifetime/application_lifetime.h" 68 #include "chrome/browser/notifications/balloon.h" 69 #include "chrome/browser/notifications/balloon_collection.h" 70 #include "chrome/browser/notifications/balloon_notification_ui_manager.h" 71 #include "chrome/browser/notifications/notification.h" 72 #include "chrome/browser/password_manager/password_store.h" 73 #include "chrome/browser/password_manager/password_store_change.h" 74 #include "chrome/browser/password_manager/password_store_factory.h" 75 #include "chrome/browser/platform_util.h" 76 #include "chrome/browser/plugins/plugin_prefs.h" 77 #include "chrome/browser/profiles/profile.h" 78 #include "chrome/browser/profiles/profile_info_cache.h" 79 #include "chrome/browser/profiles/profile_manager.h" 80 #include "chrome/browser/profiles/profile_window.h" 81 #include "chrome/browser/profiles/profiles_state.h" 82 #include "chrome/browser/search_engines/template_url.h" 83 #include "chrome/browser/search_engines/template_url_service.h" 84 #include "chrome/browser/search_engines/template_url_service_factory.h" 85 #include "chrome/browser/sessions/session_service_factory.h" 86 #include "chrome/browser/sessions/session_tab_helper.h" 87 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h" 88 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h" 89 #include "chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h" 90 #include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h" 91 #include "chrome/browser/ui/bookmarks/bookmark_bar.h" 92 #include "chrome/browser/ui/browser_commands.h" 93 #include "chrome/browser/ui/browser_finder.h" 94 #include "chrome/browser/ui/browser_iterator.h" 95 #include "chrome/browser/ui/browser_list.h" 96 #include "chrome/browser/ui/browser_tabstrip.h" 97 #include "chrome/browser/ui/browser_window.h" 98 #include "chrome/browser/ui/extensions/application_launch.h" 99 #include "chrome/browser/ui/find_bar/find_bar.h" 100 #include "chrome/browser/ui/find_bar/find_bar_controller.h" 101 #include "chrome/browser/ui/fullscreen/fullscreen_controller.h" 102 #include "chrome/browser/ui/fullscreen/fullscreen_exit_bubble_type.h" 103 #include "chrome/browser/ui/host_desktop.h" 104 #include "chrome/browser/ui/login/login_prompt.h" 105 #include "chrome/browser/ui/omnibox/location_bar.h" 106 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h" 107 #include "chrome/browser/ui/omnibox/omnibox_view.h" 108 #include "chrome/browser/ui/search_engines/keyword_editor_controller.h" 109 #include "chrome/browser/ui/startup/startup_types.h" 110 #include "chrome/common/automation_constants.h" 111 #include "chrome/common/automation_id.h" 112 #include "chrome/common/automation_messages.h" 113 #include "chrome/common/chrome_constants.h" 114 #include "chrome/common/chrome_paths.h" 115 #include "chrome/common/chrome_switches.h" 116 #include "chrome/common/extensions/background_info.h" 117 #include "chrome/common/extensions/extension.h" 118 #include "chrome/common/extensions/manifest_url_handler.h" 119 #include "chrome/common/extensions/permissions/permission_set.h" 120 #include "chrome/common/extensions/permissions/permissions_data.h" 121 #include "chrome/common/pref_names.h" 122 #include "chrome/common/render_messages.h" 123 #include "content/public/browser/browser_child_process_host_iterator.h" 124 #include "content/public/browser/child_process_data.h" 125 #include "content/public/browser/favicon_status.h" 126 #include "content/public/browser/geolocation_provider.h" 127 #include "content/public/browser/interstitial_page.h" 128 #include "content/public/browser/interstitial_page_delegate.h" 129 #include "content/public/browser/navigation_entry.h" 130 #include "content/public/browser/notification_service.h" 131 #include "content/public/browser/plugin_service.h" 132 #include "content/public/browser/render_process_host.h" 133 #include "content/public/browser/render_view_host.h" 134 #include "content/public/browser/render_widget_host_view.h" 135 #include "content/public/browser/web_contents.h" 136 #include "content/public/common/child_process_host.h" 137 #include "content/public/common/common_param_traits.h" 138 #include "content/public/common/drop_data.h" 139 #include "content/public/common/geoposition.h" 140 #include "content/public/common/ssl_status.h" 141 #include "content/public/common/webplugininfo.h" 142 #include "extensions/browser/view_type_utils.h" 143 #include "extensions/common/url_pattern.h" 144 #include "extensions/common/url_pattern_set.h" 145 #include "net/cookies/cookie_store.h" 146 #include "third_party/WebKit/public/web/WebInputEvent.h" 147 #include "ui/base/events/event_constants.h" 148 #include "ui/base/keycodes/keyboard_codes.h" 149 #include "ui/base/ui_base_types.h" 150 151 #if defined(ENABLE_CONFIGURATION_POLICY) 152 #include "chrome/browser/policy/policy_service.h" 153 #endif 154 155 #if defined(OS_CHROMEOS) 156 #include "chromeos/dbus/dbus_thread_manager.h" 157 #endif 158 159 #if defined(OS_MACOSX) 160 #include <mach/mach.h> 161 #include <mach/mach_vm.h> 162 #endif 163 164 #if !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS)) 165 #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h" 166 #endif // !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS)) 167 168 #if defined(ENABLE_FULL_PRINTING) 169 #include "chrome/browser/printing/print_preview_dialog_controller.h" 170 #endif 171 172 using automation::Error; 173 using automation::ErrorCode; 174 using automation_util::SendErrorIfModalDialogActive; 175 using content::BrowserChildProcessHostIterator; 176 using content::BrowserContext; 177 using content::BrowserThread; 178 using content::ChildProcessHost; 179 using content::DownloadItem; 180 using content::DownloadManager; 181 using content::InterstitialPage; 182 using content::NativeWebKeyboardEvent; 183 using content::NavigationController; 184 using content::NavigationEntry; 185 using content::OpenURLParams; 186 using content::PluginService; 187 using content::Referrer; 188 using content::RenderViewHost; 189 using content::SSLStatus; 190 using content::WebContents; 191 using extensions::Extension; 192 using extensions::ExtensionActionManager; 193 using extensions::ExtensionList; 194 using extensions::Manifest; 195 196 namespace { 197 198 // Helper to reply asynchronously if |automation| is still valid. 199 void SendSuccessReply(base::WeakPtr<AutomationProvider> automation, 200 IPC::Message* reply_message) { 201 if (automation.get()) 202 AutomationJSONReply(automation.get(), reply_message).SendSuccess(NULL); 203 } 204 205 // Helper to process the result of CanEnablePlugin. 206 void DidEnablePlugin(base::WeakPtr<AutomationProvider> automation, 207 IPC::Message* reply_message, 208 const base::FilePath::StringType& path, 209 const std::string& error_msg, 210 bool did_enable) { 211 if (did_enable) { 212 SendSuccessReply(automation, reply_message); 213 } else { 214 if (automation.get()) { 215 AutomationJSONReply(automation.get(), reply_message) 216 .SendError(base::StringPrintf(error_msg.c_str(), path.c_str())); 217 } 218 } 219 } 220 221 // Helper to resolve the overloading of PostTask. 222 void PostTask(BrowserThread::ID id, const base::Closure& callback) { 223 BrowserThread::PostTask(id, FROM_HERE, callback); 224 } 225 226 class AutomationInterstitialPage : public content::InterstitialPageDelegate { 227 public: 228 AutomationInterstitialPage(WebContents* tab, 229 const GURL& url, 230 const std::string& contents) 231 : contents_(contents) { 232 interstitial_page_ = InterstitialPage::Create(tab, true, url, this); 233 interstitial_page_->Show(); 234 } 235 236 virtual std::string GetHTMLContents() OVERRIDE { return contents_; } 237 238 private: 239 const std::string contents_; 240 InterstitialPage* interstitial_page_; // Owns us. 241 242 DISALLOW_COPY_AND_ASSIGN(AutomationInterstitialPage); 243 }; 244 245 } // namespace 246 247 const int TestingAutomationProvider::kSynchronousCommands[] = { 248 IDC_HOME, 249 IDC_SELECT_NEXT_TAB, 250 IDC_SELECT_PREVIOUS_TAB, 251 IDC_SHOW_BOOKMARK_MANAGER, 252 }; 253 254 TestingAutomationProvider::TestingAutomationProvider(Profile* profile) 255 : AutomationProvider(profile) { 256 BrowserList::AddObserver(this); 257 registrar_.Add(this, chrome::NOTIFICATION_SESSION_END, 258 content::NotificationService::AllSources()); 259 #if defined(OS_CHROMEOS) 260 AddChromeosObservers(); 261 #endif 262 } 263 264 TestingAutomationProvider::~TestingAutomationProvider() { 265 #if defined(OS_CHROMEOS) 266 RemoveChromeosObservers(); 267 #endif 268 BrowserList::RemoveObserver(this); 269 } 270 271 IPC::Channel::Mode TestingAutomationProvider::GetChannelMode( 272 bool use_named_interface) { 273 if (use_named_interface) 274 #if defined(OS_POSIX) 275 return IPC::Channel::MODE_OPEN_NAMED_SERVER; 276 #else 277 return IPC::Channel::MODE_NAMED_SERVER; 278 #endif 279 else 280 return IPC::Channel::MODE_CLIENT; 281 } 282 283 void TestingAutomationProvider::OnBrowserAdded(Browser* browser) { 284 } 285 286 void TestingAutomationProvider::OnBrowserRemoved(Browser* browser) { 287 #if !defined(OS_CHROMEOS) && !defined(OS_MACOSX) 288 // For backwards compatibility with the testing automation interface, we 289 // want the automation provider (and hence the process) to go away when the 290 // last browser goes away. 291 // The automation layer doesn't support non-native desktops. 292 if (BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE)->empty() && 293 !CommandLine::ForCurrentProcess()->HasSwitch( 294 switches::kKeepAliveForTest)) { 295 // If you change this, update Observer for chrome::SESSION_END 296 // below. 297 base::MessageLoop::current()->PostTask( 298 FROM_HERE, 299 base::Bind(&TestingAutomationProvider::OnRemoveProvider, this)); 300 } 301 #endif // !defined(OS_CHROMEOS) && !defined(OS_MACOSX) 302 } 303 304 void TestingAutomationProvider::Observe( 305 int type, 306 const content::NotificationSource& source, 307 const content::NotificationDetails& details) { 308 DCHECK(type == chrome::NOTIFICATION_SESSION_END); 309 // OnBrowserRemoved does a ReleaseLater. When session end is received we exit 310 // before the task runs resulting in this object not being deleted. This 311 // Release balance out the Release scheduled by OnBrowserRemoved. 312 Release(); 313 } 314 315 bool TestingAutomationProvider::OnMessageReceived( 316 const IPC::Message& message) { 317 base::ThreadRestrictions::ScopedAllowWait allow_wait; 318 bool handled = true; 319 bool deserialize_success = true; 320 IPC_BEGIN_MESSAGE_MAP_EX(TestingAutomationProvider, 321 message, 322 deserialize_success) 323 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_CloseBrowser, CloseBrowser) 324 IPC_MESSAGE_HANDLER(AutomationMsg_ActivateTab, ActivateTab) 325 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_AppendTab, AppendTab) 326 IPC_MESSAGE_HANDLER(AutomationMsg_GetMachPortCount, GetMachPortCount) 327 IPC_MESSAGE_HANDLER(AutomationMsg_ActiveTabIndex, GetActiveTabIndex) 328 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_CloseTab, CloseTab) 329 IPC_MESSAGE_HANDLER(AutomationMsg_GetCookies, GetCookies) 330 IPC_MESSAGE_HANDLER_DELAY_REPLY( 331 AutomationMsg_NavigateToURLBlockUntilNavigationsComplete, 332 NavigateToURLBlockUntilNavigationsComplete) 333 IPC_MESSAGE_HANDLER(AutomationMsg_NavigationAsync, NavigationAsync) 334 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_Reload, Reload) 335 IPC_MESSAGE_HANDLER(AutomationMsg_BrowserWindowCount, GetBrowserWindowCount) 336 IPC_MESSAGE_HANDLER(AutomationMsg_NormalBrowserWindowCount, 337 GetNormalBrowserWindowCount) 338 IPC_MESSAGE_HANDLER(AutomationMsg_BrowserWindow, GetBrowserWindow) 339 IPC_MESSAGE_HANDLER(AutomationMsg_WindowExecuteCommandAsync, 340 ExecuteBrowserCommandAsync) 341 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WindowExecuteCommand, 342 ExecuteBrowserCommand) 343 IPC_MESSAGE_HANDLER(AutomationMsg_TerminateSession, TerminateSession) 344 IPC_MESSAGE_HANDLER(AutomationMsg_WindowViewBounds, WindowGetViewBounds) 345 IPC_MESSAGE_HANDLER(AutomationMsg_SetWindowBounds, SetWindowBounds) 346 IPC_MESSAGE_HANDLER(AutomationMsg_TabCount, GetTabCount) 347 IPC_MESSAGE_HANDLER(AutomationMsg_Type, GetType) 348 IPC_MESSAGE_HANDLER(AutomationMsg_Tab, GetTab) 349 IPC_MESSAGE_HANDLER(AutomationMsg_TabTitle, GetTabTitle) 350 IPC_MESSAGE_HANDLER(AutomationMsg_TabIndex, GetTabIndex) 351 IPC_MESSAGE_HANDLER(AutomationMsg_TabURL, GetTabURL) 352 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_DomOperation, 353 ExecuteJavascript) 354 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_OpenNewBrowserWindowOfType, 355 OpenNewBrowserWindowOfType) 356 IPC_MESSAGE_HANDLER(AutomationMsg_WindowForBrowser, GetWindowForBrowser) 357 IPC_MESSAGE_HANDLER(AutomationMsg_GetMetricEventDuration, 358 GetMetricEventDuration) 359 IPC_MESSAGE_HANDLER(AutomationMsg_BringBrowserToFront, BringBrowserToFront) 360 IPC_MESSAGE_HANDLER(AutomationMsg_FindWindowVisibility, 361 GetFindWindowVisibility) 362 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForBookmarkModelToLoad, 363 WaitForBookmarkModelToLoad) 364 IPC_MESSAGE_HANDLER_DELAY_REPLY( 365 AutomationMsg_WaitForBrowserWindowCountToBecome, 366 WaitForBrowserWindowCountToBecome) 367 IPC_MESSAGE_HANDLER_DELAY_REPLY( 368 AutomationMsg_GoBackBlockUntilNavigationsComplete, 369 GoBackBlockUntilNavigationsComplete) 370 IPC_MESSAGE_HANDLER_DELAY_REPLY( 371 AutomationMsg_GoForwardBlockUntilNavigationsComplete, 372 GoForwardBlockUntilNavigationsComplete) 373 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_SendJSONRequest, 374 SendJSONRequestWithBrowserIndex) 375 IPC_MESSAGE_HANDLER_DELAY_REPLY( 376 AutomationMsg_SendJSONRequestWithBrowserHandle, 377 SendJSONRequestWithBrowserHandle) 378 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForTabCountToBecome, 379 WaitForTabCountToBecome) 380 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForInfoBarCount, 381 WaitForInfoBarCount) 382 IPC_MESSAGE_HANDLER_DELAY_REPLY( 383 AutomationMsg_WaitForProcessLauncherThreadToGoIdle, 384 WaitForProcessLauncherThreadToGoIdle) 385 386 IPC_MESSAGE_UNHANDLED( 387 handled = AutomationProvider::OnMessageReceived(message)) 388 IPC_END_MESSAGE_MAP_EX() 389 if (!deserialize_success) 390 OnMessageDeserializationFailure(); 391 return handled; 392 } 393 394 void TestingAutomationProvider::OnChannelError() { 395 if (!reinitialize_on_channel_error_ && 396 browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID) { 397 chrome::AttemptExit(); 398 } 399 AutomationProvider::OnChannelError(); 400 } 401 402 void TestingAutomationProvider::CloseBrowser(int browser_handle, 403 IPC::Message* reply_message) { 404 if (!browser_tracker_->ContainsHandle(browser_handle)) 405 return; 406 407 Browser* browser = browser_tracker_->GetResource(browser_handle); 408 new BrowserClosedNotificationObserver(browser, this, reply_message, false); 409 browser->window()->Close(); 410 } 411 412 void TestingAutomationProvider::ActivateTab(int handle, 413 int at_index, 414 int* status) { 415 *status = -1; 416 if (browser_tracker_->ContainsHandle(handle) && at_index > -1) { 417 Browser* browser = browser_tracker_->GetResource(handle); 418 if (at_index >= 0 && at_index < browser->tab_strip_model()->count()) { 419 browser->tab_strip_model()->ActivateTabAt(at_index, true); 420 *status = 0; 421 } 422 } 423 } 424 425 void TestingAutomationProvider::AppendTab(int handle, 426 const GURL& url, 427 IPC::Message* reply_message) { 428 int append_tab_response = -1; // -1 is the error code 429 TabAppendedNotificationObserver* observer = NULL; 430 431 if (browser_tracker_->ContainsHandle(handle)) { 432 Browser* browser = browser_tracker_->GetResource(handle); 433 observer = new TabAppendedNotificationObserver(browser, this, 434 reply_message, false); 435 WebContents* contents = 436 chrome::AddSelectedTabWithURL(browser, url, 437 content::PAGE_TRANSITION_TYPED); 438 if (contents) { 439 append_tab_response = GetIndexForNavigationController( 440 &contents->GetController(), browser); 441 } 442 } 443 444 if (append_tab_response < 0) { 445 // Appending tab failed. Clean up and send failure response. 446 447 if (observer) 448 delete observer; 449 450 AutomationMsg_AppendTab::WriteReplyParams(reply_message, 451 append_tab_response); 452 Send(reply_message); 453 } 454 } 455 456 void TestingAutomationProvider::GetMachPortCount(int* port_count) { 457 #if defined(OS_MACOSX) 458 mach_port_name_array_t names; 459 mach_msg_type_number_t names_count; 460 mach_port_type_array_t types; 461 mach_msg_type_number_t types_count; 462 463 mach_port_t port = mach_task_self(); 464 465 // A friendlier interface would allow NULL buffers to only get the counts. 466 kern_return_t kr = mach_port_names(port, &names, &names_count, 467 &types, &types_count); 468 if (kr != KERN_SUCCESS) { 469 *port_count = 0; 470 return; 471 } 472 473 // The documentation states this is an invariant. 474 DCHECK_EQ(names_count, types_count); 475 *port_count = names_count; 476 477 mach_vm_deallocate(port, reinterpret_cast<mach_vm_address_t>(names), 478 names_count * sizeof(mach_port_name_array_t)); 479 mach_vm_deallocate(port, reinterpret_cast<mach_vm_address_t>(types), 480 types_count * sizeof(mach_port_type_array_t)); 481 #else 482 *port_count = 0; 483 #endif 484 } 485 486 void TestingAutomationProvider::GetActiveTabIndex(int handle, 487 int* active_tab_index) { 488 *active_tab_index = -1; // -1 is the error code 489 if (browser_tracker_->ContainsHandle(handle)) { 490 Browser* browser = browser_tracker_->GetResource(handle); 491 *active_tab_index = browser->tab_strip_model()->active_index(); 492 } 493 } 494 495 void TestingAutomationProvider::CloseTab(int tab_handle, 496 bool wait_until_closed, 497 IPC::Message* reply_message) { 498 if (tab_tracker_->ContainsHandle(tab_handle)) { 499 NavigationController* controller = tab_tracker_->GetResource(tab_handle); 500 Browser* browser = chrome::FindBrowserWithWebContents( 501 controller->GetWebContents()); 502 DCHECK(browser); 503 new TabClosedNotificationObserver(this, wait_until_closed, reply_message, 504 false); 505 chrome::CloseWebContents(browser, controller->GetWebContents(), false); 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 WebContents* contents = tab_tracker_->ContainsHandle(handle) ? 517 tab_tracker_->GetResource(handle)->GetWebContents() : NULL; 518 automation_util::GetCookies(url, contents, value_size, value); 519 } 520 521 void TestingAutomationProvider::NavigateToURLBlockUntilNavigationsComplete( 522 int handle, const GURL& url, int number_of_navigations, 523 IPC::Message* reply_message) { 524 if (tab_tracker_->ContainsHandle(handle)) { 525 NavigationController* tab = tab_tracker_->GetResource(handle); 526 527 // Simulate what a user would do. Activate the tab and then navigate. 528 // We could allow navigating in a background tab in future. 529 Browser* browser = FindAndActivateTab(tab); 530 531 if (browser) { 532 new NavigationNotificationObserver(tab, this, reply_message, 533 number_of_navigations, false, false); 534 535 // TODO(darin): avoid conversion to GURL. 536 OpenURLParams params( 537 url, Referrer(), CURRENT_TAB, 538 content::PageTransitionFromInt( 539 content::PAGE_TRANSITION_TYPED | 540 content::PAGE_TRANSITION_FROM_ADDRESS_BAR), 541 false); 542 browser->OpenURL(params); 543 return; 544 } 545 } 546 547 AutomationMsg_NavigateToURLBlockUntilNavigationsComplete::WriteReplyParams( 548 reply_message, AUTOMATION_MSG_NAVIGATION_ERROR); 549 Send(reply_message); 550 } 551 552 void TestingAutomationProvider::NavigationAsync(int handle, 553 const GURL& url, 554 bool* status) { 555 *status = false; 556 557 if (tab_tracker_->ContainsHandle(handle)) { 558 NavigationController* tab = tab_tracker_->GetResource(handle); 559 560 // Simulate what a user would do. Activate the tab and then navigate. 561 // We could allow navigating in a background tab in future. 562 Browser* browser = FindAndActivateTab(tab); 563 564 if (browser) { 565 // Don't add any listener unless a callback mechanism is desired. 566 // TODO(vibhor): Do this if such a requirement arises in future. 567 OpenURLParams params( 568 url, Referrer(), CURRENT_TAB, 569 content::PageTransitionFromInt( 570 content::PAGE_TRANSITION_TYPED | 571 content::PAGE_TRANSITION_FROM_ADDRESS_BAR), 572 false); 573 browser->OpenURL(params); 574 *status = true; 575 } 576 } 577 } 578 579 void TestingAutomationProvider::Reload(int handle, 580 IPC::Message* reply_message) { 581 if (tab_tracker_->ContainsHandle(handle)) { 582 NavigationController* tab = tab_tracker_->GetResource(handle); 583 Browser* browser = FindAndActivateTab(tab); 584 if (chrome::IsCommandEnabled(browser, IDC_RELOAD)) { 585 new NavigationNotificationObserver( 586 tab, this, reply_message, 1, false, false); 587 chrome::ExecuteCommand(browser, IDC_RELOAD); 588 return; 589 } 590 } 591 592 AutomationMsg_Reload::WriteReplyParams( 593 reply_message, AUTOMATION_MSG_NAVIGATION_ERROR); 594 Send(reply_message); 595 } 596 597 void TestingAutomationProvider::GetBrowserWindowCount(int* window_count) { 598 // The automation layer doesn't support non-native desktops. 599 *window_count = static_cast<int>(BrowserList::GetInstance( 600 chrome::HOST_DESKTOP_TYPE_NATIVE)->size()); 601 } 602 603 void TestingAutomationProvider::GetNormalBrowserWindowCount(int* window_count) { 604 *window_count = static_cast<int>(chrome::GetTabbedBrowserCount( 605 profile_, chrome::HOST_DESKTOP_TYPE_NATIVE)); 606 } 607 608 void TestingAutomationProvider::GetBrowserWindow(int index, int* handle) { 609 *handle = 0; 610 Browser* browser = automation_util::GetBrowserAt(index); 611 if (browser) 612 *handle = browser_tracker_->Add(browser); 613 } 614 615 void TestingAutomationProvider::ExecuteBrowserCommandAsync(int handle, 616 int command, 617 bool* success) { 618 *success = false; 619 if (!browser_tracker_->ContainsHandle(handle)) { 620 LOG(WARNING) << "Browser tracker does not contain handle: " << handle; 621 return; 622 } 623 Browser* browser = browser_tracker_->GetResource(handle); 624 if (!chrome::SupportsCommand(browser, command)) { 625 LOG(WARNING) << "Browser does not support command: " << command; 626 return; 627 } 628 if (!chrome::IsCommandEnabled(browser, command)) { 629 LOG(WARNING) << "Browser command not enabled: " << command; 630 return; 631 } 632 chrome::ExecuteCommand(browser, command); 633 *success = true; 634 } 635 636 void TestingAutomationProvider::ExecuteBrowserCommand( 637 int handle, int command, IPC::Message* reply_message) { 638 if (browser_tracker_->ContainsHandle(handle)) { 639 Browser* browser = browser_tracker_->GetResource(handle); 640 if (chrome::SupportsCommand(browser, command) && 641 chrome::IsCommandEnabled(browser, command)) { 642 // First check if we can handle the command without using an observer. 643 for (size_t i = 0; i < arraysize(kSynchronousCommands); i++) { 644 if (command == kSynchronousCommands[i]) { 645 chrome::ExecuteCommand(browser, command); 646 AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message, 647 true); 648 Send(reply_message); 649 return; 650 } 651 } 652 653 // Use an observer if we have one, otherwise fail. 654 if (ExecuteBrowserCommandObserver::CreateAndRegisterObserver( 655 this, browser, command, reply_message, false)) { 656 chrome::ExecuteCommand(browser, command); 657 return; 658 } 659 } 660 } 661 AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message, false); 662 Send(reply_message); 663 } 664 665 void TestingAutomationProvider::WebkitMouseClick(DictionaryValue* args, 666 IPC::Message* reply_message) { 667 if (SendErrorIfModalDialogActive(this, reply_message)) 668 return; 669 670 RenderViewHost* view; 671 std::string error; 672 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) { 673 AutomationJSONReply(this, reply_message).SendError(error); 674 return; 675 } 676 677 WebKit::WebMouseEvent mouse_event; 678 if (!args->GetInteger("x", &mouse_event.x) || 679 !args->GetInteger("y", &mouse_event.y)) { 680 AutomationJSONReply(this, reply_message) 681 .SendError("(X,Y) coordinates missing or invalid"); 682 return; 683 } 684 685 int button; 686 if (!args->GetInteger("button", &button)) { 687 AutomationJSONReply(this, reply_message) 688 .SendError("Mouse button missing or invalid"); 689 return; 690 } 691 if (button == automation::kLeftButton) { 692 mouse_event.button = WebKit::WebMouseEvent::ButtonLeft; 693 } else if (button == automation::kRightButton) { 694 mouse_event.button = WebKit::WebMouseEvent::ButtonRight; 695 } else if (button == automation::kMiddleButton) { 696 mouse_event.button = WebKit::WebMouseEvent::ButtonMiddle; 697 } else { 698 AutomationJSONReply(this, reply_message) 699 .SendError("Invalid button press requested"); 700 return; 701 } 702 703 mouse_event.type = WebKit::WebInputEvent::MouseDown; 704 mouse_event.clickCount = 1; 705 706 view->ForwardMouseEvent(mouse_event); 707 708 mouse_event.type = WebKit::WebInputEvent::MouseUp; 709 new InputEventAckNotificationObserver(this, reply_message, mouse_event.type, 710 1); 711 view->ForwardMouseEvent(mouse_event); 712 } 713 714 void TestingAutomationProvider::WebkitMouseMove( 715 DictionaryValue* args, IPC::Message* reply_message) { 716 if (SendErrorIfModalDialogActive(this, reply_message)) 717 return; 718 719 RenderViewHost* view; 720 std::string error; 721 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) { 722 AutomationJSONReply(this, reply_message).SendError(error); 723 return; 724 } 725 726 WebKit::WebMouseEvent mouse_event; 727 if (!args->GetInteger("x", &mouse_event.x) || 728 !args->GetInteger("y", &mouse_event.y)) { 729 AutomationJSONReply(this, reply_message) 730 .SendError("(X,Y) coordinates missing or invalid"); 731 return; 732 } 733 734 mouse_event.type = WebKit::WebInputEvent::MouseMove; 735 new InputEventAckNotificationObserver(this, reply_message, mouse_event.type, 736 1); 737 view->ForwardMouseEvent(mouse_event); 738 } 739 740 void TestingAutomationProvider::WebkitMouseDrag(DictionaryValue* args, 741 IPC::Message* reply_message) { 742 if (SendErrorIfModalDialogActive(this, reply_message)) 743 return; 744 745 RenderViewHost* view; 746 std::string error; 747 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) { 748 AutomationJSONReply(this, reply_message).SendError(error); 749 return; 750 } 751 752 WebKit::WebMouseEvent mouse_event; 753 int start_x, start_y, end_x, end_y; 754 if (!args->GetInteger("start_x", &start_x) || 755 !args->GetInteger("start_y", &start_y) || 756 !args->GetInteger("end_x", &end_x) || 757 !args->GetInteger("end_y", &end_y)) { 758 AutomationJSONReply(this, reply_message) 759 .SendError("Invalid start/end positions"); 760 return; 761 } 762 763 mouse_event.type = WebKit::WebInputEvent::MouseMove; 764 // Step 1- Move the mouse to the start position. 765 mouse_event.x = start_x; 766 mouse_event.y = start_y; 767 view->ForwardMouseEvent(mouse_event); 768 769 // Step 2- Left click mouse down, the mouse button is fixed. 770 mouse_event.type = WebKit::WebInputEvent::MouseDown; 771 mouse_event.button = WebKit::WebMouseEvent::ButtonLeft; 772 mouse_event.clickCount = 1; 773 view->ForwardMouseEvent(mouse_event); 774 775 // Step 3 - Move the mouse to the end position. 776 mouse_event.type = WebKit::WebInputEvent::MouseMove; 777 mouse_event.x = end_x; 778 mouse_event.y = end_y; 779 mouse_event.clickCount = 0; 780 view->ForwardMouseEvent(mouse_event); 781 782 // Step 4 - Release the left mouse button. 783 mouse_event.type = WebKit::WebInputEvent::MouseUp; 784 mouse_event.clickCount = 1; 785 new InputEventAckNotificationObserver(this, reply_message, mouse_event.type, 786 1); 787 view->ForwardMouseEvent(mouse_event); 788 } 789 790 void TestingAutomationProvider::WebkitMouseButtonDown( 791 DictionaryValue* args, IPC::Message* reply_message) { 792 if (SendErrorIfModalDialogActive(this, reply_message)) 793 return; 794 795 RenderViewHost* view; 796 std::string error; 797 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) { 798 AutomationJSONReply(this, reply_message).SendError(error); 799 return; 800 } 801 802 WebKit::WebMouseEvent mouse_event; 803 if (!args->GetInteger("x", &mouse_event.x) || 804 !args->GetInteger("y", &mouse_event.y)) { 805 AutomationJSONReply(this, reply_message) 806 .SendError("(X,Y) coordinates missing or invalid"); 807 return; 808 } 809 810 mouse_event.type = WebKit::WebInputEvent::MouseDown; 811 mouse_event.button = WebKit::WebMouseEvent::ButtonLeft; 812 mouse_event.clickCount = 1; 813 new InputEventAckNotificationObserver(this, reply_message, mouse_event.type, 814 1); 815 view->ForwardMouseEvent(mouse_event); 816 } 817 818 void TestingAutomationProvider::WebkitMouseButtonUp( 819 DictionaryValue* args, IPC::Message* reply_message) { 820 if (SendErrorIfModalDialogActive(this, reply_message)) 821 return; 822 823 RenderViewHost* view; 824 std::string error; 825 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) { 826 AutomationJSONReply(this, reply_message).SendError(error); 827 return; 828 } 829 830 WebKit::WebMouseEvent mouse_event; 831 if (!args->GetInteger("x", &mouse_event.x) || 832 !args->GetInteger("y", &mouse_event.y)) { 833 AutomationJSONReply(this, reply_message) 834 .SendError("(X,Y) coordinates missing or invalid"); 835 return; 836 } 837 838 mouse_event.type = WebKit::WebInputEvent::MouseUp; 839 mouse_event.button = WebKit::WebMouseEvent::ButtonLeft; 840 mouse_event.clickCount = 1; 841 new InputEventAckNotificationObserver(this, reply_message, mouse_event.type, 842 1); 843 view->ForwardMouseEvent(mouse_event); 844 } 845 846 void TestingAutomationProvider::WebkitMouseDoubleClick( 847 DictionaryValue* args, IPC::Message* reply_message) { 848 if (SendErrorIfModalDialogActive(this, reply_message)) 849 return; 850 851 RenderViewHost* view; 852 std::string error; 853 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) { 854 AutomationJSONReply(this, reply_message).SendError(error); 855 return; 856 } 857 858 WebKit::WebMouseEvent mouse_event; 859 if (!args->GetInteger("x", &mouse_event.x) || 860 !args->GetInteger("y", &mouse_event.y)) { 861 AutomationJSONReply(this, reply_message) 862 .SendError("(X,Y) coordinates missing or invalid"); 863 return; 864 } 865 866 mouse_event.type = WebKit::WebInputEvent::MouseDown; 867 mouse_event.button = WebKit::WebMouseEvent::ButtonLeft; 868 mouse_event.clickCount = 1; 869 view->ForwardMouseEvent(mouse_event); 870 871 mouse_event.type = WebKit::WebInputEvent::MouseUp; 872 new InputEventAckNotificationObserver(this, reply_message, mouse_event.type, 873 2); 874 view->ForwardMouseEvent(mouse_event); 875 876 mouse_event.type = WebKit::WebInputEvent::MouseDown; 877 mouse_event.clickCount = 2; 878 view->ForwardMouseEvent(mouse_event); 879 880 mouse_event.type = WebKit::WebInputEvent::MouseUp; 881 view->ForwardMouseEvent(mouse_event); 882 } 883 884 void TestingAutomationProvider::DragAndDropFilePaths( 885 DictionaryValue* args, IPC::Message* reply_message) { 886 if (SendErrorIfModalDialogActive(this, reply_message)) 887 return; 888 889 RenderViewHost* view; 890 std::string error; 891 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) { 892 AutomationJSONReply(this, reply_message).SendError(error); 893 return; 894 } 895 896 int x, y; 897 if (!args->GetInteger("x", &x) || !args->GetInteger("y", &y)) { 898 AutomationJSONReply(this, reply_message) 899 .SendError("(X,Y) coordinates missing or invalid"); 900 return; 901 } 902 903 ListValue* paths = NULL; 904 if (!args->GetList("paths", &paths)) { 905 AutomationJSONReply(this, reply_message) 906 .SendError("'paths' missing or invalid"); 907 return; 908 } 909 910 // Emulate drag and drop to set the file paths to the file upload control. 911 content::DropData drop_data; 912 for (size_t path_index = 0; path_index < paths->GetSize(); ++path_index) { 913 string16 path; 914 if (!paths->GetString(path_index, &path)) { 915 AutomationJSONReply(this, reply_message) 916 .SendError("'paths' contains a non-string type"); 917 return; 918 } 919 920 drop_data.filenames.push_back( 921 content::DropData::FileInfo(path, string16())); 922 } 923 924 const gfx::Point client(x, y); 925 // We don't set any values in screen variable because DragTarget*** ignore the 926 // screen argument. 927 const gfx::Point screen; 928 929 int operations = 0; 930 operations |= WebKit::WebDragOperationCopy; 931 operations |= WebKit::WebDragOperationLink; 932 operations |= WebKit::WebDragOperationMove; 933 934 view->DragTargetDragEnter( 935 drop_data, client, screen, 936 static_cast<WebKit::WebDragOperationsMask>(operations), 0); 937 new DragTargetDropAckNotificationObserver(this, reply_message); 938 view->DragTargetDrop(client, screen, 0); 939 } 940 941 void TestingAutomationProvider::GetTabCount(int handle, int* tab_count) { 942 *tab_count = -1; // -1 is the error code 943 944 if (browser_tracker_->ContainsHandle(handle)) { 945 Browser* browser = browser_tracker_->GetResource(handle); 946 *tab_count = browser->tab_strip_model()->count(); 947 } 948 } 949 950 void TestingAutomationProvider::GetType(int handle, int* type_as_int) { 951 *type_as_int = -1; // -1 is the error code 952 953 if (browser_tracker_->ContainsHandle(handle)) { 954 Browser* browser = browser_tracker_->GetResource(handle); 955 *type_as_int = static_cast<int>(browser->type()); 956 } 957 } 958 959 void TestingAutomationProvider::GetTab(int win_handle, 960 int tab_index, 961 int* tab_handle) { 962 *tab_handle = 0; 963 if (browser_tracker_->ContainsHandle(win_handle) && (tab_index >= 0)) { 964 Browser* browser = browser_tracker_->GetResource(win_handle); 965 if (tab_index < browser->tab_strip_model()->count()) { 966 WebContents* web_contents = 967 browser->tab_strip_model()->GetWebContentsAt(tab_index); 968 *tab_handle = tab_tracker_->Add(&web_contents->GetController()); 969 } 970 } 971 } 972 973 void TestingAutomationProvider::GetTabTitle(int handle, 974 int* title_string_size, 975 std::wstring* title) { 976 *title_string_size = -1; // -1 is the error code 977 if (tab_tracker_->ContainsHandle(handle)) { 978 NavigationController* tab = tab_tracker_->GetResource(handle); 979 NavigationEntry* entry = tab->GetActiveEntry(); 980 if (entry != NULL) { 981 *title = UTF16ToWideHack(entry->GetTitleForDisplay(std::string())); 982 } else { 983 *title = std::wstring(); 984 } 985 *title_string_size = static_cast<int>(title->size()); 986 } 987 } 988 989 void TestingAutomationProvider::GetTabIndex(int handle, int* tabstrip_index) { 990 *tabstrip_index = -1; // -1 is the error code 991 992 if (tab_tracker_->ContainsHandle(handle)) { 993 NavigationController* tab = tab_tracker_->GetResource(handle); 994 Browser* browser = chrome::FindBrowserWithWebContents( 995 tab->GetWebContents()); 996 *tabstrip_index = browser->tab_strip_model()->GetIndexOfWebContents( 997 tab->GetWebContents()); 998 } 999 } 1000 1001 void TestingAutomationProvider::GetTabURL(int handle, 1002 bool* success, 1003 GURL* url) { 1004 *success = false; 1005 if (tab_tracker_->ContainsHandle(handle)) { 1006 NavigationController* tab = tab_tracker_->GetResource(handle); 1007 // Return what the user would see in the location bar. 1008 *url = tab->GetActiveEntry()->GetVirtualURL(); 1009 *success = true; 1010 } 1011 } 1012 1013 void TestingAutomationProvider::ExecuteJavascriptInRenderViewFrame( 1014 const string16& frame_xpath, 1015 const string16& script, 1016 IPC::Message* reply_message, 1017 RenderViewHost* render_view_host) { 1018 // Set the routing id of this message with the controller. 1019 // This routing id needs to be remembered for the reverse 1020 // communication while sending back the response of 1021 // this javascript execution. 1022 render_view_host->ExecuteJavascriptInWebFrame( 1023 frame_xpath, 1024 UTF8ToUTF16("window.domAutomationController.setAutomationId(0);")); 1025 render_view_host->ExecuteJavascriptInWebFrame( 1026 frame_xpath, script); 1027 } 1028 1029 void TestingAutomationProvider::ExecuteJavascript( 1030 int handle, 1031 const std::wstring& frame_xpath, 1032 const std::wstring& script, 1033 IPC::Message* reply_message) { 1034 WebContents* web_contents = GetWebContentsForHandle(handle, NULL); 1035 if (!web_contents) { 1036 AutomationMsg_DomOperation::WriteReplyParams(reply_message, std::string()); 1037 Send(reply_message); 1038 return; 1039 } 1040 1041 new DomOperationMessageSender(this, reply_message, false); 1042 ExecuteJavascriptInRenderViewFrame(WideToUTF16Hack(frame_xpath), 1043 WideToUTF16Hack(script), reply_message, 1044 web_contents->GetRenderViewHost()); 1045 } 1046 1047 // Sample json input: { "command": "OpenNewBrowserWindowWithNewProfile" } 1048 // Sample output: {} 1049 void TestingAutomationProvider::OpenNewBrowserWindowWithNewProfile( 1050 base::DictionaryValue* args, IPC::Message* reply_message) { 1051 ProfileManager* profile_manager = g_browser_process->profile_manager(); 1052 new BrowserOpenedWithNewProfileNotificationObserver(this, reply_message); 1053 profile_manager->CreateMultiProfileAsync( 1054 string16(), string16(), ProfileManager::CreateCallback(), std::string()); 1055 } 1056 1057 // Sample json input: { "command": "GetMultiProfileInfo" } 1058 // See GetMultiProfileInfo() in pyauto.py for sample output. 1059 void TestingAutomationProvider::GetMultiProfileInfo( 1060 base::DictionaryValue* args, IPC::Message* reply_message) { 1061 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 1062 ProfileManager* profile_manager = g_browser_process->profile_manager(); 1063 const ProfileInfoCache& profile_info_cache = 1064 profile_manager->GetProfileInfoCache(); 1065 return_value->SetBoolean("enabled", profiles::IsMultipleProfilesEnabled()); 1066 1067 ListValue* profiles = new ListValue; 1068 for (size_t index = 0; index < profile_info_cache.GetNumberOfProfiles(); 1069 ++index) { 1070 DictionaryValue* item = new DictionaryValue; 1071 item->SetString("name", profile_info_cache.GetNameOfProfileAtIndex(index)); 1072 item->SetString("path", 1073 profile_info_cache.GetPathOfProfileAtIndex(index).value()); 1074 profiles->Append(item); 1075 } 1076 return_value->Set("profiles", profiles); 1077 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get()); 1078 } 1079 1080 void TestingAutomationProvider::OpenNewBrowserWindowOfType( 1081 int type, bool show, IPC::Message* reply_message) { 1082 new BrowserOpenedNotificationObserver(this, reply_message, false); 1083 // We may have no current browser windows open so don't rely on 1084 // asking an existing browser to execute the IDC_NEWWINDOW command. 1085 Browser* browser = new Browser( 1086 Browser::CreateParams(static_cast<Browser::Type>(type), profile_, 1087 chrome::HOST_DESKTOP_TYPE_NATIVE)); 1088 chrome::AddBlankTabAt(browser, -1, true); 1089 if (show) 1090 browser->window()->Show(); 1091 } 1092 1093 void TestingAutomationProvider::OpenNewBrowserWindow( 1094 base::DictionaryValue* args, 1095 IPC::Message* reply_message) { 1096 bool show; 1097 if (!args->GetBoolean("show", &show)) { 1098 AutomationJSONReply(this, reply_message) 1099 .SendError("'show' missing or invalid."); 1100 return; 1101 } 1102 new BrowserOpenedNotificationObserver(this, reply_message, true); 1103 Browser* browser = new Browser( 1104 Browser::CreateParams(Browser::TYPE_TABBED, profile_, 1105 chrome::HOST_DESKTOP_TYPE_NATIVE)); 1106 chrome::AddBlankTabAt(browser, -1, true); 1107 if (show) 1108 browser->window()->Show(); 1109 } 1110 1111 void TestingAutomationProvider::GetBrowserWindowCountJSON( 1112 base::DictionaryValue* args, 1113 IPC::Message* reply_message) { 1114 DictionaryValue dict; 1115 // The automation layer doesn't support non-native desktops. 1116 dict.SetInteger("count", 1117 static_cast<int>(BrowserList::GetInstance( 1118 chrome::HOST_DESKTOP_TYPE_NATIVE)->size())); 1119 AutomationJSONReply(this, reply_message).SendSuccess(&dict); 1120 } 1121 1122 void TestingAutomationProvider::CloseBrowserWindow( 1123 base::DictionaryValue* args, 1124 IPC::Message* reply_message) { 1125 AutomationJSONReply reply(this, reply_message); 1126 Browser* browser; 1127 std::string error_msg; 1128 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) { 1129 reply.SendError(error_msg); 1130 return; 1131 } 1132 new BrowserClosedNotificationObserver(browser, this, reply_message, true); 1133 browser->window()->Close(); 1134 } 1135 1136 void TestingAutomationProvider::OpenProfileWindow( 1137 base::DictionaryValue* args, IPC::Message* reply_message) { 1138 ProfileManager* profile_manager = g_browser_process->profile_manager(); 1139 base::FilePath::StringType path; 1140 if (!args->GetString("path", &path)) { 1141 AutomationJSONReply(this, reply_message).SendError( 1142 "Invalid or missing arg: 'path'"); 1143 return; 1144 } 1145 Profile* profile = profile_manager->GetProfileByPath(base::FilePath(path)); 1146 if (!profile) { 1147 AutomationJSONReply(this, reply_message).SendError( 1148 base::StringPrintf("Invalid profile path: %s", path.c_str())); 1149 return; 1150 } 1151 int num_loads; 1152 if (!args->GetInteger("num_loads", &num_loads)) { 1153 AutomationJSONReply(this, reply_message).SendError( 1154 "Invalid or missing arg: 'num_loads'"); 1155 return; 1156 } 1157 new BrowserOpenedWithExistingProfileNotificationObserver( 1158 this, reply_message, num_loads); 1159 profiles::FindOrCreateNewWindowForProfile( 1160 profile, 1161 chrome::startup::IS_NOT_PROCESS_STARTUP, 1162 chrome::startup::IS_NOT_FIRST_RUN, 1163 chrome::HOST_DESKTOP_TYPE_NATIVE, 1164 false); 1165 } 1166 1167 void TestingAutomationProvider::GetWindowForBrowser(int browser_handle, 1168 bool* success, 1169 int* handle) { 1170 *success = false; 1171 *handle = 0; 1172 1173 if (browser_tracker_->ContainsHandle(browser_handle)) { 1174 Browser* browser = browser_tracker_->GetResource(browser_handle); 1175 gfx::NativeWindow win = browser->window()->GetNativeWindow(); 1176 // Add() returns the existing handle for the resource if any. 1177 *handle = window_tracker_->Add(win); 1178 *success = true; 1179 } 1180 } 1181 1182 void TestingAutomationProvider::GetMetricEventDuration( 1183 const std::string& event_name, 1184 int* duration_ms) { 1185 *duration_ms = metric_event_duration_observer_->GetEventDurationMs( 1186 event_name); 1187 } 1188 1189 void TestingAutomationProvider::BringBrowserToFront(int browser_handle, 1190 bool* success) { 1191 *success = false; 1192 if (browser_tracker_->ContainsHandle(browser_handle)) { 1193 Browser* browser = browser_tracker_->GetResource(browser_handle); 1194 browser->window()->Activate(); 1195 *success = true; 1196 } 1197 } 1198 1199 void TestingAutomationProvider::GetFindWindowVisibility(int handle, 1200 bool* visible) { 1201 *visible = false; 1202 Browser* browser = browser_tracker_->GetResource(handle); 1203 if (browser) { 1204 FindBarTesting* find_bar = 1205 browser->GetFindBarController()->find_bar()->GetFindBarTesting(); 1206 find_bar->GetFindBarWindowInfo(NULL, visible); 1207 } 1208 } 1209 1210 // Bookmark bar visibility is based on the pref (e.g. is it in the toolbar). 1211 // Presence in the NTP is signalled in |detached|. 1212 void TestingAutomationProvider::GetBookmarkBarStatus( 1213 DictionaryValue* args, 1214 IPC::Message* reply_message) { 1215 AutomationJSONReply reply(this, reply_message); 1216 Browser* browser; 1217 std::string error_msg; 1218 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) { 1219 reply.SendError(error_msg); 1220 return; 1221 } 1222 // browser->window()->IsBookmarkBarVisible() is not consistent across 1223 // platforms. bookmark_bar_state() also follows prefs::kShowBookmarkBar 1224 // and has a shared implementation on all platforms. 1225 DictionaryValue dict; 1226 dict.SetBoolean("visible", 1227 browser->bookmark_bar_state() == BookmarkBar::SHOW); 1228 dict.SetBoolean("animating", browser->window()->IsBookmarkBarAnimating()); 1229 dict.SetBoolean("detached", 1230 browser->bookmark_bar_state() == BookmarkBar::DETACHED); 1231 reply.SendSuccess(&dict); 1232 } 1233 1234 void TestingAutomationProvider::GetBookmarksAsJSON( 1235 DictionaryValue* args, 1236 IPC::Message* reply_message) { 1237 AutomationJSONReply reply(this, reply_message); 1238 Browser* browser; 1239 std::string error_msg, bookmarks_as_json; 1240 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) { 1241 reply.SendError(error_msg); 1242 return; 1243 } 1244 BookmarkModel* bookmark_model = 1245 BookmarkModelFactory::GetForProfile(browser->profile()); 1246 if (!bookmark_model->loaded()) { 1247 reply.SendError("Bookmark model is not loaded"); 1248 return; 1249 } 1250 scoped_refptr<BookmarkStorage> storage( 1251 new BookmarkStorage(browser->profile(), 1252 bookmark_model, 1253 browser->profile()->GetIOTaskRunner().get())); 1254 if (!storage->SerializeData(&bookmarks_as_json)) { 1255 reply.SendError("Failed to serialize bookmarks"); 1256 return; 1257 } 1258 DictionaryValue dict; 1259 dict.SetString("bookmarks_as_json", bookmarks_as_json); 1260 reply.SendSuccess(&dict); 1261 } 1262 1263 void TestingAutomationProvider::WaitForBookmarkModelToLoad( 1264 int handle, 1265 IPC::Message* reply_message) { 1266 if (browser_tracker_->ContainsHandle(handle)) { 1267 Browser* browser = browser_tracker_->GetResource(handle); 1268 BookmarkModel* model = 1269 BookmarkModelFactory::GetForProfile(browser->profile()); 1270 AutomationProviderBookmarkModelObserver* observer = 1271 new AutomationProviderBookmarkModelObserver(this, reply_message, 1272 model, false); 1273 if (model->loaded()) { 1274 observer->ReleaseReply(); 1275 delete observer; 1276 AutomationMsg_WaitForBookmarkModelToLoad::WriteReplyParams( 1277 reply_message, true); 1278 Send(reply_message); 1279 } 1280 } 1281 } 1282 1283 void TestingAutomationProvider::WaitForBookmarkModelToLoadJSON( 1284 DictionaryValue* args, 1285 IPC::Message* reply_message) { 1286 Browser* browser; 1287 std::string error_msg; 1288 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) { 1289 AutomationJSONReply(this, reply_message).SendError(error_msg); 1290 return; 1291 } 1292 BookmarkModel* model = 1293 BookmarkModelFactory::GetForProfile(browser->profile()); 1294 AutomationProviderBookmarkModelObserver* observer = 1295 new AutomationProviderBookmarkModelObserver(this, reply_message, model, 1296 true); 1297 if (model->loaded()) { 1298 observer->ReleaseReply(); 1299 delete observer; 1300 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 1301 return; 1302 } 1303 } 1304 1305 void TestingAutomationProvider::AddBookmark( 1306 DictionaryValue* args, 1307 IPC::Message* reply_message) { 1308 AutomationJSONReply reply(this, reply_message); 1309 Browser* browser; 1310 std::string error_msg, url; 1311 string16 title; 1312 int parent_id, index; 1313 bool folder; 1314 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) { 1315 reply.SendError(error_msg); 1316 return; 1317 } 1318 if (!args->GetBoolean("is_folder", &folder)) { 1319 reply.SendError("'is_folder' missing or invalid"); 1320 return; 1321 } 1322 if (!folder && !args->GetString("url", &url)) { 1323 reply.SendError("'url' missing or invalid"); 1324 return; 1325 } 1326 if (!args->GetInteger("parent_id", &parent_id)) { 1327 reply.SendError("'parent_id' missing or invalid"); 1328 return; 1329 } 1330 if (!args->GetInteger("index", &index)) { 1331 reply.SendError("'index' missing or invalid"); 1332 return; 1333 } 1334 if (!args->GetString("title", &title)) { 1335 reply.SendError("'title' missing or invalid"); 1336 return; 1337 } 1338 BookmarkModel* model = 1339 BookmarkModelFactory::GetForProfile(browser->profile()); 1340 if (!model->loaded()) { 1341 reply.SendError("Bookmark model is not loaded"); 1342 return; 1343 } 1344 const BookmarkNode* parent = model->GetNodeByID(parent_id); 1345 if (!parent) { 1346 reply.SendError("Failed to get parent bookmark node"); 1347 return; 1348 } 1349 const BookmarkNode* child; 1350 if (folder) { 1351 child = model->AddFolder(parent, index, title); 1352 } else { 1353 child = model->AddURL(parent, index, title, GURL(url)); 1354 } 1355 if (!child) { 1356 reply.SendError("Failed to add bookmark"); 1357 return; 1358 } 1359 reply.SendSuccess(NULL); 1360 } 1361 1362 void TestingAutomationProvider::ReparentBookmark(DictionaryValue* args, 1363 IPC::Message* reply_message) { 1364 AutomationJSONReply reply(this, reply_message); 1365 Browser* browser; 1366 std::string error_msg; 1367 int new_parent_id, id, index; 1368 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) { 1369 reply.SendError(error_msg); 1370 return; 1371 } 1372 if (!args->GetInteger("id", &id)) { 1373 reply.SendError("'id' missing or invalid"); 1374 return; 1375 } 1376 if (!args->GetInteger("new_parent_id", &new_parent_id)) { 1377 reply.SendError("'new_parent_id' missing or invalid"); 1378 return; 1379 } 1380 if (!args->GetInteger("index", &index)) { 1381 reply.SendError("'index' missing or invalid"); 1382 return; 1383 } 1384 BookmarkModel* model = 1385 BookmarkModelFactory::GetForProfile(browser->profile()); 1386 if (!model->loaded()) { 1387 reply.SendError("Bookmark model is not loaded"); 1388 return; 1389 } 1390 const BookmarkNode* node = model->GetNodeByID(id); 1391 const BookmarkNode* new_parent = model->GetNodeByID(new_parent_id); 1392 if (!node) { 1393 reply.SendError("Failed to get bookmark node"); 1394 return; 1395 } 1396 if (!new_parent) { 1397 reply.SendError("Failed to get new parent bookmark node"); 1398 return; 1399 } 1400 model->Move(node, new_parent, index); 1401 reply.SendSuccess(NULL); 1402 } 1403 1404 void TestingAutomationProvider::SetBookmarkTitle(DictionaryValue* args, 1405 IPC::Message* reply_message) { 1406 AutomationJSONReply reply(this, reply_message); 1407 Browser* browser; 1408 std::string error_msg; 1409 string16 title; 1410 int id; 1411 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) { 1412 reply.SendError(error_msg); 1413 return; 1414 } 1415 if (!args->GetInteger("id", &id)) { 1416 reply.SendError("'id' missing or invalid"); 1417 return; 1418 } 1419 if (!args->GetString("title", &title)) { 1420 reply.SendError("'title' missing or invalid"); 1421 return; 1422 } 1423 BookmarkModel* model = 1424 BookmarkModelFactory::GetForProfile(browser->profile()); 1425 if (!model->loaded()) { 1426 reply.SendError("Bookmark model is not loaded"); 1427 return; 1428 } 1429 const BookmarkNode* node = model->GetNodeByID(id); 1430 if (!node) { 1431 reply.SendError("Failed to get bookmark node"); 1432 return; 1433 } 1434 model->SetTitle(node, title); 1435 reply.SendSuccess(NULL); 1436 } 1437 1438 void TestingAutomationProvider::SetBookmarkURL(DictionaryValue* args, 1439 IPC::Message* reply_message) { 1440 AutomationJSONReply reply(this, reply_message); 1441 Browser* browser; 1442 std::string error_msg, url; 1443 int id; 1444 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) { 1445 reply.SendError(error_msg); 1446 return; 1447 } 1448 if (!args->GetInteger("id", &id)) { 1449 reply.SendError("'id' missing or invalid"); 1450 return; 1451 } 1452 if (!args->GetString("url", &url)) { 1453 reply.SendError("'url' missing or invalid"); 1454 return; 1455 } 1456 BookmarkModel* model = 1457 BookmarkModelFactory::GetForProfile(browser->profile()); 1458 if (!model->loaded()) { 1459 reply.SendError("Bookmark model is not loaded"); 1460 return; 1461 } 1462 const BookmarkNode* node = model->GetNodeByID(id); 1463 if (!node) { 1464 reply.SendError("Failed to get bookmark node"); 1465 return; 1466 } 1467 model->SetURL(node, GURL(url)); 1468 reply.SendSuccess(NULL); 1469 } 1470 1471 void TestingAutomationProvider::RemoveBookmark(DictionaryValue* args, 1472 IPC::Message* reply_message) { 1473 AutomationJSONReply reply(this, reply_message); 1474 Browser* browser; 1475 std::string error_msg; 1476 int id; 1477 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) { 1478 reply.SendError(error_msg); 1479 return; 1480 } 1481 if (!args->GetInteger("id", &id)) { 1482 reply.SendError("'id' missing or invalid"); 1483 return; 1484 } 1485 BookmarkModel* model = 1486 BookmarkModelFactory::GetForProfile(browser->profile()); 1487 if (!model->loaded()) { 1488 reply.SendError("Bookmark model is not loaded"); 1489 return; 1490 } 1491 const BookmarkNode* node = model->GetNodeByID(id); 1492 if (!node) { 1493 reply.SendError("Failed to get bookmark node"); 1494 return; 1495 } 1496 const BookmarkNode* parent = node->parent(); 1497 if (!parent) { 1498 reply.SendError("Failed to get parent bookmark node"); 1499 return; 1500 } 1501 model->Remove(parent, parent->GetIndexOf(node)); 1502 reply.SendSuccess(NULL); 1503 } 1504 1505 void TestingAutomationProvider::WaitForBrowserWindowCountToBecome( 1506 int target_count, 1507 IPC::Message* reply_message) { 1508 // The automation layer doesn't support non-native desktops. 1509 int current_count = static_cast<int>(BrowserList::GetInstance( 1510 chrome::HOST_DESKTOP_TYPE_NATIVE)->size()); 1511 if (current_count == target_count) { 1512 AutomationMsg_WaitForBrowserWindowCountToBecome::WriteReplyParams( 1513 reply_message, true); 1514 Send(reply_message); 1515 return; 1516 } 1517 1518 // Set up an observer (it will delete itself). 1519 new BrowserCountChangeNotificationObserver(target_count, this, reply_message); 1520 } 1521 1522 void TestingAutomationProvider::GoBackBlockUntilNavigationsComplete( 1523 int handle, int number_of_navigations, IPC::Message* reply_message) { 1524 if (tab_tracker_->ContainsHandle(handle)) { 1525 NavigationController* tab = tab_tracker_->GetResource(handle); 1526 Browser* browser = FindAndActivateTab(tab); 1527 if (chrome::IsCommandEnabled(browser, IDC_BACK)) { 1528 new NavigationNotificationObserver(tab, this, reply_message, 1529 number_of_navigations, false, false); 1530 chrome::ExecuteCommand(browser, IDC_BACK); 1531 return; 1532 } 1533 } 1534 1535 AutomationMsg_GoBackBlockUntilNavigationsComplete::WriteReplyParams( 1536 reply_message, AUTOMATION_MSG_NAVIGATION_ERROR); 1537 Send(reply_message); 1538 } 1539 1540 void TestingAutomationProvider::GoForwardBlockUntilNavigationsComplete( 1541 int handle, int number_of_navigations, IPC::Message* reply_message) { 1542 if (tab_tracker_->ContainsHandle(handle)) { 1543 NavigationController* tab = tab_tracker_->GetResource(handle); 1544 Browser* browser = FindAndActivateTab(tab); 1545 if (chrome::IsCommandEnabled(browser, IDC_FORWARD)) { 1546 new NavigationNotificationObserver(tab, this, reply_message, 1547 number_of_navigations, false, false); 1548 chrome::ExecuteCommand(browser, IDC_FORWARD); 1549 return; 1550 } 1551 } 1552 1553 AutomationMsg_GoForwardBlockUntilNavigationsComplete::WriteReplyParams( 1554 reply_message, AUTOMATION_MSG_NAVIGATION_ERROR); 1555 Send(reply_message); 1556 } 1557 1558 void TestingAutomationProvider::BuildJSONHandlerMaps() { 1559 // Map json commands to their handlers. 1560 handler_map_["ApplyAccelerator"] = 1561 &TestingAutomationProvider::ExecuteBrowserCommandAsyncJSON; 1562 handler_map_["RunCommand"] = 1563 &TestingAutomationProvider::ExecuteBrowserCommandJSON; 1564 handler_map_["IsMenuCommandEnabled"] = 1565 &TestingAutomationProvider::IsMenuCommandEnabledJSON; 1566 handler_map_["ActivateTab"] = 1567 &TestingAutomationProvider::ActivateTabJSON; 1568 handler_map_["BringBrowserToFront"] = 1569 &TestingAutomationProvider::BringBrowserToFrontJSON; 1570 handler_map_["GetIndicesFromTab"] = 1571 &TestingAutomationProvider::GetIndicesFromTab; 1572 handler_map_["NavigateToURL"] = 1573 &TestingAutomationProvider::NavigateToURL; 1574 handler_map_["GetActiveTabIndex"] = 1575 &TestingAutomationProvider::GetActiveTabIndexJSON; 1576 handler_map_["AppendTab"] = 1577 &TestingAutomationProvider::AppendTabJSON; 1578 handler_map_["OpenNewBrowserWindow"] = 1579 &TestingAutomationProvider::OpenNewBrowserWindow; 1580 handler_map_["CloseBrowserWindow"] = 1581 &TestingAutomationProvider::CloseBrowserWindow; 1582 handler_map_["WaitUntilNavigationCompletes"] = 1583 &TestingAutomationProvider::WaitUntilNavigationCompletes; 1584 handler_map_["GetLocalStatePrefsInfo"] = 1585 &TestingAutomationProvider::GetLocalStatePrefsInfo; 1586 handler_map_["SetLocalStatePrefs"] = 1587 &TestingAutomationProvider::SetLocalStatePrefs; 1588 handler_map_["GetPrefsInfo"] = &TestingAutomationProvider::GetPrefsInfo; 1589 handler_map_["SetPrefs"] = &TestingAutomationProvider::SetPrefs; 1590 handler_map_["ExecuteJavascript"] = 1591 &TestingAutomationProvider::ExecuteJavascriptJSON; 1592 handler_map_["AddDomEventObserver"] = 1593 &TestingAutomationProvider::AddDomEventObserver; 1594 handler_map_["RemoveEventObserver"] = 1595 &TestingAutomationProvider::RemoveEventObserver; 1596 handler_map_["GetNextEvent"] = 1597 &TestingAutomationProvider::GetNextEvent; 1598 handler_map_["ClearEventQueue"] = 1599 &TestingAutomationProvider::ClearEventQueue; 1600 handler_map_["ExecuteJavascriptInRenderView"] = 1601 &TestingAutomationProvider::ExecuteJavascriptInRenderView; 1602 handler_map_["GoForward"] = 1603 &TestingAutomationProvider::GoForward; 1604 handler_map_["GoBack"] = 1605 &TestingAutomationProvider::GoBack; 1606 handler_map_["Reload"] = 1607 &TestingAutomationProvider::ReloadJSON; 1608 handler_map_["OpenFindInPage"] = 1609 &TestingAutomationProvider::OpenFindInPage; 1610 handler_map_["IsFindInPageVisible"] = 1611 &TestingAutomationProvider::IsFindInPageVisible; 1612 handler_map_["SetDownloadShelfVisible"] = 1613 &TestingAutomationProvider::SetDownloadShelfVisibleJSON; 1614 handler_map_["IsDownloadShelfVisible"] = 1615 &TestingAutomationProvider::IsDownloadShelfVisibleJSON; 1616 handler_map_["GetDownloadDirectory"] = 1617 &TestingAutomationProvider::GetDownloadDirectoryJSON; 1618 handler_map_["GetCookies"] = 1619 &TestingAutomationProvider::GetCookiesJSON; 1620 handler_map_["DeleteCookie"] = 1621 &TestingAutomationProvider::DeleteCookieJSON; 1622 handler_map_["SetCookie"] = 1623 &TestingAutomationProvider::SetCookieJSON; 1624 handler_map_["GetCookiesInBrowserContext"] = 1625 &TestingAutomationProvider::GetCookiesInBrowserContext; 1626 handler_map_["DeleteCookieInBrowserContext"] = 1627 &TestingAutomationProvider::DeleteCookieInBrowserContext; 1628 handler_map_["SetCookieInBrowserContext"] = 1629 &TestingAutomationProvider::SetCookieInBrowserContext; 1630 1631 handler_map_["WaitForBookmarkModelToLoad"] = 1632 &TestingAutomationProvider::WaitForBookmarkModelToLoadJSON; 1633 handler_map_["GetBookmarksAsJSON"] = 1634 &TestingAutomationProvider::GetBookmarksAsJSON; 1635 handler_map_["GetBookmarkBarStatus"] = 1636 &TestingAutomationProvider::GetBookmarkBarStatus; 1637 handler_map_["AddBookmark"] = 1638 &TestingAutomationProvider::AddBookmark; 1639 handler_map_["ReparentBookmark"] = 1640 &TestingAutomationProvider::ReparentBookmark; 1641 handler_map_["SetBookmarkTitle"] = 1642 &TestingAutomationProvider::SetBookmarkTitle; 1643 handler_map_["SetBookmarkURL"] = 1644 &TestingAutomationProvider::SetBookmarkURL; 1645 handler_map_["RemoveBookmark"] = 1646 &TestingAutomationProvider::RemoveBookmark; 1647 1648 handler_map_["GetTabIds"] = 1649 &TestingAutomationProvider::GetTabIds; 1650 handler_map_["GetViews"] = 1651 &TestingAutomationProvider::GetViews; 1652 handler_map_["IsTabIdValid"] = 1653 &TestingAutomationProvider::IsTabIdValid; 1654 handler_map_["DoesAutomationObjectExist"] = 1655 &TestingAutomationProvider::DoesAutomationObjectExist; 1656 handler_map_["CloseTab"] = 1657 &TestingAutomationProvider::CloseTabJSON; 1658 handler_map_["SetViewBounds"] = 1659 &TestingAutomationProvider::SetViewBounds; 1660 handler_map_["MaximizeView"] = 1661 &TestingAutomationProvider::MaximizeView; 1662 handler_map_["WebkitMouseMove"] = 1663 &TestingAutomationProvider::WebkitMouseMove; 1664 handler_map_["WebkitMouseClick"] = 1665 &TestingAutomationProvider::WebkitMouseClick; 1666 handler_map_["WebkitMouseDrag"] = 1667 &TestingAutomationProvider::WebkitMouseDrag; 1668 handler_map_["WebkitMouseButtonUp"] = 1669 &TestingAutomationProvider::WebkitMouseButtonUp; 1670 handler_map_["WebkitMouseButtonDown"] = 1671 &TestingAutomationProvider::WebkitMouseButtonDown; 1672 handler_map_["WebkitMouseDoubleClick"] = 1673 &TestingAutomationProvider::WebkitMouseDoubleClick; 1674 handler_map_["DragAndDropFilePaths"] = 1675 &TestingAutomationProvider::DragAndDropFilePaths; 1676 handler_map_["SendWebkitKeyEvent"] = 1677 &TestingAutomationProvider::SendWebkitKeyEvent; 1678 handler_map_["ActivateTab"] = 1679 &TestingAutomationProvider::ActivateTabJSON; 1680 handler_map_["GetAppModalDialogMessage"] = 1681 &TestingAutomationProvider::GetAppModalDialogMessage; 1682 handler_map_["AcceptOrDismissAppModalDialog"] = 1683 &TestingAutomationProvider::AcceptOrDismissAppModalDialog; 1684 handler_map_["ActionOnSSLBlockingPage"] = 1685 &TestingAutomationProvider::ActionOnSSLBlockingPage; 1686 handler_map_["GetSecurityState"] = 1687 &TestingAutomationProvider::GetSecurityState; 1688 handler_map_["GetChromeDriverAutomationVersion"] = 1689 &TestingAutomationProvider::GetChromeDriverAutomationVersion; 1690 handler_map_["IsPageActionVisible"] = 1691 &TestingAutomationProvider::IsPageActionVisible; 1692 handler_map_["CreateNewAutomationProvider"] = 1693 &TestingAutomationProvider::CreateNewAutomationProvider; 1694 handler_map_["GetBrowserWindowCount"] = 1695 &TestingAutomationProvider::GetBrowserWindowCountJSON; 1696 handler_map_["GetBrowserInfo"] = 1697 &TestingAutomationProvider::GetBrowserInfo; 1698 handler_map_["GetTabInfo"] = 1699 &TestingAutomationProvider::GetTabInfo; 1700 handler_map_["GetTabCount"] = 1701 &TestingAutomationProvider::GetTabCountJSON; 1702 handler_map_["OpenNewBrowserWindowWithNewProfile"] = 1703 &TestingAutomationProvider::OpenNewBrowserWindowWithNewProfile; 1704 handler_map_["GetMultiProfileInfo"] = 1705 &TestingAutomationProvider::GetMultiProfileInfo; 1706 handler_map_["OpenProfileWindow"] = 1707 &TestingAutomationProvider::OpenProfileWindow; 1708 handler_map_["GetProcessInfo"] = 1709 &TestingAutomationProvider::GetProcessInfo; 1710 handler_map_["RefreshPolicies"] = 1711 &TestingAutomationProvider::RefreshPolicies; 1712 handler_map_["InstallExtension"] = 1713 &TestingAutomationProvider::InstallExtension; 1714 handler_map_["GetExtensionsInfo"] = 1715 &TestingAutomationProvider::GetExtensionsInfo; 1716 handler_map_["UninstallExtensionById"] = 1717 &TestingAutomationProvider::UninstallExtensionById; 1718 handler_map_["SetExtensionStateById"] = 1719 &TestingAutomationProvider::SetExtensionStateById; 1720 handler_map_["TriggerPageActionById"] = 1721 &TestingAutomationProvider::TriggerPageActionById; 1722 handler_map_["TriggerBrowserActionById"] = 1723 &TestingAutomationProvider::TriggerBrowserActionById; 1724 handler_map_["UpdateExtensionsNow"] = 1725 &TestingAutomationProvider::UpdateExtensionsNow; 1726 handler_map_["OverrideGeoposition"] = 1727 &TestingAutomationProvider::OverrideGeoposition; 1728 handler_map_["SimulateAsanMemoryBug"] = 1729 &TestingAutomationProvider::SimulateAsanMemoryBug; 1730 1731 #if defined(OS_CHROMEOS) 1732 handler_map_["AcceptOOBENetworkScreen"] = 1733 &TestingAutomationProvider::AcceptOOBENetworkScreen; 1734 handler_map_["AcceptOOBEEula"] = &TestingAutomationProvider::AcceptOOBEEula; 1735 handler_map_["CancelOOBEUpdate"] = 1736 &TestingAutomationProvider::CancelOOBEUpdate; 1737 handler_map_["PickUserImage"] = &TestingAutomationProvider::PickUserImage; 1738 handler_map_["SkipToLogin"] = &TestingAutomationProvider::SkipToLogin; 1739 handler_map_["GetOOBEScreenInfo"] = 1740 &TestingAutomationProvider::GetOOBEScreenInfo; 1741 1742 handler_map_["GetLoginInfo"] = &TestingAutomationProvider::GetLoginInfo; 1743 handler_map_["ShowCreateAccountUI"] = 1744 &TestingAutomationProvider::ShowCreateAccountUI; 1745 handler_map_["ExecuteJavascriptInOOBEWebUI"] = 1746 &TestingAutomationProvider::ExecuteJavascriptInOOBEWebUI; 1747 handler_map_["LoginAsGuest"] = &TestingAutomationProvider::LoginAsGuest; 1748 handler_map_["SubmitLoginForm"] = 1749 &TestingAutomationProvider::SubmitLoginForm; 1750 handler_map_["AddLoginEventObserver"] = 1751 &TestingAutomationProvider::AddLoginEventObserver; 1752 handler_map_["SignOut"] = &TestingAutomationProvider::SignOut; 1753 1754 handler_map_["LockScreen"] = &TestingAutomationProvider::LockScreen; 1755 handler_map_["UnlockScreen"] = &TestingAutomationProvider::UnlockScreen; 1756 handler_map_["SignoutInScreenLocker"] = 1757 &TestingAutomationProvider::SignoutInScreenLocker; 1758 1759 handler_map_["GetBatteryInfo"] = &TestingAutomationProvider::GetBatteryInfo; 1760 1761 handler_map_["GetNetworkInfo"] = &TestingAutomationProvider::GetNetworkInfo; 1762 handler_map_["NetworkScan"] = &TestingAutomationProvider::NetworkScan; 1763 handler_map_["ToggleNetworkDevice"] = 1764 &TestingAutomationProvider::ToggleNetworkDevice; 1765 handler_map_["ConnectToCellularNetwork"] = 1766 &TestingAutomationProvider::ConnectToCellularNetwork; 1767 handler_map_["DisconnectFromCellularNetwork"] = 1768 &TestingAutomationProvider::DisconnectFromCellularNetwork; 1769 handler_map_["ConnectToWifiNetwork"] = 1770 &TestingAutomationProvider::ConnectToWifiNetwork; 1771 handler_map_["ConnectToHiddenWifiNetwork"] = 1772 &TestingAutomationProvider::ConnectToHiddenWifiNetwork; 1773 handler_map_["DisconnectFromWifiNetwork"] = 1774 &TestingAutomationProvider::DisconnectFromWifiNetwork; 1775 handler_map_["ForgetWifiNetwork"] = 1776 &TestingAutomationProvider::ForgetWifiNetwork; 1777 1778 handler_map_["AddPrivateNetwork"] = 1779 &TestingAutomationProvider::AddPrivateNetwork; 1780 handler_map_["GetPrivateNetworkInfo"] = 1781 &TestingAutomationProvider::GetPrivateNetworkInfo; 1782 handler_map_["ConnectToPrivateNetwork"] = 1783 &TestingAutomationProvider::ConnectToPrivateNetwork; 1784 handler_map_["DisconnectFromPrivateNetwork"] = 1785 &TestingAutomationProvider::DisconnectFromPrivateNetwork; 1786 1787 handler_map_["EnableSpokenFeedback"] = 1788 &TestingAutomationProvider::EnableSpokenFeedback; 1789 handler_map_["IsSpokenFeedbackEnabled"] = 1790 &TestingAutomationProvider::IsSpokenFeedbackEnabled; 1791 1792 handler_map_["GetTimeInfo"] = &TestingAutomationProvider::GetTimeInfo; 1793 handler_map_["SetTimezone"] = &TestingAutomationProvider::SetTimezone; 1794 1795 handler_map_["UpdateCheck"] = &TestingAutomationProvider::UpdateCheck; 1796 1797 handler_map_["GetVolumeInfo"] = &TestingAutomationProvider::GetVolumeInfo; 1798 handler_map_["SetVolume"] = &TestingAutomationProvider::SetVolume; 1799 handler_map_["SetMute"] = &TestingAutomationProvider::SetMute; 1800 1801 handler_map_["OpenCrosh"] = &TestingAutomationProvider::OpenCrosh; 1802 handler_map_["SetProxySettings"] = 1803 &TestingAutomationProvider::SetProxySettings; 1804 handler_map_["SetSharedProxies"] = 1805 &TestingAutomationProvider::SetSharedProxies; 1806 1807 browser_handler_map_["GetTimeInfo"] = 1808 &TestingAutomationProvider::GetTimeInfo; 1809 #endif // defined(OS_CHROMEOS) 1810 1811 browser_handler_map_["DisablePlugin"] = 1812 &TestingAutomationProvider::DisablePlugin; 1813 browser_handler_map_["EnablePlugin"] = 1814 &TestingAutomationProvider::EnablePlugin; 1815 browser_handler_map_["GetPluginsInfo"] = 1816 &TestingAutomationProvider::GetPluginsInfo; 1817 1818 browser_handler_map_["GetNavigationInfo"] = 1819 &TestingAutomationProvider::GetNavigationInfo; 1820 1821 browser_handler_map_["PerformActionOnInfobar"] = 1822 &TestingAutomationProvider::PerformActionOnInfobar; 1823 1824 browser_handler_map_["GetHistoryInfo"] = 1825 &TestingAutomationProvider::GetHistoryInfo; 1826 1827 browser_handler_map_["GetOmniboxInfo"] = 1828 &TestingAutomationProvider::GetOmniboxInfo; 1829 browser_handler_map_["SetOmniboxText"] = 1830 &TestingAutomationProvider::SetOmniboxText; 1831 browser_handler_map_["OmniboxAcceptInput"] = 1832 &TestingAutomationProvider::OmniboxAcceptInput; 1833 browser_handler_map_["OmniboxMovePopupSelection"] = 1834 &TestingAutomationProvider::OmniboxMovePopupSelection; 1835 1836 browser_handler_map_["LoadSearchEngineInfo"] = 1837 &TestingAutomationProvider::LoadSearchEngineInfo; 1838 browser_handler_map_["GetSearchEngineInfo"] = 1839 &TestingAutomationProvider::GetSearchEngineInfo; 1840 browser_handler_map_["AddOrEditSearchEngine"] = 1841 &TestingAutomationProvider::AddOrEditSearchEngine; 1842 browser_handler_map_["PerformActionOnSearchEngine"] = 1843 &TestingAutomationProvider::PerformActionOnSearchEngine; 1844 1845 browser_handler_map_["SetWindowDimensions"] = 1846 &TestingAutomationProvider::SetWindowDimensions; 1847 1848 browser_handler_map_["GetDownloadsInfo"] = 1849 &TestingAutomationProvider::GetDownloadsInfo; 1850 browser_handler_map_["WaitForAllDownloadsToComplete"] = 1851 &TestingAutomationProvider::WaitForAllDownloadsToComplete; 1852 browser_handler_map_["PerformActionOnDownload"] = 1853 &TestingAutomationProvider::PerformActionOnDownload; 1854 1855 browser_handler_map_["GetInitialLoadTimes"] = 1856 &TestingAutomationProvider::GetInitialLoadTimes; 1857 1858 browser_handler_map_["SaveTabContents"] = 1859 &TestingAutomationProvider::SaveTabContents; 1860 1861 browser_handler_map_["AddSavedPassword"] = 1862 &TestingAutomationProvider::AddSavedPassword; 1863 browser_handler_map_["RemoveSavedPassword"] = 1864 &TestingAutomationProvider::RemoveSavedPassword; 1865 browser_handler_map_["GetSavedPasswords"] = 1866 &TestingAutomationProvider::GetSavedPasswords; 1867 1868 browser_handler_map_["FindInPage"] = &TestingAutomationProvider::FindInPage; 1869 1870 browser_handler_map_["GetAllNotifications"] = 1871 &TestingAutomationProvider::GetAllNotifications; 1872 browser_handler_map_["CloseNotification"] = 1873 &TestingAutomationProvider::CloseNotification; 1874 browser_handler_map_["WaitForNotificationCount"] = 1875 &TestingAutomationProvider::WaitForNotificationCount; 1876 1877 browser_handler_map_["GetNTPInfo"] = 1878 &TestingAutomationProvider::GetNTPInfo; 1879 browser_handler_map_["RemoveNTPMostVisitedThumbnail"] = 1880 &TestingAutomationProvider::RemoveNTPMostVisitedThumbnail; 1881 browser_handler_map_["RestoreAllNTPMostVisitedThumbnails"] = 1882 &TestingAutomationProvider::RestoreAllNTPMostVisitedThumbnails; 1883 1884 browser_handler_map_["KillRendererProcess"] = 1885 &TestingAutomationProvider::KillRendererProcess; 1886 1887 browser_handler_map_["LaunchApp"] = &TestingAutomationProvider::LaunchApp; 1888 browser_handler_map_["SetAppLaunchType"] = 1889 &TestingAutomationProvider::SetAppLaunchType; 1890 1891 browser_handler_map_["GetV8HeapStats"] = 1892 &TestingAutomationProvider::GetV8HeapStats; 1893 browser_handler_map_["GetFPS"] = 1894 &TestingAutomationProvider::GetFPS; 1895 1896 browser_handler_map_["IsFullscreenForBrowser"] = 1897 &TestingAutomationProvider::IsFullscreenForBrowser; 1898 browser_handler_map_["IsFullscreenForTab"] = 1899 &TestingAutomationProvider::IsFullscreenForTab; 1900 browser_handler_map_["IsMouseLocked"] = 1901 &TestingAutomationProvider::IsMouseLocked; 1902 browser_handler_map_["IsMouseLockPermissionRequested"] = 1903 &TestingAutomationProvider::IsMouseLockPermissionRequested; 1904 browser_handler_map_["IsFullscreenPermissionRequested"] = 1905 &TestingAutomationProvider::IsFullscreenPermissionRequested; 1906 browser_handler_map_["IsFullscreenBubbleDisplayed"] = 1907 &TestingAutomationProvider::IsFullscreenBubbleDisplayed; 1908 browser_handler_map_["IsFullscreenBubbleDisplayingButtons"] = 1909 &TestingAutomationProvider::IsFullscreenBubbleDisplayingButtons; 1910 browser_handler_map_["AcceptCurrentFullscreenOrMouseLockRequest"] = 1911 &TestingAutomationProvider::AcceptCurrentFullscreenOrMouseLockRequest; 1912 browser_handler_map_["DenyCurrentFullscreenOrMouseLockRequest"] = 1913 &TestingAutomationProvider::DenyCurrentFullscreenOrMouseLockRequest; 1914 } 1915 1916 scoped_ptr<DictionaryValue> TestingAutomationProvider::ParseJSONRequestCommand( 1917 const std::string& json_request, 1918 std::string* command, 1919 std::string* error) { 1920 scoped_ptr<DictionaryValue> dict_value; 1921 scoped_ptr<Value> values(base::JSONReader::ReadAndReturnError(json_request, 1922 base::JSON_ALLOW_TRAILING_COMMAS, NULL, error)); 1923 if (values.get()) { 1924 // Make sure input is a dict with a string command. 1925 if (values->GetType() != Value::TYPE_DICTIONARY) { 1926 *error = "Command dictionary is not a dictionary."; 1927 } else { 1928 dict_value.reset(static_cast<DictionaryValue*>(values.release())); 1929 if (!dict_value->GetStringASCII("command", command)) { 1930 *error = "Command key string missing from dictionary."; 1931 dict_value.reset(NULL); 1932 } 1933 } 1934 } 1935 return dict_value.Pass(); 1936 } 1937 1938 void TestingAutomationProvider::SendJSONRequestWithBrowserHandle( 1939 int handle, 1940 const std::string& json_request, 1941 IPC::Message* reply_message) { 1942 Browser* browser = NULL; 1943 if (browser_tracker_->ContainsHandle(handle)) 1944 browser = browser_tracker_->GetResource(handle); 1945 if (browser || handle < 0) { 1946 SendJSONRequest(browser, json_request, reply_message); 1947 } else { 1948 AutomationJSONReply(this, reply_message).SendError( 1949 "The browser window does not exist."); 1950 } 1951 } 1952 1953 void TestingAutomationProvider::SendJSONRequestWithBrowserIndex( 1954 int index, 1955 const std::string& json_request, 1956 IPC::Message* reply_message) { 1957 Browser* browser = index < 0 ? NULL : automation_util::GetBrowserAt(index); 1958 if (!browser && index >= 0) { 1959 AutomationJSONReply(this, reply_message).SendError(base::StringPrintf( 1960 "Browser window with index=%d does not exist.", index)); 1961 } else { 1962 SendJSONRequest(browser, json_request, reply_message); 1963 } 1964 } 1965 1966 void TestingAutomationProvider::SendJSONRequest(Browser* browser, 1967 const std::string& json_request, 1968 IPC::Message* reply_message) { 1969 std::string command, error_string; 1970 scoped_ptr<DictionaryValue> dict_value( 1971 ParseJSONRequestCommand(json_request, &command, &error_string)); 1972 if (!dict_value.get() || command.empty()) { 1973 AutomationJSONReply(this, reply_message).SendError(error_string); 1974 return; 1975 } 1976 1977 if (handler_map_.empty() || browser_handler_map_.empty()) 1978 BuildJSONHandlerMaps(); 1979 1980 // Look for command in handlers that take a Browser. 1981 if (browser_handler_map_.find(std::string(command)) != 1982 browser_handler_map_.end() && browser) { 1983 (this->*browser_handler_map_[command])(browser, dict_value.get(), 1984 reply_message); 1985 // Look for command in handlers that don't take a Browser. 1986 } else if (handler_map_.find(std::string(command)) != handler_map_.end()) { 1987 (this->*handler_map_[command])(dict_value.get(), reply_message); 1988 // Command has no handler. 1989 } else { 1990 error_string = base::StringPrintf("Unknown command '%s'. Options: ", 1991 command.c_str()); 1992 for (std::map<std::string, JsonHandler>::const_iterator it = 1993 handler_map_.begin(); it != handler_map_.end(); ++it) { 1994 error_string += it->first + ", "; 1995 } 1996 for (std::map<std::string, BrowserJsonHandler>::const_iterator it = 1997 browser_handler_map_.begin(); it != browser_handler_map_.end(); ++it) { 1998 error_string += it->first + ", "; 1999 } 2000 AutomationJSONReply(this, reply_message).SendError(error_string); 2001 } 2002 } 2003 2004 void TestingAutomationProvider::BringBrowserToFrontJSON( 2005 DictionaryValue* args, 2006 IPC::Message* reply_message) { 2007 AutomationJSONReply reply(this, reply_message); 2008 Browser* browser; 2009 std::string error_msg; 2010 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) { 2011 reply.SendError(error_msg); 2012 return; 2013 } 2014 browser->window()->Activate(); 2015 reply.SendSuccess(NULL); 2016 } 2017 2018 // Sample json input: { "command": "SetWindowDimensions", 2019 // "x": 20, # optional 2020 // "y": 20, # optional 2021 // "width": 800, # optional 2022 // "height": 600 } # optional 2023 void TestingAutomationProvider::SetWindowDimensions( 2024 Browser* browser, 2025 DictionaryValue* args, 2026 IPC::Message* reply_message) { 2027 gfx::Rect rect = browser->window()->GetRestoredBounds(); 2028 int x, y, width, height; 2029 if (args->GetInteger("x", &x)) 2030 rect.set_x(x); 2031 if (args->GetInteger("y", &y)) 2032 rect.set_y(y); 2033 if (args->GetInteger("width", &width)) 2034 rect.set_width(width); 2035 if (args->GetInteger("height", &height)) 2036 rect.set_height(height); 2037 browser->window()->SetBounds(rect); 2038 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 2039 } 2040 2041 ListValue* TestingAutomationProvider::GetInfobarsInfo(WebContents* wc) { 2042 // Each infobar may have different properties depending on the type. 2043 ListValue* infobars = new ListValue; 2044 InfoBarService* infobar_service = InfoBarService::FromWebContents(wc); 2045 for (size_t i = 0; i < infobar_service->infobar_count(); ++i) { 2046 DictionaryValue* infobar_item = new DictionaryValue; 2047 InfoBarDelegate* infobar = infobar_service->infobar_at(i); 2048 switch (infobar->GetInfoBarAutomationType()) { 2049 case InfoBarDelegate::CONFIRM_INFOBAR: 2050 infobar_item->SetString("type", "confirm_infobar"); 2051 break; 2052 case InfoBarDelegate::PASSWORD_INFOBAR: 2053 infobar_item->SetString("type", "password_infobar"); 2054 break; 2055 case InfoBarDelegate::RPH_INFOBAR: 2056 infobar_item->SetString("type", "rph_infobar"); 2057 break; 2058 case InfoBarDelegate::UNKNOWN_INFOBAR: 2059 infobar_item->SetString("type", "unknown_infobar"); 2060 break; 2061 } 2062 if (infobar->AsConfirmInfoBarDelegate()) { 2063 // Also covers ThemeInstalledInfoBarDelegate. 2064 ConfirmInfoBarDelegate* confirm_infobar = 2065 infobar->AsConfirmInfoBarDelegate(); 2066 infobar_item->SetString("text", confirm_infobar->GetMessageText()); 2067 infobar_item->SetString("link_text", confirm_infobar->GetLinkText()); 2068 ListValue* buttons_list = new ListValue; 2069 int buttons = confirm_infobar->GetButtons(); 2070 if (buttons & ConfirmInfoBarDelegate::BUTTON_OK) { 2071 StringValue* button_label = new StringValue( 2072 confirm_infobar->GetButtonLabel( 2073 ConfirmInfoBarDelegate::BUTTON_OK)); 2074 buttons_list->Append(button_label); 2075 } 2076 if (buttons & ConfirmInfoBarDelegate::BUTTON_CANCEL) { 2077 StringValue* button_label = new StringValue( 2078 confirm_infobar->GetButtonLabel( 2079 ConfirmInfoBarDelegate::BUTTON_CANCEL)); 2080 buttons_list->Append(button_label); 2081 } 2082 infobar_item->Set("buttons", buttons_list); 2083 } else if (infobar->AsExtensionInfoBarDelegate()) { 2084 infobar_item->SetString("type", "extension_infobar"); 2085 } else { 2086 infobar_item->SetString("type", "unknown_infobar"); 2087 } 2088 infobars->Append(infobar_item); 2089 } 2090 return infobars; 2091 } 2092 2093 // Sample json input: { "command": "PerformActionOnInfobar", 2094 // "action": "dismiss", 2095 // "infobar_index": 0, 2096 // "tab_index": 0 } 2097 // Sample output: {} 2098 void TestingAutomationProvider::PerformActionOnInfobar( 2099 Browser* browser, 2100 DictionaryValue* args, 2101 IPC::Message* reply_message) { 2102 AutomationJSONReply reply(this, reply_message); 2103 int tab_index; 2104 int infobar_index_int; 2105 std::string action; 2106 if (!args->GetInteger("tab_index", &tab_index) || 2107 !args->GetInteger("infobar_index", &infobar_index_int) || 2108 !args->GetString("action", &action)) { 2109 reply.SendError("Invalid or missing args"); 2110 return; 2111 } 2112 size_t infobar_index = static_cast<size_t>(infobar_index_int); 2113 2114 WebContents* web_contents = 2115 browser->tab_strip_model()->GetWebContentsAt(tab_index); 2116 if (!web_contents) { 2117 reply.SendError(base::StringPrintf("No such tab at index %d", tab_index)); 2118 return; 2119 } 2120 2121 InfoBarService* infobar_service = 2122 InfoBarService::FromWebContents(web_contents); 2123 if (infobar_index >= infobar_service->infobar_count()) { 2124 reply.SendError(base::StringPrintf("No such infobar at index %" PRIuS, 2125 infobar_index)); 2126 return; 2127 } 2128 InfoBarDelegate* infobar_delegate = 2129 infobar_service->infobar_at(infobar_index); 2130 2131 if (action == "dismiss") { 2132 infobar_delegate->InfoBarDismissed(); 2133 infobar_service->RemoveInfoBar(infobar_delegate); 2134 reply.SendSuccess(NULL); 2135 return; 2136 } 2137 if ((action == "accept") || (action == "cancel")) { 2138 ConfirmInfoBarDelegate* confirm_infobar_delegate = 2139 infobar_delegate->AsConfirmInfoBarDelegate(); 2140 if (!confirm_infobar_delegate) { 2141 reply.SendError("Not a confirm infobar"); 2142 return; 2143 } 2144 if ((action == "accept") ? 2145 confirm_infobar_delegate->Accept() : confirm_infobar_delegate->Cancel()) 2146 infobar_service->RemoveInfoBar(infobar_delegate); 2147 reply.SendSuccess(NULL); 2148 return; 2149 } 2150 2151 reply.SendError("Invalid action"); 2152 } 2153 2154 namespace { 2155 2156 // Gets info about BrowserChildProcessHost. Must run on IO thread to 2157 // honor the semantics of BrowserChildProcessHostIterator. 2158 // Used by AutomationProvider::GetBrowserInfo(). 2159 void GetChildProcessHostInfo(ListValue* child_processes) { 2160 for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) { 2161 // Only add processes which are already started, since we need their handle. 2162 if (iter.GetData().handle == base::kNullProcessHandle) 2163 continue; 2164 DictionaryValue* item = new DictionaryValue; 2165 item->SetString("name", iter.GetData().name); 2166 item->SetString( 2167 "type", 2168 content::GetProcessTypeNameInEnglish(iter.GetData().process_type)); 2169 item->SetInteger("pid", base::GetProcId(iter.GetData().handle)); 2170 child_processes->Append(item); 2171 } 2172 } 2173 2174 } // namespace 2175 2176 // Sample json input: { "command": "GetBrowserInfo" } 2177 // Refer to GetBrowserInfo() in chrome/test/pyautolib/pyauto.py for 2178 // sample json output. 2179 void TestingAutomationProvider::GetBrowserInfo( 2180 DictionaryValue* args, 2181 IPC::Message* reply_message) { 2182 base::ThreadRestrictions::ScopedAllowIO allow_io; // needed for PathService 2183 DictionaryValue* properties = new DictionaryValue; 2184 properties->SetString("ChromeVersion", chrome::kChromeVersion); 2185 properties->SetString("BrowserProcessExecutableName", 2186 chrome::kBrowserProcessExecutableName); 2187 properties->SetString("HelperProcessExecutableName", 2188 chrome::kHelperProcessExecutableName); 2189 properties->SetString("BrowserProcessExecutablePath", 2190 chrome::kBrowserProcessExecutablePath); 2191 properties->SetString("HelperProcessExecutablePath", 2192 chrome::kHelperProcessExecutablePath); 2193 properties->SetString("command_line_string", 2194 CommandLine::ForCurrentProcess()->GetCommandLineString()); 2195 base::FilePath dumps_path; 2196 PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path); 2197 properties->SetString("DIR_CRASH_DUMPS", dumps_path.value()); 2198 #if defined(USE_AURA) 2199 properties->SetBoolean("aura", true); 2200 #else 2201 properties->SetBoolean("aura", false); 2202 #endif 2203 2204 std::string branding; 2205 #if defined(GOOGLE_CHROME_BUILD) 2206 branding = "Google Chrome"; 2207 #elif defined(CHROMIUM_BUILD) 2208 branding = "Chromium"; 2209 #else 2210 branding = "Unknown Branding"; 2211 #endif 2212 properties->SetString("branding", branding); 2213 2214 bool is_official_build = false; 2215 #if defined(OFFICIAL_BUILD) 2216 is_official_build = true; 2217 #endif 2218 properties->SetBoolean("is_official", is_official_build); 2219 2220 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 2221 return_value->Set("properties", properties); 2222 2223 return_value->SetInteger("browser_pid", base::GetCurrentProcId()); 2224 // Add info about all windows in a list of dictionaries, one dictionary 2225 // item per window. 2226 ListValue* windows = new ListValue; 2227 int windex = 0; 2228 2229 for (chrome::BrowserIterator it; !it.done(); it.Next(), ++windex) { 2230 DictionaryValue* browser_item = new DictionaryValue; 2231 Browser* browser = *it; 2232 browser_item->SetInteger("index", windex); 2233 // Window properties 2234 gfx::Rect rect = browser->window()->GetRestoredBounds(); 2235 browser_item->SetInteger("x", rect.x()); 2236 browser_item->SetInteger("y", rect.y()); 2237 browser_item->SetInteger("width", rect.width()); 2238 browser_item->SetInteger("height", rect.height()); 2239 browser_item->SetBoolean("fullscreen", 2240 browser->window()->IsFullscreen()); 2241 ListValue* visible_page_actions = new ListValue; 2242 // Add info about all visible page actions. Skipped on panels, which do not 2243 // have a location bar. 2244 LocationBar* loc_bar = browser->window()->GetLocationBar(); 2245 if (loc_bar) { 2246 LocationBarTesting* loc_bar_test = 2247 loc_bar->GetLocationBarForTesting(); 2248 size_t page_action_visible_count = 2249 static_cast<size_t>(loc_bar_test->PageActionVisibleCount()); 2250 for (size_t i = 0; i < page_action_visible_count; ++i) { 2251 StringValue* extension_id = new StringValue( 2252 loc_bar_test->GetVisiblePageAction(i)->extension_id()); 2253 visible_page_actions->Append(extension_id); 2254 } 2255 } 2256 browser_item->Set("visible_page_actions", visible_page_actions); 2257 browser_item->SetInteger("selected_tab", 2258 browser->tab_strip_model()->active_index()); 2259 browser_item->SetBoolean("incognito", 2260 browser->profile()->IsOffTheRecord()); 2261 browser_item->SetString("profile_path", 2262 browser->profile()->GetPath().BaseName().MaybeAsASCII()); 2263 std::string type; 2264 switch (browser->type()) { 2265 case Browser::TYPE_TABBED: 2266 type = "tabbed"; 2267 break; 2268 case Browser::TYPE_POPUP: 2269 type = "popup"; 2270 break; 2271 default: 2272 type = "unknown"; 2273 break; 2274 } 2275 browser_item->SetString("type", type); 2276 // For each window, add info about all tabs in a list of dictionaries, 2277 // one dictionary item per tab. 2278 ListValue* tabs = new ListValue; 2279 for (int i = 0; i < browser->tab_strip_model()->count(); ++i) { 2280 WebContents* wc = browser->tab_strip_model()->GetWebContentsAt(i); 2281 DictionaryValue* tab = new DictionaryValue; 2282 tab->SetInteger("index", i); 2283 tab->SetString("url", wc->GetURL().spec()); 2284 tab->SetInteger("renderer_pid", 2285 base::GetProcId(wc->GetRenderProcessHost()->GetHandle())); 2286 tab->Set("infobars", GetInfobarsInfo(wc)); 2287 tab->SetBoolean("pinned", browser->tab_strip_model()->IsTabPinned(i)); 2288 tabs->Append(tab); 2289 } 2290 browser_item->Set("tabs", tabs); 2291 2292 windows->Append(browser_item); 2293 } 2294 return_value->Set("windows", windows); 2295 2296 #if defined(OS_LINUX) 2297 int flags = ChildProcessHost::CHILD_ALLOW_SELF; 2298 #else 2299 int flags = ChildProcessHost::CHILD_NORMAL; 2300 #endif 2301 2302 // Add all extension processes in a list of dictionaries, one dictionary 2303 // item per extension process. 2304 ListValue* extension_views = new ListValue; 2305 ProfileManager* profile_manager = g_browser_process->profile_manager(); 2306 std::vector<Profile*> profiles(profile_manager->GetLoadedProfiles()); 2307 for (size_t i = 0; i < profiles.size(); ++i) { 2308 ExtensionProcessManager* process_manager = 2309 extensions::ExtensionSystem::Get(profiles[i])->process_manager(); 2310 if (!process_manager) 2311 continue; 2312 const ExtensionProcessManager::ViewSet view_set = 2313 process_manager->GetAllViews(); 2314 for (ExtensionProcessManager::ViewSet::const_iterator jt = 2315 view_set.begin(); 2316 jt != view_set.end(); ++jt) { 2317 content::RenderViewHost* render_view_host = *jt; 2318 // Don't add dead extension processes. 2319 if (!render_view_host->IsRenderViewLive()) 2320 continue; 2321 // Don't add views for which we can't obtain an extension. 2322 // TODO(benwells): work out why this happens. It only happens for one 2323 // test, and only on the bots. 2324 const Extension* extension = 2325 process_manager->GetExtensionForRenderViewHost(render_view_host); 2326 if (!extension) 2327 continue; 2328 DictionaryValue* item = new DictionaryValue; 2329 item->SetString("name", extension->name()); 2330 item->SetString("extension_id", extension->id()); 2331 item->SetInteger( 2332 "pid", 2333 base::GetProcId(render_view_host->GetProcess()->GetHandle())); 2334 DictionaryValue* view = new DictionaryValue; 2335 view->SetInteger( 2336 "render_process_id", 2337 render_view_host->GetProcess()->GetID()); 2338 view->SetInteger( 2339 "render_view_id", 2340 render_view_host->GetRoutingID()); 2341 item->Set("view", view); 2342 std::string type; 2343 WebContents* web_contents = 2344 WebContents::FromRenderViewHost(render_view_host); 2345 extensions::ViewType view_type = extensions::GetViewType(web_contents); 2346 switch (view_type) { 2347 case extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE: 2348 type = "EXTENSION_BACKGROUND_PAGE"; 2349 break; 2350 case extensions::VIEW_TYPE_EXTENSION_POPUP: 2351 type = "EXTENSION_POPUP"; 2352 break; 2353 case extensions::VIEW_TYPE_EXTENSION_INFOBAR: 2354 type = "EXTENSION_INFOBAR"; 2355 break; 2356 case extensions::VIEW_TYPE_EXTENSION_DIALOG: 2357 type = "EXTENSION_DIALOG"; 2358 break; 2359 case extensions::VIEW_TYPE_APP_SHELL: 2360 type = "APP_SHELL"; 2361 break; 2362 case extensions::VIEW_TYPE_PANEL: 2363 type = "PANEL"; 2364 break; 2365 default: 2366 type = "unknown"; 2367 break; 2368 } 2369 item->SetString("view_type", type); 2370 item->SetString("url", web_contents->GetURL().spec()); 2371 item->SetBoolean("loaded", !render_view_host->IsLoading()); 2372 extension_views->Append(item); 2373 } 2374 } 2375 return_value->Set("extension_views", extension_views); 2376 2377 return_value->SetString("child_process_path", 2378 ChildProcessHost::GetChildPath(flags).value()); 2379 // Child processes are the processes for plugins and other workers. 2380 // Add all child processes in a list of dictionaries, one dictionary item 2381 // per child process. 2382 ListValue* child_processes = new ListValue; 2383 return_value->Set("child_processes", child_processes); 2384 BrowserThread::PostTaskAndReply( 2385 BrowserThread::IO, FROM_HERE, 2386 base::Bind(&GetChildProcessHostInfo, child_processes), 2387 base::Bind(&AutomationJSONReply::SendSuccess, 2388 base::Owned(new AutomationJSONReply(this, reply_message)), 2389 base::Owned(return_value.release()))); 2390 } 2391 2392 // Sample json input: { "command": "GetProcessInfo" } 2393 // Refer to GetProcessInfo() in chrome/test/pyautolib/pyauto.py for 2394 // sample json output. 2395 void TestingAutomationProvider::GetProcessInfo( 2396 DictionaryValue* args, 2397 IPC::Message* reply_message) { 2398 scoped_refptr<ProcessInfoObserver> 2399 proc_observer(new ProcessInfoObserver(this, reply_message)); 2400 // TODO(jamescook): Maybe this shouldn't update UMA stats? 2401 proc_observer->StartFetch(MemoryDetails::UPDATE_USER_METRICS); 2402 } 2403 2404 // Sample json input: { "command": "GetNavigationInfo" } 2405 // Refer to GetNavigationInfo() in chrome/test/pyautolib/pyauto.py for 2406 // sample json output. 2407 void TestingAutomationProvider::GetNavigationInfo( 2408 Browser* browser, 2409 DictionaryValue* args, 2410 IPC::Message* reply_message) { 2411 AutomationJSONReply reply(this, reply_message); 2412 int tab_index; 2413 WebContents* web_contents = NULL; 2414 if (!args->GetInteger("tab_index", &tab_index) || 2415 !(web_contents = 2416 browser->tab_strip_model()->GetWebContentsAt(tab_index))) { 2417 reply.SendError("tab_index missing or invalid."); 2418 return; 2419 } 2420 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 2421 const NavigationController& controller = web_contents->GetController(); 2422 NavigationEntry* nav_entry = controller.GetActiveEntry(); 2423 DCHECK(nav_entry); 2424 2425 // Security info. 2426 DictionaryValue* ssl = new DictionaryValue; 2427 std::map<content::SecurityStyle, std::string> style_to_string; 2428 style_to_string[content::SECURITY_STYLE_UNKNOWN] = "SECURITY_STYLE_UNKNOWN"; 2429 style_to_string[content::SECURITY_STYLE_UNAUTHENTICATED] = 2430 "SECURITY_STYLE_UNAUTHENTICATED"; 2431 style_to_string[content::SECURITY_STYLE_AUTHENTICATION_BROKEN] = 2432 "SECURITY_STYLE_AUTHENTICATION_BROKEN"; 2433 style_to_string[content::SECURITY_STYLE_AUTHENTICATED] = 2434 "SECURITY_STYLE_AUTHENTICATED"; 2435 2436 SSLStatus ssl_status = nav_entry->GetSSL(); 2437 ssl->SetString("security_style", 2438 style_to_string[ssl_status.security_style]); 2439 ssl->SetBoolean("ran_insecure_content", 2440 !!(ssl_status.content_status & SSLStatus::RAN_INSECURE_CONTENT)); 2441 ssl->SetBoolean("displayed_insecure_content", 2442 !!(ssl_status.content_status & SSLStatus::DISPLAYED_INSECURE_CONTENT)); 2443 return_value->Set("ssl", ssl); 2444 2445 // Page type. 2446 std::map<content::PageType, std::string> pagetype_to_string; 2447 pagetype_to_string[content::PAGE_TYPE_NORMAL] = "NORMAL_PAGE"; 2448 pagetype_to_string[content::PAGE_TYPE_ERROR] = "ERROR_PAGE"; 2449 pagetype_to_string[content::PAGE_TYPE_INTERSTITIAL] = 2450 "INTERSTITIAL_PAGE"; 2451 return_value->SetString("page_type", 2452 pagetype_to_string[nav_entry->GetPageType()]); 2453 2454 return_value->SetString("favicon_url", nav_entry->GetFavicon().url.spec()); 2455 reply.SendSuccess(return_value.get()); 2456 } 2457 2458 // Sample json input: { "command": "GetHistoryInfo", 2459 // "search_text": "some text" } 2460 // Refer chrome/test/pyautolib/history_info.py for sample json output. 2461 void TestingAutomationProvider::GetHistoryInfo(Browser* browser, 2462 DictionaryValue* args, 2463 IPC::Message* reply_message) { 2464 consumer_.CancelAllRequests(); 2465 2466 string16 search_text; 2467 args->GetString("search_text", &search_text); 2468 2469 // Fetch history. 2470 HistoryService* hs = HistoryServiceFactory::GetForProfile( 2471 browser->profile(), Profile::EXPLICIT_ACCESS); 2472 history::QueryOptions options; 2473 // The observer owns itself. It deletes itself after it fetches history. 2474 AutomationProviderHistoryObserver* history_observer = 2475 new AutomationProviderHistoryObserver(this, reply_message); 2476 hs->QueryHistory( 2477 search_text, 2478 options, 2479 &consumer_, 2480 base::Bind(&AutomationProviderHistoryObserver::HistoryQueryComplete, 2481 base::Unretained(history_observer))); 2482 } 2483 2484 // Sample json input: { "command": "GetDownloadsInfo" } 2485 // Refer chrome/test/pyautolib/download_info.py for sample json output. 2486 void TestingAutomationProvider::GetDownloadsInfo(Browser* browser, 2487 DictionaryValue* args, 2488 IPC::Message* reply_message) { 2489 AutomationJSONReply reply(this, reply_message); 2490 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 2491 ListValue* list_of_downloads = new ListValue; 2492 2493 DownloadService* download_service( 2494 DownloadServiceFactory::GetForBrowserContext(browser->profile())); 2495 2496 if (download_service->HasCreatedDownloadManager()) { 2497 std::vector<DownloadItem*> downloads; 2498 BrowserContext::GetDownloadManager(browser->profile())->GetAllDownloads( 2499 &downloads); 2500 2501 for (std::vector<DownloadItem*>::iterator it = downloads.begin(); 2502 it != downloads.end(); 2503 it++) { // Fill info about each download item. 2504 list_of_downloads->Append(GetDictionaryFromDownloadItem( 2505 *it, browser->profile()->IsOffTheRecord())); 2506 } 2507 } 2508 return_value->Set("downloads", list_of_downloads); 2509 reply.SendSuccess(return_value.get()); 2510 } 2511 2512 void TestingAutomationProvider::WaitForAllDownloadsToComplete( 2513 Browser* browser, 2514 DictionaryValue* args, 2515 IPC::Message* reply_message) { 2516 ListValue* pre_download_ids = NULL; 2517 2518 if (!args->GetList("pre_download_ids", &pre_download_ids)) { 2519 AutomationJSONReply(this, reply_message) 2520 .SendError( 2521 base::StringPrintf("List of IDs of previous downloads required.")); 2522 return; 2523 } 2524 2525 DownloadService* download_service = 2526 DownloadServiceFactory::GetForBrowserContext(browser->profile()); 2527 if (!download_service->HasCreatedDownloadManager()) { 2528 // No download manager, so no downloads to wait for. 2529 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 2530 return; 2531 } 2532 2533 // This observer will delete itself. 2534 new AllDownloadsCompleteObserver( 2535 this, reply_message, 2536 BrowserContext::GetDownloadManager(browser->profile()), 2537 pre_download_ids); 2538 } 2539 2540 // See PerformActionOnDownload() in chrome/test/pyautolib/pyauto.py for sample 2541 // json input and output. 2542 void TestingAutomationProvider::PerformActionOnDownload( 2543 Browser* browser, 2544 DictionaryValue* args, 2545 IPC::Message* reply_message) { 2546 int id; 2547 std::string action; 2548 2549 DownloadService* download_service = 2550 DownloadServiceFactory::GetForBrowserContext(browser->profile()); 2551 if (!download_service->HasCreatedDownloadManager()) { 2552 AutomationJSONReply(this, reply_message).SendError("No download manager."); 2553 return; 2554 } 2555 if (!args->GetInteger("id", &id) || !args->GetString("action", &action)) { 2556 AutomationJSONReply(this, reply_message) 2557 .SendError("Must include int id and string action."); 2558 return; 2559 } 2560 2561 DownloadManager* download_manager = 2562 BrowserContext::GetDownloadManager(browser->profile()); 2563 DownloadItem* selected_item = download_manager->GetDownload(id); 2564 if (!selected_item) { 2565 AutomationJSONReply(this, reply_message) 2566 .SendError(base::StringPrintf("No download with an id of %d\n", id)); 2567 return; 2568 } 2569 2570 DownloadItem::DownloadState download_state = selected_item->GetState(); 2571 2572 // We need to be IN_PROGRESS for these actions. 2573 if ((action == "pause" || action == "resume" || action == "cancel") && 2574 download_state != DownloadItem::IN_PROGRESS) { 2575 AutomationJSONReply(this, reply_message) 2576 .SendError(base::StringPrintf( 2577 "Action '%s' called on download that is not in progress.", 2578 action.c_str())); 2579 return; 2580 } 2581 2582 if (action == "open") { 2583 selected_item->AddObserver( 2584 new AutomationProviderDownloadUpdatedObserver( 2585 this, reply_message, true, browser->profile()->IsOffTheRecord())); 2586 selected_item->OpenDownload(); 2587 } else if (action == "toggle_open_files_like_this") { 2588 DownloadPrefs* prefs = 2589 DownloadPrefs::FromBrowserContext(selected_item->GetBrowserContext()); 2590 base::FilePath path = selected_item->GetTargetFilePath(); 2591 if (!selected_item->ShouldOpenFileBasedOnExtension()) 2592 prefs->EnableAutoOpenBasedOnExtension(path); 2593 else 2594 prefs->DisableAutoOpenBasedOnExtension(path); 2595 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 2596 } else if (action == "remove") { 2597 new AutomationProviderDownloadModelChangedObserver( 2598 this, reply_message, download_manager); 2599 selected_item->Remove(); 2600 } else if (action == "decline_dangerous_download") { 2601 new AutomationProviderDownloadModelChangedObserver( 2602 this, reply_message, download_manager); 2603 selected_item->Remove(); 2604 } else if (action == "save_dangerous_download") { 2605 selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver( 2606 this, reply_message, false, browser->profile()->IsOffTheRecord())); 2607 selected_item->ValidateDangerousDownload(); 2608 } else if (action == "pause") { 2609 if (selected_item->IsPaused()) { 2610 // Action would be a no-op; respond right from here. No-op implies 2611 // the test is poorly written or failing, so make it an error return. 2612 AutomationJSONReply(this, reply_message) 2613 .SendError("Action 'pause' called on already paused download."); 2614 } else { 2615 selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver( 2616 this, reply_message, false, browser->profile()->IsOffTheRecord())); 2617 selected_item->Pause(); 2618 } 2619 } else if (action == "resume") { 2620 if (!selected_item->IsPaused()) { 2621 // Action would be a no-op; respond right from here. No-op implies 2622 // the test is poorly written or failing, so make it an error return. 2623 AutomationJSONReply(this, reply_message) 2624 .SendError("Action 'resume' called on unpaused download."); 2625 } else { 2626 selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver( 2627 this, reply_message, false, browser->profile()->IsOffTheRecord())); 2628 selected_item->Resume(); 2629 } 2630 } else if (action == "cancel") { 2631 selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver( 2632 this, reply_message, false, browser->profile()->IsOffTheRecord())); 2633 selected_item->Cancel(true); 2634 } else { 2635 AutomationJSONReply(this, reply_message) 2636 .SendError( 2637 base::StringPrintf("Invalid action '%s' given.", action.c_str())); 2638 } 2639 } 2640 2641 void TestingAutomationProvider::SetDownloadShelfVisibleJSON( 2642 DictionaryValue* args, 2643 IPC::Message* reply_message) { 2644 AutomationJSONReply reply(this, reply_message); 2645 Browser* browser; 2646 std::string error_msg; 2647 bool is_visible; 2648 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) { 2649 reply.SendError(error_msg); 2650 return; 2651 } 2652 if (!args->GetBoolean("is_visible", &is_visible)) { 2653 reply.SendError("'is_visible' missing or invalid."); 2654 return; 2655 } 2656 if (is_visible) { 2657 browser->window()->GetDownloadShelf()->Show(); 2658 } else { 2659 browser->window()->GetDownloadShelf()->Close(DownloadShelf::AUTOMATIC); 2660 } 2661 reply.SendSuccess(NULL); 2662 } 2663 2664 void TestingAutomationProvider::IsDownloadShelfVisibleJSON( 2665 DictionaryValue* args, 2666 IPC::Message* reply_message) { 2667 AutomationJSONReply reply(this, reply_message); 2668 Browser* browser; 2669 std::string error_msg; 2670 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) { 2671 reply.SendError(error_msg); 2672 return; 2673 } 2674 DictionaryValue dict; 2675 dict.SetBoolean("is_visible", browser->window()->IsDownloadShelfVisible()); 2676 reply.SendSuccess(&dict); 2677 } 2678 2679 void TestingAutomationProvider::GetDownloadDirectoryJSON( 2680 DictionaryValue* args, 2681 IPC::Message* reply_message) { 2682 AutomationJSONReply reply(this, reply_message); 2683 WebContents* web_contents; 2684 std::string error; 2685 if (!GetTabFromJSONArgs(args, &web_contents, &error)) { 2686 reply.SendError(error); 2687 return; 2688 } 2689 DownloadManager* dlm = 2690 BrowserContext::GetDownloadManager( 2691 web_contents->GetController().GetBrowserContext()); 2692 DictionaryValue dict; 2693 dict.SetString("path", 2694 DownloadPrefs::FromDownloadManager(dlm)->DownloadPath().value()); 2695 reply.SendSuccess(&dict); 2696 } 2697 2698 // Sample JSON input { "command": "LoadSearchEngineInfo" } 2699 void TestingAutomationProvider::LoadSearchEngineInfo( 2700 Browser* browser, 2701 DictionaryValue* args, 2702 IPC::Message* reply_message) { 2703 TemplateURLService* url_model = 2704 TemplateURLServiceFactory::GetForProfile(browser->profile()); 2705 if (url_model->loaded()) { 2706 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 2707 return; 2708 } 2709 url_model->AddObserver(new AutomationProviderSearchEngineObserver( 2710 this, browser->profile(), reply_message)); 2711 url_model->Load(); 2712 } 2713 2714 // Sample JSON input { "command": "GetSearchEngineInfo" } 2715 // Refer to pyauto.py for sample output. 2716 void TestingAutomationProvider::GetSearchEngineInfo( 2717 Browser* browser, 2718 DictionaryValue* args, 2719 IPC::Message* reply_message) { 2720 TemplateURLService* url_model = 2721 TemplateURLServiceFactory::GetForProfile(browser->profile()); 2722 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 2723 ListValue* search_engines = new ListValue; 2724 TemplateURLService::TemplateURLVector template_urls = 2725 url_model->GetTemplateURLs(); 2726 for (TemplateURLService::TemplateURLVector::const_iterator it = 2727 template_urls.begin(); it != template_urls.end(); ++it) { 2728 DictionaryValue* search_engine = new DictionaryValue; 2729 search_engine->SetString("short_name", UTF16ToUTF8((*it)->short_name())); 2730 search_engine->SetString("keyword", UTF16ToUTF8((*it)->keyword())); 2731 search_engine->SetBoolean("in_default_list", (*it)->ShowInDefaultList()); 2732 search_engine->SetBoolean("is_default", 2733 (*it) == url_model->GetDefaultSearchProvider()); 2734 search_engine->SetBoolean("is_valid", (*it)->url_ref().IsValid()); 2735 search_engine->SetBoolean("supports_replacement", 2736 (*it)->url_ref().SupportsReplacement()); 2737 search_engine->SetString("url", (*it)->url()); 2738 search_engine->SetString("host", (*it)->url_ref().GetHost()); 2739 search_engine->SetString("path", (*it)->url_ref().GetPath()); 2740 search_engine->SetString("display_url", 2741 UTF16ToUTF8((*it)->url_ref().DisplayURL())); 2742 search_engines->Append(search_engine); 2743 } 2744 return_value->Set("search_engines", search_engines); 2745 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get()); 2746 } 2747 2748 // Refer to pyauto.py for sample JSON input. 2749 void TestingAutomationProvider::AddOrEditSearchEngine( 2750 Browser* browser, 2751 DictionaryValue* args, 2752 IPC::Message* reply_message) { 2753 TemplateURLService* url_model = 2754 TemplateURLServiceFactory::GetForProfile(browser->profile()); 2755 string16 new_title; 2756 string16 new_keyword; 2757 std::string new_url; 2758 std::string keyword; 2759 if (!args->GetString("new_title", &new_title) || 2760 !args->GetString("new_keyword", &new_keyword) || 2761 !args->GetString("new_url", &new_url)) { 2762 AutomationJSONReply(this, reply_message).SendError( 2763 "One or more inputs invalid"); 2764 return; 2765 } 2766 std::string new_ref_url = TemplateURLRef::DisplayURLToURLRef( 2767 UTF8ToUTF16(new_url)); 2768 scoped_ptr<KeywordEditorController> controller( 2769 new KeywordEditorController(browser->profile())); 2770 if (args->GetString("keyword", &keyword)) { 2771 TemplateURL* template_url = 2772 url_model->GetTemplateURLForKeyword(UTF8ToUTF16(keyword)); 2773 if (template_url == NULL) { 2774 AutomationJSONReply(this, reply_message).SendError( 2775 "No match for keyword: " + keyword); 2776 return; 2777 } 2778 url_model->AddObserver(new AutomationProviderSearchEngineObserver( 2779 this, browser->profile(), reply_message)); 2780 controller->ModifyTemplateURL(template_url, new_title, new_keyword, 2781 new_ref_url); 2782 } else { 2783 url_model->AddObserver(new AutomationProviderSearchEngineObserver( 2784 this, browser->profile(), reply_message)); 2785 controller->AddTemplateURL(new_title, new_keyword, new_ref_url); 2786 } 2787 } 2788 2789 // Sample json input: { "command": "PerformActionOnSearchEngine", 2790 // "keyword": keyword, "action": action } 2791 void TestingAutomationProvider::PerformActionOnSearchEngine( 2792 Browser* browser, 2793 DictionaryValue* args, 2794 IPC::Message* reply_message) { 2795 TemplateURLService* url_model = 2796 TemplateURLServiceFactory::GetForProfile(browser->profile()); 2797 std::string keyword; 2798 std::string action; 2799 if (!args->GetString("keyword", &keyword) || 2800 !args->GetString("action", &action)) { 2801 AutomationJSONReply(this, reply_message).SendError( 2802 "One or more inputs invalid"); 2803 return; 2804 } 2805 TemplateURL* template_url = 2806 url_model->GetTemplateURLForKeyword(UTF8ToUTF16(keyword)); 2807 if (template_url == NULL) { 2808 AutomationJSONReply(this, reply_message).SendError( 2809 "No match for keyword: " + keyword); 2810 return; 2811 } 2812 if (action == "delete") { 2813 url_model->AddObserver(new AutomationProviderSearchEngineObserver( 2814 this, browser->profile(), reply_message)); 2815 url_model->Remove(template_url); 2816 } else if (action == "default") { 2817 url_model->AddObserver(new AutomationProviderSearchEngineObserver( 2818 this, browser->profile(), reply_message)); 2819 url_model->SetDefaultSearchProvider(template_url); 2820 } else { 2821 AutomationJSONReply(this, reply_message).SendError( 2822 "Invalid action: " + action); 2823 } 2824 } 2825 2826 // Sample json input: { "command": "GetLocalStatePrefsInfo" } 2827 // Refer chrome/test/pyautolib/prefs_info.py for sample json output. 2828 void TestingAutomationProvider::GetLocalStatePrefsInfo( 2829 DictionaryValue* args, 2830 IPC::Message* reply_message) { 2831 DictionaryValue* items = g_browser_process->local_state()-> 2832 GetPreferenceValues(); 2833 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 2834 return_value->Set("prefs", items); // return_value owns items. 2835 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get()); 2836 } 2837 2838 // Sample json input: { "command": "SetLocalStatePrefs", "path": path, 2839 // "value": value } 2840 void TestingAutomationProvider::SetLocalStatePrefs( 2841 DictionaryValue* args, 2842 IPC::Message* reply_message) { 2843 std::string path; 2844 Value* val = NULL; 2845 AutomationJSONReply reply(this, reply_message); 2846 if (args->GetString("path", &path) && args->Get("value", &val)) { 2847 PrefService* pref_service = g_browser_process->local_state(); 2848 const PrefService::Preference* pref = 2849 pref_service->FindPreference(path.c_str()); 2850 if (!pref) { // Not a registered pref. 2851 reply.SendError("pref not registered."); 2852 return; 2853 } else if (pref->IsManaged()) { // Do not attempt to change a managed pref. 2854 reply.SendError("pref is managed. cannot be changed."); 2855 return; 2856 } else { // Set the pref. 2857 pref_service->Set(path.c_str(), *val); 2858 } 2859 } else { 2860 reply.SendError("no pref path or value given."); 2861 return; 2862 } 2863 2864 reply.SendSuccess(NULL); 2865 } 2866 2867 // Sample json input: { "command": "GetPrefsInfo", "windex": 0 } 2868 // Refer chrome/test/pyautolib/prefs_info.py for sample json output. 2869 void TestingAutomationProvider::GetPrefsInfo(DictionaryValue* args, 2870 IPC::Message* reply_message) { 2871 AutomationJSONReply reply(this, reply_message); 2872 Browser* browser; 2873 std::string error_msg; 2874 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) { 2875 reply.SendError(error_msg); 2876 return; 2877 } 2878 DictionaryValue* items = browser->profile()->GetPrefs()-> 2879 GetPreferenceValues(); 2880 2881 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 2882 return_value->Set("prefs", items); // return_value owns items. 2883 reply.SendSuccess(return_value.get()); 2884 } 2885 2886 // Sample json input: 2887 // { "command": "SetPrefs", 2888 // "windex": 0, 2889 // "path": path, 2890 // "value": value } 2891 void TestingAutomationProvider::SetPrefs(DictionaryValue* args, 2892 IPC::Message* reply_message) { 2893 AutomationJSONReply reply(this, reply_message); 2894 Browser* browser; 2895 std::string error_msg; 2896 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) { 2897 reply.SendError(error_msg); 2898 return; 2899 } 2900 std::string path; 2901 Value* val = NULL; 2902 if (args->GetString("path", &path) && args->Get("value", &val)) { 2903 PrefService* pref_service = browser->profile()->GetPrefs(); 2904 const PrefService::Preference* pref = 2905 pref_service->FindPreference(path.c_str()); 2906 if (!pref) { // Not a registered pref. 2907 reply.SendError("pref not registered."); 2908 return; 2909 } else if (pref->IsManaged()) { // Do not attempt to change a managed pref. 2910 reply.SendError("pref is managed. cannot be changed."); 2911 return; 2912 } else { // Set the pref. 2913 pref_service->Set(path.c_str(), *val); 2914 } 2915 } else { 2916 reply.SendError("no pref path or value given."); 2917 return; 2918 } 2919 2920 reply.SendSuccess(NULL); 2921 } 2922 2923 // Sample json input: { "command": "GetOmniboxInfo" } 2924 // Refer chrome/test/pyautolib/omnibox_info.py for sample json output. 2925 void TestingAutomationProvider::GetOmniboxInfo(Browser* browser, 2926 DictionaryValue* args, 2927 IPC::Message* reply_message) { 2928 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 2929 AutomationJSONReply reply(this, reply_message); 2930 2931 LocationBar* loc_bar = browser->window()->GetLocationBar(); 2932 if (!loc_bar) { 2933 reply.SendError("The specified browser does not have a location bar."); 2934 return; 2935 } 2936 const OmniboxView* omnibox_view = loc_bar->GetLocationEntry(); 2937 const OmniboxEditModel* model = omnibox_view->model(); 2938 2939 // Fill up matches. 2940 ListValue* matches = new ListValue; 2941 const AutocompleteResult& result = model->result(); 2942 for (AutocompleteResult::const_iterator i(result.begin()); i != result.end(); 2943 ++i) { 2944 const AutocompleteMatch& match = *i; 2945 DictionaryValue* item = new DictionaryValue; // owned by return_value 2946 item->SetString("type", AutocompleteMatchType::ToString(match.type)); 2947 item->SetBoolean("starred", match.starred); 2948 item->SetString("destination_url", match.destination_url.spec()); 2949 item->SetString("contents", match.contents); 2950 item->SetString("description", match.description); 2951 matches->Append(item); 2952 } 2953 return_value->Set("matches", matches); 2954 2955 // Fill up other properties. 2956 DictionaryValue* properties = new DictionaryValue; // owned by return_value 2957 properties->SetBoolean("has_focus", model->has_focus()); 2958 properties->SetBoolean("query_in_progress", 2959 !model->autocomplete_controller()->done()); 2960 properties->SetString("keyword", model->keyword()); 2961 properties->SetString("text", omnibox_view->GetText()); 2962 return_value->Set("properties", properties); 2963 2964 reply.SendSuccess(return_value.get()); 2965 } 2966 2967 // Sample json input: { "command": "SetOmniboxText", 2968 // "text": "goog" } 2969 void TestingAutomationProvider::SetOmniboxText(Browser* browser, 2970 DictionaryValue* args, 2971 IPC::Message* reply_message) { 2972 string16 text; 2973 AutomationJSONReply reply(this, reply_message); 2974 if (!args->GetString("text", &text)) { 2975 reply.SendError("text missing"); 2976 return; 2977 } 2978 chrome::FocusLocationBar(browser); 2979 LocationBar* loc_bar = browser->window()->GetLocationBar(); 2980 if (!loc_bar) { 2981 reply.SendError("The specified browser does not have a location bar."); 2982 return; 2983 } 2984 OmniboxView* omnibox_view = loc_bar->GetLocationEntry(); 2985 omnibox_view->model()->OnSetFocus(false); 2986 omnibox_view->SetUserText(text); 2987 reply.SendSuccess(NULL); 2988 } 2989 2990 // Sample json input: { "command": "OmniboxMovePopupSelection", 2991 // "count": 1 } 2992 // Negative count implies up, positive implies down. Count values will be 2993 // capped by the size of the popup list. 2994 void TestingAutomationProvider::OmniboxMovePopupSelection( 2995 Browser* browser, 2996 DictionaryValue* args, 2997 IPC::Message* reply_message) { 2998 int count; 2999 AutomationJSONReply reply(this, reply_message); 3000 if (!args->GetInteger("count", &count)) { 3001 reply.SendError("count missing"); 3002 return; 3003 } 3004 LocationBar* loc_bar = browser->window()->GetLocationBar(); 3005 if (!loc_bar) { 3006 reply.SendError("The specified browser does not have a location bar."); 3007 return; 3008 } 3009 loc_bar->GetLocationEntry()->model()->OnUpOrDownKeyPressed(count); 3010 reply.SendSuccess(NULL); 3011 } 3012 3013 // Sample json input: { "command": "OmniboxAcceptInput" } 3014 void TestingAutomationProvider::OmniboxAcceptInput( 3015 Browser* browser, 3016 DictionaryValue* args, 3017 IPC::Message* reply_message) { 3018 NavigationController& controller = 3019 browser->tab_strip_model()->GetActiveWebContents()->GetController(); 3020 LocationBar* loc_bar = browser->window()->GetLocationBar(); 3021 if (!loc_bar) { 3022 AutomationJSONReply(this, reply_message).SendError( 3023 "The specified browser does not have a location bar."); 3024 return; 3025 } 3026 new OmniboxAcceptNotificationObserver(&controller, this, reply_message); 3027 loc_bar->AcceptInput(); 3028 } 3029 3030 // Sample json input: { "command": "GetInitialLoadTimes" } 3031 // Refer to InitialLoadObserver::GetTimingInformation() for sample output. 3032 void TestingAutomationProvider::GetInitialLoadTimes( 3033 Browser*, 3034 DictionaryValue*, 3035 IPC::Message* reply_message) { 3036 scoped_ptr<DictionaryValue> return_value( 3037 initial_load_observer_->GetTimingInformation()); 3038 3039 std::string json_return; 3040 base::JSONWriter::Write(return_value.get(), &json_return); 3041 AutomationMsg_SendJSONRequest::WriteReplyParams( 3042 reply_message, json_return, true); 3043 Send(reply_message); 3044 } 3045 3046 // Sample json input: { "command": "GetPluginsInfo" } 3047 // Refer chrome/test/pyautolib/plugins_info.py for sample json output. 3048 void TestingAutomationProvider::GetPluginsInfo( 3049 Browser* browser, 3050 DictionaryValue* args, 3051 IPC::Message* reply_message) { 3052 PluginService::GetInstance()->GetPlugins( 3053 base::Bind(&TestingAutomationProvider::GetPluginsInfoCallback, 3054 this, browser, args, reply_message)); 3055 } 3056 3057 void TestingAutomationProvider::GetPluginsInfoCallback( 3058 Browser* browser, 3059 DictionaryValue* args, 3060 IPC::Message* reply_message, 3061 const std::vector<content::WebPluginInfo>& plugins) { 3062 PluginPrefs* plugin_prefs = 3063 PluginPrefs::GetForProfile(browser->profile()).get(); 3064 ListValue* items = new ListValue; 3065 for (std::vector<content::WebPluginInfo>::const_iterator it = 3066 plugins.begin(); 3067 it != plugins.end(); 3068 ++it) { 3069 DictionaryValue* item = new DictionaryValue; 3070 item->SetString("name", it->name); 3071 item->SetString("path", it->path.value()); 3072 item->SetString("version", it->version); 3073 item->SetString("desc", it->desc); 3074 item->SetBoolean("enabled", plugin_prefs->IsPluginEnabled(*it)); 3075 // Add info about mime types. 3076 ListValue* mime_types = new ListValue(); 3077 for (std::vector<content::WebPluginMimeType>::const_iterator type_it = 3078 it->mime_types.begin(); 3079 type_it != it->mime_types.end(); 3080 ++type_it) { 3081 DictionaryValue* mime_type = new DictionaryValue(); 3082 mime_type->SetString("mimeType", type_it->mime_type); 3083 mime_type->SetString("description", type_it->description); 3084 3085 ListValue* file_extensions = new ListValue(); 3086 for (std::vector<std::string>::const_iterator ext_it = 3087 type_it->file_extensions.begin(); 3088 ext_it != type_it->file_extensions.end(); 3089 ++ext_it) { 3090 file_extensions->Append(new StringValue(*ext_it)); 3091 } 3092 mime_type->Set("fileExtensions", file_extensions); 3093 3094 mime_types->Append(mime_type); 3095 } 3096 item->Set("mimeTypes", mime_types); 3097 items->Append(item); 3098 } 3099 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 3100 return_value->Set("plugins", items); // return_value owns items. 3101 3102 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get()); 3103 } 3104 3105 // Sample json input: 3106 // { "command": "EnablePlugin", 3107 // "path": "/Library/Internet Plug-Ins/Flash Player.plugin" } 3108 void TestingAutomationProvider::EnablePlugin(Browser* browser, 3109 DictionaryValue* args, 3110 IPC::Message* reply_message) { 3111 base::FilePath::StringType path; 3112 if (!args->GetString("path", &path)) { 3113 AutomationJSONReply(this, reply_message).SendError("path not specified."); 3114 return; 3115 } 3116 PluginPrefs* plugin_prefs = 3117 PluginPrefs::GetForProfile(browser->profile()).get(); 3118 plugin_prefs->EnablePlugin( 3119 true, 3120 base::FilePath(path), 3121 base::Bind(&DidEnablePlugin, 3122 AsWeakPtr(), 3123 reply_message, 3124 path, 3125 "Could not enable plugin for path %s.")); 3126 } 3127 3128 // Sample json input: 3129 // { "command": "DisablePlugin", 3130 // "path": "/Library/Internet Plug-Ins/Flash Player.plugin" } 3131 void TestingAutomationProvider::DisablePlugin(Browser* browser, 3132 DictionaryValue* args, 3133 IPC::Message* reply_message) { 3134 base::FilePath::StringType path; 3135 if (!args->GetString("path", &path)) { 3136 AutomationJSONReply(this, reply_message).SendError("path not specified."); 3137 return; 3138 } 3139 PluginPrefs* plugin_prefs = 3140 PluginPrefs::GetForProfile(browser->profile()).get(); 3141 plugin_prefs->EnablePlugin( 3142 false, 3143 base::FilePath(path), 3144 base::Bind(&DidEnablePlugin, 3145 AsWeakPtr(), 3146 reply_message, 3147 path, 3148 "Could not disable plugin for path %s.")); 3149 } 3150 3151 // Sample json input: 3152 // { "command": "SaveTabContents", 3153 // "tab_index": 0, 3154 // "filename": <a full pathname> } 3155 // Sample json output: 3156 // {} 3157 void TestingAutomationProvider::SaveTabContents( 3158 Browser* browser, 3159 DictionaryValue* args, 3160 IPC::Message* reply_message) { 3161 int tab_index = 0; 3162 base::FilePath::StringType filename; 3163 base::FilePath::StringType parent_directory; 3164 WebContents* web_contents = NULL; 3165 3166 if (!args->GetInteger("tab_index", &tab_index) || 3167 !args->GetString("filename", &filename)) { 3168 AutomationJSONReply(this, reply_message) 3169 .SendError("tab_index or filename param missing"); 3170 return; 3171 } else { 3172 web_contents = browser->tab_strip_model()->GetWebContentsAt(tab_index); 3173 if (!web_contents) { 3174 AutomationJSONReply(this, reply_message).SendError("no tab at tab_index"); 3175 return; 3176 } 3177 } 3178 // We're doing a SAVE_AS_ONLY_HTML so the the directory path isn't 3179 // used. Nevertheless, SavePackage requires it be valid. Sigh. 3180 parent_directory = base::FilePath(filename).DirName().value(); 3181 if (!web_contents->SavePage( 3182 base::FilePath(filename), 3183 base::FilePath(parent_directory), 3184 content::SAVE_PAGE_TYPE_AS_ONLY_HTML)) { 3185 AutomationJSONReply(this, reply_message).SendError( 3186 "Could not initiate SavePage"); 3187 return; 3188 } 3189 // The observer will delete itself when done. 3190 new SavePackageNotificationObserver( 3191 BrowserContext::GetDownloadManager(browser->profile()), 3192 this, reply_message); 3193 } 3194 3195 namespace { 3196 3197 // Translates a dictionary password to a PasswordForm struct. 3198 content::PasswordForm GetPasswordFormFromDict( 3199 const DictionaryValue& password_dict) { 3200 3201 // If the time is specified, change time to the specified time. 3202 base::Time time = base::Time::Now(); 3203 int it; 3204 double dt; 3205 if (password_dict.GetInteger("time", &it)) 3206 time = base::Time::FromTimeT(it); 3207 else if (password_dict.GetDouble("time", &dt)) 3208 time = base::Time::FromDoubleT(dt); 3209 3210 std::string signon_realm; 3211 string16 username_value; 3212 string16 password_value; 3213 string16 origin_url_text; 3214 string16 username_element; 3215 string16 password_element; 3216 string16 submit_element; 3217 string16 action_target_text; 3218 bool blacklist; 3219 string16 old_password_element; 3220 string16 old_password_value; 3221 3222 // We don't care if any of these fail - they are either optional or checked 3223 // before this function is called. 3224 password_dict.GetString("signon_realm", &signon_realm); 3225 password_dict.GetString("username_value", &username_value); 3226 password_dict.GetString("password_value", &password_value); 3227 password_dict.GetString("origin_url", &origin_url_text); 3228 password_dict.GetString("username_element", &username_element); 3229 password_dict.GetString("password_element", &password_element); 3230 password_dict.GetString("submit_element", &submit_element); 3231 password_dict.GetString("action_target", &action_target_text); 3232 if (!password_dict.GetBoolean("blacklist", &blacklist)) 3233 blacklist = false; 3234 3235 GURL origin_gurl(origin_url_text); 3236 GURL action_target(action_target_text); 3237 3238 content::PasswordForm password_form; 3239 password_form.signon_realm = signon_realm; 3240 password_form.username_value = username_value; 3241 password_form.password_value = password_value; 3242 password_form.origin = origin_gurl; 3243 password_form.username_element = username_element; 3244 password_form.password_element = password_element; 3245 password_form.submit_element = submit_element; 3246 password_form.action = action_target; 3247 password_form.blacklisted_by_user = blacklist; 3248 password_form.date_created = time; 3249 3250 return password_form; 3251 } 3252 3253 } // namespace 3254 3255 // See AddSavedPassword() in chrome/test/functional/pyauto.py for sample json 3256 // input. 3257 // Sample json output: { "password_added": true } 3258 void TestingAutomationProvider::AddSavedPassword( 3259 Browser* browser, 3260 DictionaryValue* args, 3261 IPC::Message* reply_message) { 3262 DictionaryValue* password_dict = NULL; 3263 if (!args->GetDictionary("password", &password_dict)) { 3264 AutomationJSONReply(this, reply_message).SendError( 3265 "Must specify a password dictionary."); 3266 return; 3267 } 3268 3269 // The "signon realm" is effectively the primary key and must be included. 3270 // Check here before calling GetPasswordFormFromDict. 3271 if (!password_dict->HasKey("signon_realm")) { 3272 AutomationJSONReply(this, reply_message).SendError( 3273 "Password must include a value for 'signon_realm.'"); 3274 return; 3275 } 3276 3277 content::PasswordForm new_password = 3278 GetPasswordFormFromDict(*password_dict); 3279 3280 // Use IMPLICIT_ACCESS since new passwords aren't added in incognito mode. 3281 PasswordStore* password_store = PasswordStoreFactory::GetForProfile( 3282 browser->profile(), Profile::IMPLICIT_ACCESS).get(); 3283 3284 // The password store does not exist for an incognito window. 3285 if (password_store == NULL) { 3286 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 3287 return_value->SetBoolean("password_added", false); 3288 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get()); 3289 return; 3290 } 3291 3292 // This observer will delete itself. 3293 PasswordStoreLoginsChangedObserver* observer = 3294 new PasswordStoreLoginsChangedObserver(this, reply_message, 3295 PasswordStoreChange::ADD, 3296 "password_added"); 3297 observer->Init(); 3298 password_store->AddLogin(new_password); 3299 } 3300 3301 // See RemoveSavedPassword() in chrome/test/functional/pyauto.py for sample 3302 // json input. 3303 // Sample json output: {} 3304 void TestingAutomationProvider::RemoveSavedPassword( 3305 Browser* browser, 3306 DictionaryValue* args, 3307 IPC::Message* reply_message) { 3308 DictionaryValue* password_dict = NULL; 3309 3310 if (!args->GetDictionary("password", &password_dict)) { 3311 AutomationJSONReply(this, reply_message).SendError( 3312 "Must specify a password dictionary."); 3313 return; 3314 } 3315 3316 // The "signon realm" is effectively the primary key and must be included. 3317 // Check here before calling GetPasswordFormFromDict. 3318 if (!password_dict->HasKey("signon_realm")) { 3319 AutomationJSONReply(this, reply_message).SendError( 3320 "Password must include a value for 'signon_realm.'"); 3321 return; 3322 } 3323 content::PasswordForm to_remove = 3324 GetPasswordFormFromDict(*password_dict); 3325 3326 // Use EXPLICIT_ACCESS since passwords can be removed in incognito mode. 3327 PasswordStore* password_store = PasswordStoreFactory::GetForProfile( 3328 browser->profile(), Profile::EXPLICIT_ACCESS).get(); 3329 if (password_store == NULL) { 3330 AutomationJSONReply(this, reply_message).SendError( 3331 "Unable to get password store."); 3332 return; 3333 } 3334 3335 // This observer will delete itself. 3336 PasswordStoreLoginsChangedObserver* observer = 3337 new PasswordStoreLoginsChangedObserver( 3338 this, reply_message, PasswordStoreChange::REMOVE, std::string()); 3339 observer->Init(); 3340 3341 password_store->RemoveLogin(to_remove); 3342 } 3343 3344 // Sample json input: { "command": "GetSavedPasswords" } 3345 // Refer to GetSavedPasswords() in chrome/test/pyautolib/pyauto.py for sample 3346 // json output. 3347 void TestingAutomationProvider::GetSavedPasswords( 3348 Browser* browser, 3349 DictionaryValue* args, 3350 IPC::Message* reply_message) { 3351 // Use EXPLICIT_ACCESS since saved passwords can be retrieved in 3352 // incognito mode. 3353 PasswordStore* password_store = PasswordStoreFactory::GetForProfile( 3354 browser->profile(), Profile::EXPLICIT_ACCESS).get(); 3355 3356 if (password_store == NULL) { 3357 AutomationJSONReply reply(this, reply_message); 3358 reply.SendError("Unable to get password store."); 3359 return; 3360 } 3361 password_store->GetAutofillableLogins( 3362 new AutomationProviderGetPasswordsObserver(this, reply_message)); 3363 // Observer deletes itself after sending the result. 3364 } 3365 3366 namespace { 3367 3368 // Get the WebContents from a dictionary of arguments. 3369 WebContents* GetWebContentsFromDict(const Browser* browser, 3370 const DictionaryValue* args, 3371 std::string* error_message) { 3372 int tab_index; 3373 if (!args->GetInteger("tab_index", &tab_index)) { 3374 *error_message = "Must include tab_index."; 3375 return NULL; 3376 } 3377 3378 WebContents* web_contents = 3379 browser->tab_strip_model()->GetWebContentsAt(tab_index); 3380 if (!web_contents) { 3381 *error_message = base::StringPrintf("No tab at index %d.", tab_index); 3382 return NULL; 3383 } 3384 return web_contents; 3385 } 3386 3387 } // namespace 3388 3389 void TestingAutomationProvider::FindInPage( 3390 Browser* browser, 3391 DictionaryValue* args, 3392 IPC::Message* reply_message) { 3393 std::string error_message; 3394 WebContents* web_contents = 3395 GetWebContentsFromDict(browser, args, &error_message); 3396 if (!web_contents) { 3397 AutomationJSONReply(this, reply_message).SendError(error_message); 3398 return; 3399 } 3400 string16 search_string; 3401 bool forward; 3402 bool match_case; 3403 bool find_next; 3404 if (!args->GetString("search_string", &search_string)) { 3405 AutomationJSONReply(this, reply_message). 3406 SendError("Must include search_string string."); 3407 return; 3408 } 3409 if (!args->GetBoolean("forward", &forward)) { 3410 AutomationJSONReply(this, reply_message). 3411 SendError("Must include forward boolean."); 3412 return; 3413 } 3414 if (!args->GetBoolean("match_case", &match_case)) { 3415 AutomationJSONReply(this, reply_message). 3416 SendError("Must include match_case boolean."); 3417 return; 3418 } 3419 if (!args->GetBoolean("find_next", &find_next)) { 3420 AutomationJSONReply(this, reply_message). 3421 SendError("Must include find_next boolean."); 3422 return; 3423 } 3424 SendFindRequest(web_contents, 3425 true, 3426 search_string, 3427 forward, 3428 match_case, 3429 find_next, 3430 reply_message); 3431 } 3432 3433 void TestingAutomationProvider::OpenFindInPage( 3434 DictionaryValue* args, 3435 IPC::Message* reply_message) { 3436 AutomationJSONReply reply(this, reply_message); 3437 Browser* browser; 3438 std::string error_msg; 3439 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) { 3440 reply.SendError(error_msg); 3441 return; 3442 } 3443 chrome::FindInPage(browser, false, false); 3444 reply.SendSuccess(NULL); 3445 } 3446 3447 void TestingAutomationProvider::IsFindInPageVisible( 3448 DictionaryValue* args, 3449 IPC::Message* reply_message) { 3450 AutomationJSONReply reply(this, reply_message); 3451 bool visible; 3452 Browser* browser; 3453 std::string error_msg; 3454 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) { 3455 reply.SendError(error_msg); 3456 return; 3457 } 3458 FindBarTesting* find_bar = 3459 browser->GetFindBarController()->find_bar()->GetFindBarTesting(); 3460 find_bar->GetFindBarWindowInfo(NULL, &visible); 3461 DictionaryValue dict; 3462 dict.SetBoolean("is_visible", visible); 3463 reply.SendSuccess(&dict); 3464 } 3465 3466 void TestingAutomationProvider::InstallExtension( 3467 DictionaryValue* args, IPC::Message* reply_message) { 3468 base::FilePath::StringType path_string; 3469 bool with_ui; 3470 bool from_webstore = false; 3471 Browser* browser; 3472 content::WebContents* tab; 3473 std::string error_msg; 3474 if (!GetBrowserAndTabFromJSONArgs(args, &browser, &tab, &error_msg)) { 3475 AutomationJSONReply(this, reply_message).SendError(error_msg); 3476 return; 3477 } 3478 if (!args->GetString("path", &path_string)) { 3479 AutomationJSONReply(this, reply_message).SendError( 3480 "Missing or invalid 'path'"); 3481 return; 3482 } 3483 if (!args->GetBoolean("with_ui", &with_ui)) { 3484 AutomationJSONReply(this, reply_message).SendError( 3485 "Missing or invalid 'with_ui'"); 3486 return; 3487 } 3488 args->GetBoolean("from_webstore", &from_webstore); 3489 3490 ExtensionService* service = extensions::ExtensionSystem::Get( 3491 browser->profile())->extension_service(); 3492 ExtensionProcessManager* manager = 3493 extensions::ExtensionSystem::Get(browser->profile())->process_manager(); 3494 if (service && manager) { 3495 // The observer will delete itself when done. 3496 new ExtensionReadyNotificationObserver( 3497 manager, 3498 service, 3499 this, 3500 reply_message); 3501 3502 base::FilePath extension_path(path_string); 3503 // If the given path has a 'crx' extension, assume it is a packed extension 3504 // and install it. Otherwise load it as an unpacked extension. 3505 if (extension_path.MatchesExtension(FILE_PATH_LITERAL(".crx"))) { 3506 scoped_ptr<ExtensionInstallPrompt> client( 3507 with_ui ? new ExtensionInstallPrompt(tab) : NULL); 3508 scoped_refptr<extensions::CrxInstaller> installer( 3509 extensions::CrxInstaller::Create(service, client.Pass())); 3510 if (!with_ui) 3511 installer->set_allow_silent_install(true); 3512 installer->set_install_cause(extension_misc::INSTALL_CAUSE_AUTOMATION); 3513 if (from_webstore) 3514 installer->set_creation_flags(Extension::FROM_WEBSTORE); 3515 installer->InstallCrx(extension_path); 3516 } else { 3517 scoped_refptr<extensions::UnpackedInstaller> installer( 3518 extensions::UnpackedInstaller::Create(service)); 3519 installer->set_prompt_for_plugins(with_ui); 3520 installer->Load(extension_path); 3521 } 3522 } else { 3523 AutomationJSONReply(this, reply_message).SendError( 3524 "Extensions service/process manager is not available"); 3525 } 3526 } 3527 3528 namespace { 3529 3530 ListValue* GetHostPermissions(const Extension* ext, bool effective_perm) { 3531 extensions::URLPatternSet pattern_set; 3532 if (effective_perm) { 3533 pattern_set = 3534 extensions::PermissionsData::GetEffectiveHostPermissions(ext); 3535 } else { 3536 pattern_set = ext->GetActivePermissions()->explicit_hosts(); 3537 } 3538 3539 ListValue* permissions = new ListValue; 3540 for (extensions::URLPatternSet::const_iterator perm = pattern_set.begin(); 3541 perm != pattern_set.end(); ++perm) { 3542 permissions->Append(new StringValue(perm->GetAsString())); 3543 } 3544 3545 return permissions; 3546 } 3547 3548 ListValue* GetAPIPermissions(const Extension* ext) { 3549 ListValue* permissions = new ListValue; 3550 std::set<std::string> perm_list = 3551 ext->GetActivePermissions()->GetAPIsAsStrings(); 3552 for (std::set<std::string>::const_iterator perm = perm_list.begin(); 3553 perm != perm_list.end(); ++perm) { 3554 permissions->Append(new StringValue(perm->c_str())); 3555 } 3556 return permissions; 3557 } 3558 3559 } // namespace 3560 3561 // Sample json input: { "command": "GetExtensionsInfo" } 3562 // See GetExtensionsInfo() in chrome/test/pyautolib/pyauto.py for sample json 3563 // output. 3564 void TestingAutomationProvider::GetExtensionsInfo(DictionaryValue* args, 3565 IPC::Message* reply_message) { 3566 AutomationJSONReply reply(this, reply_message); 3567 Browser* browser; 3568 std::string error_msg; 3569 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) { 3570 reply.SendError(error_msg); 3571 return; 3572 } 3573 ExtensionService* service = extensions::ExtensionSystem::Get( 3574 browser->profile())->extension_service(); 3575 if (!service) { 3576 reply.SendError("No extensions service."); 3577 return; 3578 } 3579 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 3580 ListValue* extensions_values = new ListValue; 3581 const ExtensionSet* extensions = service->extensions(); 3582 const ExtensionSet* disabled_extensions = service->disabled_extensions(); 3583 ExtensionList all; 3584 all.insert(all.end(), 3585 extensions->begin(), 3586 extensions->end()); 3587 all.insert(all.end(), 3588 disabled_extensions->begin(), 3589 disabled_extensions->end()); 3590 ExtensionActionManager* extension_action_manager = 3591 ExtensionActionManager::Get(browser->profile()); 3592 for (ExtensionList::const_iterator it = all.begin(); 3593 it != all.end(); ++it) { 3594 const Extension* extension = it->get(); 3595 std::string id = extension->id(); 3596 DictionaryValue* extension_value = new DictionaryValue; 3597 extension_value->SetString("id", id); 3598 extension_value->SetString("version", extension->VersionString()); 3599 extension_value->SetString("name", extension->name()); 3600 extension_value->SetString("public_key", extension->public_key()); 3601 extension_value->SetString("description", extension->description()); 3602 extension_value->SetString( 3603 "background_url", 3604 extensions::BackgroundInfo::GetBackgroundURL(extension).spec()); 3605 extension_value->SetString("options_url", 3606 extensions::ManifestURL::GetOptionsPage(extension).spec()); 3607 extension_value->Set("host_permissions", 3608 GetHostPermissions(extension, false)); 3609 extension_value->Set("effective_host_permissions", 3610 GetHostPermissions(extension, true)); 3611 extension_value->Set("api_permissions", GetAPIPermissions(extension)); 3612 Manifest::Location location = extension->location(); 3613 extension_value->SetBoolean("is_component", 3614 location == Manifest::COMPONENT); 3615 extension_value->SetBoolean("is_internal", 3616 location == Manifest::INTERNAL); 3617 extension_value->SetBoolean("is_user_installed", 3618 location == Manifest::INTERNAL || 3619 Manifest::IsUnpackedLocation(location)); 3620 extension_value->SetBoolean("is_enabled", service->IsExtensionEnabled(id)); 3621 extension_value->SetBoolean("allowed_in_incognito", 3622 service->IsIncognitoEnabled(id)); 3623 extension_value->SetBoolean( 3624 "has_page_action", 3625 extension_action_manager->GetPageAction(*extension) != NULL); 3626 extensions_values->Append(extension_value); 3627 } 3628 return_value->Set("extensions", extensions_values); 3629 reply.SendSuccess(return_value.get()); 3630 } 3631 3632 // See UninstallExtensionById() in chrome/test/pyautolib/pyauto.py for sample 3633 // json input. 3634 // Sample json output: {} 3635 void TestingAutomationProvider::UninstallExtensionById( 3636 DictionaryValue* args, 3637 IPC::Message* reply_message) { 3638 const Extension* extension; 3639 std::string error; 3640 Browser* browser; 3641 if (!GetBrowserFromJSONArgs(args, &browser, &error)) { 3642 AutomationJSONReply(this, reply_message).SendError(error); 3643 return; 3644 } 3645 if (!GetExtensionFromJSONArgs( 3646 args, "id", browser->profile(), &extension, &error)) { 3647 AutomationJSONReply(this, reply_message).SendError(error); 3648 return; 3649 } 3650 ExtensionService* service = extensions::ExtensionSystem::Get( 3651 browser->profile())->extension_service(); 3652 if (!service) { 3653 AutomationJSONReply(this, reply_message).SendError( 3654 "No extensions service."); 3655 return; 3656 } 3657 3658 // Wait for a notification indicating that the extension with the given ID 3659 // has been uninstalled. This observer will delete itself. 3660 new ExtensionUninstallObserver(this, reply_message, extension->id()); 3661 service->UninstallExtension(extension->id(), false, NULL); 3662 } 3663 3664 // See SetExtensionStateById() in chrome/test/pyautolib/pyauto.py 3665 // for sample json input. 3666 void TestingAutomationProvider::SetExtensionStateById( 3667 DictionaryValue* args, 3668 IPC::Message* reply_message) { 3669 const Extension* extension; 3670 std::string error; 3671 Browser* browser; 3672 if (!GetBrowserFromJSONArgs(args, &browser, &error)) { 3673 AutomationJSONReply(this, reply_message).SendError(error); 3674 return; 3675 } 3676 if (!GetExtensionFromJSONArgs( 3677 args, "id", browser->profile(), &extension, &error)) { 3678 AutomationJSONReply(this, reply_message).SendError(error); 3679 return; 3680 } 3681 3682 bool enable; 3683 if (!args->GetBoolean("enable", &enable)) { 3684 AutomationJSONReply(this, reply_message) 3685 .SendError("Missing or invalid key: enable"); 3686 return; 3687 } 3688 3689 bool allow_in_incognito; 3690 if (!args->GetBoolean("allow_in_incognito", &allow_in_incognito)) { 3691 AutomationJSONReply(this, reply_message) 3692 .SendError("Missing or invalid key: allow_in_incognito"); 3693 return; 3694 } 3695 3696 if (allow_in_incognito && !enable) { 3697 AutomationJSONReply(this, reply_message) 3698 .SendError("Invalid state: Disabled extension " 3699 "cannot be allowed in incognito mode."); 3700 return; 3701 } 3702 3703 ExtensionService* service = extensions::ExtensionSystem::Get( 3704 browser->profile())->extension_service(); 3705 ExtensionProcessManager* manager = 3706 extensions::ExtensionSystem::Get(browser->profile())->process_manager(); 3707 if (!service) { 3708 AutomationJSONReply(this, reply_message) 3709 .SendError("No extensions service or process manager."); 3710 return; 3711 } 3712 3713 if (enable) { 3714 if (!service->IsExtensionEnabled(extension->id())) { 3715 new ExtensionReadyNotificationObserver( 3716 manager, 3717 service, 3718 this, 3719 reply_message); 3720 service->EnableExtension(extension->id()); 3721 } else { 3722 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 3723 } 3724 } else { 3725 service->DisableExtension(extension->id(), 3726 Extension::DISABLE_USER_ACTION); 3727 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 3728 } 3729 3730 service->SetIsIncognitoEnabled(extension->id(), allow_in_incognito); 3731 } 3732 3733 // See TriggerPageActionById() in chrome/test/pyautolib/pyauto.py 3734 // for sample json input. 3735 void TestingAutomationProvider::TriggerPageActionById( 3736 DictionaryValue* args, 3737 IPC::Message* reply_message) { 3738 std::string error; 3739 Browser* browser; 3740 WebContents* tab; 3741 if (!GetBrowserAndTabFromJSONArgs(args, &browser, &tab, &error)) { 3742 AutomationJSONReply(this, reply_message).SendError(error); 3743 return; 3744 } 3745 const Extension* extension; 3746 if (!GetEnabledExtensionFromJSONArgs( 3747 args, "id", browser->profile(), &extension, &error)) { 3748 AutomationJSONReply(this, reply_message).SendError(error); 3749 return; 3750 } 3751 ExtensionAction* page_action = 3752 ExtensionActionManager::Get(browser->profile())-> 3753 GetPageAction(*extension); 3754 if (!page_action) { 3755 AutomationJSONReply(this, reply_message).SendError( 3756 "Extension doesn't have any page action."); 3757 return; 3758 } 3759 EnsureTabSelected(browser, tab); 3760 3761 bool pressed = false; 3762 LocationBarTesting* loc_bar = 3763 browser->window()->GetLocationBar()->GetLocationBarForTesting(); 3764 size_t page_action_visible_count = 3765 static_cast<size_t>(loc_bar->PageActionVisibleCount()); 3766 for (size_t i = 0; i < page_action_visible_count; ++i) { 3767 if (loc_bar->GetVisiblePageAction(i) == page_action) { 3768 loc_bar->TestPageActionPressed(i); 3769 pressed = true; 3770 break; 3771 } 3772 } 3773 if (!pressed) { 3774 AutomationJSONReply(this, reply_message).SendError( 3775 "Extension's page action is not visible."); 3776 return; 3777 } 3778 3779 if (page_action->HasPopup(ExtensionTabUtil::GetTabId(tab))) { 3780 // This observer will delete itself. 3781 new ExtensionPopupObserver( 3782 this, reply_message, extension->id()); 3783 } else { 3784 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 3785 } 3786 } 3787 3788 // See TriggerBrowserActionById() in chrome/test/pyautolib/pyauto.py 3789 // for sample json input. 3790 void TestingAutomationProvider::TriggerBrowserActionById( 3791 DictionaryValue* args, 3792 IPC::Message* reply_message) { 3793 std::string error; 3794 Browser* browser; 3795 WebContents* tab; 3796 if (!GetBrowserAndTabFromJSONArgs(args, &browser, &tab, &error)) { 3797 AutomationJSONReply(this, reply_message).SendError(error); 3798 return; 3799 } 3800 const Extension* extension; 3801 if (!GetEnabledExtensionFromJSONArgs( 3802 args, "id", browser->profile(), &extension, &error)) { 3803 AutomationJSONReply(this, reply_message).SendError(error); 3804 return; 3805 } 3806 ExtensionAction* action = ExtensionActionManager::Get(browser->profile())-> 3807 GetBrowserAction(*extension); 3808 if (!action) { 3809 AutomationJSONReply(this, reply_message).SendError( 3810 "Extension doesn't have any browser action."); 3811 return; 3812 } 3813 EnsureTabSelected(browser, tab); 3814 3815 BrowserActionTestUtil browser_actions(browser); 3816 int num_browser_actions = browser_actions.NumberOfBrowserActions(); 3817 int action_index = -1; 3818 #if defined(TOOLKIT_VIEWS) 3819 for (int i = 0; i < num_browser_actions; ++i) { 3820 if (extension->id() == browser_actions.GetExtensionId(i)) { 3821 action_index = i; 3822 break; 3823 } 3824 } 3825 #else 3826 // TODO(kkania): Implement the platform-specific GetExtensionId() in 3827 // BrowserActionTestUtil. 3828 if (num_browser_actions != 1) { 3829 AutomationJSONReply(this, reply_message).SendError(base::StringPrintf( 3830 "Found %d browser actions. Only one browser action must be active.", 3831 num_browser_actions)); 3832 return; 3833 } 3834 // This extension has a browser action, and there's only one action, so this 3835 // must be the first one. 3836 action_index = 0; 3837 #endif 3838 if (action_index == -1) { 3839 AutomationJSONReply(this, reply_message).SendError( 3840 "Extension's browser action is not visible."); 3841 return; 3842 } 3843 browser_actions.Press(action_index); 3844 3845 if (action->HasPopup(ExtensionTabUtil::GetTabId(tab))) { 3846 // This observer will delete itself. 3847 new ExtensionPopupObserver( 3848 this, reply_message, extension->id()); 3849 } else { 3850 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 3851 } 3852 } 3853 3854 void TestingAutomationProvider::ActionOnSSLBlockingPage( 3855 DictionaryValue* args, 3856 IPC::Message* reply_message) { 3857 WebContents* web_contents; 3858 bool proceed; 3859 std::string error; 3860 if (!GetTabFromJSONArgs(args, &web_contents, &error)) { 3861 AutomationJSONReply(this, reply_message).SendError(error); 3862 return; 3863 } 3864 if (!args->GetBoolean("proceed", &proceed)) { 3865 AutomationJSONReply(this, reply_message).SendError( 3866 "'proceed' is missing or invalid"); 3867 return; 3868 } 3869 NavigationController& controller = web_contents->GetController(); 3870 NavigationEntry* entry = controller.GetActiveEntry(); 3871 if (entry->GetPageType() == content::PAGE_TYPE_INTERSTITIAL) { 3872 InterstitialPage* ssl_blocking_page = 3873 InterstitialPage::GetInterstitialPage(web_contents); 3874 if (ssl_blocking_page) { 3875 if (proceed) { 3876 new NavigationNotificationObserver(&controller, this, reply_message, 1, 3877 false, true); 3878 ssl_blocking_page->Proceed(); 3879 return; 3880 } 3881 ssl_blocking_page->DontProceed(); 3882 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 3883 return; 3884 } 3885 } 3886 AutomationJSONReply(this, reply_message).SendError(error); 3887 } 3888 3889 void TestingAutomationProvider::GetSecurityState(DictionaryValue* args, 3890 IPC::Message* reply_message) { 3891 AutomationJSONReply reply(this, reply_message); 3892 WebContents* web_contents; 3893 std::string error; 3894 if (!GetTabFromJSONArgs(args, &web_contents, &error)) { 3895 reply.SendError(error); 3896 return; 3897 } 3898 NavigationEntry* entry = web_contents->GetController().GetActiveEntry(); 3899 DictionaryValue dict; 3900 dict.SetInteger("security_style", 3901 static_cast<int>(entry->GetSSL().security_style)); 3902 dict.SetInteger("ssl_cert_status", 3903 static_cast<int>(entry->GetSSL().cert_status)); 3904 dict.SetInteger("insecure_content_status", 3905 static_cast<int>(entry->GetSSL().content_status)); 3906 reply.SendSuccess(&dict); 3907 } 3908 3909 // Sample json input: { "command": "UpdateExtensionsNow" } 3910 // Sample json output: {} 3911 void TestingAutomationProvider::UpdateExtensionsNow( 3912 DictionaryValue* args, 3913 IPC::Message* reply_message) { 3914 std::string error; 3915 Browser* browser; 3916 if (!GetBrowserFromJSONArgs(args, &browser, &error)) { 3917 AutomationJSONReply(this, reply_message).SendError(error); 3918 return; 3919 } 3920 ExtensionService* service = extensions::ExtensionSystem::Get( 3921 browser->profile())->extension_service(); 3922 if (!service) { 3923 AutomationJSONReply(this, reply_message).SendError( 3924 "No extensions service."); 3925 return; 3926 } 3927 3928 extensions::ExtensionUpdater* updater = service->updater(); 3929 if (!updater) { 3930 AutomationJSONReply(this, reply_message).SendError( 3931 "No updater for extensions service."); 3932 return; 3933 } 3934 3935 ExtensionProcessManager* manager = 3936 extensions::ExtensionSystem::Get(browser->profile())->process_manager(); 3937 if (!manager) { 3938 AutomationJSONReply(this, reply_message).SendError( 3939 "No extension process manager."); 3940 return; 3941 } 3942 3943 // Create a new observer that waits until the extensions have been fully 3944 // updated (we should not send the reply until after all extensions have 3945 // been updated). This observer will delete itself. 3946 ExtensionsUpdatedObserver* observer = new ExtensionsUpdatedObserver( 3947 manager, this, reply_message); 3948 extensions::ExtensionUpdater::CheckParams params; 3949 params.install_immediately = true; 3950 params.callback = base::Bind(&ExtensionsUpdatedObserver::UpdateCheckFinished, 3951 base::Unretained(observer)); 3952 updater->CheckNow(params); 3953 } 3954 3955 namespace { 3956 3957 void SendSuccessIfAlive( 3958 base::WeakPtr<AutomationProvider> provider, 3959 IPC::Message* reply_message) { 3960 if (provider.get()) 3961 AutomationJSONReply(provider.get(), reply_message).SendSuccess(NULL); 3962 } 3963 3964 } // namespace 3965 3966 void TestingAutomationProvider::OverrideGeoposition( 3967 base::DictionaryValue* args, 3968 IPC::Message* reply_message) { 3969 double latitude, longitude, altitude; 3970 if (!args->GetDouble("latitude", &latitude) || 3971 !args->GetDouble("longitude", &longitude) || 3972 !args->GetDouble("altitude", &altitude)) { 3973 AutomationJSONReply(this, reply_message).SendError( 3974 "Missing or invalid geolocation parameters"); 3975 return; 3976 } 3977 content::Geoposition position; 3978 position.latitude = latitude; 3979 position.longitude = longitude; 3980 position.altitude = altitude; 3981 position.accuracy = 0.; 3982 position.timestamp = base::Time::Now(); 3983 3984 content::GeolocationProvider::OverrideLocationForTesting( 3985 position, 3986 base::Bind(&SendSuccessIfAlive, AsWeakPtr(), reply_message)); 3987 } 3988 3989 // Refer to GetAllNotifications() in chrome/test/pyautolib/pyauto.py for 3990 // sample json input/output. 3991 void TestingAutomationProvider::GetAllNotifications( 3992 Browser* browser, 3993 DictionaryValue* args, 3994 IPC::Message* reply_message) { 3995 new GetAllNotificationsObserver(this, reply_message); 3996 } 3997 3998 // Refer to CloseNotification() in chrome/test/pyautolib/pyauto.py for 3999 // sample json input. 4000 // Returns empty json message. 4001 void TestingAutomationProvider::CloseNotification( 4002 Browser* browser, 4003 DictionaryValue* args, 4004 IPC::Message* reply_message) { 4005 int index; 4006 if (!args->GetInteger("index", &index)) { 4007 AutomationJSONReply(this, reply_message) 4008 .SendError("'index' missing or invalid."); 4009 return; 4010 } 4011 BalloonNotificationUIManager* manager = 4012 BalloonNotificationUIManager::GetInstanceForTesting(); 4013 BalloonCollection* collection = manager->balloon_collection(); 4014 const BalloonCollection::Balloons& balloons = collection->GetActiveBalloons(); 4015 int balloon_count = static_cast<int>(balloons.size()); 4016 if (index < 0 || index >= balloon_count) { 4017 AutomationJSONReply(this, reply_message) 4018 .SendError(base::StringPrintf("No notification at index %d", index)); 4019 return; 4020 } 4021 std::vector<const Notification*> queued_notes; 4022 manager->GetQueuedNotificationsForTesting(&queued_notes); 4023 if (queued_notes.empty()) { 4024 new OnNotificationBalloonCountObserver( 4025 this, reply_message, balloon_count - 1); 4026 } else { 4027 new NewNotificationBalloonObserver(this, reply_message); 4028 } 4029 manager->CancelById(balloons[index]->notification().notification_id()); 4030 } 4031 4032 // Refer to WaitForNotificationCount() in chrome/test/pyautolib/pyauto.py for 4033 // sample json input. 4034 // Returns empty json message. 4035 void TestingAutomationProvider::WaitForNotificationCount( 4036 Browser* browser, 4037 DictionaryValue* args, 4038 IPC::Message* reply_message) { 4039 int count; 4040 if (!args->GetInteger("count", &count)) { 4041 AutomationJSONReply(this, reply_message) 4042 .SendError("'count' missing or invalid."); 4043 return; 4044 } 4045 // This will delete itself when finished. 4046 new OnNotificationBalloonCountObserver(this, reply_message, count); 4047 } 4048 4049 // Sample JSON input: { "command": "GetNTPInfo" } 4050 // For output, refer to chrome/test/pyautolib/ntp_model.py. 4051 void TestingAutomationProvider::GetNTPInfo( 4052 Browser* browser, 4053 DictionaryValue* args, 4054 IPC::Message* reply_message) { 4055 // This observer will delete itself. 4056 new NTPInfoObserver(this, reply_message); 4057 } 4058 4059 void TestingAutomationProvider::RemoveNTPMostVisitedThumbnail( 4060 Browser* browser, 4061 DictionaryValue* args, 4062 IPC::Message* reply_message) { 4063 AutomationJSONReply reply(this, reply_message); 4064 std::string url; 4065 if (!args->GetString("url", &url)) { 4066 reply.SendError("Missing or invalid 'url' key."); 4067 return; 4068 } 4069 history::TopSites* top_sites = browser->profile()->GetTopSites(); 4070 if (!top_sites) { 4071 reply.SendError("TopSites service is not initialized."); 4072 return; 4073 } 4074 top_sites->AddBlacklistedURL(GURL(url)); 4075 reply.SendSuccess(NULL); 4076 } 4077 4078 void TestingAutomationProvider::RestoreAllNTPMostVisitedThumbnails( 4079 Browser* browser, 4080 DictionaryValue* args, 4081 IPC::Message* reply_message) { 4082 AutomationJSONReply reply(this, reply_message); 4083 history::TopSites* top_sites = browser->profile()->GetTopSites(); 4084 if (!top_sites) { 4085 reply.SendError("TopSites service is not initialized."); 4086 return; 4087 } 4088 top_sites->ClearBlacklistedURLs(); 4089 reply.SendSuccess(NULL); 4090 } 4091 4092 void TestingAutomationProvider::KillRendererProcess( 4093 Browser* browser, 4094 DictionaryValue* args, 4095 IPC::Message* reply_message) { 4096 int pid; 4097 uint32 kAccessFlags = base::kProcessAccessTerminate | 4098 base::kProcessAccessWaitForTermination | 4099 base::kProcessAccessQueryInformation; 4100 4101 if (!args->GetInteger("pid", &pid)) { 4102 AutomationJSONReply(this, reply_message) 4103 .SendError("'pid' key missing or invalid."); 4104 return; 4105 } 4106 base::ProcessHandle process; 4107 if (!base::OpenProcessHandleWithAccess(static_cast<base::ProcessId>(pid), 4108 kAccessFlags, 4109 &process)) { 4110 AutomationJSONReply(this, reply_message).SendError(base::StringPrintf( 4111 "Failed to open process handle for pid %d", pid)); 4112 return; 4113 } 4114 new RendererProcessClosedObserver(this, reply_message); 4115 base::KillProcess(process, 0, false); 4116 base::CloseProcessHandle(process); 4117 } 4118 4119 bool TestingAutomationProvider::BuildWebKeyEventFromArgs( 4120 DictionaryValue* args, 4121 std::string* error, 4122 NativeWebKeyboardEvent* event) { 4123 int type, modifiers; 4124 bool is_system_key; 4125 string16 unmodified_text, text; 4126 std::string key_identifier; 4127 if (!args->GetInteger("type", &type)) { 4128 *error = "'type' missing or invalid."; 4129 return false; 4130 } 4131 if (!args->GetBoolean("isSystemKey", &is_system_key)) { 4132 *error = "'isSystemKey' missing or invalid."; 4133 return false; 4134 } 4135 if (!args->GetString("unmodifiedText", &unmodified_text)) { 4136 *error = "'unmodifiedText' missing or invalid."; 4137 return false; 4138 } 4139 if (!args->GetString("text", &text)) { 4140 *error = "'text' missing or invalid."; 4141 return false; 4142 } 4143 if (!args->GetInteger("nativeKeyCode", &event->nativeKeyCode)) { 4144 *error = "'nativeKeyCode' missing or invalid."; 4145 return false; 4146 } 4147 if (!args->GetInteger("windowsKeyCode", &event->windowsKeyCode)) { 4148 *error = "'windowsKeyCode' missing or invalid."; 4149 return false; 4150 } 4151 if (!args->GetInteger("modifiers", &modifiers)) { 4152 *error = "'modifiers' missing or invalid."; 4153 return false; 4154 } 4155 if (args->GetString("keyIdentifier", &key_identifier)) { 4156 base::strlcpy(event->keyIdentifier, 4157 key_identifier.c_str(), 4158 WebKit::WebKeyboardEvent::keyIdentifierLengthCap); 4159 } else { 4160 *error = "'keyIdentifier' missing or invalid."; 4161 return false; 4162 } 4163 4164 if (type == automation::kRawKeyDownType) { 4165 event->type = WebKit::WebInputEvent::RawKeyDown; 4166 } else if (type == automation::kKeyDownType) { 4167 event->type = WebKit::WebInputEvent::KeyDown; 4168 } else if (type == automation::kKeyUpType) { 4169 event->type = WebKit::WebInputEvent::KeyUp; 4170 } else if (type == automation::kCharType) { 4171 event->type = WebKit::WebInputEvent::Char; 4172 } else { 4173 *error = "'type' refers to an unrecognized keyboard event type"; 4174 return false; 4175 } 4176 4177 string16 unmodified_text_truncated = unmodified_text.substr( 4178 0, WebKit::WebKeyboardEvent::textLengthCap - 1); 4179 memcpy(event->unmodifiedText, 4180 unmodified_text_truncated.c_str(), 4181 unmodified_text_truncated.length() + 1); 4182 string16 text_truncated = text.substr( 4183 0, WebKit::WebKeyboardEvent::textLengthCap - 1); 4184 memcpy(event->text, text_truncated.c_str(), text_truncated.length() + 1); 4185 4186 event->modifiers = 0; 4187 if (modifiers & automation::kShiftKeyMask) 4188 event->modifiers |= WebKit::WebInputEvent::ShiftKey; 4189 if (modifiers & automation::kControlKeyMask) 4190 event->modifiers |= WebKit::WebInputEvent::ControlKey; 4191 if (modifiers & automation::kAltKeyMask) 4192 event->modifiers |= WebKit::WebInputEvent::AltKey; 4193 if (modifiers & automation::kMetaKeyMask) 4194 event->modifiers |= WebKit::WebInputEvent::MetaKey; 4195 4196 event->isSystemKey = is_system_key; 4197 event->timeStampSeconds = base::Time::Now().ToDoubleT(); 4198 event->skip_in_browser = true; 4199 return true; 4200 } 4201 4202 void TestingAutomationProvider::SendWebkitKeyEvent( 4203 DictionaryValue* args, 4204 IPC::Message* reply_message) { 4205 if (SendErrorIfModalDialogActive(this, reply_message)) 4206 return; 4207 4208 NativeWebKeyboardEvent event; 4209 // In the event of an error, BuildWebKeyEventFromArgs handles telling what 4210 // went wrong and sending the reply message; if it fails, we just have to 4211 // stop here. 4212 std::string error; 4213 if (!BuildWebKeyEventFromArgs(args, &error, &event)) { 4214 AutomationJSONReply(this, reply_message).SendError(error); 4215 return; 4216 } 4217 4218 RenderViewHost* view; 4219 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) { 4220 AutomationJSONReply(this, reply_message).SendError(error); 4221 return; 4222 } 4223 new InputEventAckNotificationObserver(this, reply_message, event.type, 1); 4224 view->ForwardKeyboardEvent(event); 4225 } 4226 4227 namespace { 4228 4229 // Gets the active JavaScript modal dialog, or NULL if none. 4230 JavaScriptAppModalDialog* GetActiveJavaScriptModalDialog( 4231 ErrorCode* error_code) { 4232 AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance(); 4233 if (!dialog_queue->HasActiveDialog() || 4234 !dialog_queue->active_dialog()->IsJavaScriptModalDialog()) { 4235 *error_code = automation::kNoJavaScriptModalDialogOpen; 4236 return NULL; 4237 } 4238 return static_cast<JavaScriptAppModalDialog*>(dialog_queue->active_dialog()); 4239 } 4240 4241 } // namespace 4242 4243 void TestingAutomationProvider::GetAppModalDialogMessage( 4244 DictionaryValue* args, IPC::Message* reply_message) { 4245 AutomationJSONReply reply(this, reply_message); 4246 ErrorCode code; 4247 JavaScriptAppModalDialog* dialog = GetActiveJavaScriptModalDialog(&code); 4248 if (!dialog) { 4249 reply.SendErrorCode(code); 4250 return; 4251 } 4252 DictionaryValue result_dict; 4253 result_dict.SetString("message", UTF16ToUTF8(dialog->message_text())); 4254 reply.SendSuccess(&result_dict); 4255 } 4256 4257 void TestingAutomationProvider::AcceptOrDismissAppModalDialog( 4258 DictionaryValue* args, IPC::Message* reply_message) { 4259 AutomationJSONReply reply(this, reply_message); 4260 bool accept; 4261 if (!args->GetBoolean("accept", &accept)) { 4262 reply.SendError("Missing or invalid 'accept'"); 4263 return; 4264 } 4265 4266 ErrorCode code; 4267 JavaScriptAppModalDialog* dialog = GetActiveJavaScriptModalDialog(&code); 4268 if (!dialog) { 4269 reply.SendErrorCode(code); 4270 return; 4271 } 4272 if (accept) { 4273 std::string prompt_text; 4274 if (args->GetString("prompt_text", &prompt_text)) 4275 dialog->SetOverridePromptText(UTF8ToUTF16(prompt_text)); 4276 dialog->native_dialog()->AcceptAppModalDialog(); 4277 } else { 4278 dialog->native_dialog()->CancelAppModalDialog(); 4279 } 4280 reply.SendSuccess(NULL); 4281 } 4282 4283 // Sample JSON input: { "command": "LaunchApp", 4284 // "id": "ahfgeienlihckogmohjhadlkjgocpleb" } 4285 // Sample JSON output: {} 4286 void TestingAutomationProvider::LaunchApp( 4287 Browser* browser, 4288 DictionaryValue* args, 4289 IPC::Message* reply_message) { 4290 std::string id; 4291 if (!args->GetString("id", &id)) { 4292 AutomationJSONReply(this, reply_message).SendError( 4293 "Must include string id."); 4294 return; 4295 } 4296 4297 ExtensionService* service = extensions::ExtensionSystem::Get( 4298 browser->profile())->extension_service(); 4299 if (!service) { 4300 AutomationJSONReply(this, reply_message).SendError( 4301 "No extensions service."); 4302 return; 4303 } 4304 4305 const Extension* extension = service->GetExtensionById( 4306 id, false /* do not include disabled extensions */); 4307 if (!extension) { 4308 AutomationJSONReply(this, reply_message).SendError( 4309 base::StringPrintf( 4310 "Extension with ID '%s' doesn't exist or is disabled.", 4311 id.c_str())); 4312 return; 4313 } 4314 4315 WebContents* old_contents = 4316 browser->tab_strip_model()->GetActiveWebContents(); 4317 if (!old_contents) { 4318 AutomationJSONReply(this, reply_message).SendError( 4319 "Cannot identify selected tab contents."); 4320 return; 4321 } 4322 4323 chrome::AppLaunchParams launch_params(profile(), extension, CURRENT_TAB); 4324 // This observer will delete itself. 4325 new AppLaunchObserver(&old_contents->GetController(), this, reply_message, 4326 launch_params.container); 4327 chrome::OpenApplication(launch_params); 4328 } 4329 4330 // Sample JSON input: { "command": "SetAppLaunchType", 4331 // "id": "ahfgeienlihckogmohjhadlkjgocpleb", 4332 // "launch_type": "pinned" } 4333 // Sample JSON output: {} 4334 void TestingAutomationProvider::SetAppLaunchType( 4335 Browser* browser, 4336 DictionaryValue* args, 4337 IPC::Message* reply_message) { 4338 AutomationJSONReply reply(this, reply_message); 4339 4340 std::string id; 4341 if (!args->GetString("id", &id)) { 4342 reply.SendError("Must include string id."); 4343 return; 4344 } 4345 4346 std::string launch_type_str; 4347 if (!args->GetString("launch_type", &launch_type_str)) { 4348 reply.SendError("Must specify app launch type."); 4349 return; 4350 } 4351 4352 ExtensionService* service = extensions::ExtensionSystem::Get( 4353 browser->profile())->extension_service(); 4354 if (!service) { 4355 reply.SendError("No extensions service."); 4356 return; 4357 } 4358 4359 const Extension* extension = service->GetExtensionById( 4360 id, true /* include disabled extensions */); 4361 if (!extension) { 4362 reply.SendError(base::StringPrintf( 4363 "Extension with ID '%s' doesn't exist.", id.c_str())); 4364 return; 4365 } 4366 4367 extensions::ExtensionPrefs::LaunchType launch_type; 4368 if (launch_type_str == "pinned") { 4369 launch_type = extensions::ExtensionPrefs::LAUNCH_PINNED; 4370 } else if (launch_type_str == "regular") { 4371 launch_type = extensions::ExtensionPrefs::LAUNCH_REGULAR; 4372 } else if (launch_type_str == "fullscreen") { 4373 launch_type = extensions::ExtensionPrefs::LAUNCH_FULLSCREEN; 4374 } else if (launch_type_str == "window") { 4375 launch_type = extensions::ExtensionPrefs::LAUNCH_WINDOW; 4376 } else { 4377 reply.SendError(base::StringPrintf( 4378 "Unexpected launch type '%s'.", launch_type_str.c_str())); 4379 return; 4380 } 4381 4382 service->extension_prefs()->SetLaunchType(extension->id(), launch_type); 4383 reply.SendSuccess(NULL); 4384 } 4385 4386 // Sample json input: { "command": "GetV8HeapStats", 4387 // "tab_index": 0 } 4388 // Refer to GetV8HeapStats() in chrome/test/pyautolib/pyauto.py for 4389 // sample json output. 4390 void TestingAutomationProvider::GetV8HeapStats( 4391 Browser* browser, 4392 DictionaryValue* args, 4393 IPC::Message* reply_message) { 4394 WebContents* web_contents; 4395 int tab_index; 4396 4397 if (!args->GetInteger("tab_index", &tab_index)) { 4398 AutomationJSONReply(this, reply_message).SendError( 4399 "Missing 'tab_index' argument."); 4400 return; 4401 } 4402 4403 web_contents = browser->tab_strip_model()->GetWebContentsAt(tab_index); 4404 if (!web_contents) { 4405 AutomationJSONReply(this, reply_message).SendError(base::StringPrintf( 4406 "Could not get WebContents at tab index %d", tab_index)); 4407 return; 4408 } 4409 4410 RenderViewHost* render_view = web_contents->GetRenderViewHost(); 4411 4412 // This observer will delete itself. 4413 new V8HeapStatsObserver( 4414 this, reply_message, 4415 base::GetProcId(render_view->GetProcess()->GetHandle())); 4416 render_view->Send(new ChromeViewMsg_GetV8HeapStats); 4417 } 4418 4419 // Sample json input: { "command": "GetFPS", 4420 // "tab_index": 0 } 4421 // Refer to GetFPS() in chrome/test/pyautolib/pyauto.py for 4422 // sample json output. 4423 void TestingAutomationProvider::GetFPS( 4424 Browser* browser, 4425 DictionaryValue* args, 4426 IPC::Message* reply_message) { 4427 WebContents* web_contents; 4428 int tab_index; 4429 4430 if (!args->GetInteger("tab_index", &tab_index)) { 4431 AutomationJSONReply(this, reply_message).SendError( 4432 "Missing 'tab_index' argument."); 4433 return; 4434 } 4435 4436 web_contents = browser->tab_strip_model()->GetWebContentsAt(tab_index); 4437 if (!web_contents) { 4438 AutomationJSONReply(this, reply_message).SendError(base::StringPrintf( 4439 "Could not get WebContents at tab index %d", tab_index)); 4440 return; 4441 } 4442 4443 RenderViewHost* render_view = web_contents->GetRenderViewHost(); 4444 int routing_id = render_view->GetRoutingID(); 4445 4446 // This observer will delete itself. 4447 new FPSObserver( 4448 this, reply_message, 4449 base::GetProcId(render_view->GetProcess()->GetHandle()), 4450 routing_id); 4451 render_view->Send(new ChromeViewMsg_GetFPS(routing_id)); 4452 } 4453 4454 void TestingAutomationProvider::IsFullscreenForBrowser(Browser* browser, 4455 base::DictionaryValue* args, 4456 IPC::Message* reply_message) { 4457 DictionaryValue dict; 4458 dict.SetBoolean("result", 4459 browser->fullscreen_controller()->IsFullscreenForBrowser()); 4460 AutomationJSONReply(this, reply_message).SendSuccess(&dict); 4461 } 4462 4463 void TestingAutomationProvider::IsFullscreenForTab(Browser* browser, 4464 base::DictionaryValue* args, 4465 IPC::Message* reply_message) { 4466 DictionaryValue dict; 4467 dict.SetBoolean("result", 4468 browser->fullscreen_controller()->IsFullscreenForTabOrPending()); 4469 AutomationJSONReply(this, reply_message).SendSuccess(&dict); 4470 } 4471 4472 void TestingAutomationProvider::IsMouseLocked(Browser* browser, 4473 base::DictionaryValue* args, 4474 IPC::Message* reply_message) { 4475 DictionaryValue dict; 4476 dict.SetBoolean("result", browser->tab_strip_model()->GetActiveWebContents()-> 4477 GetRenderViewHost()->GetView()->IsMouseLocked()); 4478 AutomationJSONReply(this, reply_message).SendSuccess(&dict); 4479 } 4480 4481 void TestingAutomationProvider::IsMouseLockPermissionRequested( 4482 Browser* browser, 4483 base::DictionaryValue* args, 4484 IPC::Message* reply_message) { 4485 FullscreenExitBubbleType type = 4486 browser->fullscreen_controller()->GetFullscreenExitBubbleType(); 4487 bool mouse_lock = false; 4488 fullscreen_bubble::PermissionRequestedByType(type, NULL, &mouse_lock); 4489 DictionaryValue dict; 4490 dict.SetBoolean("result", mouse_lock); 4491 AutomationJSONReply(this, reply_message).SendSuccess(&dict); 4492 } 4493 4494 void TestingAutomationProvider::IsFullscreenPermissionRequested( 4495 Browser* browser, 4496 base::DictionaryValue* args, 4497 IPC::Message* reply_message) { 4498 FullscreenExitBubbleType type = 4499 browser->fullscreen_controller()->GetFullscreenExitBubbleType(); 4500 bool fullscreen = false; 4501 fullscreen_bubble::PermissionRequestedByType(type, &fullscreen, NULL); 4502 DictionaryValue dict; 4503 dict.SetBoolean("result", fullscreen); 4504 AutomationJSONReply(this, reply_message).SendSuccess(&dict); 4505 } 4506 4507 void TestingAutomationProvider::IsFullscreenBubbleDisplayed(Browser* browser, 4508 base::DictionaryValue* args, 4509 IPC::Message* reply_message) { 4510 FullscreenExitBubbleType type = 4511 browser->fullscreen_controller()->GetFullscreenExitBubbleType(); 4512 DictionaryValue dict; 4513 dict.SetBoolean("result", 4514 type != FEB_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION); 4515 AutomationJSONReply(this, reply_message).SendSuccess(&dict); 4516 } 4517 4518 void TestingAutomationProvider::IsFullscreenBubbleDisplayingButtons( 4519 Browser* browser, 4520 base::DictionaryValue* args, 4521 IPC::Message* reply_message) { 4522 FullscreenExitBubbleType type = 4523 browser->fullscreen_controller()->GetFullscreenExitBubbleType(); 4524 DictionaryValue dict; 4525 dict.SetBoolean("result", fullscreen_bubble::ShowButtonsForType(type)); 4526 AutomationJSONReply(this, reply_message).SendSuccess(&dict); 4527 } 4528 4529 void TestingAutomationProvider::AcceptCurrentFullscreenOrMouseLockRequest( 4530 Browser* browser, 4531 base::DictionaryValue* args, 4532 IPC::Message* reply_message) { 4533 browser->fullscreen_controller()->OnAcceptFullscreenPermission(); 4534 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 4535 } 4536 4537 void TestingAutomationProvider::DenyCurrentFullscreenOrMouseLockRequest( 4538 Browser* browser, 4539 base::DictionaryValue* args, 4540 IPC::Message* reply_message) { 4541 browser->fullscreen_controller()->OnDenyFullscreenPermission(); 4542 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 4543 } 4544 4545 void TestingAutomationProvider::WaitForTabToBeRestored( 4546 DictionaryValue* args, 4547 IPC::Message* reply_message) { 4548 WebContents* web_contents; 4549 std::string error; 4550 if (!GetTabFromJSONArgs(args, &web_contents, &error)) { 4551 AutomationJSONReply(this, reply_message).SendError(error); 4552 return; 4553 } 4554 NavigationController& controller = web_contents->GetController(); 4555 new NavigationControllerRestoredObserver(this, &controller, reply_message); 4556 } 4557 4558 void TestingAutomationProvider::RefreshPolicies( 4559 base::DictionaryValue* args, 4560 IPC::Message* reply_message) { 4561 #if !defined(ENABLE_CONFIGURATION_POLICY) 4562 AutomationJSONReply(this, reply_message).SendError( 4563 "Configuration Policy disabled"); 4564 #else 4565 // Some policies (e.g. URLBlacklist) post tasks to other message loops 4566 // before they start enforcing updated policy values; make sure those tasks 4567 // have finished after a policy update. 4568 // Updates of the URLBlacklist are done on IO, after building the blacklist 4569 // on FILE, which is initiated from IO. 4570 base::Closure reply = 4571 base::Bind(SendSuccessReply, AsWeakPtr(), reply_message); 4572 g_browser_process->policy_service()->RefreshPolicies( 4573 base::Bind(PostTask, BrowserThread::IO, 4574 base::Bind(PostTask, BrowserThread::FILE, 4575 base::Bind(PostTask, BrowserThread::IO, 4576 base::Bind(PostTask, BrowserThread::UI, reply))))); 4577 #endif 4578 } 4579 4580 static int AccessArray(const volatile int arr[], const volatile int *index) { 4581 return arr[*index]; 4582 } 4583 4584 void TestingAutomationProvider::SimulateAsanMemoryBug( 4585 base::DictionaryValue* args, IPC::Message* reply_message) { 4586 // This array is volatile not to let compiler optimize us out. 4587 volatile int testarray[3] = {0, 0, 0}; 4588 4589 // Send the reply while we can. 4590 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 4591 4592 // Cause Address Sanitizer to abort this process. 4593 volatile int index = 5; 4594 AccessArray(testarray, &index); 4595 } 4596 4597 void TestingAutomationProvider::GetIndicesFromTab( 4598 DictionaryValue* args, 4599 IPC::Message* reply_message) { 4600 AutomationJSONReply reply(this, reply_message); 4601 int id_or_handle = 0; 4602 bool has_id = args->HasKey("tab_id"); 4603 bool has_handle = args->HasKey("tab_handle"); 4604 if (has_id && has_handle) { 4605 reply.SendError( 4606 "Both 'tab_id' and 'tab_handle' were specified. Only one is allowed"); 4607 return; 4608 } else if (!has_id && !has_handle) { 4609 reply.SendError("Either 'tab_id' or 'tab_handle' must be specified"); 4610 return; 4611 } 4612 if (has_id && !args->GetInteger("tab_id", &id_or_handle)) { 4613 reply.SendError("'tab_id' is invalid"); 4614 return; 4615 } 4616 if (has_handle && (!args->GetInteger("tab_handle", &id_or_handle) || 4617 !tab_tracker_->ContainsHandle(id_or_handle))) { 4618 reply.SendError("'tab_handle' is invalid"); 4619 return; 4620 } 4621 int id = id_or_handle; 4622 if (has_handle) { 4623 SessionTabHelper* session_tab_helper = 4624 SessionTabHelper::FromWebContents( 4625 tab_tracker_->GetResource(id_or_handle)->GetWebContents()); 4626 id = session_tab_helper->session_id().id(); 4627 } 4628 chrome::BrowserIterator it; 4629 int browser_index = 0; 4630 for (; !it.done(); it.Next(), ++browser_index) { 4631 Browser* browser = *it; 4632 for (int tab_index = 0; 4633 tab_index < browser->tab_strip_model()->count(); 4634 ++tab_index) { 4635 WebContents* tab = 4636 browser->tab_strip_model()->GetWebContentsAt(tab_index); 4637 SessionTabHelper* session_tab_helper = 4638 SessionTabHelper::FromWebContents(tab); 4639 if (session_tab_helper->session_id().id() == id) { 4640 DictionaryValue dict; 4641 dict.SetInteger("windex", browser_index); 4642 dict.SetInteger("tab_index", tab_index); 4643 reply.SendSuccess(&dict); 4644 return; 4645 } 4646 } 4647 } 4648 reply.SendError("Could not find tab among current browser windows"); 4649 } 4650 4651 void TestingAutomationProvider::NavigateToURL( 4652 DictionaryValue* args, 4653 IPC::Message* reply_message) { 4654 if (SendErrorIfModalDialogActive(this, reply_message)) 4655 return; 4656 4657 int navigation_count; 4658 std::string url, error; 4659 Browser* browser; 4660 WebContents* web_contents; 4661 if (!GetBrowserAndTabFromJSONArgs(args, &browser, &web_contents, &error)) { 4662 AutomationJSONReply(this, reply_message).SendError(error); 4663 return; 4664 } 4665 if (!args->GetString("url", &url)) { 4666 AutomationJSONReply(this, reply_message) 4667 .SendError("'url' missing or invalid"); 4668 return; 4669 } 4670 if (!args->GetInteger("navigation_count", &navigation_count)) { 4671 AutomationJSONReply(this, reply_message) 4672 .SendError("'navigation_count' missing or invalid"); 4673 return; 4674 } 4675 if (navigation_count > 0) { 4676 new NavigationNotificationObserver( 4677 &web_contents->GetController(), this, reply_message, 4678 navigation_count, false, true); 4679 } else { 4680 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 4681 } 4682 OpenURLParams params( 4683 GURL(url), content::Referrer(), CURRENT_TAB, 4684 content::PageTransitionFromInt( 4685 content::PAGE_TRANSITION_TYPED | 4686 content::PAGE_TRANSITION_FROM_ADDRESS_BAR), 4687 false); 4688 browser->OpenURLFromTab(web_contents, params); 4689 } 4690 4691 void TestingAutomationProvider::GetActiveTabIndexJSON( 4692 DictionaryValue* args, 4693 IPC::Message* reply_message) { 4694 AutomationJSONReply reply(this, reply_message); 4695 Browser* browser; 4696 std::string error_msg; 4697 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) { 4698 reply.SendError(error_msg); 4699 return; 4700 } 4701 int tab_index = browser->tab_strip_model()->active_index(); 4702 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 4703 return_value->SetInteger("tab_index", tab_index); 4704 reply.SendSuccess(return_value.get()); 4705 } 4706 4707 void TestingAutomationProvider::AppendTabJSON(DictionaryValue* args, 4708 IPC::Message* reply_message) { 4709 TabAppendedNotificationObserver* observer = NULL; 4710 int append_tab_response = -1; 4711 Browser* browser; 4712 std::string error_msg, url; 4713 if (!GetBrowserFromJSONArgs(args, &browser, &error_msg)) { 4714 AutomationJSONReply(this, reply_message).SendError(error_msg); 4715 return; 4716 } 4717 if (!args->GetString("url", &url)) { 4718 AutomationJSONReply(this, reply_message) 4719 .SendError("'url' missing or invalid"); 4720 return; 4721 } 4722 observer = new TabAppendedNotificationObserver(browser, this, reply_message, 4723 true); 4724 WebContents* contents = 4725 chrome::AddSelectedTabWithURL(browser, GURL(url), 4726 content::PAGE_TRANSITION_TYPED); 4727 if (contents) { 4728 append_tab_response = GetIndexForNavigationController( 4729 &contents->GetController(), browser); 4730 } 4731 4732 if (!contents || append_tab_response < 0) { 4733 if (observer) { 4734 observer->ReleaseReply(); 4735 delete observer; 4736 } 4737 AutomationJSONReply(this, reply_message).SendError("Failed to append tab."); 4738 } 4739 } 4740 4741 void TestingAutomationProvider::WaitUntilNavigationCompletes( 4742 DictionaryValue* args, 4743 IPC::Message* reply_message) { 4744 if (SendErrorIfModalDialogActive(this, reply_message)) 4745 return; 4746 4747 std::string error; 4748 Browser* browser; 4749 WebContents* web_contents; 4750 if (!GetBrowserAndTabFromJSONArgs(args, &browser, &web_contents, &error)) { 4751 AutomationJSONReply(this, reply_message).SendError(error); 4752 return; 4753 } 4754 NavigationNotificationObserver* observer = 4755 new NavigationNotificationObserver(&web_contents->GetController(), this, 4756 reply_message, 1, true, true); 4757 if (!web_contents->IsLoading()) { 4758 observer->ConditionMet(AUTOMATION_MSG_NAVIGATION_SUCCESS); 4759 return; 4760 } 4761 } 4762 4763 void TestingAutomationProvider::ExecuteJavascriptJSON( 4764 DictionaryValue* args, 4765 IPC::Message* reply_message) { 4766 if (SendErrorIfModalDialogActive(this, reply_message)) 4767 return; 4768 4769 string16 frame_xpath, javascript; 4770 std::string error; 4771 RenderViewHost* render_view; 4772 if (!GetRenderViewFromJSONArgs(args, profile(), &render_view, &error)) { 4773 AutomationJSONReply(this, reply_message).SendError( 4774 Error(automation::kInvalidId, error)); 4775 return; 4776 } 4777 if (!args->GetString("frame_xpath", &frame_xpath)) { 4778 AutomationJSONReply(this, reply_message) 4779 .SendError("'frame_xpath' missing or invalid"); 4780 return; 4781 } 4782 if (!args->GetString("javascript", &javascript)) { 4783 AutomationJSONReply(this, reply_message) 4784 .SendError("'javascript' missing or invalid"); 4785 return; 4786 } 4787 4788 new DomOperationMessageSender(this, reply_message, true); 4789 ExecuteJavascriptInRenderViewFrame(frame_xpath, javascript, reply_message, 4790 render_view); 4791 } 4792 4793 void TestingAutomationProvider::ExecuteJavascriptInRenderView( 4794 DictionaryValue* args, 4795 IPC::Message* reply_message) { 4796 string16 frame_xpath, javascript, extension_id, url_text; 4797 int render_process_id, render_view_id; 4798 if (!args->GetString("frame_xpath", &frame_xpath)) { 4799 AutomationJSONReply(this, reply_message) 4800 .SendError("'frame_xpath' missing or invalid"); 4801 return; 4802 } 4803 if (!args->GetString("javascript", &javascript)) { 4804 AutomationJSONReply(this, reply_message) 4805 .SendError("'javascript' missing or invalid"); 4806 return; 4807 } 4808 if (!args->GetInteger("view.render_process_id", &render_process_id)) { 4809 AutomationJSONReply(this, reply_message) 4810 .SendError("'view.render_process_id' missing or invalid"); 4811 return; 4812 } 4813 if (!args->GetInteger("view.render_view_id", &render_view_id)) { 4814 AutomationJSONReply(this, reply_message) 4815 .SendError("'view.render_view_id' missing or invalid"); 4816 return; 4817 } 4818 4819 RenderViewHost* rvh = RenderViewHost::FromID(render_process_id, 4820 render_view_id); 4821 if (!rvh) { 4822 AutomationJSONReply(this, reply_message).SendError( 4823 "A RenderViewHost object was not found with the given view ID."); 4824 return; 4825 } 4826 4827 new DomOperationMessageSender(this, reply_message, true); 4828 ExecuteJavascriptInRenderViewFrame(frame_xpath, javascript, reply_message, 4829 rvh); 4830 } 4831 4832 void TestingAutomationProvider::AddDomEventObserver( 4833 DictionaryValue* args, 4834 IPC::Message* reply_message) { 4835 if (SendErrorIfModalDialogActive(this, reply_message)) 4836 return; 4837 4838 AutomationJSONReply reply(this, reply_message); 4839 std::string event_name; 4840 int automation_id; 4841 bool recurring; 4842 if (!args->GetString("event_name", &event_name)) { 4843 reply.SendError("'event_name' missing or invalid"); 4844 return; 4845 } 4846 if (!args->GetInteger("automation_id", &automation_id)) { 4847 reply.SendError("'automation_id' missing or invalid"); 4848 return; 4849 } 4850 if (!args->GetBoolean("recurring", &recurring)) { 4851 reply.SendError("'recurring' missing or invalid"); 4852 return; 4853 } 4854 4855 if (!automation_event_queue_.get()) 4856 automation_event_queue_.reset(new AutomationEventQueue); 4857 4858 int observer_id = automation_event_queue_->AddObserver( 4859 new DomEventObserver(automation_event_queue_.get(), event_name, 4860 automation_id, recurring)); 4861 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 4862 return_value->SetInteger("observer_id", observer_id); 4863 reply.SendSuccess(return_value.get()); 4864 } 4865 4866 void TestingAutomationProvider::RemoveEventObserver( 4867 DictionaryValue* args, 4868 IPC::Message* reply_message) { 4869 AutomationJSONReply reply(this, reply_message); 4870 int observer_id; 4871 if (!args->GetInteger("observer_id", &observer_id) || 4872 !automation_event_queue_.get()) { 4873 reply.SendError("'observer_id' missing or invalid"); 4874 return; 4875 } 4876 if (automation_event_queue_->RemoveObserver(observer_id)) { 4877 reply.SendSuccess(NULL); 4878 return; 4879 } 4880 reply.SendError("Invalid observer id."); 4881 } 4882 4883 void TestingAutomationProvider::ClearEventQueue( 4884 DictionaryValue* args, 4885 IPC::Message* reply_message) { 4886 automation_event_queue_.reset(); 4887 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 4888 } 4889 4890 void TestingAutomationProvider::GetNextEvent( 4891 DictionaryValue* args, 4892 IPC::Message* reply_message) { 4893 scoped_ptr<AutomationJSONReply> reply( 4894 new AutomationJSONReply(this, reply_message)); 4895 int observer_id; 4896 bool blocking; 4897 if (!args->GetInteger("observer_id", &observer_id)) { 4898 reply->SendError("'observer_id' missing or invalid"); 4899 return; 4900 } 4901 if (!args->GetBoolean("blocking", &blocking)) { 4902 reply->SendError("'blocking' missing or invalid"); 4903 return; 4904 } 4905 if (!automation_event_queue_.get()) { 4906 reply->SendError( 4907 "No observers are attached to the queue. Did you create any?"); 4908 return; 4909 } 4910 4911 // The reply will be freed once a matching event is added to the queue. 4912 automation_event_queue_->GetNextEvent(reply.release(), observer_id, blocking); 4913 } 4914 4915 void TestingAutomationProvider::GoForward( 4916 DictionaryValue* args, 4917 IPC::Message* reply_message) { 4918 if (SendErrorIfModalDialogActive(this, reply_message)) 4919 return; 4920 4921 WebContents* web_contents; 4922 std::string error; 4923 if (!GetTabFromJSONArgs(args, &web_contents, &error)) { 4924 AutomationJSONReply(this, reply_message).SendError(error); 4925 return; 4926 } 4927 NavigationController& controller = web_contents->GetController(); 4928 if (!controller.CanGoForward()) { 4929 DictionaryValue dict; 4930 dict.SetBoolean("did_go_forward", false); 4931 AutomationJSONReply(this, reply_message).SendSuccess(&dict); 4932 return; 4933 } 4934 new NavigationNotificationObserver(&controller, this, reply_message, 4935 1, false, true); 4936 controller.GoForward(); 4937 } 4938 4939 void TestingAutomationProvider::ExecuteBrowserCommandAsyncJSON( 4940 DictionaryValue* args, 4941 IPC::Message* reply_message) { 4942 AutomationJSONReply reply(this, reply_message); 4943 int command; 4944 Browser* browser; 4945 std::string error; 4946 if (!GetBrowserFromJSONArgs(args, &browser, &error)) { 4947 reply.SendError(error); 4948 return; 4949 } 4950 if (!args->GetInteger("accelerator", &command)) { 4951 reply.SendError("'accelerator' missing or invalid."); 4952 return; 4953 } 4954 if (!chrome::SupportsCommand(browser, command)) { 4955 reply.SendError(base::StringPrintf("Browser does not support command=%d.", 4956 command)); 4957 return; 4958 } 4959 if (!chrome::IsCommandEnabled(browser, command)) { 4960 reply.SendError(base::StringPrintf( 4961 "Browser command=%d not enabled.", command)); 4962 return; 4963 } 4964 chrome::ExecuteCommand(browser, command); 4965 reply.SendSuccess(NULL); 4966 } 4967 4968 void TestingAutomationProvider::ExecuteBrowserCommandJSON( 4969 DictionaryValue* args, 4970 IPC::Message* reply_message) { 4971 int command; 4972 Browser* browser; 4973 std::string error; 4974 if (!GetBrowserFromJSONArgs(args, &browser, &error)) { 4975 AutomationJSONReply(this, reply_message).SendError(error); 4976 return; 4977 } 4978 if (!args->GetInteger("accelerator", &command)) { 4979 AutomationJSONReply(this, reply_message).SendError( 4980 "'accelerator' missing or invalid."); 4981 return; 4982 } 4983 if (!chrome::SupportsCommand(browser, command)) { 4984 AutomationJSONReply(this, reply_message).SendError( 4985 base::StringPrintf("Browser does not support command=%d.", command)); 4986 return; 4987 } 4988 if (!chrome::IsCommandEnabled(browser, command)) { 4989 AutomationJSONReply(this, reply_message).SendError( 4990 base::StringPrintf("Browser command=%d not enabled.", command)); 4991 return; 4992 } 4993 // First check if we can handle the command without using an observer. 4994 for (size_t i = 0; i < arraysize(kSynchronousCommands); i++) { 4995 if (command == kSynchronousCommands[i]) { 4996 chrome::ExecuteCommand(browser, command); 4997 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 4998 return; 4999 } 5000 } 5001 // Use an observer if we have one, otherwise fail. 5002 if (ExecuteBrowserCommandObserver::CreateAndRegisterObserver( 5003 this, browser, command, reply_message, true)) { 5004 chrome::ExecuteCommand(browser, command); 5005 return; 5006 } 5007 AutomationJSONReply(this, reply_message).SendError(base::StringPrintf( 5008 "Unable to register observer for browser command=%d.", command)); 5009 } 5010 5011 void TestingAutomationProvider::IsMenuCommandEnabledJSON( 5012 DictionaryValue* args, 5013 IPC::Message* reply_message) { 5014 int command; 5015 Browser* browser; 5016 std::string error; 5017 if (!GetBrowserFromJSONArgs(args, &browser, &error)) { 5018 AutomationJSONReply(this, reply_message).SendError(error); 5019 return; 5020 } 5021 if (!args->GetInteger("accelerator", &command)) { 5022 AutomationJSONReply(this, reply_message).SendError( 5023 "'accelerator' missing or invalid."); 5024 return; 5025 } 5026 DictionaryValue dict; 5027 dict.SetBoolean("enabled", chrome::IsCommandEnabled(browser, command)); 5028 AutomationJSONReply(this, reply_message).SendSuccess(&dict); 5029 } 5030 5031 void TestingAutomationProvider::GetTabInfo( 5032 DictionaryValue* args, 5033 IPC::Message* reply_message) { 5034 AutomationJSONReply reply(this, reply_message); 5035 Browser* browser; 5036 WebContents* tab; 5037 std::string error; 5038 if (GetBrowserAndTabFromJSONArgs(args, &browser, &tab, &error)) { 5039 NavigationEntry* entry = tab->GetController().GetActiveEntry(); 5040 if (!entry) { 5041 reply.SendError("Unable to get active navigation entry"); 5042 return; 5043 } 5044 DictionaryValue dict; 5045 dict.SetString("title", entry->GetTitleForDisplay(std::string())); 5046 dict.SetString("url", entry->GetVirtualURL().spec()); 5047 reply.SendSuccess(&dict); 5048 } else { 5049 reply.SendError(error); 5050 } 5051 } 5052 5053 void TestingAutomationProvider::GetTabCountJSON( 5054 DictionaryValue* args, 5055 IPC::Message* reply_message) { 5056 AutomationJSONReply reply(this, reply_message); 5057 Browser* browser; 5058 std::string error; 5059 if (!GetBrowserFromJSONArgs(args, &browser, &error)) { 5060 reply.SendError(error); 5061 return; 5062 } 5063 DictionaryValue dict; 5064 dict.SetInteger("tab_count", browser->tab_strip_model()->count()); 5065 reply.SendSuccess(&dict); 5066 } 5067 5068 void TestingAutomationProvider::GoBack( 5069 DictionaryValue* args, 5070 IPC::Message* reply_message) { 5071 if (SendErrorIfModalDialogActive(this, reply_message)) 5072 return; 5073 5074 WebContents* web_contents; 5075 std::string error; 5076 if (!GetTabFromJSONArgs(args, &web_contents, &error)) { 5077 AutomationJSONReply(this, reply_message).SendError(error); 5078 return; 5079 } 5080 NavigationController& controller = web_contents->GetController(); 5081 if (!controller.CanGoBack()) { 5082 DictionaryValue dict; 5083 dict.SetBoolean("did_go_back", false); 5084 AutomationJSONReply(this, reply_message).SendSuccess(&dict); 5085 return; 5086 } 5087 new NavigationNotificationObserver(&controller, this, reply_message, 5088 1, false, true); 5089 controller.GoBack(); 5090 } 5091 5092 void TestingAutomationProvider::ReloadJSON( 5093 DictionaryValue* args, 5094 IPC::Message* reply_message) { 5095 if (SendErrorIfModalDialogActive(this, reply_message)) 5096 return; 5097 5098 WebContents* web_contents; 5099 std::string error; 5100 if (!GetTabFromJSONArgs(args, &web_contents, &error)) { 5101 AutomationJSONReply(this, reply_message).SendError(error); 5102 return; 5103 } 5104 NavigationController& controller = web_contents->GetController(); 5105 new NavigationNotificationObserver(&controller, this, reply_message, 5106 1, false, true); 5107 controller.Reload(false); 5108 } 5109 5110 void TestingAutomationProvider::GetCookiesJSON( 5111 DictionaryValue* args, IPC::Message* reply_message) { 5112 automation_util::GetCookiesJSON(this, args, reply_message); 5113 } 5114 5115 void TestingAutomationProvider::DeleteCookieJSON( 5116 DictionaryValue* args, IPC::Message* reply_message) { 5117 automation_util::DeleteCookieJSON(this, args, reply_message); 5118 } 5119 5120 void TestingAutomationProvider::SetCookieJSON( 5121 DictionaryValue* args, IPC::Message* reply_message) { 5122 automation_util::SetCookieJSON(this, args, reply_message); 5123 } 5124 5125 void TestingAutomationProvider::GetCookiesInBrowserContext( 5126 DictionaryValue* args, 5127 IPC::Message* reply_message) { 5128 AutomationJSONReply reply(this, reply_message); 5129 WebContents* web_contents; 5130 std::string value, url_string; 5131 int windex, value_size; 5132 if (!args->GetInteger("windex", &windex)) { 5133 reply.SendError("'windex' missing or invalid."); 5134 return; 5135 } 5136 web_contents = automation_util::GetWebContentsAt(windex, 0); 5137 if (!web_contents) { 5138 reply.SendError("'windex' does not refer to a browser window."); 5139 return; 5140 } 5141 if (!args->GetString("url", &url_string)) { 5142 reply.SendError("'url' missing or invalid."); 5143 return; 5144 } 5145 GURL url(url_string); 5146 if (!url.is_valid()) { 5147 reply.SendError("Invalid url."); 5148 return; 5149 } 5150 automation_util::GetCookies(url, web_contents, &value_size, &value); 5151 if (value_size == -1) { 5152 reply.SendError( 5153 base::StringPrintf("Unable to retrieve cookies for url=%s.", 5154 url_string.c_str())); 5155 return; 5156 } 5157 DictionaryValue dict; 5158 dict.SetString("cookies", value); 5159 reply.SendSuccess(&dict); 5160 } 5161 5162 void TestingAutomationProvider::DeleteCookieInBrowserContext( 5163 DictionaryValue* args, 5164 IPC::Message* reply_message) { 5165 AutomationJSONReply reply(this, reply_message); 5166 WebContents* web_contents; 5167 std::string cookie_name, url_string; 5168 int windex; 5169 bool success = false; 5170 if (!args->GetInteger("windex", &windex)) { 5171 reply.SendError("'windex' missing or invalid."); 5172 return; 5173 } 5174 web_contents = automation_util::GetWebContentsAt(windex, 0); 5175 if (!web_contents) { 5176 reply.SendError("'windex' does not refer to a browser window."); 5177 return; 5178 } 5179 if (!args->GetString("cookie_name", &cookie_name)) { 5180 reply.SendError("'cookie_name' missing or invalid."); 5181 return; 5182 } 5183 if (!args->GetString("url", &url_string)) { 5184 reply.SendError("'url' missing or invalid."); 5185 return; 5186 } 5187 GURL url(url_string); 5188 if (!url.is_valid()) { 5189 reply.SendError("Invalid url."); 5190 return; 5191 } 5192 automation_util::DeleteCookie(url, cookie_name, web_contents, &success); 5193 if (!success) { 5194 reply.SendError( 5195 base::StringPrintf("Failed to delete cookie with name=%s for url=%s.", 5196 cookie_name.c_str(), url_string.c_str())); 5197 return; 5198 } 5199 reply.SendSuccess(NULL); 5200 } 5201 5202 void TestingAutomationProvider::SetCookieInBrowserContext( 5203 DictionaryValue* args, 5204 IPC::Message* reply_message) { 5205 AutomationJSONReply reply(this, reply_message); 5206 WebContents* web_contents; 5207 std::string value, url_string; 5208 int windex, response_value = -1; 5209 if (!args->GetInteger("windex", &windex)) { 5210 reply.SendError("'windex' missing or invalid."); 5211 return; 5212 } 5213 web_contents = automation_util::GetWebContentsAt(windex, 0); 5214 if (!web_contents) { 5215 reply.SendError("'windex' does not refer to a browser window."); 5216 return; 5217 } 5218 if (!args->GetString("value", &value)) { 5219 reply.SendError("'value' missing or invalid."); 5220 return; 5221 } 5222 if (!args->GetString("url", &url_string)) { 5223 reply.SendError("'url' missing or invalid."); 5224 return; 5225 } 5226 GURL url(url_string); 5227 if (!url.is_valid()) { 5228 reply.SendError("Invalid url."); 5229 return; 5230 } 5231 automation_util::SetCookie(url, value, web_contents, &response_value); 5232 if (response_value != 1) { 5233 reply.SendError(base::StringPrintf( 5234 "Unable set cookie for url=%s.", url_string.c_str())); 5235 return; 5236 } 5237 reply.SendSuccess(NULL); 5238 } 5239 5240 void TestingAutomationProvider::GetTabIds( 5241 DictionaryValue* args, IPC::Message* reply_message) { 5242 ListValue* id_list = new ListValue(); 5243 for (chrome::BrowserIterator it; !it.done(); it.Next()) { 5244 Browser* browser = *it; 5245 for (int i = 0; i < browser->tab_strip_model()->count(); ++i) { 5246 int id = SessionTabHelper::FromWebContents( 5247 browser->tab_strip_model()->GetWebContentsAt(i))->session_id().id(); 5248 id_list->Append(Value::CreateIntegerValue(id)); 5249 } 5250 } 5251 DictionaryValue dict; 5252 dict.Set("ids", id_list); 5253 AutomationJSONReply(this, reply_message).SendSuccess(&dict); 5254 } 5255 5256 void TestingAutomationProvider::GetViews( 5257 DictionaryValue* args, IPC::Message* reply_message) { 5258 ListValue* view_list = new ListValue(); 5259 #if defined(ENABLE_FULL_PRINTING) 5260 printing::PrintPreviewDialogController* preview_controller = 5261 printing::PrintPreviewDialogController::GetInstance(); 5262 #endif 5263 for (chrome::BrowserIterator it; !it.done(); it.Next()) { 5264 Browser* browser = *it; 5265 for (int i = 0; i < browser->tab_strip_model()->count(); ++i) { 5266 WebContents* contents = browser->tab_strip_model()->GetWebContentsAt(i); 5267 DictionaryValue* dict = new DictionaryValue(); 5268 AutomationId id = automation_util::GetIdForTab(contents); 5269 dict->Set("auto_id", id.ToValue()); 5270 view_list->Append(dict); 5271 #if defined(ENABLE_FULL_PRINTING) 5272 if (preview_controller) { 5273 WebContents* preview_dialog = 5274 preview_controller->GetPrintPreviewForContents(contents); 5275 if (preview_dialog) { 5276 DictionaryValue* dict = new DictionaryValue(); 5277 AutomationId id = automation_util::GetIdForTab(preview_dialog); 5278 dict->Set("auto_id", id.ToValue()); 5279 view_list->Append(dict); 5280 } 5281 } 5282 #endif 5283 } 5284 } 5285 5286 ExtensionProcessManager* extension_mgr = 5287 extensions::ExtensionSystem::Get(profile())->process_manager(); 5288 const ExtensionProcessManager::ViewSet all_views = 5289 extension_mgr->GetAllViews(); 5290 ExtensionProcessManager::ViewSet::const_iterator iter; 5291 for (iter = all_views.begin(); iter != all_views.end(); ++iter) { 5292 content::RenderViewHost* host = (*iter); 5293 AutomationId id = automation_util::GetIdForExtensionView(host); 5294 if (!id.is_valid()) 5295 continue; 5296 const Extension* extension = 5297 extension_mgr->GetExtensionForRenderViewHost(host); 5298 DictionaryValue* dict = new DictionaryValue(); 5299 dict->Set("auto_id", id.ToValue()); 5300 dict->SetString("extension_id", extension->id()); 5301 view_list->Append(dict); 5302 } 5303 DictionaryValue dict; 5304 dict.Set("views", view_list); 5305 AutomationJSONReply(this, reply_message).SendSuccess(&dict); 5306 } 5307 5308 void TestingAutomationProvider::IsTabIdValid( 5309 DictionaryValue* args, IPC::Message* reply_message) { 5310 AutomationJSONReply reply(this, reply_message); 5311 int id; 5312 if (!args->GetInteger("id", &id)) { 5313 reply.SendError("'id' missing or invalid"); 5314 return; 5315 } 5316 bool is_valid = false; 5317 for (chrome::BrowserIterator it; !it.done(); it.Next()) { 5318 Browser* browser = *it; 5319 for (int i = 0; i < browser->tab_strip_model()->count(); ++i) { 5320 WebContents* tab = browser->tab_strip_model()->GetWebContentsAt(i); 5321 SessionTabHelper* session_tab_helper = 5322 SessionTabHelper::FromWebContents(tab); 5323 if (session_tab_helper->session_id().id() == id) { 5324 is_valid = true; 5325 break; 5326 } 5327 } 5328 } 5329 DictionaryValue dict; 5330 dict.SetBoolean("is_valid", is_valid); 5331 reply.SendSuccess(&dict); 5332 } 5333 5334 void TestingAutomationProvider::DoesAutomationObjectExist( 5335 DictionaryValue* args, IPC::Message* reply_message) { 5336 AutomationJSONReply reply(this, reply_message); 5337 AutomationId id; 5338 std::string error_msg; 5339 if (!GetAutomationIdFromJSONArgs(args, "auto_id", &id, &error_msg)) { 5340 reply.SendError(error_msg); 5341 return; 5342 } 5343 DictionaryValue dict; 5344 dict.SetBoolean( 5345 "does_exist", 5346 automation_util::DoesObjectWithIdExist(id, profile())); 5347 reply.SendSuccess(&dict); 5348 } 5349 5350 void TestingAutomationProvider::CloseTabJSON( 5351 DictionaryValue* args, IPC::Message* reply_message) { 5352 Browser* browser; 5353 WebContents* tab; 5354 std::string error; 5355 bool wait_until_closed = false; // ChromeDriver does not use this. 5356 args->GetBoolean("wait_until_closed", &wait_until_closed); 5357 // Close tabs synchronously. 5358 if (GetBrowserAndTabFromJSONArgs(args, &browser, &tab, &error)) { 5359 if (wait_until_closed) { 5360 new TabClosedNotificationObserver(this, wait_until_closed, reply_message, 5361 true); 5362 } 5363 chrome::CloseWebContents(browser, tab, false); 5364 if (!wait_until_closed) 5365 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 5366 return; 5367 } 5368 // Close other types of views asynchronously. 5369 RenderViewHost* view; 5370 if (!GetRenderViewFromJSONArgs(args, profile(), &view, &error)) { 5371 AutomationJSONReply(this, reply_message).SendError(error); 5372 return; 5373 } 5374 view->ClosePage(); 5375 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 5376 } 5377 5378 void TestingAutomationProvider::SetViewBounds( 5379 base::DictionaryValue* args, 5380 IPC::Message* reply_message) { 5381 AutomationJSONReply reply(this, reply_message); 5382 int x, y, width, height; 5383 if (!args->GetInteger("bounds.x", &x) || 5384 !args->GetInteger("bounds.y", &y) || 5385 !args->GetInteger("bounds.width", &width) || 5386 !args->GetInteger("bounds.height", &height)) { 5387 reply.SendError("Missing or invalid 'bounds'"); 5388 return; 5389 } 5390 Browser* browser; 5391 std::string error; 5392 if (!GetBrowserFromJSONArgs(args, &browser, &error)) { 5393 reply.SendError(Error(automation::kInvalidId, error)); 5394 return; 5395 } 5396 BrowserWindow* browser_window = browser->window(); 5397 if (browser_window->IsMaximized()) { 5398 browser_window->Restore(); 5399 } 5400 browser_window->SetBounds(gfx::Rect(x, y, width, height)); 5401 reply.SendSuccess(NULL); 5402 } 5403 5404 void TestingAutomationProvider::MaximizeView( 5405 base::DictionaryValue* args, 5406 IPC::Message* reply_message) { 5407 Browser* browser; 5408 std::string error; 5409 if (!GetBrowserFromJSONArgs(args, &browser, &error)) { 5410 AutomationJSONReply(this, reply_message) 5411 .SendError(Error(automation::kInvalidId, error)); 5412 return; 5413 } 5414 5415 #if defined(OS_LINUX) 5416 // Maximization on Linux is asynchronous, so create an observer object to be 5417 // notified upon maximization completion. 5418 new WindowMaximizedObserver(this, reply_message); 5419 #endif // defined(OS_LINUX) 5420 5421 browser->window()->Maximize(); 5422 5423 #if !defined(OS_LINUX) 5424 // Send success reply right away for OS's with synchronous maximize command. 5425 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 5426 #endif // !defined(OS_LINUX) 5427 } 5428 5429 void TestingAutomationProvider::ActivateTabJSON( 5430 DictionaryValue* args, 5431 IPC::Message* reply_message) { 5432 if (SendErrorIfModalDialogActive(this, reply_message)) 5433 return; 5434 5435 AutomationJSONReply reply(this, reply_message); 5436 Browser* browser; 5437 WebContents* web_contents; 5438 std::string error; 5439 if (!GetBrowserAndTabFromJSONArgs(args, &browser, &web_contents, &error)) { 5440 reply.SendError(error); 5441 return; 5442 } 5443 TabStripModel* tab_strip = browser->tab_strip_model(); 5444 tab_strip->ActivateTabAt(tab_strip->GetIndexOfWebContents(web_contents), 5445 true); 5446 reply.SendSuccess(NULL); 5447 } 5448 5449 void TestingAutomationProvider::IsPageActionVisible( 5450 base::DictionaryValue* args, 5451 IPC::Message* reply_message) { 5452 AutomationJSONReply reply(this, reply_message); 5453 5454 WebContents* tab; 5455 std::string error; 5456 if (!GetTabFromJSONArgs(args, &tab, &error)) { 5457 reply.SendError(error); 5458 return; 5459 } 5460 Browser* browser = automation_util::GetBrowserForTab(tab); 5461 const Extension* extension; 5462 if (!GetEnabledExtensionFromJSONArgs( 5463 args, "extension_id", browser->profile(), &extension, &error)) { 5464 reply.SendError(error); 5465 return; 5466 } 5467 if (!browser) { 5468 reply.SendError("Tab does not belong to an open browser"); 5469 return; 5470 } 5471 ExtensionAction* page_action = 5472 ExtensionActionManager::Get(browser->profile())-> 5473 GetPageAction(*extension); 5474 if (!page_action) { 5475 reply.SendError("Extension doesn't have any page action"); 5476 return; 5477 } 5478 EnsureTabSelected(browser, tab); 5479 5480 bool is_visible = false; 5481 LocationBarTesting* loc_bar = 5482 browser->window()->GetLocationBar()->GetLocationBarForTesting(); 5483 size_t page_action_visible_count = 5484 static_cast<size_t>(loc_bar->PageActionVisibleCount()); 5485 for (size_t i = 0; i < page_action_visible_count; ++i) { 5486 if (loc_bar->GetVisiblePageAction(i) == page_action) { 5487 is_visible = true; 5488 break; 5489 } 5490 } 5491 DictionaryValue dict; 5492 dict.SetBoolean("is_visible", is_visible); 5493 reply.SendSuccess(&dict); 5494 } 5495 5496 void TestingAutomationProvider::GetChromeDriverAutomationVersion( 5497 DictionaryValue* args, 5498 IPC::Message* reply_message) { 5499 DictionaryValue reply_dict; 5500 reply_dict.SetInteger("version", automation::kChromeDriverAutomationVersion); 5501 AutomationJSONReply(this, reply_message).SendSuccess(&reply_dict); 5502 } 5503 5504 void TestingAutomationProvider::CreateNewAutomationProvider( 5505 DictionaryValue* args, 5506 IPC::Message* reply_message) { 5507 AutomationJSONReply reply(this, reply_message); 5508 std::string channel_id; 5509 if (!args->GetString("channel_id", &channel_id)) { 5510 reply.SendError("'channel_id' missing or invalid"); 5511 return; 5512 } 5513 5514 AutomationProvider* provider = new TestingAutomationProvider(profile_); 5515 provider->DisableInitialLoadObservers(); 5516 // TODO(kkania): Remove this when crbug.com/91311 is fixed. 5517 // Named server channels should ideally be created and closed on the file 5518 // thread, within the IPC channel code. 5519 base::ThreadRestrictions::ScopedAllowIO allow_io; 5520 if (!provider->InitializeChannel( 5521 automation::kNamedInterfacePrefix + channel_id)) { 5522 reply.SendError("Failed to initialize channel: " + channel_id); 5523 return; 5524 } 5525 DCHECK(g_browser_process); 5526 g_browser_process->GetAutomationProviderList()->AddProvider(provider); 5527 reply.SendSuccess(NULL); 5528 } 5529 5530 void TestingAutomationProvider::WaitForTabCountToBecome( 5531 int browser_handle, 5532 int target_tab_count, 5533 IPC::Message* reply_message) { 5534 if (!browser_tracker_->ContainsHandle(browser_handle)) { 5535 AutomationMsg_WaitForTabCountToBecome::WriteReplyParams(reply_message, 5536 false); 5537 Send(reply_message); 5538 return; 5539 } 5540 5541 Browser* browser = browser_tracker_->GetResource(browser_handle); 5542 5543 // The observer will delete itself. 5544 new TabCountChangeObserver(this, browser, reply_message, target_tab_count); 5545 } 5546 5547 void TestingAutomationProvider::WaitForInfoBarCount( 5548 int tab_handle, 5549 size_t target_count, 5550 IPC::Message* reply_message) { 5551 if (!tab_tracker_->ContainsHandle(tab_handle)) { 5552 AutomationMsg_WaitForInfoBarCount::WriteReplyParams(reply_message_, false); 5553 Send(reply_message_); 5554 return; 5555 } 5556 5557 NavigationController* controller = tab_tracker_->GetResource(tab_handle); 5558 if (!controller) { 5559 AutomationMsg_WaitForInfoBarCount::WriteReplyParams(reply_message_, false); 5560 Send(reply_message_); 5561 return; 5562 } 5563 5564 // The delegate will delete itself. 5565 new InfoBarCountObserver(this, reply_message, 5566 controller->GetWebContents(), target_count); 5567 } 5568 5569 void TestingAutomationProvider::WaitForProcessLauncherThreadToGoIdle( 5570 IPC::Message* reply_message) { 5571 new WaitForProcessLauncherThreadToGoIdleObserver(this, reply_message); 5572 } 5573 5574 void TestingAutomationProvider::OnRemoveProvider() { 5575 if (g_browser_process) 5576 g_browser_process->GetAutomationProviderList()->RemoveProvider(this); 5577 } 5578 5579 void TestingAutomationProvider::EnsureTabSelected(Browser* browser, 5580 WebContents* tab) { 5581 TabStripModel* tab_strip = browser->tab_strip_model(); 5582 if (tab_strip->GetActiveWebContents() != tab) 5583 tab_strip->ActivateTabAt(tab_strip->GetIndexOfWebContents(tab), true); 5584 } 5585