automation_provider.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1// Copyright (c) 2010 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/automation_provider.h" 6 7#include <set> 8 9#include "app/l10n_util.h" 10#include "app/message_box_flags.h" 11#include "base/callback.h" 12#include "base/file_path.h" 13#include "base/file_version_info.h" 14#include "base/json/json_reader.h" 15#include "base/json/json_writer.h" 16#include "base/json/string_escape.h" 17#include "base/keyboard_codes.h" 18#include "base/message_loop.h" 19#include "base/path_service.h" 20#include "base/process_util.h" 21#include "base/stl_util-inl.h" 22#include "base/string_util.h" 23#include "base/task.h" 24#include "base/thread.h" 25#include "base/utf_string_conversions.h" 26#include "base/values.h" 27#include "base/waitable_event.h" 28#include "chrome/app/chrome_dll_resource.h" 29#include "chrome/browser/app_modal_dialog.h" 30#include "chrome/browser/app_modal_dialog_queue.h" 31#include "chrome/browser/autofill/autofill_manager.h" 32#include "chrome/browser/automation/automation_autocomplete_edit_tracker.h" 33#include "chrome/browser/automation/automation_browser_tracker.h" 34#include "chrome/browser/automation/automation_extension_tracker.h" 35#include "chrome/browser/automation/automation_provider_json.h" 36#include "chrome/browser/automation/automation_provider_list.h" 37#include "chrome/browser/automation/automation_provider_observers.h" 38#include "chrome/browser/automation/automation_resource_message_filter.h" 39#include "chrome/browser/automation/automation_tab_tracker.h" 40#include "chrome/browser/automation/automation_window_tracker.h" 41#include "chrome/browser/automation/extension_port_container.h" 42#include "chrome/browser/autocomplete/autocomplete_edit.h" 43#include "chrome/browser/blocked_popup_container.h" 44#include "chrome/browser/bookmarks/bookmark_model.h" 45#include "chrome/browser/bookmarks/bookmark_storage.h" 46#include "chrome/browser/browser_list.h" 47#include "chrome/browser/browser_process.h" 48#include "chrome/browser/browser_window.h" 49#include "chrome/browser/browsing_data_remover.h" 50#include "chrome/browser/character_encoding.h" 51#include "chrome/browser/chrome_thread.h" 52#include "chrome/browser/dom_operation_notification_details.h" 53#include "chrome/browser/debugger/devtools_manager.h" 54#include "chrome/browser/download/download_item.h" 55#include "chrome/browser/download/download_shelf.h" 56#include "chrome/browser/download/save_package.h" 57#include "chrome/browser/extensions/crx_installer.h" 58#include "chrome/browser/extensions/extension_browser_event_router.h" 59#include "chrome/browser/extensions/extension_host.h" 60#include "chrome/browser/extensions/extension_install_ui.h" 61#include "chrome/browser/extensions/extension_message_service.h" 62#include "chrome/browser/extensions/extension_tabs_module.h" 63#include "chrome/browser/extensions/extension_toolbar_model.h" 64#include "chrome/browser/extensions/extensions_service.h" 65#include "chrome/browser/extensions/user_script_master.h" 66#include "chrome/browser/find_bar.h" 67#include "chrome/browser/find_bar_controller.h" 68#include "chrome/browser/find_notification_details.h" 69#include "chrome/browser/host_content_settings_map.h" 70#include "chrome/browser/importer/importer.h" 71#include "chrome/browser/importer/importer_data_types.h" 72#include "chrome/browser/io_thread.h" 73#include "chrome/browser/location_bar.h" 74#include "chrome/browser/login_prompt.h" 75#include "chrome/browser/net/url_request_mock_util.h" 76#include "chrome/browser/platform_util.h" 77#include "chrome/browser/pref_service.h" 78#include "chrome/browser/printing/print_job.h" 79#include "chrome/browser/profile_manager.h" 80#include "chrome/browser/renderer_host/render_process_host.h" 81#include "chrome/browser/renderer_host/render_view_host.h" 82#include "chrome/browser/ssl/ssl_manager.h" 83#include "chrome/browser/ssl/ssl_blocking_page.h" 84#include "chrome/browser/tab_contents/infobar_delegate.h" 85#include "chrome/browser/tab_contents/tab_contents.h" 86#include "chrome/browser/tab_contents/tab_contents_view.h" 87#include "chrome/browser/translate/translate_infobar_delegate.h" 88#include "chrome/common/automation_constants.h" 89#include "chrome/common/chrome_constants.h" 90#include "chrome/common/chrome_paths.h" 91#include "chrome/common/chrome_switches.h" 92#include "chrome/common/chrome_version_info.h" 93#include "chrome/common/extensions/extension.h" 94#include "chrome/common/json_value_serializer.h" 95#include "chrome/common/net/url_request_context_getter.h" 96#include "chrome/common/notification_service.h" 97#include "chrome/common/pref_names.h" 98#include "chrome/common/url_constants.h" 99#include "chrome/test/automation/automation_messages.h" 100#include "chrome/test/automation/tab_proxy.h" 101#include "net/proxy/proxy_service.h" 102#include "net/proxy/proxy_config_service_fixed.h" 103#include "net/url_request/url_request_context.h" 104#include "chrome/browser/automation/ui_controls.h" 105#include "views/event.h" 106#include "webkit/glue/password_form.h" 107#include "webkit/glue/plugins/plugin_list.h" 108 109#if defined(OS_WIN) 110#include "chrome/browser/external_tab_container_win.h" 111#endif // defined(OS_WIN) 112 113using base::Time; 114 115class AutomationInterstitialPage : public InterstitialPage { 116 public: 117 AutomationInterstitialPage(TabContents* tab, 118 const GURL& url, 119 const std::string& contents) 120 : InterstitialPage(tab, true, url), 121 contents_(contents) { 122 } 123 124 virtual std::string GetHTMLContents() { return contents_; } 125 126 private: 127 std::string contents_; 128 129 DISALLOW_COPY_AND_ASSIGN(AutomationInterstitialPage); 130}; 131 132class ClickTask : public Task { 133 public: 134 explicit ClickTask(int flags) : flags_(flags) {} 135 virtual ~ClickTask() {} 136 137 virtual void Run() { 138 ui_controls::MouseButton button = ui_controls::LEFT; 139 if ((flags_ & views::Event::EF_LEFT_BUTTON_DOWN) == 140 views::Event::EF_LEFT_BUTTON_DOWN) { 141 button = ui_controls::LEFT; 142 } else if ((flags_ & views::Event::EF_RIGHT_BUTTON_DOWN) == 143 views::Event::EF_RIGHT_BUTTON_DOWN) { 144 button = ui_controls::RIGHT; 145 } else if ((flags_ & views::Event::EF_MIDDLE_BUTTON_DOWN) == 146 views::Event::EF_MIDDLE_BUTTON_DOWN) { 147 button = ui_controls::MIDDLE; 148 } else { 149 NOTREACHED(); 150 } 151 152 ui_controls::SendMouseClick(button); 153 } 154 155 private: 156 int flags_; 157 158 DISALLOW_COPY_AND_ASSIGN(ClickTask); 159}; 160 161AutomationProvider::AutomationProvider(Profile* profile) 162 : redirect_query_(0), 163 profile_(profile), 164 reply_message_(NULL), 165 popup_menu_waiter_(NULL) { 166 browser_tracker_.reset(new AutomationBrowserTracker(this)); 167 extension_tracker_.reset(new AutomationExtensionTracker(this)); 168 tab_tracker_.reset(new AutomationTabTracker(this)); 169 window_tracker_.reset(new AutomationWindowTracker(this)); 170 autocomplete_edit_tracker_.reset( 171 new AutomationAutocompleteEditTracker(this)); 172 new_tab_ui_load_observer_.reset(new NewTabUILoadObserver(this)); 173 dom_operation_observer_.reset(new DomOperationNotificationObserver(this)); 174 metric_event_duration_observer_.reset(new MetricEventDurationObserver()); 175 extension_test_result_observer_.reset( 176 new ExtensionTestResultNotificationObserver(this)); 177 g_browser_process->AddRefModule(); 178} 179 180AutomationProvider::~AutomationProvider() { 181 STLDeleteContainerPairSecondPointers(port_containers_.begin(), 182 port_containers_.end()); 183 port_containers_.clear(); 184 185 // Make sure that any outstanding NotificationObservers also get destroyed. 186 ObserverList<NotificationObserver>::Iterator it(notification_observer_list_); 187 NotificationObserver* observer; 188 while ((observer = it.GetNext()) != NULL) 189 delete observer; 190 191 if (channel_.get()) { 192 channel_->Close(); 193 } 194 g_browser_process->ReleaseModule(); 195} 196 197void AutomationProvider::ConnectToChannel(const std::string& channel_id) { 198 automation_resource_message_filter_ = new AutomationResourceMessageFilter; 199 channel_.reset( 200 new IPC::SyncChannel(channel_id, IPC::Channel::MODE_CLIENT, this, 201 automation_resource_message_filter_, 202 g_browser_process->io_thread()->message_loop(), 203 true, g_browser_process->shutdown_event())); 204 scoped_ptr<FileVersionInfo> version_info(chrome::GetChromeVersionInfo()); 205 std::string version_string; 206 if (version_info != NULL) { 207 version_string = WideToASCII(version_info->file_version()); 208 } 209 210 // Send a hello message with our current automation protocol version. 211 channel_->Send(new AutomationMsg_Hello(0, version_string.c_str())); 212} 213 214void AutomationProvider::SetExpectedTabCount(size_t expected_tabs) { 215 if (expected_tabs == 0) { 216 Send(new AutomationMsg_InitialLoadsComplete(0)); 217 } else { 218 initial_load_observer_.reset(new InitialLoadObserver(expected_tabs, this)); 219 } 220} 221 222NotificationObserver* AutomationProvider::AddNavigationStatusListener( 223 NavigationController* tab, IPC::Message* reply_message, 224 int number_of_navigations, bool include_current_navigation) { 225 NotificationObserver* observer = 226 new NavigationNotificationObserver(tab, this, reply_message, 227 number_of_navigations, 228 include_current_navigation); 229 230 notification_observer_list_.AddObserver(observer); 231 return observer; 232} 233 234void AutomationProvider::RemoveNavigationStatusListener( 235 NotificationObserver* obs) { 236 notification_observer_list_.RemoveObserver(obs); 237} 238 239NotificationObserver* AutomationProvider::AddTabStripObserver( 240 Browser* parent, 241 IPC::Message* reply_message) { 242 NotificationObserver* observer = 243 new TabAppendedNotificationObserver(parent, this, reply_message); 244 notification_observer_list_.AddObserver(observer); 245 246 return observer; 247} 248 249void AutomationProvider::RemoveTabStripObserver(NotificationObserver* obs) { 250 notification_observer_list_.RemoveObserver(obs); 251} 252 253void AutomationProvider::AddLoginHandler(NavigationController* tab, 254 LoginHandler* handler) { 255 login_handler_map_[tab] = handler; 256} 257 258void AutomationProvider::RemoveLoginHandler(NavigationController* tab) { 259 DCHECK(login_handler_map_[tab]); 260 login_handler_map_.erase(tab); 261} 262 263void AutomationProvider::AddPortContainer(ExtensionPortContainer* port) { 264 int port_id = port->port_id(); 265 DCHECK_NE(-1, port_id); 266 DCHECK(port_containers_.find(port_id) == port_containers_.end()); 267 268 port_containers_[port_id] = port; 269} 270 271void AutomationProvider::RemovePortContainer(ExtensionPortContainer* port) { 272 int port_id = port->port_id(); 273 DCHECK_NE(-1, port_id); 274 275 PortContainerMap::iterator it = port_containers_.find(port_id); 276 DCHECK(it != port_containers_.end()); 277 278 if (it != port_containers_.end()) { 279 delete it->second; 280 port_containers_.erase(it); 281 } 282} 283 284ExtensionPortContainer* AutomationProvider::GetPortContainer( 285 int port_id) const { 286 PortContainerMap::const_iterator it = port_containers_.find(port_id); 287 if (it == port_containers_.end()) 288 return NULL; 289 290 return it->second; 291} 292 293int AutomationProvider::GetIndexForNavigationController( 294 const NavigationController* controller, const Browser* parent) const { 295 DCHECK(parent); 296 return parent->GetIndexOfController(controller); 297} 298 299int AutomationProvider::AddExtension(Extension* extension) { 300 DCHECK(extension); 301 return extension_tracker_->Add(extension); 302} 303 304Extension* AutomationProvider::GetExtension(int extension_handle) { 305 return extension_tracker_->GetResource(extension_handle); 306} 307 308Extension* AutomationProvider::GetEnabledExtension(int extension_handle) { 309 Extension* extension = extension_tracker_->GetResource(extension_handle); 310 ExtensionsService* service = profile_->GetExtensionsService(); 311 if (extension && service && 312 service->GetExtensionById(extension->id(), false)) 313 return extension; 314 return NULL; 315} 316 317Extension* AutomationProvider::GetDisabledExtension(int extension_handle) { 318 Extension* extension = extension_tracker_->GetResource(extension_handle); 319 ExtensionsService* service = profile_->GetExtensionsService(); 320 if (extension && service && 321 service->GetExtensionById(extension->id(), true) && 322 !service->GetExtensionById(extension->id(), false)) 323 return extension; 324 return NULL; 325} 326 327void AutomationProvider::OnMessageReceived(const IPC::Message& message) { 328 IPC_BEGIN_MESSAGE_MAP(AutomationProvider, message) 329 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_CloseBrowser, CloseBrowser) 330 IPC_MESSAGE_HANDLER(AutomationMsg_CloseBrowserRequestAsync, 331 CloseBrowserAsync) 332 IPC_MESSAGE_HANDLER(AutomationMsg_ActivateTab, ActivateTab) 333 IPC_MESSAGE_HANDLER(AutomationMsg_ActiveTabIndex, GetActiveTabIndex) 334 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_AppendTab, AppendTab) 335 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_CloseTab, CloseTab) 336 IPC_MESSAGE_HANDLER(AutomationMsg_GetCookies, GetCookies) 337 IPC_MESSAGE_HANDLER(AutomationMsg_SetCookie, SetCookie) 338 IPC_MESSAGE_HANDLER(AutomationMsg_DeleteCookie, DeleteCookie) 339 IPC_MESSAGE_HANDLER(AutomationMsg_ShowCollectedCookiesDialog, 340 ShowCollectedCookiesDialog) 341 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_NavigateToURL, NavigateToURL) 342 IPC_MESSAGE_HANDLER_DELAY_REPLY( 343 AutomationMsg_NavigateToURLBlockUntilNavigationsComplete, 344 NavigateToURLBlockUntilNavigationsComplete) 345 IPC_MESSAGE_HANDLER(AutomationMsg_NavigationAsync, NavigationAsync) 346 IPC_MESSAGE_HANDLER(AutomationMsg_NavigationAsyncWithDisposition, 347 NavigationAsyncWithDisposition) 348 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_GoBack, GoBack) 349 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_GoForward, GoForward) 350 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_Reload, Reload) 351 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_SetAuth, SetAuth) 352 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_CancelAuth, CancelAuth) 353 IPC_MESSAGE_HANDLER(AutomationMsg_NeedsAuth, NeedsAuth) 354 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_RedirectsFrom, 355 GetRedirectsFrom) 356 IPC_MESSAGE_HANDLER(AutomationMsg_BrowserWindowCount, GetBrowserWindowCount) 357 IPC_MESSAGE_HANDLER(AutomationMsg_NormalBrowserWindowCount, 358 GetNormalBrowserWindowCount) 359 IPC_MESSAGE_HANDLER(AutomationMsg_BrowserWindow, GetBrowserWindow) 360 IPC_MESSAGE_HANDLER(AutomationMsg_GetBrowserLocale, GetBrowserLocale) 361 IPC_MESSAGE_HANDLER(AutomationMsg_LastActiveBrowserWindow, 362 GetLastActiveBrowserWindow) 363 IPC_MESSAGE_HANDLER(AutomationMsg_ActiveWindow, GetActiveWindow) 364 IPC_MESSAGE_HANDLER(AutomationMsg_FindNormalBrowserWindow, 365 FindNormalBrowserWindow) 366 IPC_MESSAGE_HANDLER(AutomationMsg_IsWindowActive, IsWindowActive) 367 IPC_MESSAGE_HANDLER(AutomationMsg_ActivateWindow, ActivateWindow) 368 IPC_MESSAGE_HANDLER(AutomationMsg_IsWindowMaximized, IsWindowMaximized) 369 IPC_MESSAGE_HANDLER(AutomationMsg_WindowExecuteCommandAsync, 370 ExecuteBrowserCommandAsync) 371 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WindowExecuteCommand, 372 ExecuteBrowserCommand) 373 IPC_MESSAGE_HANDLER(AutomationMsg_TerminateSession, TerminateSession) 374 IPC_MESSAGE_HANDLER(AutomationMsg_WindowViewBounds, WindowGetViewBounds) 375 IPC_MESSAGE_HANDLER(AutomationMsg_GetWindowBounds, GetWindowBounds) 376 IPC_MESSAGE_HANDLER(AutomationMsg_SetWindowBounds, SetWindowBounds) 377 IPC_MESSAGE_HANDLER(AutomationMsg_SetWindowVisible, SetWindowVisible) 378 IPC_MESSAGE_HANDLER(AutomationMsg_WindowClick, WindowSimulateClick) 379 IPC_MESSAGE_HANDLER(AutomationMsg_WindowMouseMove, WindowSimulateMouseMove) 380 IPC_MESSAGE_HANDLER(AutomationMsg_WindowKeyPress, WindowSimulateKeyPress) 381#if !defined(OS_MACOSX) 382 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WindowDrag, 383 WindowSimulateDrag) 384#endif // !defined(OS_MACOSX) 385 IPC_MESSAGE_HANDLER(AutomationMsg_TabCount, GetTabCount) 386 IPC_MESSAGE_HANDLER(AutomationMsg_Type, GetType) 387 IPC_MESSAGE_HANDLER(AutomationMsg_Tab, GetTab) 388#if defined(OS_WIN) 389 IPC_MESSAGE_HANDLER(AutomationMsg_TabHWND, GetTabHWND) 390#endif // defined(OS_WIN) 391 IPC_MESSAGE_HANDLER(AutomationMsg_TabProcessID, GetTabProcessID) 392 IPC_MESSAGE_HANDLER(AutomationMsg_TabTitle, GetTabTitle) 393 IPC_MESSAGE_HANDLER(AutomationMsg_TabIndex, GetTabIndex) 394 IPC_MESSAGE_HANDLER(AutomationMsg_TabURL, GetTabURL) 395 IPC_MESSAGE_HANDLER(AutomationMsg_ShelfVisibility, GetShelfVisibility) 396 IPC_MESSAGE_HANDLER(AutomationMsg_IsFullscreen, IsFullscreen) 397 IPC_MESSAGE_HANDLER(AutomationMsg_IsFullscreenBubbleVisible, 398 GetFullscreenBubbleVisibility) 399 IPC_MESSAGE_HANDLER(AutomationMsg_HandleUnused, HandleUnused) 400 IPC_MESSAGE_HANDLER(AutomationMsg_ApplyAccelerator, ApplyAccelerator) 401 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_DomOperation, 402 ExecuteJavascript) 403 IPC_MESSAGE_HANDLER(AutomationMsg_ConstrainedWindowCount, 404 GetConstrainedWindowCount) 405 IPC_MESSAGE_HANDLER(AutomationMsg_FindInPage, HandleFindInPageRequest) 406 IPC_MESSAGE_HANDLER(AutomationMsg_GetFocusedViewID, GetFocusedViewID) 407 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_InspectElement, 408 HandleInspectElementRequest) 409 IPC_MESSAGE_HANDLER(AutomationMsg_DownloadDirectory, GetDownloadDirectory) 410 IPC_MESSAGE_HANDLER(AutomationMsg_SetProxyConfig, SetProxyConfig); 411 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_OpenNewBrowserWindow, 412 OpenNewBrowserWindow) 413 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_OpenNewBrowserWindowOfType, 414 OpenNewBrowserWindowOfType) 415 IPC_MESSAGE_HANDLER(AutomationMsg_WindowForBrowser, GetWindowForBrowser) 416 IPC_MESSAGE_HANDLER(AutomationMsg_AutocompleteEditForBrowser, 417 GetAutocompleteEditForBrowser) 418 IPC_MESSAGE_HANDLER(AutomationMsg_BrowserForWindow, GetBrowserForWindow) 419 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_ShowInterstitialPage, 420 ShowInterstitialPage) 421 IPC_MESSAGE_HANDLER(AutomationMsg_HideInterstitialPage, 422 HideInterstitialPage) 423 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForTabToBeRestored, 424 WaitForTabToBeRestored) 425 IPC_MESSAGE_HANDLER(AutomationMsg_GetSecurityState, GetSecurityState) 426 IPC_MESSAGE_HANDLER(AutomationMsg_GetPageType, GetPageType) 427 IPC_MESSAGE_HANDLER(AutomationMsg_GetMetricEventDuration, 428 GetMetricEventDuration) 429 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_ActionOnSSLBlockingPage, 430 ActionOnSSLBlockingPage) 431 IPC_MESSAGE_HANDLER(AutomationMsg_BringBrowserToFront, BringBrowserToFront) 432 IPC_MESSAGE_HANDLER(AutomationMsg_IsMenuCommandEnabled, 433 IsMenuCommandEnabled) 434 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_PrintNow, PrintNow) 435 IPC_MESSAGE_HANDLER(AutomationMsg_PrintAsync, PrintAsync) 436 IPC_MESSAGE_HANDLER(AutomationMsg_SavePage, SavePage) 437 IPC_MESSAGE_HANDLER(AutomationMsg_AutocompleteEditGetText, 438 GetAutocompleteEditText) 439 IPC_MESSAGE_HANDLER(AutomationMsg_AutocompleteEditSetText, 440 SetAutocompleteEditText) 441 IPC_MESSAGE_HANDLER(AutomationMsg_AutocompleteEditIsQueryInProgress, 442 AutocompleteEditIsQueryInProgress) 443 IPC_MESSAGE_HANDLER(AutomationMsg_AutocompleteEditGetMatches, 444 AutocompleteEditGetMatches) 445 IPC_MESSAGE_HANDLER(AutomationMsg_OpenFindInPage, 446 HandleOpenFindInPageRequest) 447 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_Find, HandleFindRequest) 448 IPC_MESSAGE_HANDLER(AutomationMsg_FindWindowVisibility, 449 GetFindWindowVisibility) 450 IPC_MESSAGE_HANDLER(AutomationMsg_FindWindowLocation, 451 HandleFindWindowLocationRequest) 452 IPC_MESSAGE_HANDLER(AutomationMsg_BookmarkBarVisibility, 453 GetBookmarkBarVisibility) 454 IPC_MESSAGE_HANDLER(AutomationMsg_GetBookmarksAsJSON, 455 GetBookmarksAsJSON) 456 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForBookmarkModelToLoad, 457 WaitForBookmarkModelToLoad) 458 IPC_MESSAGE_HANDLER(AutomationMsg_AddBookmarkGroup, 459 AddBookmarkGroup) 460 IPC_MESSAGE_HANDLER(AutomationMsg_AddBookmarkURL, 461 AddBookmarkURL) 462 IPC_MESSAGE_HANDLER(AutomationMsg_ReparentBookmark, 463 ReparentBookmark) 464 IPC_MESSAGE_HANDLER(AutomationMsg_SetBookmarkTitle, 465 SetBookmarkTitle) 466 IPC_MESSAGE_HANDLER(AutomationMsg_SetBookmarkURL, 467 SetBookmarkURL) 468 IPC_MESSAGE_HANDLER(AutomationMsg_RemoveBookmark, 469 RemoveBookmark) 470 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_SendJSONRequest, 471 SendJSONRequest) 472 IPC_MESSAGE_HANDLER(AutomationMsg_GetInfoBarCount, GetInfoBarCount) 473 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_ClickInfoBarAccept, 474 ClickInfoBarAccept) 475 IPC_MESSAGE_HANDLER(AutomationMsg_GetLastNavigationTime, 476 GetLastNavigationTime) 477 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForNavigation, 478 WaitForNavigation) 479 IPC_MESSAGE_HANDLER(AutomationMsg_SetIntPreference, SetIntPreference) 480 IPC_MESSAGE_HANDLER(AutomationMsg_ShowingAppModalDialog, 481 GetShowingAppModalDialog) 482 IPC_MESSAGE_HANDLER(AutomationMsg_ClickAppModalDialogButton, 483 ClickAppModalDialogButton) 484 IPC_MESSAGE_HANDLER(AutomationMsg_SetStringPreference, SetStringPreference) 485 IPC_MESSAGE_HANDLER(AutomationMsg_GetBooleanPreference, 486 GetBooleanPreference) 487 IPC_MESSAGE_HANDLER(AutomationMsg_SetBooleanPreference, 488 SetBooleanPreference) 489 IPC_MESSAGE_HANDLER(AutomationMsg_GetPageCurrentEncoding, 490 GetPageCurrentEncoding) 491 IPC_MESSAGE_HANDLER(AutomationMsg_OverrideEncoding, OverrideEncoding) 492 IPC_MESSAGE_HANDLER(AutomationMsg_SavePackageShouldPromptUser, 493 SavePackageShouldPromptUser) 494 IPC_MESSAGE_HANDLER(AutomationMsg_WindowTitle, GetWindowTitle) 495 IPC_MESSAGE_HANDLER(AutomationMsg_SetShelfVisibility, SetShelfVisibility) 496 IPC_MESSAGE_HANDLER(AutomationMsg_BlockedPopupCount, GetBlockedPopupCount) 497 IPC_MESSAGE_HANDLER(AutomationMsg_SelectAll, SelectAll) 498 IPC_MESSAGE_HANDLER(AutomationMsg_Cut, Cut) 499 IPC_MESSAGE_HANDLER(AutomationMsg_Copy, Copy) 500 IPC_MESSAGE_HANDLER(AutomationMsg_Paste, Paste) 501 IPC_MESSAGE_HANDLER(AutomationMsg_ReloadAsync, ReloadAsync) 502 IPC_MESSAGE_HANDLER(AutomationMsg_StopAsync, StopAsync) 503 IPC_MESSAGE_HANDLER_DELAY_REPLY( 504 AutomationMsg_WaitForBrowserWindowCountToBecome, 505 WaitForBrowserWindowCountToBecome) 506 IPC_MESSAGE_HANDLER_DELAY_REPLY( 507 AutomationMsg_WaitForAppModalDialogToBeShown, 508 WaitForAppModalDialogToBeShown) 509 IPC_MESSAGE_HANDLER_DELAY_REPLY( 510 AutomationMsg_GoBackBlockUntilNavigationsComplete, 511 GoBackBlockUntilNavigationsComplete) 512 IPC_MESSAGE_HANDLER_DELAY_REPLY( 513 AutomationMsg_GoForwardBlockUntilNavigationsComplete, 514 GoForwardBlockUntilNavigationsComplete) 515 IPC_MESSAGE_HANDLER(AutomationMsg_SetPageFontSize, OnSetPageFontSize) 516 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_InstallExtension, 517 InstallExtension) 518 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_LoadExpandedExtension, 519 LoadExpandedExtension) 520 IPC_MESSAGE_HANDLER(AutomationMsg_GetEnabledExtensions, 521 GetEnabledExtensions) 522 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForExtensionTestResult, 523 WaitForExtensionTestResult) 524 IPC_MESSAGE_HANDLER_DELAY_REPLY( 525 AutomationMsg_InstallExtensionAndGetHandle, 526 InstallExtensionAndGetHandle) 527 IPC_MESSAGE_HANDLER(AutomationMsg_UninstallExtension, 528 UninstallExtension) 529 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_EnableExtension, 530 EnableExtension) 531 IPC_MESSAGE_HANDLER(AutomationMsg_DisableExtension, 532 DisableExtension) 533 IPC_MESSAGE_HANDLER_DELAY_REPLY( 534 AutomationMsg_ExecuteExtensionActionInActiveTabAsync, 535 ExecuteExtensionActionInActiveTabAsync) 536 IPC_MESSAGE_HANDLER(AutomationMsg_MoveExtensionBrowserAction, 537 MoveExtensionBrowserAction) 538 IPC_MESSAGE_HANDLER(AutomationMsg_GetExtensionProperty, 539 GetExtensionProperty) 540 IPC_MESSAGE_HANDLER(AutomationMsg_ShutdownSessionService, 541 ShutdownSessionService) 542 IPC_MESSAGE_HANDLER(AutomationMsg_SaveAsAsync, SaveAsAsync) 543 IPC_MESSAGE_HANDLER(AutomationMsg_SetContentSetting, SetContentSetting) 544 IPC_MESSAGE_HANDLER(AutomationMsg_RemoveBrowsingData, RemoveBrowsingData) 545 IPC_MESSAGE_HANDLER(AutomationMsg_ResetToDefaultTheme, ResetToDefaultTheme) 546#if defined(TOOLKIT_VIEWS) 547 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForFocusedViewIDToChange, 548 WaitForFocusedViewIDToChange) 549 IPC_MESSAGE_HANDLER(AutomationMsg_StartTrackingPopupMenus, 550 StartTrackingPopupMenus) 551 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForPopupMenuToOpen, 552 WaitForPopupMenuToOpen) 553#endif // defined(TOOLKIT_VIEWS) 554#if defined(OS_WIN) 555 // These are for use with external tabs. 556 IPC_MESSAGE_HANDLER(AutomationMsg_CreateExternalTab, CreateExternalTab) 557 IPC_MESSAGE_HANDLER(AutomationMsg_ProcessUnhandledAccelerator, 558 ProcessUnhandledAccelerator) 559 IPC_MESSAGE_HANDLER(AutomationMsg_SetInitialFocus, SetInitialFocus) 560 IPC_MESSAGE_HANDLER(AutomationMsg_TabReposition, OnTabReposition) 561 IPC_MESSAGE_HANDLER(AutomationMsg_ForwardContextMenuCommandToChrome, 562 OnForwardContextMenuCommandToChrome) 563 IPC_MESSAGE_HANDLER(AutomationMsg_NavigateInExternalTab, 564 NavigateInExternalTab) 565 IPC_MESSAGE_HANDLER(AutomationMsg_NavigateExternalTabAtIndex, 566 NavigateExternalTabAtIndex) 567 IPC_MESSAGE_HANDLER(AutomationMsg_ConnectExternalTab, ConnectExternalTab) 568 IPC_MESSAGE_HANDLER(AutomationMsg_SetEnableExtensionAutomation, 569 SetEnableExtensionAutomation) 570 IPC_MESSAGE_HANDLER(AutomationMsg_HandleMessageFromExternalHost, 571 OnMessageFromExternalHost) 572 IPC_MESSAGE_HANDLER(AutomationMsg_BrowserMove, OnBrowserMoved) 573 IPC_MESSAGE_HANDLER(AutomationMsg_RunUnloadHandlers, OnRunUnloadHandlers) 574#endif // defined(OS_WIN) 575#if defined(OS_CHROMEOS) 576 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_LoginWithUserAndPass, 577 LoginWithUserAndPass) 578#endif // defined(OS_CHROMEOS) 579 IPC_END_MESSAGE_MAP() 580} 581 582void AutomationProvider::ActivateTab(int handle, int at_index, int* status) { 583 *status = -1; 584 if (browser_tracker_->ContainsHandle(handle) && at_index > -1) { 585 Browser* browser = browser_tracker_->GetResource(handle); 586 if (at_index >= 0 && at_index < browser->tab_count()) { 587 browser->SelectTabContentsAt(at_index, true); 588 *status = 0; 589 } 590 } 591} 592 593void AutomationProvider::AppendTab(int handle, const GURL& url, 594 IPC::Message* reply_message) { 595 int append_tab_response = -1; // -1 is the error code 596 NotificationObserver* observer = NULL; 597 598 if (browser_tracker_->ContainsHandle(handle)) { 599 Browser* browser = browser_tracker_->GetResource(handle); 600 observer = AddTabStripObserver(browser, reply_message); 601 TabContents* tab_contents = browser->AddTabWithURL( 602 url, GURL(), PageTransition::TYPED, -1, TabStripModel::ADD_SELECTED, 603 NULL, std::string()); 604 if (tab_contents) { 605 append_tab_response = 606 GetIndexForNavigationController(&tab_contents->controller(), browser); 607 } 608 } 609 610 if (append_tab_response < 0) { 611 // The append tab failed. Remove the TabStripObserver 612 if (observer) { 613 RemoveTabStripObserver(observer); 614 delete observer; 615 } 616 617 AutomationMsg_AppendTab::WriteReplyParams(reply_message, 618 append_tab_response); 619 Send(reply_message); 620 } 621} 622 623void AutomationProvider::NavigateToURL(int handle, const GURL& url, 624 IPC::Message* reply_message) { 625 NavigateToURLBlockUntilNavigationsComplete(handle, url, 1, reply_message); 626} 627 628void AutomationProvider::NavigateToURLBlockUntilNavigationsComplete( 629 int handle, const GURL& url, int number_of_navigations, 630 IPC::Message* reply_message) { 631 if (tab_tracker_->ContainsHandle(handle)) { 632 NavigationController* tab = tab_tracker_->GetResource(handle); 633 634 // Simulate what a user would do. Activate the tab and then navigate. 635 // We could allow navigating in a background tab in future. 636 Browser* browser = FindAndActivateTab(tab); 637 638 if (browser) { 639 AddNavigationStatusListener(tab, reply_message, number_of_navigations, 640 false); 641 642 // TODO(darin): avoid conversion to GURL 643 browser->OpenURL(url, GURL(), CURRENT_TAB, PageTransition::TYPED); 644 return; 645 } 646 } 647 648 AutomationMsg_NavigateToURL::WriteReplyParams( 649 reply_message, AUTOMATION_MSG_NAVIGATION_ERROR); 650 Send(reply_message); 651} 652 653void AutomationProvider::NavigationAsync(int handle, 654 const GURL& url, 655 bool* status) { 656 NavigationAsyncWithDisposition(handle, url, CURRENT_TAB, status); 657} 658 659void AutomationProvider::NavigationAsyncWithDisposition( 660 int handle, 661 const GURL& url, 662 WindowOpenDisposition disposition, 663 bool* status) { 664 *status = false; 665 666 if (tab_tracker_->ContainsHandle(handle)) { 667 NavigationController* tab = tab_tracker_->GetResource(handle); 668 669 // Simulate what a user would do. Activate the tab and then navigate. 670 // We could allow navigating in a background tab in future. 671 Browser* browser = FindAndActivateTab(tab); 672 673 if (browser) { 674 // Don't add any listener unless a callback mechanism is desired. 675 // TODO(vibhor): Do this if such a requirement arises in future. 676 browser->OpenURL(url, GURL(), disposition, PageTransition::TYPED); 677 *status = true; 678 } 679 } 680} 681 682void AutomationProvider::GoBack(int handle, IPC::Message* reply_message) { 683 if (tab_tracker_->ContainsHandle(handle)) { 684 NavigationController* tab = tab_tracker_->GetResource(handle); 685 Browser* browser = FindAndActivateTab(tab); 686 if (browser && browser->command_updater()->IsCommandEnabled(IDC_BACK)) { 687 AddNavigationStatusListener(tab, reply_message, 1, false); 688 browser->GoBack(CURRENT_TAB); 689 return; 690 } 691 } 692 693 AutomationMsg_GoBack::WriteReplyParams( 694 reply_message, AUTOMATION_MSG_NAVIGATION_ERROR); 695 Send(reply_message); 696} 697 698void AutomationProvider::GoForward(int handle, IPC::Message* reply_message) { 699 if (tab_tracker_->ContainsHandle(handle)) { 700 NavigationController* tab = tab_tracker_->GetResource(handle); 701 Browser* browser = FindAndActivateTab(tab); 702 if (browser && browser->command_updater()->IsCommandEnabled(IDC_FORWARD)) { 703 AddNavigationStatusListener(tab, reply_message, 1, false); 704 browser->GoForward(CURRENT_TAB); 705 return; 706 } 707 } 708 709 AutomationMsg_GoForward::WriteReplyParams( 710 reply_message, AUTOMATION_MSG_NAVIGATION_ERROR); 711 Send(reply_message); 712} 713 714void AutomationProvider::Reload(int handle, IPC::Message* reply_message) { 715 if (tab_tracker_->ContainsHandle(handle)) { 716 NavigationController* tab = tab_tracker_->GetResource(handle); 717 Browser* browser = FindAndActivateTab(tab); 718 if (browser && browser->command_updater()->IsCommandEnabled(IDC_RELOAD)) { 719 AddNavigationStatusListener(tab, reply_message, 1, false); 720 browser->Reload(CURRENT_TAB); 721 return; 722 } 723 } 724 725 AutomationMsg_Reload::WriteReplyParams( 726 reply_message, AUTOMATION_MSG_NAVIGATION_ERROR); 727 Send(reply_message); 728} 729 730void AutomationProvider::SetAuth(int tab_handle, 731 const std::wstring& username, 732 const std::wstring& password, 733 IPC::Message* reply_message) { 734 if (tab_tracker_->ContainsHandle(tab_handle)) { 735 NavigationController* tab = tab_tracker_->GetResource(tab_handle); 736 LoginHandlerMap::iterator iter = login_handler_map_.find(tab); 737 738 if (iter != login_handler_map_.end()) { 739 // If auth is needed again after this, assume login has failed. This is 740 // not strictly correct, because a navigation can require both proxy and 741 // server auth, but it should be OK for now. 742 LoginHandler* handler = iter->second; 743 AddNavigationStatusListener(tab, reply_message, 1, false); 744 handler->SetAuth(username, password); 745 return; 746 } 747 } 748 749 AutomationMsg_SetAuth::WriteReplyParams( 750 reply_message, AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED); 751 Send(reply_message); 752} 753 754void AutomationProvider::CancelAuth(int tab_handle, 755 IPC::Message* reply_message) { 756 if (tab_tracker_->ContainsHandle(tab_handle)) { 757 NavigationController* tab = tab_tracker_->GetResource(tab_handle); 758 LoginHandlerMap::iterator iter = login_handler_map_.find(tab); 759 760 if (iter != login_handler_map_.end()) { 761 // If auth is needed again after this, something is screwy. 762 LoginHandler* handler = iter->second; 763 AddNavigationStatusListener(tab, reply_message, 1, false); 764 handler->CancelAuth(); 765 return; 766 } 767 } 768 769 AutomationMsg_CancelAuth::WriteReplyParams( 770 reply_message, AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED); 771 Send(reply_message); 772} 773 774void AutomationProvider::NeedsAuth(int tab_handle, bool* needs_auth) { 775 *needs_auth = false; 776 777 if (tab_tracker_->ContainsHandle(tab_handle)) { 778 NavigationController* tab = tab_tracker_->GetResource(tab_handle); 779 LoginHandlerMap::iterator iter = login_handler_map_.find(tab); 780 781 if (iter != login_handler_map_.end()) { 782 // The LoginHandler will be in our map IFF the tab needs auth. 783 *needs_auth = true; 784 } 785 } 786} 787 788void AutomationProvider::GetRedirectsFrom(int tab_handle, 789 const GURL& source_url, 790 IPC::Message* reply_message) { 791 DCHECK(!redirect_query_) << "Can only handle one redirect query at once."; 792 if (tab_tracker_->ContainsHandle(tab_handle)) { 793 NavigationController* tab = tab_tracker_->GetResource(tab_handle); 794 HistoryService* history_service = 795 tab->profile()->GetHistoryService(Profile::EXPLICIT_ACCESS); 796 797 DCHECK(history_service) << "Tab " << tab_handle << "'s profile " << 798 "has no history service"; 799 if (history_service) { 800 DCHECK(reply_message_ == NULL); 801 reply_message_ = reply_message; 802 // Schedule a history query for redirects. The response will be sent 803 // asynchronously from the callback the history system uses to notify us 804 // that it's done: OnRedirectQueryComplete. 805 redirect_query_ = history_service->QueryRedirectsFrom( 806 source_url, &consumer_, 807 NewCallback(this, &AutomationProvider::OnRedirectQueryComplete)); 808 return; // Response will be sent when query completes. 809 } 810 } 811 812 // Send failure response. 813 std::vector<GURL> empty; 814 AutomationMsg_RedirectsFrom::WriteReplyParams(reply_message, false, empty); 815 Send(reply_message); 816} 817 818void AutomationProvider::GetActiveTabIndex(int handle, int* active_tab_index) { 819 *active_tab_index = -1; // -1 is the error code 820 if (browser_tracker_->ContainsHandle(handle)) { 821 Browser* browser = browser_tracker_->GetResource(handle); 822 *active_tab_index = browser->selected_index(); 823 } 824} 825 826void AutomationProvider::GetBrowserLocale(string16* locale) { 827 DCHECK(g_browser_process); 828 *locale = ASCIIToUTF16(g_browser_process->GetApplicationLocale()); 829} 830 831void AutomationProvider::GetBrowserWindowCount(int* window_count) { 832 *window_count = static_cast<int>(BrowserList::size()); 833} 834 835void AutomationProvider::GetNormalBrowserWindowCount(int* window_count) { 836 *window_count = static_cast<int>( 837 BrowserList::GetBrowserCountForType(profile_, Browser::TYPE_NORMAL)); 838} 839 840void AutomationProvider::GetShowingAppModalDialog(bool* showing_dialog, 841 int* dialog_button) { 842 AppModalDialog* dialog_delegate = 843 Singleton<AppModalDialogQueue>()->active_dialog(); 844 *showing_dialog = (dialog_delegate != NULL); 845 if (*showing_dialog) 846 *dialog_button = dialog_delegate->GetDialogButtons(); 847 else 848 *dialog_button = MessageBoxFlags::DIALOGBUTTON_NONE; 849} 850 851void AutomationProvider::ClickAppModalDialogButton(int button, bool* success) { 852 *success = false; 853 854 AppModalDialog* dialog_delegate = 855 Singleton<AppModalDialogQueue>()->active_dialog(); 856 if (dialog_delegate && 857 (dialog_delegate->GetDialogButtons() & button) == button) { 858 if ((button & MessageBoxFlags::DIALOGBUTTON_OK) == 859 MessageBoxFlags::DIALOGBUTTON_OK) { 860 dialog_delegate->AcceptWindow(); 861 *success = true; 862 } 863 if ((button & MessageBoxFlags::DIALOGBUTTON_CANCEL) == 864 MessageBoxFlags::DIALOGBUTTON_CANCEL) { 865 DCHECK(!*success) << "invalid param, OK and CANCEL specified"; 866 dialog_delegate->CancelWindow(); 867 *success = true; 868 } 869 } 870} 871 872void AutomationProvider::ShutdownSessionService(int handle, bool* result) { 873 if (browser_tracker_->ContainsHandle(handle)) { 874 Browser* browser = browser_tracker_->GetResource(handle); 875 browser->profile()->ShutdownSessionService(); 876 *result = true; 877 } else { 878 *result = false; 879 } 880} 881 882void AutomationProvider::GetBrowserWindow(int index, int* handle) { 883 *handle = 0; 884 if (index >= 0) { 885 BrowserList::const_iterator iter = BrowserList::begin(); 886 for (; (iter != BrowserList::end()) && (index > 0); ++iter, --index) {} 887 if (iter != BrowserList::end()) { 888 *handle = browser_tracker_->Add(*iter); 889 } 890 } 891} 892 893void AutomationProvider::FindNormalBrowserWindow(int* handle) { 894 *handle = 0; 895 Browser* browser = BrowserList::FindBrowserWithType(profile_, 896 Browser::TYPE_NORMAL, 897 false); 898 if (browser) 899 *handle = browser_tracker_->Add(browser); 900} 901 902void AutomationProvider::GetLastActiveBrowserWindow(int* handle) { 903 *handle = 0; 904 Browser* browser = BrowserList::GetLastActive(); 905 if (browser) 906 *handle = browser_tracker_->Add(browser); 907} 908 909#if defined(OS_POSIX) 910// TODO(estade): use this implementation for all platforms? 911void AutomationProvider::GetActiveWindow(int* handle) { 912 gfx::NativeWindow window = 913 BrowserList::GetLastActive()->window()->GetNativeHandle(); 914 *handle = window_tracker_->Add(window); 915} 916#endif 917 918void AutomationProvider::ExecuteBrowserCommandAsync(int handle, int command, 919 bool* success) { 920 *success = false; 921 if (browser_tracker_->ContainsHandle(handle)) { 922 Browser* browser = browser_tracker_->GetResource(handle); 923 if (browser->command_updater()->SupportsCommand(command) && 924 browser->command_updater()->IsCommandEnabled(command)) { 925 browser->ExecuteCommand(command); 926 *success = true; 927 } 928 } 929} 930 931void AutomationProvider::ExecuteBrowserCommand( 932 int handle, int command, IPC::Message* reply_message) { 933 // List of commands which just finish synchronously and don't require 934 // setting up an observer. 935 static const int kSynchronousCommands[] = { 936 IDC_HOME, 937 IDC_SELECT_NEXT_TAB, 938 IDC_SELECT_PREVIOUS_TAB, 939 IDC_SHOW_BOOKMARK_MANAGER, 940 }; 941 if (browser_tracker_->ContainsHandle(handle)) { 942 Browser* browser = browser_tracker_->GetResource(handle); 943 if (browser->command_updater()->SupportsCommand(command) && 944 browser->command_updater()->IsCommandEnabled(command)) { 945 // First check if we can handle the command without using an observer. 946 for (size_t i = 0; i < arraysize(kSynchronousCommands); i++) { 947 if (command == kSynchronousCommands[i]) { 948 browser->ExecuteCommand(command); 949 AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message, 950 true); 951 Send(reply_message); 952 return; 953 } 954 } 955 956 // Use an observer if we have one, otherwise fail. 957 if (ExecuteBrowserCommandObserver::CreateAndRegisterObserver( 958 this, browser, command, reply_message)) { 959 browser->ExecuteCommand(command); 960 return; 961 } 962 } 963 } 964 AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message, false); 965 Send(reply_message); 966} 967 968// This task just adds another task to the event queue. This is useful if 969// you want to ensure that any tasks added to the event queue after this one 970// have already been processed by the time |task| is run. 971class InvokeTaskLaterTask : public Task { 972 public: 973 explicit InvokeTaskLaterTask(Task* task) : task_(task) {} 974 virtual ~InvokeTaskLaterTask() {} 975 976 virtual void Run() { 977 MessageLoop::current()->PostTask(FROM_HERE, task_); 978 } 979 980 private: 981 Task* task_; 982 983 DISALLOW_COPY_AND_ASSIGN(InvokeTaskLaterTask); 984}; 985 986void AutomationProvider::WindowSimulateClick(const IPC::Message& message, 987 int handle, 988 const gfx::Point& click, 989 int flags) { 990 if (window_tracker_->ContainsHandle(handle)) { 991 ui_controls::SendMouseMoveNotifyWhenDone(click.x(), click.y(), 992 new ClickTask(flags)); 993 } 994} 995 996void AutomationProvider::WindowSimulateMouseMove(const IPC::Message& message, 997 int handle, 998 const gfx::Point& location) { 999 if (window_tracker_->ContainsHandle(handle)) 1000 ui_controls::SendMouseMove(location.x(), location.y()); 1001} 1002 1003void AutomationProvider::WindowSimulateKeyPress(const IPC::Message& message, 1004 int handle, 1005 int key, 1006 int flags) { 1007 if (!window_tracker_->ContainsHandle(handle)) 1008 return; 1009 1010 gfx::NativeWindow window = window_tracker_->GetResource(handle); 1011 // The key event is sent to whatever window is active. 1012 ui_controls::SendKeyPress(window, static_cast<base::KeyboardCode>(key), 1013 ((flags & views::Event::EF_CONTROL_DOWN) == 1014 views::Event::EF_CONTROL_DOWN), 1015 ((flags & views::Event::EF_SHIFT_DOWN) == 1016 views::Event::EF_SHIFT_DOWN), 1017 ((flags & views::Event::EF_ALT_DOWN) == 1018 views::Event::EF_ALT_DOWN), 1019 ((flags & views::Event::EF_COMMAND_DOWN) == 1020 views::Event::EF_COMMAND_DOWN)); 1021} 1022 1023void AutomationProvider::IsWindowActive(int handle, bool* success, 1024 bool* is_active) { 1025 if (window_tracker_->ContainsHandle(handle)) { 1026 *is_active = 1027 platform_util::IsWindowActive(window_tracker_->GetResource(handle)); 1028 *success = true; 1029 } else { 1030 *success = false; 1031 *is_active = false; 1032 } 1033} 1034 1035void AutomationProvider::GetTabCount(int handle, int* tab_count) { 1036 *tab_count = -1; // -1 is the error code 1037 1038 if (browser_tracker_->ContainsHandle(handle)) { 1039 Browser* browser = browser_tracker_->GetResource(handle); 1040 *tab_count = browser->tab_count(); 1041 } 1042} 1043 1044void AutomationProvider::GetType(int handle, int* type_as_int) { 1045 *type_as_int = -1; // -1 is the error code 1046 1047 if (browser_tracker_->ContainsHandle(handle)) { 1048 Browser* browser = browser_tracker_->GetResource(handle); 1049 *type_as_int = static_cast<int>(browser->type()); 1050 } 1051} 1052 1053void AutomationProvider::GetTab(int win_handle, int tab_index, 1054 int* tab_handle) { 1055 *tab_handle = 0; 1056 if (browser_tracker_->ContainsHandle(win_handle) && (tab_index >= 0)) { 1057 Browser* browser = browser_tracker_->GetResource(win_handle); 1058 if (tab_index < browser->tab_count()) { 1059 TabContents* tab_contents = 1060 browser->GetTabContentsAt(tab_index); 1061 *tab_handle = tab_tracker_->Add(&tab_contents->controller()); 1062 } 1063 } 1064} 1065 1066void AutomationProvider::GetTabTitle(int handle, int* title_string_size, 1067 std::wstring* title) { 1068 *title_string_size = -1; // -1 is the error code 1069 if (tab_tracker_->ContainsHandle(handle)) { 1070 NavigationController* tab = tab_tracker_->GetResource(handle); 1071 NavigationEntry* entry = tab->GetActiveEntry(); 1072 if (entry != NULL) { 1073 *title = UTF16ToWideHack(entry->title()); 1074 } else { 1075 *title = std::wstring(); 1076 } 1077 *title_string_size = static_cast<int>(title->size()); 1078 } 1079} 1080 1081void AutomationProvider::GetTabIndex(int handle, int* tabstrip_index) { 1082 *tabstrip_index = -1; // -1 is the error code 1083 1084 if (tab_tracker_->ContainsHandle(handle)) { 1085 NavigationController* tab = tab_tracker_->GetResource(handle); 1086 Browser* browser = Browser::GetBrowserForController(tab, NULL); 1087 *tabstrip_index = browser->tabstrip_model()->GetIndexOfController(tab); 1088 } 1089} 1090 1091void AutomationProvider::HandleUnused(const IPC::Message& message, int handle) { 1092 if (window_tracker_->ContainsHandle(handle)) { 1093 window_tracker_->Remove(window_tracker_->GetResource(handle)); 1094 } 1095} 1096 1097void AutomationProvider::OnChannelError() { 1098 LOG(INFO) << "AutomationProxy went away, shutting down app."; 1099 AutomationProviderList::GetInstance()->RemoveProvider(this); 1100} 1101 1102// TODO(brettw) change this to accept GURLs when history supports it 1103void AutomationProvider::OnRedirectQueryComplete( 1104 HistoryService::Handle request_handle, 1105 GURL from_url, 1106 bool success, 1107 history::RedirectList* redirects) { 1108 DCHECK(request_handle == redirect_query_); 1109 DCHECK(reply_message_ != NULL); 1110 1111 std::vector<GURL> redirects_gurl; 1112 reply_message_->WriteBool(success); 1113 if (success) { 1114 for (size_t i = 0; i < redirects->size(); i++) 1115 redirects_gurl.push_back(redirects->at(i)); 1116 } 1117 1118 IPC::ParamTraits<std::vector<GURL> >::Write(reply_message_, redirects_gurl); 1119 1120 Send(reply_message_); 1121 redirect_query_ = 0; 1122 reply_message_ = NULL; 1123} 1124 1125bool AutomationProvider::Send(IPC::Message* msg) { 1126 DCHECK(channel_.get()); 1127 return channel_->Send(msg); 1128} 1129 1130Browser* AutomationProvider::FindAndActivateTab( 1131 NavigationController* controller) { 1132 int tab_index; 1133 Browser* browser = Browser::GetBrowserForController(controller, &tab_index); 1134 if (browser) 1135 browser->SelectTabContentsAt(tab_index, true); 1136 1137 return browser; 1138} 1139 1140namespace { 1141 1142class GetCookiesTask : public Task { 1143 public: 1144 GetCookiesTask(const GURL& url, 1145 URLRequestContextGetter* context_getter, 1146 base::WaitableEvent* event, 1147 std::string* cookies) 1148 : url_(url), 1149 context_getter_(context_getter), 1150 event_(event), 1151 cookies_(cookies) {} 1152 1153 virtual void Run() { 1154 *cookies_ = context_getter_->GetCookieStore()->GetCookies(url_); 1155 event_->Signal(); 1156 } 1157 1158 private: 1159 const GURL& url_; 1160 URLRequestContextGetter* const context_getter_; 1161 base::WaitableEvent* const event_; 1162 std::string* const cookies_; 1163 1164 DISALLOW_COPY_AND_ASSIGN(GetCookiesTask); 1165}; 1166 1167std::string GetCookiesForURL( 1168 const GURL& url, 1169 URLRequestContextGetter* context_getter) { 1170 std::string cookies; 1171 base::WaitableEvent event(true /* manual reset */, 1172 false /* not initially signaled */); 1173 CHECK(ChromeThread::PostTask( 1174 ChromeThread::IO, FROM_HERE, 1175 new GetCookiesTask(url, context_getter, &event, &cookies))); 1176 event.Wait(); 1177 return cookies; 1178} 1179 1180class SetCookieTask : public Task { 1181 public: 1182 SetCookieTask(const GURL& url, 1183 const std::string& value, 1184 URLRequestContextGetter* context_getter, 1185 base::WaitableEvent* event, 1186 bool* rv) 1187 : url_(url), 1188 value_(value), 1189 context_getter_(context_getter), 1190 event_(event), 1191 rv_(rv) {} 1192 1193 virtual void Run() { 1194 *rv_ = context_getter_->GetCookieStore()->SetCookie(url_, value_); 1195 event_->Signal(); 1196 } 1197 1198 private: 1199 const GURL& url_; 1200 const std::string& value_; 1201 URLRequestContextGetter* const context_getter_; 1202 base::WaitableEvent* const event_; 1203 bool* const rv_; 1204 1205 DISALLOW_COPY_AND_ASSIGN(SetCookieTask); 1206}; 1207 1208bool SetCookieForURL( 1209 const GURL& url, 1210 const std::string& value, 1211 URLRequestContextGetter* context_getter) { 1212 base::WaitableEvent event(true /* manual reset */, 1213 false /* not initially signaled */); 1214 bool rv = false; 1215 CHECK(ChromeThread::PostTask( 1216 ChromeThread::IO, FROM_HERE, 1217 new SetCookieTask(url, value, context_getter, &event, &rv))); 1218 event.Wait(); 1219 return rv; 1220} 1221 1222class DeleteCookieTask : public Task { 1223 public: 1224 DeleteCookieTask(const GURL& url, 1225 const std::string& name, 1226 const scoped_refptr<URLRequestContextGetter>& context_getter) 1227 : url_(url), 1228 name_(name), 1229 context_getter_(context_getter) {} 1230 1231 virtual void Run() { 1232 net::CookieStore* cookie_store = context_getter_->GetCookieStore(); 1233 cookie_store->DeleteCookie(url_, name_); 1234 } 1235 1236 private: 1237 const GURL url_; 1238 const std::string name_; 1239 const scoped_refptr<URLRequestContextGetter> context_getter_; 1240 1241 DISALLOW_COPY_AND_ASSIGN(DeleteCookieTask); 1242}; 1243 1244} // namespace 1245 1246void AutomationProvider::GetCookies(const GURL& url, int handle, 1247 int* value_size, 1248 std::string* value) { 1249 *value_size = -1; 1250 if (url.is_valid() && tab_tracker_->ContainsHandle(handle)) { 1251 NavigationController* tab = tab_tracker_->GetResource(handle); 1252 1253 // Since we are running on the UI thread don't call GetURLRequestContext(). 1254 scoped_refptr<URLRequestContextGetter> request_context = 1255 tab->tab_contents()->request_context(); 1256 if (!request_context.get()) 1257 request_context = tab->profile()->GetRequestContext(); 1258 1259 *value = GetCookiesForURL(url, request_context.get()); 1260 *value_size = static_cast<int>(value->size()); 1261 } 1262} 1263 1264void AutomationProvider::SetCookie(const GURL& url, 1265 const std::string value, 1266 int handle, 1267 int* response_value) { 1268 *response_value = -1; 1269 1270 if (url.is_valid() && tab_tracker_->ContainsHandle(handle)) { 1271 NavigationController* tab = tab_tracker_->GetResource(handle); 1272 1273 scoped_refptr<URLRequestContextGetter> request_context = 1274 tab->tab_contents()->request_context(); 1275 if (!request_context.get()) 1276 request_context = tab->profile()->GetRequestContext(); 1277 1278 if (SetCookieForURL(url, value, request_context.get())) 1279 *response_value = 1; 1280 } 1281} 1282 1283void AutomationProvider::DeleteCookie(const GURL& url, 1284 const std::string& cookie_name, 1285 int handle, bool* success) { 1286 *success = false; 1287 if (url.is_valid() && tab_tracker_->ContainsHandle(handle)) { 1288 NavigationController* tab = tab_tracker_->GetResource(handle); 1289 ChromeThread::PostTask( 1290 ChromeThread::IO, FROM_HERE, 1291 new DeleteCookieTask(url, cookie_name, 1292 tab->profile()->GetRequestContext())); 1293 *success = true; 1294 } 1295} 1296 1297void AutomationProvider::ShowCollectedCookiesDialog( 1298 int handle, bool* success) { 1299 *success = false; 1300 if (tab_tracker_->ContainsHandle(handle)) { 1301 TabContents* tab_contents = 1302 tab_tracker_->GetResource(handle)->tab_contents(); 1303 tab_contents->delegate()->ShowCollectedCookiesDialog(tab_contents); 1304 *success = true; 1305 } 1306} 1307 1308void AutomationProvider::GetTabURL(int handle, bool* success, GURL* url) { 1309 *success = false; 1310 if (tab_tracker_->ContainsHandle(handle)) { 1311 NavigationController* tab = tab_tracker_->GetResource(handle); 1312 // Return what the user would see in the location bar. 1313 *url = tab->GetActiveEntry()->virtual_url(); 1314 *success = true; 1315 } 1316} 1317 1318void AutomationProvider::GetTabProcessID(int handle, int* process_id) { 1319 *process_id = -1; 1320 1321 if (tab_tracker_->ContainsHandle(handle)) { 1322 *process_id = 0; 1323 TabContents* tab_contents = 1324 tab_tracker_->GetResource(handle)->tab_contents(); 1325 RenderProcessHost* rph = tab_contents->GetRenderProcessHost(); 1326 if (rph) 1327 *process_id = base::GetProcId(rph->GetHandle()); 1328 } 1329} 1330 1331void AutomationProvider::ApplyAccelerator(int handle, int id) { 1332 NOTREACHED() << "This function has been deprecated. " 1333 << "Please use ExecuteBrowserCommandAsync instead."; 1334} 1335 1336void AutomationProvider::ExecuteJavascript(int handle, 1337 const std::wstring& frame_xpath, 1338 const std::wstring& script, 1339 IPC::Message* reply_message) { 1340 bool succeeded = false; 1341 TabContents* tab_contents = GetTabContentsForHandle(handle, NULL); 1342 if (tab_contents) { 1343 // Set the routing id of this message with the controller. 1344 // This routing id needs to be remembered for the reverse 1345 // communication while sending back the response of 1346 // this javascript execution. 1347 std::wstring set_automation_id; 1348 SStringPrintf(&set_automation_id, 1349 L"window.domAutomationController.setAutomationId(%d);", 1350 reply_message->routing_id()); 1351 1352 DCHECK(reply_message_ == NULL); 1353 reply_message_ = reply_message; 1354 1355 tab_contents->render_view_host()->ExecuteJavascriptInWebFrame( 1356 frame_xpath, set_automation_id); 1357 tab_contents->render_view_host()->ExecuteJavascriptInWebFrame( 1358 frame_xpath, script); 1359 succeeded = true; 1360 } 1361 1362 if (!succeeded) { 1363 AutomationMsg_DomOperation::WriteReplyParams(reply_message, std::string()); 1364 Send(reply_message); 1365 } 1366} 1367 1368void AutomationProvider::GetShelfVisibility(int handle, bool* visible) { 1369 *visible = false; 1370 1371 if (browser_tracker_->ContainsHandle(handle)) { 1372#if defined(OS_CHROMEOS) 1373 // Chromium OS shows FileBrowse ui rather than download shelf. So we 1374 // enumerate all browsers and look for a chrome://filebrowse... pop up. 1375 for (BrowserList::const_iterator it = BrowserList::begin(); 1376 it != BrowserList::end(); ++it) { 1377 if ((*it)->type() == Browser::TYPE_POPUP) { 1378 const GURL& url = 1379 (*it)->GetTabContentsAt((*it)->selected_index())->GetURL(); 1380 1381 if (url.SchemeIs(chrome::kChromeUIScheme) && 1382 url.host() == chrome::kChromeUIFileBrowseHost) { 1383 *visible = true; 1384 break; 1385 } 1386 } 1387 } 1388#else 1389 Browser* browser = browser_tracker_->GetResource(handle); 1390 if (browser) { 1391 *visible = browser->window()->IsDownloadShelfVisible(); 1392 } 1393#endif 1394 } 1395} 1396 1397void AutomationProvider::SetShelfVisibility(int handle, bool visible) { 1398 if (browser_tracker_->ContainsHandle(handle)) { 1399 Browser* browser = browser_tracker_->GetResource(handle); 1400 if (browser) { 1401 if (visible) 1402 browser->window()->GetDownloadShelf()->Show(); 1403 else 1404 browser->window()->GetDownloadShelf()->Close(); 1405 } 1406 } 1407} 1408 1409void AutomationProvider::IsFullscreen(int handle, bool* visible) { 1410 *visible = false; 1411 1412 if (browser_tracker_->ContainsHandle(handle)) { 1413 Browser* browser = browser_tracker_->GetResource(handle); 1414 if (browser) 1415 *visible = browser->window()->IsFullscreen(); 1416 } 1417} 1418 1419void AutomationProvider::GetFullscreenBubbleVisibility(int handle, 1420 bool* visible) { 1421 *visible = false; 1422 1423 if (browser_tracker_->ContainsHandle(handle)) { 1424 Browser* browser = browser_tracker_->GetResource(handle); 1425 if (browser) 1426 *visible = browser->window()->IsFullscreenBubbleVisible(); 1427 } 1428} 1429 1430void AutomationProvider::GetConstrainedWindowCount(int handle, int* count) { 1431 *count = -1; // -1 is the error code 1432 if (tab_tracker_->ContainsHandle(handle)) { 1433 NavigationController* nav_controller = tab_tracker_->GetResource(handle); 1434 TabContents* tab_contents = nav_controller->tab_contents(); 1435 if (tab_contents) { 1436 *count = static_cast<int>(tab_contents->child_windows_.size()); 1437 } 1438 } 1439} 1440 1441void AutomationProvider::HandleFindInPageRequest( 1442 int handle, const std::wstring& find_request, 1443 int forward, int match_case, int* active_ordinal, int* matches_found) { 1444 NOTREACHED() << "This function has been deprecated." 1445 << "Please use HandleFindRequest instead."; 1446 *matches_found = -1; 1447 return; 1448} 1449 1450void AutomationProvider::HandleFindRequest( 1451 int handle, 1452 const AutomationMsg_Find_Params& params, 1453 IPC::Message* reply_message) { 1454 if (!tab_tracker_->ContainsHandle(handle)) { 1455 AutomationMsg_FindInPage::WriteReplyParams(reply_message, -1, -1); 1456 Send(reply_message); 1457 return; 1458 } 1459 1460 NavigationController* nav = tab_tracker_->GetResource(handle); 1461 TabContents* tab_contents = nav->tab_contents(); 1462 1463 find_in_page_observer_.reset(new 1464 FindInPageNotificationObserver(this, tab_contents, reply_message)); 1465 1466 tab_contents->set_current_find_request_id( 1467 FindInPageNotificationObserver::kFindInPageRequestId); 1468 tab_contents->render_view_host()->StartFinding( 1469 FindInPageNotificationObserver::kFindInPageRequestId, 1470 params.search_string, params.forward, params.match_case, 1471 params.find_next); 1472} 1473 1474void AutomationProvider::HandleOpenFindInPageRequest( 1475 const IPC::Message& message, int handle) { 1476 if (browser_tracker_->ContainsHandle(handle)) { 1477 Browser* browser = browser_tracker_->GetResource(handle); 1478 browser->FindInPage(false, false); 1479 } 1480} 1481 1482void AutomationProvider::GetFindWindowVisibility(int handle, bool* visible) { 1483 *visible = false; 1484 Browser* browser = browser_tracker_->GetResource(handle); 1485 if (browser) { 1486 FindBarTesting* find_bar = 1487 browser->GetFindBarController()->find_bar()->GetFindBarTesting(); 1488 find_bar->GetFindBarWindowInfo(NULL, visible); 1489 } 1490} 1491 1492void AutomationProvider::HandleFindWindowLocationRequest(int handle, int* x, 1493 int* y) { 1494 gfx::Point position(0, 0); 1495 bool visible = false; 1496 if (browser_tracker_->ContainsHandle(handle)) { 1497 Browser* browser = browser_tracker_->GetResource(handle); 1498 FindBarTesting* find_bar = 1499 browser->GetFindBarController()->find_bar()->GetFindBarTesting(); 1500 find_bar->GetFindBarWindowInfo(&position, &visible); 1501 } 1502 1503 *x = position.x(); 1504 *y = position.y(); 1505} 1506 1507// Bookmark bar visibility is based on the pref (e.g. is it in the toolbar). 1508// Presence in the NTP is NOT considered visible by this call. 1509void AutomationProvider::GetBookmarkBarVisibility(int handle, 1510 bool* visible, 1511 bool* animating) { 1512 *visible = false; 1513 *animating = false; 1514 1515 if (browser_tracker_->ContainsHandle(handle)) { 1516 Browser* browser = browser_tracker_->GetResource(handle); 1517 if (browser) { 1518#if 0 // defined(TOOLKIT_VIEWS) && defined(OS_LINUX) 1519 // TODO(jrg): Was removed in rev43789 for perf. Need to investigate. 1520 1521 // IsBookmarkBarVisible() line looks correct but is not 1522 // consistent across platforms. Specifically, on Mac/Linux, it 1523 // returns false if the bar is hidden in a pref (even if visible 1524 // on the NTP). On ChromeOS, it returned true if on NTP 1525 // independent of the pref. Making the code more consistent 1526 // caused a perf bot regression on Windows (which shares views). 1527 // See http://crbug.com/40225 1528 *visible = browser->profile()->GetPrefs()->GetBoolean( 1529 prefs::kShowBookmarkBar); 1530#else 1531 *visible = browser->window()->IsBookmarkBarVisible(); 1532#endif 1533 *animating = browser->window()->IsBookmarkBarAnimating(); 1534 } 1535 } 1536} 1537 1538void AutomationProvider::GetBookmarksAsJSON(int handle, 1539 std::string* bookmarks_as_json, 1540 bool *success) { 1541 *success = false; 1542 if (browser_tracker_->ContainsHandle(handle)) { 1543 Browser* browser = browser_tracker_->GetResource(handle); 1544 if (browser) { 1545 if (!browser->profile()->GetBookmarkModel()->IsLoaded()) { 1546 return; 1547 } 1548 scoped_refptr<BookmarkStorage> storage = new BookmarkStorage( 1549 browser->profile(), 1550 browser->profile()->GetBookmarkModel()); 1551 *success = storage->SerializeData(bookmarks_as_json); 1552 } 1553 } 1554} 1555 1556void AutomationProvider::WaitForBookmarkModelToLoad( 1557 int handle, 1558 IPC::Message* reply_message) { 1559 if (browser_tracker_->ContainsHandle(handle)) { 1560 Browser* browser = browser_tracker_->GetResource(handle); 1561 BookmarkModel* model = browser->profile()->GetBookmarkModel(); 1562 if (model->IsLoaded()) { 1563 AutomationMsg_WaitForBookmarkModelToLoad::WriteReplyParams( 1564 reply_message, true); 1565 Send(reply_message); 1566 } else { 1567 // The observer will delete itself when done. 1568 new AutomationProviderBookmarkModelObserver(this, reply_message, 1569 model); 1570 } 1571 } 1572} 1573 1574void AutomationProvider::AddBookmarkGroup(int handle, 1575 int64 parent_id, int index, 1576 std::wstring title, 1577 bool* success) { 1578 if (browser_tracker_->ContainsHandle(handle)) { 1579 Browser* browser = browser_tracker_->GetResource(handle); 1580 if (browser) { 1581 BookmarkModel* model = browser->profile()->GetBookmarkModel(); 1582 if (!model->IsLoaded()) { 1583 *success = false; 1584 return; 1585 } 1586 const BookmarkNode* parent = model->GetNodeByID(parent_id); 1587 DCHECK(parent); 1588 if (parent) { 1589 const BookmarkNode* child = model->AddGroup(parent, index, 1590 WideToUTF16(title)); 1591 DCHECK(child); 1592 if (child) 1593 *success = true; 1594 } 1595 } 1596 } 1597 *success = false; 1598} 1599 1600void AutomationProvider::AddBookmarkURL(int handle, 1601 int64 parent_id, int index, 1602 std::wstring title, const GURL& url, 1603 bool* success) { 1604 if (browser_tracker_->ContainsHandle(handle)) { 1605 Browser* browser = browser_tracker_->GetResource(handle); 1606 if (browser) { 1607 BookmarkModel* model = browser->profile()->GetBookmarkModel(); 1608 if (!model->IsLoaded()) { 1609 *success = false; 1610 return; 1611 } 1612 const BookmarkNode* parent = model->GetNodeByID(parent_id); 1613 DCHECK(parent); 1614 if (parent) { 1615 const BookmarkNode* child = model->AddURL(parent, index, 1616 WideToUTF16(title), url); 1617 DCHECK(child); 1618 if (child) 1619 *success = true; 1620 } 1621 } 1622 } 1623 *success = false; 1624} 1625 1626void AutomationProvider::ReparentBookmark(int handle, 1627 int64 id, int64 new_parent_id, 1628 int index, 1629 bool* success) { 1630 if (browser_tracker_->ContainsHandle(handle)) { 1631 Browser* browser = browser_tracker_->GetResource(handle); 1632 if (browser) { 1633 BookmarkModel* model = browser->profile()->GetBookmarkModel(); 1634 if (!model->IsLoaded()) { 1635 *success = false; 1636 return; 1637 } 1638 const BookmarkNode* node = model->GetNodeByID(id); 1639 DCHECK(node); 1640 const BookmarkNode* new_parent = model->GetNodeByID(new_parent_id); 1641 DCHECK(new_parent); 1642 if (node && new_parent) { 1643 model->Move(node, new_parent, index); 1644 *success = true; 1645 } 1646 } 1647 } 1648 *success = false; 1649} 1650 1651void AutomationProvider::SetBookmarkTitle(int handle, 1652 int64 id, std::wstring title, 1653 bool* success) { 1654 if (browser_tracker_->ContainsHandle(handle)) { 1655 Browser* browser = browser_tracker_->GetResource(handle); 1656 if (browser) { 1657 BookmarkModel* model = browser->profile()->GetBookmarkModel(); 1658 if (!model->IsLoaded()) { 1659 *success = false; 1660 return; 1661 } 1662 const BookmarkNode* node = model->GetNodeByID(id); 1663 DCHECK(node); 1664 if (node) { 1665 model->SetTitle(node, WideToUTF16(title)); 1666 *success = true; 1667 } 1668 } 1669 } 1670 *success = false; 1671} 1672 1673void AutomationProvider::SetBookmarkURL(int handle, 1674 int64 id, const GURL& url, 1675 bool* success) { 1676 if (browser_tracker_->ContainsHandle(handle)) { 1677 Browser* browser = browser_tracker_->GetResource(handle); 1678 if (browser) { 1679 BookmarkModel* model = browser->profile()->GetBookmarkModel(); 1680 if (!model->IsLoaded()) { 1681 *success = false; 1682 return; 1683 } 1684 const BookmarkNode* node = model->GetNodeByID(id); 1685 DCHECK(node); 1686 if (node) { 1687 model->SetURL(node, url); 1688 *success = true; 1689 } 1690 } 1691 } 1692 *success = false; 1693} 1694 1695void AutomationProvider::RemoveBookmark(int handle, 1696 int64 id, 1697 bool* success) { 1698 if (browser_tracker_->ContainsHandle(handle)) { 1699 Browser* browser = browser_tracker_->GetResource(handle); 1700 if (browser) { 1701 BookmarkModel* model = browser->profile()->GetBookmarkModel(); 1702 if (!model->IsLoaded()) { 1703 *success = false; 1704 return; 1705 } 1706 const BookmarkNode* node = model->GetNodeByID(id); 1707 DCHECK(node); 1708 if (node) { 1709 const BookmarkNode* parent = node->GetParent(); 1710 DCHECK(parent); 1711 model->Remove(parent, parent->IndexOfChild(node)); 1712 *success = true; 1713 } 1714 } 1715 } 1716 *success = false; 1717} 1718 1719// Sample json input: { "command": "SetWindowDimensions", 1720// "x": 20, # optional 1721// "y": 20, # optional 1722// "width": 800, # optional 1723// "height": 600 } # optional 1724void AutomationProvider::SetWindowDimensions(Browser* browser, 1725 DictionaryValue* args, 1726 IPC::Message* reply_message) { 1727 gfx::Rect rect = browser->window()->GetRestoredBounds(); 1728 int x, y, width, height; 1729 if (args->GetInteger(L"x", &x)) 1730 rect.set_x(x); 1731 if (args->GetInteger(L"y", &y)) 1732 rect.set_y(y); 1733 if (args->GetInteger(L"width", &width)) 1734 rect.set_width(width); 1735 if (args->GetInteger(L"height", &height)) 1736 rect.set_height(height); 1737 browser->window()->SetBounds(rect); 1738 AutomationJSONReply(this, reply_message).SendSuccess(NULL); 1739} 1740 1741ListValue* AutomationProvider::GetInfobarsInfo(TabContents* tc) { 1742 // Each infobar may have different properties depending on the type. 1743 ListValue* infobars = new ListValue; 1744 for (int infobar_index = 0; 1745 infobar_index < tc->infobar_delegate_count(); 1746 ++infobar_index) { 1747 DictionaryValue* infobar_item = new DictionaryValue; 1748 InfoBarDelegate* infobar = tc->GetInfoBarDelegateAt(infobar_index); 1749 if (infobar->AsConfirmInfoBarDelegate()) { 1750 // Also covers ThemeInstalledInfoBarDelegate and 1751 // CrashedExtensionInfoBarDelegate. 1752 infobar_item->SetString(L"type", "confirm_infobar"); 1753 ConfirmInfoBarDelegate* confirm_infobar = 1754 infobar->AsConfirmInfoBarDelegate(); 1755 infobar_item->SetString(L"text", confirm_infobar->GetMessageText()); 1756 infobar_item->SetString(L"link_text", confirm_infobar->GetLinkText()); 1757 ListValue* buttons_list = new ListValue; 1758 int buttons = confirm_infobar->GetButtons(); 1759 if (ConfirmInfoBarDelegate::BUTTON_OK & buttons) { 1760 StringValue* button_label = new StringValue( 1761 confirm_infobar->GetButtonLabel( 1762 ConfirmInfoBarDelegate::BUTTON_OK)); 1763 buttons_list->Append(button_label); 1764 } 1765 if (ConfirmInfoBarDelegate::BUTTON_CANCEL & buttons) { 1766 StringValue* button_label = new StringValue( 1767 confirm_infobar->GetButtonLabel( 1768 ConfirmInfoBarDelegate::BUTTON_CANCEL)); 1769 buttons_list->Append(button_label); 1770 } 1771 infobar_item->Set(L"buttons", buttons_list); 1772 } else if (infobar->AsAlertInfoBarDelegate()) { 1773 infobar_item->SetString(L"type", "alert_infobar"); 1774 AlertInfoBarDelegate* alert_infobar = 1775 infobar->AsAlertInfoBarDelegate(); 1776 infobar_item->SetString(L"text", alert_infobar->GetMessageText()); 1777 } else if (infobar->AsLinkInfoBarDelegate()) { 1778 infobar_item->SetString(L"type", "link_infobar"); 1779 LinkInfoBarDelegate* link_infobar = infobar->AsLinkInfoBarDelegate(); 1780 infobar_item->SetString(L"link_text", link_infobar->GetLinkText()); 1781 } else if (infobar->AsTranslateInfoBarDelegate()) { 1782 infobar_item->SetString(L"type", "translate_infobar"); 1783 TranslateInfoBarDelegate* translate_infobar = 1784 infobar->AsTranslateInfoBarDelegate(); 1785 infobar_item->SetString(L"original_lang_code", 1786 translate_infobar->GetOriginalLanguageCode()); 1787 infobar_item->SetString(L"target_lang_code", 1788 translate_infobar->GetTargetLanguageCode()); 1789 } else if (infobar->AsExtensionInfoBarDelegate()) { 1790 infobar_item->SetString(L"type", "extension_infobar"); 1791 } else { 1792 infobar_item->SetString(L"type", "unknown_infobar"); 1793 } 1794 infobars->Append(infobar_item); 1795 } 1796 return infobars; 1797} 1798 1799// Sample json input: { "command": "WaitForInfobarCount", 1800// "count": COUNT, 1801// "tab_index": INDEX } 1802// Sample output: {} 1803void AutomationProvider::WaitForInfobarCount(Browser* browser, 1804 DictionaryValue* args, 1805 IPC::Message* reply_message) { 1806 int tab_index; 1807 int count; 1808 if (!args->GetInteger(L"count", &count) || count < 0 || 1809 !args->GetInteger(L"tab_index", &tab_index) || tab_index < 0) { 1810 AutomationJSONReply(this, reply_message).SendError( 1811 "Missing or invalid args: 'count', 'tab_index'."); 1812 return; 1813 } 1814 1815 TabContents* tab_contents = browser->GetTabContentsAt(tab_index); 1816 // Observer deletes itself. 1817 new WaitForInfobarCountObserver(this, reply_message, tab_contents, count); 1818} 1819 1820namespace { 1821 1822// Task to get info about BrowserChildProcessHost. Must run on IO thread to 1823// honor the semantics of BrowserChildProcessHost. 1824// Used by AutomationProvider::GetBrowserInfo(). 1825class GetChildProcessHostInfoTask : public Task { 1826 public: 1827 GetChildProcessHostInfoTask(base::WaitableEvent* event, 1828 ListValue* child_processes) 1829 : event_(event), 1830 child_processes_(child_processes) {} 1831 1832 virtual void Run() { 1833 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); 1834 for (BrowserChildProcessHost::Iterator iter; !iter.Done(); ++iter) { 1835 // Only add processes which are already started, 1836 // since we need their handle. 1837 if ((*iter)->handle() == base::kNullProcessHandle) { 1838 continue; 1839 } 1840 ChildProcessInfo* info = *iter; 1841 DictionaryValue* item = new DictionaryValue; 1842 item->SetString(L"name", info->name()); 1843 item->SetString(L"type", 1844 ChildProcessInfo::GetTypeNameInEnglish(info->type())); 1845 item->SetInteger(L"pid", base::GetProcId(info->handle())); 1846 child_processes_->Append(item); 1847 } 1848 event_->Signal(); 1849 } 1850 1851 private: 1852 base::WaitableEvent* const event_; // weak 1853 ListValue* child_processes_; 1854 1855 DISALLOW_COPY_AND_ASSIGN(GetChildProcessHostInfoTask); 1856}; 1857 1858} // namespace 1859 1860// Sample json input: { "command": "GetBrowserInfo" } 1861// Refer to GetBrowserInfo() in chrome/test/pyautolib/pyauto.py for 1862// sample json output. 1863void AutomationProvider::GetBrowserInfo(Browser* browser, 1864 DictionaryValue* args, 1865 IPC::Message* reply_message) { 1866 DictionaryValue* properties = new DictionaryValue; 1867 properties->SetString(L"ChromeVersion", chrome::kChromeVersion); 1868 properties->SetString(L"BrowserProcessExecutableName", 1869 chrome::kBrowserProcessExecutableName); 1870 properties->SetString(L"HelperProcessExecutableName", 1871 chrome::kHelperProcessExecutableName); 1872 properties->SetString(L"BrowserProcessExecutablePath", 1873 chrome::kBrowserProcessExecutablePath); 1874 properties->SetString(L"HelperProcessExecutablePath", 1875 chrome::kHelperProcessExecutablePath); 1876 properties->SetString(L"command_line_string", 1877 CommandLine::ForCurrentProcess()->command_line_string()); 1878 1879 std::string branding; 1880#if defined(GOOGLE_CHROME_BUILD) 1881 branding = "Google Chrome"; 1882#elif defined(CHROMIUM_BUILD) 1883 branding = "Chromium"; 1884#else 1885 branding = "Unknown Branding"; 1886#endif 1887 properties->SetString(L"branding", branding); 1888 1889 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 1890 return_value->Set(L"properties", properties); 1891 1892 return_value->SetInteger(L"browser_pid", base::GetCurrentProcId()); 1893 // Add info about all windows in a list of dictionaries, one dictionary 1894 // item per window. 1895 ListValue* windows = new ListValue; 1896 int windex = 0; 1897 for (BrowserList::const_iterator it = BrowserList::begin(); 1898 it != BrowserList::end(); 1899 ++it, ++windex) { 1900 DictionaryValue* browser_item = new DictionaryValue; 1901 browser = *it; 1902 browser_item->SetInteger(L"index", windex); 1903 // Window properties 1904 gfx::Rect rect = browser->window()->GetRestoredBounds(); 1905 browser_item->SetInteger(L"x", rect.x()); 1906 browser_item->SetInteger(L"y", rect.y()); 1907 browser_item->SetInteger(L"width", rect.width()); 1908 browser_item->SetInteger(L"height", rect.height()); 1909 browser_item->SetBoolean(L"fullscreen", 1910 browser->window()->IsFullscreen()); 1911 browser_item->SetInteger(L"selected_tab", browser->selected_index()); 1912 browser_item->SetBoolean(L"incognito", 1913 browser->profile()->IsOffTheRecord()); 1914 // For each window, add info about all tabs in a list of dictionaries, 1915 // one dictionary item per tab. 1916 ListValue* tabs = new ListValue; 1917 for (int i = 0; i < browser->tab_count(); ++i) { 1918 TabContents* tc = browser->GetTabContentsAt(i); 1919 DictionaryValue* tab = new DictionaryValue; 1920 tab->SetInteger(L"index", i); 1921 tab->SetString(L"url", tc->GetURL().spec()); 1922 tab->SetInteger(L"renderer_pid", 1923 base::GetProcId(tc->GetRenderProcessHost()->GetHandle())); 1924 tab->Set(L"infobars", GetInfobarsInfo(tc)); 1925 tabs->Append(tab); 1926 } 1927 browser_item->Set(L"tabs", tabs); 1928 1929 windows->Append(browser_item); 1930 } 1931 return_value->Set(L"windows", windows); 1932 1933 return_value->SetString(L"child_process_path", 1934 ChildProcessHost::GetChildPath(true).value()); 1935 // Child processes are the processes for plugins and other workers. 1936 // Add all child processes in a list of dictionaries, one dictionary item 1937 // per child process. 1938 ListValue* child_processes = new ListValue; 1939 base::WaitableEvent event(true /* manual reset */, 1940 false /* not initially signaled */); 1941 CHECK(ChromeThread::PostTask( 1942 ChromeThread::IO, FROM_HERE, 1943 new GetChildProcessHostInfoTask(&event, child_processes))); 1944 event.Wait(); 1945 return_value->Set(L"child_processes", child_processes); 1946 1947 // Add all extension processes in a list of dictionaries, one dictionary 1948 // item per extension process. 1949 ListValue* extension_processes = new ListValue; 1950 ProfileManager* profile_manager = g_browser_process->profile_manager(); 1951 for (ProfileManager::const_iterator it = profile_manager->begin(); 1952 it != profile_manager->end(); ++it) { 1953 ExtensionProcessManager* process_manager = 1954 (*it)->GetExtensionProcessManager(); 1955 ExtensionProcessManager::const_iterator jt; 1956 for (jt = process_manager->begin(); jt != process_manager->end(); ++jt) { 1957 ExtensionHost* ex_host = *jt; 1958 // Don't add dead extension processes. 1959 if (!ex_host->IsRenderViewLive()) 1960 continue; 1961 DictionaryValue* item = new DictionaryValue; 1962 item->SetString(L"name", ex_host->extension()->name()); 1963 item->SetInteger( 1964 L"pid", 1965 base::GetProcId(ex_host->render_process_host()->GetHandle())); 1966 extension_processes->Append(item); 1967 } 1968 } 1969 return_value->Set(L"extension_processes", extension_processes); 1970 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get()); 1971} 1972 1973// Sample json input: { "command": "GetHistoryInfo", 1974// "search_text": "some text" } 1975// Refer chrome/test/pyautolib/history_info.py for sample json output. 1976void AutomationProvider::GetHistoryInfo(Browser* browser, 1977 DictionaryValue* args, 1978 IPC::Message* reply_message) { 1979 consumer_.CancelAllRequests(); 1980 1981 string16 search_text; 1982 args->GetString("search_text", &search_text); 1983 1984 // Fetch history. 1985 HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); 1986 history::QueryOptions options; 1987 // The observer owns itself. It deletes itself after it fetches history. 1988 AutomationProviderHistoryObserver* history_observer = 1989 new AutomationProviderHistoryObserver(this, reply_message); 1990 hs->QueryHistory( 1991 search_text, 1992 options, 1993 &consumer_, 1994 NewCallback(history_observer, 1995 &AutomationProviderHistoryObserver::HistoryQueryComplete)); 1996} 1997 1998// Sample json input: { "command": "AddHistoryItem", 1999// "item": { "URL": "http://www.google.com", 2000// "title": "Google", # optional 2001// "time": 12345 # optional (time_t) 2002// } } 2003// Refer chrome/test/pyautolib/pyauto.py for details on input. 2004void AutomationProvider::AddHistoryItem(Browser* browser, 2005 DictionaryValue* args, 2006 IPC::Message* reply_message) { 2007 DictionaryValue* item = NULL; 2008 args->GetDictionary(L"item", &item); 2009 string16 url_text; 2010 string16 title; 2011 base::Time time = base::Time::Now(); 2012 AutomationJSONReply reply(this, reply_message); 2013 2014 if (!item->GetString("url", &url_text)) { 2015 reply.SendError("bad args (no URL in dict?)"); 2016 return; 2017 } 2018 GURL gurl(url_text); 2019 item->GetString("title", &title); // Don't care if it fails. 2020 int it; 2021 double dt; 2022 if (item->GetInteger(L"time", &it)) 2023 time = base::Time::FromTimeT(it); 2024 else if (item->GetReal(L"time", &dt)) 2025 time = base::Time::FromDoubleT(dt); 2026 2027 // Ideas for "dummy" values (e.g. id_scope) came from 2028 // chrome/browser/autocomplete/history_contents_provider_unittest.cc 2029 HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); 2030 const void* id_scope = reinterpret_cast<void*>(1); 2031 hs->AddPage(gurl, time, 2032 id_scope, 2033 0, 2034 GURL(), 2035 PageTransition::LINK, 2036 history::RedirectList(), 2037 false); 2038 if (title.length()) 2039 hs->SetPageTitle(gurl, title); 2040 reply.SendSuccess(NULL); 2041} 2042 2043// Sample json input: { "command": "GetDownloadsInfo" } 2044// Refer chrome/test/pyautolib/download_info.py for sample json output. 2045void AutomationProvider::GetDownloadsInfo(Browser* browser, 2046 DictionaryValue* args, 2047 IPC::Message* reply_message) { 2048 AutomationProviderDownloadManagerObserver observer; 2049 std::vector<DownloadItem*> downloads; 2050 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 2051 AutomationJSONReply reply(this, reply_message); 2052 2053 if (!profile_->HasCreatedDownloadManager()) { 2054 reply.SendError("no download manager"); 2055 return; 2056 } 2057 // Use DownloadManager's GetDownloads() method and not GetCurrentDownloads() 2058 // since that would be transient; a download might enter and empty out 2059 // the current download queue too soon to be noticed. 2060 profile_->GetDownloadManager()->GetDownloads(&observer, L""); 2061 downloads = observer.Downloads(); 2062 2063 std::map<DownloadItem::DownloadState, std::string> state_to_string; 2064 state_to_string[DownloadItem::IN_PROGRESS] = std::string("IN_PROGRESS"); 2065 state_to_string[DownloadItem::CANCELLED] = std::string("CANCELLED"); 2066 state_to_string[DownloadItem::REMOVING] = std::string("REMOVING"); 2067 state_to_string[DownloadItem::COMPLETE] = std::string("COMPLETE"); 2068 2069 std::map<DownloadItem::SafetyState, std::string> safety_state_to_string; 2070 safety_state_to_string[DownloadItem::SAFE] = std::string("SAFE"); 2071 safety_state_to_string[DownloadItem::DANGEROUS] = std::string("DANGEROUS"); 2072 safety_state_to_string[DownloadItem::DANGEROUS_BUT_VALIDATED] = 2073 std::string("DANGEROUS_BUT_VALIDATED"); 2074 2075 ListValue* list_of_downloads = new ListValue; 2076 for (std::vector<DownloadItem*>::iterator it = downloads.begin(); 2077 it != downloads.end(); 2078 it++) { // Fill info about each download item. 2079 DictionaryValue* dl_item_value = new DictionaryValue; 2080 dl_item_value->SetInteger(L"id", static_cast<int>((*it)->id())); 2081 dl_item_value->SetString(L"url", (*it)->url().spec()); 2082 dl_item_value->SetString(L"referrer_url", (*it)->referrer_url().spec()); 2083 dl_item_value->SetString(L"file_name", (*it)->file_name().value()); 2084 dl_item_value->SetString(L"full_path", (*it)->full_path().value()); 2085 dl_item_value->SetBoolean(L"is_paused", (*it)->is_paused()); 2086 dl_item_value->SetBoolean(L"open_when_complete", 2087 (*it)->open_when_complete()); 2088 dl_item_value->SetBoolean(L"is_extension_install", 2089 (*it)->is_extension_install()); 2090 dl_item_value->SetBoolean(L"is_temporary", (*it)->is_temporary()); 2091 dl_item_value->SetBoolean(L"is_otr", (*it)->is_otr()); // off-the-record 2092 dl_item_value->SetString(L"state", state_to_string[(*it)->state()]); 2093 dl_item_value->SetString(L"safety_state", 2094 safety_state_to_string[(*it)->safety_state()]); 2095 dl_item_value->SetInteger(L"PercentComplete", (*it)->PercentComplete()); 2096 list_of_downloads->Append(dl_item_value); 2097 } 2098 return_value->Set(L"downloads", list_of_downloads); 2099 2100 reply.SendSuccess(return_value.get()); 2101 // All value objects allocated above are owned by |return_value| 2102 // and get freed by it. 2103} 2104 2105void AutomationProvider::WaitForDownloadsToComplete( 2106 Browser* browser, 2107 DictionaryValue* args, 2108 IPC::Message* reply_message) { 2109 AutomationProviderDownloadManagerObserver observer; 2110 std::vector<DownloadItem*> downloads; 2111 AutomationJSONReply reply(this, reply_message); 2112 2113 // Look for a quick return. 2114 if (!profile_->HasCreatedDownloadManager()) { 2115 reply.SendSuccess(NULL); // No download manager. 2116 return; 2117 } 2118 profile_->GetDownloadManager()->GetCurrentDownloads(&observer, FilePath()); 2119 downloads = observer.Downloads(); 2120 if (downloads.size() == 0) { 2121 reply.SendSuccess(NULL); 2122 return; 2123 } 2124 2125 // The observer owns itself. When the last observed item pings, it 2126 // deletes itself. 2127 AutomationProviderDownloadItemObserver* item_observer = 2128 new AutomationProviderDownloadItemObserver( 2129 this, reply_message, downloads.size()); 2130 for (std::vector<DownloadItem*>::iterator i = downloads.begin(); 2131 i != downloads.end(); 2132 i++) { 2133 (*i)->AddObserver(item_observer); 2134 } 2135} 2136 2137// Sample json input: { "command": "GetPrefsInfo" } 2138// Refer chrome/test/pyautolib/prefs_info.py for sample json output. 2139void AutomationProvider::GetPrefsInfo(Browser* browser, 2140 DictionaryValue* args, 2141 IPC::Message* reply_message) { 2142 const PrefService::PreferenceSet& prefs = 2143 profile_->GetPrefs()->preference_set(); 2144 DictionaryValue* items = new DictionaryValue; 2145 for (PrefService::PreferenceSet::const_iterator it = prefs.begin(); 2146 it != prefs.end(); ++it) { 2147 items->Set((*it)->name(), (*it)->GetValue()->DeepCopy()); 2148 } 2149 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 2150 return_value->Set(L"prefs", items); // return_value owns items. 2151 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get()); 2152} 2153 2154// Sample json input: { "command": "SetPrefs", "path": path, "value": value } 2155void AutomationProvider::SetPrefs(Browser* browser, 2156 DictionaryValue* args, 2157 IPC::Message* reply_message) { 2158 std::wstring path; 2159 Value* val; 2160 AutomationJSONReply reply(this, reply_message); 2161 if (args->GetString(L"path", &path) && args->Get(L"value", &val)) { 2162 PrefService* pref_service = profile_->GetPrefs(); 2163 const PrefService::Preference* pref = 2164 pref_service->FindPreference(path.c_str()); 2165 if (!pref) { // Not a registered pref. 2166 reply.SendError("pref not registered."); 2167 return; 2168 } else if (pref->IsManaged()) { // Do not attempt to change a managed pref. 2169 reply.SendError("pref is managed. cannot be changed."); 2170 return; 2171 } else { // Set the pref. 2172 pref_service->Set(path.c_str(), *val); 2173 } 2174 } else { 2175 reply.SendError("no pref path or value given."); 2176 return; 2177 } 2178 2179 reply.SendSuccess(NULL); 2180} 2181 2182// Sample json input: { "command": "GetOmniboxInfo" } 2183// Refer chrome/test/pyautolib/omnibox_info.py for sample json output. 2184void AutomationProvider::GetOmniboxInfo(Browser* browser, 2185 DictionaryValue* args, 2186 IPC::Message* reply_message) { 2187 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 2188 2189 LocationBar* loc_bar = browser->window()->GetLocationBar(); 2190 AutocompleteEditView* edit_view = loc_bar->location_entry(); 2191 AutocompleteEditModel* model = edit_view->model(); 2192 2193 // Fill up matches. 2194 ListValue* matches = new ListValue; 2195 const AutocompleteResult& result = model->result(); 2196 for (AutocompleteResult::const_iterator i = result.begin(); 2197 i != result.end(); ++i) { 2198 const AutocompleteMatch& match = *i; 2199 DictionaryValue* item = new DictionaryValue; // owned by return_value 2200 item->SetString(L"type", AutocompleteMatch::TypeToString(match.type)); 2201 item->SetBoolean(L"starred", match.starred); 2202 item->SetString(L"destination_url", match.destination_url.spec()); 2203 item->SetString(L"contents", match.contents); 2204 item->SetString(L"description", match.description); 2205 matches->Append(item); 2206 } 2207 return_value->Set(L"matches", matches); 2208 2209 // Fill up other properties. 2210 DictionaryValue* properties = new DictionaryValue; // owned by return_value 2211 properties->SetBoolean(L"has_focus", model->has_focus()); 2212 properties->SetBoolean(L"query_in_progress", model->query_in_progress()); 2213 properties->SetString(L"keyword", model->keyword()); 2214 properties->SetString(L"text", edit_view->GetText()); 2215 return_value->Set(L"properties", properties); 2216 2217 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get()); 2218} 2219 2220// Sample json input: { "command": "SetOmniboxText", 2221// "text": "goog" } 2222void AutomationProvider::SetOmniboxText(Browser* browser, 2223 DictionaryValue* args, 2224 IPC::Message* reply_message) { 2225 std::wstring text; 2226 AutomationJSONReply reply(this, reply_message); 2227 if (!args->GetString(L"text", &text)) { 2228 reply.SendError("text missing"); 2229 return; 2230 } 2231 browser->FocusLocationBar(); 2232 LocationBar* loc_bar = browser->window()->GetLocationBar(); 2233 AutocompleteEditView* edit_view = loc_bar->location_entry(); 2234 edit_view->model()->OnSetFocus(false); 2235 edit_view->SetUserText(text); 2236 reply.SendSuccess(NULL); 2237} 2238 2239// Sample json input: { "command": "OmniboxMovePopupSelection", 2240// "count": 1 } 2241// Negative count implies up, positive implies down. Count values will be 2242// capped by the size of the popup list. 2243void AutomationProvider::OmniboxMovePopupSelection( 2244 Browser* browser, 2245 DictionaryValue* args, 2246 IPC::Message* reply_message) { 2247 int count; 2248 AutomationJSONReply reply(this, reply_message); 2249 if (!args->GetInteger(L"count", &count)) { 2250 reply.SendError("count missing"); 2251 return; 2252 } 2253 LocationBar* loc_bar = browser->window()->GetLocationBar(); 2254 AutocompleteEditModel* model = loc_bar->location_entry()->model(); 2255 model->OnUpOrDownKeyPressed(count); 2256 reply.SendSuccess(NULL); 2257} 2258 2259// Sample json input: { "command": "OmniboxAcceptInput" } 2260void AutomationProvider::OmniboxAcceptInput(Browser* browser, 2261 DictionaryValue* args, 2262 IPC::Message* reply_message) { 2263 NavigationController& controller = 2264 browser->GetSelectedTabContents()->controller(); 2265 // Setup observer to wait until the selected item loads. 2266 NotificationObserver* observer = 2267 new OmniboxAcceptNotificationObserver(&controller, this, reply_message); 2268 notification_observer_list_.AddObserver(observer); 2269 2270 browser->window()->GetLocationBar()->AcceptInput(); 2271} 2272 2273// Sample json input: { "command": "GetInitialLoadTimes" } 2274// Refer to InitialLoadObserver::GetTimingInformation() for sample output. 2275void AutomationProvider::GetInitialLoadTimes( 2276 Browser*, 2277 DictionaryValue*, 2278 IPC::Message* reply_message) { 2279 scoped_ptr<DictionaryValue> return_value( 2280 initial_load_observer_->GetTimingInformation()); 2281 2282 std::string json_return; 2283 base::JSONWriter::Write(return_value.get(), false, &json_return); 2284 AutomationMsg_SendJSONRequest::WriteReplyParams( 2285 reply_message, json_return, true); 2286 Send(reply_message); 2287} 2288 2289// Sample json input: { "command": "GetPluginsInfo" } 2290// Refer chrome/test/pyautolib/plugins_info.py for sample json output. 2291void AutomationProvider::GetPluginsInfo(Browser* browser, 2292 DictionaryValue* args, 2293 IPC::Message* reply_message) { 2294 std::vector<WebPluginInfo> plugins; 2295 NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins); 2296 ListValue* items = new ListValue; 2297 for (std::vector<WebPluginInfo>::const_iterator it = plugins.begin(); 2298 it != plugins.end(); 2299 ++it) { 2300 DictionaryValue* item = new DictionaryValue; 2301 item->SetStringFromUTF16(L"name", it->name); 2302 item->SetString(L"path", it->path.value()); 2303 item->SetStringFromUTF16(L"version", it->version); 2304 item->SetStringFromUTF16(L"desc", it->desc); 2305 item->SetBoolean(L"enabled", it->enabled); 2306 // Add info about mime types. 2307 ListValue* mime_types = new ListValue(); 2308 for (std::vector<WebPluginMimeType>::const_iterator type_it = 2309 it->mime_types.begin(); 2310 type_it != it->mime_types.end(); 2311 ++type_it) { 2312 DictionaryValue* mime_type = new DictionaryValue(); 2313 mime_type->SetString(L"mimeType", type_it->mime_type); 2314 mime_type->SetStringFromUTF16(L"description", type_it->description); 2315 2316 ListValue* file_extensions = new ListValue(); 2317 for (std::vector<std::string>::const_iterator ext_it = 2318 type_it->file_extensions.begin(); 2319 ext_it != type_it->file_extensions.end(); 2320 ++ext_it) { 2321 file_extensions->Append(new StringValue(*ext_it)); 2322 } 2323 mime_type->Set(L"fileExtensions", file_extensions); 2324 2325 mime_types->Append(mime_type); 2326 } 2327 item->Set(L"mimeTypes", mime_types); 2328 items->Append(item); 2329 } 2330 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 2331 return_value->Set(L"plugins", items); // return_value owns items. 2332 2333 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get()); 2334} 2335 2336// Sample json input: 2337// { "command": "EnablePlugin", 2338// "path": "/Library/Internet Plug-Ins/Flash Player.plugin" } 2339void AutomationProvider::EnablePlugin(Browser* browser, 2340 DictionaryValue* args, 2341 IPC::Message* reply_message) { 2342 FilePath::StringType path; 2343 AutomationJSONReply reply(this, reply_message); 2344 if (!args->GetString(L"path", &path)) { 2345 reply.SendError("path not specified."); 2346 return; 2347 } else if (!NPAPI::PluginList::Singleton()->EnablePlugin(FilePath(path))) { 2348 reply.SendError(StringPrintf("Could not enable plugin for path %s.", 2349 path.c_str())); 2350 return; 2351 } 2352 reply.SendSuccess(NULL); 2353} 2354 2355// Sample json input: 2356// { "command": "DisablePlugin", 2357// "path": "/Library/Internet Plug-Ins/Flash Player.plugin" } 2358void AutomationProvider::DisablePlugin(Browser* browser, 2359 DictionaryValue* args, 2360 IPC::Message* reply_message) { 2361 FilePath::StringType path; 2362 AutomationJSONReply reply(this, reply_message); 2363 if (!args->GetString(L"path", &path)) { 2364 reply.SendError("path not specified."); 2365 return; 2366 } else if (!NPAPI::PluginList::Singleton()->DisablePlugin(FilePath(path))) { 2367 reply.SendError(StringPrintf("Could not disable plugin for path %s.", 2368 path.c_str())); 2369 return; 2370 } 2371 reply.SendSuccess(NULL); 2372} 2373 2374// Sample json input: 2375// { "command": "SaveTabContents", 2376// "tab_index": 0, 2377// "filename": <a full pathname> } 2378// Sample json output: 2379// {} 2380void AutomationProvider::SaveTabContents(Browser* browser, 2381 DictionaryValue* args, 2382 IPC::Message* reply_message) { 2383 int tab_index = 0; 2384 FilePath::StringType filename; 2385 FilePath::StringType parent_directory; 2386 TabContents* tab_contents = NULL; 2387 2388 if (!args->GetInteger(L"tab_index", &tab_index) || 2389 !args->GetString(L"filename", &filename)) { 2390 AutomationJSONReply(this, reply_message).SendError( 2391 "tab_index or filename param missing"); 2392 return; 2393 } else { 2394 tab_contents = browser->GetTabContentsAt(tab_index); 2395 if (!tab_contents) { 2396 AutomationJSONReply(this, reply_message).SendError( 2397 "no tab at tab_index"); 2398 return; 2399 } 2400 } 2401 // We're doing a SAVE_AS_ONLY_HTML so the the directory path isn't 2402 // used. Nevertheless, SavePackage requires it be valid. Sigh. 2403 parent_directory = FilePath(filename).DirName().value(); 2404 if (!tab_contents->SavePage(FilePath(filename), FilePath(parent_directory), 2405 SavePackage::SAVE_AS_ONLY_HTML)) { 2406 AutomationJSONReply(this, reply_message).SendError( 2407 "Could not initiate SavePage"); 2408 return; 2409 } 2410 // The observer will delete itself when done. 2411 new SavePackageNotificationObserver(tab_contents->save_package(), 2412 this, reply_message); 2413} 2414 2415// Refer to ImportSettings() in chrome/test/pyautolib/pyauto.py for sample 2416// json input. 2417// Sample json output: "{}" 2418void AutomationProvider::ImportSettings(Browser* browser, 2419 DictionaryValue* args, 2420 IPC::Message* reply_message) { 2421 // Map from the json string passed over to the import item masks. 2422 std::map<std::string, ImportItem> string_to_import_item; 2423 string_to_import_item["HISTORY"] = importer::HISTORY; 2424 string_to_import_item["FAVORITES"] = importer::FAVORITES; 2425 string_to_import_item["COOKIES"] = importer::COOKIES; 2426 string_to_import_item["PASSWORDS"] = importer::PASSWORDS; 2427 string_to_import_item["SEARCH_ENGINES"] = importer::SEARCH_ENGINES; 2428 string_to_import_item["HOME_PAGE"] = importer::HOME_PAGE; 2429 string_to_import_item["ALL"] = importer::ALL; 2430 2431 std::wstring browser_name; 2432 int import_items = 0; 2433 ListValue* import_items_list = NULL; 2434 bool first_run; 2435 2436 if (!args->GetString(L"import_from", &browser_name) || 2437 !args->GetBoolean(L"first_run", &first_run) || 2438 !args->GetList(L"import_items", &import_items_list)) { 2439 AutomationJSONReply(this, reply_message).SendError( 2440 "Incorrect type for one or more of the arguments."); 2441 return; 2442 } 2443 2444 int num_items = import_items_list->GetSize(); 2445 for (int i = 0; i < num_items; i++) { 2446 std::string item; 2447 import_items_list->GetString(i, &item); 2448 // If the provided string is not part of the map, error out. 2449 if (!ContainsKey(string_to_import_item, item)) { 2450 AutomationJSONReply(this, reply_message).SendError( 2451 "Invalid item string found in import_items."); 2452 return; 2453 } 2454 import_items |= string_to_import_item[item]; 2455 } 2456 2457 ImporterHost* importer_host = new ImporterHost(); 2458 // Get the correct ProfileInfo based on the browser they user provided. 2459 importer::ProfileInfo profile_info; 2460 int num_browsers = importer_host->GetAvailableProfileCount(); 2461 int i = 0; 2462 for ( ; i < num_browsers; i++) { 2463 std::wstring name = importer_host->GetSourceProfileNameAt(i); 2464 if (name == browser_name) { 2465 profile_info = importer_host->GetSourceProfileInfoAt(i); 2466 break; 2467 } 2468 } 2469 // If we made it to the end of the loop, then the input was bad. 2470 if (i == num_browsers) { 2471 AutomationJSONReply(this, reply_message).SendError( 2472 "Invalid browser name string found."); 2473 return; 2474 } 2475 2476 Profile* profile = browser->profile(); 2477 2478 importer_host->SetObserver( 2479 new AutomationProviderImportSettingsObserver(this, reply_message)); 2480 importer_host->StartImportSettings(profile_info, profile, import_items, 2481 new ProfileWriter(profile), first_run); 2482} 2483 2484// See AddSavedPassword() in chrome/test/functional/pyauto.py for sample json 2485// input. 2486// Sample json output: { "password_added": true } 2487void AutomationProvider::AddSavedPassword(Browser* browser, 2488 DictionaryValue* args, 2489 IPC::Message* reply_message) { 2490 string16 username; 2491 string16 password; 2492 base::Time time = base::Time::Now(); 2493 AutomationJSONReply reply(this, reply_message); 2494 2495 if (!args->GetStringAsUTF16(L"password", &password) || 2496 !args->GetStringAsUTF16(L"username", &username)) { 2497 reply.SendError("Username and password must be strings."); 2498 return; 2499 } 2500 2501 // If the time is specified, change time to the specified time. 2502 int it; 2503 double dt; 2504 if (args->GetInteger(L"time", &it)) 2505 time = base::Time::FromTimeT(it); 2506 else if (args->GetReal(L"time", &dt)) 2507 time = base::Time::FromDoubleT(dt); 2508 2509 webkit_glue::PasswordForm new_password; 2510 new_password.username_value = username; 2511 new_password.password_value = password; 2512 new_password.date_created = time; 2513 2514 Profile* profile = browser->profile(); 2515 // Use IMPLICIT_ACCESS since new passwords aren't added off the record. 2516 PasswordStore* password_store = 2517 profile->GetPasswordStore(Profile::IMPLICIT_ACCESS); 2518 2519 // Set the return based on whether setting the password succeeded. 2520 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 2521 2522 // It will be null if it's accessed in an incognito window. 2523 if (password_store != NULL) { 2524 password_store->AddLogin(new_password); 2525 return_value->SetBoolean(L"password_added", true); 2526 } else { 2527 return_value->SetBoolean(L"password_added", false); 2528 } 2529 2530 reply.SendSuccess(return_value.get()); 2531} 2532 2533// Sample json input: { "command": "GetSavedPasswords" } 2534// Refer to GetSavedPasswords() in chrome/test/pyautolib/pyauto.py for sample 2535// json output. 2536void AutomationProvider::GetSavedPasswords(Browser* browser, 2537 DictionaryValue* args, 2538 IPC::Message* reply_message) { 2539 Profile* profile = browser->profile(); 2540 // Use EXPLICIT_ACCESS since saved passwords can be retreived off the record. 2541 PasswordStore* password_store = 2542 profile->GetPasswordStore(Profile::EXPLICIT_ACCESS); 2543 password_store->GetAutofillableLogins( 2544 new AutomationProviderGetPasswordsObserver(this, reply_message)); 2545 // Observer deletes itself after returning. 2546} 2547 2548// Refer to ClearBrowsingData() in chrome/test/pyautolib/pyauto.py for sample 2549// json input. 2550// Sample json output: {} 2551void AutomationProvider::ClearBrowsingData(Browser* browser, 2552 DictionaryValue* args, 2553 IPC::Message* reply_message) { 2554 std::map<std::string, BrowsingDataRemover::TimePeriod> string_to_time_period; 2555 string_to_time_period["LAST_HOUR"] = BrowsingDataRemover::LAST_HOUR; 2556 string_to_time_period["LAST_DAY"] = BrowsingDataRemover::LAST_DAY; 2557 string_to_time_period["LAST_WEEK"] = BrowsingDataRemover::LAST_WEEK; 2558 string_to_time_period["FOUR_WEEKS"] = BrowsingDataRemover::FOUR_WEEKS; 2559 string_to_time_period["EVERYTHING"] = BrowsingDataRemover::EVERYTHING; 2560 2561 std::map<std::string, int> string_to_mask_value; 2562 string_to_mask_value["HISTORY"] = BrowsingDataRemover::REMOVE_HISTORY; 2563 string_to_mask_value["DOWNLOADS"] = BrowsingDataRemover::REMOVE_DOWNLOADS; 2564 string_to_mask_value["COOKIES"] = BrowsingDataRemover::REMOVE_COOKIES; 2565 string_to_mask_value["PASSWORDS"] = BrowsingDataRemover::REMOVE_PASSWORDS; 2566 string_to_mask_value["FORM_DATA"] = BrowsingDataRemover::REMOVE_FORM_DATA; 2567 string_to_mask_value["CACHE"] = BrowsingDataRemover::REMOVE_CACHE; 2568 2569 std::string time_period; 2570 ListValue* to_remove; 2571 if (!args->GetString(L"time_period", &time_period) || 2572 !args->GetList(L"to_remove", &to_remove)) { 2573 AutomationJSONReply(this, reply_message).SendError( 2574 "time_period must be a string and to_remove a list."); 2575 return; 2576 } 2577 2578 int remove_mask = 0; 2579 int num_removals = to_remove->GetSize(); 2580 for (int i = 0; i < num_removals; i++) { 2581 std::string removal; 2582 to_remove->GetString(i, &removal); 2583 // If the provided string is not part of the map, then error out. 2584 if (!ContainsKey(string_to_mask_value, removal)) { 2585 AutomationJSONReply(this, reply_message).SendError( 2586 "Invalid browsing data string found in to_remove."); 2587 return; 2588 } 2589 remove_mask |= string_to_mask_value[removal]; 2590 } 2591 2592 if (!ContainsKey(string_to_time_period, time_period)) { 2593 AutomationJSONReply(this, reply_message).SendError( 2594 "Invalid string for time_period."); 2595 return; 2596 } 2597 2598 BrowsingDataRemover* remover = new BrowsingDataRemover( 2599 profile(), string_to_time_period[time_period], base::Time()); 2600 2601 remover->AddObserver( 2602 new AutomationProviderBrowsingDataObserver(this, reply_message)); 2603 remover->Remove(remove_mask); 2604 // BrowsingDataRemover deletes itself using DeleteTask. 2605 // The observer also deletes itself after sending the reply. 2606} 2607 2608// Sample json input: { "command": "GetThemeInfo" } 2609// Refer GetThemeInfo() in chrome/test/pyautolib/pyauto.py for sample output. 2610void AutomationProvider::GetThemeInfo(Browser* browser, 2611 DictionaryValue* args, 2612 IPC::Message* reply_message) { 2613 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 2614 Extension* theme = browser->profile()->GetTheme(); 2615 if (theme) { 2616 return_value->SetString(L"name", theme->name()); 2617 return_value->Set(L"images", theme->GetThemeImages()->DeepCopy()); 2618 return_value->Set(L"colors", theme->GetThemeColors()->DeepCopy()); 2619 return_value->Set(L"tints", theme->GetThemeTints()->DeepCopy()); 2620 } 2621 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get()); 2622} 2623 2624// Sample json input: 2625// { "command": "GetAutoFillProfile" } 2626// Refer to GetAutoFillProfile() in chrome/test/pyautolib/pyauto.py for sample 2627// json output. 2628void AutomationProvider::GetAutoFillProfile(Browser* browser, 2629 DictionaryValue* args, 2630 IPC::Message* reply_message) { 2631 // Get the AutoFillProfiles currently in the database. 2632 int tab_index = 0; 2633 args->GetInteger(L"tab_index", &tab_index); 2634 TabContents* tab_contents = browser->GetTabContentsAt(tab_index); 2635 AutomationJSONReply reply(this, reply_message); 2636 2637 if (tab_contents) { 2638 PersonalDataManager* pdm = tab_contents->profile()->GetOriginalProfile() 2639 ->GetPersonalDataManager(); 2640 if (pdm) { 2641 std::vector<AutoFillProfile*> autofill_profiles = pdm->profiles(); 2642 std::vector<CreditCard*> credit_cards = pdm->credit_cards(); 2643 2644 ListValue* profiles = GetListFromAutoFillProfiles(autofill_profiles); 2645 ListValue* cards = GetListFromCreditCards(credit_cards); 2646 2647 scoped_ptr<DictionaryValue> return_value(new DictionaryValue); 2648 2649 return_value->Set(L"profiles", profiles); 2650 return_value->Set(L"credit_cards", cards); 2651 reply.SendSuccess(return_value.get()); 2652 } else { 2653 reply.SendError("No PersonalDataManager."); 2654 return; 2655 } 2656 } else { 2657 reply.SendError("No tab at that index."); 2658 return; 2659 } 2660} 2661 2662// Refer to FillAutoFillProfile() in chrome/test/pyautolib/pyauto.py for sample 2663// json input. 2664// Sample json output: {} 2665void AutomationProvider::FillAutoFillProfile(Browser* browser, 2666 DictionaryValue* args, 2667 IPC::Message* reply_message) { 2668 AutomationJSONReply reply(this, reply_message); 2669 ListValue* profiles = NULL; 2670 ListValue* cards = NULL; 2671 args->GetList(L"profiles", &profiles); 2672 args->GetList(L"credit_cards", &cards); 2673 std::string error_mesg; 2674 2675 std::vector<AutoFillProfile> autofill_profiles; 2676 std::vector<CreditCard> credit_cards; 2677 // Create an AutoFillProfile for each of the dictionary profiles. 2678 if (profiles) { 2679 autofill_profiles = GetAutoFillProfilesFromList(*profiles, &error_mesg); 2680 } 2681 // Create a CreditCard for each of the dictionary values. 2682 if (cards) { 2683 credit_cards = GetCreditCardsFromList(*cards, &error_mesg); 2684 } 2685 if (!error_mesg.empty()) { 2686 reply.SendError(error_mesg); 2687 return; 2688 } 2689 2690 // Save the AutoFillProfiles. 2691 int tab_index = 0; 2692 args->GetInteger(L"tab_index", &tab_index); 2693 TabContents* tab_contents = browser->GetTabContentsAt(tab_index); 2694 2695 if (tab_contents) { 2696 PersonalDataManager* pdm = tab_contents->profile() 2697 ->GetPersonalDataManager(); 2698 if (pdm) { 2699 pdm->OnAutoFillDialogApply(profiles? &autofill_profiles : NULL, 2700 cards? &credit_cards : NULL); 2701 } else { 2702 reply.SendError("No PersonalDataManager."); 2703 return; 2704 } 2705 } else { 2706 reply.SendError("No tab at that index."); 2707 return; 2708 } 2709 reply.SendSuccess(NULL); 2710} 2711 2712/* static */ 2713ListValue* AutomationProvider::GetListFromAutoFillProfiles( 2714 std::vector<AutoFillProfile*> autofill_profiles) { 2715 ListValue* profiles = new ListValue; 2716 2717 std::map<AutoFillFieldType, std::wstring> autofill_type_to_string 2718 = GetAutoFillFieldToStringMap(); 2719 2720 // For each AutoFillProfile, transform it to a dictionary object to return. 2721 for (std::vector<AutoFillProfile*>::iterator it = autofill_profiles.begin(); 2722 it != autofill_profiles.end(); ++it) { 2723 AutoFillProfile* profile = *it; 2724 DictionaryValue* profile_info = new DictionaryValue; 2725 profile_info->SetStringFromUTF16(L"label", profile->Label()); 2726 // For each of the types, if it has a value, add it to the dictionary. 2727 for (std::map<AutoFillFieldType, std::wstring>::iterator 2728 type_it = autofill_type_to_string.begin(); 2729 type_it != autofill_type_to_string.end(); ++type_it) { 2730 string16 value = profile->GetFieldText(AutoFillType(type_it->first)); 2731 if (value.length()) { // If there was something stored for that value. 2732 profile_info->SetStringFromUTF16(type_it->second, value); 2733 } 2734 } 2735 profiles->Append(profile_info); 2736 } 2737 return profiles; 2738} 2739 2740/* static */ 2741ListValue* AutomationProvider::GetListFromCreditCards( 2742 std::vector<CreditCard*> credit_cards) { 2743 ListValue* cards = new ListValue; 2744 2745 std::map<AutoFillFieldType, std::wstring> credit_card_type_to_string = 2746 GetCreditCardFieldToStringMap(); 2747 2748 // For each AutoFillProfile, transform it to a dictionary object to return. 2749 for (std::vector<CreditCard*>::iterator it = credit_cards.begin(); 2750 it != credit_cards.end(); ++it) { 2751 CreditCard* card = *it; 2752 DictionaryValue* card_info = new DictionaryValue; 2753 card_info->SetStringFromUTF16(L"label", card->Label()); 2754 // For each of the types, if it has a value, add it to the dictionary. 2755 for (std::map<AutoFillFieldType, std::wstring>::iterator type_it = 2756 credit_card_type_to_string.begin(); 2757 type_it != credit_card_type_to_string.end(); ++type_it) { 2758 string16 value = card->GetFieldText(AutoFillType(type_it->first)); 2759 // If there was something stored for that value. 2760 if (value.length()) { 2761 card_info->SetStringFromUTF16(type_it->second, value); 2762 } 2763 } 2764 cards->Append(card_info); 2765 } 2766 return cards; 2767} 2768 2769/* static */ 2770std::vector<AutoFillProfile> AutomationProvider::GetAutoFillProfilesFromList( 2771 const ListValue& profiles, std::string* error_message) { 2772 std::vector<AutoFillProfile> autofill_profiles; 2773 DictionaryValue* profile_info = NULL; 2774 string16 profile_label; 2775 string16 current_value; 2776 2777 std::map<AutoFillFieldType, std::wstring> autofill_type_to_string = 2778 GetAutoFillFieldToStringMap(); 2779 2780 int num_profiles = profiles.GetSize(); 2781 for (int i = 0; i < num_profiles; i++) { 2782 profiles.GetDictionary(i, &profile_info); 2783 profile_info->GetString("label", &profile_label); 2784 // Choose an id of 0 so that a unique id will be created. 2785 AutoFillProfile profile(profile_label, 0); 2786 // Loop through the possible profile types and add those provided. 2787 for (std::map<AutoFillFieldType, std::wstring>::iterator type_it = 2788 autofill_type_to_string.begin(); 2789 type_it != autofill_type_to_string.end(); ++type_it) { 2790 if (profile_info->HasKey(type_it->second)) { 2791 if (profile_info->GetStringAsUTF16(type_it->second, ¤t_value)) { 2792 profile.SetInfo(AutoFillType(type_it->first), current_value); 2793 } else { 2794 *error_message= "All values must be strings"; 2795 break; 2796 } 2797 } 2798 } 2799 autofill_profiles.push_back(profile); 2800 } 2801 return autofill_profiles; 2802} 2803 2804/* static */ 2805std::vector<CreditCard> AutomationProvider::GetCreditCardsFromList( 2806 const ListValue& cards, std::string* error_message) { 2807 std::vector<CreditCard> credit_cards; 2808 DictionaryValue* card_info = NULL; 2809 string16 card_label; 2810 string16 current_value; 2811 2812 std::map<AutoFillFieldType, std::wstring> credit_card_type_to_string = 2813 GetCreditCardFieldToStringMap(); 2814 2815 int num_credit_cards = cards.GetSize(); 2816 for (int i = 0; i < num_credit_cards; i++) { 2817 cards.GetDictionary(i, &card_info); 2818 card_info->GetString("label", &card_label); 2819 CreditCard card(card_label, 0); 2820 // Loop through the possible credit card fields and add those provided. 2821 for (std::map<AutoFillFieldType, std::wstring>::iterator type_it = 2822 credit_card_type_to_string.begin(); 2823 type_it != credit_card_type_to_string.end(); ++type_it) { 2824 if (card_info->HasKey(type_it->second)) { 2825 if (card_info->GetStringAsUTF16(type_it->second, ¤t_value)) { 2826 card.SetInfo(AutoFillType(type_it->first), current_value); 2827 } else { 2828 *error_message= "All values must be strings"; 2829 break; 2830 } 2831 } 2832 } 2833 credit_cards.push_back(card); 2834 } 2835 return credit_cards; 2836} 2837 2838/* static */ 2839std::map<AutoFillFieldType, std::wstring> 2840 AutomationProvider::GetAutoFillFieldToStringMap() { 2841 std::map<AutoFillFieldType, std::wstring> autofill_type_to_string; 2842 autofill_type_to_string[NAME_FIRST] = L"NAME_FIRST"; 2843 autofill_type_to_string[NAME_MIDDLE] = L"NAME_MIDDLE"; 2844 autofill_type_to_string[NAME_LAST] = L"NAME_LAST"; 2845 autofill_type_to_string[COMPANY_NAME] = L"COMPANY_NAME"; 2846 autofill_type_to_string[EMAIL_ADDRESS] = L"EMAIL_ADDRESS"; 2847 autofill_type_to_string[ADDRESS_HOME_LINE1] = L"ADDRESS_HOME_LINE1"; 2848 autofill_type_to_string[ADDRESS_HOME_LINE2] = L"ADDRESS_HOME_LINE2"; 2849 autofill_type_to_string[ADDRESS_HOME_CITY] = L"ADDRESS_HOME_CITY"; 2850 autofill_type_to_string[ADDRESS_HOME_STATE] = L"ADDRESS_HOME_STATE"; 2851 autofill_type_to_string[ADDRESS_HOME_ZIP] = L"ADDRESS_HOME_ZIP"; 2852 autofill_type_to_string[ADDRESS_HOME_COUNTRY] = L"ADDRESS_HOME_COUNTRY"; 2853 autofill_type_to_string[PHONE_HOME_NUMBER] = L"PHONE_HOME_NUMBER"; 2854 autofill_type_to_string[PHONE_FAX_NUMBER] = L"PHONE_FAX_NUMBER"; 2855 autofill_type_to_string[NAME_FIRST] = L"NAME_FIRST"; 2856 return autofill_type_to_string; 2857} 2858 2859/* static */ 2860std::map<AutoFillFieldType, std::wstring> 2861 AutomationProvider::GetCreditCardFieldToStringMap() { 2862 std::map<AutoFillFieldType, std::wstring> credit_card_type_to_string; 2863 credit_card_type_to_string[CREDIT_CARD_NAME] = L"CREDIT_CARD_NAME"; 2864 credit_card_type_to_string[CREDIT_CARD_NUMBER] = L"CREDIT_CARD_NUMBER"; 2865 credit_card_type_to_string[CREDIT_CARD_TYPE] = L"CREDIT_CARD_TYPE"; 2866 credit_card_type_to_string[CREDIT_CARD_EXP_MONTH] = L"CREDIT_CARD_EXP_MONTH"; 2867 credit_card_type_to_string[CREDIT_CARD_EXP_4_DIGIT_YEAR] = 2868 L"CREDIT_CARD_EXP_4_DIGIT_YEAR"; 2869 return credit_card_type_to_string; 2870} 2871 2872void AutomationProvider::SendJSONRequest(int handle, 2873 std::string json_request, 2874 IPC::Message* reply_message) { 2875 Browser* browser = NULL; 2876 scoped_ptr<Value> values; 2877 2878 // Basic error checking. 2879 if (browser_tracker_->ContainsHandle(handle)) { 2880 browser = browser_tracker_->GetResource(handle); 2881 } 2882 if (!browser) { 2883 AutomationJSONReply(this, reply_message).SendError("no browser object"); 2884 return; 2885 } 2886 base::JSONReader reader; 2887 std::string error; 2888 values.reset(reader.ReadAndReturnError(json_request, true, NULL, &error)); 2889 if (!error.empty()) { 2890 AutomationJSONReply(this, reply_message).SendError(error); 2891 return; 2892 } 2893 2894 // Make sure input is a dict with a string command. 2895 std::string command; 2896 DictionaryValue* dict_value = NULL; 2897 if (values->GetType() != Value::TYPE_DICTIONARY) { 2898 AutomationJSONReply(this, reply_message).SendError("not a dict"); 2899 return; 2900 } 2901 // Ownership remains with "values" variable. 2902 dict_value = static_cast<DictionaryValue*>(values.get()); 2903 if (!dict_value->GetStringASCII(std::string("command"), &command)) { 2904 AutomationJSONReply(this, reply_message).SendError( 2905 "no command key in dict or not a string command"); 2906 return; 2907 } 2908 2909 // Map json commands to their handlers. 2910 std::map<std::string, JsonHandler> handler_map; 2911 handler_map["DisablePlugin"] = &AutomationProvider::DisablePlugin; 2912 handler_map["EnablePlugin"] = &AutomationProvider::EnablePlugin; 2913 handler_map["GetPluginsInfo"] = &AutomationProvider::GetPluginsInfo; 2914 2915 handler_map["GetBrowserInfo"] = &AutomationProvider::GetBrowserInfo; 2916 2917 handler_map["WaitForInfobarCount"] = &AutomationProvider::WaitForInfobarCount; 2918 2919 handler_map["GetHistoryInfo"] = &AutomationProvider::GetHistoryInfo; 2920 handler_map["AddHistoryItem"] = &AutomationProvider::AddHistoryItem; 2921 2922 handler_map["GetOmniboxInfo"] = &AutomationProvider::GetOmniboxInfo; 2923 handler_map["SetOmniboxText"] = &AutomationProvider::SetOmniboxText; 2924 handler_map["OmniboxAcceptInput"] = &AutomationProvider::OmniboxAcceptInput; 2925 handler_map["OmniboxMovePopupSelection"] = 2926 &AutomationProvider::OmniboxMovePopupSelection; 2927 2928 handler_map["GetPrefsInfo"] = &AutomationProvider::GetPrefsInfo; 2929 handler_map["SetPrefs"] = &AutomationProvider::SetPrefs; 2930 2931 handler_map["SetWindowDimensions"] = &AutomationProvider::SetWindowDimensions; 2932 2933 handler_map["GetDownloadsInfo"] = &AutomationProvider::GetDownloadsInfo; 2934 handler_map["WaitForAllDownloadsToComplete"] = 2935 &AutomationProvider::WaitForDownloadsToComplete; 2936 2937 handler_map["GetInitialLoadTimes"] = &AutomationProvider::GetInitialLoadTimes; 2938 2939 handler_map["SaveTabContents"] = &AutomationProvider::SaveTabContents; 2940 2941 handler_map["ImportSettings"] = &AutomationProvider::ImportSettings; 2942 2943 handler_map["AddSavedPassword"] = &AutomationProvider::AddSavedPassword; 2944 handler_map["GetSavedPasswords"] = &AutomationProvider::GetSavedPasswords; 2945 2946 handler_map["ClearBrowsingData"] = &AutomationProvider::ClearBrowsingData; 2947 2948 // SetTheme() implemented using InstallExtension(). 2949 handler_map["GetThemeInfo"] = &AutomationProvider::GetThemeInfo; 2950 2951 handler_map["GetAutoFillProfile"] = &AutomationProvider::GetAutoFillProfile; 2952 handler_map["FillAutoFillProfile"] = &AutomationProvider::FillAutoFillProfile; 2953 2954 if (handler_map.find(std::string(command)) != handler_map.end()) { 2955 (this->*handler_map[command])(browser, dict_value, reply_message); 2956 } else { 2957 std::string error_string = "Unknown command. Options: "; 2958 for (std::map<std::string, JsonHandler>::const_iterator it = 2959 handler_map.begin(); it != handler_map.end(); ++it) { 2960 error_string += it->first + ", "; 2961 } 2962 AutomationJSONReply(this, reply_message).SendError(error_string); 2963 } 2964} 2965 2966void AutomationProvider::HandleInspectElementRequest( 2967 int handle, int x, int y, IPC::Message* reply_message) { 2968 TabContents* tab_contents = GetTabContentsForHandle(handle, NULL); 2969 if (tab_contents) { 2970 DCHECK(reply_message_ == NULL); 2971 reply_message_ = reply_message; 2972 2973 DevToolsManager::GetInstance()->InspectElement( 2974 tab_contents->render_view_host(), x, y); 2975 } else { 2976 AutomationMsg_InspectElement::WriteReplyParams(reply_message, -1); 2977 Send(reply_message); 2978 } 2979} 2980 2981void AutomationProvider::ReceivedInspectElementResponse(int num_resources) { 2982 if (reply_message_) { 2983 AutomationMsg_InspectElement::WriteReplyParams(reply_message_, 2984 num_resources); 2985 Send(reply_message_); 2986 reply_message_ = NULL; 2987 } 2988} 2989 2990class SetProxyConfigTask : public Task { 2991 public: 2992 SetProxyConfigTask(URLRequestContextGetter* request_context_getter, 2993 const std::string& new_proxy_config) 2994 : request_context_getter_(request_context_getter), 2995 proxy_config_(new_proxy_config) {} 2996 virtual void Run() { 2997 // First, deserialize the JSON string. If this fails, log and bail. 2998 JSONStringValueSerializer deserializer(proxy_config_); 2999 std::string error_msg; 3000 scoped_ptr<Value> root(deserializer.Deserialize(NULL, &error_msg)); 3001 if (!root.get() || root->GetType() != Value::TYPE_DICTIONARY) { 3002 DLOG(WARNING) << "Received bad JSON string for ProxyConfig: " 3003 << error_msg; 3004 return; 3005 } 3006 3007 scoped_ptr<DictionaryValue> dict( 3008 static_cast<DictionaryValue*>(root.release())); 3009 // Now put together a proxy configuration from the deserialized string. 3010 net::ProxyConfig pc; 3011 PopulateProxyConfig(*dict.get(), &pc); 3012 3013 net::ProxyService* proxy_service = 3014 request_context_getter_->GetURLRequestContext()->proxy_service(); 3015 DCHECK(proxy_service); 3016 scoped_ptr<net::ProxyConfigService> proxy_config_service( 3017 new net::ProxyConfigServiceFixed(pc)); 3018 proxy_service->ResetConfigService(proxy_config_service.release()); 3019 } 3020 3021 void PopulateProxyConfig(const DictionaryValue& dict, net::ProxyConfig* pc) { 3022 DCHECK(pc); 3023 bool no_proxy = false; 3024 if (dict.GetBoolean(automation::kJSONProxyNoProxy, &no_proxy)) { 3025 // Make no changes to the ProxyConfig. 3026 return; 3027 } 3028 bool auto_config; 3029 if (dict.GetBoolean(automation::kJSONProxyAutoconfig, &auto_config)) { 3030 pc->set_auto_detect(true); 3031 } 3032 std::string pac_url; 3033 if (dict.GetString(automation::kJSONProxyPacUrl, &pac_url)) { 3034 pc->set_pac_url(GURL(pac_url)); 3035 } 3036 std::string proxy_bypass_list; 3037 if (dict.GetString(automation::kJSONProxyBypassList, &proxy_bypass_list)) { 3038 pc->proxy_rules().bypass_rules.ParseFromString(proxy_bypass_list); 3039 } 3040 std::string proxy_server; 3041 if (dict.GetString(automation::kJSONProxyServer, &proxy_server)) { 3042 pc->proxy_rules().ParseFromString(proxy_server); 3043 } 3044 } 3045 3046 private: 3047 scoped_refptr<URLRequestContextGetter> request_context_getter_; 3048 std::string proxy_config_; 3049}; 3050 3051 3052void AutomationProvider::SetProxyConfig(const std::string& new_proxy_config) { 3053 URLRequestContextGetter* context_getter = Profile::GetDefaultRequestContext(); 3054 if (!context_getter) { 3055 FilePath user_data_dir; 3056 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); 3057 ProfileManager* profile_manager = g_browser_process->profile_manager(); 3058 DCHECK(profile_manager); 3059 Profile* profile = profile_manager->GetDefaultProfile(user_data_dir); 3060 DCHECK(profile); 3061 context_getter = profile->GetRequestContext(); 3062 } 3063 DCHECK(context_getter); 3064 3065 ChromeThread::PostTask( 3066 ChromeThread::IO, FROM_HERE, 3067 new SetProxyConfigTask(context_getter, new_proxy_config)); 3068} 3069 3070void AutomationProvider::GetDownloadDirectory( 3071 int handle, FilePath* download_directory) { 3072 DLOG(INFO) << "Handling download directory request"; 3073 if (tab_tracker_->ContainsHandle(handle)) { 3074 NavigationController* tab = tab_tracker_->GetResource(handle); 3075 DownloadManager* dlm = tab->profile()->GetDownloadManager(); 3076 DCHECK(dlm); 3077 *download_directory = dlm->download_path(); 3078 } 3079} 3080 3081void AutomationProvider::OpenNewBrowserWindow(bool show, 3082 IPC::Message* reply_message) { 3083 OpenNewBrowserWindowOfType(static_cast<int>(Browser::TYPE_NORMAL), show, 3084 reply_message); 3085} 3086 3087void AutomationProvider::OpenNewBrowserWindowOfType( 3088 int type, bool show, IPC::Message* reply_message) { 3089 new BrowserOpenedNotificationObserver(this, reply_message); 3090 // We may have no current browser windows open so don't rely on 3091 // asking an existing browser to execute the IDC_NEWWINDOW command 3092 Browser* browser = new Browser(static_cast<Browser::Type>(type), profile_); 3093 browser->CreateBrowserWindow(); 3094 browser->AddBlankTab(true); 3095 if (show) 3096 browser->window()->Show(); 3097} 3098 3099void AutomationProvider::GetWindowForBrowser(int browser_handle, 3100 bool* success, 3101 int* handle) { 3102 *success = false; 3103 *handle = 0; 3104 3105 if (browser_tracker_->ContainsHandle(browser_handle)) { 3106 Browser* browser = browser_tracker_->GetResource(browser_handle); 3107 gfx::NativeWindow win = browser->window()->GetNativeHandle(); 3108 // Add() returns the existing handle for the resource if any. 3109 *handle = window_tracker_->Add(win); 3110 *success = true; 3111 } 3112} 3113 3114void AutomationProvider::GetAutocompleteEditForBrowser( 3115 int browser_handle, 3116 bool* success, 3117 int* autocomplete_edit_handle) { 3118 *success = false; 3119 *autocomplete_edit_handle = 0; 3120 3121 if (browser_tracker_->ContainsHandle(browser_handle)) { 3122 Browser* browser = browser_tracker_->GetResource(browser_handle); 3123 LocationBar* loc_bar = browser->window()->GetLocationBar(); 3124 AutocompleteEditView* edit_view = loc_bar->location_entry(); 3125 // Add() returns the existing handle for the resource if any. 3126 *autocomplete_edit_handle = autocomplete_edit_tracker_->Add(edit_view); 3127 *success = true; 3128 } 3129} 3130 3131void AutomationProvider::ShowInterstitialPage(int tab_handle, 3132 const std::string& html_text, 3133 IPC::Message* reply_message) { 3134 if (tab_tracker_->ContainsHandle(tab_handle)) { 3135 NavigationController* controller = tab_tracker_->GetResource(tab_handle); 3136 TabContents* tab_contents = controller->tab_contents(); 3137 3138 AddNavigationStatusListener(controller, reply_message, 1, false); 3139 AutomationInterstitialPage* interstitial = 3140 new AutomationInterstitialPage(tab_contents, 3141 GURL("about:interstitial"), 3142 html_text); 3143 interstitial->Show(); 3144 return; 3145 } 3146 3147 AutomationMsg_ShowInterstitialPage::WriteReplyParams( 3148 reply_message, AUTOMATION_MSG_NAVIGATION_ERROR); 3149 Send(reply_message); 3150} 3151 3152void AutomationProvider::HideInterstitialPage(int tab_handle, 3153 bool* success) { 3154 *success = false; 3155 TabContents* tab_contents = GetTabContentsForHandle(tab_handle, NULL); 3156 if (tab_contents && tab_contents->interstitial_page()) { 3157 tab_contents->interstitial_page()->DontProceed(); 3158 *success = true; 3159 } 3160} 3161 3162void AutomationProvider::CloseTab(int tab_handle, 3163 bool wait_until_closed, 3164 IPC::Message* reply_message) { 3165 if (tab_tracker_->ContainsHandle(tab_handle)) { 3166 NavigationController* controller = tab_tracker_->GetResource(tab_handle); 3167 int index; 3168 Browser* browser = Browser::GetBrowserForController(controller, &index); 3169 DCHECK(browser); 3170 new TabClosedNotificationObserver(this, wait_until_closed, reply_message); 3171 browser->CloseContents(controller->tab_contents()); 3172 return; 3173 } 3174 3175 AutomationMsg_CloseTab::WriteReplyParams(reply_message, false); 3176 Send(reply_message); 3177} 3178 3179void AutomationProvider::CloseBrowser(int browser_handle, 3180 IPC::Message* reply_message) { 3181 if (browser_tracker_->ContainsHandle(browser_handle)) { 3182 Browser* browser = browser_tracker_->GetResource(browser_handle); 3183 new BrowserClosedNotificationObserver(browser, this, 3184 reply_message); 3185 browser->window()->Close(); 3186 } else { 3187 NOTREACHED(); 3188 } 3189} 3190 3191void AutomationProvider::CloseBrowserAsync(int browser_handle) { 3192 if (browser_tracker_->ContainsHandle(browser_handle)) { 3193 Browser* browser = browser_tracker_->GetResource(browser_handle); 3194 browser->window()->Close(); 3195 } else { 3196 NOTREACHED(); 3197 } 3198} 3199 3200void AutomationProvider::WaitForTabToBeRestored(int tab_handle, 3201 IPC::Message* reply_message) { 3202 if (tab_tracker_->ContainsHandle(tab_handle)) { 3203 NavigationController* tab = tab_tracker_->GetResource(tab_handle); 3204 restore_tracker_.reset( 3205 new NavigationControllerRestoredObserver(this, tab, reply_message)); 3206 } 3207} 3208 3209void AutomationProvider::GetSecurityState(int handle, bool* success, 3210 SecurityStyle* security_style, 3211 int* ssl_cert_status, 3212 int* insecure_content_status) { 3213 if (tab_tracker_->ContainsHandle(handle)) { 3214 NavigationController* tab = tab_tracker_->GetResource(handle); 3215 NavigationEntry* entry = tab->GetActiveEntry(); 3216 *success = true; 3217 *security_style = entry->ssl().security_style(); 3218 *ssl_cert_status = entry->ssl().cert_status(); 3219 *insecure_content_status = entry->ssl().content_status(); 3220 } else { 3221 *success = false; 3222 *security_style = SECURITY_STYLE_UNKNOWN; 3223 *ssl_cert_status = 0; 3224 *insecure_content_status = 0; 3225 } 3226} 3227 3228void AutomationProvider::GetPageType(int handle, bool* success, 3229 NavigationEntry::PageType* page_type) { 3230 if (tab_tracker_->ContainsHandle(handle)) { 3231 NavigationController* tab = tab_tracker_->GetResource(handle); 3232 NavigationEntry* entry = tab->GetActiveEntry(); 3233 *page_type = entry->page_type(); 3234 *success = true; 3235 // In order to return the proper result when an interstitial is shown and 3236 // no navigation entry were created for it we need to ask the TabContents. 3237 if (*page_type == NavigationEntry::NORMAL_PAGE && 3238 tab->tab_contents()->showing_interstitial_page()) 3239 *page_type = NavigationEntry::INTERSTITIAL_PAGE; 3240 } else { 3241 *success = false; 3242 *page_type = NavigationEntry::NORMAL_PAGE; 3243 } 3244} 3245 3246void AutomationProvider::GetMetricEventDuration(const std::string& event_name, 3247 int* duration_ms) { 3248 *duration_ms = metric_event_duration_observer_->GetEventDurationMs( 3249 event_name); 3250} 3251 3252void AutomationProvider::ActionOnSSLBlockingPage(int handle, bool proceed, 3253 IPC::Message* reply_message) { 3254 if (tab_tracker_->ContainsHandle(handle)) { 3255 NavigationController* tab = tab_tracker_->GetResource(handle); 3256 NavigationEntry* entry = tab->GetActiveEntry(); 3257 if (entry->page_type() == NavigationEntry::INTERSTITIAL_PAGE) { 3258 TabContents* tab_contents = tab->tab_contents(); 3259 InterstitialPage* ssl_blocking_page = 3260 InterstitialPage::GetInterstitialPage(tab_contents); 3261 if (ssl_blocking_page) { 3262 if (proceed) { 3263 AddNavigationStatusListener(tab, reply_message, 1, false); 3264 ssl_blocking_page->Proceed(); 3265 return; 3266 } 3267 ssl_blocking_page->DontProceed(); 3268 AutomationMsg_ActionOnSSLBlockingPage::WriteReplyParams( 3269 reply_message, AUTOMATION_MSG_NAVIGATION_SUCCESS); 3270 Send(reply_message); 3271 return; 3272 } 3273 } 3274 } 3275 // We failed. 3276 AutomationMsg_ActionOnSSLBlockingPage::WriteReplyParams( 3277 reply_message, AUTOMATION_MSG_NAVIGATION_ERROR); 3278 Send(reply_message); 3279} 3280 3281void AutomationProvider::BringBrowserToFront(int browser_handle, 3282 bool* success) { 3283 if (browser_tracker_->ContainsHandle(browser_handle)) { 3284 Browser* browser = browser_tracker_->GetResource(browser_handle); 3285 browser->window()->Activate(); 3286 *success = true; 3287 } else { 3288 *success = false; 3289 } 3290} 3291 3292void AutomationProvider::IsMenuCommandEnabled(int browser_handle, 3293 int message_num, 3294 bool* menu_item_enabled) { 3295 if (browser_tracker_->ContainsHandle(browser_handle)) { 3296 Browser* browser = browser_tracker_->GetResource(browser_handle); 3297 *menu_item_enabled = 3298 browser->command_updater()->IsCommandEnabled(message_num); 3299 } else { 3300 *menu_item_enabled = false; 3301 } 3302} 3303 3304void AutomationProvider::PrintNow(int tab_handle, 3305 IPC::Message* reply_message) { 3306 NavigationController* tab = NULL; 3307 TabContents* tab_contents = GetTabContentsForHandle(tab_handle, &tab); 3308 if (tab_contents) { 3309 FindAndActivateTab(tab); 3310 notification_observer_list_.AddObserver( 3311 new DocumentPrintedNotificationObserver(this, reply_message)); 3312 if (tab_contents->PrintNow()) 3313 return; 3314 } 3315 AutomationMsg_PrintNow::WriteReplyParams(reply_message, false); 3316 Send(reply_message); 3317} 3318 3319void AutomationProvider::SavePage(int tab_handle, 3320 const FilePath& file_name, 3321 const FilePath& dir_path, 3322 int type, 3323 bool* success) { 3324 if (!tab_tracker_->ContainsHandle(tab_handle)) { 3325 *success = false; 3326 return; 3327 } 3328 3329 NavigationController* nav = tab_tracker_->GetResource(tab_handle); 3330 Browser* browser = FindAndActivateTab(nav); 3331 DCHECK(browser); 3332 if (!browser->command_updater()->IsCommandEnabled(IDC_SAVE_PAGE)) { 3333 *success = false; 3334 return; 3335 } 3336 3337 SavePackage::SavePackageType save_type = 3338 static_cast<SavePackage::SavePackageType>(type); 3339 DCHECK(save_type >= SavePackage::SAVE_AS_ONLY_HTML && 3340 save_type <= SavePackage::SAVE_AS_COMPLETE_HTML); 3341 nav->tab_contents()->SavePage(file_name, dir_path, save_type); 3342 3343 *success = true; 3344} 3345 3346void AutomationProvider::GetAutocompleteEditText(int autocomplete_edit_handle, 3347 bool* success, 3348 std::wstring* text) { 3349 *success = false; 3350 if (autocomplete_edit_tracker_->ContainsHandle(autocomplete_edit_handle)) { 3351 *text = autocomplete_edit_tracker_->GetResource(autocomplete_edit_handle)-> 3352 GetText(); 3353 *success = true; 3354 } 3355} 3356 3357void AutomationProvider::SetAutocompleteEditText(int autocomplete_edit_handle, 3358 const std::wstring& text, 3359 bool* success) { 3360 *success = false; 3361 if (autocomplete_edit_tracker_->ContainsHandle(autocomplete_edit_handle)) { 3362 autocomplete_edit_tracker_->GetResource(autocomplete_edit_handle)-> 3363 SetUserText(text); 3364 *success = true; 3365 } 3366} 3367 3368void AutomationProvider::AutocompleteEditGetMatches( 3369 int autocomplete_edit_handle, 3370 bool* success, 3371 std::vector<AutocompleteMatchData>* matches) { 3372 *success = false; 3373 if (autocomplete_edit_tracker_->ContainsHandle(autocomplete_edit_handle)) { 3374 const AutocompleteResult& result = autocomplete_edit_tracker_-> 3375 GetResource(autocomplete_edit_handle)->model()->result(); 3376 for (AutocompleteResult::const_iterator i = result.begin(); 3377 i != result.end(); ++i) 3378 matches->push_back(AutocompleteMatchData(*i)); 3379 *success = true; 3380 } 3381} 3382 3383void AutomationProvider::AutocompleteEditIsQueryInProgress( 3384 int autocomplete_edit_handle, 3385 bool* success, 3386 bool* query_in_progress) { 3387 *success = false; 3388 *query_in_progress = false; 3389 if (autocomplete_edit_tracker_->ContainsHandle(autocomplete_edit_handle)) { 3390 *query_in_progress = autocomplete_edit_tracker_-> 3391 GetResource(autocomplete_edit_handle)->model()->query_in_progress(); 3392 *success = true; 3393 } 3394} 3395 3396#if !defined(OS_MACOSX) 3397 3398#endif // !defined(OS_MACOSX) 3399 3400TabContents* AutomationProvider::GetTabContentsForHandle( 3401 int handle, NavigationController** tab) { 3402 if (tab_tracker_->ContainsHandle(handle)) { 3403 NavigationController* nav_controller = tab_tracker_->GetResource(handle); 3404 if (tab) 3405 *tab = nav_controller; 3406 return nav_controller->tab_contents(); 3407 } 3408 return NULL; 3409} 3410 3411TestingAutomationProvider::TestingAutomationProvider(Profile* profile) 3412 : AutomationProvider(profile) { 3413 BrowserList::AddObserver(this); 3414 registrar_.Add(this, NotificationType::SESSION_END, 3415 NotificationService::AllSources()); 3416} 3417 3418TestingAutomationProvider::~TestingAutomationProvider() { 3419 BrowserList::RemoveObserver(this); 3420} 3421 3422void TestingAutomationProvider::OnChannelError() { 3423 BrowserList::CloseAllBrowsersAndExit(); 3424 AutomationProvider::OnChannelError(); 3425} 3426 3427void TestingAutomationProvider::OnBrowserAdded(const Browser* browser) { 3428} 3429 3430void TestingAutomationProvider::OnBrowserRemoving(const Browser* browser) { 3431 // For backwards compatibility with the testing automation interface, we 3432 // want the automation provider (and hence the process) to go away when the 3433 // last browser goes away. 3434 if (BrowserList::size() == 1 && !CommandLine::ForCurrentProcess()->HasSwitch( 3435 switches::kKeepAliveForTest)) { 3436 // If you change this, update Observer for NotificationType::SESSION_END 3437 // below. 3438 MessageLoop::current()->PostTask(FROM_HERE, 3439 NewRunnableMethod(this, &TestingAutomationProvider::OnRemoveProvider)); 3440 } 3441} 3442 3443void TestingAutomationProvider::Observe(NotificationType type, 3444 const NotificationSource& source, 3445 const NotificationDetails& details) { 3446 DCHECK(type == NotificationType::SESSION_END); 3447 // OnBrowserRemoving does a ReleaseLater. When session end is received we exit 3448 // before the task runs resulting in this object not being deleted. This 3449 // Release balance out the Release scheduled by OnBrowserRemoving. 3450 Release(); 3451} 3452 3453void TestingAutomationProvider::OnRemoveProvider() { 3454 AutomationProviderList::GetInstance()->RemoveProvider(this); 3455} 3456 3457void AutomationProvider::GetInfoBarCount(int handle, int* count) { 3458 *count = -1; // -1 means error. 3459 if (tab_tracker_->ContainsHandle(handle)) { 3460 NavigationController* nav_controller = tab_tracker_->GetResource(handle); 3461 if (nav_controller) 3462 *count = nav_controller->tab_contents()->infobar_delegate_count(); 3463 } 3464} 3465 3466void AutomationProvider::ClickInfoBarAccept(int handle, 3467 int info_bar_index, 3468 bool wait_for_navigation, 3469 IPC::Message* reply_message) { 3470 bool success = false; 3471 if (tab_tracker_->ContainsHandle(handle)) { 3472 NavigationController* nav_controller = tab_tracker_->GetResource(handle); 3473 if (nav_controller) { 3474 int count = nav_controller->tab_contents()->infobar_delegate_count(); 3475 if (info_bar_index >= 0 && info_bar_index < count) { 3476 if (wait_for_navigation) { 3477 AddNavigationStatusListener(nav_controller, reply_message, 1, false); 3478 } 3479 InfoBarDelegate* delegate = 3480 nav_controller->tab_contents()->GetInfoBarDelegateAt( 3481 info_bar_index); 3482 if (delegate->AsConfirmInfoBarDelegate()) 3483 delegate->AsConfirmInfoBarDelegate()->Accept(); 3484 success = true; 3485 } 3486 } 3487 } 3488 3489 // This "!wait_for_navigation || !success condition" logic looks suspicious. 3490 // It will send a failure message when success is true but 3491 // |wait_for_navigation| is false. 3492 // TODO(phajdan.jr): investgate whether the reply param (currently 3493 // AUTOMATION_MSG_NAVIGATION_ERROR) should depend on success. 3494 if (!wait_for_navigation || !success) 3495 AutomationMsg_ClickInfoBarAccept::WriteReplyParams( 3496 reply_message, AUTOMATION_MSG_NAVIGATION_ERROR); 3497} 3498 3499void AutomationProvider::GetLastNavigationTime(int handle, 3500 int64* last_navigation_time) { 3501 Time time = tab_tracker_->GetLastNavigationTime(handle); 3502 *last_navigation_time = time.ToInternalValue(); 3503} 3504 3505void AutomationProvider::WaitForNavigation(int handle, 3506 int64 last_navigation_time, 3507 IPC::Message* reply_message) { 3508 NavigationController* controller = tab_tracker_->GetResource(handle); 3509 Time time = tab_tracker_->GetLastNavigationTime(handle); 3510 3511 if (time.ToInternalValue() > last_navigation_time || !controller) { 3512 AutomationMsg_WaitForNavigation::WriteReplyParams(reply_message, 3513 controller == NULL ? AUTOMATION_MSG_NAVIGATION_ERROR : 3514 AUTOMATION_MSG_NAVIGATION_SUCCESS); 3515 Send(reply_message); 3516 return; 3517 } 3518 3519 AddNavigationStatusListener(controller, reply_message, 1, true); 3520} 3521 3522void AutomationProvider::SetIntPreference(int handle, 3523 const std::wstring& name, 3524 int value, 3525 bool* success) { 3526 *success = false; 3527 if (browser_tracker_->ContainsHandle(handle)) { 3528 Browser* browser = browser_tracker_->GetResource(handle); 3529 browser->profile()->GetPrefs()->SetInteger(name.c_str(), value); 3530 *success = true; 3531 } 3532} 3533 3534void AutomationProvider::SetStringPreference(int handle, 3535 const std::wstring& name, 3536 const std::string& value, 3537 bool* success) { 3538 *success = false; 3539 if (browser_tracker_->ContainsHandle(handle)) { 3540 Browser* browser = browser_tracker_->GetResource(handle); 3541 browser->profile()->GetPrefs()->SetString(name.c_str(), value); 3542 *success = true; 3543 } 3544} 3545 3546void AutomationProvider::GetBooleanPreference(int handle, 3547 const std::wstring& name, 3548 bool* success, 3549 bool* value) { 3550 *success = false; 3551 *value = false; 3552 if (browser_tracker_->ContainsHandle(handle)) { 3553 Browser* browser = browser_tracker_->GetResource(handle); 3554 *value = browser->profile()->GetPrefs()->GetBoolean(name.c_str()); 3555 *success = true; 3556 } 3557} 3558 3559void AutomationProvider::SetBooleanPreference(int handle, 3560 const std::wstring& name, 3561 bool value, 3562 bool* success) { 3563 *success = false; 3564 if (browser_tracker_->ContainsHandle(handle)) { 3565 Browser* browser = browser_tracker_->GetResource(handle); 3566 browser->profile()->GetPrefs()->SetBoolean(name.c_str(), value); 3567 *success = true; 3568 } 3569} 3570 3571// Gets the current used encoding name of the page in the specified tab. 3572void AutomationProvider::GetPageCurrentEncoding( 3573 int tab_handle, std::string* current_encoding) { 3574 if (tab_tracker_->ContainsHandle(tab_handle)) { 3575 NavigationController* nav = tab_tracker_->GetResource(tab_handle); 3576 Browser* browser = FindAndActivateTab(nav); 3577 DCHECK(browser); 3578 3579 if (browser->command_updater()->IsCommandEnabled(IDC_ENCODING_MENU)) 3580 *current_encoding = nav->tab_contents()->encoding(); 3581 } 3582} 3583 3584// Gets the current used encoding name of the page in the specified tab. 3585void AutomationProvider::OverrideEncoding(int tab_handle, 3586 const std::string& encoding_name, 3587 bool* success) { 3588 *success = false; 3589 if (tab_tracker_->ContainsHandle(tab_handle)) { 3590 NavigationController* nav = tab_tracker_->GetResource(tab_handle); 3591 if (!nav) 3592 return; 3593 Browser* browser = FindAndActivateTab(nav); 3594 3595 // If the browser has UI, simulate what a user would do. 3596 // Activate the tab and then click the encoding menu. 3597 if (browser && 3598 browser->command_updater()->IsCommandEnabled(IDC_ENCODING_MENU)) { 3599 int selected_encoding_id = 3600 CharacterEncoding::GetCommandIdByCanonicalEncodingName(encoding_name); 3601 if (selected_encoding_id) { 3602 browser->OverrideEncoding(selected_encoding_id); 3603 *success = true; 3604 } 3605 } else { 3606 // There is no UI, Chrome probably runs as Chrome-Frame mode. 3607 // Try to get TabContents and call its override_encoding method. 3608 TabContents* contents = nav->tab_contents(); 3609 if (!contents) 3610 return; 3611 const std::string selected_encoding = 3612 CharacterEncoding::GetCanonicalEncodingNameByAliasName(encoding_name); 3613 if (selected_encoding.empty()) 3614 return; 3615 contents->SetOverrideEncoding(selected_encoding); 3616 } 3617 } 3618} 3619 3620void AutomationProvider::SavePackageShouldPromptUser(bool should_prompt) { 3621 SavePackage::SetShouldPromptUser(should_prompt); 3622} 3623 3624void AutomationProvider::GetBlockedPopupCount(int handle, int* count) { 3625 *count = -1; // -1 is the error code 3626 if (tab_tracker_->ContainsHandle(handle)) { 3627 NavigationController* nav_controller = tab_tracker_->GetResource(handle); 3628 TabContents* tab_contents = nav_controller->tab_contents(); 3629 if (tab_contents) { 3630 BlockedPopupContainer* container = 3631 tab_contents->blocked_popup_container(); 3632 if (container) { 3633 *count = static_cast<int>(container->GetBlockedPopupCount()); 3634 } else { 3635 // If we don't have a container, we don't have any blocked popups to 3636 // contain! 3637 *count = 0; 3638 } 3639 } 3640 } 3641} 3642 3643void AutomationProvider::SelectAll(int tab_handle) { 3644 RenderViewHost* view = GetViewForTab(tab_handle); 3645 if (!view) { 3646 NOTREACHED(); 3647 return; 3648 } 3649 3650 view->SelectAll(); 3651} 3652 3653void AutomationProvider::Cut(int tab_handle) { 3654 RenderViewHost* view = GetViewForTab(tab_handle); 3655 if (!view) { 3656 NOTREACHED(); 3657 return; 3658 } 3659 3660 view->Cut(); 3661} 3662 3663void AutomationProvider::Copy(int tab_handle) { 3664 RenderViewHost* view = GetViewForTab(tab_handle); 3665 if (!view) { 3666 NOTREACHED(); 3667 return; 3668 } 3669 3670 view->Copy(); 3671} 3672 3673void AutomationProvider::Paste(int tab_handle) { 3674 RenderViewHost* view = GetViewForTab(tab_handle); 3675 if (!view) { 3676 NOTREACHED(); 3677 return; 3678 } 3679 3680 view->Paste(); 3681} 3682 3683void AutomationProvider::ReloadAsync(int tab_handle) { 3684 if (tab_tracker_->ContainsHandle(tab_handle)) { 3685 NavigationController* tab = tab_tracker_->GetResource(tab_handle); 3686 if (!tab) { 3687 NOTREACHED(); 3688 return; 3689 } 3690 3691 const bool check_for_repost = true; 3692 tab->Reload(check_for_repost); 3693 } 3694} 3695 3696void AutomationProvider::StopAsync(int tab_handle) { 3697 RenderViewHost* view = GetViewForTab(tab_handle); 3698 if (!view) { 3699 // We tolerate StopAsync being called even before a view has been created. 3700 // So just log a warning instead of a NOTREACHED(). 3701 DLOG(WARNING) << "StopAsync: no view for handle " << tab_handle; 3702 return; 3703 } 3704 3705 view->Stop(); 3706} 3707 3708void AutomationProvider::OnSetPageFontSize(int tab_handle, 3709 int font_size) { 3710 AutomationPageFontSize automation_font_size = 3711 static_cast<AutomationPageFontSize>(font_size); 3712 3713 if (automation_font_size < SMALLEST_FONT || 3714 automation_font_size > LARGEST_FONT) { 3715 DLOG(ERROR) << "Invalid font size specified : " 3716 << font_size; 3717 return; 3718 } 3719 3720 if (tab_tracker_->ContainsHandle(tab_handle)) { 3721 NavigationController* tab = tab_tracker_->GetResource(tab_handle); 3722 DCHECK(tab != NULL); 3723 if (tab && tab->tab_contents()) { 3724 DCHECK(tab->tab_contents()->profile() != NULL); 3725 tab->tab_contents()->profile()->GetPrefs()->SetInteger( 3726 prefs::kWebKitDefaultFontSize, font_size); 3727 } 3728 } 3729} 3730 3731void AutomationProvider::RemoveBrowsingData(int remove_mask) { 3732 BrowsingDataRemover* remover; 3733 remover = new BrowsingDataRemover(profile(), 3734 BrowsingDataRemover::EVERYTHING, // All time periods. 3735 base::Time()); 3736 remover->Remove(remove_mask); 3737 // BrowsingDataRemover deletes itself. 3738} 3739 3740void AutomationProvider::WaitForBrowserWindowCountToBecome( 3741 int target_count, IPC::Message* reply_message) { 3742 if (static_cast<int>(BrowserList::size()) == target_count) { 3743 AutomationMsg_WaitForBrowserWindowCountToBecome::WriteReplyParams( 3744 reply_message, true); 3745 Send(reply_message); 3746 return; 3747 } 3748 3749 // Set up an observer (it will delete itself). 3750 new BrowserCountChangeNotificationObserver(target_count, this, reply_message); 3751} 3752 3753void AutomationProvider::WaitForAppModalDialogToBeShown( 3754 IPC::Message* reply_message) { 3755 if (Singleton<AppModalDialogQueue>()->HasActiveDialog()) { 3756 AutomationMsg_WaitForAppModalDialogToBeShown::WriteReplyParams( 3757 reply_message, true); 3758 Send(reply_message); 3759 return; 3760 } 3761 3762 // Set up an observer (it will delete itself). 3763 new AppModalDialogShownObserver(this, reply_message); 3764} 3765 3766void AutomationProvider::GoBackBlockUntilNavigationsComplete( 3767 int handle, int number_of_navigations, IPC::Message* reply_message) { 3768 if (tab_tracker_->ContainsHandle(handle)) { 3769 NavigationController* tab = tab_tracker_->GetResource(handle); 3770 Browser* browser = FindAndActivateTab(tab); 3771 if (browser && browser->command_updater()->IsCommandEnabled(IDC_BACK)) { 3772 AddNavigationStatusListener(tab, reply_message, number_of_navigations, 3773 false); 3774 browser->GoBack(CURRENT_TAB); 3775 return; 3776 } 3777 } 3778 3779 AutomationMsg_GoBackBlockUntilNavigationsComplete::WriteReplyParams( 3780 reply_message, AUTOMATION_MSG_NAVIGATION_ERROR); 3781 Send(reply_message); 3782} 3783 3784void AutomationProvider::GoForwardBlockUntilNavigationsComplete( 3785 int handle, int number_of_navigations, IPC::Message* reply_message) { 3786 if (tab_tracker_->ContainsHandle(handle)) { 3787 NavigationController* tab = tab_tracker_->GetResource(handle); 3788 Browser* browser = FindAndActivateTab(tab); 3789 if (browser && browser->command_updater()->IsCommandEnabled(IDC_FORWARD)) { 3790 AddNavigationStatusListener(tab, reply_message, number_of_navigations, 3791 false); 3792 browser->GoForward(CURRENT_TAB); 3793 return; 3794 } 3795 } 3796 3797 AutomationMsg_GoForwardBlockUntilNavigationsComplete::WriteReplyParams( 3798 reply_message, AUTOMATION_MSG_NAVIGATION_ERROR); 3799 Send(reply_message); 3800} 3801 3802RenderViewHost* AutomationProvider::GetViewForTab(int tab_handle) { 3803 if (tab_tracker_->ContainsHandle(tab_handle)) { 3804 NavigationController* tab = tab_tracker_->GetResource(tab_handle); 3805 if (!tab) { 3806 NOTREACHED(); 3807 return NULL; 3808 } 3809 3810 TabContents* tab_contents = tab->tab_contents(); 3811 if (!tab_contents) { 3812 NOTREACHED(); 3813 return NULL; 3814 } 3815 3816 RenderViewHost* view_host = tab_contents->render_view_host(); 3817 return view_host; 3818 } 3819 3820 return NULL; 3821} 3822 3823void AutomationProvider::GetBrowserForWindow(int window_handle, 3824 bool* success, 3825 int* browser_handle) { 3826 *success = false; 3827 *browser_handle = 0; 3828 3829 gfx::NativeWindow window = window_tracker_->GetResource(window_handle); 3830 if (!window) 3831 return; 3832 3833 BrowserList::const_iterator iter = BrowserList::begin(); 3834 for (;iter != BrowserList::end(); ++iter) { 3835 gfx::NativeWindow this_window = (*iter)->window()->GetNativeHandle(); 3836 if (window == this_window) { 3837 // Add() returns the existing handle for the resource if any. 3838 *browser_handle = browser_tracker_->Add(*iter); 3839 *success = true; 3840 return; 3841 } 3842 } 3843} 3844 3845void AutomationProvider::InstallExtension(const FilePath& crx_path, 3846 IPC::Message* reply_message) { 3847 ExtensionsService* service = profile_->GetExtensionsService(); 3848 if (service) { 3849 // The observer will delete itself when done. 3850 new ExtensionInstallNotificationObserver(this, 3851 AutomationMsg_InstallExtension::ID, 3852 reply_message); 3853 3854 const FilePath& install_dir = service->install_directory(); 3855 scoped_refptr<CrxInstaller> installer( 3856 new CrxInstaller(install_dir, 3857 service, 3858 NULL)); // silent install, no UI 3859 installer->set_allow_privilege_increase(true); 3860 installer->InstallCrx(crx_path); 3861 } else { 3862 AutomationMsg_InstallExtension::WriteReplyParams( 3863 reply_message, AUTOMATION_MSG_EXTENSION_INSTALL_FAILED); 3864 Send(reply_message); 3865 } 3866} 3867 3868void AutomationProvider::LoadExpandedExtension( 3869 const FilePath& extension_dir, 3870 IPC::Message* reply_message) { 3871 if (profile_->GetExtensionsService()) { 3872 // The observer will delete itself when done. 3873 new ExtensionInstallNotificationObserver( 3874 this, 3875 AutomationMsg_LoadExpandedExtension::ID, 3876 reply_message); 3877 3878 profile_->GetExtensionsService()->LoadExtension(extension_dir); 3879 } else { 3880 AutomationMsg_LoadExpandedExtension::WriteReplyParams( 3881 reply_message, AUTOMATION_MSG_EXTENSION_INSTALL_FAILED); 3882 Send(reply_message); 3883 } 3884} 3885 3886void AutomationProvider::GetEnabledExtensions( 3887 std::vector<FilePath>* result) { 3888 ExtensionsService* service = profile_->GetExtensionsService(); 3889 DCHECK(service); 3890 if (service->extensions_enabled()) { 3891 const ExtensionList* extensions = service->extensions(); 3892 DCHECK(extensions); 3893 for (size_t i = 0; i < extensions->size(); ++i) { 3894 Extension* extension = (*extensions)[i]; 3895 DCHECK(extension); 3896 if (extension->location() == Extension::INTERNAL || 3897 extension->location() == Extension::LOAD) { 3898 result->push_back(extension->path()); 3899 } 3900 } 3901 } 3902} 3903 3904void AutomationProvider::WaitForExtensionTestResult( 3905 IPC::Message* reply_message) { 3906 DCHECK(reply_message_ == NULL); 3907 reply_message_ = reply_message; 3908 // Call MaybeSendResult, because the result might have come in before 3909 // we were waiting on it. 3910 extension_test_result_observer_->MaybeSendResult(); 3911} 3912 3913void AutomationProvider::InstallExtensionAndGetHandle( 3914 const FilePath& crx_path, bool with_ui, IPC::Message* reply_message) { 3915 ExtensionsService* service = profile_->GetExtensionsService(); 3916 ExtensionProcessManager* manager = profile_->GetExtensionProcessManager(); 3917 if (service && manager) { 3918 // The observer will delete itself when done. 3919 new ExtensionReadyNotificationObserver( 3920 manager, 3921 this, 3922 AutomationMsg_InstallExtensionAndGetHandle::ID, 3923 reply_message); 3924 3925 ExtensionInstallUI* client = 3926 (with_ui ? new ExtensionInstallUI(profile_) : NULL); 3927 scoped_refptr<CrxInstaller> installer( 3928 new CrxInstaller(service->install_directory(), 3929 service, 3930 client)); 3931 installer->set_allow_privilege_increase(true); 3932 installer->InstallCrx(crx_path); 3933 } else { 3934 AutomationMsg_InstallExtensionAndGetHandle::WriteReplyParams( 3935 reply_message, 0); 3936 Send(reply_message); 3937 } 3938} 3939 3940void AutomationProvider::UninstallExtension(int extension_handle, 3941 bool* success) { 3942 *success = false; 3943 Extension* extension = GetExtension(extension_handle); 3944 ExtensionsService* service = profile_->GetExtensionsService(); 3945 if (extension && service) { 3946 ExtensionUnloadNotificationObserver observer; 3947 service->UninstallExtension(extension->id(), false); 3948 // The extension unload notification should have been sent synchronously 3949 // with the uninstall. Just to be safe, check that it was received. 3950 *success = observer.did_receive_unload_notification(); 3951 } 3952} 3953 3954void AutomationProvider::EnableExtension(int extension_handle, 3955 IPC::Message* reply_message) { 3956 Extension* extension = GetDisabledExtension(extension_handle); 3957 ExtensionsService* service = profile_->GetExtensionsService(); 3958 ExtensionProcessManager* manager = profile_->GetExtensionProcessManager(); 3959 // Only enable if this extension is disabled. 3960 if (extension && service && manager) { 3961 // The observer will delete itself when done. 3962 new ExtensionReadyNotificationObserver( 3963 manager, 3964 this, 3965 AutomationMsg_EnableExtension::ID, 3966 reply_message); 3967 service->EnableExtension(extension->id()); 3968 } else { 3969 AutomationMsg_EnableExtension::WriteReplyParams(reply_message, false); 3970 Send(reply_message); 3971 } 3972} 3973 3974void AutomationProvider::DisableExtension(int extension_handle, 3975 bool* success) { 3976 *success = false; 3977 Extension* extension = GetEnabledExtension(extension_handle); 3978 ExtensionsService* service = profile_->GetExtensionsService(); 3979 if (extension && service) { 3980 ExtensionUnloadNotificationObserver observer; 3981 service->DisableExtension(extension->id()); 3982 // The extension unload notification should have been sent synchronously 3983 // with the disable. Just to be safe, check that it was received. 3984 *success = observer.did_receive_unload_notification(); 3985 } 3986} 3987 3988void AutomationProvider::ExecuteExtensionActionInActiveTabAsync( 3989 int extension_handle, int browser_handle, 3990 IPC::Message* reply_message) { 3991 bool success = false; 3992 Extension* extension = GetEnabledExtension(extension_handle); 3993 ExtensionsService* service = profile_->GetExtensionsService(); 3994 ExtensionMessageService* message_service = 3995 profile_->GetExtensionMessageService(); 3996 Browser* browser = browser_tracker_->GetResource(browser_handle); 3997 if (extension && service && message_service && browser) { 3998 int tab_id = ExtensionTabUtil::GetTabId(browser->GetSelectedTabContents()); 3999 if (extension->page_action()) { 4000 ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted( 4001 browser->profile(), extension->id(), "action", tab_id, "", 1); 4002 success = true; 4003 } else if (extension->browser_action()) { 4004 ExtensionBrowserEventRouter::GetInstance()->BrowserActionExecuted( 4005 browser->profile(), extension->id(), browser); 4006 success = true; 4007 } 4008 } 4009 AutomationMsg_ExecuteExtensionActionInActiveTabAsync::WriteReplyParams( 4010 reply_message, success); 4011 Send(reply_message); 4012} 4013 4014void AutomationProvider::MoveExtensionBrowserAction( 4015 int extension_handle, int index, bool* success) { 4016 *success = false; 4017 Extension* extension = GetEnabledExtension(extension_handle); 4018 ExtensionsService* service = profile_->GetExtensionsService(); 4019 if (extension && service) { 4020 ExtensionToolbarModel* toolbar = service->toolbar_model(); 4021 if (toolbar) { 4022 if (index >= 0 && index < static_cast<int>(toolbar->size())) { 4023 toolbar->MoveBrowserAction(extension, index); 4024 *success = true; 4025 } else { 4026 DLOG(WARNING) << "Attempted to move browser action to invalid index."; 4027 } 4028 } 4029 } 4030} 4031 4032void AutomationProvider::GetExtensionProperty( 4033 int extension_handle, 4034 AutomationMsg_ExtensionProperty type, 4035 bool* success, 4036 std::string* value) { 4037 *success = false; 4038 Extension* extension = GetExtension(extension_handle); 4039 ExtensionsService* service = profile_->GetExtensionsService(); 4040 if (extension && service) { 4041 ExtensionToolbarModel* toolbar = service->toolbar_model(); 4042 int found_index = -1; 4043 int index = 0; 4044 switch (type) { 4045 case AUTOMATION_MSG_EXTENSION_ID: 4046 *value = extension->id(); 4047 *success = true; 4048 break; 4049 case AUTOMATION_MSG_EXTENSION_NAME: 4050 *value = extension->name(); 4051 *success = true; 4052 break; 4053 case AUTOMATION_MSG_EXTENSION_VERSION: 4054 *value = extension->VersionString(); 4055 *success = true; 4056 break; 4057 case AUTOMATION_MSG_EXTENSION_BROWSER_ACTION_INDEX: 4058 if (toolbar) { 4059 for (ExtensionList::const_iterator iter = toolbar->begin(); 4060 iter != toolbar->end(); iter++) { 4061 // Skip this extension if we are in incognito mode 4062 // and it is not incognito-enabled. 4063 if (profile_->IsOffTheRecord() && 4064 !service->IsIncognitoEnabled(*iter)) 4065 continue; 4066 if (*iter == extension) { 4067 found_index = index; 4068 break; 4069 } 4070 index++; 4071 } 4072 *value = IntToString(found_index); 4073 *success = true; 4074 } 4075 break; 4076 default: 4077 LOG(WARNING) << "Trying to get undefined extension property"; 4078 break; 4079 } 4080 } 4081} 4082 4083void AutomationProvider::SaveAsAsync(int tab_handle) { 4084 NavigationController* tab = NULL; 4085 TabContents* tab_contents = GetTabContentsForHandle(tab_handle, &tab); 4086 if (tab_contents) 4087 tab_contents->OnSavePage(); 4088} 4089 4090void AutomationProvider::SetContentSetting( 4091 int handle, 4092 const std::string& host, 4093 ContentSettingsType content_type, 4094 ContentSetting setting, 4095 bool* success) { 4096 *success = false; 4097 if (browser_tracker_->ContainsHandle(handle)) { 4098 Browser* browser = browser_tracker_->GetResource(handle); 4099 HostContentSettingsMap* map = 4100 browser->profile()->GetHostContentSettingsMap(); 4101 if (host.empty()) { 4102 map->SetDefaultContentSetting(content_type, setting); 4103 } else { 4104 map->SetContentSetting(HostContentSettingsMap::Pattern(host), 4105 content_type, setting); 4106 } 4107 *success = true; 4108 } 4109} 4110 4111#if !defined(TOOLKIT_VIEWS) 4112void AutomationProvider::GetFocusedViewID(int handle, int* view_id) { 4113 NOTIMPLEMENTED(); 4114}; 4115 4116void AutomationProvider::WaitForFocusedViewIDToChange( 4117 int handle, int previous_view_id, IPC::Message* reply_message) { 4118 NOTIMPLEMENTED(); 4119} 4120 4121void AutomationProvider::StartTrackingPopupMenus( 4122 int browser_handle, bool* success) { 4123 NOTIMPLEMENTED(); 4124} 4125 4126void AutomationProvider::WaitForPopupMenuToOpen(IPC::Message* reply_message) { 4127 NOTIMPLEMENTED(); 4128} 4129#endif // !defined(TOOLKIT_VIEWS) 4130 4131void AutomationProvider::ResetToDefaultTheme() { 4132 profile_->ClearTheme(); 4133} 4134