blob: d4325504a86a859c56e312699f19e2f3fb6dd528 [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]c6cb1992009-04-13 16:45:2912#include "base/file_version_info.h"
[email protected]93d49d72009-10-23 20:00:2013#include "base/json/json_reader.h"
[email protected]59a611242010-04-02 02:24:0414#include "base/json/json_writer.h"
[email protected]93364da2010-06-29 18:03:4415#include "base/json/string_escape.h"
[email protected]bc1407f2009-09-29 00:33:3516#include "base/keyboard_codes.h"
[email protected]5fac9622009-02-04 21:49:3817#include "base/message_loop.h"
initial.commit09911bf2008-07-26 23:55:2918#include "base/path_service.h"
[email protected]201b2732009-11-13 18:57:4619#include "base/process_util.h"
[email protected]f44265b2009-05-19 18:52:5020#include "base/stl_util-inl.h"
[email protected]4c4d8d22009-03-04 05:29:2721#include "base/string_util.h"
[email protected]9eaa18e2010-06-29 20:51:0122#include "base/task.h"
[email protected]5fac9622009-02-04 21:49:3823#include "base/thread.h"
[email protected]a872ea1f2010-08-11 04:45:3324#include "base/trace_event.h"
[email protected]528c56d2010-07-30 19:28:4425#include "base/string_number_conversions.h"
[email protected]6d8ffc9f2010-03-12 18:27:5326#include "base/utf_string_conversions.h"
[email protected]a7eee32f2009-05-22 18:08:1727#include "base/values.h"
[email protected]9eaa18e2010-06-29 20:51:0128#include "base/waitable_event.h"
[email protected]4f3dc372009-02-24 00:10:2929#include "chrome/app/chrome_dll_resource.h"
[email protected]0bfa713f2009-04-07 20:18:2830#include "chrome/browser/app_modal_dialog.h"
[email protected]464146e2009-04-09 18:17:0931#include "chrome/browser/app_modal_dialog_queue.h"
[email protected]55846ad842010-07-09 18:22:5632#include "chrome/browser/autofill/autofill_manager.h"
[email protected]679082052010-07-21 21:30:1333#include "chrome/browser/automation/automation_autocomplete_edit_tracker.h"
34#include "chrome/browser/automation/automation_browser_tracker.h"
[email protected]790788ac2010-04-06 17:52:1935#include "chrome/browser/automation/automation_extension_tracker.h"
[email protected]7c983cc2010-07-16 11:33:3436#include "chrome/browser/automation/automation_provider_json.h"
initial.commit09911bf2008-07-26 23:55:2937#include "chrome/browser/automation/automation_provider_list.h"
[email protected]e12de87e2009-08-28 00:02:0838#include "chrome/browser/automation/automation_provider_observers.h"
[email protected]679082052010-07-21 21:30:1339#include "chrome/browser/automation/automation_resource_message_filter.h"
40#include "chrome/browser/automation/automation_tab_tracker.h"
41#include "chrome/browser/automation/automation_window_tracker.h"
[email protected]f44265b2009-05-19 18:52:5042#include "chrome/browser/automation/extension_port_container.h"
[email protected]12802702010-07-09 19:43:0943#include "chrome/browser/autocomplete/autocomplete_edit.h"
[email protected]66ba4932009-06-04 19:22:1344#include "chrome/browser/blocked_popup_container.h"
[email protected]6d8ffc9f2010-03-12 18:27:5345#include "chrome/browser/bookmarks/bookmark_model.h"
46#include "chrome/browser/bookmarks/bookmark_storage.h"
[email protected]ef413ca2010-05-25 21:09:1447#include "chrome/browser/browser_list.h"
[email protected]5c238752009-06-13 10:29:0748#include "chrome/browser/browser_process.h"
[email protected]f3e99e32008-07-30 04:48:3949#include "chrome/browser/browser_window.h"
[email protected]bc73b4e52010-03-26 04:16:2050#include "chrome/browser/browsing_data_remover.h"
[email protected]f83f9102010-05-04 17:01:0551#include "chrome/browser/character_encoding.h"
[email protected]fae20792009-10-28 20:31:5852#include "chrome/browser/chrome_thread.h"
initial.commit09911bf2008-07-26 23:55:2953#include "chrome/browser/dom_operation_notification_details.h"
[email protected]d9f9b792009-06-24 13:17:1254#include "chrome/browser/debugger/devtools_manager.h"
[email protected]6c69796d2010-07-16 21:41:1655#include "chrome/browser/download/download_item.h"
[email protected]59560e0b2009-06-04 03:30:2256#include "chrome/browser/download/download_shelf.h"
[email protected]f83f9102010-05-04 17:01:0557#include "chrome/browser/download/save_package.h"
[email protected]d11c8e92009-10-20 23:26:4058#include "chrome/browser/extensions/crx_installer.h"
[email protected]790788ac2010-04-06 17:52:1959#include "chrome/browser/extensions/extension_browser_event_router.h"
[email protected]ef413ca2010-05-25 21:09:1460#include "chrome/browser/extensions/extension_host.h"
[email protected]d11c8e92009-10-20 23:26:4061#include "chrome/browser/extensions/extension_install_ui.h"
[email protected]a9024892009-06-16 23:13:5562#include "chrome/browser/extensions/extension_message_service.h"
[email protected]790788ac2010-04-06 17:52:1963#include "chrome/browser/extensions/extension_tabs_module.h"
64#include "chrome/browser/extensions/extension_toolbar_model.h"
65#include "chrome/browser/extensions/extensions_service.h"
[email protected]8cb5d5b2010-02-09 11:36:1666#include "chrome/browser/extensions/user_script_master.h"
[email protected]4801ecc2009-04-05 04:52:5867#include "chrome/browser/find_bar.h"
68#include "chrome/browser/find_bar_controller.h"
initial.commit09911bf2008-07-26 23:55:2969#include "chrome/browser/find_notification_details.h"
[email protected]7dad3d5f2010-03-04 00:27:0170#include "chrome/browser/host_content_settings_map.h"
[email protected]c5aa5322010-07-15 19:00:0771#include "chrome/browser/importer/importer.h"
72#include "chrome/browser/importer/importer_data_types.h"
[email protected]0ac83682010-01-22 17:46:2773#include "chrome/browser/io_thread.h"
[email protected]13869dd2009-05-05 00:40:0674#include "chrome/browser/location_bar.h"
[email protected]3fcac682009-08-13 02:28:0175#include "chrome/browser/login_prompt.h"
[email protected]f732c1e2009-07-30 15:48:5376#include "chrome/browser/net/url_request_mock_util.h"
[email protected]14a000d2010-04-29 21:44:2477#include "chrome/browser/platform_util.h"
[email protected]37858e52010-08-26 00:22:0278#include "chrome/browser/prefs/pref_service.h"
[email protected]f83f9102010-05-04 17:01:0579#include "chrome/browser/printing/print_job.h"
[email protected]a7eee32f2009-05-22 18:08:1780#include "chrome/browser/profile_manager.h"
[email protected]1db6ff152009-10-12 15:32:0781#include "chrome/browser/renderer_host/render_process_host.h"
[email protected]6524b5f92009-01-22 17:48:2582#include "chrome/browser/renderer_host/render_view_host.h"
[email protected]3b073b22009-01-16 03:29:0383#include "chrome/browser/ssl/ssl_manager.h"
84#include "chrome/browser/ssl/ssl_blocking_page.h"
[email protected]b5558cf22010-07-12 17:30:0685#include "chrome/browser/tab_contents/infobar_delegate.h"
[email protected]57c6a652009-05-04 07:58:3486#include "chrome/browser/tab_contents/tab_contents.h"
[email protected]81af9392009-04-21 02:37:4587#include "chrome/browser/tab_contents/tab_contents_view.h"
[email protected]38b5a3852010-07-21 06:49:5288#include "chrome/browser/translate/translate_infobar_delegate.h"
[email protected]a7eee32f2009-05-22 18:08:1789#include "chrome/common/automation_constants.h"
[email protected]a9ff2c02010-05-13 17:33:0590#include "chrome/common/chrome_constants.h"
initial.commit09911bf2008-07-26 23:55:2991#include "chrome/common/chrome_paths.h"
[email protected]c984d9f2010-07-20 20:52:2092#include "chrome/common/chrome_switches.h"
[email protected]1eeb5e02010-07-20 23:02:1193#include "chrome/common/chrome_version_info.h"
[email protected]790788ac2010-04-06 17:52:1994#include "chrome/common/extensions/extension.h"
[email protected]a7eee32f2009-05-22 18:08:1795#include "chrome/common/json_value_serializer.h"
[email protected]68d2a05f2010-05-07 21:39:5596#include "chrome/common/net/url_request_context_getter.h"
[email protected]1c58a5c2009-05-21 18:47:1497#include "chrome/common/notification_service.h"
[email protected]1bb5f892009-10-06 01:44:5798#include "chrome/common/pref_names.h"
[email protected]f5bf8ccf2010-02-05 18:19:2599#include "chrome/common/url_constants.h"
[email protected]71f65dd2009-02-11 19:14:56100#include "chrome/test/automation/automation_messages.h"
[email protected]1bb5f892009-10-06 01:44:57101#include "chrome/test/automation/tab_proxy.h"
[email protected]a7eee32f2009-05-22 18:08:17102#include "net/proxy/proxy_service.h"
103#include "net/proxy/proxy_config_service_fixed.h"
[email protected]319d9e6f2009-02-18 19:47:21104#include "net/url_request/url_request_context.h"
[email protected]1b5a48c2010-04-29 23:08:30105#include "chrome/browser/automation/ui_controls.h"
[email protected]9a08bcf2009-08-12 19:56:28106#include "views/event.h"
[email protected]5bcfe1672010-07-16 20:51:57107#include "webkit/glue/password_form.h"
[email protected]f7d48012010-05-06 08:17:05108#include "webkit/glue/plugins/plugin_list.h"
initial.commit09911bf2008-07-26 23:55:29109
[email protected]de246f52009-02-25 18:25:45110#if defined(OS_WIN)
[email protected]4bdde602010-06-16 03:17:35111#include "chrome/browser/external_tab_container_win.h"
[email protected]de246f52009-02-25 18:25:45112#endif // defined(OS_WIN)
113
[email protected]e1acf6f2008-10-27 20:43:33114using base::Time;
115
initial.commit09911bf2008-07-26 23:55:29116AutomationProvider::AutomationProvider(Profile* profile)
[email protected]c97080f2010-08-20 20:42:48117 : profile_(profile),
[email protected]4feac662010-08-25 23:29:39118 reply_message_(NULL) {
[email protected]a872ea1f2010-08-11 04:45:33119 TRACE_EVENT_BEGIN("AutomationProvider::AutomationProvider", 0, "");
120
initial.commit09911bf2008-07-26 23:55:29121 browser_tracker_.reset(new AutomationBrowserTracker(this));
[email protected]790788ac2010-04-06 17:52:19122 extension_tracker_.reset(new AutomationExtensionTracker(this));
initial.commit09911bf2008-07-26 23:55:29123 tab_tracker_.reset(new AutomationTabTracker(this));
[email protected]0e9f4ee2009-04-08 01:44:20124 window_tracker_.reset(new AutomationWindowTracker(this));
initial.commit09911bf2008-07-26 23:55:29125 autocomplete_edit_tracker_.reset(
126 new AutomationAutocompleteEditTracker(this));
initial.commit09911bf2008-07-26 23:55:29127 new_tab_ui_load_observer_.reset(new NewTabUILoadObserver(this));
128 dom_operation_observer_.reset(new DomOperationNotificationObserver(this));
[email protected]84abba62009-10-07 17:01:44129 metric_event_duration_observer_.reset(new MetricEventDurationObserver());
[email protected]790788ac2010-04-06 17:52:19130 extension_test_result_observer_.reset(
131 new ExtensionTestResultNotificationObserver(this));
[email protected]528211a2010-01-14 15:25:13132 g_browser_process->AddRefModule();
[email protected]a872ea1f2010-08-11 04:45:33133
134 TRACE_EVENT_END("AutomationProvider::AutomationProvider", 0, "");
initial.commit09911bf2008-07-26 23:55:29135}
136
137AutomationProvider::~AutomationProvider() {
[email protected]f44265b2009-05-19 18:52:50138 STLDeleteContainerPairSecondPointers(port_containers_.begin(),
139 port_containers_.end());
140 port_containers_.clear();
141
[email protected]0da050b92008-08-19 19:29:47142 // Make sure that any outstanding NotificationObservers also get destroyed.
143 ObserverList<NotificationObserver>::Iterator it(notification_observer_list_);
[email protected]5a52f162008-08-27 04:15:31144 NotificationObserver* observer;
[email protected]0da050b92008-08-19 19:29:47145 while ((observer = it.GetNext()) != NULL)
146 delete observer;
[email protected]528211a2010-01-14 15:25:13147
148 if (channel_.get()) {
149 channel_->Close();
150 }
151 g_browser_process->ReleaseModule();
initial.commit09911bf2008-07-26 23:55:29152}
153
[email protected]9a3a293b2009-06-04 22:28:16154void AutomationProvider::ConnectToChannel(const std::string& channel_id) {
[email protected]a872ea1f2010-08-11 04:45:33155 TRACE_EVENT_BEGIN("AutomationProvider::ConnectToChannel", 0, "");
156
[email protected]2e4633c2009-07-09 16:58:06157 automation_resource_message_filter_ = new AutomationResourceMessageFilter;
[email protected]295039bd2008-08-15 04:32:57158 channel_.reset(
[email protected]2e4633c2009-07-09 16:58:06159 new IPC::SyncChannel(channel_id, IPC::Channel::MODE_CLIENT, this,
160 automation_resource_message_filter_,
161 g_browser_process->io_thread()->message_loop(),
162 true, g_browser_process->shutdown_event()));
[email protected]1eeb5e02010-07-20 23:02:11163 scoped_ptr<FileVersionInfo> version_info(chrome::GetChromeVersionInfo());
[email protected]cf620752009-04-24 17:05:40164 std::string version_string;
[email protected]bcff05a2010-04-14 01:46:43165 if (version_info != NULL) {
166 version_string = WideToASCII(version_info->file_version());
[email protected]cf620752009-04-24 17:05:40167 }
[email protected]c6cb1992009-04-13 16:45:29168
169 // Send a hello message with our current automation protocol version.
170 channel_->Send(new AutomationMsg_Hello(0, version_string.c_str()));
[email protected]a872ea1f2010-08-11 04:45:33171
172 TRACE_EVENT_END("AutomationProvider::ConnectToChannel", 0, "");
initial.commit09911bf2008-07-26 23:55:29173}
174
175void AutomationProvider::SetExpectedTabCount(size_t expected_tabs) {
176 if (expected_tabs == 0) {
177 Send(new AutomationMsg_InitialLoadsComplete(0));
178 } else {
179 initial_load_observer_.reset(new InitialLoadObserver(expected_tabs, this));
180 }
181}
182
183NotificationObserver* AutomationProvider::AddNavigationStatusListener(
[email protected]2e028a082009-08-19 20:32:58184 NavigationController* tab, IPC::Message* reply_message,
[email protected]7dad3d5f2010-03-04 00:27:01185 int number_of_navigations, bool include_current_navigation) {
initial.commit09911bf2008-07-26 23:55:29186 NotificationObserver* observer =
[email protected]2e028a082009-08-19 20:32:58187 new NavigationNotificationObserver(tab, this, reply_message,
[email protected]7dad3d5f2010-03-04 00:27:01188 number_of_navigations,
189 include_current_navigation);
initial.commit09911bf2008-07-26 23:55:29190
[email protected]71f65dd2009-02-11 19:14:56191 notification_observer_list_.AddObserver(observer);
initial.commit09911bf2008-07-26 23:55:29192 return observer;
193}
194
[email protected]faf2ee42010-05-11 14:26:17195void AutomationProvider::RemoveNavigationStatusListener(
196 NotificationObserver* obs) {
197 notification_observer_list_.RemoveObserver(obs);
198}
199
initial.commit09911bf2008-07-26 23:55:29200NotificationObserver* AutomationProvider::AddTabStripObserver(
[email protected]1c58a5c2009-05-21 18:47:14201 Browser* parent,
202 IPC::Message* reply_message) {
[email protected]71f65dd2009-02-11 19:14:56203 NotificationObserver* observer =
[email protected]1c58a5c2009-05-21 18:47:14204 new TabAppendedNotificationObserver(parent, this, reply_message);
initial.commit09911bf2008-07-26 23:55:29205 notification_observer_list_.AddObserver(observer);
206
207 return observer;
208}
209
[email protected]faf2ee42010-05-11 14:26:17210void AutomationProvider::RemoveTabStripObserver(NotificationObserver* obs) {
initial.commit09911bf2008-07-26 23:55:29211 notification_observer_list_.RemoveObserver(obs);
212}
213
214void AutomationProvider::AddLoginHandler(NavigationController* tab,
215 LoginHandler* handler) {
216 login_handler_map_[tab] = handler;
217}
218
219void AutomationProvider::RemoveLoginHandler(NavigationController* tab) {
220 DCHECK(login_handler_map_[tab]);
221 login_handler_map_.erase(tab);
222}
223
[email protected]f44265b2009-05-19 18:52:50224void AutomationProvider::AddPortContainer(ExtensionPortContainer* port) {
225 int port_id = port->port_id();
226 DCHECK_NE(-1, port_id);
227 DCHECK(port_containers_.find(port_id) == port_containers_.end());
228
229 port_containers_[port_id] = port;
230}
231
232void AutomationProvider::RemovePortContainer(ExtensionPortContainer* port) {
233 int port_id = port->port_id();
234 DCHECK_NE(-1, port_id);
235
236 PortContainerMap::iterator it = port_containers_.find(port_id);
237 DCHECK(it != port_containers_.end());
238
239 if (it != port_containers_.end()) {
240 delete it->second;
241 port_containers_.erase(it);
242 }
243}
244
245ExtensionPortContainer* AutomationProvider::GetPortContainer(
246 int port_id) const {
247 PortContainerMap::const_iterator it = port_containers_.find(port_id);
248 if (it == port_containers_.end())
249 return NULL;
250
251 return it->second;
252}
253
initial.commit09911bf2008-07-26 23:55:29254int AutomationProvider::GetIndexForNavigationController(
255 const NavigationController* controller, const Browser* parent) const {
256 DCHECK(parent);
[email protected]902cdf772009-05-06 15:08:12257 return parent->GetIndexOfController(controller);
initial.commit09911bf2008-07-26 23:55:29258}
259
[email protected]790788ac2010-04-06 17:52:19260int AutomationProvider::AddExtension(Extension* extension) {
261 DCHECK(extension);
262 return extension_tracker_->Add(extension);
263}
264
265Extension* AutomationProvider::GetExtension(int extension_handle) {
266 return extension_tracker_->GetResource(extension_handle);
267}
268
269Extension* AutomationProvider::GetEnabledExtension(int extension_handle) {
270 Extension* extension = extension_tracker_->GetResource(extension_handle);
271 ExtensionsService* service = profile_->GetExtensionsService();
272 if (extension && service &&
273 service->GetExtensionById(extension->id(), false))
274 return extension;
275 return NULL;
276}
277
278Extension* AutomationProvider::GetDisabledExtension(int extension_handle) {
279 Extension* extension = extension_tracker_->GetResource(extension_handle);
280 ExtensionsService* service = profile_->GetExtensionsService();
281 if (extension && service &&
282 service->GetExtensionById(extension->id(), true) &&
283 !service->GetExtensionById(extension->id(), false))
284 return extension;
285 return NULL;
286}
287
initial.commit09911bf2008-07-26 23:55:29288void AutomationProvider::OnMessageReceived(const IPC::Message& message) {
289 IPC_BEGIN_MESSAGE_MAP(AutomationProvider, message)
[email protected]1b5a48c2010-04-29 23:08:30290#if !defined(OS_MACOSX)
[email protected]71f65dd2009-02-11 19:14:56291 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WindowDrag,
292 WindowSimulateDrag)
[email protected]1b5a48c2010-04-29 23:08:30293#endif // !defined(OS_MACOSX)
[email protected]d7fa7552009-03-20 21:06:37294#if defined(OS_WIN)
[email protected]71f65dd2009-02-11 19:14:56295 IPC_MESSAGE_HANDLER(AutomationMsg_TabHWND, GetTabHWND)
[email protected]de246f52009-02-25 18:25:45296#endif // defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29297 IPC_MESSAGE_HANDLER(AutomationMsg_HandleUnused, HandleUnused)
[email protected]a7eee32f2009-05-22 18:08:17298 IPC_MESSAGE_HANDLER(AutomationMsg_SetProxyConfig, SetProxyConfig);
[email protected]d301c952009-07-13 15:02:41299 IPC_MESSAGE_HANDLER(AutomationMsg_PrintAsync, PrintAsync)
[email protected]1c58a5c2009-05-21 18:47:14300 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_Find, HandleFindRequest)
[email protected]59a611242010-04-02 02:24:04301 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_SendJSONRequest,
302 SendJSONRequest)
[email protected]71f65dd2009-02-11 19:14:56303 IPC_MESSAGE_HANDLER(AutomationMsg_GetPageCurrentEncoding,
[email protected]97fa6ce32008-12-19 01:48:16304 GetPageCurrentEncoding)
[email protected]1c58a5c2009-05-21 18:47:14305 IPC_MESSAGE_HANDLER(AutomationMsg_OverrideEncoding, OverrideEncoding)
[email protected]f7a68432009-07-29 23:18:19306 IPC_MESSAGE_HANDLER(AutomationMsg_SelectAll, SelectAll)
307 IPC_MESSAGE_HANDLER(AutomationMsg_Cut, Cut)
308 IPC_MESSAGE_HANDLER(AutomationMsg_Copy, Copy)
309 IPC_MESSAGE_HANDLER(AutomationMsg_Paste, Paste)
310 IPC_MESSAGE_HANDLER(AutomationMsg_ReloadAsync, ReloadAsync)
311 IPC_MESSAGE_HANDLER(AutomationMsg_StopAsync, StopAsync)
[email protected]1bb5f892009-10-06 01:44:57312 IPC_MESSAGE_HANDLER(AutomationMsg_SetPageFontSize, OnSetPageFontSize)
[email protected]d11c8e92009-10-20 23:26:40313 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_InstallExtension,
314 InstallExtension)
315 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_LoadExpandedExtension,
316 LoadExpandedExtension)
[email protected]a1e62d12010-03-16 02:18:43317 IPC_MESSAGE_HANDLER(AutomationMsg_GetEnabledExtensions,
318 GetEnabledExtensions)
[email protected]790788ac2010-04-06 17:52:19319 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForExtensionTestResult,
320 WaitForExtensionTestResult)
321 IPC_MESSAGE_HANDLER_DELAY_REPLY(
322 AutomationMsg_InstallExtensionAndGetHandle,
323 InstallExtensionAndGetHandle)
324 IPC_MESSAGE_HANDLER(AutomationMsg_UninstallExtension,
325 UninstallExtension)
326 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_EnableExtension,
327 EnableExtension)
328 IPC_MESSAGE_HANDLER(AutomationMsg_DisableExtension,
329 DisableExtension)
330 IPC_MESSAGE_HANDLER_DELAY_REPLY(
331 AutomationMsg_ExecuteExtensionActionInActiveTabAsync,
332 ExecuteExtensionActionInActiveTabAsync)
333 IPC_MESSAGE_HANDLER(AutomationMsg_MoveExtensionBrowserAction,
334 MoveExtensionBrowserAction)
335 IPC_MESSAGE_HANDLER(AutomationMsg_GetExtensionProperty,
336 GetExtensionProperty)
[email protected]fedaa7d2010-01-26 20:34:57337 IPC_MESSAGE_HANDLER(AutomationMsg_ShutdownSessionService,
338 ShutdownSessionService)
[email protected]673fd2c02010-02-04 23:10:00339 IPC_MESSAGE_HANDLER(AutomationMsg_SaveAsAsync, SaveAsAsync)
[email protected]7dad3d5f2010-03-04 00:27:01340 IPC_MESSAGE_HANDLER(AutomationMsg_SetContentSetting, SetContentSetting)
[email protected]bc73b4e52010-03-26 04:16:20341 IPC_MESSAGE_HANDLER(AutomationMsg_RemoveBrowsingData, RemoveBrowsingData)
[email protected]bdd5a9c92010-06-14 18:21:00342 IPC_MESSAGE_HANDLER(AutomationMsg_ResetToDefaultTheme, ResetToDefaultTheme)
[email protected]52415f842010-06-10 21:51:52343#if defined(OS_WIN)
344 // These are for use with external tabs.
345 IPC_MESSAGE_HANDLER(AutomationMsg_CreateExternalTab, CreateExternalTab)
346 IPC_MESSAGE_HANDLER(AutomationMsg_ProcessUnhandledAccelerator,
347 ProcessUnhandledAccelerator)
348 IPC_MESSAGE_HANDLER(AutomationMsg_SetInitialFocus, SetInitialFocus)
349 IPC_MESSAGE_HANDLER(AutomationMsg_TabReposition, OnTabReposition)
350 IPC_MESSAGE_HANDLER(AutomationMsg_ForwardContextMenuCommandToChrome,
351 OnForwardContextMenuCommandToChrome)
352 IPC_MESSAGE_HANDLER(AutomationMsg_NavigateInExternalTab,
353 NavigateInExternalTab)
354 IPC_MESSAGE_HANDLER(AutomationMsg_NavigateExternalTabAtIndex,
355 NavigateExternalTabAtIndex)
356 IPC_MESSAGE_HANDLER(AutomationMsg_ConnectExternalTab, ConnectExternalTab)
357 IPC_MESSAGE_HANDLER(AutomationMsg_SetEnableExtensionAutomation,
358 SetEnableExtensionAutomation)
359 IPC_MESSAGE_HANDLER(AutomationMsg_HandleMessageFromExternalHost,
360 OnMessageFromExternalHost)
[email protected]bdd5a9c92010-06-14 18:21:00361 IPC_MESSAGE_HANDLER(AutomationMsg_BrowserMove, OnBrowserMoved)
[email protected]1f71d5882010-07-15 20:39:07362 IPC_MESSAGE_HANDLER(AutomationMsg_RunUnloadHandlers, OnRunUnloadHandlers)
[email protected]7f860dd82010-08-09 23:18:05363 IPC_MESSAGE_HANDLER(AutomationMsg_SetZoomLevel, OnSetZoomLevel)
[email protected]bdd5a9c92010-06-14 18:21:00364#endif // defined(OS_WIN)
365#if defined(OS_CHROMEOS)
366 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_LoginWithUserAndPass,
367 LoginWithUserAndPass)
368#endif // defined(OS_CHROMEOS)
initial.commit09911bf2008-07-26 23:55:29369 IPC_END_MESSAGE_MAP()
370}
371
[email protected]fedaa7d2010-01-26 20:34:57372void AutomationProvider::ShutdownSessionService(int handle, bool* result) {
373 if (browser_tracker_->ContainsHandle(handle)) {
374 Browser* browser = browser_tracker_->GetResource(handle);
375 browser->profile()->ShutdownSessionService();
376 *result = true;
377 } else {
378 *result = false;
379 }
380}
381
[email protected]fc2e0872009-08-21 22:14:41382// This task just adds another task to the event queue. This is useful if
383// you want to ensure that any tasks added to the event queue after this one
384// have already been processed by the time |task| is run.
385class InvokeTaskLaterTask : public Task {
386 public:
387 explicit InvokeTaskLaterTask(Task* task) : task_(task) {}
388 virtual ~InvokeTaskLaterTask() {}
389
390 virtual void Run() {
391 MessageLoop::current()->PostTask(FROM_HERE, task_);
392 }
393
394 private:
395 Task* task_;
396
397 DISALLOW_COPY_AND_ASSIGN(InvokeTaskLaterTask);
398};
399
initial.commit09911bf2008-07-26 23:55:29400void AutomationProvider::HandleUnused(const IPC::Message& message, int handle) {
401 if (window_tracker_->ContainsHandle(handle)) {
402 window_tracker_->Remove(window_tracker_->GetResource(handle));
403 }
404}
405
406void AutomationProvider::OnChannelError() {
[email protected]2947cdcd2009-12-03 21:05:16407 LOG(INFO) << "AutomationProxy went away, shutting down app.";
[email protected]295039bd2008-08-15 04:32:57408 AutomationProviderList::GetInstance()->RemoveProvider(this);
initial.commit09911bf2008-07-26 23:55:29409}
410
initial.commit09911bf2008-07-26 23:55:29411bool AutomationProvider::Send(IPC::Message* msg) {
[email protected]295039bd2008-08-15 04:32:57412 DCHECK(channel_.get());
413 return channel_->Send(msg);
initial.commit09911bf2008-07-26 23:55:29414}
415
416Browser* AutomationProvider::FindAndActivateTab(
417 NavigationController* controller) {
418 int tab_index;
419 Browser* browser = Browser::GetBrowserForController(controller, &tab_index);
420 if (browser)
421 browser->SelectTabContentsAt(tab_index, true);
422
423 return browser;
424}
425
[email protected]4f999132009-03-31 18:08:40426void AutomationProvider::HandleFindRequest(
427 int handle,
428 const AutomationMsg_Find_Params& params,
429 IPC::Message* reply_message) {
initial.commit09911bf2008-07-26 23:55:29430 if (!tab_tracker_->ContainsHandle(handle)) {
[email protected]71f65dd2009-02-11 19:14:56431 AutomationMsg_FindInPage::WriteReplyParams(reply_message, -1, -1);
432 Send(reply_message);
initial.commit09911bf2008-07-26 23:55:29433 return;
434 }
435
436 NavigationController* nav = tab_tracker_->GetResource(handle);
[email protected]7f0005a2009-04-15 03:25:11437 TabContents* tab_contents = nav->tab_contents();
initial.commit09911bf2008-07-26 23:55:29438
439 find_in_page_observer_.reset(new
[email protected]1c58a5c2009-05-21 18:47:14440 FindInPageNotificationObserver(this, tab_contents, reply_message));
initial.commit09911bf2008-07-26 23:55:29441
[email protected]57c6a652009-05-04 07:58:34442 tab_contents->set_current_find_request_id(
443 FindInPageNotificationObserver::kFindInPageRequestId);
444 tab_contents->render_view_host()->StartFinding(
445 FindInPageNotificationObserver::kFindInPageRequestId,
446 params.search_string, params.forward, params.match_case,
447 params.find_next);
initial.commit09911bf2008-07-26 23:55:29448}
449
[email protected]ef413ca2010-05-25 21:09:14450// Sample json input: { "command": "SetWindowDimensions",
451// "x": 20, # optional
452// "y": 20, # optional
453// "width": 800, # optional
454// "height": 600 } # optional
455void AutomationProvider::SetWindowDimensions(Browser* browser,
456 DictionaryValue* args,
457 IPC::Message* reply_message) {
458 gfx::Rect rect = browser->window()->GetRestoredBounds();
459 int x, y, width, height;
[email protected]ff4c1d82010-08-04 16:58:12460 if (args->GetInteger("x", &x))
[email protected]ef413ca2010-05-25 21:09:14461 rect.set_x(x);
[email protected]ff4c1d82010-08-04 16:58:12462 if (args->GetInteger("y", &y))
[email protected]ef413ca2010-05-25 21:09:14463 rect.set_y(y);
[email protected]ff4c1d82010-08-04 16:58:12464 if (args->GetInteger("width", &width))
[email protected]ef413ca2010-05-25 21:09:14465 rect.set_width(width);
[email protected]ff4c1d82010-08-04 16:58:12466 if (args->GetInteger("height", &height))
[email protected]ef413ca2010-05-25 21:09:14467 rect.set_height(height);
468 browser->window()->SetBounds(rect);
[email protected]7c983cc2010-07-16 11:33:34469 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
[email protected]ef413ca2010-05-25 21:09:14470}
471
[email protected]38b5a3852010-07-21 06:49:52472ListValue* AutomationProvider::GetInfobarsInfo(TabContents* tc) {
473 // Each infobar may have different properties depending on the type.
474 ListValue* infobars = new ListValue;
475 for (int infobar_index = 0;
476 infobar_index < tc->infobar_delegate_count();
477 ++infobar_index) {
478 DictionaryValue* infobar_item = new DictionaryValue;
479 InfoBarDelegate* infobar = tc->GetInfoBarDelegateAt(infobar_index);
480 if (infobar->AsConfirmInfoBarDelegate()) {
481 // Also covers ThemeInstalledInfoBarDelegate and
482 // CrashedExtensionInfoBarDelegate.
[email protected]ff4c1d82010-08-04 16:58:12483 infobar_item->SetString("type", "confirm_infobar");
[email protected]38b5a3852010-07-21 06:49:52484 ConfirmInfoBarDelegate* confirm_infobar =
485 infobar->AsConfirmInfoBarDelegate();
[email protected]e23d3a32010-08-13 19:39:58486 infobar_item->SetString("text", confirm_infobar->GetMessageText());
487 infobar_item->SetString("link_text", confirm_infobar->GetLinkText());
[email protected]38b5a3852010-07-21 06:49:52488 ListValue* buttons_list = new ListValue;
489 int buttons = confirm_infobar->GetButtons();
490 if (ConfirmInfoBarDelegate::BUTTON_OK & buttons) {
491 StringValue* button_label = new StringValue(
492 confirm_infobar->GetButtonLabel(
493 ConfirmInfoBarDelegate::BUTTON_OK));
494 buttons_list->Append(button_label);
495 }
496 if (ConfirmInfoBarDelegate::BUTTON_CANCEL & buttons) {
497 StringValue* button_label = new StringValue(
498 confirm_infobar->GetButtonLabel(
499 ConfirmInfoBarDelegate::BUTTON_CANCEL));
500 buttons_list->Append(button_label);
501 }
[email protected]ff4c1d82010-08-04 16:58:12502 infobar_item->Set("buttons", buttons_list);
[email protected]38b5a3852010-07-21 06:49:52503 } else if (infobar->AsAlertInfoBarDelegate()) {
[email protected]ff4c1d82010-08-04 16:58:12504 infobar_item->SetString("type", "alert_infobar");
[email protected]38b5a3852010-07-21 06:49:52505 AlertInfoBarDelegate* alert_infobar =
506 infobar->AsAlertInfoBarDelegate();
[email protected]e23d3a32010-08-13 19:39:58507 infobar_item->SetString("text", alert_infobar->GetMessageText());
[email protected]38b5a3852010-07-21 06:49:52508 } else if (infobar->AsLinkInfoBarDelegate()) {
[email protected]ff4c1d82010-08-04 16:58:12509 infobar_item->SetString("type", "link_infobar");
[email protected]38b5a3852010-07-21 06:49:52510 LinkInfoBarDelegate* link_infobar = infobar->AsLinkInfoBarDelegate();
[email protected]e23d3a32010-08-13 19:39:58511 infobar_item->SetString("link_text", link_infobar->GetLinkText());
[email protected]38b5a3852010-07-21 06:49:52512 } else if (infobar->AsTranslateInfoBarDelegate()) {
[email protected]ff4c1d82010-08-04 16:58:12513 infobar_item->SetString("type", "translate_infobar");
[email protected]38b5a3852010-07-21 06:49:52514 TranslateInfoBarDelegate* translate_infobar =
515 infobar->AsTranslateInfoBarDelegate();
[email protected]ff4c1d82010-08-04 16:58:12516 infobar_item->SetString("original_lang_code",
[email protected]38b5a3852010-07-21 06:49:52517 translate_infobar->GetOriginalLanguageCode());
[email protected]ff4c1d82010-08-04 16:58:12518 infobar_item->SetString("target_lang_code",
[email protected]38b5a3852010-07-21 06:49:52519 translate_infobar->GetTargetLanguageCode());
520 } else if (infobar->AsExtensionInfoBarDelegate()) {
[email protected]ff4c1d82010-08-04 16:58:12521 infobar_item->SetString("type", "extension_infobar");
[email protected]38b5a3852010-07-21 06:49:52522 } else {
[email protected]ff4c1d82010-08-04 16:58:12523 infobar_item->SetString("type", "unknown_infobar");
[email protected]38b5a3852010-07-21 06:49:52524 }
525 infobars->Append(infobar_item);
526 }
527 return infobars;
528}
529
530// Sample json input: { "command": "WaitForInfobarCount",
531// "count": COUNT,
532// "tab_index": INDEX }
533// Sample output: {}
534void AutomationProvider::WaitForInfobarCount(Browser* browser,
535 DictionaryValue* args,
536 IPC::Message* reply_message) {
537 int tab_index;
538 int count;
[email protected]ff4c1d82010-08-04 16:58:12539 if (!args->GetInteger("count", &count) || count < 0 ||
540 !args->GetInteger("tab_index", &tab_index) || tab_index < 0) {
[email protected]38b5a3852010-07-21 06:49:52541 AutomationJSONReply(this, reply_message).SendError(
542 "Missing or invalid args: 'count', 'tab_index'.");
543 return;
544 }
545
546 TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
547 // Observer deletes itself.
548 new WaitForInfobarCountObserver(this, reply_message, tab_contents, count);
549}
550
[email protected]e004a2d2010-07-22 04:55:28551// Sample json input: { "command": "PerformActionOnInfobar",
552// "action": "dismiss",
553// "infobar_index": 0,
554// "tab_index": 0 }
555// Sample output: {}
556void AutomationProvider::PerformActionOnInfobar(Browser* browser,
557 DictionaryValue* args,
558 IPC::Message* reply_message) {
559 AutomationJSONReply reply(this, reply_message);
560 int tab_index;
561 int infobar_index;
562 std::string action;
[email protected]ff4c1d82010-08-04 16:58:12563 if (!args->GetInteger("tab_index", &tab_index) ||
564 !args->GetInteger("infobar_index", &infobar_index) ||
565 !args->GetString("action", &action)) {
[email protected]e004a2d2010-07-22 04:55:28566 reply.SendError("Invalid or missing args");
567 return;
568 }
569 TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
570 if (!tab_contents) {
571 reply.SendError(StringPrintf("No such tab at index %d", tab_index));
572 return;
573 }
574 InfoBarDelegate* infobar = NULL;
575 if (infobar_index < 0 ||
576 infobar_index >= tab_contents->infobar_delegate_count() ||
577 !(infobar = tab_contents->GetInfoBarDelegateAt(infobar_index))) {
578 reply.SendError(StringPrintf("No such infobar at index %d", infobar_index));
579 return;
580 }
581 if ("dismiss" == action) {
582 infobar->InfoBarDismissed();
583 tab_contents->RemoveInfoBar(infobar);
584 reply.SendSuccess(NULL);
585 return;
586 }
587 if ("accept" == action || "cancel" == action) {
588 ConfirmInfoBarDelegate* confirm_infobar;
589 if (!(confirm_infobar = infobar->AsConfirmInfoBarDelegate())) {
590 reply.SendError("Not a confirm infobar");
591 return;
592 }
593 if ("accept" == action) {
594 if (confirm_infobar->Accept())
595 tab_contents->RemoveInfoBar(infobar);
596 } else if ("cancel" == action) {
597 if (confirm_infobar->Cancel())
598 tab_contents->RemoveInfoBar(infobar);
599 }
600 reply.SendSuccess(NULL);
601 return;
602 }
603 reply.SendError("Invalid action");
604}
605
[email protected]26adfd312010-07-20 01:04:46606namespace {
607
608// Task to get info about BrowserChildProcessHost. Must run on IO thread to
609// honor the semantics of BrowserChildProcessHost.
610// Used by AutomationProvider::GetBrowserInfo().
611class GetChildProcessHostInfoTask : public Task {
612 public:
613 GetChildProcessHostInfoTask(base::WaitableEvent* event,
614 ListValue* child_processes)
615 : event_(event),
616 child_processes_(child_processes) {}
617
618 virtual void Run() {
619 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
620 for (BrowserChildProcessHost::Iterator iter; !iter.Done(); ++iter) {
621 // Only add processes which are already started,
622 // since we need their handle.
623 if ((*iter)->handle() == base::kNullProcessHandle) {
624 continue;
625 }
626 ChildProcessInfo* info = *iter;
627 DictionaryValue* item = new DictionaryValue;
[email protected]ff4c1d82010-08-04 16:58:12628 item->SetString("name", WideToUTF16Hack(info->name()));
629 item->SetString("type",
[email protected]41b5c202010-08-19 01:11:08630 ChildProcessInfo::GetTypeNameInEnglish(info->type()));
[email protected]ff4c1d82010-08-04 16:58:12631 item->SetInteger("pid", base::GetProcId(info->handle()));
[email protected]26adfd312010-07-20 01:04:46632 child_processes_->Append(item);
633 }
634 event_->Signal();
635 }
636
637 private:
638 base::WaitableEvent* const event_; // weak
639 ListValue* child_processes_;
640
641 DISALLOW_COPY_AND_ASSIGN(GetChildProcessHostInfoTask);
642};
643
644} // namespace
645
[email protected]a9ff2c02010-05-13 17:33:05646// Sample json input: { "command": "GetBrowserInfo" }
647// Refer to GetBrowserInfo() in chrome/test/pyautolib/pyauto.py for
648// sample json output.
[email protected]53329582010-05-14 21:10:58649void AutomationProvider::GetBrowserInfo(Browser* browser,
650 DictionaryValue* args,
[email protected]a9ff2c02010-05-13 17:33:05651 IPC::Message* reply_message) {
[email protected]a9ff2c02010-05-13 17:33:05652 DictionaryValue* properties = new DictionaryValue;
[email protected]ff4c1d82010-08-04 16:58:12653 properties->SetString("ChromeVersion", chrome::kChromeVersion);
654 properties->SetString("BrowserProcessExecutableName",
655 WideToUTF16Hack(chrome::kBrowserProcessExecutableName));
656 properties->SetString("HelperProcessExecutableName",
657 WideToUTF16Hack(chrome::kHelperProcessExecutableName));
658 properties->SetString("BrowserProcessExecutablePath",
659 WideToUTF16Hack(chrome::kBrowserProcessExecutablePath));
660 properties->SetString("HelperProcessExecutablePath",
[email protected]a9ff2c02010-05-13 17:33:05661 chrome::kHelperProcessExecutablePath);
[email protected]ff4c1d82010-08-04 16:58:12662 properties->SetString("command_line_string",
[email protected]a9ff2c02010-05-13 17:33:05663 CommandLine::ForCurrentProcess()->command_line_string());
[email protected]9d8fe3b2010-08-20 19:51:24664 FilePath dumps_path;
665 PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path);
666 properties->SetString("DIR_CRASH_DUMPS", dumps_path.value());
[email protected]44eed9f2010-06-28 22:04:00667
668 std::string branding;
669#if defined(GOOGLE_CHROME_BUILD)
670 branding = "Google Chrome";
671#elif defined(CHROMIUM_BUILD)
672 branding = "Chromium";
673#else
674 branding = "Unknown Branding";
[email protected]a9ff2c02010-05-13 17:33:05675#endif
[email protected]ff4c1d82010-08-04 16:58:12676 properties->SetString("branding", branding);
[email protected]a9ff2c02010-05-13 17:33:05677
678 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
[email protected]ff4c1d82010-08-04 16:58:12679 return_value->Set("properties", properties);
[email protected]a9ff2c02010-05-13 17:33:05680
[email protected]ff4c1d82010-08-04 16:58:12681 return_value->SetInteger("browser_pid", base::GetCurrentProcId());
[email protected]ef413ca2010-05-25 21:09:14682 // Add info about all windows in a list of dictionaries, one dictionary
683 // item per window.
684 ListValue* windows = new ListValue;
685 int windex = 0;
686 for (BrowserList::const_iterator it = BrowserList::begin();
687 it != BrowserList::end();
688 ++it, ++windex) {
689 DictionaryValue* browser_item = new DictionaryValue;
690 browser = *it;
[email protected]ff4c1d82010-08-04 16:58:12691 browser_item->SetInteger("index", windex);
[email protected]ef413ca2010-05-25 21:09:14692 // Window properties
693 gfx::Rect rect = browser->window()->GetRestoredBounds();
[email protected]ff4c1d82010-08-04 16:58:12694 browser_item->SetInteger("x", rect.x());
695 browser_item->SetInteger("y", rect.y());
696 browser_item->SetInteger("width", rect.width());
697 browser_item->SetInteger("height", rect.height());
698 browser_item->SetBoolean("fullscreen",
[email protected]ef413ca2010-05-25 21:09:14699 browser->window()->IsFullscreen());
[email protected]ff4c1d82010-08-04 16:58:12700 browser_item->SetInteger("selected_tab", browser->selected_index());
701 browser_item->SetBoolean("incognito",
[email protected]ef413ca2010-05-25 21:09:14702 browser->profile()->IsOffTheRecord());
703 // For each window, add info about all tabs in a list of dictionaries,
704 // one dictionary item per tab.
705 ListValue* tabs = new ListValue;
706 for (int i = 0; i < browser->tab_count(); ++i) {
707 TabContents* tc = browser->GetTabContentsAt(i);
708 DictionaryValue* tab = new DictionaryValue;
[email protected]ff4c1d82010-08-04 16:58:12709 tab->SetInteger("index", i);
710 tab->SetString("url", tc->GetURL().spec());
711 tab->SetInteger("renderer_pid",
[email protected]ef413ca2010-05-25 21:09:14712 base::GetProcId(tc->GetRenderProcessHost()->GetHandle()));
[email protected]ff4c1d82010-08-04 16:58:12713 tab->Set("infobars", GetInfobarsInfo(tc));
[email protected]ef413ca2010-05-25 21:09:14714 tabs->Append(tab);
715 }
[email protected]ff4c1d82010-08-04 16:58:12716 browser_item->Set("tabs", tabs);
[email protected]ef413ca2010-05-25 21:09:14717
718 windows->Append(browser_item);
719 }
[email protected]ff4c1d82010-08-04 16:58:12720 return_value->Set("windows", windows);
[email protected]ef413ca2010-05-25 21:09:14721
[email protected]ff4c1d82010-08-04 16:58:12722 return_value->SetString("child_process_path",
[email protected]ef413ca2010-05-25 21:09:14723 ChildProcessHost::GetChildPath(true).value());
724 // Child processes are the processes for plugins and other workers.
725 // Add all child processes in a list of dictionaries, one dictionary item
726 // per child process.
727 ListValue* child_processes = new ListValue;
[email protected]26adfd312010-07-20 01:04:46728 base::WaitableEvent event(true /* manual reset */,
729 false /* not initially signaled */);
730 CHECK(ChromeThread::PostTask(
731 ChromeThread::IO, FROM_HERE,
732 new GetChildProcessHostInfoTask(&event, child_processes)));
733 event.Wait();
[email protected]ff4c1d82010-08-04 16:58:12734 return_value->Set("child_processes", child_processes);
[email protected]ef413ca2010-05-25 21:09:14735
736 // Add all extension processes in a list of dictionaries, one dictionary
737 // item per extension process.
738 ListValue* extension_processes = new ListValue;
739 ProfileManager* profile_manager = g_browser_process->profile_manager();
740 for (ProfileManager::const_iterator it = profile_manager->begin();
741 it != profile_manager->end(); ++it) {
742 ExtensionProcessManager* process_manager =
743 (*it)->GetExtensionProcessManager();
744 ExtensionProcessManager::const_iterator jt;
745 for (jt = process_manager->begin(); jt != process_manager->end(); ++jt) {
746 ExtensionHost* ex_host = *jt;
747 // Don't add dead extension processes.
748 if (!ex_host->IsRenderViewLive())
749 continue;
750 DictionaryValue* item = new DictionaryValue;
[email protected]ff4c1d82010-08-04 16:58:12751 item->SetString("name", ex_host->extension()->name());
[email protected]ef413ca2010-05-25 21:09:14752 item->SetInteger(
[email protected]ff4c1d82010-08-04 16:58:12753 "pid",
[email protected]ef413ca2010-05-25 21:09:14754 base::GetProcId(ex_host->render_process_host()->GetHandle()));
755 extension_processes->Append(item);
756 }
757 }
[email protected]ff4c1d82010-08-04 16:58:12758 return_value->Set("extension_processes", extension_processes);
[email protected]7c983cc2010-07-16 11:33:34759 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
[email protected]a9ff2c02010-05-13 17:33:05760}
761
[email protected]24e2b102010-04-29 17:56:47762// Sample json input: { "command": "GetHistoryInfo",
763// "search_text": "some text" }
[email protected]e6e376e2010-04-19 21:41:36764// Refer chrome/test/pyautolib/history_info.py for sample json output.
[email protected]53329582010-05-14 21:10:58765void AutomationProvider::GetHistoryInfo(Browser* browser,
766 DictionaryValue* args,
767 IPC::Message* reply_message) {
[email protected]e6e376e2010-04-19 21:41:36768 consumer_.CancelAllRequests();
769
[email protected]e53668962010-06-23 15:35:25770 string16 search_text;
771 args->GetString("search_text", &search_text);
[email protected]e6e376e2010-04-19 21:41:36772
773 // Fetch history.
774 HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
775 history::QueryOptions options;
776 // The observer owns itself. It deletes itself after it fetches history.
777 AutomationProviderHistoryObserver* history_observer =
778 new AutomationProviderHistoryObserver(this, reply_message);
779 hs->QueryHistory(
780 search_text,
781 options,
782 &consumer_,
783 NewCallback(history_observer,
784 &AutomationProviderHistoryObserver::HistoryQueryComplete));
785}
786
[email protected]bbe6aa02010-05-07 17:27:29787// Sample json input: { "command": "AddHistoryItem",
788// "item": { "URL": "http://www.google.com",
789// "title": "Google", # optional
790// "time": 12345 # optional (time_t)
791// } }
792// Refer chrome/test/pyautolib/pyauto.py for details on input.
[email protected]53329582010-05-14 21:10:58793void AutomationProvider::AddHistoryItem(Browser* browser,
794 DictionaryValue* args,
795 IPC::Message* reply_message) {
[email protected]bbe6aa02010-05-07 17:27:29796 DictionaryValue* item = NULL;
[email protected]ff4c1d82010-08-04 16:58:12797 args->GetDictionary("item", &item);
[email protected]bbe6aa02010-05-07 17:27:29798 string16 url_text;
[email protected]e53668962010-06-23 15:35:25799 string16 title;
[email protected]bbe6aa02010-05-07 17:27:29800 base::Time time = base::Time::Now();
[email protected]7c983cc2010-07-16 11:33:34801 AutomationJSONReply reply(this, reply_message);
[email protected]bbe6aa02010-05-07 17:27:29802
[email protected]7c983cc2010-07-16 11:33:34803 if (!item->GetString("url", &url_text)) {
804 reply.SendError("bad args (no URL in dict?)");
805 return;
[email protected]bbe6aa02010-05-07 17:27:29806 }
[email protected]7c983cc2010-07-16 11:33:34807 GURL gurl(url_text);
808 item->GetString("title", &title); // Don't care if it fails.
809 int it;
810 double dt;
[email protected]ff4c1d82010-08-04 16:58:12811 if (item->GetInteger("time", &it))
[email protected]7c983cc2010-07-16 11:33:34812 time = base::Time::FromTimeT(it);
[email protected]ff4c1d82010-08-04 16:58:12813 else if (item->GetReal("time", &dt))
[email protected]7c983cc2010-07-16 11:33:34814 time = base::Time::FromDoubleT(dt);
[email protected]f6ff0df2010-07-11 22:41:43815
[email protected]7c983cc2010-07-16 11:33:34816 // Ideas for "dummy" values (e.g. id_scope) came from
817 // chrome/browser/autocomplete/history_contents_provider_unittest.cc
818 HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
819 const void* id_scope = reinterpret_cast<void*>(1);
820 hs->AddPage(gurl, time,
821 id_scope,
822 0,
823 GURL(),
824 PageTransition::LINK,
825 history::RedirectList(),
[email protected]5989f1a2010-08-21 02:21:11826 history::SOURCE_BROWSED,
[email protected]7c983cc2010-07-16 11:33:34827 false);
828 if (title.length())
829 hs->SetPageTitle(gurl, title);
830 reply.SendSuccess(NULL);
[email protected]bbe6aa02010-05-07 17:27:29831}
832
[email protected]2d54c4032010-08-20 00:42:28833DictionaryValue* AutomationProvider::GetDictionaryFromDownloadItem(
834 const DownloadItem* download) {
[email protected]d4adc292010-04-15 18:06:39835 std::map<DownloadItem::DownloadState, std::string> state_to_string;
836 state_to_string[DownloadItem::IN_PROGRESS] = std::string("IN_PROGRESS");
837 state_to_string[DownloadItem::CANCELLED] = std::string("CANCELLED");
838 state_to_string[DownloadItem::REMOVING] = std::string("REMOVING");
839 state_to_string[DownloadItem::COMPLETE] = std::string("COMPLETE");
840
841 std::map<DownloadItem::SafetyState, std::string> safety_state_to_string;
842 safety_state_to_string[DownloadItem::SAFE] = std::string("SAFE");
843 safety_state_to_string[DownloadItem::DANGEROUS] = std::string("DANGEROUS");
844 safety_state_to_string[DownloadItem::DANGEROUS_BUT_VALIDATED] =
845 std::string("DANGEROUS_BUT_VALIDATED");
846
[email protected]2d54c4032010-08-20 00:42:28847 DictionaryValue* dl_item_value = new DictionaryValue;
848 dl_item_value->SetInteger("id", static_cast<int>(download->id()));
849 dl_item_value->SetString("url", download->url().spec());
850 dl_item_value->SetString("referrer_url", download->referrer_url().spec());
851 dl_item_value->SetString("file_name", download->GetFileName().value());
852 dl_item_value->SetString("full_path", download->full_path().value());
853 dl_item_value->SetBoolean("is_paused", download->is_paused());
854 dl_item_value->SetBoolean("open_when_complete",
855 download->open_when_complete());
856 dl_item_value->SetBoolean("is_extension_install",
857 download->is_extension_install());
858 dl_item_value->SetBoolean("is_temporary", download->is_temporary());
859 dl_item_value->SetBoolean("is_otr", download->is_otr()); // off-the-record
860 dl_item_value->SetString("state", state_to_string[download->state()]);
861 dl_item_value->SetString("safety_state",
862 safety_state_to_string[download->safety_state()]);
863 dl_item_value->SetInteger("PercentComplete", download->PercentComplete());
864
865 return dl_item_value;
866}
867
868// Sample json input: { "command": "GetDownloadsInfo" }
869// Refer chrome/test/pyautolib/download_info.py for sample json output.
870void AutomationProvider::GetDownloadsInfo(Browser* browser,
871 DictionaryValue* args,
872 IPC::Message* reply_message) {
873 AutomationJSONReply reply(this, reply_message);
874
875 if (!profile_->HasCreatedDownloadManager()) {
876 reply.SendError("no download manager");
877 return;
878 }
879
880 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
881 std::vector<DownloadItem*> downloads;
882 profile_->GetDownloadManager()->GetAllDownloads(FilePath(), &downloads);
883
[email protected]d4adc292010-04-15 18:06:39884 ListValue* list_of_downloads = new ListValue;
885 for (std::vector<DownloadItem*>::iterator it = downloads.begin();
886 it != downloads.end();
887 it++) { // Fill info about each download item.
[email protected]2d54c4032010-08-20 00:42:28888 list_of_downloads->Append(GetDictionaryFromDownloadItem(*it));
[email protected]d4adc292010-04-15 18:06:39889 }
[email protected]ff4c1d82010-08-04 16:58:12890 return_value->Set("downloads", list_of_downloads);
[email protected]7c983cc2010-07-16 11:33:34891 reply.SendSuccess(return_value.get());
[email protected]d4adc292010-04-15 18:06:39892 // All value objects allocated above are owned by |return_value|
893 // and get freed by it.
894}
895
[email protected]59a611242010-04-02 02:24:04896void AutomationProvider::WaitForDownloadsToComplete(
[email protected]53329582010-05-14 21:10:58897 Browser* browser,
[email protected]59a611242010-04-02 02:24:04898 DictionaryValue* args,
899 IPC::Message* reply_message) {
[email protected]7c983cc2010-07-16 11:33:34900 AutomationJSONReply reply(this, reply_message);
[email protected]59a611242010-04-02 02:24:04901
902 // Look for a quick return.
903 if (!profile_->HasCreatedDownloadManager()) {
[email protected]7c983cc2010-07-16 11:33:34904 reply.SendSuccess(NULL); // No download manager.
905 return;
[email protected]59a611242010-04-02 02:24:04906 }
[email protected]82f37b02010-07-29 22:04:57907 std::vector<DownloadItem*> downloads;
908 profile_->GetDownloadManager()->GetCurrentDownloads(FilePath(), &downloads);
909 if (downloads.empty()) {
[email protected]7c983cc2010-07-16 11:33:34910 reply.SendSuccess(NULL);
[email protected]f6ff0df2010-07-11 22:41:43911 return;
912 }
[email protected]59a611242010-04-02 02:24:04913
914 // The observer owns itself. When the last observed item pings, it
915 // deletes itself.
916 AutomationProviderDownloadItemObserver* item_observer =
917 new AutomationProviderDownloadItemObserver(
918 this, reply_message, downloads.size());
919 for (std::vector<DownloadItem*>::iterator i = downloads.begin();
920 i != downloads.end();
921 i++) {
922 (*i)->AddObserver(item_observer);
923 }
924}
925
[email protected]2d54c4032010-08-20 00:42:28926namespace {
927
928DownloadItem* GetDownloadItemFromId(int id, DownloadManager* download_manager) {
929 std::vector<DownloadItem*> downloads;
930 download_manager->GetAllDownloads(FilePath(), &downloads);
931 DownloadItem* selected_item = NULL;
932
933 for (std::vector<DownloadItem*>::iterator it = downloads.begin();
934 it != downloads.end();
935 it++) {
936 DownloadItem* curr_item = *it;
937 if (curr_item->id() == id) {
938 selected_item = curr_item;
939 break;
940 }
941 }
942 return selected_item;
943}
944
945} // namespace
946
947// See PerformActionOnDownload() in chrome/test/pyautolib/pyauto.py for sample
948// json input and output.
949void AutomationProvider::PerformActionOnDownload(Browser* browser,
950 DictionaryValue* args,
951 IPC::Message* reply_message) {
952 int id;
953 std::string action;
954
955 if (!profile_->HasCreatedDownloadManager()) {
956 AutomationJSONReply(this, reply_message).SendError("No download manager.");
957 return;
958 }
959 if (!args->GetInteger("id", &id) || !args->GetString("action", &action)) {
960 AutomationJSONReply(this, reply_message).SendError(
961 "Must include int id and string action.");
962 return;
963 }
964
965 DownloadManager* download_manager = profile_->GetDownloadManager();
966 DownloadItem* selected_item = GetDownloadItemFromId(id, download_manager);
967 if (!selected_item) {
968 AutomationJSONReply(this, reply_message).SendError(
969 StringPrintf("No download with an id of %d\n", id));
970 return;
971 }
972
973 if (action == "open") {
974 selected_item->AddObserver(
975 new AutomationProviderDownloadUpdatedObserver(
976 this, reply_message, true));
977 selected_item->OpenDownload();
978 } else if (action == "toggle_open_files_like_this") {
979 selected_item->OpenFilesBasedOnExtension(
980 !selected_item->ShouldOpenFileBasedOnExtension());
981 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
982 } else if (action == "remove") {
983 download_manager->AddObserver(
984 new AutomationProviderDownloadModelChangedObserver(
985 this, reply_message, download_manager));
986 selected_item->Remove(false);
987 } else if (action == "decline_dangerous_download") {
988 // This is the same as removing the file with delete_file=true.
989 download_manager->AddObserver(
990 new AutomationProviderDownloadModelChangedObserver(
991 this, reply_message, download_manager));
992 selected_item->Remove(true);
993 } else if (action == "save_dangerous_download") {
994 selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
995 this, reply_message, false));
996 selected_item->DangerousDownloadValidated();
997 } else if (action == "toggle_pause") {
998 selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
999 this, reply_message, false));
1000 // This will still return if download has already completed.
1001 selected_item->TogglePause();
1002 } else if (action == "cancel") {
1003 selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
1004 this, reply_message, false));
1005 selected_item->Cancel(true);
1006 } else {
1007 AutomationJSONReply(this, reply_message).SendError(
1008 StringPrintf("Invalid action '%s' given.", action.c_str()));
1009 }
1010}
1011
1012// See WaitForAlwaysOpenDownloadTypeToOpen() in chrome/test/pyautolib/pyauto.py
1013// for sample json input.
1014// Sample json output: {}
1015void AutomationProvider::WaitForAlwaysOpenDownloadTypeToOpen(
1016 Browser* browser, DictionaryValue* args, IPC::Message* reply_message) {
1017 int id;
1018
1019 if (!profile_->HasCreatedDownloadManager()) {
1020 AutomationJSONReply(this, reply_message).SendError("No download manager.");
1021 return;
1022 }
1023 if (!args->GetInteger("id", &id)) {
1024 AutomationJSONReply(this, reply_message).SendError(
1025 "Must include int id.");
1026 return;
1027 }
1028
1029 DownloadItem* selected_item = GetDownloadItemFromId(
1030 id, profile_->GetDownloadManager());
1031 if (!selected_item) {
1032 AutomationJSONReply(this, reply_message).SendError(
1033 StringPrintf("No download with an id of %d\n", id));
1034 return;
1035 }
1036
1037 if (selected_item->auto_opened()) {
1038 AutomationJSONReply(this, reply_message).SendSuccess(NULL);
1039 return;
1040 }
1041 // The observer will reply after the download is opened.
1042 selected_item->AddObserver(new AutomationProviderDownloadUpdatedObserver(
1043 this, reply_message, true));
1044}
1045
[email protected]24e2b102010-04-29 17:56:471046// Sample json input: { "command": "GetPrefsInfo" }
1047// Refer chrome/test/pyautolib/prefs_info.py for sample json output.
[email protected]53329582010-05-14 21:10:581048void AutomationProvider::GetPrefsInfo(Browser* browser,
1049 DictionaryValue* args,
[email protected]24e2b102010-04-29 17:56:471050 IPC::Message* reply_message) {
[email protected]24e2b102010-04-29 17:56:471051 const PrefService::PreferenceSet& prefs =
1052 profile_->GetPrefs()->preference_set();
1053 DictionaryValue* items = new DictionaryValue;
1054 for (PrefService::PreferenceSet::const_iterator it = prefs.begin();
1055 it != prefs.end(); ++it) {
1056 items->Set((*it)->name(), (*it)->GetValue()->DeepCopy());
1057 }
1058 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
[email protected]ff4c1d82010-08-04 16:58:121059 return_value->Set("prefs", items); // return_value owns items.
[email protected]7c983cc2010-07-16 11:33:341060 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
[email protected]24e2b102010-04-29 17:56:471061}
1062
1063// Sample json input: { "command": "SetPrefs", "path": path, "value": value }
[email protected]53329582010-05-14 21:10:581064void AutomationProvider::SetPrefs(Browser* browser,
1065 DictionaryValue* args,
[email protected]24e2b102010-04-29 17:56:471066 IPC::Message* reply_message) {
[email protected]57ecc4b2010-08-11 03:02:511067 std::string path;
[email protected]24e2b102010-04-29 17:56:471068 Value* val;
[email protected]7c983cc2010-07-16 11:33:341069 AutomationJSONReply reply(this, reply_message);
[email protected]57ecc4b2010-08-11 03:02:511070 if (args->GetString("path", &path) && args->Get("value", &val)) {
[email protected]24e2b102010-04-29 17:56:471071 PrefService* pref_service = profile_->GetPrefs();
1072 const PrefService::Preference* pref =
1073 pref_service->FindPreference(path.c_str());
1074 if (!pref) { // Not a registered pref.
[email protected]7c983cc2010-07-16 11:33:341075 reply.SendError("pref not registered.");
1076 return;
[email protected]24e2b102010-04-29 17:56:471077 } else if (pref->IsManaged()) { // Do not attempt to change a managed pref.
[email protected]7c983cc2010-07-16 11:33:341078 reply.SendError("pref is managed. cannot be changed.");
1079 return;
[email protected]24e2b102010-04-29 17:56:471080 } else { // Set the pref.
1081 pref_service->Set(path.c_str(), *val);
1082 }
1083 } else {
[email protected]7c983cc2010-07-16 11:33:341084 reply.SendError("no pref path or value given.");
1085 return;
[email protected]24e2b102010-04-29 17:56:471086 }
1087
[email protected]7c983cc2010-07-16 11:33:341088 reply.SendSuccess(NULL);
[email protected]24e2b102010-04-29 17:56:471089}
1090
[email protected]53329582010-05-14 21:10:581091// Sample json input: { "command": "GetOmniboxInfo" }
1092// Refer chrome/test/pyautolib/omnibox_info.py for sample json output.
1093void AutomationProvider::GetOmniboxInfo(Browser* browser,
1094 DictionaryValue* args,
1095 IPC::Message* reply_message) {
[email protected]53329582010-05-14 21:10:581096 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
1097
1098 LocationBar* loc_bar = browser->window()->GetLocationBar();
1099 AutocompleteEditView* edit_view = loc_bar->location_entry();
1100 AutocompleteEditModel* model = edit_view->model();
1101
1102 // Fill up matches.
1103 ListValue* matches = new ListValue;
1104 const AutocompleteResult& result = model->result();
1105 for (AutocompleteResult::const_iterator i = result.begin();
1106 i != result.end(); ++i) {
1107 const AutocompleteMatch& match = *i;
1108 DictionaryValue* item = new DictionaryValue; // owned by return_value
[email protected]ff4c1d82010-08-04 16:58:121109 item->SetString("type", AutocompleteMatch::TypeToString(match.type));
1110 item->SetBoolean("starred", match.starred);
1111 item->SetString("destination_url", match.destination_url.spec());
1112 item->SetString("contents", WideToUTF16Hack(match.contents));
1113 item->SetString("description", WideToUTF16Hack(match.description));
[email protected]53329582010-05-14 21:10:581114 matches->Append(item);
1115 }
[email protected]ff4c1d82010-08-04 16:58:121116 return_value->Set("matches", matches);
[email protected]53329582010-05-14 21:10:581117
1118 // Fill up other properties.
1119 DictionaryValue* properties = new DictionaryValue; // owned by return_value
[email protected]ff4c1d82010-08-04 16:58:121120 properties->SetBoolean("has_focus", model->has_focus());
1121 properties->SetBoolean("query_in_progress", model->query_in_progress());
1122 properties->SetString("keyword", WideToUTF16Hack(model->keyword()));
1123 properties->SetString("text", WideToUTF16Hack(edit_view->GetText()));
1124 return_value->Set("properties", properties);
[email protected]53329582010-05-14 21:10:581125
[email protected]7c983cc2010-07-16 11:33:341126 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
[email protected]53329582010-05-14 21:10:581127}
1128
1129// Sample json input: { "command": "SetOmniboxText",
1130// "text": "goog" }
1131void AutomationProvider::SetOmniboxText(Browser* browser,
1132 DictionaryValue* args,
1133 IPC::Message* reply_message) {
[email protected]a748ff62010-08-14 17:25:321134 string16 text;
[email protected]7c983cc2010-07-16 11:33:341135 AutomationJSONReply reply(this, reply_message);
[email protected]a748ff62010-08-14 17:25:321136 if (!args->GetString("text", &text)) {
[email protected]7c983cc2010-07-16 11:33:341137 reply.SendError("text missing");
1138 return;
[email protected]53329582010-05-14 21:10:581139 }
[email protected]7c983cc2010-07-16 11:33:341140 browser->FocusLocationBar();
1141 LocationBar* loc_bar = browser->window()->GetLocationBar();
1142 AutocompleteEditView* edit_view = loc_bar->location_entry();
1143 edit_view->model()->OnSetFocus(false);
[email protected]a748ff62010-08-14 17:25:321144 edit_view->SetUserText(UTF16ToWideHack(text));
[email protected]7c983cc2010-07-16 11:33:341145 reply.SendSuccess(NULL);
[email protected]53329582010-05-14 21:10:581146}
1147
1148// Sample json input: { "command": "OmniboxMovePopupSelection",
1149// "count": 1 }
1150// Negative count implies up, positive implies down. Count values will be
1151// capped by the size of the popup list.
1152void AutomationProvider::OmniboxMovePopupSelection(
1153 Browser* browser,
1154 DictionaryValue* args,
1155 IPC::Message* reply_message) {
[email protected]53329582010-05-14 21:10:581156 int count;
[email protected]7c983cc2010-07-16 11:33:341157 AutomationJSONReply reply(this, reply_message);
[email protected]ff4c1d82010-08-04 16:58:121158 if (!args->GetInteger("count", &count)) {
[email protected]7c983cc2010-07-16 11:33:341159 reply.SendError("count missing");
1160 return;
[email protected]53329582010-05-14 21:10:581161 }
[email protected]7c983cc2010-07-16 11:33:341162 LocationBar* loc_bar = browser->window()->GetLocationBar();
1163 AutocompleteEditModel* model = loc_bar->location_entry()->model();
1164 model->OnUpOrDownKeyPressed(count);
1165 reply.SendSuccess(NULL);
[email protected]53329582010-05-14 21:10:581166}
1167
1168// Sample json input: { "command": "OmniboxAcceptInput" }
1169void AutomationProvider::OmniboxAcceptInput(Browser* browser,
1170 DictionaryValue* args,
1171 IPC::Message* reply_message) {
[email protected]cb84d642010-06-10 00:56:281172 NavigationController& controller =
1173 browser->GetSelectedTabContents()->controller();
[email protected]c1654832010-05-17 23:22:121174 // Setup observer to wait until the selected item loads.
1175 NotificationObserver* observer =
[email protected]cb84d642010-06-10 00:56:281176 new OmniboxAcceptNotificationObserver(&controller, this, reply_message);
[email protected]c1654832010-05-17 23:22:121177 notification_observer_list_.AddObserver(observer);
[email protected]53329582010-05-14 21:10:581178
1179 browser->window()->GetLocationBar()->AcceptInput();
[email protected]53329582010-05-14 21:10:581180}
1181
[email protected]a3cd5022010-06-16 18:25:291182// Sample json input: { "command": "GetInitialLoadTimes" }
1183// Refer to InitialLoadObserver::GetTimingInformation() for sample output.
1184void AutomationProvider::GetInitialLoadTimes(
1185 Browser*,
1186 DictionaryValue*,
1187 IPC::Message* reply_message) {
1188 scoped_ptr<DictionaryValue> return_value(
1189 initial_load_observer_->GetTimingInformation());
[email protected]f6ff0df2010-07-11 22:41:431190
1191 std::string json_return;
1192 base::JSONWriter::Write(return_value.get(), false, &json_return);
1193 AutomationMsg_SendJSONRequest::WriteReplyParams(
1194 reply_message, json_return, true);
1195 Send(reply_message);
[email protected]a3cd5022010-06-16 18:25:291196}
1197
[email protected]f7d48012010-05-06 08:17:051198// Sample json input: { "command": "GetPluginsInfo" }
1199// Refer chrome/test/pyautolib/plugins_info.py for sample json output.
[email protected]53329582010-05-14 21:10:581200void AutomationProvider::GetPluginsInfo(Browser* browser,
1201 DictionaryValue* args,
[email protected]f7d48012010-05-06 08:17:051202 IPC::Message* reply_message) {
[email protected]f7d48012010-05-06 08:17:051203 std::vector<WebPluginInfo> plugins;
1204 NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins);
1205 ListValue* items = new ListValue;
1206 for (std::vector<WebPluginInfo>::const_iterator it = plugins.begin();
1207 it != plugins.end();
1208 ++it) {
1209 DictionaryValue* item = new DictionaryValue;
[email protected]ff4c1d82010-08-04 16:58:121210 item->SetString("name", it->name);
1211 item->SetString("path", it->path.value());
1212 item->SetString("version", it->version);
1213 item->SetString("desc", it->desc);
1214 item->SetBoolean("enabled", it->enabled);
[email protected]f7d48012010-05-06 08:17:051215 // Add info about mime types.
1216 ListValue* mime_types = new ListValue();
1217 for (std::vector<WebPluginMimeType>::const_iterator type_it =
1218 it->mime_types.begin();
1219 type_it != it->mime_types.end();
1220 ++type_it) {
1221 DictionaryValue* mime_type = new DictionaryValue();
[email protected]ff4c1d82010-08-04 16:58:121222 mime_type->SetString("mimeType", type_it->mime_type);
1223 mime_type->SetString("description", type_it->description);
[email protected]f7d48012010-05-06 08:17:051224
1225 ListValue* file_extensions = new ListValue();
1226 for (std::vector<std::string>::const_iterator ext_it =
1227 type_it->file_extensions.begin();
1228 ext_it != type_it->file_extensions.end();
1229 ++ext_it) {
1230 file_extensions->Append(new StringValue(*ext_it));
1231 }
[email protected]ff4c1d82010-08-04 16:58:121232 mime_type->Set("fileExtensions", file_extensions);
[email protected]f7d48012010-05-06 08:17:051233
1234 mime_types->Append(mime_type);
1235 }
[email protected]ff4c1d82010-08-04 16:58:121236 item->Set("mimeTypes", mime_types);
[email protected]f7d48012010-05-06 08:17:051237 items->Append(item);
1238 }
1239 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
[email protected]ff4c1d82010-08-04 16:58:121240 return_value->Set("plugins", items); // return_value owns items.
[email protected]f7d48012010-05-06 08:17:051241
[email protected]7c983cc2010-07-16 11:33:341242 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
[email protected]f7d48012010-05-06 08:17:051243}
1244
1245// Sample json input:
1246// { "command": "EnablePlugin",
1247// "path": "/Library/Internet Plug-Ins/Flash Player.plugin" }
[email protected]53329582010-05-14 21:10:581248void AutomationProvider::EnablePlugin(Browser* browser,
1249 DictionaryValue* args,
[email protected]f7d48012010-05-06 08:17:051250 IPC::Message* reply_message) {
[email protected]f7d48012010-05-06 08:17:051251 FilePath::StringType path;
[email protected]7c983cc2010-07-16 11:33:341252 AutomationJSONReply reply(this, reply_message);
[email protected]ff4c1d82010-08-04 16:58:121253 if (!args->GetString("path", &path)) {
[email protected]7c983cc2010-07-16 11:33:341254 reply.SendError("path not specified.");
1255 return;
[email protected]f6ff0df2010-07-11 22:41:431256 } else if (!NPAPI::PluginList::Singleton()->EnablePlugin(FilePath(path))) {
[email protected]7c983cc2010-07-16 11:33:341257 reply.SendError(StringPrintf("Could not enable plugin for path %s.",
1258 path.c_str()));
1259 return;
[email protected]f6ff0df2010-07-11 22:41:431260 }
[email protected]7c983cc2010-07-16 11:33:341261 reply.SendSuccess(NULL);
[email protected]f7d48012010-05-06 08:17:051262}
1263
1264// Sample json input:
1265// { "command": "DisablePlugin",
1266// "path": "/Library/Internet Plug-Ins/Flash Player.plugin" }
[email protected]53329582010-05-14 21:10:581267void AutomationProvider::DisablePlugin(Browser* browser,
1268 DictionaryValue* args,
1269 IPC::Message* reply_message) {
[email protected]f7d48012010-05-06 08:17:051270 FilePath::StringType path;
[email protected]7c983cc2010-07-16 11:33:341271 AutomationJSONReply reply(this, reply_message);
[email protected]ff4c1d82010-08-04 16:58:121272 if (!args->GetString("path", &path)) {
[email protected]7c983cc2010-07-16 11:33:341273 reply.SendError("path not specified.");
1274 return;
[email protected]f6ff0df2010-07-11 22:41:431275 } else if (!NPAPI::PluginList::Singleton()->DisablePlugin(FilePath(path))) {
[email protected]7c983cc2010-07-16 11:33:341276 reply.SendError(StringPrintf("Could not disable plugin for path %s.",
1277 path.c_str()));
1278 return;
[email protected]f6ff0df2010-07-11 22:41:431279 }
[email protected]7c983cc2010-07-16 11:33:341280 reply.SendSuccess(NULL);
[email protected]f7d48012010-05-06 08:17:051281}
1282
[email protected]7060bb292010-06-24 00:52:491283// Sample json input:
1284// { "command": "SaveTabContents",
1285// "tab_index": 0,
1286// "filename": <a full pathname> }
1287// Sample json output:
1288// {}
1289void AutomationProvider::SaveTabContents(Browser* browser,
1290 DictionaryValue* args,
1291 IPC::Message* reply_message) {
[email protected]7060bb292010-06-24 00:52:491292 int tab_index = 0;
1293 FilePath::StringType filename;
1294 FilePath::StringType parent_directory;
1295 TabContents* tab_contents = NULL;
1296
[email protected]ff4c1d82010-08-04 16:58:121297 if (!args->GetInteger("tab_index", &tab_index) ||
1298 !args->GetString("filename", &filename)) {
[email protected]26adfd312010-07-20 01:04:461299 AutomationJSONReply(this, reply_message).SendError(
1300 "tab_index or filename param missing");
[email protected]7c983cc2010-07-16 11:33:341301 return;
[email protected]7060bb292010-06-24 00:52:491302 } else {
1303 tab_contents = browser->GetTabContentsAt(tab_index);
1304 if (!tab_contents) {
[email protected]26adfd312010-07-20 01:04:461305 AutomationJSONReply(this, reply_message).SendError(
1306 "no tab at tab_index");
[email protected]7060bb292010-06-24 00:52:491307 return;
1308 }
1309 }
[email protected]7c983cc2010-07-16 11:33:341310 // We're doing a SAVE_AS_ONLY_HTML so the the directory path isn't
1311 // used. Nevertheless, SavePackage requires it be valid. Sigh.
1312 parent_directory = FilePath(filename).DirName().value();
1313 if (!tab_contents->SavePage(FilePath(filename), FilePath(parent_directory),
1314 SavePackage::SAVE_AS_ONLY_HTML)) {
[email protected]26adfd312010-07-20 01:04:461315 AutomationJSONReply(this, reply_message).SendError(
1316 "Could not initiate SavePage");
[email protected]7c983cc2010-07-16 11:33:341317 return;
1318 }
1319 // The observer will delete itself when done.
1320 new SavePackageNotificationObserver(tab_contents->save_package(),
1321 this, reply_message);
[email protected]7060bb292010-06-24 00:52:491322}
1323
[email protected]c5aa5322010-07-15 19:00:071324// Refer to ImportSettings() in chrome/test/pyautolib/pyauto.py for sample
1325// json input.
1326// Sample json output: "{}"
1327void AutomationProvider::ImportSettings(Browser* browser,
1328 DictionaryValue* args,
1329 IPC::Message* reply_message) {
[email protected]c5aa5322010-07-15 19:00:071330 // Map from the json string passed over to the import item masks.
1331 std::map<std::string, ImportItem> string_to_import_item;
1332 string_to_import_item["HISTORY"] = importer::HISTORY;
1333 string_to_import_item["FAVORITES"] = importer::FAVORITES;
1334 string_to_import_item["COOKIES"] = importer::COOKIES;
1335 string_to_import_item["PASSWORDS"] = importer::PASSWORDS;
1336 string_to_import_item["SEARCH_ENGINES"] = importer::SEARCH_ENGINES;
1337 string_to_import_item["HOME_PAGE"] = importer::HOME_PAGE;
1338 string_to_import_item["ALL"] = importer::ALL;
1339
[email protected]a748ff62010-08-14 17:25:321340 string16 browser_name;
[email protected]c5aa5322010-07-15 19:00:071341 int import_items = 0;
1342 ListValue* import_items_list = NULL;
1343 bool first_run;
1344
[email protected]a748ff62010-08-14 17:25:321345 if (!args->GetString("import_from", &browser_name) ||
[email protected]ff4c1d82010-08-04 16:58:121346 !args->GetBoolean("first_run", &first_run) ||
1347 !args->GetList("import_items", &import_items_list)) {
[email protected]7c983cc2010-07-16 11:33:341348 AutomationJSONReply(this, reply_message).SendError(
1349 "Incorrect type for one or more of the arguments.");
[email protected]c5aa5322010-07-15 19:00:071350 return;
1351 }
1352
1353 int num_items = import_items_list->GetSize();
1354 for (int i = 0; i < num_items; i++) {
1355 std::string item;
1356 import_items_list->GetString(i, &item);
1357 // If the provided string is not part of the map, error out.
1358 if (!ContainsKey(string_to_import_item, item)) {
[email protected]7c983cc2010-07-16 11:33:341359 AutomationJSONReply(this, reply_message).SendError(
1360 "Invalid item string found in import_items.");
[email protected]c5aa5322010-07-15 19:00:071361 return;
1362 }
1363 import_items |= string_to_import_item[item];
1364 }
1365
1366 ImporterHost* importer_host = new ImporterHost();
1367 // Get the correct ProfileInfo based on the browser they user provided.
1368 importer::ProfileInfo profile_info;
1369 int num_browsers = importer_host->GetAvailableProfileCount();
1370 int i = 0;
1371 for ( ; i < num_browsers; i++) {
[email protected]a748ff62010-08-14 17:25:321372 string16 name = WideToUTF16Hack(importer_host->GetSourceProfileNameAt(i));
[email protected]c5aa5322010-07-15 19:00:071373 if (name == browser_name) {
1374 profile_info = importer_host->GetSourceProfileInfoAt(i);
1375 break;
1376 }
1377 }
1378 // If we made it to the end of the loop, then the input was bad.
1379 if (i == num_browsers) {
[email protected]7c983cc2010-07-16 11:33:341380 AutomationJSONReply(this, reply_message).SendError(
1381 "Invalid browser name string found.");
[email protected]c5aa5322010-07-15 19:00:071382 return;
1383 }
1384
1385 Profile* profile = browser->profile();
1386
1387 importer_host->SetObserver(
1388 new AutomationProviderImportSettingsObserver(this, reply_message));
1389 importer_host->StartImportSettings(profile_info, profile, import_items,
1390 new ProfileWriter(profile), first_run);
1391}
1392
[email protected]95222282010-07-26 17:43:021393namespace {
1394
1395// Translates a dictionary password to a PasswordForm struct.
1396webkit_glue::PasswordForm GetPasswordFormFromDict(
1397 const DictionaryValue& password_dict) {
1398
1399 // If the time is specified, change time to the specified time.
1400 base::Time time = base::Time::Now();
1401 int it;
1402 double dt;
[email protected]ff4c1d82010-08-04 16:58:121403 if (password_dict.GetInteger("time", &it))
[email protected]95222282010-07-26 17:43:021404 time = base::Time::FromTimeT(it);
[email protected]ff4c1d82010-08-04 16:58:121405 else if (password_dict.GetReal("time", &dt))
[email protected]95222282010-07-26 17:43:021406 time = base::Time::FromDoubleT(dt);
1407
1408 std::string signon_realm;
1409 string16 username_value;
1410 string16 password_value;
1411 string16 origin_url_text;
1412 string16 username_element;
1413 string16 password_element;
1414 string16 submit_element;
1415 string16 action_target_text;
1416 bool blacklist = false;
1417 string16 old_password_element;
1418 string16 old_password_value;
1419
1420 // We don't care if any of these fail - they are either optional or checked
1421 // before this function is called.
[email protected]ff4c1d82010-08-04 16:58:121422 password_dict.GetString("signon_realm", &signon_realm);
[email protected]698f7f42010-08-04 19:35:331423 password_dict.GetString("username_value", &username_value);
1424 password_dict.GetString("password_value", &password_value);
1425 password_dict.GetString("origin_url", &origin_url_text);
1426 password_dict.GetString("username_element", &username_element);
1427 password_dict.GetString("password_element", &password_element);
1428 password_dict.GetString("submit_element", &submit_element);
1429 password_dict.GetString("action_target", &action_target_text);
[email protected]ff4c1d82010-08-04 16:58:121430 password_dict.GetBoolean("blacklist", &blacklist);
[email protected]95222282010-07-26 17:43:021431
1432 GURL origin_gurl(origin_url_text);
1433 GURL action_target(action_target_text);
1434
1435 webkit_glue::PasswordForm password_form;
1436 password_form.signon_realm = signon_realm;
1437 password_form.username_value = username_value;
1438 password_form.password_value = password_value;
1439 password_form.origin = origin_gurl;
1440 password_form.username_element = username_element;
1441 password_form.password_element = password_element;
1442 password_form.submit_element = submit_element;
1443 password_form.action = action_target;
1444 password_form.blacklisted_by_user = blacklist;
1445 password_form.date_created = time;
1446
1447 return password_form;
1448}
1449
1450} // namespace
1451
[email protected]5bcfe1672010-07-16 20:51:571452// See AddSavedPassword() in chrome/test/functional/pyauto.py for sample json
1453// input.
1454// Sample json output: { "password_added": true }
1455void AutomationProvider::AddSavedPassword(Browser* browser,
1456 DictionaryValue* args,
1457 IPC::Message* reply_message) {
[email protected]5bcfe1672010-07-16 20:51:571458 AutomationJSONReply reply(this, reply_message);
[email protected]95222282010-07-26 17:43:021459 DictionaryValue* password_dict = NULL;
[email protected]5bcfe1672010-07-16 20:51:571460
[email protected]ff4c1d82010-08-04 16:58:121461 if (!args->GetDictionary("password", &password_dict)) {
[email protected]95222282010-07-26 17:43:021462 reply.SendError("Password must be a dictionary.");
[email protected]5bcfe1672010-07-16 20:51:571463 return;
1464 }
1465
[email protected]95222282010-07-26 17:43:021466 // The signon realm is effectively the primary key and must be included.
1467 // Check here before calling GetPasswordFormFromDict.
[email protected]ff4c1d82010-08-04 16:58:121468 if (!password_dict->HasKey("signon_realm")) {
[email protected]95222282010-07-26 17:43:021469 reply.SendError("Password must include signon_realm.");
1470 return;
1471 }
1472 webkit_glue::PasswordForm new_password =
1473 GetPasswordFormFromDict(*password_dict);
[email protected]5bcfe1672010-07-16 20:51:571474
1475 Profile* profile = browser->profile();
1476 // Use IMPLICIT_ACCESS since new passwords aren't added off the record.
1477 PasswordStore* password_store =
1478 profile->GetPasswordStore(Profile::IMPLICIT_ACCESS);
1479
1480 // Set the return based on whether setting the password succeeded.
1481 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
1482
1483 // It will be null if it's accessed in an incognito window.
1484 if (password_store != NULL) {
1485 password_store->AddLogin(new_password);
[email protected]ff4c1d82010-08-04 16:58:121486 return_value->SetBoolean("password_added", true);
[email protected]5bcfe1672010-07-16 20:51:571487 } else {
[email protected]ff4c1d82010-08-04 16:58:121488 return_value->SetBoolean("password_added", false);
[email protected]5bcfe1672010-07-16 20:51:571489 }
1490
1491 reply.SendSuccess(return_value.get());
1492}
1493
[email protected]95222282010-07-26 17:43:021494// See RemoveSavedPassword() in chrome/test/functional/pyauto.py for sample
1495// json input.
1496// Sample json output: {}
1497void AutomationProvider::RemoveSavedPassword(Browser* browser,
1498 DictionaryValue* args,
1499 IPC::Message* reply_message) {
1500 AutomationJSONReply reply(this, reply_message);
1501 DictionaryValue* password_dict = NULL;
1502
[email protected]ff4c1d82010-08-04 16:58:121503 if (!args->GetDictionary("password", &password_dict)) {
[email protected]95222282010-07-26 17:43:021504 reply.SendError("Password must be a dictionary.");
1505 return;
1506 }
1507
1508 // The signon realm is effectively the primary key and must be included.
1509 // Check here before calling GetPasswordFormFromDict.
[email protected]ff4c1d82010-08-04 16:58:121510 if (!password_dict->HasKey("signon_realm")) {
[email protected]95222282010-07-26 17:43:021511 reply.SendError("Password must include signon_realm.");
1512 return;
1513 }
1514 webkit_glue::PasswordForm to_remove =
1515 GetPasswordFormFromDict(*password_dict);
1516
1517 Profile* profile = browser->profile();
1518 // Use EXPLICIT_ACCESS since passwords can be removed off the record.
1519 PasswordStore* password_store =
1520 profile->GetPasswordStore(Profile::EXPLICIT_ACCESS);
1521
1522 password_store->RemoveLogin(to_remove);
1523 reply.SendSuccess(NULL);
1524}
1525
[email protected]5bcfe1672010-07-16 20:51:571526// Sample json input: { "command": "GetSavedPasswords" }
1527// Refer to GetSavedPasswords() in chrome/test/pyautolib/pyauto.py for sample
1528// json output.
1529void AutomationProvider::GetSavedPasswords(Browser* browser,
1530 DictionaryValue* args,
1531 IPC::Message* reply_message) {
1532 Profile* profile = browser->profile();
1533 // Use EXPLICIT_ACCESS since saved passwords can be retreived off the record.
1534 PasswordStore* password_store =
1535 profile->GetPasswordStore(Profile::EXPLICIT_ACCESS);
1536 password_store->GetAutofillableLogins(
1537 new AutomationProviderGetPasswordsObserver(this, reply_message));
1538 // Observer deletes itself after returning.
1539}
1540
[email protected]a0fc50d72010-07-14 21:14:191541// Refer to ClearBrowsingData() in chrome/test/pyautolib/pyauto.py for sample
1542// json input.
1543// Sample json output: {}
1544void AutomationProvider::ClearBrowsingData(Browser* browser,
1545 DictionaryValue* args,
1546 IPC::Message* reply_message) {
[email protected]a0fc50d72010-07-14 21:14:191547 std::map<std::string, BrowsingDataRemover::TimePeriod> string_to_time_period;
1548 string_to_time_period["LAST_HOUR"] = BrowsingDataRemover::LAST_HOUR;
1549 string_to_time_period["LAST_DAY"] = BrowsingDataRemover::LAST_DAY;
1550 string_to_time_period["LAST_WEEK"] = BrowsingDataRemover::LAST_WEEK;
1551 string_to_time_period["FOUR_WEEKS"] = BrowsingDataRemover::FOUR_WEEKS;
1552 string_to_time_period["EVERYTHING"] = BrowsingDataRemover::EVERYTHING;
1553
1554 std::map<std::string, int> string_to_mask_value;
1555 string_to_mask_value["HISTORY"] = BrowsingDataRemover::REMOVE_HISTORY;
1556 string_to_mask_value["DOWNLOADS"] = BrowsingDataRemover::REMOVE_DOWNLOADS;
1557 string_to_mask_value["COOKIES"] = BrowsingDataRemover::REMOVE_COOKIES;
1558 string_to_mask_value["PASSWORDS"] = BrowsingDataRemover::REMOVE_PASSWORDS;
1559 string_to_mask_value["FORM_DATA"] = BrowsingDataRemover::REMOVE_FORM_DATA;
1560 string_to_mask_value["CACHE"] = BrowsingDataRemover::REMOVE_CACHE;
1561
1562 std::string time_period;
1563 ListValue* to_remove;
[email protected]ff4c1d82010-08-04 16:58:121564 if (!args->GetString("time_period", &time_period) ||
1565 !args->GetList("to_remove", &to_remove)) {
[email protected]7c983cc2010-07-16 11:33:341566 AutomationJSONReply(this, reply_message).SendError(
1567 "time_period must be a string and to_remove a list.");
[email protected]a0fc50d72010-07-14 21:14:191568 return;
1569 }
1570
1571 int remove_mask = 0;
1572 int num_removals = to_remove->GetSize();
1573 for (int i = 0; i < num_removals; i++) {
1574 std::string removal;
1575 to_remove->GetString(i, &removal);
1576 // If the provided string is not part of the map, then error out.
1577 if (!ContainsKey(string_to_mask_value, removal)) {
[email protected]7c983cc2010-07-16 11:33:341578 AutomationJSONReply(this, reply_message).SendError(
1579 "Invalid browsing data string found in to_remove.");
[email protected]a0fc50d72010-07-14 21:14:191580 return;
1581 }
1582 remove_mask |= string_to_mask_value[removal];
1583 }
1584
1585 if (!ContainsKey(string_to_time_period, time_period)) {
[email protected]7c983cc2010-07-16 11:33:341586 AutomationJSONReply(this, reply_message).SendError(
1587 "Invalid string for time_period.");
[email protected]a0fc50d72010-07-14 21:14:191588 return;
1589 }
1590
1591 BrowsingDataRemover* remover = new BrowsingDataRemover(
1592 profile(), string_to_time_period[time_period], base::Time());
1593
1594 remover->AddObserver(
1595 new AutomationProviderBrowsingDataObserver(this, reply_message));
1596 remover->Remove(remove_mask);
1597 // BrowsingDataRemover deletes itself using DeleteTask.
1598 // The observer also deletes itself after sending the reply.
1599}
1600
[email protected]3dda5b02010-07-27 16:35:421601namespace {
1602
1603 // Get the TabContents from a dictionary of arguments.
1604 TabContents* GetTabContentsFromDict(const Browser* browser,
1605 const DictionaryValue* args,
1606 std::string* error_message) {
1607 int tab_index;
[email protected]ff4c1d82010-08-04 16:58:121608 if (!args->GetInteger("tab_index", &tab_index)) {
[email protected]3dda5b02010-07-27 16:35:421609 *error_message = "Must include tab_index.";
1610 return NULL;
1611 }
1612
1613 TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
1614 if (!tab_contents) {
1615 *error_message = StringPrintf("No tab at index %d.", tab_index);
1616 return NULL;
1617 }
1618 return tab_contents;
1619 }
1620
1621 // Get the TranslateInfoBarDelegate from TabContents.
1622 TranslateInfoBarDelegate* GetTranslateInfoBarDelegate(
1623 TabContents* tab_contents) {
1624 for (int i = 0; i < tab_contents->infobar_delegate_count(); i++) {
1625 InfoBarDelegate* infobar = tab_contents->GetInfoBarDelegateAt(i);
1626 if (infobar->AsTranslateInfoBarDelegate())
1627 return infobar->AsTranslateInfoBarDelegate();
1628 }
1629 // No translate infobar.
1630 return NULL;
1631 }
1632
1633} // namespace
1634
1635// See GetTranslateInfo() in chrome/test/pyautolib/pyauto.py for sample json
1636// input and output.
1637void AutomationProvider::GetTranslateInfo(Browser* browser,
1638 DictionaryValue* args,
1639 IPC::Message* reply_message) {
1640 std::string error_message;
1641 TabContents* tab_contents = GetTabContentsFromDict(browser, args,
1642 &error_message);
1643 if (!tab_contents) {
1644 AutomationJSONReply(this, reply_message).SendError(error_message);
1645 return;
1646 }
1647
1648 // Get the translate bar if there is one and pass it to the observer.
1649 // The observer will check for null and populate the information accordingly.
1650 TranslateInfoBarDelegate* translate_bar =
1651 GetTranslateInfoBarDelegate(tab_contents);
1652
1653 TabLanguageDeterminedObserver* observer = new TabLanguageDeterminedObserver(
1654 this, reply_message, tab_contents, translate_bar);
1655 // If the language for the page hasn't been loaded yet, then just make
1656 // the observer, otherwise call observe directly.
1657 std::string language = tab_contents->language_state().original_language();
1658 if (!language.empty()) {
1659 observer->Observe(NotificationType::TAB_LANGUAGE_DETERMINED,
1660 Source<TabContents>(tab_contents),
1661 Details<std::string>(&language));
1662 }
1663}
1664
1665// See SelectTranslateOption() in chrome/test/pyautolib/pyauto.py for sample
1666// json input.
1667// Sample json output: {}
1668void AutomationProvider::SelectTranslateOption(Browser* browser,
1669 DictionaryValue* args,
1670 IPC::Message* reply_message) {
1671 std::string option;
1672 std::string error_message;
1673 TabContents* tab_contents = GetTabContentsFromDict(browser, args,
1674 &error_message);
1675 if (!tab_contents) {
1676 AutomationJSONReply(this, reply_message).SendError(error_message);
1677 return;
1678 }
1679
1680 TranslateInfoBarDelegate* translate_bar =
1681 GetTranslateInfoBarDelegate(tab_contents);
1682 if (!translate_bar) {
1683 AutomationJSONReply(this, reply_message)
1684 .SendError("There is no translate bar open.");
1685 return;
1686 }
1687
[email protected]ff4c1d82010-08-04 16:58:121688 if (!args->GetString("option", &option)) {
[email protected]3dda5b02010-07-27 16:35:421689 AutomationJSONReply(this, reply_message).SendError("Must include option");
1690 return;
1691 }
1692
1693 if (option == "translate_page") {
1694 // Make a new notification observer which will send the reply.
1695 new PageTranslatedObserver(this, reply_message, tab_contents);
1696 translate_bar->Translate();
1697 return;
[email protected]da1913e2010-08-04 23:50:151698 } else if (option == "set_target_language") {
1699 string16 target_language;
1700 if (!args->GetString("target_language", &target_language)) {
1701 AutomationJSONReply(this, reply_message).
1702 SendError("Must include target_language string.");
1703 return;
1704 }
1705 // Get the target language index based off of the language name.
1706 int target_language_index = -1;
1707 for (int i = 0; i < translate_bar->GetLanguageCount(); i++) {
1708 if (translate_bar->GetLanguageDisplayableNameAt(i) == target_language) {
1709 target_language_index = i;
1710 break;
1711 }
1712 }
1713 if (target_language_index == -1) {
1714 AutomationJSONReply(this, reply_message)
1715 .SendError("Invalid target language string.");
1716 return;
1717 }
1718 // If the page has already been translated it will be translated again to
1719 // the new language. The observer will wait until the page has been
1720 // translated to reply.
1721 if (translate_bar->type() == TranslateInfoBarDelegate::AFTER_TRANSLATE) {
1722 new PageTranslatedObserver(this, reply_message, tab_contents);
1723 translate_bar->SetTargetLanguage(target_language_index);
1724 return;
1725 }
1726 // Otherwise just send the reply back immediately.
1727 translate_bar->SetTargetLanguage(target_language_index);
1728 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
1729 return_value->SetBoolean("translation_success", true);
1730 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
1731 return;
[email protected]4a47d76122010-08-10 18:11:161732 } else if (option == "click_always_translate_lang_button") {
1733 if (!translate_bar->ShouldShowAlwaysTranslateButton()) {
1734 AutomationJSONReply(this, reply_message)
1735 .SendError("Always translate button not showing.");
1736 return;
1737 }
1738 // Clicking 'Always Translate' triggers a translation. The observer will
1739 // wait until the translation is complete before sending the reply.
1740 new PageTranslatedObserver(this, reply_message, tab_contents);
1741 translate_bar->AlwaysTranslatePageLanguage();
1742 return;
[email protected]3dda5b02010-07-27 16:35:421743 }
1744
1745 AutomationJSONReply reply(this, reply_message);
1746 if (option == "never_translate_language") {
1747 if (translate_bar->IsLanguageBlacklisted()) {
1748 reply.SendError("The language was already blacklisted.");
1749 return;
1750 }
1751 translate_bar->ToggleLanguageBlacklist();
1752 reply.SendSuccess(NULL);
1753 } else if (option == "never_translate_site") {
1754 if (translate_bar->IsSiteBlacklisted()) {
1755 reply.SendError("The site was already blacklisted.");
1756 return;
1757 }
1758 translate_bar->ToggleSiteBlacklist();
1759 reply.SendSuccess(NULL);
1760 } else if (option == "toggle_always_translate") {
1761 translate_bar->ToggleAlwaysTranslate();
1762 reply.SendSuccess(NULL);
1763 } else if (option == "revert_translation") {
1764 translate_bar->RevertTranslation();
1765 reply.SendSuccess(NULL);
[email protected]4a47d76122010-08-10 18:11:161766 } else if (option == "click_never_translate_lang_button") {
1767 if (!translate_bar->ShouldShowNeverTranslateButton()) {
1768 reply.SendError("Always translate button not showing.");
1769 return;
1770 }
1771 translate_bar->NeverTranslatePageLanguage();
1772 reply.SendSuccess(NULL);
1773 } else if (option == "decline_translation") {
1774 // This is the function called when an infobar is dismissed or when the
1775 // user clicks the 'Nope' translate button.
1776 translate_bar->TranslationDeclined();
[email protected]a9add882010-08-16 20:37:481777 tab_contents->RemoveInfoBar(translate_bar);
[email protected]4a47d76122010-08-10 18:11:161778 reply.SendSuccess(NULL);
[email protected]3dda5b02010-07-27 16:35:421779 } else {
1780 reply.SendError("Invalid string found for option.");
1781 }
1782}
1783
[email protected]f89ee5d2010-08-02 16:39:121784// See WaitUntilTranslateComplete() in chrome/test/pyautolib/pyauto.py for
1785// sample json input and output.
1786void AutomationProvider::WaitUntilTranslateComplete(
1787 Browser* browser, DictionaryValue* args, IPC::Message* reply_message) {
1788 std::string error_message;
1789 TabContents* tab_contents = GetTabContentsFromDict(browser, args,
1790 &error_message);
1791 if (!tab_contents) {
1792 AutomationJSONReply(this, reply_message).SendError(error_message);
1793 return;
1794 }
1795
[email protected]f89ee5d2010-08-02 16:39:121796 TranslateInfoBarDelegate* translate_bar =
1797 GetTranslateInfoBarDelegate(tab_contents);
1798 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
[email protected]14a0aac2010-08-05 15:52:591799
[email protected]f89ee5d2010-08-02 16:39:121800 if (!translate_bar) {
[email protected]57ecc4b2010-08-11 03:02:511801 return_value->SetBoolean("translation_success", false);
[email protected]14a0aac2010-08-05 15:52:591802 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
1803 return;
[email protected]f89ee5d2010-08-02 16:39:121804 }
[email protected]14a0aac2010-08-05 15:52:591805
1806 // If the translation is still pending, the observer will wait
1807 // for it to finish and then reply.
1808 if (translate_bar->type() == TranslateInfoBarDelegate::TRANSLATING) {
1809 new PageTranslatedObserver(this, reply_message, tab_contents);
1810 return;
1811 }
1812
1813 // Otherwise send back the success or failure of the attempted translation.
1814 return_value->SetBoolean(
[email protected]57ecc4b2010-08-11 03:02:511815 "translation_success",
[email protected]14a0aac2010-08-05 15:52:591816 translate_bar->type() == TranslateInfoBarDelegate::AFTER_TRANSLATE);
1817 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
[email protected]f89ee5d2010-08-02 16:39:121818}
1819
[email protected]4d1929f12010-07-10 00:09:031820// Sample json input: { "command": "GetThemeInfo" }
1821// Refer GetThemeInfo() in chrome/test/pyautolib/pyauto.py for sample output.
1822void AutomationProvider::GetThemeInfo(Browser* browser,
1823 DictionaryValue* args,
1824 IPC::Message* reply_message) {
1825 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
1826 Extension* theme = browser->profile()->GetTheme();
1827 if (theme) {
[email protected]ff4c1d82010-08-04 16:58:121828 return_value->SetString("name", theme->name());
1829 return_value->Set("images", theme->GetThemeImages()->DeepCopy());
1830 return_value->Set("colors", theme->GetThemeColors()->DeepCopy());
1831 return_value->Set("tints", theme->GetThemeTints()->DeepCopy());
[email protected]4d1929f12010-07-10 00:09:031832 }
[email protected]7c983cc2010-07-16 11:33:341833 AutomationJSONReply(this, reply_message).SendSuccess(return_value.get());
[email protected]4d1929f12010-07-10 00:09:031834}
1835
[email protected]32a69cf2010-08-03 16:27:011836// Sample json input: { "command": "GetExtensionsInfo" }
1837// See GetExtensionsInfo() in chrome/test/pyautolib/pyauto.py for sample json
1838// output.
1839void AutomationProvider::GetExtensionsInfo(Browser* browser,
1840 DictionaryValue* args,
1841 IPC::Message* reply_message) {
1842 AutomationJSONReply reply(this, reply_message);
1843 ExtensionsService* service = profile()->GetExtensionsService();
1844 if (!service) {
1845 reply.SendError("No extensions service.");
1846 }
1847 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
1848 ListValue* extensions_values = new ListValue;
1849 const ExtensionList* extensions = service->extensions();
1850 for (ExtensionList::const_iterator it = extensions->begin();
1851 it != extensions->end(); ++it) {
1852 const Extension* extension = *it;
1853 DictionaryValue* extension_value = new DictionaryValue;
[email protected]ff4c1d82010-08-04 16:58:121854 extension_value->SetString("id", extension->id());
1855 extension_value->SetString("version", extension->VersionString());
1856 extension_value->SetString("name", extension->name());
1857 extension_value->SetString("public_key", extension->public_key());
1858 extension_value->SetString("description", extension->description());
1859 extension_value->SetString("background_url",
[email protected]32a69cf2010-08-03 16:27:011860 extension->background_url().spec());
[email protected]ff4c1d82010-08-04 16:58:121861 extension_value->SetString("options_url",
[email protected]32a69cf2010-08-03 16:27:011862 extension->options_url().spec());
1863 extensions_values->Append(extension_value);
1864 }
[email protected]ff4c1d82010-08-04 16:58:121865 return_value->Set("extensions", extensions_values);
[email protected]32a69cf2010-08-03 16:27:011866 reply.SendSuccess(return_value.get());
1867}
1868
1869// See UninstallExtensionById() in chrome/test/pyautolib/pyauto.py for sample
1870// json input.
1871// Sample json output: {}
1872void AutomationProvider::UninstallExtensionById(Browser* browser,
1873 DictionaryValue* args,
1874 IPC::Message* reply_message) {
1875 AutomationJSONReply reply(this, reply_message);
1876 std::string id;
[email protected]ff4c1d82010-08-04 16:58:121877 if (!args->GetString("id", &id)) {
[email protected]32a69cf2010-08-03 16:27:011878 reply.SendError("Must include string id.");
1879 return;
1880 }
1881 ExtensionsService* service = profile()->GetExtensionsService();
1882 if (!service) {
1883 reply.SendError("No extensions service.");
1884 return;
1885 }
1886 ExtensionUnloadNotificationObserver observer;
1887 service->UninstallExtension(id, false);
1888 reply.SendSuccess(NULL);
1889}
1890
[email protected]55846ad842010-07-09 18:22:561891// Sample json input:
1892// { "command": "GetAutoFillProfile" }
1893// Refer to GetAutoFillProfile() in chrome/test/pyautolib/pyauto.py for sample
1894// json output.
1895void AutomationProvider::GetAutoFillProfile(Browser* browser,
1896 DictionaryValue* args,
1897 IPC::Message* reply_message) {
[email protected]55846ad842010-07-09 18:22:561898 // Get the AutoFillProfiles currently in the database.
1899 int tab_index = 0;
[email protected]ff4c1d82010-08-04 16:58:121900 args->GetInteger("tab_index", &tab_index);
[email protected]55846ad842010-07-09 18:22:561901 TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
[email protected]7c983cc2010-07-16 11:33:341902 AutomationJSONReply reply(this, reply_message);
[email protected]55846ad842010-07-09 18:22:561903
1904 if (tab_contents) {
1905 PersonalDataManager* pdm = tab_contents->profile()->GetOriginalProfile()
1906 ->GetPersonalDataManager();
1907 if (pdm) {
1908 std::vector<AutoFillProfile*> autofill_profiles = pdm->profiles();
1909 std::vector<CreditCard*> credit_cards = pdm->credit_cards();
1910
1911 ListValue* profiles = GetListFromAutoFillProfiles(autofill_profiles);
1912 ListValue* cards = GetListFromCreditCards(credit_cards);
1913
1914 scoped_ptr<DictionaryValue> return_value(new DictionaryValue);
1915
[email protected]ff4c1d82010-08-04 16:58:121916 return_value->Set("profiles", profiles);
1917 return_value->Set("credit_cards", cards);
[email protected]7c983cc2010-07-16 11:33:341918 reply.SendSuccess(return_value.get());
[email protected]55846ad842010-07-09 18:22:561919 } else {
[email protected]7c983cc2010-07-16 11:33:341920 reply.SendError("No PersonalDataManager.");
1921 return;
[email protected]55846ad842010-07-09 18:22:561922 }
1923 } else {
[email protected]7c983cc2010-07-16 11:33:341924 reply.SendError("No tab at that index.");
1925 return;
[email protected]55846ad842010-07-09 18:22:561926 }
[email protected]55846ad842010-07-09 18:22:561927}
1928
1929// Refer to FillAutoFillProfile() in chrome/test/pyautolib/pyauto.py for sample
1930// json input.
1931// Sample json output: {}
1932void AutomationProvider::FillAutoFillProfile(Browser* browser,
1933 DictionaryValue* args,
1934 IPC::Message* reply_message) {
[email protected]7c983cc2010-07-16 11:33:341935 AutomationJSONReply reply(this, reply_message);
[email protected]55846ad842010-07-09 18:22:561936 ListValue* profiles = NULL;
1937 ListValue* cards = NULL;
[email protected]ff4c1d82010-08-04 16:58:121938 args->GetList("profiles", &profiles);
1939 args->GetList("credit_cards", &cards);
[email protected]7c983cc2010-07-16 11:33:341940 std::string error_mesg;
[email protected]55846ad842010-07-09 18:22:561941
1942 std::vector<AutoFillProfile> autofill_profiles;
1943 std::vector<CreditCard> credit_cards;
1944 // Create an AutoFillProfile for each of the dictionary profiles.
1945 if (profiles) {
[email protected]7c983cc2010-07-16 11:33:341946 autofill_profiles = GetAutoFillProfilesFromList(*profiles, &error_mesg);
[email protected]55846ad842010-07-09 18:22:561947 }
1948 // Create a CreditCard for each of the dictionary values.
1949 if (cards) {
[email protected]7c983cc2010-07-16 11:33:341950 credit_cards = GetCreditCardsFromList(*cards, &error_mesg);
1951 }
1952 if (!error_mesg.empty()) {
1953 reply.SendError(error_mesg);
1954 return;
[email protected]55846ad842010-07-09 18:22:561955 }
1956
1957 // Save the AutoFillProfiles.
1958 int tab_index = 0;
[email protected]ff4c1d82010-08-04 16:58:121959 args->GetInteger("tab_index", &tab_index);
[email protected]55846ad842010-07-09 18:22:561960 TabContents* tab_contents = browser->GetTabContentsAt(tab_index);
1961
1962 if (tab_contents) {
[email protected]ce6b0122010-07-19 19:07:301963 PersonalDataManager* pdm = tab_contents->profile()
[email protected]55846ad842010-07-09 18:22:561964 ->GetPersonalDataManager();
1965 if (pdm) {
1966 pdm->OnAutoFillDialogApply(profiles? &autofill_profiles : NULL,
1967 cards? &credit_cards : NULL);
1968 } else {
[email protected]7c983cc2010-07-16 11:33:341969 reply.SendError("No PersonalDataManager.");
1970 return;
[email protected]55846ad842010-07-09 18:22:561971 }
1972 } else {
[email protected]7c983cc2010-07-16 11:33:341973 reply.SendError("No tab at that index.");
1974 return;
[email protected]55846ad842010-07-09 18:22:561975 }
[email protected]7c983cc2010-07-16 11:33:341976 reply.SendSuccess(NULL);
[email protected]55846ad842010-07-09 18:22:561977}
1978
1979/* static */
1980ListValue* AutomationProvider::GetListFromAutoFillProfiles(
1981 std::vector<AutoFillProfile*> autofill_profiles) {
1982 ListValue* profiles = new ListValue;
1983
1984 std::map<AutoFillFieldType, std::wstring> autofill_type_to_string
1985 = GetAutoFillFieldToStringMap();
1986
1987 // For each AutoFillProfile, transform it to a dictionary object to return.
1988 for (std::vector<AutoFillProfile*>::iterator it = autofill_profiles.begin();
1989 it != autofill_profiles.end(); ++it) {
1990 AutoFillProfile* profile = *it;
1991 DictionaryValue* profile_info = new DictionaryValue;
[email protected]ff4c1d82010-08-04 16:58:121992 profile_info->SetString("label", profile->Label());
[email protected]55846ad842010-07-09 18:22:561993 // For each of the types, if it has a value, add it to the dictionary.
1994 for (std::map<AutoFillFieldType, std::wstring>::iterator
1995 type_it = autofill_type_to_string.begin();
1996 type_it != autofill_type_to_string.end(); ++type_it) {
1997 string16 value = profile->GetFieldText(AutoFillType(type_it->first));
1998 if (value.length()) { // If there was something stored for that value.
[email protected]99922662010-08-17 16:24:251999 profile_info->SetString(WideToUTF8(type_it->second), value);
[email protected]55846ad842010-07-09 18:22:562000 }
2001 }
2002 profiles->Append(profile_info);
2003 }
2004 return profiles;
2005}
2006
2007/* static */
2008ListValue* AutomationProvider::GetListFromCreditCards(
2009 std::vector<CreditCard*> credit_cards) {
2010 ListValue* cards = new ListValue;
2011
2012 std::map<AutoFillFieldType, std::wstring> credit_card_type_to_string =
2013 GetCreditCardFieldToStringMap();
2014
2015 // For each AutoFillProfile, transform it to a dictionary object to return.
2016 for (std::vector<CreditCard*>::iterator it = credit_cards.begin();
2017 it != credit_cards.end(); ++it) {
2018 CreditCard* card = *it;
2019 DictionaryValue* card_info = new DictionaryValue;
[email protected]ff4c1d82010-08-04 16:58:122020 card_info->SetString("label", card->Label());
[email protected]55846ad842010-07-09 18:22:562021 // For each of the types, if it has a value, add it to the dictionary.
2022 for (std::map<AutoFillFieldType, std::wstring>::iterator type_it =
2023 credit_card_type_to_string.begin();
2024 type_it != credit_card_type_to_string.end(); ++type_it) {
2025 string16 value = card->GetFieldText(AutoFillType(type_it->first));
2026 // If there was something stored for that value.
2027 if (value.length()) {
[email protected]99922662010-08-17 16:24:252028 card_info->SetString(WideToUTF8(type_it->second), value);
[email protected]55846ad842010-07-09 18:22:562029 }
2030 }
2031 cards->Append(card_info);
2032 }
2033 return cards;
2034}
2035
2036/* static */
2037std::vector<AutoFillProfile> AutomationProvider::GetAutoFillProfilesFromList(
[email protected]7c983cc2010-07-16 11:33:342038 const ListValue& profiles, std::string* error_message) {
[email protected]55846ad842010-07-09 18:22:562039 std::vector<AutoFillProfile> autofill_profiles;
2040 DictionaryValue* profile_info = NULL;
2041 string16 profile_label;
2042 string16 current_value;
2043
2044 std::map<AutoFillFieldType, std::wstring> autofill_type_to_string =
2045 GetAutoFillFieldToStringMap();
2046
2047 int num_profiles = profiles.GetSize();
2048 for (int i = 0; i < num_profiles; i++) {
2049 profiles.GetDictionary(i, &profile_info);
2050 profile_info->GetString("label", &profile_label);
2051 // Choose an id of 0 so that a unique id will be created.
2052 AutoFillProfile profile(profile_label, 0);
2053 // Loop through the possible profile types and add those provided.
2054 for (std::map<AutoFillFieldType, std::wstring>::iterator type_it =
2055 autofill_type_to_string.begin();
2056 type_it != autofill_type_to_string.end(); ++type_it) {
[email protected]99922662010-08-17 16:24:252057 if (profile_info->HasKey(WideToUTF8(type_it->second))) {
[email protected]698f7f42010-08-04 19:35:332058 if (profile_info->GetString(WideToUTF8(type_it->second),
2059 &current_value)) {
[email protected]55846ad842010-07-09 18:22:562060 profile.SetInfo(AutoFillType(type_it->first), current_value);
2061 } else {
[email protected]7c983cc2010-07-16 11:33:342062 *error_message= "All values must be strings";
[email protected]55846ad842010-07-09 18:22:562063 break;
2064 }
2065 }
2066 }
2067 autofill_profiles.push_back(profile);
2068 }
2069 return autofill_profiles;
2070}
2071
2072/* static */
2073std::vector<CreditCard> AutomationProvider::GetCreditCardsFromList(
[email protected]7c983cc2010-07-16 11:33:342074 const ListValue& cards, std::string* error_message) {
[email protected]55846ad842010-07-09 18:22:562075 std::vector<CreditCard> credit_cards;
2076 DictionaryValue* card_info = NULL;
2077 string16 card_label;
2078 string16 current_value;
2079
2080 std::map<AutoFillFieldType, std::wstring> credit_card_type_to_string =
2081 GetCreditCardFieldToStringMap();
2082
2083 int num_credit_cards = cards.GetSize();
2084 for (int i = 0; i < num_credit_cards; i++) {
2085 cards.GetDictionary(i, &card_info);
2086 card_info->GetString("label", &card_label);
2087 CreditCard card(card_label, 0);
2088 // Loop through the possible credit card fields and add those provided.
2089 for (std::map<AutoFillFieldType, std::wstring>::iterator type_it =
2090 credit_card_type_to_string.begin();
2091 type_it != credit_card_type_to_string.end(); ++type_it) {
[email protected]99922662010-08-17 16:24:252092 if (card_info->HasKey(WideToUTF8(type_it->second))) {
[email protected]698f7f42010-08-04 19:35:332093 if (card_info->GetString(WideToUTF8(type_it->second), &current_value)) {
[email protected]55846ad842010-07-09 18:22:562094 card.SetInfo(AutoFillType(type_it->first), current_value);
2095 } else {
[email protected]7c983cc2010-07-16 11:33:342096 *error_message= "All values must be strings";
[email protected]55846ad842010-07-09 18:22:562097 break;
2098 }
2099 }
2100 }
2101 credit_cards.push_back(card);
2102 }
2103 return credit_cards;
2104}
2105
2106/* static */
2107std::map<AutoFillFieldType, std::wstring>
2108 AutomationProvider::GetAutoFillFieldToStringMap() {
2109 std::map<AutoFillFieldType, std::wstring> autofill_type_to_string;
2110 autofill_type_to_string[NAME_FIRST] = L"NAME_FIRST";
2111 autofill_type_to_string[NAME_MIDDLE] = L"NAME_MIDDLE";
2112 autofill_type_to_string[NAME_LAST] = L"NAME_LAST";
2113 autofill_type_to_string[COMPANY_NAME] = L"COMPANY_NAME";
2114 autofill_type_to_string[EMAIL_ADDRESS] = L"EMAIL_ADDRESS";
2115 autofill_type_to_string[ADDRESS_HOME_LINE1] = L"ADDRESS_HOME_LINE1";
2116 autofill_type_to_string[ADDRESS_HOME_LINE2] = L"ADDRESS_HOME_LINE2";
2117 autofill_type_to_string[ADDRESS_HOME_CITY] = L"ADDRESS_HOME_CITY";
2118 autofill_type_to_string[ADDRESS_HOME_STATE] = L"ADDRESS_HOME_STATE";
2119 autofill_type_to_string[ADDRESS_HOME_ZIP] = L"ADDRESS_HOME_ZIP";
2120 autofill_type_to_string[ADDRESS_HOME_COUNTRY] = L"ADDRESS_HOME_COUNTRY";
2121 autofill_type_to_string[PHONE_HOME_NUMBER] = L"PHONE_HOME_NUMBER";
2122 autofill_type_to_string[PHONE_FAX_NUMBER] = L"PHONE_FAX_NUMBER";
2123 autofill_type_to_string[NAME_FIRST] = L"NAME_FIRST";
2124 return autofill_type_to_string;
2125}
2126
2127/* static */
2128std::map<AutoFillFieldType, std::wstring>
2129 AutomationProvider::GetCreditCardFieldToStringMap() {
2130 std::map<AutoFillFieldType, std::wstring> credit_card_type_to_string;
2131 credit_card_type_to_string[CREDIT_CARD_NAME] = L"CREDIT_CARD_NAME";
2132 credit_card_type_to_string[CREDIT_CARD_NUMBER] = L"CREDIT_CARD_NUMBER";
[email protected]55846ad842010-07-09 18:22:562133 credit_card_type_to_string[CREDIT_CARD_EXP_MONTH] = L"CREDIT_CARD_EXP_MONTH";
2134 credit_card_type_to_string[CREDIT_CARD_EXP_4_DIGIT_YEAR] =
2135 L"CREDIT_CARD_EXP_4_DIGIT_YEAR";
2136 return credit_card_type_to_string;
2137}
2138
[email protected]53329582010-05-14 21:10:582139void AutomationProvider::SendJSONRequest(int handle,
2140 std::string json_request,
2141 IPC::Message* reply_message) {
[email protected]59a611242010-04-02 02:24:042142 Browser* browser = NULL;
[email protected]59a611242010-04-02 02:24:042143 scoped_ptr<Value> values;
2144
2145 // Basic error checking.
2146 if (browser_tracker_->ContainsHandle(handle)) {
2147 browser = browser_tracker_->GetResource(handle);
2148 }
2149 if (!browser) {
[email protected]7c983cc2010-07-16 11:33:342150 AutomationJSONReply(this, reply_message).SendError("no browser object");
2151 return;
2152 }
2153 base::JSONReader reader;
2154 std::string error;
2155 values.reset(reader.ReadAndReturnError(json_request, true, NULL, &error));
2156 if (!error.empty()) {
2157 AutomationJSONReply(this, reply_message).SendError(error);
2158 return;
[email protected]59a611242010-04-02 02:24:042159 }
2160
2161 // Make sure input is a dict with a string command.
2162 std::string command;
2163 DictionaryValue* dict_value = NULL;
[email protected]7c983cc2010-07-16 11:33:342164 if (values->GetType() != Value::TYPE_DICTIONARY) {
2165 AutomationJSONReply(this, reply_message).SendError("not a dict");
2166 return;
2167 }
2168 // Ownership remains with "values" variable.
2169 dict_value = static_cast<DictionaryValue*>(values.get());
2170 if (!dict_value->GetStringASCII(std::string("command"), &command)) {
2171 AutomationJSONReply(this, reply_message).SendError(
2172 "no command key in dict or not a string command");
2173 return;
[email protected]59a611242010-04-02 02:24:042174 }
2175
[email protected]24e2b102010-04-29 17:56:472176 // Map json commands to their handlers.
2177 std::map<std::string, JsonHandler> handler_map;
[email protected]f7d48012010-05-06 08:17:052178 handler_map["DisablePlugin"] = &AutomationProvider::DisablePlugin;
2179 handler_map["EnablePlugin"] = &AutomationProvider::EnablePlugin;
2180 handler_map["GetPluginsInfo"] = &AutomationProvider::GetPluginsInfo;
2181
[email protected]a9ff2c02010-05-13 17:33:052182 handler_map["GetBrowserInfo"] = &AutomationProvider::GetBrowserInfo;
[email protected]7c983cc2010-07-16 11:33:342183
[email protected]38b5a3852010-07-21 06:49:522184 handler_map["WaitForInfobarCount"] = &AutomationProvider::WaitForInfobarCount;
[email protected]e004a2d2010-07-22 04:55:282185 handler_map["PerformActionOnInfobar"] =
2186 &AutomationProvider::PerformActionOnInfobar;
[email protected]38b5a3852010-07-21 06:49:522187
[email protected]24e2b102010-04-29 17:56:472188 handler_map["GetHistoryInfo"] = &AutomationProvider::GetHistoryInfo;
[email protected]bbe6aa02010-05-07 17:27:292189 handler_map["AddHistoryItem"] = &AutomationProvider::AddHistoryItem;
[email protected]f7d48012010-05-06 08:17:052190
[email protected]53329582010-05-14 21:10:582191 handler_map["GetOmniboxInfo"] = &AutomationProvider::GetOmniboxInfo;
2192 handler_map["SetOmniboxText"] = &AutomationProvider::SetOmniboxText;
2193 handler_map["OmniboxAcceptInput"] = &AutomationProvider::OmniboxAcceptInput;
2194 handler_map["OmniboxMovePopupSelection"] =
2195 &AutomationProvider::OmniboxMovePopupSelection;
2196
[email protected]24e2b102010-04-29 17:56:472197 handler_map["GetPrefsInfo"] = &AutomationProvider::GetPrefsInfo;
2198 handler_map["SetPrefs"] = &AutomationProvider::SetPrefs;
[email protected]f7d48012010-05-06 08:17:052199
[email protected]ef413ca2010-05-25 21:09:142200 handler_map["SetWindowDimensions"] = &AutomationProvider::SetWindowDimensions;
2201
[email protected]f7d48012010-05-06 08:17:052202 handler_map["GetDownloadsInfo"] = &AutomationProvider::GetDownloadsInfo;
[email protected]24e2b102010-04-29 17:56:472203 handler_map["WaitForAllDownloadsToComplete"] =
2204 &AutomationProvider::WaitForDownloadsToComplete;
[email protected]2d54c4032010-08-20 00:42:282205 handler_map["PerformActionOnDownload"] =
2206 &AutomationProvider::PerformActionOnDownload;
2207 handler_map["WaitForAlwaysOpenDownloadTypeToOpen"] =
2208 &AutomationProvider::WaitForAlwaysOpenDownloadTypeToOpen;
[email protected]24e2b102010-04-29 17:56:472209
[email protected]a3cd5022010-06-16 18:25:292210 handler_map["GetInitialLoadTimes"] = &AutomationProvider::GetInitialLoadTimes;
2211
[email protected]7060bb292010-06-24 00:52:492212 handler_map["SaveTabContents"] = &AutomationProvider::SaveTabContents;
2213
[email protected]c5aa5322010-07-15 19:00:072214 handler_map["ImportSettings"] = &AutomationProvider::ImportSettings;
2215
[email protected]5bcfe1672010-07-16 20:51:572216 handler_map["AddSavedPassword"] = &AutomationProvider::AddSavedPassword;
[email protected]95222282010-07-26 17:43:022217 handler_map["RemoveSavedPassword"] =
2218 &AutomationProvider::RemoveSavedPassword;
[email protected]5bcfe1672010-07-16 20:51:572219 handler_map["GetSavedPasswords"] = &AutomationProvider::GetSavedPasswords;
2220
[email protected]a0fc50d72010-07-14 21:14:192221 handler_map["ClearBrowsingData"] = &AutomationProvider::ClearBrowsingData;
2222
[email protected]4d1929f12010-07-10 00:09:032223 // SetTheme() implemented using InstallExtension().
2224 handler_map["GetThemeInfo"] = &AutomationProvider::GetThemeInfo;
2225
[email protected]32a69cf2010-08-03 16:27:012226 // InstallExtension() present in pyauto.py.
2227 handler_map["GetExtensionsInfo"] = &AutomationProvider::GetExtensionsInfo;
2228 handler_map["UninstallExtensionById"] =
2229 &AutomationProvider::UninstallExtensionById;
2230
[email protected]3dda5b02010-07-27 16:35:422231 handler_map["SelectTranslateOption"] =
2232 &AutomationProvider::SelectTranslateOption;
2233 handler_map["GetTranslateInfo"] = &AutomationProvider::GetTranslateInfo;
[email protected]f89ee5d2010-08-02 16:39:122234 handler_map["WaitUntilTranslateComplete"] =
2235 &AutomationProvider::WaitUntilTranslateComplete;
[email protected]3dda5b02010-07-27 16:35:422236
[email protected]55846ad842010-07-09 18:22:562237 handler_map["GetAutoFillProfile"] = &AutomationProvider::GetAutoFillProfile;
2238 handler_map["FillAutoFillProfile"] = &AutomationProvider::FillAutoFillProfile;
2239
[email protected]7c983cc2010-07-16 11:33:342240 if (handler_map.find(std::string(command)) != handler_map.end()) {
2241 (this->*handler_map[command])(browser, dict_value, reply_message);
[email protected]1ac875d22010-07-16 09:57:582242 } else {
[email protected]7c983cc2010-07-16 11:33:342243 std::string error_string = "Unknown command. Options: ";
2244 for (std::map<std::string, JsonHandler>::const_iterator it =
2245 handler_map.begin(); it != handler_map.end(); ++it) {
2246 error_string += it->first + ", ";
2247 }
2248 AutomationJSONReply(this, reply_message).SendError(error_string);
[email protected]1ac875d22010-07-16 09:57:582249 }
[email protected]59a611242010-04-02 02:24:042250}
2251
[email protected]a7eee32f2009-05-22 18:08:172252class SetProxyConfigTask : public Task {
2253 public:
[email protected]be180c802009-10-23 06:33:312254 SetProxyConfigTask(URLRequestContextGetter* request_context_getter,
2255 const std::string& new_proxy_config)
[email protected]2aa336e2010-04-06 21:05:252256 : request_context_getter_(request_context_getter),
2257 proxy_config_(new_proxy_config) {}
[email protected]a7eee32f2009-05-22 18:08:172258 virtual void Run() {
2259 // First, deserialize the JSON string. If this fails, log and bail.
2260 JSONStringValueSerializer deserializer(proxy_config_);
[email protected]ba399672010-04-06 15:42:392261 std::string error_msg;
2262 scoped_ptr<Value> root(deserializer.Deserialize(NULL, &error_msg));
[email protected]a7eee32f2009-05-22 18:08:172263 if (!root.get() || root->GetType() != Value::TYPE_DICTIONARY) {
2264 DLOG(WARNING) << "Received bad JSON string for ProxyConfig: "
[email protected]ba399672010-04-06 15:42:392265 << error_msg;
[email protected]a7eee32f2009-05-22 18:08:172266 return;
2267 }
2268
2269 scoped_ptr<DictionaryValue> dict(
2270 static_cast<DictionaryValue*>(root.release()));
2271 // Now put together a proxy configuration from the deserialized string.
2272 net::ProxyConfig pc;
2273 PopulateProxyConfig(*dict.get(), &pc);
2274
[email protected]be180c802009-10-23 06:33:312275 net::ProxyService* proxy_service =
2276 request_context_getter_->GetURLRequestContext()->proxy_service();
2277 DCHECK(proxy_service);
[email protected]a7eee32f2009-05-22 18:08:172278 scoped_ptr<net::ProxyConfigService> proxy_config_service(
2279 new net::ProxyConfigServiceFixed(pc));
[email protected]be180c802009-10-23 06:33:312280 proxy_service->ResetConfigService(proxy_config_service.release());
[email protected]a7eee32f2009-05-22 18:08:172281 }
2282
2283 void PopulateProxyConfig(const DictionaryValue& dict, net::ProxyConfig* pc) {
2284 DCHECK(pc);
2285 bool no_proxy = false;
2286 if (dict.GetBoolean(automation::kJSONProxyNoProxy, &no_proxy)) {
2287 // Make no changes to the ProxyConfig.
2288 return;
2289 }
2290 bool auto_config;
2291 if (dict.GetBoolean(automation::kJSONProxyAutoconfig, &auto_config)) {
[email protected]ed4ed0f2010-02-24 00:20:482292 pc->set_auto_detect(true);
[email protected]a7eee32f2009-05-22 18:08:172293 }
2294 std::string pac_url;
2295 if (dict.GetString(automation::kJSONProxyPacUrl, &pac_url)) {
[email protected]ed4ed0f2010-02-24 00:20:482296 pc->set_pac_url(GURL(pac_url));
[email protected]a7eee32f2009-05-22 18:08:172297 }
2298 std::string proxy_bypass_list;
2299 if (dict.GetString(automation::kJSONProxyBypassList, &proxy_bypass_list)) {
[email protected]ed4ed0f2010-02-24 00:20:482300 pc->proxy_rules().bypass_rules.ParseFromString(proxy_bypass_list);
[email protected]a7eee32f2009-05-22 18:08:172301 }
2302 std::string proxy_server;
2303 if (dict.GetString(automation::kJSONProxyServer, &proxy_server)) {
[email protected]ed4ed0f2010-02-24 00:20:482304 pc->proxy_rules().ParseFromString(proxy_server);
[email protected]a7eee32f2009-05-22 18:08:172305 }
2306 }
2307
2308 private:
[email protected]be180c802009-10-23 06:33:312309 scoped_refptr<URLRequestContextGetter> request_context_getter_;
[email protected]a7eee32f2009-05-22 18:08:172310 std::string proxy_config_;
2311};
2312
2313
2314void AutomationProvider::SetProxyConfig(const std::string& new_proxy_config) {
[email protected]be180c802009-10-23 06:33:312315 URLRequestContextGetter* context_getter = Profile::GetDefaultRequestContext();
2316 if (!context_getter) {
[email protected]a7eee32f2009-05-22 18:08:172317 FilePath user_data_dir;
2318 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
2319 ProfileManager* profile_manager = g_browser_process->profile_manager();
2320 DCHECK(profile_manager);
2321 Profile* profile = profile_manager->GetDefaultProfile(user_data_dir);
2322 DCHECK(profile);
[email protected]be180c802009-10-23 06:33:312323 context_getter = profile->GetRequestContext();
[email protected]a7eee32f2009-05-22 18:08:172324 }
[email protected]be180c802009-10-23 06:33:312325 DCHECK(context_getter);
[email protected]a7eee32f2009-05-22 18:08:172326
[email protected]fae20792009-10-28 20:31:582327 ChromeThread::PostTask(
2328 ChromeThread::IO, FROM_HERE,
[email protected]be180c802009-10-23 06:33:312329 new SetProxyConfigTask(context_getter, new_proxy_config));
[email protected]a7eee32f2009-05-22 18:08:172330}
2331
[email protected]57c6a652009-05-04 07:58:342332TabContents* AutomationProvider::GetTabContentsForHandle(
[email protected]20e93d12008-08-28 16:31:572333 int handle, NavigationController** tab) {
[email protected]20e93d12008-08-28 16:31:572334 if (tab_tracker_->ContainsHandle(handle)) {
2335 NavigationController* nav_controller = tab_tracker_->GetResource(handle);
[email protected]57c6a652009-05-04 07:58:342336 if (tab)
2337 *tab = nav_controller;
2338 return nav_controller->tab_contents();
[email protected]20e93d12008-08-28 16:31:572339 }
[email protected]57c6a652009-05-04 07:58:342340 return NULL;
[email protected]20e93d12008-08-28 16:31:572341}
2342
[email protected]97fa6ce32008-12-19 01:48:162343// Gets the current used encoding name of the page in the specified tab.
[email protected]71f65dd2009-02-11 19:14:562344void AutomationProvider::GetPageCurrentEncoding(
[email protected]41fc0322009-09-04 22:23:402345 int tab_handle, std::string* current_encoding) {
[email protected]97fa6ce32008-12-19 01:48:162346 if (tab_tracker_->ContainsHandle(tab_handle)) {
2347 NavigationController* nav = tab_tracker_->GetResource(tab_handle);
2348 Browser* browser = FindAndActivateTab(nav);
2349 DCHECK(browser);
2350
[email protected]57c6a652009-05-04 07:58:342351 if (browser->command_updater()->IsCommandEnabled(IDC_ENCODING_MENU))
2352 *current_encoding = nav->tab_contents()->encoding();
[email protected]97fa6ce32008-12-19 01:48:162353 }
[email protected]97fa6ce32008-12-19 01:48:162354}
2355
[email protected]b8f48d12009-11-09 20:14:362356// Gets the current used encoding name of the page in the specified tab.
[email protected]71f65dd2009-02-11 19:14:562357void AutomationProvider::OverrideEncoding(int tab_handle,
[email protected]41fc0322009-09-04 22:23:402358 const std::string& encoding_name,
[email protected]71f65dd2009-02-11 19:14:562359 bool* success) {
2360 *success = false;
[email protected]97fa6ce32008-12-19 01:48:162361 if (tab_tracker_->ContainsHandle(tab_handle)) {
2362 NavigationController* nav = tab_tracker_->GetResource(tab_handle);
[email protected]2f2afba2010-04-01 01:53:192363 if (!nav)
2364 return;
[email protected]97fa6ce32008-12-19 01:48:162365 Browser* browser = FindAndActivateTab(nav);
[email protected]97fa6ce32008-12-19 01:48:162366
[email protected]2f2afba2010-04-01 01:53:192367 // If the browser has UI, simulate what a user would do.
2368 // Activate the tab and then click the encoding menu.
2369 if (browser &&
2370 browser->command_updater()->IsCommandEnabled(IDC_ENCODING_MENU)) {
[email protected]97fa6ce32008-12-19 01:48:162371 int selected_encoding_id =
2372 CharacterEncoding::GetCommandIdByCanonicalEncodingName(encoding_name);
2373 if (selected_encoding_id) {
2374 browser->OverrideEncoding(selected_encoding_id);
[email protected]71f65dd2009-02-11 19:14:562375 *success = true;
[email protected]97fa6ce32008-12-19 01:48:162376 }
[email protected]2f2afba2010-04-01 01:53:192377 } else {
2378 // There is no UI, Chrome probably runs as Chrome-Frame mode.
2379 // Try to get TabContents and call its override_encoding method.
2380 TabContents* contents = nav->tab_contents();
2381 if (!contents)
2382 return;
2383 const std::string selected_encoding =
2384 CharacterEncoding::GetCanonicalEncodingNameByAliasName(encoding_name);
2385 if (selected_encoding.empty())
2386 return;
2387 contents->SetOverrideEncoding(selected_encoding);
[email protected]97fa6ce32008-12-19 01:48:162388 }
2389 }
[email protected]97fa6ce32008-12-19 01:48:162390}
[email protected]5bcdb312009-01-07 21:43:202391
[email protected]f7a68432009-07-29 23:18:192392void AutomationProvider::SelectAll(int tab_handle) {
2393 RenderViewHost* view = GetViewForTab(tab_handle);
2394 if (!view) {
2395 NOTREACHED();
2396 return;
2397 }
2398
2399 view->SelectAll();
2400}
2401
2402void AutomationProvider::Cut(int tab_handle) {
2403 RenderViewHost* view = GetViewForTab(tab_handle);
2404 if (!view) {
2405 NOTREACHED();
2406 return;
2407 }
2408
2409 view->Cut();
2410}
2411
2412void AutomationProvider::Copy(int tab_handle) {
2413 RenderViewHost* view = GetViewForTab(tab_handle);
2414 if (!view) {
2415 NOTREACHED();
2416 return;
2417 }
2418
2419 view->Copy();
2420}
2421
2422void AutomationProvider::Paste(int tab_handle) {
2423 RenderViewHost* view = GetViewForTab(tab_handle);
2424 if (!view) {
2425 NOTREACHED();
2426 return;
2427 }
2428
2429 view->Paste();
2430}
2431
2432void AutomationProvider::ReloadAsync(int tab_handle) {
2433 if (tab_tracker_->ContainsHandle(tab_handle)) {
2434 NavigationController* tab = tab_tracker_->GetResource(tab_handle);
2435 if (!tab) {
2436 NOTREACHED();
2437 return;
2438 }
2439
[email protected]106a0812010-03-18 00:15:122440 const bool check_for_repost = true;
2441 tab->Reload(check_for_repost);
[email protected]f7a68432009-07-29 23:18:192442 }
2443}
2444
2445void AutomationProvider::StopAsync(int tab_handle) {
2446 RenderViewHost* view = GetViewForTab(tab_handle);
2447 if (!view) {
[email protected]8b2b3312009-09-14 18:38:362448 // We tolerate StopAsync being called even before a view has been created.
2449 // So just log a warning instead of a NOTREACHED().
2450 DLOG(WARNING) << "StopAsync: no view for handle " << tab_handle;
[email protected]f7a68432009-07-29 23:18:192451 return;
2452 }
2453
2454 view->Stop();
2455}
2456
[email protected]1bb5f892009-10-06 01:44:572457void AutomationProvider::OnSetPageFontSize(int tab_handle,
2458 int font_size) {
2459 AutomationPageFontSize automation_font_size =
2460 static_cast<AutomationPageFontSize>(font_size);
2461
2462 if (automation_font_size < SMALLEST_FONT ||
2463 automation_font_size > LARGEST_FONT) {
2464 DLOG(ERROR) << "Invalid font size specified : "
2465 << font_size;
2466 return;
2467 }
2468
2469 if (tab_tracker_->ContainsHandle(tab_handle)) {
2470 NavigationController* tab = tab_tracker_->GetResource(tab_handle);
2471 DCHECK(tab != NULL);
2472 if (tab && tab->tab_contents()) {
2473 DCHECK(tab->tab_contents()->profile() != NULL);
2474 tab->tab_contents()->profile()->GetPrefs()->SetInteger(
2475 prefs::kWebKitDefaultFontSize, font_size);
2476 }
2477 }
2478}
2479
[email protected]bc73b4e52010-03-26 04:16:202480void AutomationProvider::RemoveBrowsingData(int remove_mask) {
2481 BrowsingDataRemover* remover;
2482 remover = new BrowsingDataRemover(profile(),
2483 BrowsingDataRemover::EVERYTHING, // All time periods.
2484 base::Time());
2485 remover->Remove(remove_mask);
2486 // BrowsingDataRemover deletes itself.
2487}
[email protected]1bb5f892009-10-06 01:44:572488
[email protected]f7a68432009-07-29 23:18:192489RenderViewHost* AutomationProvider::GetViewForTab(int tab_handle) {
2490 if (tab_tracker_->ContainsHandle(tab_handle)) {
2491 NavigationController* tab = tab_tracker_->GetResource(tab_handle);
2492 if (!tab) {
2493 NOTREACHED();
2494 return NULL;
2495 }
2496
2497 TabContents* tab_contents = tab->tab_contents();
2498 if (!tab_contents) {
2499 NOTREACHED();
2500 return NULL;
2501 }
2502
2503 RenderViewHost* view_host = tab_contents->render_view_host();
2504 return view_host;
2505 }
2506
2507 return NULL;
2508}
[email protected]675595f2009-08-26 22:32:042509
[email protected]d11c8e92009-10-20 23:26:402510void AutomationProvider::InstallExtension(const FilePath& crx_path,
2511 IPC::Message* reply_message) {
2512 ExtensionsService* service = profile_->GetExtensionsService();
2513 if (service) {
2514 // The observer will delete itself when done.
[email protected]790788ac2010-04-06 17:52:192515 new ExtensionInstallNotificationObserver(this,
2516 AutomationMsg_InstallExtension::ID,
2517 reply_message);
[email protected]d11c8e92009-10-20 23:26:402518
2519 const FilePath& install_dir = service->install_directory();
[email protected]6dfbbf82010-03-12 23:09:162520 scoped_refptr<CrxInstaller> installer(
2521 new CrxInstaller(install_dir,
2522 service,
2523 NULL)); // silent install, no UI
2524 installer->set_allow_privilege_increase(true);
2525 installer->InstallCrx(crx_path);
[email protected]d11c8e92009-10-20 23:26:402526 } else {
2527 AutomationMsg_InstallExtension::WriteReplyParams(
2528 reply_message, AUTOMATION_MSG_EXTENSION_INSTALL_FAILED);
2529 Send(reply_message);
2530 }
2531}
2532
2533void AutomationProvider::LoadExpandedExtension(
2534 const FilePath& extension_dir,
2535 IPC::Message* reply_message) {
[email protected]a4378252010-02-09 08:14:382536 if (profile_->GetExtensionsService()) {
[email protected]d11c8e92009-10-20 23:26:402537 // The observer will delete itself when done.
[email protected]790788ac2010-04-06 17:52:192538 new ExtensionInstallNotificationObserver(
2539 this,
2540 AutomationMsg_LoadExpandedExtension::ID,
2541 reply_message);
[email protected]d11c8e92009-10-20 23:26:402542
2543 profile_->GetExtensionsService()->LoadExtension(extension_dir);
[email protected]d11c8e92009-10-20 23:26:402544 } else {
2545 AutomationMsg_LoadExpandedExtension::WriteReplyParams(
2546 reply_message, AUTOMATION_MSG_EXTENSION_INSTALL_FAILED);
2547 Send(reply_message);
2548 }
2549}
[email protected]673fd2c02010-02-04 23:10:002550
[email protected]a1e62d12010-03-16 02:18:432551void AutomationProvider::GetEnabledExtensions(
2552 std::vector<FilePath>* result) {
2553 ExtensionsService* service = profile_->GetExtensionsService();
2554 DCHECK(service);
2555 if (service->extensions_enabled()) {
2556 const ExtensionList* extensions = service->extensions();
2557 DCHECK(extensions);
2558 for (size_t i = 0; i < extensions->size(); ++i) {
2559 Extension* extension = (*extensions)[i];
2560 DCHECK(extension);
[email protected]472f099b2010-05-27 17:07:122561 if (extension->location() == Extension::INTERNAL ||
2562 extension->location() == Extension::LOAD) {
[email protected]237f281672010-03-20 12:37:072563 result->push_back(extension->path());
2564 }
[email protected]a1e62d12010-03-16 02:18:432565 }
2566 }
2567}
2568
[email protected]790788ac2010-04-06 17:52:192569void AutomationProvider::WaitForExtensionTestResult(
2570 IPC::Message* reply_message) {
2571 DCHECK(reply_message_ == NULL);
2572 reply_message_ = reply_message;
2573 // Call MaybeSendResult, because the result might have come in before
2574 // we were waiting on it.
2575 extension_test_result_observer_->MaybeSendResult();
2576}
2577
2578void AutomationProvider::InstallExtensionAndGetHandle(
[email protected]d7e5525d2010-04-20 14:37:092579 const FilePath& crx_path, bool with_ui, IPC::Message* reply_message) {
[email protected]790788ac2010-04-06 17:52:192580 ExtensionsService* service = profile_->GetExtensionsService();
2581 ExtensionProcessManager* manager = profile_->GetExtensionProcessManager();
2582 if (service && manager) {
2583 // The observer will delete itself when done.
2584 new ExtensionReadyNotificationObserver(
2585 manager,
2586 this,
2587 AutomationMsg_InstallExtensionAndGetHandle::ID,
2588 reply_message);
2589
[email protected]d7e5525d2010-04-20 14:37:092590 ExtensionInstallUI* client =
2591 (with_ui ? new ExtensionInstallUI(profile_) : NULL);
[email protected]790788ac2010-04-06 17:52:192592 scoped_refptr<CrxInstaller> installer(
2593 new CrxInstaller(service->install_directory(),
2594 service,
[email protected]d7e5525d2010-04-20 14:37:092595 client));
[email protected]790788ac2010-04-06 17:52:192596 installer->set_allow_privilege_increase(true);
2597 installer->InstallCrx(crx_path);
2598 } else {
2599 AutomationMsg_InstallExtensionAndGetHandle::WriteReplyParams(
2600 reply_message, 0);
2601 Send(reply_message);
2602 }
2603}
2604
2605void AutomationProvider::UninstallExtension(int extension_handle,
2606 bool* success) {
2607 *success = false;
2608 Extension* extension = GetExtension(extension_handle);
2609 ExtensionsService* service = profile_->GetExtensionsService();
2610 if (extension && service) {
2611 ExtensionUnloadNotificationObserver observer;
2612 service->UninstallExtension(extension->id(), false);
2613 // The extension unload notification should have been sent synchronously
2614 // with the uninstall. Just to be safe, check that it was received.
2615 *success = observer.did_receive_unload_notification();
2616 }
2617}
2618
2619void AutomationProvider::EnableExtension(int extension_handle,
2620 IPC::Message* reply_message) {
2621 Extension* extension = GetDisabledExtension(extension_handle);
2622 ExtensionsService* service = profile_->GetExtensionsService();
2623 ExtensionProcessManager* manager = profile_->GetExtensionProcessManager();
2624 // Only enable if this extension is disabled.
2625 if (extension && service && manager) {
2626 // The observer will delete itself when done.
2627 new ExtensionReadyNotificationObserver(
2628 manager,
2629 this,
2630 AutomationMsg_EnableExtension::ID,
2631 reply_message);
2632 service->EnableExtension(extension->id());
2633 } else {
2634 AutomationMsg_EnableExtension::WriteReplyParams(reply_message, false);
2635 Send(reply_message);
2636 }
2637}
2638
2639void AutomationProvider::DisableExtension(int extension_handle,
2640 bool* success) {
2641 *success = false;
2642 Extension* extension = GetEnabledExtension(extension_handle);
2643 ExtensionsService* service = profile_->GetExtensionsService();
2644 if (extension && service) {
2645 ExtensionUnloadNotificationObserver observer;
2646 service->DisableExtension(extension->id());
2647 // The extension unload notification should have been sent synchronously
2648 // with the disable. Just to be safe, check that it was received.
2649 *success = observer.did_receive_unload_notification();
2650 }
2651}
2652
2653void AutomationProvider::ExecuteExtensionActionInActiveTabAsync(
2654 int extension_handle, int browser_handle,
2655 IPC::Message* reply_message) {
2656 bool success = false;
2657 Extension* extension = GetEnabledExtension(extension_handle);
2658 ExtensionsService* service = profile_->GetExtensionsService();
2659 ExtensionMessageService* message_service =
2660 profile_->GetExtensionMessageService();
2661 Browser* browser = browser_tracker_->GetResource(browser_handle);
2662 if (extension && service && message_service && browser) {
2663 int tab_id = ExtensionTabUtil::GetTabId(browser->GetSelectedTabContents());
2664 if (extension->page_action()) {
2665 ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted(
2666 browser->profile(), extension->id(), "action", tab_id, "", 1);
2667 success = true;
2668 } else if (extension->browser_action()) {
2669 ExtensionBrowserEventRouter::GetInstance()->BrowserActionExecuted(
2670 browser->profile(), extension->id(), browser);
2671 success = true;
2672 }
2673 }
2674 AutomationMsg_ExecuteExtensionActionInActiveTabAsync::WriteReplyParams(
2675 reply_message, success);
2676 Send(reply_message);
2677}
2678
2679void AutomationProvider::MoveExtensionBrowserAction(
2680 int extension_handle, int index, bool* success) {
2681 *success = false;
2682 Extension* extension = GetEnabledExtension(extension_handle);
2683 ExtensionsService* service = profile_->GetExtensionsService();
2684 if (extension && service) {
2685 ExtensionToolbarModel* toolbar = service->toolbar_model();
2686 if (toolbar) {
2687 if (index >= 0 && index < static_cast<int>(toolbar->size())) {
2688 toolbar->MoveBrowserAction(extension, index);
2689 *success = true;
2690 } else {
2691 DLOG(WARNING) << "Attempted to move browser action to invalid index.";
2692 }
2693 }
2694 }
2695}
2696
2697void AutomationProvider::GetExtensionProperty(
2698 int extension_handle,
2699 AutomationMsg_ExtensionProperty type,
2700 bool* success,
2701 std::string* value) {
2702 *success = false;
2703 Extension* extension = GetExtension(extension_handle);
2704 ExtensionsService* service = profile_->GetExtensionsService();
2705 if (extension && service) {
2706 ExtensionToolbarModel* toolbar = service->toolbar_model();
2707 int found_index = -1;
2708 int index = 0;
2709 switch (type) {
2710 case AUTOMATION_MSG_EXTENSION_ID:
2711 *value = extension->id();
2712 *success = true;
2713 break;
2714 case AUTOMATION_MSG_EXTENSION_NAME:
2715 *value = extension->name();
2716 *success = true;
2717 break;
2718 case AUTOMATION_MSG_EXTENSION_VERSION:
2719 *value = extension->VersionString();
2720 *success = true;
2721 break;
2722 case AUTOMATION_MSG_EXTENSION_BROWSER_ACTION_INDEX:
2723 if (toolbar) {
2724 for (ExtensionList::const_iterator iter = toolbar->begin();
2725 iter != toolbar->end(); iter++) {
2726 // Skip this extension if we are in incognito mode
2727 // and it is not incognito-enabled.
2728 if (profile_->IsOffTheRecord() &&
2729 !service->IsIncognitoEnabled(*iter))
2730 continue;
2731 if (*iter == extension) {
2732 found_index = index;
2733 break;
2734 }
2735 index++;
2736 }
[email protected]528c56d2010-07-30 19:28:442737 *value = base::IntToString(found_index);
[email protected]790788ac2010-04-06 17:52:192738 *success = true;
2739 }
2740 break;
2741 default:
2742 LOG(WARNING) << "Trying to get undefined extension property";
2743 break;
2744 }
2745 }
2746}
2747
[email protected]673fd2c02010-02-04 23:10:002748void AutomationProvider::SaveAsAsync(int tab_handle) {
2749 NavigationController* tab = NULL;
2750 TabContents* tab_contents = GetTabContentsForHandle(tab_handle, &tab);
2751 if (tab_contents)
2752 tab_contents->OnSavePage();
2753}
[email protected]7dad3d5f2010-03-04 00:27:012754
2755void AutomationProvider::SetContentSetting(
2756 int handle,
2757 const std::string& host,
2758 ContentSettingsType content_type,
2759 ContentSetting setting,
2760 bool* success) {
2761 *success = false;
2762 if (browser_tracker_->ContainsHandle(handle)) {
2763 Browser* browser = browser_tracker_->GetResource(handle);
2764 HostContentSettingsMap* map =
2765 browser->profile()->GetHostContentSettingsMap();
2766 if (host.empty()) {
2767 map->SetDefaultContentSetting(content_type, setting);
2768 } else {
[email protected]0314ae02010-04-08 09:18:292769 map->SetContentSetting(HostContentSettingsMap::Pattern(host),
[email protected]ca352452010-08-06 11:14:092770 content_type, "", setting);
[email protected]7dad3d5f2010-03-04 00:27:012771 }
2772 *success = true;
2773 }
2774}
[email protected]cc824372010-03-31 15:33:012775
[email protected]d7e5525d2010-04-20 14:37:092776void AutomationProvider::ResetToDefaultTheme() {
2777 profile_->ClearTheme();
2778}