blob: cf6b0721c7633b62c78133ac3b5991ba04a9d2e9 [file] [log] [blame]
[email protected]3b5f7022010-03-25 20:37:401// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
5#include "chrome/browser/automation/automation_provider.h"
6
[email protected]5ae5bed2009-08-21 18:52:447#include <set>
8
[email protected]37126212009-05-06 02:23:319#include "app/message_box_flags.h"
[email protected]2041cf342010-02-19 03:15:5910#include "base/callback.h"
[email protected]7060bb292010-06-24 00:52:4911#include "base/file_path.h"
[email protected]93d49d72009-10-23 20:00:2012#include "base/json/json_reader.h"
[email protected]59a611242010-04-02 02:24:0413#include "base/json/json_writer.h"
[email protected]93364da2010-06-29 18:03:4414#include "base/json/string_escape.h"
[email protected]bc1407f2009-09-29 00:33:3515#include "base/keyboard_codes.h"
[email protected]5fac9622009-02-04 21:49:3816#include "base/message_loop.h"
initial.commit09911bf2008-07-26 23:55:2917#include "base/path_service.h"
[email protected]201b2732009-11-13 18:57:4618#include "base/process_util.h"
[email protected]f44265b2009-05-19 18:52:5019#include "base/stl_util-inl.h"
[email protected]4c4d8d22009-03-04 05:29:2720#include "base/string_util.h"
[email protected]9eaa18e2010-06-29 20:51:0121#include "base/task.h"
[email protected]5fac9622009-02-04 21:49:3822#include "base/thread.h"
[email protected]a872ea1f2010-08-11 04:45:3323#include "base/trace_event.h"
[email protected]528c56d2010-07-30 19:28:4424#include "base/string_number_conversions.h"
[email protected]6d8ffc9f2010-03-12 18:27:5325#include "base/utf_string_conversions.h"
[email protected]a7eee32f2009-05-22 18:08:1726#include "base/values.h"
[email protected]9eaa18e2010-06-29 20:51:0127#include "base/waitable_event.h"
[email protected]4f3dc372009-02-24 00:10:2928#include "chrome/app/chrome_dll_resource.h"
[email protected]0bfa713f2009-04-07 20:18:2829#include "chrome/browser/app_modal_dialog.h"
[email protected]464146e2009-04-09 18:17:0930#include "chrome/browser/app_modal_dialog_queue.h"
[email protected]55846ad842010-07-09 18:22:5631#include "chrome/browser/autofill/autofill_manager.h"
[email protected]679082052010-07-21 21:30:1332#include "chrome/browser/automation/automation_autocomplete_edit_tracker.h"
33#include "chrome/browser/automation/automation_browser_tracker.h"
[email protected]790788ac2010-04-06 17:52:1934#include "chrome/browser/automation/automation_extension_tracker.h"
[email protected]7c983cc2010-07-16 11:33:3435#include "chrome/browser/automation/automation_provider_json.h"
initial.commit09911bf2008-07-26 23:55:2936#include "chrome/browser/automation/automation_provider_list.h"
[email protected]e12de87e2009-08-28 00:02:0837#include "chrome/browser/automation/automation_provider_observers.h"
[email protected]679082052010-07-21 21:30:1338#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"
[email protected]f44265b2009-05-19 18:52:5041#include "chrome/browser/automation/extension_port_container.h"
[email protected]12802702010-07-09 19:43:0942#include "chrome/browser/autocomplete/autocomplete_edit.h"
[email protected]66ba4932009-06-04 19:22:1343#include "chrome/browser/blocked_popup_container.h"
[email protected]6d8ffc9f2010-03-12 18:27:5344#include "chrome/browser/bookmarks/bookmark_model.h"
45#include "chrome/browser/bookmarks/bookmark_storage.h"
[email protected]ef413ca2010-05-25 21:09:1446#include "chrome/browser/browser_list.h"
[email protected]5c238752009-06-13 10:29:0747#include "chrome/browser/browser_process.h"
[email protected]f3e99e32008-07-30 04:48:3948#include "chrome/browser/browser_window.h"
[email protected]bc73b4e52010-03-26 04:16:2049#include "chrome/browser/browsing_data_remover.h"
[email protected]f83f9102010-05-04 17:01:0550#include "chrome/browser/character_encoding.h"
[email protected]fae20792009-10-28 20:31:5851#include "chrome/browser/chrome_thread.h"
initial.commit09911bf2008-07-26 23:55:2952#include "chrome/browser/dom_operation_notification_details.h"
[email protected]d9f9b792009-06-24 13:17:1253#include "chrome/browser/debugger/devtools_manager.h"
[email protected]6c69796d2010-07-16 21:41:1654#include "chrome/browser/download/download_item.h"
[email protected]59560e0b2009-06-04 03:30:2255#include "chrome/browser/download/download_shelf.h"
[email protected]f83f9102010-05-04 17:01:0556#include "chrome/browser/download/save_package.h"
[email protected]d11c8e92009-10-20 23:26:4057#include "chrome/browser/extensions/crx_installer.h"
[email protected]790788ac2010-04-06 17:52:1958#include "chrome/browser/extensions/extension_browser_event_router.h"
[email protected]ef413ca2010-05-25 21:09:1459#include "chrome/browser/extensions/extension_host.h"
[email protected]d11c8e92009-10-20 23:26:4060#include "chrome/browser/extensions/extension_install_ui.h"
[email protected]a9024892009-06-16 23:13:5561#include "chrome/browser/extensions/extension_message_service.h"
[email protected]790788ac2010-04-06 17:52:1962#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"
[email protected]8cb5d5b2010-02-09 11:36:1665#include "chrome/browser/extensions/user_script_master.h"
[email protected]4801ecc2009-04-05 04:52:5866#include "chrome/browser/find_bar.h"
67#include "chrome/browser/find_bar_controller.h"
initial.commit09911bf2008-07-26 23:55:2968#include "chrome/browser/find_notification_details.h"
[email protected]7dad3d5f2010-03-04 00:27:0169#include "chrome/browser/host_content_settings_map.h"
[email protected]c5aa5322010-07-15 19:00:0770#include "chrome/browser/importer/importer.h"
71#include "chrome/browser/importer/importer_data_types.h"
[email protected]0ac83682010-01-22 17:46:2772#include "chrome/browser/io_thread.h"
[email protected]13869dd2009-05-05 00:40:0673#include "chrome/browser/location_bar.h"
[email protected]3fcac682009-08-13 02:28:0174#include "chrome/browser/login_prompt.h"
[email protected]f732c1e2009-07-30 15:48:5375#include "chrome/browser/net/url_request_mock_util.h"
[email protected]14a000d2010-04-29 21:44:2476#include "chrome/browser/platform_util.h"
[email protected]37858e52010-08-26 00:22:0277#include "chrome/browser/prefs/pref_service.h"
[email protected]f83f9102010-05-04 17:01:0578#include "chrome/browser/printing/print_job.h"
[email protected]a7eee32f2009-05-22 18:08:1779#include "chrome/browser/profile_manager.h"
[email protected]1db6ff152009-10-12 15:32:0780#include "chrome/browser/renderer_host/render_process_host.h"
[email protected]6524b5f92009-01-22 17:48:2581#include "chrome/browser/renderer_host/render_view_host.h"
[email protected]3b073b22009-01-16 03:29:0382#include "chrome/browser/ssl/ssl_manager.h"
83#include "chrome/browser/ssl/ssl_blocking_page.h"
[email protected]b5558cf22010-07-12 17:30:0684#include "chrome/browser/tab_contents/infobar_delegate.h"
[email protected]57c6a652009-05-04 07:58:3485#include "chrome/browser/tab_contents/tab_contents.h"
[email protected]81af9392009-04-21 02:37:4586#include "chrome/browser/tab_contents/tab_contents_view.h"
[email protected]38b5a3852010-07-21 06:49:5287#include "chrome/browser/translate/translate_infobar_delegate.h"
[email protected]a7eee32f2009-05-22 18:08:1788#include "chrome/common/automation_constants.h"
[email protected]a9ff2c02010-05-13 17:33:0589#include "chrome/common/chrome_constants.h"
initial.commit09911bf2008-07-26 23:55:2990#include "chrome/common/chrome_paths.h"
[email protected]c984d9f2010-07-20 20:52:2091#include "chrome/common/chrome_switches.h"
[email protected]1eeb5e02010-07-20 23:02:1192#include "chrome/common/chrome_version_info.h"
[email protected]790788ac2010-04-06 17:52:1993#include "chrome/common/extensions/extension.h"
[email protected]a7eee32f2009-05-22 18:08:1794#include "chrome/common/json_value_serializer.h"
[email protected]68d2a05f2010-05-07 21:39:5595#include "chrome/common/net/url_request_context_getter.h"
[email protected]1c58a5c2009-05-21 18:47:1496#include "chrome/common/notification_service.h"
[email protected]1bb5f892009-10-06 01:44:5797#include "chrome/common/pref_names.h"
[email protected]f5bf8ccf2010-02-05 18:19:2598#include "chrome/common/url_constants.h"
[email protected]71f65dd2009-02-11 19:14:5699#include "chrome/test/automation/automation_messages.h"
[email protected]1bb5f892009-10-06 01:44:57100#include "chrome/test/automation/tab_proxy.h"
[email protected]a7eee32f2009-05-22 18:08:17101#include "net/proxy/proxy_service.h"
102#include "net/proxy/proxy_config_service_fixed.h"
[email protected]319d9e6f2009-02-18 19:47:21103#include "net/url_request/url_request_context.h"
[email protected]1b5a48c2010-04-29 23:08:30104#include "chrome/browser/automation/ui_controls.h"
[email protected]9a08bcf2009-08-12 19:56:28105#include "views/event.h"
[email protected]5bcfe1672010-07-16 20:51:57106#include "webkit/glue/password_form.h"
[email protected]f7d48012010-05-06 08:17:05107#include "webkit/glue/plugins/plugin_list.h"
initial.commit09911bf2008-07-26 23:55:29108
[email protected]de246f52009-02-25 18:25:45109#if defined(OS_WIN)
[email protected]4bdde602010-06-16 03:17:35110#include "chrome/browser/external_tab_container_win.h"
[email protected]de246f52009-02-25 18:25:45111#endif // defined(OS_WIN)
112
[email protected]e1acf6f2008-10-27 20:43:33113using base::Time;
114
initial.commit09911bf2008-07-26 23:55:29115AutomationProvider::AutomationProvider(Profile* profile)
[email protected]c97080f2010-08-20 20:42:48116 : profile_(profile),
[email protected]4feac662010-08-25 23:29:39117 reply_message_(NULL) {
[email protected]a872ea1f2010-08-11 04:45:33118 TRACE_EVENT_BEGIN("AutomationProvider::AutomationProvider", 0, "");
119
initial.commit09911bf2008-07-26 23:55:29120 browser_tracker_.reset(new AutomationBrowserTracker(this));
[email protected]790788ac2010-04-06 17:52:19121 extension_tracker_.reset(new AutomationExtensionTracker(this));
initial.commit09911bf2008-07-26 23:55:29122 tab_tracker_.reset(new AutomationTabTracker(this));
[email protected]0e9f4ee2009-04-08 01:44:20123 window_tracker_.reset(new AutomationWindowTracker(this));
initial.commit09911bf2008-07-26 23:55:29124 autocomplete_edit_tracker_.reset(
125 new AutomationAutocompleteEditTracker(this));
initial.commit09911bf2008-07-26 23:55:29126 new_tab_ui_load_observer_.reset(new NewTabUILoadObserver(this));
127 dom_operation_observer_.reset(new DomOperationNotificationObserver(this));
[email protected]84abba62009-10-07 17:01:44128 metric_event_duration_observer_.reset(new MetricEventDurationObserver());
[email protected]790788ac2010-04-06 17:52:19129 extension_test_result_observer_.reset(
130 new ExtensionTestResultNotificationObserver(this));
[email protected]528211a2010-01-14 15:25:13131 g_browser_process->AddRefModule();
[email protected]a872ea1f2010-08-11 04:45:33132
133 TRACE_EVENT_END("AutomationProvider::AutomationProvider", 0, "");
initial.commit09911bf2008-07-26 23:55:29134}
135
136AutomationProvider::~AutomationProvider() {
[email protected]f44265b2009-05-19 18:52:50137 STLDeleteContainerPairSecondPointers(port_containers_.begin(),
138 port_containers_.end());
139 port_containers_.clear();
140
[email protected]0da050b92008-08-19 19:29:47141 // Make sure that any outstanding NotificationObservers also get destroyed.
142 ObserverList<NotificationObserver>::Iterator it(notification_observer_list_);
[email protected]5a52f162008-08-27 04:15:31143 NotificationObserver* observer;
[email protected]0da050b92008-08-19 19:29:47144 while ((observer = it.GetNext()) != NULL)
145 delete observer;
[email protected]528211a2010-01-14 15:25:13146
147 if (channel_.get()) {
148 channel_->Close();
149 }
150 g_browser_process->ReleaseModule();
initial.commit09911bf2008-07-26 23:55:29151}
152
[email protected]9a3a293b2009-06-04 22:28:16153void AutomationProvider::ConnectToChannel(const std::string& channel_id) {
[email protected]a872ea1f2010-08-11 04:45:33154 TRACE_EVENT_BEGIN("AutomationProvider::ConnectToChannel", 0, "");
155
[email protected]2e4633c2009-07-09 16:58:06156 automation_resource_message_filter_ = new AutomationResourceMessageFilter;
[email protected]295039bd2008-08-15 04:32:57157 channel_.reset(
[email protected]2e4633c2009-07-09 16:58:06158 new IPC::SyncChannel(channel_id, IPC::Channel::MODE_CLIENT, this,
159 automation_resource_message_filter_,
160 g_browser_process->io_thread()->message_loop(),
161 true, g_browser_process->shutdown_event()));
[email protected]0211f57e2010-08-27 20:28:42162 chrome::VersionInfo version_info;
[email protected]c6cb1992009-04-13 16:45:29163
164 // Send a hello message with our current automation protocol version.
[email protected]0211f57e2010-08-27 20:28:42165 channel_->Send(new AutomationMsg_Hello(0, version_info.Version().c_str()));
[email protected]a872ea1f2010-08-11 04:45:33166
167 TRACE_EVENT_END("AutomationProvider::ConnectToChannel", 0, "");
initial.commit09911bf2008-07-26 23:55:29168}
169
170void AutomationProvider::SetExpectedTabCount(size_t expected_tabs) {
171 if (expected_tabs == 0) {
172 Send(new AutomationMsg_InitialLoadsComplete(0));
173 } else {
174 initial_load_observer_.reset(new InitialLoadObserver(expected_tabs, this));
175 }
176}
177
178NotificationObserver* AutomationProvider::AddNavigationStatusListener(
[email protected]2e028a082009-08-19 20:32:58179 NavigationController* tab, IPC::Message* reply_message,
[email protected]7dad3d5f2010-03-04 00:27:01180 int number_of_navigations, bool include_current_navigation) {
initial.commit09911bf2008-07-26 23:55:29181 NotificationObserver* observer =
[email protected]2e028a082009-08-19 20:32:58182 new NavigationNotificationObserver(tab, this, reply_message,
[email protected]7dad3d5f2010-03-04 00:27:01183 number_of_navigations,
184 include_current_navigation);
initial.commit09911bf2008-07-26 23:55:29185
[email protected]71f65dd2009-02-11 19:14:56186 notification_observer_list_.AddObserver(observer);
initial.commit09911bf2008-07-26 23:55:29187 return observer;
188}
189
[email protected]faf2ee42010-05-11 14:26:17190void AutomationProvider::RemoveNavigationStatusListener(
191 NotificationObserver* obs) {
192 notification_observer_list_.RemoveObserver(obs);
193}
194
initial.commit09911bf2008-07-26 23:55:29195NotificationObserver* AutomationProvider::AddTabStripObserver(
[email protected]1c58a5c2009-05-21 18:47:14196 Browser* parent,
197 IPC::Message* reply_message) {
[email protected]71f65dd2009-02-11 19:14:56198 NotificationObserver* observer =
[email protected]1c58a5c2009-05-21 18:47:14199 new TabAppendedNotificationObserver(parent, this, reply_message);
initial.commit09911bf2008-07-26 23:55:29200 notification_observer_list_.AddObserver(observer);
201
202 return observer;
203}
204
[email protected]faf2ee42010-05-11 14:26:17205void AutomationProvider::RemoveTabStripObserver(NotificationObserver* obs) {
initial.commit09911bf2008-07-26 23:55:29206 notification_observer_list_.RemoveObserver(obs);
207}
208
209void AutomationProvider::AddLoginHandler(NavigationController* tab,
210 LoginHandler* handler) {
211 login_handler_map_[tab] = handler;
212}
213
214void AutomationProvider::RemoveLoginHandler(NavigationController* tab) {
215 DCHECK(login_handler_map_[tab]);
216 login_handler_map_.erase(tab);
217}
218
[email protected]f44265b2009-05-19 18:52:50219void AutomationProvider::AddPortContainer(ExtensionPortContainer* port) {
220 int port_id = port->port_id();
221 DCHECK_NE(-1, port_id);
222 DCHECK(port_containers_.find(port_id) == port_containers_.end());
223
224 port_containers_[port_id] = port;
225}
226
227void AutomationProvider::RemovePortContainer(ExtensionPortContainer* port) {
228 int port_id = port->port_id();
229 DCHECK_NE(-1, port_id);
230
231 PortContainerMap::iterator it = port_containers_.find(port_id);
232 DCHECK(it != port_containers_.end());
233
234 if (it != port_containers_.end()) {
235 delete it->second;
236 port_containers_.erase(it);
237 }
238}
239
240ExtensionPortContainer* AutomationProvider::GetPortContainer(
241 int port_id) const {
242 PortContainerMap::const_iterator it = port_containers_.find(port_id);
243 if (it == port_containers_.end())
244 return NULL;
245
246 return it->second;
247}
248
initial.commit09911bf2008-07-26 23:55:29249int AutomationProvider::GetIndexForNavigationController(
250 const NavigationController* controller, const Browser* parent) const {
251 DCHECK(parent);
[email protected]902cdf772009-05-06 15:08:12252 return parent->GetIndexOfController(controller);
initial.commit09911bf2008-07-26 23:55:29253}
254
[email protected]790788ac2010-04-06 17:52:19255int AutomationProvider::AddExtension(Extension* extension) {
256 DCHECK(extension);
257 return extension_tracker_->Add(extension);
258}
259
260Extension* AutomationProvider::GetExtension(int extension_handle) {
261 return extension_tracker_->GetResource(extension_handle);
262}
263
264Extension* AutomationProvider::GetEnabledExtension(int extension_handle) {
265 Extension* extension = extension_tracker_->GetResource(extension_handle);
266 ExtensionsService* service = profile_->GetExtensionsService();
267 if (extension && service &&
268 service->GetExtensionById(extension->id(), false))
269 return extension;
270 return NULL;
271}
272
273Extension* AutomationProvider::GetDisabledExtension(int extension_handle) {
274 Extension* extension = extension_tracker_->GetResource(extension_handle);
275 ExtensionsService* service = profile_->GetExtensionsService();
276 if (extension && service &&
277 service->GetExtensionById(extension->id(), true) &&
278 !service->GetExtensionById(extension->id(), false))
279 return extension;
280 return NULL;
281}
282
initial.commit09911bf2008-07-26 23:55:29283void AutomationProvider::OnMessageReceived(const IPC::Message& message) {
284 IPC_BEGIN_MESSAGE_MAP(AutomationProvider, message)
[email protected]1b5a48c2010-04-29 23:08:30285#if !defined(OS_MACOSX)
[email protected]71f65dd2009-02-11 19:14:56286 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WindowDrag,
287 WindowSimulateDrag)
[email protected]1b5a48c2010-04-29 23:08:30288#endif // !defined(OS_MACOSX)
[email protected]d7fa7552009-03-20 21:06:37289#if defined(OS_WIN)
[email protected]71f65dd2009-02-11 19:14:56290 IPC_MESSAGE_HANDLER(AutomationMsg_TabHWND, GetTabHWND)
[email protected]de246f52009-02-25 18:25:45291#endif // defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29292 IPC_MESSAGE_HANDLER(AutomationMsg_HandleUnused, HandleUnused)
[email protected]a7eee32f2009-05-22 18:08:17293 IPC_MESSAGE_HANDLER(AutomationMsg_SetProxyConfig, SetProxyConfig);
[email protected]d301c952009-07-13 15:02:41294 IPC_MESSAGE_HANDLER(AutomationMsg_PrintAsync, PrintAsync)
[email protected]1c58a5c2009-05-21 18:47:14295 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_Find, HandleFindRequest)
[email protected]59a611242010-04-02 02:24:04296 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_SendJSONRequest,
297 SendJSONRequest)
[email protected]71f65dd2009-02-11 19:14:56298 IPC_MESSAGE_HANDLER(AutomationMsg_GetPageCurrentEncoding,
[email protected]97fa6ce32008-12-19 01:48:16299 GetPageCurrentEncoding)
[email protected]1c58a5c2009-05-21 18:47:14300 IPC_MESSAGE_HANDLER(AutomationMsg_OverrideEncoding, OverrideEncoding)
[email protected]f7a68432009-07-29 23:18:19301 IPC_MESSAGE_HANDLER(AutomationMsg_SelectAll, SelectAll)
302 IPC_MESSAGE_HANDLER(AutomationMsg_Cut, Cut)
303 IPC_MESSAGE_HANDLER(AutomationMsg_Copy, Copy)
304 IPC_MESSAGE_HANDLER(AutomationMsg_Paste, Paste)
305 IPC_MESSAGE_HANDLER(AutomationMsg_ReloadAsync, ReloadAsync)
306 IPC_MESSAGE_HANDLER(AutomationMsg_StopAsync, StopAsync)
[email protected]1bb5f892009-10-06 01:44:57307 IPC_MESSAGE_HANDLER(AutomationMsg_SetPageFontSize, OnSetPageFontSize)
[email protected]d11c8e92009-10-20 23:26:40308 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_InstallExtension,
309 InstallExtension)
310 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_LoadExpandedExtension,
311 LoadExpandedExtension)
[email protected]a1e62d12010-03-16 02:18:43312 IPC_MESSAGE_HANDLER(AutomationMsg_GetEnabledExtensions,
313 GetEnabledExtensions)
[email protected]790788ac2010-04-06 17:52:19314 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForExtensionTestResult,
315 WaitForExtensionTestResult)
316 IPC_MESSAGE_HANDLER_DELAY_REPLY(
317 AutomationMsg_InstallExtensionAndGetHandle,
318 InstallExtensionAndGetHandle)
319 IPC_MESSAGE_HANDLER(AutomationMsg_UninstallExtension,
320 UninstallExtension)
321 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_EnableExtension,
322 EnableExtension)
323 IPC_MESSAGE_HANDLER(AutomationMsg_DisableExtension,
324 DisableExtension)
325 IPC_MESSAGE_HANDLER_DELAY_REPLY(
326 AutomationMsg_ExecuteExtensionActionInActiveTabAsync,
327 ExecuteExtensionActionInActiveTabAsync)
328 IPC_MESSAGE_HANDLER(AutomationMsg_MoveExtensionBrowserAction,
329 MoveExtensionBrowserAction)
330 IPC_MESSAGE_HANDLER(AutomationMsg_GetExtensionProperty,
331 GetExtensionProperty)
[email protected]fedaa7d2010-01-26 20:34:57332 IPC_MESSAGE_HANDLER(AutomationMsg_ShutdownSessionService,
333 ShutdownSessionService)
[email protected]673fd2c02010-02-04 23:10:00334 IPC_MESSAGE_HANDLER(AutomationMsg_SaveAsAsync, SaveAsAsync)
[email protected]7dad3d5f2010-03-04 00:27:01335 IPC_MESSAGE_HANDLER(AutomationMsg_SetContentSetting, SetContentSetting)
[email protected]bc73b4e52010-03-26 04:16:20336 IPC_MESSAGE_HANDLER(AutomationMsg_RemoveBrowsingData, RemoveBrowsingData)
[email protected]bdd5a9c92010-06-14 18:21:00337 IPC_MESSAGE_HANDLER(AutomationMsg_ResetToDefaultTheme, ResetToDefaultTheme)
[email protected]52415f842010-06-10 21:51:52338#if defined(OS_WIN)
339 // These are for use with external tabs.
340 IPC_MESSAGE_HANDLER(AutomationMsg_CreateExternalTab, CreateExternalTab)
341 IPC_MESSAGE_HANDLER(AutomationMsg_ProcessUnhandledAccelerator,
342 ProcessUnhandledAccelerator)
343 IPC_MESSAGE_HANDLER(AutomationMsg_SetInitialFocus, SetInitialFocus)
344 IPC_MESSAGE_HANDLER(AutomationMsg_TabReposition, OnTabReposition)
345 IPC_MESSAGE_HANDLER(AutomationMsg_ForwardContextMenuCommandToChrome,
346 OnForwardContextMenuCommandToChrome)
347 IPC_MESSAGE_HANDLER(AutomationMsg_NavigateInExternalTab,
348 NavigateInExternalTab)
349 IPC_MESSAGE_HANDLER(AutomationMsg_NavigateExternalTabAtIndex,
350 NavigateExternalTabAtIndex)
351 IPC_MESSAGE_HANDLER(AutomationMsg_ConnectExternalTab, ConnectExternalTab)
352 IPC_MESSAGE_HANDLER(AutomationMsg_SetEnableExtensionAutomation,
353 SetEnableExtensionAutomation)
354 IPC_MESSAGE_HANDLER(AutomationMsg_HandleMessageFromExternalHost,
355 OnMessageFromExternalHost)
[email protected]bdd5a9c92010-06-14 18:21:00356 IPC_MESSAGE_HANDLER(AutomationMsg_BrowserMove, OnBrowserMoved)
[email protected]1f71d5882010-07-15 20:39:07357 IPC_MESSAGE_HANDLER(AutomationMsg_RunUnloadHandlers, OnRunUnloadHandlers)
[email protected]7f860dd82010-08-09 23:18:05358 IPC_MESSAGE_HANDLER(AutomationMsg_SetZoomLevel, OnSetZoomLevel)
[email protected]bdd5a9c92010-06-14 18:21:00359#endif // defined(OS_WIN)
360#if defined(OS_CHROMEOS)
361 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_LoginWithUserAndPass,
362 LoginWithUserAndPass)
363#endif // defined(OS_CHROMEOS)
initial.commit09911bf2008-07-26 23:55:29364 IPC_END_MESSAGE_MAP()
365}
366
[email protected]fedaa7d2010-01-26 20:34:57367void AutomationProvider::ShutdownSessionService(int handle, bool* result) {
368 if (browser_tracker_->ContainsHandle(handle)) {
369 Browser* browser = browser_tracker_->GetResource(handle);
370 browser->profile()->ShutdownSessionService();
371 *result = true;
372 } else {
373 *result = false;
374 }
375}
376
[email protected]fc2e0872009-08-21 22:14:41377// This task just adds another task to the event queue. This is useful if
378// you want to ensure that any tasks added to the event queue after this one
379// have already been processed by the time |task| is run.
380class InvokeTaskLaterTask : public Task {
381 public:
382 explicit InvokeTaskLaterTask(Task* task) : task_(task) {}
383 virtual ~InvokeTaskLaterTask() {}
384
385 virtual void Run() {
386 MessageLoop::current()->PostTask(FROM_HERE, task_);
387 }
388
389 private:
390 Task* task_;
391
392 DISALLOW_COPY_AND_ASSIGN(InvokeTaskLaterTask);
393};
394
initial.commit09911bf2008-07-26 23:55:29395void AutomationProvider::HandleUnused(const IPC::Message& message, int handle) {
396 if (window_tracker_->ContainsHandle(handle)) {
397 window_tracker_->Remove(window_tracker_->GetResource(handle));
398 }
399}
400
401void AutomationProvider::OnChannelError() {
[email protected]2947cdcd2009-12-03 21:05:16402 LOG(INFO) << "AutomationProxy went away, shutting down app.";
[email protected]295039bd2008-08-15 04:32:57403 AutomationProviderList::GetInstance()->RemoveProvider(this);
initial.commit09911bf2008-07-26 23:55:29404}
405
initial.commit09911bf2008-07-26 23:55:29406bool AutomationProvider::Send(IPC::Message* msg) {
[email protected]295039bd2008-08-15 04:32:57407 DCHECK(channel_.get());
408 return channel_->Send(msg);
initial.commit09911bf2008-07-26 23:55:29409}
410
411Browser* AutomationProvider::FindAndActivateTab(
412 NavigationController* controller) {
413 int tab_index;
414 Browser* browser = Browser::GetBrowserForController(controller, &tab_index);
415 if (browser)
416 browser->SelectTabContentsAt(tab_index, true);
417
418 return browser;
419}
420
[email protected]4f999132009-03-31 18:08:40421void AutomationProvider::HandleFindRequest(
422 int handle,
423 const AutomationMsg_Find_Params& params,
424 IPC::Message* reply_message) {
initial.commit09911bf2008-07-26 23:55:29425 if (!tab_tracker_->ContainsHandle(handle)) {
[email protected]71f65dd2009-02-11 19:14:56426 AutomationMsg_FindInPage::WriteReplyParams(reply_message, -1, -1);
427 Send(reply_message);
initial.commit09911bf2008-07-26 23:55:29428 return;
429 }
430
431 NavigationController* nav = tab_tracker_->GetResource(handle);
[email protected]7f0005a2009-04-15 03:25:11432 TabContents* tab_contents = nav->tab_contents();
initial.commit09911bf2008-07-26 23:55:29433
434 find_in_page_observer_.reset(new
[email protected]1c58a5c2009-05-21 18:47:14435 FindInPageNotificationObserver(this, tab_contents, reply_message));
initial.commit09911bf2008-07-26 23:55:29436
[email protected]57c6a652009-05-04 07:58:34437 tab_contents->set_current_find_request_id(
438 FindInPageNotificationObserver::kFindInPageRequestId);
439 tab_contents->render_view_host()->StartFinding(
440 FindInPageNotificationObserver::kFindInPageRequestId,
441 params.search_string, params.forward, params.match_case,
442 params.find_next);
initial.commit09911bf2008-07-26 23:55:29443}
444
[email protected]ef413ca2010-05-25 21:09:14445// Sample json input: { "command": "SetWindowDimensions",
446// "x": 20, # optional
447// "y": 20, # optional
448// "width": 800, # optional
449// "height": 600 } # optional
450void AutomationProvider::SetWindowDimensions(Browser* browser,
451 DictionaryValue* args,
452 IPC::Message* reply_message) {
453 gfx::Rect rect = browser->window()->GetRestoredBounds();
454 int x, y, width, height;
[email protected]ff4c1d82010-08-04 16:58:12455 if (args->GetInteger("x", &x))
[email protected]ef413ca2010-05-25 21:09:14456 rect.set_x(x);
[email protected]ff4c1d82010-08-04 16:58:12457 if (args->GetInteger("y", &y))
[email protected]ef413ca2010-05-25 21:09:14458 rect.set_y(y);
[email protected]ff4c1d82010-08-04 16:58:12459 if (args->GetInteger("width", &width))
[email protected]ef413ca2010-05-25 21:09:14460 rect.set_width(width);
[email protected]ff4c1d82010-08-04 16:58:12461 if (args->GetInteger("height", &height))
[email protected]ef413ca2010-05-25 21:09:14462 rect.set_height(height);
463 browser->window()->SetBounds(rect);
[email protected]7c983cc2010-07-16 11:33:34464 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
[email protected]ef413ca2010-05-25 21:09:14465}
466
[email protected]38b5a3852010-07-21 06:49:52467ListValue* AutomationProvider::GetInfobarsInfo(TabContents* tc) {
468 // Each infobar may have different properties depending on the type.
469 ListValue* infobars = new ListValue;
470 for (int infobar_index = 0;
471 infobar_index < tc->infobar_delegate_count();
472 ++infobar_index) {
473 DictionaryValue* infobar_item = new DictionaryValue;
474 InfoBarDelegate* infobar = tc->GetInfoBarDelegateAt(infobar_index);
475 if (infobar->AsConfirmInfoBarDelegate()) {
476 // Also covers ThemeInstalledInfoBarDelegate and
477 // CrashedExtensionInfoBarDelegate.
[email protected]ff4c1d82010-08-04 16:58:12478 infobar_item->SetString("type", "confirm_infobar");
[email protected]38b5a3852010-07-21 06:49:52479 ConfirmInfoBarDelegate* confirm_infobar =
480 infobar->AsConfirmInfoBarDelegate();
[email protected]e23d3a32010-08-13 19:39:58481 infobar_item->SetString("text", confirm_infobar->GetMessageText());
482 infobar_item->SetString("link_text", confirm_infobar->GetLinkText());
[email protected]38b5a3852010-07-21 06:49:52483 ListValue* buttons_list = new ListValue;
484 int buttons = confirm_infobar->GetButtons();
485 if (ConfirmInfoBarDelegate::BUTTON_OK & buttons) {
486 StringValue* button_label = new StringValue(
487 confirm_infobar->GetButtonLabel(
488 ConfirmInfoBarDelegate::BUTTON_OK));
489 buttons_list->Append(button_label);
490 }
491 if (ConfirmInfoBarDelegate::BUTTON_CANCEL & buttons) {
492 StringValue* button_label = new StringValue(
493 confirm_infobar->GetButtonLabel(
494 ConfirmInfoBarDelegate::BUTTON_CANCEL));
495 buttons_list->Append(button_label);
496 }
[email protected]ff4c1d82010-08-04 16:58:12497 infobar_item->Set("buttons", buttons_list);
[email protected]38b5a3852010-07-21 06:49:52498 } else if (infobar->AsAlertInfoBarDelegate()) {
[email protected]ff4c1d82010-08-04 16:58:12499 infobar_item->SetString("type", "alert_infobar");
[email protected]38b5a3852010-07-21 06:49:52500 AlertInfoBarDelegate* alert_infobar =
501 infobar->AsAlertInfoBarDelegate();
[email protected]e23d3a32010-08-13 19:39:58502 infobar_item->SetString("text", alert_infobar->GetMessageText());
[email protected]38b5a3852010-07-21 06:49:52503 } else if (infobar->AsLinkInfoBarDelegate()) {
[email protected]ff4c1d82010-08-04 16:58:12504 infobar_item->SetString("type", "link_infobar");
[email protected]38b5a3852010-07-21 06:49:52505 LinkInfoBarDelegate* link_infobar = infobar->AsLinkInfoBarDelegate();
[email protected]e23d3a32010-08-13 19:39:58506 infobar_item->SetString("link_text", link_infobar->GetLinkText());
[email protected]38b5a3852010-07-21 06:49:52507 } else if (infobar->AsTranslateInfoBarDelegate()) {
[email protected]ff4c1d82010-08-04 16:58:12508 infobar_item->SetString("type", "translate_infobar");
[email protected]38b5a3852010-07-21 06:49:52509 TranslateInfoBarDelegate* translate_infobar =
510 infobar->AsTranslateInfoBarDelegate();
[email protected]ff4c1d82010-08-04 16:58:12511 infobar_item->SetString("original_lang_code",
[email protected]38b5a3852010-07-21 06:49:52512 translate_infobar->GetOriginalLanguageCode());
[email protected]ff4c1d82010-08-04 16:58:12513 infobar_item->SetString("target_lang_code",
[email protected]38b5a3852010-07-21 06:49:52514 translate_infobar->GetTargetLanguageCode());
515 } else if (infobar->AsExtensionInfoBarDelegate()) {
[email protected]ff4c1d82010-08-04 16:58:12516 infobar_item->SetString("type", "extension_infobar");
[email protected]38b5a3852010-07-21 06:49:52517 } else {
[email protected]ff4c1d82010-08-04 16:58:12518 infobar_item->SetString("type", "unknown_infobar");
[email protected]38b5a3852010-07-21 06:49:52519 }
520 infobars->Append(infobar_item);
521 }
522 return infobars;
523}
524
525// Sample json input: { "command": "WaitForInfobarCount",
526// "count": COUNT,
527// "tab_index": INDEX }
528// Sample output: {}
529void AutomationProvider::WaitForInfobarCount(Browser* browser,
530 DictionaryValue* args,
531 IPC::Message* reply_message) {
532 int tab_index;
533 int count;
[email protected]ff4c1d82010-08-04 16:58:12534 if (!args->GetInteger("count", &count) || count < 0 ||
535 !args->GetInteger("tab_index", &tab_index) || tab_index < 0) {
[email protected]38b5a3852010-07-21 06:49:52536 AutomationJSONReply(this, reply_message).SendError(
537 "Missing or invalid args: 'count', 'tab_index'.");
538 return;
539 }
540
541 TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
542 // Observer deletes itself.
543 new WaitForInfobarCountObserver(this, reply_message, tab_contents, count);
544}
545
[email protected]e004a2d2010-07-22 04:55:28546// Sample json input: { "command": "PerformActionOnInfobar",
547// "action": "dismiss",
548// "infobar_index": 0,
549// "tab_index": 0 }
550// Sample output: {}
551void AutomationProvider::PerformActionOnInfobar(Browser* browser,
552 DictionaryValue* args,
553 IPC::Message* reply_message) {
554 AutomationJSONReply reply(this, reply_message);
555 int tab_index;
556 int infobar_index;
557 std::string action;
[email protected]ff4c1d82010-08-04 16:58:12558 if (!args->GetInteger("tab_index", &tab_index) ||
559 !args->GetInteger("infobar_index", &infobar_index) ||
560 !args->GetString("action", &action)) {
[email protected]e004a2d2010-07-22 04:55:28561 reply.SendError("Invalid or missing args");
562 return;
563 }
564 TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
565 if (!tab_contents) {
566 reply.SendError(StringPrintf("No such tab at index %d", tab_index));
567 return;
568 }
569 InfoBarDelegate* infobar = NULL;
570 if (infobar_index < 0 ||
571 infobar_index >= tab_contents->infobar_delegate_count() ||
572 !(infobar = tab_contents->GetInfoBarDelegateAt(infobar_index))) {
573 reply.SendError(StringPrintf("No such infobar at index %d", infobar_index));
574 return;
575 }
576 if ("dismiss" == action) {
577 infobar->InfoBarDismissed();
578 tab_contents->RemoveInfoBar(infobar);
579 reply.SendSuccess(NULL);
580 return;
581 }
582 if ("accept" == action || "cancel" == action) {
583 ConfirmInfoBarDelegate* confirm_infobar;
584 if (!(confirm_infobar = infobar->AsConfirmInfoBarDelegate())) {
585 reply.SendError("Not a confirm infobar");
586 return;
587 }
588 if ("accept" == action) {
589 if (confirm_infobar->Accept())
590 tab_contents->RemoveInfoBar(infobar);
591 } else if ("cancel" == action) {
592 if (confirm_infobar->Cancel())
593 tab_contents->RemoveInfoBar(infobar);
594 }
595 reply.SendSuccess(NULL);
596 return;
597 }
598 reply.SendError("Invalid action");
599}
600
[email protected]26adfd312010-07-20 01:04:46601namespace {
602
603// Task to get info about BrowserChildProcessHost. Must run on IO thread to
604// honor the semantics of BrowserChildProcessHost.
605// Used by AutomationProvider::GetBrowserInfo().
606class GetChildProcessHostInfoTask : public Task {
607 public:
608 GetChildProcessHostInfoTask(base::WaitableEvent* event,
609 ListValue* child_processes)
610 : event_(event),
611 child_processes_(child_processes) {}
612
613 virtual void Run() {
614 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
615 for (BrowserChildProcessHost::Iterator iter; !iter.Done(); ++iter) {
616 // Only add processes which are already started,
617 // since we need their handle.
618 if ((*iter)->handle() == base::kNullProcessHandle) {
619 continue;
620 }
621 ChildProcessInfo* info = *iter;
622 DictionaryValue* item = new DictionaryValue;
[email protected]ff4c1d82010-08-04 16:58:12623 item->SetString("name", WideToUTF16Hack(info->name()));
624 item->SetString("type",
[email protected]41b5c202010-08-19 01:11:08625 ChildProcessInfo::GetTypeNameInEnglish(info->type()));
[email protected]ff4c1d82010-08-04 16:58:12626 item->SetInteger("pid", base::GetProcId(info->handle()));
[email protected]26adfd312010-07-20 01:04:46627 child_processes_->Append(item);
628 }
629 event_->Signal();
630 }
631
632 private:
633 base::WaitableEvent* const event_; // weak
634 ListValue* child_processes_;
635
636 DISALLOW_COPY_AND_ASSIGN(GetChildProcessHostInfoTask);
637};
638
639} // namespace
640
[email protected]a9ff2c02010-05-13 17:33:05641// Sample json input: { "command": "GetBrowserInfo" }
642// Refer to GetBrowserInfo() in chrome/test/pyautolib/pyauto.py for
643// sample json output.
[email protected]53329582010-05-14 21:10:58644void AutomationProvider::GetBrowserInfo(Browser* browser,
645 DictionaryValue* args,
[email protected]a9ff2c02010-05-13 17:33:05646 IPC::Message* reply_message) {
[email protected]a9ff2c02010-05-13 17:33:05647 DictionaryValue* properties = new DictionaryValue;
[email protected]ff4c1d82010-08-04 16:58:12648 properties->SetString("ChromeVersion", chrome::kChromeVersion);
649 properties->SetString("BrowserProcessExecutableName",
650 WideToUTF16Hack(chrome::kBrowserProcessExecutableName));
651 properties->SetString("HelperProcessExecutableName",
652 WideToUTF16Hack(chrome::kHelperProcessExecutableName));
653 properties->SetString("BrowserProcessExecutablePath",
654 WideToUTF16Hack(chrome::kBrowserProcessExecutablePath));
655 properties->SetString("HelperProcessExecutablePath",
[email protected]a9ff2c02010-05-13 17:33:05656 chrome::kHelperProcessExecutablePath);
[email protected]ff4c1d82010-08-04 16:58:12657 properties->SetString("command_line_string",
[email protected]a9ff2c02010-05-13 17:33:05658 CommandLine::ForCurrentProcess()->command_line_string());
[email protected]9d8fe3b2010-08-20 19:51:24659 FilePath dumps_path;
660 PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path);
661 properties->SetString("DIR_CRASH_DUMPS", dumps_path.value());
[email protected]44eed9f2010-06-28 22:04:00662
663 std::string branding;
664#if defined(GOOGLE_CHROME_BUILD)
665 branding = "Google Chrome";
666#elif defined(CHROMIUM_BUILD)
667 branding = "Chromium";
668#else
669 branding = "Unknown Branding";
[email protected]a9ff2c02010-05-13 17:33:05670#endif
[email protected]ff4c1d82010-08-04 16:58:12671 properties->SetString("branding", branding);
[email protected]a9ff2c02010-05-13 17:33:05672
673 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
[email protected]ff4c1d82010-08-04 16:58:12674 return_value->Set("properties", properties);
[email protected]a9ff2c02010-05-13 17:33:05675
[email protected]ff4c1d82010-08-04 16:58:12676 return_value->SetInteger("browser_pid", base::GetCurrentProcId());
[email protected]ef413ca2010-05-25 21:09:14677 // Add info about all windows in a list of dictionaries, one dictionary
678 // item per window.
679 ListValue* windows = new ListValue;
680 int windex = 0;
681 for (BrowserList::const_iterator it = BrowserList::begin();
682 it != BrowserList::end();
683 ++it, ++windex) {
684 DictionaryValue* browser_item = new DictionaryValue;
685 browser = *it;
[email protected]ff4c1d82010-08-04 16:58:12686 browser_item->SetInteger("index", windex);
[email protected]ef413ca2010-05-25 21:09:14687 // Window properties
688 gfx::Rect rect = browser->window()->GetRestoredBounds();
[email protected]ff4c1d82010-08-04 16:58:12689 browser_item->SetInteger("x", rect.x());
690 browser_item->SetInteger("y", rect.y());
691 browser_item->SetInteger("width", rect.width());
692 browser_item->SetInteger("height", rect.height());
693 browser_item->SetBoolean("fullscreen",
[email protected]ef413ca2010-05-25 21:09:14694 browser->window()->IsFullscreen());
[email protected]ff4c1d82010-08-04 16:58:12695 browser_item->SetInteger("selected_tab", browser->selected_index());
696 browser_item->SetBoolean("incognito",
[email protected]ef413ca2010-05-25 21:09:14697 browser->profile()->IsOffTheRecord());
698 // For each window, add info about all tabs in a list of dictionaries,
699 // one dictionary item per tab.
700 ListValue* tabs = new ListValue;
701 for (int i = 0; i < browser->tab_count(); ++i) {
702 TabContents* tc = browser->GetTabContentsAt(i);
703 DictionaryValue* tab = new DictionaryValue;
[email protected]ff4c1d82010-08-04 16:58:12704 tab->SetInteger("index", i);
705 tab->SetString("url", tc->GetURL().spec());
706 tab->SetInteger("renderer_pid",
[email protected]ef413ca2010-05-25 21:09:14707 base::GetProcId(tc->GetRenderProcessHost()->GetHandle()));
[email protected]ff4c1d82010-08-04 16:58:12708 tab->Set("infobars", GetInfobarsInfo(tc));
[email protected]ef413ca2010-05-25 21:09:14709 tabs->Append(tab);
710 }
[email protected]ff4c1d82010-08-04 16:58:12711 browser_item->Set("tabs", tabs);
[email protected]ef413ca2010-05-25 21:09:14712
713 windows->Append(browser_item);
714 }
[email protected]ff4c1d82010-08-04 16:58:12715 return_value->Set("windows", windows);
[email protected]ef413ca2010-05-25 21:09:14716
[email protected]ff4c1d82010-08-04 16:58:12717 return_value->SetString("child_process_path",
[email protected]ef413ca2010-05-25 21:09:14718 ChildProcessHost::GetChildPath(true).value());
719 // Child processes are the processes for plugins and other workers.
720 // Add all child processes in a list of dictionaries, one dictionary item
721 // per child process.
722 ListValue* child_processes = new ListValue;
[email protected]26adfd312010-07-20 01:04:46723 base::WaitableEvent event(true /* manual reset */,
724 false /* not initially signaled */);
725 CHECK(ChromeThread::PostTask(
726 ChromeThread::IO, FROM_HERE,
727 new GetChildProcessHostInfoTask(&event, child_processes)));
728 event.Wait();
[email protected]ff4c1d82010-08-04 16:58:12729 return_value->Set("child_processes", child_processes);
[email protected]ef413ca2010-05-25 21:09:14730
731 // Add all extension processes in a list of dictionaries, one dictionary
732 // item per extension process.
733 ListValue* extension_processes = new ListValue;
734 ProfileManager* profile_manager = g_browser_process->profile_manager();
735 for (ProfileManager::const_iterator it = profile_manager->begin();
736 it != profile_manager->end(); ++it) {
737 ExtensionProcessManager* process_manager =
738 (*it)->GetExtensionProcessManager();
739 ExtensionProcessManager::const_iterator jt;
740 for (jt = process_manager->begin(); jt != process_manager->end(); ++jt) {
741 ExtensionHost* ex_host = *jt;
742 // Don't add dead extension processes.
743 if (!ex_host->IsRenderViewLive())
744 continue;
745 DictionaryValue* item = new DictionaryValue;
[email protected]ff4c1d82010-08-04 16:58:12746 item->SetString("name", ex_host->extension()->name());
[email protected]ef413ca2010-05-25 21:09:14747 item->SetInteger(
[email protected]ff4c1d82010-08-04 16:58:12748 "pid",
[email protected]ef413ca2010-05-25 21:09:14749 base::GetProcId(ex_host->render_process_host()->GetHandle()));
750 extension_processes->Append(item);
751 }
752 }
[email protected]ff4c1d82010-08-04 16:58:12753 return_value->Set("extension_processes", extension_processes);
[email protected]7c983cc2010-07-16 11:33:34754 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
[email protected]a9ff2c02010-05-13 17:33:05755}
756
[email protected]24e2b102010-04-29 17:56:47757// Sample json input: { "command": "GetHistoryInfo",
758// "search_text": "some text" }
[email protected]e6e376e2010-04-19 21:41:36759// Refer chrome/test/pyautolib/history_info.py for sample json output.
[email protected]53329582010-05-14 21:10:58760void AutomationProvider::GetHistoryInfo(Browser* browser,
761 DictionaryValue* args,
762 IPC::Message* reply_message) {
[email protected]e6e376e2010-04-19 21:41:36763 consumer_.CancelAllRequests();
764
[email protected]e53668962010-06-23 15:35:25765 string16 search_text;
766 args->GetString("search_text", &search_text);
[email protected]e6e376e2010-04-19 21:41:36767
768 // Fetch history.
769 HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
770 history::QueryOptions options;
771 // The observer owns itself. It deletes itself after it fetches history.
772 AutomationProviderHistoryObserver* history_observer =
773 new AutomationProviderHistoryObserver(this, reply_message);
774 hs->QueryHistory(
775 search_text,
776 options,
777 &consumer_,
778 NewCallback(history_observer,
779 &AutomationProviderHistoryObserver::HistoryQueryComplete));
780}
781
[email protected]bbe6aa02010-05-07 17:27:29782// Sample json input: { "command": "AddHistoryItem",
783// "item": { "URL": "http://www.google.com",
784// "title": "Google", # optional
785// "time": 12345 # optional (time_t)
786// } }
787// Refer chrome/test/pyautolib/pyauto.py for details on input.
[email protected]53329582010-05-14 21:10:58788void AutomationProvider::AddHistoryItem(Browser* browser,
789 DictionaryValue* args,
790 IPC::Message* reply_message) {
[email protected]bbe6aa02010-05-07 17:27:29791 DictionaryValue* item = NULL;
[email protected]ff4c1d82010-08-04 16:58:12792 args->GetDictionary("item", &item);
[email protected]bbe6aa02010-05-07 17:27:29793 string16 url_text;
[email protected]e53668962010-06-23 15:35:25794 string16 title;
[email protected]bbe6aa02010-05-07 17:27:29795 base::Time time = base::Time::Now();
[email protected]7c983cc2010-07-16 11:33:34796 AutomationJSONReply reply(this, reply_message);
[email protected]bbe6aa02010-05-07 17:27:29797
[email protected]7c983cc2010-07-16 11:33:34798 if (!item->GetString("url", &url_text)) {
799 reply.SendError("bad args (no URL in dict?)");
800 return;
[email protected]bbe6aa02010-05-07 17:27:29801 }
[email protected]7c983cc2010-07-16 11:33:34802 GURL gurl(url_text);
803 item->GetString("title", &title); // Don't care if it fails.
804 int it;
805 double dt;
[email protected]ff4c1d82010-08-04 16:58:12806 if (item->GetInteger("time", &it))
[email protected]7c983cc2010-07-16 11:33:34807 time = base::Time::FromTimeT(it);
[email protected]ff4c1d82010-08-04 16:58:12808 else if (item->GetReal("time", &dt))
[email protected]7c983cc2010-07-16 11:33:34809 time = base::Time::FromDoubleT(dt);
[email protected]f6ff0df2010-07-11 22:41:43810
[email protected]7c983cc2010-07-16 11:33:34811 // Ideas for "dummy" values (e.g. id_scope) came from
812 // chrome/browser/autocomplete/history_contents_provider_unittest.cc
813 HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
814 const void* id_scope = reinterpret_cast<void*>(1);
815 hs->AddPage(gurl, time,
816 id_scope,
817 0,
818 GURL(),
819 PageTransition::LINK,
820 history::RedirectList(),
[email protected]5989f1a2010-08-21 02:21:11821 history::SOURCE_BROWSED,
[email protected]7c983cc2010-07-16 11:33:34822 false);
823 if (title.length())
824 hs->SetPageTitle(gurl, title);
825 reply.SendSuccess(NULL);
[email protected]bbe6aa02010-05-07 17:27:29826}
827
[email protected]2d54c4032010-08-20 00:42:28828DictionaryValue* AutomationProvider::GetDictionaryFromDownloadItem(
829 const DownloadItem* download) {
[email protected]d4adc292010-04-15 18:06:39830 std::map<DownloadItem::DownloadState, std::string> state_to_string;
831 state_to_string[DownloadItem::IN_PROGRESS] = std::string("IN_PROGRESS");
832 state_to_string[DownloadItem::CANCELLED] = std::string("CANCELLED");
833 state_to_string[DownloadItem::REMOVING] = std::string("REMOVING");
834 state_to_string[DownloadItem::COMPLETE] = std::string("COMPLETE");
835
836 std::map<DownloadItem::SafetyState, std::string> safety_state_to_string;
837 safety_state_to_string[DownloadItem::SAFE] = std::string("SAFE");
838 safety_state_to_string[DownloadItem::DANGEROUS] = std::string("DANGEROUS");
839 safety_state_to_string[DownloadItem::DANGEROUS_BUT_VALIDATED] =
840 std::string("DANGEROUS_BUT_VALIDATED");
841
[email protected]2d54c4032010-08-20 00:42:28842 DictionaryValue* dl_item_value = new DictionaryValue;
843 dl_item_value->SetInteger("id", static_cast<int>(download->id()));
844 dl_item_value->SetString("url", download->url().spec());
845 dl_item_value->SetString("referrer_url", download->referrer_url().spec());
846 dl_item_value->SetString("file_name", download->GetFileName().value());
847 dl_item_value->SetString("full_path", download->full_path().value());
848 dl_item_value->SetBoolean("is_paused", download->is_paused());
849 dl_item_value->SetBoolean("open_when_complete",
850 download->open_when_complete());
851 dl_item_value->SetBoolean("is_extension_install",
852 download->is_extension_install());
853 dl_item_value->SetBoolean("is_temporary", download->is_temporary());
854 dl_item_value->SetBoolean("is_otr", download->is_otr()); // off-the-record
855 dl_item_value->SetString("state", state_to_string[download->state()]);
856 dl_item_value->SetString("safety_state",
857 safety_state_to_string[download->safety_state()]);
858 dl_item_value->SetInteger("PercentComplete", download->PercentComplete());
859
860 return dl_item_value;
861}
862
863// Sample json input: { "command": "GetDownloadsInfo" }
864// Refer chrome/test/pyautolib/download_info.py for sample json output.
865void AutomationProvider::GetDownloadsInfo(Browser* browser,
866 DictionaryValue* args,
867 IPC::Message* reply_message) {
868 AutomationJSONReply reply(this, reply_message);
869
870 if (!profile_->HasCreatedDownloadManager()) {
871 reply.SendError("no download manager");
872 return;
873 }
874
875 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
876 std::vector<DownloadItem*> downloads;
877 profile_->GetDownloadManager()->GetAllDownloads(FilePath(), &downloads);
878
[email protected]d4adc292010-04-15 18:06:39879 ListValue* list_of_downloads = new ListValue;
880 for (std::vector<DownloadItem*>::iterator it = downloads.begin();
881 it != downloads.end();
882 it++) { // Fill info about each download item.
[email protected]2d54c4032010-08-20 00:42:28883 list_of_downloads->Append(GetDictionaryFromDownloadItem(*it));
[email protected]d4adc292010-04-15 18:06:39884 }
[email protected]ff4c1d82010-08-04 16:58:12885 return_value->Set("downloads", list_of_downloads);
[email protected]7c983cc2010-07-16 11:33:34886 reply.SendSuccess(return_value.get());
[email protected]d4adc292010-04-15 18:06:39887 // All value objects allocated above are owned by |return_value|
888 // and get freed by it.
889}
890
[email protected]59a611242010-04-02 02:24:04891void AutomationProvider::WaitForDownloadsToComplete(
[email protected]53329582010-05-14 21:10:58892 Browser* browser,
[email protected]59a611242010-04-02 02:24:04893 DictionaryValue* args,
894 IPC::Message* reply_message) {
[email protected]7c983cc2010-07-16 11:33:34895 AutomationJSONReply reply(this, reply_message);
[email protected]59a611242010-04-02 02:24:04896
897 // Look for a quick return.
898 if (!profile_->HasCreatedDownloadManager()) {
[email protected]7c983cc2010-07-16 11:33:34899 reply.SendSuccess(NULL); // No download manager.
900 return;
[email protected]59a611242010-04-02 02:24:04901 }
[email protected]82f37b02010-07-29 22:04:57902 std::vector<DownloadItem*> downloads;
903 profile_->GetDownloadManager()->GetCurrentDownloads(FilePath(), &downloads);
904 if (downloads.empty()) {
[email protected]7c983cc2010-07-16 11:33:34905 reply.SendSuccess(NULL);
[email protected]f6ff0df2010-07-11 22:41:43906 return;
907 }
[email protected]59a611242010-04-02 02:24:04908
909 // The observer owns itself. When the last observed item pings, it
910 // deletes itself.
911 AutomationProviderDownloadItemObserver* item_observer =
912 new AutomationProviderDownloadItemObserver(
913 this, reply_message, downloads.size());
914 for (std::vector<DownloadItem*>::iterator i = downloads.begin();
915 i != downloads.end();
916 i++) {
917 (*i)->AddObserver(item_observer);
918 }
919}
920
[email protected]2d54c4032010-08-20 00:42:28921namespace {
922
923DownloadItem* GetDownloadItemFromId(int id, DownloadManager* download_manager) {
924 std::vector<DownloadItem*> downloads;
925 download_manager->GetAllDownloads(FilePath(), &downloads);
926 DownloadItem* selected_item = NULL;
927
928 for (std::vector<DownloadItem*>::iterator it = downloads.begin();
929 it != downloads.end();
930 it++) {
931 DownloadItem* curr_item = *it;
932 if (curr_item->id() == id) {
933 selected_item = curr_item;
934 break;
935 }
936 }
937 return selected_item;
938}
939
940} // namespace
941
942// See PerformActionOnDownload() in chrome/test/pyautolib/pyauto.py for sample
943// json input and output.
944void AutomationProvider::PerformActionOnDownload(Browser* browser,
945 DictionaryValue* args,
946 IPC::Message* reply_message) {
947 int id;
948 std::string action;
949
950 if (!profile_->HasCreatedDownloadManager()) {
951 AutomationJSONReply(this, reply_message).SendError("No download manager.");
952 return;
953 }
954 if (!args->GetInteger("id", &id) || !args->GetString("action", &action)) {
955 AutomationJSONReply(this, reply_message).SendError(
956 "Must include int id and string action.");
957 return;
958 }
959
960 DownloadManager* download_manager = profile_->GetDownloadManager();
961 DownloadItem* selected_item = GetDownloadItemFromId(id, download_manager);
962 if (!selected_item) {
963 AutomationJSONReply(this, reply_message).SendError(
964 StringPrintf("No download with an id of %d\n", id));
965 return;
966 }
967
968 if (action == "open") {
969 selected_item->AddObserver(
970 new AutomationProviderDownloadUpdatedObserver(
971 this, reply_message, true));
972 selected_item->OpenDownload();
973 } else if (action == "toggle_open_files_like_this") {
974 selected_item->OpenFilesBasedOnExtension(
975 !selected_item->ShouldOpenFileBasedOnExtension());
976 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
977 } else if (action == "remove") {
978 download_manager->AddObserver(
979 new AutomationProviderDownloadModelChangedObserver(
980 this, reply_message, download_manager));
981 selected_item->Remove(false);
982 } else if (action == "decline_dangerous_download") {
983 // This is the same as removing the file with delete_file=true.
984 download_manager->AddObserver(
985 new AutomationProviderDownloadModelChangedObserver(
986 this, reply_message, download_manager));
987 selected_item->Remove(true);
988 } else if (action == "save_dangerous_download") {
989 selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
990 this, reply_message, false));
991 selected_item->DangerousDownloadValidated();
992 } else if (action == "toggle_pause") {
993 selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
994 this, reply_message, false));
995 // This will still return if download has already completed.
996 selected_item->TogglePause();
997 } else if (action == "cancel") {
998 selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
999 this, reply_message, false));
1000 selected_item->Cancel(true);
1001 } else {
1002 AutomationJSONReply(this, reply_message).SendError(
1003 StringPrintf("Invalid action '%s' given.", action.c_str()));
1004 }
1005}
1006
1007// See WaitForAlwaysOpenDownloadTypeToOpen() in chrome/test/pyautolib/pyauto.py
1008// for sample json input.
1009// Sample json output: {}
1010void AutomationProvider::WaitForAlwaysOpenDownloadTypeToOpen(
1011 Browser* browser, DictionaryValue* args, IPC::Message* reply_message) {
1012 int id;
1013
1014 if (!profile_->HasCreatedDownloadManager()) {
1015 AutomationJSONReply(this, reply_message).SendError("No download manager.");
1016 return;
1017 }
1018 if (!args->GetInteger("id", &id)) {
1019 AutomationJSONReply(this, reply_message).SendError(
1020 "Must include int id.");
1021 return;
1022 }
1023
1024 DownloadItem* selected_item = GetDownloadItemFromId(
1025 id, profile_->GetDownloadManager());
1026 if (!selected_item) {
1027 AutomationJSONReply(this, reply_message).SendError(
1028 StringPrintf("No download with an id of %d\n", id));
1029 return;
1030 }
1031
1032 if (selected_item->auto_opened()) {
1033 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
1034 return;
1035 }
1036 // The observer will reply after the download is opened.
1037 selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
1038 this, reply_message, true));
1039}
1040
[email protected]24e2b102010-04-29 17:56:471041// Sample json input: { "command": "GetPrefsInfo" }
1042// Refer chrome/test/pyautolib/prefs_info.py for sample json output.
[email protected]53329582010-05-14 21:10:581043void AutomationProvider::GetPrefsInfo(Browser* browser,
1044 DictionaryValue* args,
[email protected]24e2b102010-04-29 17:56:471045 IPC::Message* reply_message) {
[email protected]24e2b102010-04-29 17:56:471046 const PrefService::PreferenceSet& prefs =
1047 profile_->GetPrefs()->preference_set();
1048 DictionaryValue* items = new DictionaryValue;
1049 for (PrefService::PreferenceSet::const_iterator it = prefs.begin();
1050 it != prefs.end(); ++it) {
1051 items->Set((*it)->name(), (*it)->GetValue()->DeepCopy());
1052 }
1053 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
[email protected]ff4c1d82010-08-04 16:58:121054 return_value->Set("prefs", items); // return_value owns items.
[email protected]7c983cc2010-07-16 11:33:341055 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
[email protected]24e2b102010-04-29 17:56:471056}
1057
1058// Sample json input: { "command": "SetPrefs", "path": path, "value": value }
[email protected]53329582010-05-14 21:10:581059void AutomationProvider::SetPrefs(Browser* browser,
1060 DictionaryValue* args,
[email protected]24e2b102010-04-29 17:56:471061 IPC::Message* reply_message) {
[email protected]57ecc4b2010-08-11 03:02:511062 std::string path;
[email protected]24e2b102010-04-29 17:56:471063 Value* val;
[email protected]7c983cc2010-07-16 11:33:341064 AutomationJSONReply reply(this, reply_message);
[email protected]57ecc4b2010-08-11 03:02:511065 if (args->GetString("path", &path) && args->Get("value", &val)) {
[email protected]24e2b102010-04-29 17:56:471066 PrefService* pref_service = profile_->GetPrefs();
1067 const PrefService::Preference* pref =
1068 pref_service->FindPreference(path.c_str());
1069 if (!pref) { // Not a registered pref.
[email protected]7c983cc2010-07-16 11:33:341070 reply.SendError("pref not registered.");
1071 return;
[email protected]24e2b102010-04-29 17:56:471072 } else if (pref->IsManaged()) { // Do not attempt to change a managed pref.
[email protected]7c983cc2010-07-16 11:33:341073 reply.SendError("pref is managed. cannot be changed.");
1074 return;
[email protected]24e2b102010-04-29 17:56:471075 } else { // Set the pref.
1076 pref_service->Set(path.c_str(), *val);
1077 }
1078 } else {
[email protected]7c983cc2010-07-16 11:33:341079 reply.SendError("no pref path or value given.");
1080 return;
[email protected]24e2b102010-04-29 17:56:471081 }
1082
[email protected]7c983cc2010-07-16 11:33:341083 reply.SendSuccess(NULL);
[email protected]24e2b102010-04-29 17:56:471084}
1085
[email protected]53329582010-05-14 21:10:581086// Sample json input: { "command": "GetOmniboxInfo" }
1087// Refer chrome/test/pyautolib/omnibox_info.py for sample json output.
1088void AutomationProvider::GetOmniboxInfo(Browser* browser,
1089 DictionaryValue* args,
1090 IPC::Message* reply_message) {
[email protected]53329582010-05-14 21:10:581091 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
1092
1093 LocationBar* loc_bar = browser->window()->GetLocationBar();
1094 AutocompleteEditView* edit_view = loc_bar->location_entry();
1095 AutocompleteEditModel* model = edit_view->model();
1096
1097 // Fill up matches.
1098 ListValue* matches = new ListValue;
1099 const AutocompleteResult& result = model->result();
1100 for (AutocompleteResult::const_iterator i = result.begin();
1101 i != result.end(); ++i) {
1102 const AutocompleteMatch& match = *i;
1103 DictionaryValue* item = new DictionaryValue; // owned by return_value
[email protected]ff4c1d82010-08-04 16:58:121104 item->SetString("type", AutocompleteMatch::TypeToString(match.type));
1105 item->SetBoolean("starred", match.starred);
1106 item->SetString("destination_url", match.destination_url.spec());
1107 item->SetString("contents", WideToUTF16Hack(match.contents));
1108 item->SetString("description", WideToUTF16Hack(match.description));
[email protected]53329582010-05-14 21:10:581109 matches->Append(item);
1110 }
[email protected]ff4c1d82010-08-04 16:58:121111 return_value->Set("matches", matches);
[email protected]53329582010-05-14 21:10:581112
1113 // Fill up other properties.
1114 DictionaryValue* properties = new DictionaryValue; // owned by return_value
[email protected]ff4c1d82010-08-04 16:58:121115 properties->SetBoolean("has_focus", model->has_focus());
1116 properties->SetBoolean("query_in_progress", model->query_in_progress());
1117 properties->SetString("keyword", WideToUTF16Hack(model->keyword()));
1118 properties->SetString("text", WideToUTF16Hack(edit_view->GetText()));
1119 return_value->Set("properties", properties);
[email protected]53329582010-05-14 21:10:581120
[email protected]7c983cc2010-07-16 11:33:341121 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
[email protected]53329582010-05-14 21:10:581122}
1123
1124// Sample json input: { "command": "SetOmniboxText",
1125// "text": "goog" }
1126void AutomationProvider::SetOmniboxText(Browser* browser,
1127 DictionaryValue* args,
1128 IPC::Message* reply_message) {
[email protected]a748ff62010-08-14 17:25:321129 string16 text;
[email protected]7c983cc2010-07-16 11:33:341130 AutomationJSONReply reply(this, reply_message);
[email protected]a748ff62010-08-14 17:25:321131 if (!args->GetString("text", &text)) {
[email protected]7c983cc2010-07-16 11:33:341132 reply.SendError("text missing");
1133 return;
[email protected]53329582010-05-14 21:10:581134 }
[email protected]7c983cc2010-07-16 11:33:341135 browser->FocusLocationBar();
1136 LocationBar* loc_bar = browser->window()->GetLocationBar();
1137 AutocompleteEditView* edit_view = loc_bar->location_entry();
1138 edit_view->model()->OnSetFocus(false);
[email protected]a748ff62010-08-14 17:25:321139 edit_view->SetUserText(UTF16ToWideHack(text));
[email protected]7c983cc2010-07-16 11:33:341140 reply.SendSuccess(NULL);
[email protected]53329582010-05-14 21:10:581141}
1142
1143// Sample json input: { "command": "OmniboxMovePopupSelection",
1144// "count": 1 }
1145// Negative count implies up, positive implies down. Count values will be
1146// capped by the size of the popup list.
1147void AutomationProvider::OmniboxMovePopupSelection(
1148 Browser* browser,
1149 DictionaryValue* args,
1150 IPC::Message* reply_message) {
[email protected]53329582010-05-14 21:10:581151 int count;
[email protected]7c983cc2010-07-16 11:33:341152 AutomationJSONReply reply(this, reply_message);
[email protected]ff4c1d82010-08-04 16:58:121153 if (!args->GetInteger("count", &count)) {
[email protected]7c983cc2010-07-16 11:33:341154 reply.SendError("count missing");
1155 return;
[email protected]53329582010-05-14 21:10:581156 }
[email protected]7c983cc2010-07-16 11:33:341157 LocationBar* loc_bar = browser->window()->GetLocationBar();
1158 AutocompleteEditModel* model = loc_bar->location_entry()->model();
1159 model->OnUpOrDownKeyPressed(count);
1160 reply.SendSuccess(NULL);
[email protected]53329582010-05-14 21:10:581161}
1162
1163// Sample json input: { "command": "OmniboxAcceptInput" }
1164void AutomationProvider::OmniboxAcceptInput(Browser* browser,
1165 DictionaryValue* args,
1166 IPC::Message* reply_message) {
[email protected]cb84d642010-06-10 00:56:281167 NavigationController& controller =
1168 browser->GetSelectedTabContents()->controller();
[email protected]c1654832010-05-17 23:22:121169 // Setup observer to wait until the selected item loads.
1170 NotificationObserver* observer =
[email protected]cb84d642010-06-10 00:56:281171 new OmniboxAcceptNotificationObserver(&controller, this, reply_message);
[email protected]c1654832010-05-17 23:22:121172 notification_observer_list_.AddObserver(observer);
[email protected]53329582010-05-14 21:10:581173
1174 browser->window()->GetLocationBar()->AcceptInput();
[email protected]53329582010-05-14 21:10:581175}
1176
[email protected]a3cd5022010-06-16 18:25:291177// Sample json input: { "command": "GetInitialLoadTimes" }
1178// Refer to InitialLoadObserver::GetTimingInformation() for sample output.
1179void AutomationProvider::GetInitialLoadTimes(
1180 Browser*,
1181 DictionaryValue*,
1182 IPC::Message* reply_message) {
1183 scoped_ptr<DictionaryValue> return_value(
1184 initial_load_observer_->GetTimingInformation());
[email protected]f6ff0df2010-07-11 22:41:431185
1186 std::string json_return;
1187 base::JSONWriter::Write(return_value.get(), false, &json_return);
1188 AutomationMsg_SendJSONRequest::WriteReplyParams(
1189 reply_message, json_return, true);
1190 Send(reply_message);
[email protected]a3cd5022010-06-16 18:25:291191}
1192
[email protected]f7d48012010-05-06 08:17:051193// Sample json input: { "command": "GetPluginsInfo" }
1194// Refer chrome/test/pyautolib/plugins_info.py for sample json output.
[email protected]53329582010-05-14 21:10:581195void AutomationProvider::GetPluginsInfo(Browser* browser,
1196 DictionaryValue* args,
[email protected]f7d48012010-05-06 08:17:051197 IPC::Message* reply_message) {
[email protected]f7d48012010-05-06 08:17:051198 std::vector<WebPluginInfo> plugins;
1199 NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins);
1200 ListValue* items = new ListValue;
1201 for (std::vector<WebPluginInfo>::const_iterator it = plugins.begin();
1202 it != plugins.end();
1203 ++it) {
1204 DictionaryValue* item = new DictionaryValue;
[email protected]ff4c1d82010-08-04 16:58:121205 item->SetString("name", it->name);
1206 item->SetString("path", it->path.value());
1207 item->SetString("version", it->version);
1208 item->SetString("desc", it->desc);
1209 item->SetBoolean("enabled", it->enabled);
[email protected]f7d48012010-05-06 08:17:051210 // Add info about mime types.
1211 ListValue* mime_types = new ListValue();
1212 for (std::vector<WebPluginMimeType>::const_iterator type_it =
1213 it->mime_types.begin();
1214 type_it != it->mime_types.end();
1215 ++type_it) {
1216 DictionaryValue* mime_type = new DictionaryValue();
[email protected]ff4c1d82010-08-04 16:58:121217 mime_type->SetString("mimeType", type_it->mime_type);
1218 mime_type->SetString("description", type_it->description);
[email protected]f7d48012010-05-06 08:17:051219
1220 ListValue* file_extensions = new ListValue();
1221 for (std::vector<std::string>::const_iterator ext_it =
1222 type_it->file_extensions.begin();
1223 ext_it != type_it->file_extensions.end();
1224 ++ext_it) {
1225 file_extensions->Append(new StringValue(*ext_it));
1226 }
[email protected]ff4c1d82010-08-04 16:58:121227 mime_type->Set("fileExtensions", file_extensions);
[email protected]f7d48012010-05-06 08:17:051228
1229 mime_types->Append(mime_type);
1230 }
[email protected]ff4c1d82010-08-04 16:58:121231 item->Set("mimeTypes", mime_types);
[email protected]f7d48012010-05-06 08:17:051232 items->Append(item);
1233 }
1234 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
[email protected]ff4c1d82010-08-04 16:58:121235 return_value->Set("plugins", items); // return_value owns items.
[email protected]f7d48012010-05-06 08:17:051236
[email protected]7c983cc2010-07-16 11:33:341237 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
[email protected]f7d48012010-05-06 08:17:051238}
1239
1240// Sample json input:
1241// { "command": "EnablePlugin",
1242// "path": "/Library/Internet Plug-Ins/Flash Player.plugin" }
[email protected]53329582010-05-14 21:10:581243void AutomationProvider::EnablePlugin(Browser* browser,
1244 DictionaryValue* args,
[email protected]f7d48012010-05-06 08:17:051245 IPC::Message* reply_message) {
[email protected]f7d48012010-05-06 08:17:051246 FilePath::StringType path;
[email protected]7c983cc2010-07-16 11:33:341247 AutomationJSONReply reply(this, reply_message);
[email protected]ff4c1d82010-08-04 16:58:121248 if (!args->GetString("path", &path)) {
[email protected]7c983cc2010-07-16 11:33:341249 reply.SendError("path not specified.");
1250 return;
[email protected]f6ff0df2010-07-11 22:41:431251 } else if (!NPAPI::PluginList::Singleton()->EnablePlugin(FilePath(path))) {
[email protected]7c983cc2010-07-16 11:33:341252 reply.SendError(StringPrintf("Could not enable plugin for path %s.",
1253 path.c_str()));
1254 return;
[email protected]f6ff0df2010-07-11 22:41:431255 }
[email protected]7c983cc2010-07-16 11:33:341256 reply.SendSuccess(NULL);
[email protected]f7d48012010-05-06 08:17:051257}
1258
1259// Sample json input:
1260// { "command": "DisablePlugin",
1261// "path": "/Library/Internet Plug-Ins/Flash Player.plugin" }
[email protected]53329582010-05-14 21:10:581262void AutomationProvider::DisablePlugin(Browser* browser,
1263 DictionaryValue* args,
1264 IPC::Message* reply_message) {
[email protected]f7d48012010-05-06 08:17:051265 FilePath::StringType path;
[email protected]7c983cc2010-07-16 11:33:341266 AutomationJSONReply reply(this, reply_message);
[email protected]ff4c1d82010-08-04 16:58:121267 if (!args->GetString("path", &path)) {
[email protected]7c983cc2010-07-16 11:33:341268 reply.SendError("path not specified.");
1269 return;
[email protected]f6ff0df2010-07-11 22:41:431270 } else if (!NPAPI::PluginList::Singleton()->DisablePlugin(FilePath(path))) {
[email protected]7c983cc2010-07-16 11:33:341271 reply.SendError(StringPrintf("Could not disable plugin for path %s.",
1272 path.c_str()));
1273 return;
[email protected]f6ff0df2010-07-11 22:41:431274 }
[email protected]7c983cc2010-07-16 11:33:341275 reply.SendSuccess(NULL);
[email protected]f7d48012010-05-06 08:17:051276}
1277
[email protected]7060bb292010-06-24 00:52:491278// Sample json input:
1279// { "command": "SaveTabContents",
1280// "tab_index": 0,
1281// "filename": <a full pathname> }
1282// Sample json output:
1283// {}
1284void AutomationProvider::SaveTabContents(Browser* browser,
1285 DictionaryValue* args,
1286 IPC::Message* reply_message) {
[email protected]7060bb292010-06-24 00:52:491287 int tab_index = 0;
1288 FilePath::StringType filename;
1289 FilePath::StringType parent_directory;
1290 TabContents* tab_contents = NULL;
1291
[email protected]ff4c1d82010-08-04 16:58:121292 if (!args->GetInteger("tab_index", &tab_index) ||
1293 !args->GetString("filename", &filename)) {
[email protected]26adfd312010-07-20 01:04:461294 AutomationJSONReply(this, reply_message).SendError(
1295 "tab_index or filename param missing");
[email protected]7c983cc2010-07-16 11:33:341296 return;
[email protected]7060bb292010-06-24 00:52:491297 } else {
1298 tab_contents = browser->GetTabContentsAt(tab_index);
1299 if (!tab_contents) {
[email protected]26adfd312010-07-20 01:04:461300 AutomationJSONReply(this, reply_message).SendError(
1301 "no tab at tab_index");
[email protected]7060bb292010-06-24 00:52:491302 return;
1303 }
1304 }
[email protected]7c983cc2010-07-16 11:33:341305 // We're doing a SAVE_AS_ONLY_HTML so the the directory path isn't
1306 // used. Nevertheless, SavePackage requires it be valid. Sigh.
1307 parent_directory = FilePath(filename).DirName().value();
1308 if (!tab_contents->SavePage(FilePath(filename), FilePath(parent_directory),
1309 SavePackage::SAVE_AS_ONLY_HTML)) {
[email protected]26adfd312010-07-20 01:04:461310 AutomationJSONReply(this, reply_message).SendError(
1311 "Could not initiate SavePage");
[email protected]7c983cc2010-07-16 11:33:341312 return;
1313 }
1314 // The observer will delete itself when done.
1315 new SavePackageNotificationObserver(tab_contents->save_package(),
1316 this, reply_message);
[email protected]7060bb292010-06-24 00:52:491317}
1318
[email protected]c5aa5322010-07-15 19:00:071319// Refer to ImportSettings() in chrome/test/pyautolib/pyauto.py for sample
1320// json input.
1321// Sample json output: "{}"
1322void AutomationProvider::ImportSettings(Browser* browser,
1323 DictionaryValue* args,
1324 IPC::Message* reply_message) {
[email protected]c5aa5322010-07-15 19:00:071325 // Map from the json string passed over to the import item masks.
1326 std::map<std::string, ImportItem> string_to_import_item;
1327 string_to_import_item["HISTORY"] = importer::HISTORY;
1328 string_to_import_item["FAVORITES"] = importer::FAVORITES;
1329 string_to_import_item["COOKIES"] = importer::COOKIES;
1330 string_to_import_item["PASSWORDS"] = importer::PASSWORDS;
1331 string_to_import_item["SEARCH_ENGINES"] = importer::SEARCH_ENGINES;
1332 string_to_import_item["HOME_PAGE"] = importer::HOME_PAGE;
1333 string_to_import_item["ALL"] = importer::ALL;
1334
[email protected]a748ff62010-08-14 17:25:321335 string16 browser_name;
[email protected]c5aa5322010-07-15 19:00:071336 int import_items = 0;
1337 ListValue* import_items_list = NULL;
1338 bool first_run;
1339
[email protected]a748ff62010-08-14 17:25:321340 if (!args->GetString("import_from", &browser_name) ||
[email protected]ff4c1d82010-08-04 16:58:121341 !args->GetBoolean("first_run", &first_run) ||
1342 !args->GetList("import_items", &import_items_list)) {
[email protected]7c983cc2010-07-16 11:33:341343 AutomationJSONReply(this, reply_message).SendError(
1344 "Incorrect type for one or more of the arguments.");
[email protected]c5aa5322010-07-15 19:00:071345 return;
1346 }
1347
1348 int num_items = import_items_list->GetSize();
1349 for (int i = 0; i < num_items; i++) {
1350 std::string item;
1351 import_items_list->GetString(i, &item);
1352 // If the provided string is not part of the map, error out.
1353 if (!ContainsKey(string_to_import_item, item)) {
[email protected]7c983cc2010-07-16 11:33:341354 AutomationJSONReply(this, reply_message).SendError(
1355 "Invalid item string found in import_items.");
[email protected]c5aa5322010-07-15 19:00:071356 return;
1357 }
1358 import_items |= string_to_import_item[item];
1359 }
1360
1361 ImporterHost* importer_host = new ImporterHost();
1362 // Get the correct ProfileInfo based on the browser they user provided.
1363 importer::ProfileInfo profile_info;
1364 int num_browsers = importer_host->GetAvailableProfileCount();
1365 int i = 0;
1366 for ( ; i < num_browsers; i++) {
[email protected]a748ff62010-08-14 17:25:321367 string16 name = WideToUTF16Hack(importer_host->GetSourceProfileNameAt(i));
[email protected]c5aa5322010-07-15 19:00:071368 if (name == browser_name) {
1369 profile_info = importer_host->GetSourceProfileInfoAt(i);
1370 break;
1371 }
1372 }
1373 // If we made it to the end of the loop, then the input was bad.
1374 if (i == num_browsers) {
[email protected]7c983cc2010-07-16 11:33:341375 AutomationJSONReply(this, reply_message).SendError(
1376 "Invalid browser name string found.");
[email protected]c5aa5322010-07-15 19:00:071377 return;
1378 }
1379
1380 Profile* profile = browser->profile();
1381
1382 importer_host->SetObserver(
1383 new AutomationProviderImportSettingsObserver(this, reply_message));
1384 importer_host->StartImportSettings(profile_info, profile, import_items,
1385 new ProfileWriter(profile), first_run);
1386}
1387
[email protected]95222282010-07-26 17:43:021388namespace {
1389
1390// Translates a dictionary password to a PasswordForm struct.
1391webkit_glue::PasswordForm GetPasswordFormFromDict(
1392 const DictionaryValue& password_dict) {
1393
1394 // If the time is specified, change time to the specified time.
1395 base::Time time = base::Time::Now();
1396 int it;
1397 double dt;
[email protected]ff4c1d82010-08-04 16:58:121398 if (password_dict.GetInteger("time", &it))
[email protected]95222282010-07-26 17:43:021399 time = base::Time::FromTimeT(it);
[email protected]ff4c1d82010-08-04 16:58:121400 else if (password_dict.GetReal("time", &dt))
[email protected]95222282010-07-26 17:43:021401 time = base::Time::FromDoubleT(dt);
1402
1403 std::string signon_realm;
1404 string16 username_value;
1405 string16 password_value;
1406 string16 origin_url_text;
1407 string16 username_element;
1408 string16 password_element;
1409 string16 submit_element;
1410 string16 action_target_text;
1411 bool blacklist = false;
1412 string16 old_password_element;
1413 string16 old_password_value;
1414
1415 // We don't care if any of these fail - they are either optional or checked
1416 // before this function is called.
[email protected]ff4c1d82010-08-04 16:58:121417 password_dict.GetString("signon_realm", &signon_realm);
[email protected]698f7f42010-08-04 19:35:331418 password_dict.GetString("username_value", &username_value);
1419 password_dict.GetString("password_value", &password_value);
1420 password_dict.GetString("origin_url", &origin_url_text);
1421 password_dict.GetString("username_element", &username_element);
1422 password_dict.GetString("password_element", &password_element);
1423 password_dict.GetString("submit_element", &submit_element);
1424 password_dict.GetString("action_target", &action_target_text);
[email protected]ff4c1d82010-08-04 16:58:121425 password_dict.GetBoolean("blacklist", &blacklist);
[email protected]95222282010-07-26 17:43:021426
1427 GURL origin_gurl(origin_url_text);
1428 GURL action_target(action_target_text);
1429
1430 webkit_glue::PasswordForm password_form;
1431 password_form.signon_realm = signon_realm;
1432 password_form.username_value = username_value;
1433 password_form.password_value = password_value;
1434 password_form.origin = origin_gurl;
1435 password_form.username_element = username_element;
1436 password_form.password_element = password_element;
1437 password_form.submit_element = submit_element;
1438 password_form.action = action_target;
1439 password_form.blacklisted_by_user = blacklist;
1440 password_form.date_created = time;
1441
1442 return password_form;
1443}
1444
1445} // namespace
1446
[email protected]5bcfe1672010-07-16 20:51:571447// See AddSavedPassword() in chrome/test/functional/pyauto.py for sample json
1448// input.
1449// Sample json output: { "password_added": true }
1450void AutomationProvider::AddSavedPassword(Browser* browser,
1451 DictionaryValue* args,
1452 IPC::Message* reply_message) {
[email protected]5bcfe1672010-07-16 20:51:571453 AutomationJSONReply reply(this, reply_message);
[email protected]95222282010-07-26 17:43:021454 DictionaryValue* password_dict = NULL;
[email protected]5bcfe1672010-07-16 20:51:571455
[email protected]ff4c1d82010-08-04 16:58:121456 if (!args->GetDictionary("password", &password_dict)) {
[email protected]95222282010-07-26 17:43:021457 reply.SendError("Password must be a dictionary.");
[email protected]5bcfe1672010-07-16 20:51:571458 return;
1459 }
1460
[email protected]95222282010-07-26 17:43:021461 // The signon realm is effectively the primary key and must be included.
1462 // Check here before calling GetPasswordFormFromDict.
[email protected]ff4c1d82010-08-04 16:58:121463 if (!password_dict->HasKey("signon_realm")) {
[email protected]95222282010-07-26 17:43:021464 reply.SendError("Password must include signon_realm.");
1465 return;
1466 }
1467 webkit_glue::PasswordForm new_password =
1468 GetPasswordFormFromDict(*password_dict);
[email protected]5bcfe1672010-07-16 20:51:571469
1470 Profile* profile = browser->profile();
1471 // Use IMPLICIT_ACCESS since new passwords aren't added off the record.
1472 PasswordStore* password_store =
1473 profile->GetPasswordStore(Profile::IMPLICIT_ACCESS);
1474
1475 // Set the return based on whether setting the password succeeded.
1476 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
1477
1478 // It will be null if it's accessed in an incognito window.
1479 if (password_store != NULL) {
1480 password_store->AddLogin(new_password);
[email protected]ff4c1d82010-08-04 16:58:121481 return_value->SetBoolean("password_added", true);
[email protected]5bcfe1672010-07-16 20:51:571482 } else {
[email protected]ff4c1d82010-08-04 16:58:121483 return_value->SetBoolean("password_added", false);
[email protected]5bcfe1672010-07-16 20:51:571484 }
1485
1486 reply.SendSuccess(return_value.get());
1487}
1488
[email protected]95222282010-07-26 17:43:021489// See RemoveSavedPassword() in chrome/test/functional/pyauto.py for sample
1490// json input.
1491// Sample json output: {}
1492void AutomationProvider::RemoveSavedPassword(Browser* browser,
1493 DictionaryValue* args,
1494 IPC::Message* reply_message) {
1495 AutomationJSONReply reply(this, reply_message);
1496 DictionaryValue* password_dict = NULL;
1497
[email protected]ff4c1d82010-08-04 16:58:121498 if (!args->GetDictionary("password", &password_dict)) {
[email protected]95222282010-07-26 17:43:021499 reply.SendError("Password must be a dictionary.");
1500 return;
1501 }
1502
1503 // The signon realm is effectively the primary key and must be included.
1504 // Check here before calling GetPasswordFormFromDict.
[email protected]ff4c1d82010-08-04 16:58:121505 if (!password_dict->HasKey("signon_realm")) {
[email protected]95222282010-07-26 17:43:021506 reply.SendError("Password must include signon_realm.");
1507 return;
1508 }
1509 webkit_glue::PasswordForm to_remove =
1510 GetPasswordFormFromDict(*password_dict);
1511
1512 Profile* profile = browser->profile();
1513 // Use EXPLICIT_ACCESS since passwords can be removed off the record.
1514 PasswordStore* password_store =
1515 profile->GetPasswordStore(Profile::EXPLICIT_ACCESS);
1516
1517 password_store->RemoveLogin(to_remove);
1518 reply.SendSuccess(NULL);
1519}
1520
[email protected]5bcfe1672010-07-16 20:51:571521// Sample json input: { "command": "GetSavedPasswords" }
1522// Refer to GetSavedPasswords() in chrome/test/pyautolib/pyauto.py for sample
1523// json output.
1524void AutomationProvider::GetSavedPasswords(Browser* browser,
1525 DictionaryValue* args,
1526 IPC::Message* reply_message) {
1527 Profile* profile = browser->profile();
1528 // Use EXPLICIT_ACCESS since saved passwords can be retreived off the record.
1529 PasswordStore* password_store =
1530 profile->GetPasswordStore(Profile::EXPLICIT_ACCESS);
1531 password_store->GetAutofillableLogins(
1532 new AutomationProviderGetPasswordsObserver(this, reply_message));
1533 // Observer deletes itself after returning.
1534}
1535
[email protected]a0fc50d72010-07-14 21:14:191536// Refer to ClearBrowsingData() in chrome/test/pyautolib/pyauto.py for sample
1537// json input.
1538// Sample json output: {}
1539void AutomationProvider::ClearBrowsingData(Browser* browser,
1540 DictionaryValue* args,
1541 IPC::Message* reply_message) {
[email protected]a0fc50d72010-07-14 21:14:191542 std::map<std::string, BrowsingDataRemover::TimePeriod> string_to_time_period;
1543 string_to_time_period["LAST_HOUR"] = BrowsingDataRemover::LAST_HOUR;
1544 string_to_time_period["LAST_DAY"] = BrowsingDataRemover::LAST_DAY;
1545 string_to_time_period["LAST_WEEK"] = BrowsingDataRemover::LAST_WEEK;
1546 string_to_time_period["FOUR_WEEKS"] = BrowsingDataRemover::FOUR_WEEKS;
1547 string_to_time_period["EVERYTHING"] = BrowsingDataRemover::EVERYTHING;
1548
1549 std::map<std::string, int> string_to_mask_value;
1550 string_to_mask_value["HISTORY"] = BrowsingDataRemover::REMOVE_HISTORY;
1551 string_to_mask_value["DOWNLOADS"] = BrowsingDataRemover::REMOVE_DOWNLOADS;
1552 string_to_mask_value["COOKIES"] = BrowsingDataRemover::REMOVE_COOKIES;
1553 string_to_mask_value["PASSWORDS"] = BrowsingDataRemover::REMOVE_PASSWORDS;
1554 string_to_mask_value["FORM_DATA"] = BrowsingDataRemover::REMOVE_FORM_DATA;
1555 string_to_mask_value["CACHE"] = BrowsingDataRemover::REMOVE_CACHE;
1556
1557 std::string time_period;
1558 ListValue* to_remove;
[email protected]ff4c1d82010-08-04 16:58:121559 if (!args->GetString("time_period", &time_period) ||
1560 !args->GetList("to_remove", &to_remove)) {
[email protected]7c983cc2010-07-16 11:33:341561 AutomationJSONReply(this, reply_message).SendError(
1562 "time_period must be a string and to_remove a list.");
[email protected]a0fc50d72010-07-14 21:14:191563 return;
1564 }
1565
1566 int remove_mask = 0;
1567 int num_removals = to_remove->GetSize();
1568 for (int i = 0; i < num_removals; i++) {
1569 std::string removal;
1570 to_remove->GetString(i, &removal);
1571 // If the provided string is not part of the map, then error out.
1572 if (!ContainsKey(string_to_mask_value, removal)) {
[email protected]7c983cc2010-07-16 11:33:341573 AutomationJSONReply(this, reply_message).SendError(
1574 "Invalid browsing data string found in to_remove.");
[email protected]a0fc50d72010-07-14 21:14:191575 return;
1576 }
1577 remove_mask |= string_to_mask_value[removal];
1578 }
1579
1580 if (!ContainsKey(string_to_time_period, time_period)) {
[email protected]7c983cc2010-07-16 11:33:341581 AutomationJSONReply(this, reply_message).SendError(
1582 "Invalid string for time_period.");
[email protected]a0fc50d72010-07-14 21:14:191583 return;
1584 }
1585
1586 BrowsingDataRemover* remover = new BrowsingDataRemover(
1587 profile(), string_to_time_period[time_period], base::Time());
1588
1589 remover->AddObserver(
1590 new AutomationProviderBrowsingDataObserver(this, reply_message));
1591 remover->Remove(remove_mask);
1592 // BrowsingDataRemover deletes itself using DeleteTask.
1593 // The observer also deletes itself after sending the reply.
1594}
1595
[email protected]3dda5b02010-07-27 16:35:421596namespace {
1597
1598 // Get the TabContents from a dictionary of arguments.
1599 TabContents* GetTabContentsFromDict(const Browser* browser,
1600 const DictionaryValue* args,
1601 std::string* error_message) {
1602 int tab_index;
[email protected]ff4c1d82010-08-04 16:58:121603 if (!args->GetInteger("tab_index", &tab_index)) {
[email protected]3dda5b02010-07-27 16:35:421604 *error_message = "Must include tab_index.";
1605 return NULL;
1606 }
1607
1608 TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
1609 if (!tab_contents) {
1610 *error_message = StringPrintf("No tab at index %d.", tab_index);
1611 return NULL;
1612 }
1613 return tab_contents;
1614 }
1615
1616 // Get the TranslateInfoBarDelegate from TabContents.
1617 TranslateInfoBarDelegate* GetTranslateInfoBarDelegate(
1618 TabContents* tab_contents) {
1619 for (int i = 0; i < tab_contents->infobar_delegate_count(); i++) {
1620 InfoBarDelegate* infobar = tab_contents->GetInfoBarDelegateAt(i);
1621 if (infobar->AsTranslateInfoBarDelegate())
1622 return infobar->AsTranslateInfoBarDelegate();
1623 }
1624 // No translate infobar.
1625 return NULL;
1626 }
1627
1628} // namespace
1629
1630// See GetTranslateInfo() in chrome/test/pyautolib/pyauto.py for sample json
1631// input and output.
1632void AutomationProvider::GetTranslateInfo(Browser* browser,
1633 DictionaryValue* args,
1634 IPC::Message* reply_message) {
1635 std::string error_message;
1636 TabContents* tab_contents = GetTabContentsFromDict(browser, args,
1637 &error_message);
1638 if (!tab_contents) {
1639 AutomationJSONReply(this, reply_message).SendError(error_message);
1640 return;
1641 }
1642
1643 // Get the translate bar if there is one and pass it to the observer.
1644 // The observer will check for null and populate the information accordingly.
1645 TranslateInfoBarDelegate* translate_bar =
1646 GetTranslateInfoBarDelegate(tab_contents);
1647
1648 TabLanguageDeterminedObserver* observer = new TabLanguageDeterminedObserver(
1649 this, reply_message, tab_contents, translate_bar);
1650 // If the language for the page hasn't been loaded yet, then just make
1651 // the observer, otherwise call observe directly.
1652 std::string language = tab_contents->language_state().original_language();
1653 if (!language.empty()) {
1654 observer->Observe(NotificationType::TAB_LANGUAGE_DETERMINED,
1655 Source<TabContents>(tab_contents),
1656 Details<std::string>(&language));
1657 }
1658}
1659
1660// See SelectTranslateOption() in chrome/test/pyautolib/pyauto.py for sample
1661// json input.
1662// Sample json output: {}
1663void AutomationProvider::SelectTranslateOption(Browser* browser,
1664 DictionaryValue* args,
1665 IPC::Message* reply_message) {
1666 std::string option;
1667 std::string error_message;
1668 TabContents* tab_contents = GetTabContentsFromDict(browser, args,
1669 &error_message);
1670 if (!tab_contents) {
1671 AutomationJSONReply(this, reply_message).SendError(error_message);
1672 return;
1673 }
1674
1675 TranslateInfoBarDelegate* translate_bar =
1676 GetTranslateInfoBarDelegate(tab_contents);
1677 if (!translate_bar) {
1678 AutomationJSONReply(this, reply_message)
1679 .SendError("There is no translate bar open.");
1680 return;
1681 }
1682
[email protected]ff4c1d82010-08-04 16:58:121683 if (!args->GetString("option", &option)) {
[email protected]3dda5b02010-07-27 16:35:421684 AutomationJSONReply(this, reply_message).SendError("Must include option");
1685 return;
1686 }
1687
1688 if (option == "translate_page") {
1689 // Make a new notification observer which will send the reply.
1690 new PageTranslatedObserver(this, reply_message, tab_contents);
1691 translate_bar->Translate();
1692 return;
[email protected]da1913e2010-08-04 23:50:151693 } else if (option == "set_target_language") {
1694 string16 target_language;
1695 if (!args->GetString("target_language", &target_language)) {
1696 AutomationJSONReply(this, reply_message).
1697 SendError("Must include target_language string.");
1698 return;
1699 }
1700 // Get the target language index based off of the language name.
1701 int target_language_index = -1;
1702 for (int i = 0; i < translate_bar->GetLanguageCount(); i++) {
1703 if (translate_bar->GetLanguageDisplayableNameAt(i) == target_language) {
1704 target_language_index = i;
1705 break;
1706 }
1707 }
1708 if (target_language_index == -1) {
1709 AutomationJSONReply(this, reply_message)
1710 .SendError("Invalid target language string.");
1711 return;
1712 }
1713 // If the page has already been translated it will be translated again to
1714 // the new language. The observer will wait until the page has been
1715 // translated to reply.
1716 if (translate_bar->type() == TranslateInfoBarDelegate::AFTER_TRANSLATE) {
1717 new PageTranslatedObserver(this, reply_message, tab_contents);
1718 translate_bar->SetTargetLanguage(target_language_index);
1719 return;
1720 }
1721 // Otherwise just send the reply back immediately.
1722 translate_bar->SetTargetLanguage(target_language_index);
1723 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
1724 return_value->SetBoolean("translation_success", true);
1725 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
1726 return;
[email protected]4a47d76122010-08-10 18:11:161727 } else if (option == "click_always_translate_lang_button") {
1728 if (!translate_bar->ShouldShowAlwaysTranslateButton()) {
1729 AutomationJSONReply(this, reply_message)
1730 .SendError("Always translate button not showing.");
1731 return;
1732 }
1733 // Clicking 'Always Translate' triggers a translation. The observer will
1734 // wait until the translation is complete before sending the reply.
1735 new PageTranslatedObserver(this, reply_message, tab_contents);
1736 translate_bar->AlwaysTranslatePageLanguage();
1737 return;
[email protected]3dda5b02010-07-27 16:35:421738 }
1739
1740 AutomationJSONReply reply(this, reply_message);
1741 if (option == "never_translate_language") {
1742 if (translate_bar->IsLanguageBlacklisted()) {
1743 reply.SendError("The language was already blacklisted.");
1744 return;
1745 }
1746 translate_bar->ToggleLanguageBlacklist();
1747 reply.SendSuccess(NULL);
1748 } else if (option == "never_translate_site") {
1749 if (translate_bar->IsSiteBlacklisted()) {
1750 reply.SendError("The site was already blacklisted.");
1751 return;
1752 }
1753 translate_bar->ToggleSiteBlacklist();
1754 reply.SendSuccess(NULL);
1755 } else if (option == "toggle_always_translate") {
1756 translate_bar->ToggleAlwaysTranslate();
1757 reply.SendSuccess(NULL);
1758 } else if (option == "revert_translation") {
1759 translate_bar->RevertTranslation();
1760 reply.SendSuccess(NULL);
[email protected]4a47d76122010-08-10 18:11:161761 } else if (option == "click_never_translate_lang_button") {
1762 if (!translate_bar->ShouldShowNeverTranslateButton()) {
1763 reply.SendError("Always translate button not showing.");
1764 return;
1765 }
1766 translate_bar->NeverTranslatePageLanguage();
1767 reply.SendSuccess(NULL);
1768 } else if (option == "decline_translation") {
1769 // This is the function called when an infobar is dismissed or when the
1770 // user clicks the 'Nope' translate button.
1771 translate_bar->TranslationDeclined();
[email protected]a9add882010-08-16 20:37:481772 tab_contents->RemoveInfoBar(translate_bar);
[email protected]4a47d76122010-08-10 18:11:161773 reply.SendSuccess(NULL);
[email protected]3dda5b02010-07-27 16:35:421774 } else {
1775 reply.SendError("Invalid string found for option.");
1776 }
1777}
1778
[email protected]f89ee5d2010-08-02 16:39:121779// See WaitUntilTranslateComplete() in chrome/test/pyautolib/pyauto.py for
1780// sample json input and output.
1781void AutomationProvider::WaitUntilTranslateComplete(
1782 Browser* browser, DictionaryValue* args, IPC::Message* reply_message) {
1783 std::string error_message;
1784 TabContents* tab_contents = GetTabContentsFromDict(browser, args,
1785 &error_message);
1786 if (!tab_contents) {
1787 AutomationJSONReply(this, reply_message).SendError(error_message);
1788 return;
1789 }
1790
[email protected]f89ee5d2010-08-02 16:39:121791 TranslateInfoBarDelegate* translate_bar =
1792 GetTranslateInfoBarDelegate(tab_contents);
1793 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
[email protected]14a0aac2010-08-05 15:52:591794
[email protected]f89ee5d2010-08-02 16:39:121795 if (!translate_bar) {
[email protected]57ecc4b2010-08-11 03:02:511796 return_value->SetBoolean("translation_success", false);
[email protected]14a0aac2010-08-05 15:52:591797 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
1798 return;
[email protected]f89ee5d2010-08-02 16:39:121799 }
[email protected]14a0aac2010-08-05 15:52:591800
1801 // If the translation is still pending, the observer will wait
1802 // for it to finish and then reply.
1803 if (translate_bar->type() == TranslateInfoBarDelegate::TRANSLATING) {
1804 new PageTranslatedObserver(this, reply_message, tab_contents);
1805 return;
1806 }
1807
1808 // Otherwise send back the success or failure of the attempted translation.
1809 return_value->SetBoolean(
[email protected]57ecc4b2010-08-11 03:02:511810 "translation_success",
[email protected]14a0aac2010-08-05 15:52:591811 translate_bar->type() == TranslateInfoBarDelegate::AFTER_TRANSLATE);
1812 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
[email protected]f89ee5d2010-08-02 16:39:121813}
1814
[email protected]4d1929f12010-07-10 00:09:031815// Sample json input: { "command": "GetThemeInfo" }
1816// Refer GetThemeInfo() in chrome/test/pyautolib/pyauto.py for sample output.
1817void AutomationProvider::GetThemeInfo(Browser* browser,
1818 DictionaryValue* args,
1819 IPC::Message* reply_message) {
1820 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
1821 Extension* theme = browser->profile()->GetTheme();
1822 if (theme) {
[email protected]ff4c1d82010-08-04 16:58:121823 return_value->SetString("name", theme->name());
1824 return_value->Set("images", theme->GetThemeImages()->DeepCopy());
1825 return_value->Set("colors", theme->GetThemeColors()->DeepCopy());
1826 return_value->Set("tints", theme->GetThemeTints()->DeepCopy());
[email protected]4d1929f12010-07-10 00:09:031827 }
[email protected]7c983cc2010-07-16 11:33:341828 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
[email protected]4d1929f12010-07-10 00:09:031829}
1830
[email protected]32a69cf2010-08-03 16:27:011831// Sample json input: { "command": "GetExtensionsInfo" }
1832// See GetExtensionsInfo() in chrome/test/pyautolib/pyauto.py for sample json
1833// output.
1834void AutomationProvider::GetExtensionsInfo(Browser* browser,
1835 DictionaryValue* args,
1836 IPC::Message* reply_message) {
1837 AutomationJSONReply reply(this, reply_message);
1838 ExtensionsService* service = profile()->GetExtensionsService();
1839 if (!service) {
1840 reply.SendError("No extensions service.");
1841 }
1842 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
1843 ListValue* extensions_values = new ListValue;
1844 const ExtensionList* extensions = service->extensions();
1845 for (ExtensionList::const_iterator it = extensions->begin();
1846 it != extensions->end(); ++it) {
1847 const Extension* extension = *it;
1848 DictionaryValue* extension_value = new DictionaryValue;
[email protected]ff4c1d82010-08-04 16:58:121849 extension_value->SetString("id", extension->id());
1850 extension_value->SetString("version", extension->VersionString());
1851 extension_value->SetString("name", extension->name());
1852 extension_value->SetString("public_key", extension->public_key());
1853 extension_value->SetString("description", extension->description());
1854 extension_value->SetString("background_url",
[email protected]32a69cf2010-08-03 16:27:011855 extension->background_url().spec());
[email protected]ff4c1d82010-08-04 16:58:121856 extension_value->SetString("options_url",
[email protected]32a69cf2010-08-03 16:27:011857 extension->options_url().spec());
1858 extensions_values->Append(extension_value);
1859 }
[email protected]ff4c1d82010-08-04 16:58:121860 return_value->Set("extensions", extensions_values);
[email protected]32a69cf2010-08-03 16:27:011861 reply.SendSuccess(return_value.get());
1862}
1863
1864// See UninstallExtensionById() in chrome/test/pyautolib/pyauto.py for sample
1865// json input.
1866// Sample json output: {}
1867void AutomationProvider::UninstallExtensionById(Browser* browser,
1868 DictionaryValue* args,
1869 IPC::Message* reply_message) {
1870 AutomationJSONReply reply(this, reply_message);
1871 std::string id;
[email protected]ff4c1d82010-08-04 16:58:121872 if (!args->GetString("id", &id)) {
[email protected]32a69cf2010-08-03 16:27:011873 reply.SendError("Must include string id.");
1874 return;
1875 }
1876 ExtensionsService* service = profile()->GetExtensionsService();
1877 if (!service) {
1878 reply.SendError("No extensions service.");
1879 return;
1880 }
1881 ExtensionUnloadNotificationObserver observer;
1882 service->UninstallExtension(id, false);
1883 reply.SendSuccess(NULL);
1884}
1885
[email protected]55846ad842010-07-09 18:22:561886// Sample json input:
1887// { "command": "GetAutoFillProfile" }
1888// Refer to GetAutoFillProfile() in chrome/test/pyautolib/pyauto.py for sample
1889// json output.
1890void AutomationProvider::GetAutoFillProfile(Browser* browser,
1891 DictionaryValue* args,
1892 IPC::Message* reply_message) {
[email protected]55846ad842010-07-09 18:22:561893 // Get the AutoFillProfiles currently in the database.
1894 int tab_index = 0;
[email protected]ff4c1d82010-08-04 16:58:121895 args->GetInteger("tab_index", &tab_index);
[email protected]55846ad842010-07-09 18:22:561896 TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
[email protected]7c983cc2010-07-16 11:33:341897 AutomationJSONReply reply(this, reply_message);
[email protected]55846ad842010-07-09 18:22:561898
1899 if (tab_contents) {
1900 PersonalDataManager* pdm = tab_contents->profile()->GetOriginalProfile()
1901 ->GetPersonalDataManager();
1902 if (pdm) {
1903 std::vector<AutoFillProfile*> autofill_profiles = pdm->profiles();
1904 std::vector<CreditCard*> credit_cards = pdm->credit_cards();
1905
1906 ListValue* profiles = GetListFromAutoFillProfiles(autofill_profiles);
1907 ListValue* cards = GetListFromCreditCards(credit_cards);
1908
1909 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
1910
[email protected]ff4c1d82010-08-04 16:58:121911 return_value->Set("profiles", profiles);
1912 return_value->Set("credit_cards", cards);
[email protected]7c983cc2010-07-16 11:33:341913 reply.SendSuccess(return_value.get());
[email protected]55846ad842010-07-09 18:22:561914 } else {
[email protected]7c983cc2010-07-16 11:33:341915 reply.SendError("No PersonalDataManager.");
1916 return;
[email protected]55846ad842010-07-09 18:22:561917 }
1918 } else {
[email protected]7c983cc2010-07-16 11:33:341919 reply.SendError("No tab at that index.");
1920 return;
[email protected]55846ad842010-07-09 18:22:561921 }
[email protected]55846ad842010-07-09 18:22:561922}
1923
1924// Refer to FillAutoFillProfile() in chrome/test/pyautolib/pyauto.py for sample
1925// json input.
1926// Sample json output: {}
1927void AutomationProvider::FillAutoFillProfile(Browser* browser,
1928 DictionaryValue* args,
1929 IPC::Message* reply_message) {
[email protected]7c983cc2010-07-16 11:33:341930 AutomationJSONReply reply(this, reply_message);
[email protected]55846ad842010-07-09 18:22:561931 ListValue* profiles = NULL;
1932 ListValue* cards = NULL;
[email protected]ff4c1d82010-08-04 16:58:121933 args->GetList("profiles", &profiles);
1934 args->GetList("credit_cards", &cards);
[email protected]7c983cc2010-07-16 11:33:341935 std::string error_mesg;
[email protected]55846ad842010-07-09 18:22:561936
1937 std::vector<AutoFillProfile> autofill_profiles;
1938 std::vector<CreditCard> credit_cards;
1939 // Create an AutoFillProfile for each of the dictionary profiles.
1940 if (profiles) {
[email protected]7c983cc2010-07-16 11:33:341941 autofill_profiles = GetAutoFillProfilesFromList(*profiles, &error_mesg);
[email protected]55846ad842010-07-09 18:22:561942 }
1943 // Create a CreditCard for each of the dictionary values.
1944 if (cards) {
[email protected]7c983cc2010-07-16 11:33:341945 credit_cards = GetCreditCardsFromList(*cards, &error_mesg);
1946 }
1947 if (!error_mesg.empty()) {
1948 reply.SendError(error_mesg);
1949 return;
[email protected]55846ad842010-07-09 18:22:561950 }
1951
1952 // Save the AutoFillProfiles.
1953 int tab_index = 0;
[email protected]ff4c1d82010-08-04 16:58:121954 args->GetInteger("tab_index", &tab_index);
[email protected]55846ad842010-07-09 18:22:561955 TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
1956
1957 if (tab_contents) {
[email protected]ce6b0122010-07-19 19:07:301958 PersonalDataManager* pdm = tab_contents->profile()
[email protected]55846ad842010-07-09 18:22:561959 ->GetPersonalDataManager();
1960 if (pdm) {
1961 pdm->OnAutoFillDialogApply(profiles? &autofill_profiles : NULL,
1962 cards? &credit_cards : NULL);
1963 } else {
[email protected]7c983cc2010-07-16 11:33:341964 reply.SendError("No PersonalDataManager.");
1965 return;
[email protected]55846ad842010-07-09 18:22:561966 }
1967 } else {
[email protected]7c983cc2010-07-16 11:33:341968 reply.SendError("No tab at that index.");
1969 return;
[email protected]55846ad842010-07-09 18:22:561970 }
[email protected]7c983cc2010-07-16 11:33:341971 reply.SendSuccess(NULL);
[email protected]55846ad842010-07-09 18:22:561972}
1973
1974/* static */
1975ListValue* AutomationProvider::GetListFromAutoFillProfiles(
1976 std::vector<AutoFillProfile*> autofill_profiles) {
1977 ListValue* profiles = new ListValue;
1978
1979 std::map<AutoFillFieldType, std::wstring> autofill_type_to_string
1980 = GetAutoFillFieldToStringMap();
1981
1982 // For each AutoFillProfile, transform it to a dictionary object to return.
1983 for (std::vector<AutoFillProfile*>::iterator it = autofill_profiles.begin();
1984 it != autofill_profiles.end(); ++it) {
1985 AutoFillProfile* profile = *it;
1986 DictionaryValue* profile_info = new DictionaryValue;
[email protected]ff4c1d82010-08-04 16:58:121987 profile_info->SetString("label", profile->Label());
[email protected]55846ad842010-07-09 18:22:561988 // For each of the types, if it has a value, add it to the dictionary.
1989 for (std::map<AutoFillFieldType, std::wstring>::iterator
1990 type_it = autofill_type_to_string.begin();
1991 type_it != autofill_type_to_string.end(); ++type_it) {
1992 string16 value = profile->GetFieldText(AutoFillType(type_it->first));
1993 if (value.length()) { // If there was something stored for that value.
[email protected]99922662010-08-17 16:24:251994 profile_info->SetString(WideToUTF8(type_it->second), value);
[email protected]55846ad842010-07-09 18:22:561995 }
1996 }
1997 profiles->Append(profile_info);
1998 }
1999 return profiles;
2000}
2001
2002/* static */
2003ListValue* AutomationProvider::GetListFromCreditCards(
2004 std::vector<CreditCard*> credit_cards) {
2005 ListValue* cards = new ListValue;
2006
2007 std::map<AutoFillFieldType, std::wstring> credit_card_type_to_string =
2008 GetCreditCardFieldToStringMap();
2009
2010 // For each AutoFillProfile, transform it to a dictionary object to return.
2011 for (std::vector<CreditCard*>::iterator it = credit_cards.begin();
2012 it != credit_cards.end(); ++it) {
2013 CreditCard* card = *it;
2014 DictionaryValue* card_info = new DictionaryValue;
[email protected]ff4c1d82010-08-04 16:58:122015 card_info->SetString("label", card->Label());
[email protected]55846ad842010-07-09 18:22:562016 // For each of the types, if it has a value, add it to the dictionary.
2017 for (std::map<AutoFillFieldType, std::wstring>::iterator type_it =
2018 credit_card_type_to_string.begin();
2019 type_it != credit_card_type_to_string.end(); ++type_it) {
2020 string16 value = card->GetFieldText(AutoFillType(type_it->first));
2021 // If there was something stored for that value.
2022 if (value.length()) {
[email protected]99922662010-08-17 16:24:252023 card_info->SetString(WideToUTF8(type_it->second), value);
[email protected]55846ad842010-07-09 18:22:562024 }
2025 }
2026 cards->Append(card_info);
2027 }
2028 return cards;
2029}
2030
2031/* static */
2032std::vector<AutoFillProfile> AutomationProvider::GetAutoFillProfilesFromList(
[email protected]7c983cc2010-07-16 11:33:342033 const ListValue& profiles, std::string* error_message) {
[email protected]55846ad842010-07-09 18:22:562034 std::vector<AutoFillProfile> autofill_profiles;
2035 DictionaryValue* profile_info = NULL;
2036 string16 profile_label;
2037 string16 current_value;
2038
2039 std::map<AutoFillFieldType, std::wstring> autofill_type_to_string =
2040 GetAutoFillFieldToStringMap();
2041
2042 int num_profiles = profiles.GetSize();
2043 for (int i = 0; i < num_profiles; i++) {
2044 profiles.GetDictionary(i, &profile_info);
2045 profile_info->GetString("label", &profile_label);
2046 // Choose an id of 0 so that a unique id will be created.
2047 AutoFillProfile profile(profile_label, 0);
2048 // Loop through the possible profile types and add those provided.
2049 for (std::map<AutoFillFieldType, std::wstring>::iterator type_it =
2050 autofill_type_to_string.begin();
2051 type_it != autofill_type_to_string.end(); ++type_it) {
[email protected]99922662010-08-17 16:24:252052 if (profile_info->HasKey(WideToUTF8(type_it->second))) {
[email protected]698f7f42010-08-04 19:35:332053 if (profile_info->GetString(WideToUTF8(type_it->second),
2054 &current_value)) {
[email protected]55846ad842010-07-09 18:22:562055 profile.SetInfo(AutoFillType(type_it->first), current_value);
2056 } else {
[email protected]7c983cc2010-07-16 11:33:342057 *error_message= "All values must be strings";
[email protected]55846ad842010-07-09 18:22:562058 break;
2059 }
2060 }
2061 }
2062 autofill_profiles.push_back(profile);
2063 }
2064 return autofill_profiles;
2065}
2066
2067/* static */
2068std::vector<CreditCard> AutomationProvider::GetCreditCardsFromList(
[email protected]7c983cc2010-07-16 11:33:342069 const ListValue& cards, std::string* error_message) {
[email protected]55846ad842010-07-09 18:22:562070 std::vector<CreditCard> credit_cards;
2071 DictionaryValue* card_info = NULL;
2072 string16 card_label;
2073 string16 current_value;
2074
2075 std::map<AutoFillFieldType, std::wstring> credit_card_type_to_string =
2076 GetCreditCardFieldToStringMap();
2077
2078 int num_credit_cards = cards.GetSize();
2079 for (int i = 0; i < num_credit_cards; i++) {
2080 cards.GetDictionary(i, &card_info);
2081 card_info->GetString("label", &card_label);
2082 CreditCard card(card_label, 0);
2083 // Loop through the possible credit card fields and add those provided.
2084 for (std::map<AutoFillFieldType, std::wstring>::iterator type_it =
2085 credit_card_type_to_string.begin();
2086 type_it != credit_card_type_to_string.end(); ++type_it) {
[email protected]99922662010-08-17 16:24:252087 if (card_info->HasKey(WideToUTF8(type_it->second))) {
[email protected]698f7f42010-08-04 19:35:332088 if (card_info->GetString(WideToUTF8(type_it->second), &current_value)) {
[email protected]55846ad842010-07-09 18:22:562089 card.SetInfo(AutoFillType(type_it->first), current_value);
2090 } else {
[email protected]7c983cc2010-07-16 11:33:342091 *error_message= "All values must be strings";
[email protected]55846ad842010-07-09 18:22:562092 break;
2093 }
2094 }
2095 }
2096 credit_cards.push_back(card);
2097 }
2098 return credit_cards;
2099}
2100
2101/* static */
2102std::map<AutoFillFieldType, std::wstring>
2103 AutomationProvider::GetAutoFillFieldToStringMap() {
2104 std::map<AutoFillFieldType, std::wstring> autofill_type_to_string;
2105 autofill_type_to_string[NAME_FIRST] = L"NAME_FIRST";
2106 autofill_type_to_string[NAME_MIDDLE] = L"NAME_MIDDLE";
2107 autofill_type_to_string[NAME_LAST] = L"NAME_LAST";
2108 autofill_type_to_string[COMPANY_NAME] = L"COMPANY_NAME";
2109 autofill_type_to_string[EMAIL_ADDRESS] = L"EMAIL_ADDRESS";
2110 autofill_type_to_string[ADDRESS_HOME_LINE1] = L"ADDRESS_HOME_LINE1";
2111 autofill_type_to_string[ADDRESS_HOME_LINE2] = L"ADDRESS_HOME_LINE2";
2112 autofill_type_to_string[ADDRESS_HOME_CITY] = L"ADDRESS_HOME_CITY";
2113 autofill_type_to_string[ADDRESS_HOME_STATE] = L"ADDRESS_HOME_STATE";
2114 autofill_type_to_string[ADDRESS_HOME_ZIP] = L"ADDRESS_HOME_ZIP";
2115 autofill_type_to_string[ADDRESS_HOME_COUNTRY] = L"ADDRESS_HOME_COUNTRY";
2116 autofill_type_to_string[PHONE_HOME_NUMBER] = L"PHONE_HOME_NUMBER";
2117 autofill_type_to_string[PHONE_FAX_NUMBER] = L"PHONE_FAX_NUMBER";
2118 autofill_type_to_string[NAME_FIRST] = L"NAME_FIRST";
2119 return autofill_type_to_string;
2120}
2121
2122/* static */
2123std::map<AutoFillFieldType, std::wstring>
2124 AutomationProvider::GetCreditCardFieldToStringMap() {
2125 std::map<AutoFillFieldType, std::wstring> credit_card_type_to_string;
2126 credit_card_type_to_string[CREDIT_CARD_NAME] = L"CREDIT_CARD_NAME";
2127 credit_card_type_to_string[CREDIT_CARD_NUMBER] = L"CREDIT_CARD_NUMBER";
[email protected]55846ad842010-07-09 18:22:562128 credit_card_type_to_string[CREDIT_CARD_EXP_MONTH] = L"CREDIT_CARD_EXP_MONTH";
2129 credit_card_type_to_string[CREDIT_CARD_EXP_4_DIGIT_YEAR] =
2130 L"CREDIT_CARD_EXP_4_DIGIT_YEAR";
2131 return credit_card_type_to_string;
2132}
2133
[email protected]53329582010-05-14 21:10:582134void AutomationProvider::SendJSONRequest(int handle,
2135 std::string json_request,
2136 IPC::Message* reply_message) {
[email protected]59a611242010-04-02 02:24:042137 Browser* browser = NULL;
[email protected]59a611242010-04-02 02:24:042138 scoped_ptr<Value> values;
2139
2140 // Basic error checking.
2141 if (browser_tracker_->ContainsHandle(handle)) {
2142 browser = browser_tracker_->GetResource(handle);
2143 }
2144 if (!browser) {
[email protected]7c983cc2010-07-16 11:33:342145 AutomationJSONReply(this, reply_message).SendError("no browser object");
2146 return;
2147 }
2148 base::JSONReader reader;
2149 std::string error;
2150 values.reset(reader.ReadAndReturnError(json_request, true, NULL, &error));
2151 if (!error.empty()) {
2152 AutomationJSONReply(this, reply_message).SendError(error);
2153 return;
[email protected]59a611242010-04-02 02:24:042154 }
2155
2156 // Make sure input is a dict with a string command.
2157 std::string command;
2158 DictionaryValue* dict_value = NULL;
[email protected]7c983cc2010-07-16 11:33:342159 if (values->GetType() != Value::TYPE_DICTIONARY) {
2160 AutomationJSONReply(this, reply_message).SendError("not a dict");
2161 return;
2162 }
2163 // Ownership remains with "values" variable.
2164 dict_value = static_cast<DictionaryValue*>(values.get());
2165 if (!dict_value->GetStringASCII(std::string("command"), &command)) {
2166 AutomationJSONReply(this, reply_message).SendError(
2167 "no command key in dict or not a string command");
2168 return;
[email protected]59a611242010-04-02 02:24:042169 }
2170
[email protected]24e2b102010-04-29 17:56:472171 // Map json commands to their handlers.
2172 std::map<std::string, JsonHandler> handler_map;
[email protected]f7d48012010-05-06 08:17:052173 handler_map["DisablePlugin"] = &AutomationProvider::DisablePlugin;
2174 handler_map["EnablePlugin"] = &AutomationProvider::EnablePlugin;
2175 handler_map["GetPluginsInfo"] = &AutomationProvider::GetPluginsInfo;
2176
[email protected]a9ff2c02010-05-13 17:33:052177 handler_map["GetBrowserInfo"] = &AutomationProvider::GetBrowserInfo;
[email protected]7c983cc2010-07-16 11:33:342178
[email protected]38b5a3852010-07-21 06:49:522179 handler_map["WaitForInfobarCount"] = &AutomationProvider::WaitForInfobarCount;
[email protected]e004a2d2010-07-22 04:55:282180 handler_map["PerformActionOnInfobar"] =
2181 &AutomationProvider::PerformActionOnInfobar;
[email protected]38b5a3852010-07-21 06:49:522182
[email protected]24e2b102010-04-29 17:56:472183 handler_map["GetHistoryInfo"] = &AutomationProvider::GetHistoryInfo;
[email protected]bbe6aa02010-05-07 17:27:292184 handler_map["AddHistoryItem"] = &AutomationProvider::AddHistoryItem;
[email protected]f7d48012010-05-06 08:17:052185
[email protected]53329582010-05-14 21:10:582186 handler_map["GetOmniboxInfo"] = &AutomationProvider::GetOmniboxInfo;
2187 handler_map["SetOmniboxText"] = &AutomationProvider::SetOmniboxText;
2188 handler_map["OmniboxAcceptInput"] = &AutomationProvider::OmniboxAcceptInput;
2189 handler_map["OmniboxMovePopupSelection"] =
2190 &AutomationProvider::OmniboxMovePopupSelection;
2191
[email protected]24e2b102010-04-29 17:56:472192 handler_map["GetPrefsInfo"] = &AutomationProvider::GetPrefsInfo;
2193 handler_map["SetPrefs"] = &AutomationProvider::SetPrefs;
[email protected]f7d48012010-05-06 08:17:052194
[email protected]ef413ca2010-05-25 21:09:142195 handler_map["SetWindowDimensions"] = &AutomationProvider::SetWindowDimensions;
2196
[email protected]f7d48012010-05-06 08:17:052197 handler_map["GetDownloadsInfo"] = &AutomationProvider::GetDownloadsInfo;
[email protected]24e2b102010-04-29 17:56:472198 handler_map["WaitForAllDownloadsToComplete"] =
2199 &AutomationProvider::WaitForDownloadsToComplete;
[email protected]2d54c4032010-08-20 00:42:282200 handler_map["PerformActionOnDownload"] =
2201 &AutomationProvider::PerformActionOnDownload;
2202 handler_map["WaitForAlwaysOpenDownloadTypeToOpen"] =
2203 &AutomationProvider::WaitForAlwaysOpenDownloadTypeToOpen;
[email protected]24e2b102010-04-29 17:56:472204
[email protected]a3cd5022010-06-16 18:25:292205 handler_map["GetInitialLoadTimes"] = &AutomationProvider::GetInitialLoadTimes;
2206
[email protected]7060bb292010-06-24 00:52:492207 handler_map["SaveTabContents"] = &AutomationProvider::SaveTabContents;
2208
[email protected]c5aa5322010-07-15 19:00:072209 handler_map["ImportSettings"] = &AutomationProvider::ImportSettings;
2210
[email protected]5bcfe1672010-07-16 20:51:572211 handler_map["AddSavedPassword"] = &AutomationProvider::AddSavedPassword;
[email protected]95222282010-07-26 17:43:022212 handler_map["RemoveSavedPassword"] =
2213 &AutomationProvider::RemoveSavedPassword;
[email protected]5bcfe1672010-07-16 20:51:572214 handler_map["GetSavedPasswords"] = &AutomationProvider::GetSavedPasswords;
2215
[email protected]a0fc50d72010-07-14 21:14:192216 handler_map["ClearBrowsingData"] = &AutomationProvider::ClearBrowsingData;
2217
[email protected]4d1929f12010-07-10 00:09:032218 // SetTheme() implemented using InstallExtension().
2219 handler_map["GetThemeInfo"] = &AutomationProvider::GetThemeInfo;
2220
[email protected]32a69cf2010-08-03 16:27:012221 // InstallExtension() present in pyauto.py.
2222 handler_map["GetExtensionsInfo"] = &AutomationProvider::GetExtensionsInfo;
2223 handler_map["UninstallExtensionById"] =
2224 &AutomationProvider::UninstallExtensionById;
2225
[email protected]3dda5b02010-07-27 16:35:422226 handler_map["SelectTranslateOption"] =
2227 &AutomationProvider::SelectTranslateOption;
2228 handler_map["GetTranslateInfo"] = &AutomationProvider::GetTranslateInfo;
[email protected]f89ee5d2010-08-02 16:39:122229 handler_map["WaitUntilTranslateComplete"] =
2230 &AutomationProvider::WaitUntilTranslateComplete;
[email protected]3dda5b02010-07-27 16:35:422231
[email protected]55846ad842010-07-09 18:22:562232 handler_map["GetAutoFillProfile"] = &AutomationProvider::GetAutoFillProfile;
2233 handler_map["FillAutoFillProfile"] = &AutomationProvider::FillAutoFillProfile;
2234
[email protected]7c983cc2010-07-16 11:33:342235 if (handler_map.find(std::string(command)) != handler_map.end()) {
2236 (this->*handler_map[command])(browser, dict_value, reply_message);
[email protected]1ac875d22010-07-16 09:57:582237 } else {
[email protected]7c983cc2010-07-16 11:33:342238 std::string error_string = "Unknown command. Options: ";
2239 for (std::map<std::string, JsonHandler>::const_iterator it =
2240 handler_map.begin(); it != handler_map.end(); ++it) {
2241 error_string += it->first + ", ";
2242 }
2243 AutomationJSONReply(this, reply_message).SendError(error_string);
[email protected]1ac875d22010-07-16 09:57:582244 }
[email protected]59a611242010-04-02 02:24:042245}
2246
[email protected]a7eee32f2009-05-22 18:08:172247class SetProxyConfigTask : public Task {
2248 public:
[email protected]be180c802009-10-23 06:33:312249 SetProxyConfigTask(URLRequestContextGetter* request_context_getter,
2250 const std::string& new_proxy_config)
[email protected]2aa336e2010-04-06 21:05:252251 : request_context_getter_(request_context_getter),
2252 proxy_config_(new_proxy_config) {}
[email protected]a7eee32f2009-05-22 18:08:172253 virtual void Run() {
2254 // First, deserialize the JSON string. If this fails, log and bail.
2255 JSONStringValueSerializer deserializer(proxy_config_);
[email protected]ba399672010-04-06 15:42:392256 std::string error_msg;
2257 scoped_ptr<Value> root(deserializer.Deserialize(NULL, &error_msg));
[email protected]a7eee32f2009-05-22 18:08:172258 if (!root.get() || root->GetType() != Value::TYPE_DICTIONARY) {
2259 DLOG(WARNING) << "Received bad JSON string for ProxyConfig: "
[email protected]ba399672010-04-06 15:42:392260 << error_msg;
[email protected]a7eee32f2009-05-22 18:08:172261 return;
2262 }
2263
2264 scoped_ptr<DictionaryValue> dict(
2265 static_cast<DictionaryValue*>(root.release()));
2266 // Now put together a proxy configuration from the deserialized string.
2267 net::ProxyConfig pc;
2268 PopulateProxyConfig(*dict.get(), &pc);
2269
[email protected]be180c802009-10-23 06:33:312270 net::ProxyService* proxy_service =
2271 request_context_getter_->GetURLRequestContext()->proxy_service();
2272 DCHECK(proxy_service);
[email protected]a7eee32f2009-05-22 18:08:172273 scoped_ptr<net::ProxyConfigService> proxy_config_service(
2274 new net::ProxyConfigServiceFixed(pc));
[email protected]be180c802009-10-23 06:33:312275 proxy_service->ResetConfigService(proxy_config_service.release());
[email protected]a7eee32f2009-05-22 18:08:172276 }
2277
2278 void PopulateProxyConfig(const DictionaryValue& dict, net::ProxyConfig* pc) {
2279 DCHECK(pc);
2280 bool no_proxy = false;
2281 if (dict.GetBoolean(automation::kJSONProxyNoProxy, &no_proxy)) {
2282 // Make no changes to the ProxyConfig.
2283 return;
2284 }
2285 bool auto_config;
2286 if (dict.GetBoolean(automation::kJSONProxyAutoconfig, &auto_config)) {
[email protected]ed4ed0f2010-02-24 00:20:482287 pc->set_auto_detect(true);
[email protected]a7eee32f2009-05-22 18:08:172288 }
2289 std::string pac_url;
2290 if (dict.GetString(automation::kJSONProxyPacUrl, &pac_url)) {
[email protected]ed4ed0f2010-02-24 00:20:482291 pc->set_pac_url(GURL(pac_url));
[email protected]a7eee32f2009-05-22 18:08:172292 }
2293 std::string proxy_bypass_list;
2294 if (dict.GetString(automation::kJSONProxyBypassList, &proxy_bypass_list)) {
[email protected]ed4ed0f2010-02-24 00:20:482295 pc->proxy_rules().bypass_rules.ParseFromString(proxy_bypass_list);
[email protected]a7eee32f2009-05-22 18:08:172296 }
2297 std::string proxy_server;
2298 if (dict.GetString(automation::kJSONProxyServer, &proxy_server)) {
[email protected]ed4ed0f2010-02-24 00:20:482299 pc->proxy_rules().ParseFromString(proxy_server);
[email protected]a7eee32f2009-05-22 18:08:172300 }
2301 }
2302
2303 private:
[email protected]be180c802009-10-23 06:33:312304 scoped_refptr<URLRequestContextGetter> request_context_getter_;
[email protected]a7eee32f2009-05-22 18:08:172305 std::string proxy_config_;
2306};
2307
2308
2309void AutomationProvider::SetProxyConfig(const std::string& new_proxy_config) {
[email protected]be180c802009-10-23 06:33:312310 URLRequestContextGetter* context_getter = Profile::GetDefaultRequestContext();
2311 if (!context_getter) {
[email protected]a7eee32f2009-05-22 18:08:172312 FilePath user_data_dir;
2313 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
2314 ProfileManager* profile_manager = g_browser_process->profile_manager();
2315 DCHECK(profile_manager);
2316 Profile* profile = profile_manager->GetDefaultProfile(user_data_dir);
2317 DCHECK(profile);
[email protected]be180c802009-10-23 06:33:312318 context_getter = profile->GetRequestContext();
[email protected]a7eee32f2009-05-22 18:08:172319 }
[email protected]be180c802009-10-23 06:33:312320 DCHECK(context_getter);
[email protected]a7eee32f2009-05-22 18:08:172321
[email protected]fae20792009-10-28 20:31:582322 ChromeThread::PostTask(
2323 ChromeThread::IO, FROM_HERE,
[email protected]be180c802009-10-23 06:33:312324 new SetProxyConfigTask(context_getter, new_proxy_config));
[email protected]a7eee32f2009-05-22 18:08:172325}
2326
[email protected]57c6a652009-05-04 07:58:342327TabContents* AutomationProvider::GetTabContentsForHandle(
[email protected]20e93d12008-08-28 16:31:572328 int handle, NavigationController** tab) {
[email protected]20e93d12008-08-28 16:31:572329 if (tab_tracker_->ContainsHandle(handle)) {
2330 NavigationController* nav_controller = tab_tracker_->GetResource(handle);
[email protected]57c6a652009-05-04 07:58:342331 if (tab)
2332 *tab = nav_controller;
2333 return nav_controller->tab_contents();
[email protected]20e93d12008-08-28 16:31:572334 }
[email protected]57c6a652009-05-04 07:58:342335 return NULL;
[email protected]20e93d12008-08-28 16:31:572336}
2337
[email protected]97fa6ce32008-12-19 01:48:162338// Gets the current used encoding name of the page in the specified tab.
[email protected]71f65dd2009-02-11 19:14:562339void AutomationProvider::GetPageCurrentEncoding(
[email protected]41fc0322009-09-04 22:23:402340 int tab_handle, std::string* current_encoding) {
[email protected]97fa6ce32008-12-19 01:48:162341 if (tab_tracker_->ContainsHandle(tab_handle)) {
2342 NavigationController* nav = tab_tracker_->GetResource(tab_handle);
2343 Browser* browser = FindAndActivateTab(nav);
2344 DCHECK(browser);
2345
[email protected]57c6a652009-05-04 07:58:342346 if (browser->command_updater()->IsCommandEnabled(IDC_ENCODING_MENU))
2347 *current_encoding = nav->tab_contents()->encoding();
[email protected]97fa6ce32008-12-19 01:48:162348 }
[email protected]97fa6ce32008-12-19 01:48:162349}
2350
[email protected]b8f48d12009-11-09 20:14:362351// Gets the current used encoding name of the page in the specified tab.
[email protected]71f65dd2009-02-11 19:14:562352void AutomationProvider::OverrideEncoding(int tab_handle,
[email protected]41fc0322009-09-04 22:23:402353 const std::string& encoding_name,
[email protected]71f65dd2009-02-11 19:14:562354 bool* success) {
2355 *success = false;
[email protected]97fa6ce32008-12-19 01:48:162356 if (tab_tracker_->ContainsHandle(tab_handle)) {
2357 NavigationController* nav = tab_tracker_->GetResource(tab_handle);
[email protected]2f2afba2010-04-01 01:53:192358 if (!nav)
2359 return;
[email protected]97fa6ce32008-12-19 01:48:162360 Browser* browser = FindAndActivateTab(nav);
[email protected]97fa6ce32008-12-19 01:48:162361
[email protected]2f2afba2010-04-01 01:53:192362 // If the browser has UI, simulate what a user would do.
2363 // Activate the tab and then click the encoding menu.
2364 if (browser &&
2365 browser->command_updater()->IsCommandEnabled(IDC_ENCODING_MENU)) {
[email protected]97fa6ce32008-12-19 01:48:162366 int selected_encoding_id =
2367 CharacterEncoding::GetCommandIdByCanonicalEncodingName(encoding_name);
2368 if (selected_encoding_id) {
2369 browser->OverrideEncoding(selected_encoding_id);
[email protected]71f65dd2009-02-11 19:14:562370 *success = true;
[email protected]97fa6ce32008-12-19 01:48:162371 }
[email protected]2f2afba2010-04-01 01:53:192372 } else {
2373 // There is no UI, Chrome probably runs as Chrome-Frame mode.
2374 // Try to get TabContents and call its override_encoding method.
2375 TabContents* contents = nav->tab_contents();
2376 if (!contents)
2377 return;
2378 const std::string selected_encoding =
2379 CharacterEncoding::GetCanonicalEncodingNameByAliasName(encoding_name);
2380 if (selected_encoding.empty())
2381 return;
2382 contents->SetOverrideEncoding(selected_encoding);
[email protected]97fa6ce32008-12-19 01:48:162383 }
2384 }
[email protected]97fa6ce32008-12-19 01:48:162385}
[email protected]5bcdb312009-01-07 21:43:202386
[email protected]f7a68432009-07-29 23:18:192387void AutomationProvider::SelectAll(int tab_handle) {
2388 RenderViewHost* view = GetViewForTab(tab_handle);
2389 if (!view) {
2390 NOTREACHED();
2391 return;
2392 }
2393
2394 view->SelectAll();
2395}
2396
2397void AutomationProvider::Cut(int tab_handle) {
2398 RenderViewHost* view = GetViewForTab(tab_handle);
2399 if (!view) {
2400 NOTREACHED();
2401 return;
2402 }
2403
2404 view->Cut();
2405}
2406
2407void AutomationProvider::Copy(int tab_handle) {
2408 RenderViewHost* view = GetViewForTab(tab_handle);
2409 if (!view) {
2410 NOTREACHED();
2411 return;
2412 }
2413
2414 view->Copy();
2415}
2416
2417void AutomationProvider::Paste(int tab_handle) {
2418 RenderViewHost* view = GetViewForTab(tab_handle);
2419 if (!view) {
2420 NOTREACHED();
2421 return;
2422 }
2423
2424 view->Paste();
2425}
2426
2427void AutomationProvider::ReloadAsync(int tab_handle) {
2428 if (tab_tracker_->ContainsHandle(tab_handle)) {
2429 NavigationController* tab = tab_tracker_->GetResource(tab_handle);
2430 if (!tab) {
2431 NOTREACHED();
2432 return;
2433 }
2434
[email protected]106a0812010-03-18 00:15:122435 const bool check_for_repost = true;
2436 tab->Reload(check_for_repost);
[email protected]f7a68432009-07-29 23:18:192437 }
2438}
2439
2440void AutomationProvider::StopAsync(int tab_handle) {
2441 RenderViewHost* view = GetViewForTab(tab_handle);
2442 if (!view) {
[email protected]8b2b3312009-09-14 18:38:362443 // We tolerate StopAsync being called even before a view has been created.
2444 // So just log a warning instead of a NOTREACHED().
2445 DLOG(WARNING) << "StopAsync: no view for handle " << tab_handle;
[email protected]f7a68432009-07-29 23:18:192446 return;
2447 }
2448
2449 view->Stop();
2450}
2451
[email protected]1bb5f892009-10-06 01:44:572452void AutomationProvider::OnSetPageFontSize(int tab_handle,
2453 int font_size) {
2454 AutomationPageFontSize automation_font_size =
2455 static_cast<AutomationPageFontSize>(font_size);
2456
2457 if (automation_font_size < SMALLEST_FONT ||
2458 automation_font_size > LARGEST_FONT) {
2459 DLOG(ERROR) << "Invalid font size specified : "
2460 << font_size;
2461 return;
2462 }
2463
2464 if (tab_tracker_->ContainsHandle(tab_handle)) {
2465 NavigationController* tab = tab_tracker_->GetResource(tab_handle);
2466 DCHECK(tab != NULL);
2467 if (tab && tab->tab_contents()) {
2468 DCHECK(tab->tab_contents()->profile() != NULL);
2469 tab->tab_contents()->profile()->GetPrefs()->SetInteger(
2470 prefs::kWebKitDefaultFontSize, font_size);
2471 }
2472 }
2473}
2474
[email protected]bc73b4e52010-03-26 04:16:202475void AutomationProvider::RemoveBrowsingData(int remove_mask) {
2476 BrowsingDataRemover* remover;
2477 remover = new BrowsingDataRemover(profile(),
2478 BrowsingDataRemover::EVERYTHING, // All time periods.
2479 base::Time());
2480 remover->Remove(remove_mask);
2481 // BrowsingDataRemover deletes itself.
2482}
[email protected]1bb5f892009-10-06 01:44:572483
[email protected]f7a68432009-07-29 23:18:192484RenderViewHost* AutomationProvider::GetViewForTab(int tab_handle) {
2485 if (tab_tracker_->ContainsHandle(tab_handle)) {
2486 NavigationController* tab = tab_tracker_->GetResource(tab_handle);
2487 if (!tab) {
2488 NOTREACHED();
2489 return NULL;
2490 }
2491
2492 TabContents* tab_contents = tab->tab_contents();
2493 if (!tab_contents) {
2494 NOTREACHED();
2495 return NULL;
2496 }
2497
2498 RenderViewHost* view_host = tab_contents->render_view_host();
2499 return view_host;
2500 }
2501
2502 return NULL;
2503}
[email protected]675595f2009-08-26 22:32:042504
[email protected]d11c8e92009-10-20 23:26:402505void AutomationProvider::InstallExtension(const FilePath& crx_path,
2506 IPC::Message* reply_message) {
2507 ExtensionsService* service = profile_->GetExtensionsService();
2508 if (service) {
2509 // The observer will delete itself when done.
[email protected]790788ac2010-04-06 17:52:192510 new ExtensionInstallNotificationObserver(this,
2511 AutomationMsg_InstallExtension::ID,
2512 reply_message);
[email protected]d11c8e92009-10-20 23:26:402513
2514 const FilePath& install_dir = service->install_directory();
[email protected]6dfbbf82010-03-12 23:09:162515 scoped_refptr<CrxInstaller> installer(
2516 new CrxInstaller(install_dir,
2517 service,
2518 NULL)); // silent install, no UI
2519 installer->set_allow_privilege_increase(true);
2520 installer->InstallCrx(crx_path);
[email protected]d11c8e92009-10-20 23:26:402521 } else {
2522 AutomationMsg_InstallExtension::WriteReplyParams(
2523 reply_message, AUTOMATION_MSG_EXTENSION_INSTALL_FAILED);
2524 Send(reply_message);
2525 }
2526}
2527
2528void AutomationProvider::LoadExpandedExtension(
2529 const FilePath& extension_dir,
2530 IPC::Message* reply_message) {
[email protected]a4378252010-02-09 08:14:382531 if (profile_->GetExtensionsService()) {
[email protected]d11c8e92009-10-20 23:26:402532 // The observer will delete itself when done.
[email protected]790788ac2010-04-06 17:52:192533 new ExtensionInstallNotificationObserver(
2534 this,
2535 AutomationMsg_LoadExpandedExtension::ID,
2536 reply_message);
[email protected]d11c8e92009-10-20 23:26:402537
2538 profile_->GetExtensionsService()->LoadExtension(extension_dir);
[email protected]d11c8e92009-10-20 23:26:402539 } else {
2540 AutomationMsg_LoadExpandedExtension::WriteReplyParams(
2541 reply_message, AUTOMATION_MSG_EXTENSION_INSTALL_FAILED);
2542 Send(reply_message);
2543 }
2544}
[email protected]673fd2c02010-02-04 23:10:002545
[email protected]a1e62d12010-03-16 02:18:432546void AutomationProvider::GetEnabledExtensions(
2547 std::vector<FilePath>* result) {
2548 ExtensionsService* service = profile_->GetExtensionsService();
2549 DCHECK(service);
2550 if (service->extensions_enabled()) {
2551 const ExtensionList* extensions = service->extensions();
2552 DCHECK(extensions);
2553 for (size_t i = 0; i < extensions->size(); ++i) {
2554 Extension* extension = (*extensions)[i];
2555 DCHECK(extension);
[email protected]472f099b2010-05-27 17:07:122556 if (extension->location() == Extension::INTERNAL ||
2557 extension->location() == Extension::LOAD) {
[email protected]237f281672010-03-20 12:37:072558 result->push_back(extension->path());
2559 }
[email protected]a1e62d12010-03-16 02:18:432560 }
2561 }
2562}
2563
[email protected]790788ac2010-04-06 17:52:192564void AutomationProvider::WaitForExtensionTestResult(
2565 IPC::Message* reply_message) {
2566 DCHECK(reply_message_ == NULL);
2567 reply_message_ = reply_message;
2568 // Call MaybeSendResult, because the result might have come in before
2569 // we were waiting on it.
2570 extension_test_result_observer_->MaybeSendResult();
2571}
2572
2573void AutomationProvider::InstallExtensionAndGetHandle(
[email protected]d7e5525d2010-04-20 14:37:092574 const FilePath& crx_path, bool with_ui, IPC::Message* reply_message) {
[email protected]790788ac2010-04-06 17:52:192575 ExtensionsService* service = profile_->GetExtensionsService();
2576 ExtensionProcessManager* manager = profile_->GetExtensionProcessManager();
2577 if (service && manager) {
2578 // The observer will delete itself when done.
2579 new ExtensionReadyNotificationObserver(
2580 manager,
2581 this,
2582 AutomationMsg_InstallExtensionAndGetHandle::ID,
2583 reply_message);
2584
[email protected]d7e5525d2010-04-20 14:37:092585 ExtensionInstallUI* client =
2586 (with_ui ? new ExtensionInstallUI(profile_) : NULL);
[email protected]790788ac2010-04-06 17:52:192587 scoped_refptr<CrxInstaller> installer(
2588 new CrxInstaller(service->install_directory(),
2589 service,
[email protected]d7e5525d2010-04-20 14:37:092590 client));
[email protected]790788ac2010-04-06 17:52:192591 installer->set_allow_privilege_increase(true);
2592 installer->InstallCrx(crx_path);
2593 } else {
2594 AutomationMsg_InstallExtensionAndGetHandle::WriteReplyParams(
2595 reply_message, 0);
2596 Send(reply_message);
2597 }
2598}
2599
2600void AutomationProvider::UninstallExtension(int extension_handle,
2601 bool* success) {
2602 *success = false;
2603 Extension* extension = GetExtension(extension_handle);
2604 ExtensionsService* service = profile_->GetExtensionsService();
2605 if (extension && service) {
2606 ExtensionUnloadNotificationObserver observer;
2607 service->UninstallExtension(extension->id(), false);
2608 // The extension unload notification should have been sent synchronously
2609 // with the uninstall. Just to be safe, check that it was received.
2610 *success = observer.did_receive_unload_notification();
2611 }
2612}
2613
2614void AutomationProvider::EnableExtension(int extension_handle,
2615 IPC::Message* reply_message) {
2616 Extension* extension = GetDisabledExtension(extension_handle);
2617 ExtensionsService* service = profile_->GetExtensionsService();
2618 ExtensionProcessManager* manager = profile_->GetExtensionProcessManager();
2619 // Only enable if this extension is disabled.
2620 if (extension && service && manager) {
2621 // The observer will delete itself when done.
2622 new ExtensionReadyNotificationObserver(
2623 manager,
2624 this,
2625 AutomationMsg_EnableExtension::ID,
2626 reply_message);
2627 service->EnableExtension(extension->id());
2628 } else {
2629 AutomationMsg_EnableExtension::WriteReplyParams(reply_message, false);
2630 Send(reply_message);
2631 }
2632}
2633
2634void AutomationProvider::DisableExtension(int extension_handle,
2635 bool* success) {
2636 *success = false;
2637 Extension* extension = GetEnabledExtension(extension_handle);
2638 ExtensionsService* service = profile_->GetExtensionsService();
2639 if (extension && service) {
2640 ExtensionUnloadNotificationObserver observer;
2641 service->DisableExtension(extension->id());
2642 // The extension unload notification should have been sent synchronously
2643 // with the disable. Just to be safe, check that it was received.
2644 *success = observer.did_receive_unload_notification();
2645 }
2646}
2647
2648void AutomationProvider::ExecuteExtensionActionInActiveTabAsync(
2649 int extension_handle, int browser_handle,
2650 IPC::Message* reply_message) {
2651 bool success = false;
2652 Extension* extension = GetEnabledExtension(extension_handle);
2653 ExtensionsService* service = profile_->GetExtensionsService();
2654 ExtensionMessageService* message_service =
2655 profile_->GetExtensionMessageService();
2656 Browser* browser = browser_tracker_->GetResource(browser_handle);
2657 if (extension && service && message_service && browser) {
2658 int tab_id = ExtensionTabUtil::GetTabId(browser->GetSelectedTabContents());
2659 if (extension->page_action()) {
2660 ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted(
2661 browser->profile(), extension->id(), "action", tab_id, "", 1);
2662 success = true;
2663 } else if (extension->browser_action()) {
2664 ExtensionBrowserEventRouter::GetInstance()->BrowserActionExecuted(
2665 browser->profile(), extension->id(), browser);
2666 success = true;
2667 }
2668 }
2669 AutomationMsg_ExecuteExtensionActionInActiveTabAsync::WriteReplyParams(
2670 reply_message, success);
2671 Send(reply_message);
2672}
2673
2674void AutomationProvider::MoveExtensionBrowserAction(
2675 int extension_handle, int index, bool* success) {
2676 *success = false;
2677 Extension* extension = GetEnabledExtension(extension_handle);
2678 ExtensionsService* service = profile_->GetExtensionsService();
2679 if (extension && service) {
2680 ExtensionToolbarModel* toolbar = service->toolbar_model();
2681 if (toolbar) {
2682 if (index >= 0 && index < static_cast<int>(toolbar->size())) {
2683 toolbar->MoveBrowserAction(extension, index);
2684 *success = true;
2685 } else {
2686 DLOG(WARNING) << "Attempted to move browser action to invalid index.";
2687 }
2688 }
2689 }
2690}
2691
2692void AutomationProvider::GetExtensionProperty(
2693 int extension_handle,
2694 AutomationMsg_ExtensionProperty type,
2695 bool* success,
2696 std::string* value) {
2697 *success = false;
2698 Extension* extension = GetExtension(extension_handle);
2699 ExtensionsService* service = profile_->GetExtensionsService();
2700 if (extension && service) {
2701 ExtensionToolbarModel* toolbar = service->toolbar_model();
2702 int found_index = -1;
2703 int index = 0;
2704 switch (type) {
2705 case AUTOMATION_MSG_EXTENSION_ID:
2706 *value = extension->id();
2707 *success = true;
2708 break;
2709 case AUTOMATION_MSG_EXTENSION_NAME:
2710 *value = extension->name();
2711 *success = true;
2712 break;
2713 case AUTOMATION_MSG_EXTENSION_VERSION:
2714 *value = extension->VersionString();
2715 *success = true;
2716 break;
2717 case AUTOMATION_MSG_EXTENSION_BROWSER_ACTION_INDEX:
2718 if (toolbar) {
2719 for (ExtensionList::const_iterator iter = toolbar->begin();
2720 iter != toolbar->end(); iter++) {
2721 // Skip this extension if we are in incognito mode
2722 // and it is not incognito-enabled.
2723 if (profile_->IsOffTheRecord() &&
2724 !service->IsIncognitoEnabled(*iter))
2725 continue;
2726 if (*iter == extension) {
2727 found_index = index;
2728 break;
2729 }
2730 index++;
2731 }
[email protected]528c56d2010-07-30 19:28:442732 *value = base::IntToString(found_index);
[email protected]790788ac2010-04-06 17:52:192733 *success = true;
2734 }
2735 break;
2736 default:
2737 LOG(WARNING) << "Trying to get undefined extension property";
2738 break;
2739 }
2740 }
2741}
2742
[email protected]673fd2c02010-02-04 23:10:002743void AutomationProvider::SaveAsAsync(int tab_handle) {
2744 NavigationController* tab = NULL;
2745 TabContents* tab_contents = GetTabContentsForHandle(tab_handle, &tab);
2746 if (tab_contents)
2747 tab_contents->OnSavePage();
2748}
[email protected]7dad3d5f2010-03-04 00:27:012749
2750void AutomationProvider::SetContentSetting(
2751 int handle,
2752 const std::string& host,
2753 ContentSettingsType content_type,
2754 ContentSetting setting,
2755 bool* success) {
2756 *success = false;
2757 if (browser_tracker_->ContainsHandle(handle)) {
2758 Browser* browser = browser_tracker_->GetResource(handle);
2759 HostContentSettingsMap* map =
2760 browser->profile()->GetHostContentSettingsMap();
2761 if (host.empty()) {
2762 map->SetDefaultContentSetting(content_type, setting);
2763 } else {
[email protected]0314ae02010-04-08 09:18:292764 map->SetContentSetting(HostContentSettingsMap::Pattern(host),
[email protected]ca352452010-08-06 11:14:092765 content_type, "", setting);
[email protected]7dad3d5f2010-03-04 00:27:012766 }
2767 *success = true;
2768 }
2769}
[email protected]cc824372010-03-31 15:33:012770
[email protected]d7e5525d2010-04-20 14:37:092771void AutomationProvider::ResetToDefaultTheme() {
2772 profile_->ClearTheme();
2773}