blob: 67d4af2d98b79086e233bd6dbf1d51674cbb165d [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]58580352010-10-26 04:07:5011#include "base/debug/trace_event.h"
[email protected]7060bb292010-06-24 00:52:4912#include "base/file_path.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]5fac9622009-02-04 21:49:3816#include "base/message_loop.h"
initial.commit09911bf2008-07-26 23:55:2917#include "base/path_service.h"
[email protected]201b2732009-11-13 18:57:4618#include "base/process_util.h"
[email protected]f44265b2009-05-19 18:52:5019#include "base/stl_util-inl.h"
[email protected]4c4d8d22009-03-04 05:29:2720#include "base/string_util.h"
[email protected]9eaa18e2010-06-29 20:51:0121#include "base/task.h"
[email protected]34b99632011-01-01 01:01:0622#include "base/threading/thread.h"
[email protected]528c56d2010-07-30 19:28:4423#include "base/string_number_conversions.h"
[email protected]6d8ffc9f2010-03-12 18:27:5324#include "base/utf_string_conversions.h"
[email protected]a7eee32f2009-05-22 18:08:1725#include "base/values.h"
[email protected]9eaa18e2010-06-29 20:51:0126#include "base/waitable_event.h"
[email protected]1a3aba82010-11-08 23:52:5427#include "chrome/app/chrome_command_ids.h"
[email protected]55846ad842010-07-09 18:22:5628#include "chrome/browser/autofill/autofill_manager.h"
[email protected]679082052010-07-21 21:30:1329#include "chrome/browser/automation/automation_autocomplete_edit_tracker.h"
30#include "chrome/browser/automation/automation_browser_tracker.h"
[email protected]790788ac2010-04-06 17:52:1931#include "chrome/browser/automation/automation_extension_tracker.h"
initial.commit09911bf2008-07-26 23:55:2932#include "chrome/browser/automation/automation_provider_list.h"
[email protected]e12de87e2009-08-28 00:02:0833#include "chrome/browser/automation/automation_provider_observers.h"
[email protected]679082052010-07-21 21:30:1334#include "chrome/browser/automation/automation_resource_message_filter.h"
35#include "chrome/browser/automation/automation_tab_tracker.h"
36#include "chrome/browser/automation/automation_window_tracker.h"
[email protected]f44265b2009-05-19 18:52:5037#include "chrome/browser/automation/extension_port_container.h"
[email protected]12802702010-07-09 19:43:0938#include "chrome/browser/autocomplete/autocomplete_edit.h"
[email protected]c65e2f152010-10-14 15:30:4039#include "chrome/browser/blocked_content_container.h"
[email protected]6d8ffc9f2010-03-12 18:27:5340#include "chrome/browser/bookmarks/bookmark_model.h"
41#include "chrome/browser/bookmarks/bookmark_storage.h"
[email protected]ef413ca2010-05-25 21:09:1442#include "chrome/browser/browser_list.h"
[email protected]5c238752009-06-13 10:29:0743#include "chrome/browser/browser_process.h"
[email protected]ed7e6dd2010-10-12 02:02:4544#include "chrome/browser/browser_thread.h"
[email protected]f3e99e32008-07-30 04:48:3945#include "chrome/browser/browser_window.h"
[email protected]bc73b4e52010-03-26 04:16:2046#include "chrome/browser/browsing_data_remover.h"
[email protected]f83f9102010-05-04 17:01:0547#include "chrome/browser/character_encoding.h"
[email protected]9d01a6a2010-11-30 12:03:3348#include "chrome/browser/content_settings/host_content_settings_map.h"
initial.commit09911bf2008-07-26 23:55:2949#include "chrome/browser/dom_operation_notification_details.h"
[email protected]d9f9b792009-06-24 13:17:1250#include "chrome/browser/debugger/devtools_manager.h"
[email protected]6c69796d2010-07-16 21:41:1651#include "chrome/browser/download/download_item.h"
[email protected]59560e0b2009-06-04 03:30:2252#include "chrome/browser/download/download_shelf.h"
[email protected]f83f9102010-05-04 17:01:0553#include "chrome/browser/download/save_package.h"
[email protected]d11c8e92009-10-20 23:26:4054#include "chrome/browser/extensions/crx_installer.h"
[email protected]790788ac2010-04-06 17:52:1955#include "chrome/browser/extensions/extension_browser_event_router.h"
[email protected]ef413ca2010-05-25 21:09:1456#include "chrome/browser/extensions/extension_host.h"
[email protected]d11c8e92009-10-20 23:26:4057#include "chrome/browser/extensions/extension_install_ui.h"
[email protected]a9024892009-06-16 23:13:5558#include "chrome/browser/extensions/extension_message_service.h"
[email protected]790788ac2010-04-06 17:52:1959#include "chrome/browser/extensions/extension_tabs_module.h"
60#include "chrome/browser/extensions/extension_toolbar_model.h"
[email protected]eaa7dd182010-12-14 11:09:0061#include "chrome/browser/extensions/extension_service.h"
[email protected]8cb5d5b2010-02-09 11:36:1662#include "chrome/browser/extensions/user_script_master.h"
[email protected]c5aa5322010-07-15 19:00:0763#include "chrome/browser/importer/importer.h"
64#include "chrome/browser/importer/importer_data_types.h"
[email protected]0ac83682010-01-22 17:46:2765#include "chrome/browser/io_thread.h"
[email protected]f732c1e2009-07-30 15:48:5366#include "chrome/browser/net/url_request_mock_util.h"
[email protected]14a000d2010-04-29 21:44:2467#include "chrome/browser/platform_util.h"
[email protected]37858e52010-08-26 00:22:0268#include "chrome/browser/prefs/pref_service.h"
[email protected]f83f9102010-05-04 17:01:0569#include "chrome/browser/printing/print_job.h"
[email protected]8ecad5e2010-12-02 21:18:3370#include "chrome/browser/profiles/profile_manager.h"
[email protected]1db6ff152009-10-12 15:32:0771#include "chrome/browser/renderer_host/render_process_host.h"
[email protected]6524b5f92009-01-22 17:48:2572#include "chrome/browser/renderer_host/render_view_host.h"
[email protected]3b073b22009-01-16 03:29:0373#include "chrome/browser/ssl/ssl_manager.h"
74#include "chrome/browser/ssl/ssl_blocking_page.h"
[email protected]b5558cf22010-07-12 17:30:0675#include "chrome/browser/tab_contents/infobar_delegate.h"
[email protected]8982ab12010-08-31 17:39:4276#include "chrome/browser/tab_contents/navigation_entry.h"
[email protected]57c6a652009-05-04 07:58:3477#include "chrome/browser/tab_contents/tab_contents.h"
[email protected]81af9392009-04-21 02:37:4578#include "chrome/browser/tab_contents/tab_contents_view.h"
[email protected]38b5a3852010-07-21 06:49:5279#include "chrome/browser/translate/translate_infobar_delegate.h"
[email protected]1caa1522010-12-01 20:23:3580#include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h"
81#include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h"
[email protected]45300ad42010-12-02 15:51:1482#include "chrome/browser/ui/find_bar/find_bar.h"
83#include "chrome/browser/ui/find_bar/find_bar_controller.h"
84#include "chrome/browser/ui/find_bar/find_notification_details.h"
[email protected]8ecad5e2010-12-02 21:18:3385#include "chrome/browser/ui/login/login_prompt.h"
[email protected]6a3ec2312010-12-02 19:30:1986#include "chrome/browser/ui/omnibox/location_bar.h"
[email protected]a7eee32f2009-05-22 18:08:1787#include "chrome/common/automation_constants.h"
[email protected]a8ba6362010-11-10 20:02:2588#include "chrome/common/automation_messages.h"
[email protected]a9ff2c02010-05-13 17:33:0589#include "chrome/common/chrome_constants.h"
initial.commit09911bf2008-07-26 23:55:2990#include "chrome/common/chrome_paths.h"
[email protected]c984d9f2010-07-20 20:52:2091#include "chrome/common/chrome_switches.h"
[email protected]1eeb5e02010-07-20 23:02:1192#include "chrome/common/chrome_version_info.h"
[email protected]790788ac2010-04-06 17:52:1993#include "chrome/common/extensions/extension.h"
[email protected]a7eee32f2009-05-22 18:08:1794#include "chrome/common/json_value_serializer.h"
[email protected]68d2a05f2010-05-07 21:39:5595#include "chrome/common/net/url_request_context_getter.h"
[email protected]1bb5f892009-10-06 01:44:5796#include "chrome/common/pref_names.h"
[email protected]f5bf8ccf2010-02-05 18:19:2597#include "chrome/common/url_constants.h"
[email protected]1bb5f892009-10-06 01:44:5798#include "chrome/test/automation/tab_proxy.h"
[email protected]a7eee32f2009-05-22 18:08:1799#include "net/proxy/proxy_service.h"
100#include "net/proxy/proxy_config_service_fixed.h"
[email protected]319d9e6f2009-02-18 19:47:21101#include "net/url_request/url_request_context.h"
[email protected]1b5a48c2010-04-29 23:08:30102#include "chrome/browser/automation/ui_controls.h"
[email protected]9a08bcf2009-08-12 19:56:28103#include "views/event.h"
[email protected]5bcfe1672010-07-16 20:51:57104#include "webkit/glue/password_form.h"
initial.commit09911bf2008-07-26 23:55:29105
[email protected]de246f52009-02-25 18:25:45106#if defined(OS_WIN)
[email protected]4bdde602010-06-16 03:17:35107#include "chrome/browser/external_tab_container_win.h"
[email protected]de246f52009-02-25 18:25:45108#endif // defined(OS_WIN)
109
[email protected]e1acf6f2008-10-27 20:43:33110using base::Time;
111
initial.commit09911bf2008-07-26 23:55:29112AutomationProvider::AutomationProvider(Profile* profile)
[email protected]c97080f2010-08-20 20:42:48113 : profile_(profile),
[email protected]dfe0deb2010-12-23 20:40:16114 reply_message_(NULL),
115 is_connected_(false),
116 initial_loads_complete_(false) {
[email protected]a872ea1f2010-08-11 04:45:33117 TRACE_EVENT_BEGIN("AutomationProvider::AutomationProvider", 0, "");
118
initial.commit09911bf2008-07-26 23:55:29119 browser_tracker_.reset(new AutomationBrowserTracker(this));
[email protected]790788ac2010-04-06 17:52:19120 extension_tracker_.reset(new AutomationExtensionTracker(this));
initial.commit09911bf2008-07-26 23:55:29121 tab_tracker_.reset(new AutomationTabTracker(this));
[email protected]0e9f4ee2009-04-08 01:44:20122 window_tracker_.reset(new AutomationWindowTracker(this));
initial.commit09911bf2008-07-26 23:55:29123 autocomplete_edit_tracker_.reset(
124 new AutomationAutocompleteEditTracker(this));
initial.commit09911bf2008-07-26 23:55:29125 new_tab_ui_load_observer_.reset(new NewTabUILoadObserver(this));
[email protected]4203e6b2010-11-12 21:41:50126 dom_operation_observer_.reset(new DomOperationMessageSender(this));
[email protected]84abba62009-10-07 17:01:44127 metric_event_duration_observer_.reset(new MetricEventDurationObserver());
[email protected]790788ac2010-04-06 17:52:19128 extension_test_result_observer_.reset(
129 new ExtensionTestResultNotificationObserver(this));
[email protected]528211a2010-01-14 15:25:13130 g_browser_process->AddRefModule();
[email protected]a872ea1f2010-08-11 04:45:33131
132 TRACE_EVENT_END("AutomationProvider::AutomationProvider", 0, "");
initial.commit09911bf2008-07-26 23:55:29133}
134
135AutomationProvider::~AutomationProvider() {
[email protected]f44265b2009-05-19 18:52:50136 STLDeleteContainerPairSecondPointers(port_containers_.begin(),
137 port_containers_.end());
138 port_containers_.clear();
139
[email protected]0da050b92008-08-19 19:29:47140 // Make sure that any outstanding NotificationObservers also get destroyed.
141 ObserverList<NotificationObserver>::Iterator it(notification_observer_list_);
[email protected]5a52f162008-08-27 04:15:31142 NotificationObserver* observer;
[email protected]0da050b92008-08-19 19:29:47143 while ((observer = it.GetNext()) != NULL)
144 delete observer;
[email protected]528211a2010-01-14 15:25:13145
146 if (channel_.get()) {
147 channel_->Close();
148 }
149 g_browser_process->ReleaseModule();
initial.commit09911bf2008-07-26 23:55:29150}
151
[email protected]dfe0deb2010-12-23 20:40:16152bool AutomationProvider::InitializeChannel(const std::string& channel_id) {
153 TRACE_EVENT_BEGIN("AutomationProvider::InitializeChannel", 0, "");
154
155 std::string effective_channel_id = channel_id;
156
157 // If the channel_id starts with kNamedInterfacePrefix, create a named IPC
158 // server and listen on it, else connect as client to an existing IPC server
159 bool use_named_interface =
160 channel_id.find(automation::kNamedInterfacePrefix) == 0;
161 if (use_named_interface) {
162 effective_channel_id = channel_id.substr(
163 strlen(automation::kNamedInterfacePrefix));
164 if (effective_channel_id.length() <= 0)
165 return false;
166 }
[email protected]a872ea1f2010-08-11 04:45:33167
[email protected]b58dd3e2010-10-12 21:44:35168 if (!automation_resource_message_filter_.get()) {
169 automation_resource_message_filter_ = new AutomationResourceMessageFilter;
170 }
171
[email protected]dfe0deb2010-12-23 20:40:16172 channel_.reset(new IPC::SyncChannel(
173 effective_channel_id,
174 use_named_interface ? IPC::Channel::MODE_NAMED_SERVER
175 : IPC::Channel::MODE_CLIENT,
176 this,
177 g_browser_process->io_thread()->message_loop(),
178 true, g_browser_process->shutdown_event()));
[email protected]4b580bf2010-12-02 19:16:07179 channel_->AddFilter(automation_resource_message_filter_);
[email protected]c6cb1992009-04-13 16:45:29180
[email protected]dfe0deb2010-12-23 20:40:16181 TRACE_EVENT_END("AutomationProvider::InitializeChannel", 0, "");
[email protected]a872ea1f2010-08-11 04:45:33182
[email protected]dfe0deb2010-12-23 20:40:16183 return true;
initial.commit09911bf2008-07-26 23:55:29184}
185
[email protected]22a91282010-10-26 04:37:20186std::string AutomationProvider::GetProtocolVersion() {
187 chrome::VersionInfo version_info;
188 return version_info.Version().c_str();
189}
190
initial.commit09911bf2008-07-26 23:55:29191void AutomationProvider::SetExpectedTabCount(size_t expected_tabs) {
[email protected]dfe0deb2010-12-23 20:40:16192 if (expected_tabs == 0)
193 OnInitialLoadsComplete();
194 else
[email protected]713a5f22010-12-11 11:37:41195 initial_load_observer_.reset(new InitialLoadObserver(expected_tabs, this));
[email protected]dfe0deb2010-12-23 20:40:16196}
197
198void AutomationProvider::OnInitialLoadsComplete() {
199 initial_loads_complete_ = true;
200 if (is_connected_)
[email protected]f5494d42010-12-23 22:15:34201 Send(new AutomationMsg_InitialLoadsComplete());
initial.commit09911bf2008-07-26 23:55:29202}
203
204NotificationObserver* AutomationProvider::AddNavigationStatusListener(
[email protected]2e028a082009-08-19 20:32:58205 NavigationController* tab, IPC::Message* reply_message,
[email protected]7dad3d5f2010-03-04 00:27:01206 int number_of_navigations, bool include_current_navigation) {
initial.commit09911bf2008-07-26 23:55:29207 NotificationObserver* observer =
[email protected]2e028a082009-08-19 20:32:58208 new NavigationNotificationObserver(tab, this, reply_message,
[email protected]7dad3d5f2010-03-04 00:27:01209 number_of_navigations,
210 include_current_navigation);
initial.commit09911bf2008-07-26 23:55:29211
[email protected]71f65dd2009-02-11 19:14:56212 notification_observer_list_.AddObserver(observer);
initial.commit09911bf2008-07-26 23:55:29213 return observer;
214}
215
[email protected]faf2ee42010-05-11 14:26:17216void AutomationProvider::RemoveNavigationStatusListener(
217 NotificationObserver* obs) {
218 notification_observer_list_.RemoveObserver(obs);
219}
220
initial.commit09911bf2008-07-26 23:55:29221NotificationObserver* AutomationProvider::AddTabStripObserver(
[email protected]1c58a5c2009-05-21 18:47:14222 Browser* parent,
223 IPC::Message* reply_message) {
[email protected]71f65dd2009-02-11 19:14:56224 NotificationObserver* observer =
[email protected]1c58a5c2009-05-21 18:47:14225 new TabAppendedNotificationObserver(parent, this, reply_message);
initial.commit09911bf2008-07-26 23:55:29226 notification_observer_list_.AddObserver(observer);
227
228 return observer;
229}
230
[email protected]faf2ee42010-05-11 14:26:17231void AutomationProvider::RemoveTabStripObserver(NotificationObserver* obs) {
initial.commit09911bf2008-07-26 23:55:29232 notification_observer_list_.RemoveObserver(obs);
233}
234
235void AutomationProvider::AddLoginHandler(NavigationController* tab,
236 LoginHandler* handler) {
237 login_handler_map_[tab] = handler;
238}
239
240void AutomationProvider::RemoveLoginHandler(NavigationController* tab) {
241 DCHECK(login_handler_map_[tab]);
242 login_handler_map_.erase(tab);
243}
244
[email protected]f44265b2009-05-19 18:52:50245void AutomationProvider::AddPortContainer(ExtensionPortContainer* port) {
246 int port_id = port->port_id();
247 DCHECK_NE(-1, port_id);
248 DCHECK(port_containers_.find(port_id) == port_containers_.end());
249
250 port_containers_[port_id] = port;
251}
252
253void AutomationProvider::RemovePortContainer(ExtensionPortContainer* port) {
254 int port_id = port->port_id();
255 DCHECK_NE(-1, port_id);
256
257 PortContainerMap::iterator it = port_containers_.find(port_id);
258 DCHECK(it != port_containers_.end());
259
260 if (it != port_containers_.end()) {
261 delete it->second;
262 port_containers_.erase(it);
263 }
264}
265
266ExtensionPortContainer* AutomationProvider::GetPortContainer(
267 int port_id) const {
268 PortContainerMap::const_iterator it = port_containers_.find(port_id);
269 if (it == port_containers_.end())
270 return NULL;
271
272 return it->second;
273}
274
initial.commit09911bf2008-07-26 23:55:29275int AutomationProvider::GetIndexForNavigationController(
276 const NavigationController* controller, const Browser* parent) const {
277 DCHECK(parent);
[email protected]902cdf772009-05-06 15:08:12278 return parent->GetIndexOfController(controller);
initial.commit09911bf2008-07-26 23:55:29279}
280
[email protected]9adb9692010-10-29 23:14:02281int AutomationProvider::AddExtension(const Extension* extension) {
[email protected]790788ac2010-04-06 17:52:19282 DCHECK(extension);
283 return extension_tracker_->Add(extension);
284}
285
[email protected]e51cb6f2010-09-02 23:51:45286// TODO(phajdan.jr): move to TestingAutomationProvider.
287DictionaryValue* AutomationProvider::GetDictionaryFromDownloadItem(
288 const DownloadItem* download) {
289 std::map<DownloadItem::DownloadState, std::string> state_to_string;
290 state_to_string[DownloadItem::IN_PROGRESS] = std::string("IN_PROGRESS");
291 state_to_string[DownloadItem::CANCELLED] = std::string("CANCELLED");
292 state_to_string[DownloadItem::REMOVING] = std::string("REMOVING");
293 state_to_string[DownloadItem::COMPLETE] = std::string("COMPLETE");
294
295 std::map<DownloadItem::SafetyState, std::string> safety_state_to_string;
296 safety_state_to_string[DownloadItem::SAFE] = std::string("SAFE");
297 safety_state_to_string[DownloadItem::DANGEROUS] = std::string("DANGEROUS");
298 safety_state_to_string[DownloadItem::DANGEROUS_BUT_VALIDATED] =
299 std::string("DANGEROUS_BUT_VALIDATED");
300
301 DictionaryValue* dl_item_value = new DictionaryValue;
302 dl_item_value->SetInteger("id", static_cast<int>(download->id()));
303 dl_item_value->SetString("url", download->url().spec());
304 dl_item_value->SetString("referrer_url", download->referrer_url().spec());
[email protected]44b94b82010-11-08 20:49:18305 dl_item_value->SetString("file_name",
306 download->GetFileNameToReportUser().value());
307 dl_item_value->SetString("full_path",
308 download->GetTargetFilePath().value());
[email protected]e51cb6f2010-09-02 23:51:45309 dl_item_value->SetBoolean("is_paused", download->is_paused());
310 dl_item_value->SetBoolean("open_when_complete",
311 download->open_when_complete());
312 dl_item_value->SetBoolean("is_extension_install",
313 download->is_extension_install());
314 dl_item_value->SetBoolean("is_temporary", download->is_temporary());
315 dl_item_value->SetBoolean("is_otr", download->is_otr()); // off-the-record
316 dl_item_value->SetString("state", state_to_string[download->state()]);
317 dl_item_value->SetString("safety_state",
318 safety_state_to_string[download->safety_state()]);
319 dl_item_value->SetInteger("PercentComplete", download->PercentComplete());
320
321 return dl_item_value;
322}
323
[email protected]9adb9692010-10-29 23:14:02324const Extension* AutomationProvider::GetExtension(int extension_handle) {
[email protected]790788ac2010-04-06 17:52:19325 return extension_tracker_->GetResource(extension_handle);
326}
327
[email protected]9adb9692010-10-29 23:14:02328const Extension* AutomationProvider::GetEnabledExtension(int extension_handle) {
329 const Extension* extension =
330 extension_tracker_->GetResource(extension_handle);
[email protected]eaa7dd182010-12-14 11:09:00331 ExtensionService* service = profile_->GetExtensionService();
[email protected]790788ac2010-04-06 17:52:19332 if (extension && service &&
333 service->GetExtensionById(extension->id(), false))
334 return extension;
335 return NULL;
336}
337
[email protected]9adb9692010-10-29 23:14:02338const Extension* AutomationProvider::GetDisabledExtension(
339 int extension_handle) {
340 const Extension* extension =
341 extension_tracker_->GetResource(extension_handle);
[email protected]eaa7dd182010-12-14 11:09:00342 ExtensionService* service = profile_->GetExtensionService();
[email protected]790788ac2010-04-06 17:52:19343 if (extension && service &&
344 service->GetExtensionById(extension->id(), true) &&
345 !service->GetExtensionById(extension->id(), false))
346 return extension;
347 return NULL;
348}
349
[email protected]dfe0deb2010-12-23 20:40:16350void AutomationProvider::OnChannelConnected(int pid) {
351 is_connected_ = true;
352 LOG(INFO) << "Testing channel connected, sending hello message";
353
354 // Send a hello message with our current automation protocol version.
355 chrome::VersionInfo version_info;
[email protected]f5494d42010-12-23 22:15:34356 channel_->Send(new AutomationMsg_Hello(version_info.Version()));
[email protected]dfe0deb2010-12-23 20:40:16357 if (initial_loads_complete_)
[email protected]f5494d42010-12-23 22:15:34358 Send(new AutomationMsg_InitialLoadsComplete());
[email protected]dfe0deb2010-12-23 20:40:16359}
360
[email protected]a95986a82010-12-24 06:19:28361bool AutomationProvider::OnMessageReceived(const IPC::Message& message) {
362 bool handled = true;
initial.commit09911bf2008-07-26 23:55:29363 IPC_BEGIN_MESSAGE_MAP(AutomationProvider, message)
[email protected]1b5a48c2010-04-29 23:08:30364#if !defined(OS_MACOSX)
[email protected]71f65dd2009-02-11 19:14:56365 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WindowDrag,
366 WindowSimulateDrag)
[email protected]1b5a48c2010-04-29 23:08:30367#endif // !defined(OS_MACOSX)
initial.commit09911bf2008-07-26 23:55:29368 IPC_MESSAGE_HANDLER(AutomationMsg_HandleUnused, HandleUnused)
[email protected]a95986a82010-12-24 06:19:28369 IPC_MESSAGE_HANDLER(AutomationMsg_SetProxyConfig, SetProxyConfig)
[email protected]d301c952009-07-13 15:02:41370 IPC_MESSAGE_HANDLER(AutomationMsg_PrintAsync, PrintAsync)
[email protected]1c58a5c2009-05-21 18:47:14371 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_Find, HandleFindRequest)
[email protected]1c58a5c2009-05-21 18:47:14372 IPC_MESSAGE_HANDLER(AutomationMsg_OverrideEncoding, OverrideEncoding)
[email protected]f7a68432009-07-29 23:18:19373 IPC_MESSAGE_HANDLER(AutomationMsg_SelectAll, SelectAll)
374 IPC_MESSAGE_HANDLER(AutomationMsg_Cut, Cut)
375 IPC_MESSAGE_HANDLER(AutomationMsg_Copy, Copy)
376 IPC_MESSAGE_HANDLER(AutomationMsg_Paste, Paste)
377 IPC_MESSAGE_HANDLER(AutomationMsg_ReloadAsync, ReloadAsync)
378 IPC_MESSAGE_HANDLER(AutomationMsg_StopAsync, StopAsync)
[email protected]1bb5f892009-10-06 01:44:57379 IPC_MESSAGE_HANDLER(AutomationMsg_SetPageFontSize, OnSetPageFontSize)
[email protected]d11c8e92009-10-20 23:26:40380 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_InstallExtension,
381 InstallExtension)
382 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_LoadExpandedExtension,
383 LoadExpandedExtension)
[email protected]a1e62d12010-03-16 02:18:43384 IPC_MESSAGE_HANDLER(AutomationMsg_GetEnabledExtensions,
385 GetEnabledExtensions)
[email protected]790788ac2010-04-06 17:52:19386 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_WaitForExtensionTestResult,
387 WaitForExtensionTestResult)
388 IPC_MESSAGE_HANDLER_DELAY_REPLY(
389 AutomationMsg_InstallExtensionAndGetHandle,
390 InstallExtensionAndGetHandle)
391 IPC_MESSAGE_HANDLER(AutomationMsg_UninstallExtension,
392 UninstallExtension)
393 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_EnableExtension,
394 EnableExtension)
395 IPC_MESSAGE_HANDLER(AutomationMsg_DisableExtension,
396 DisableExtension)
397 IPC_MESSAGE_HANDLER_DELAY_REPLY(
398 AutomationMsg_ExecuteExtensionActionInActiveTabAsync,
399 ExecuteExtensionActionInActiveTabAsync)
400 IPC_MESSAGE_HANDLER(AutomationMsg_MoveExtensionBrowserAction,
401 MoveExtensionBrowserAction)
402 IPC_MESSAGE_HANDLER(AutomationMsg_GetExtensionProperty,
403 GetExtensionProperty)
[email protected]673fd2c02010-02-04 23:10:00404 IPC_MESSAGE_HANDLER(AutomationMsg_SaveAsAsync, SaveAsAsync)
[email protected]bc73b4e52010-03-26 04:16:20405 IPC_MESSAGE_HANDLER(AutomationMsg_RemoveBrowsingData, RemoveBrowsingData)
[email protected]52415f842010-06-10 21:51:52406#if defined(OS_WIN)
407 // These are for use with external tabs.
408 IPC_MESSAGE_HANDLER(AutomationMsg_CreateExternalTab, CreateExternalTab)
409 IPC_MESSAGE_HANDLER(AutomationMsg_ProcessUnhandledAccelerator,
410 ProcessUnhandledAccelerator)
411 IPC_MESSAGE_HANDLER(AutomationMsg_SetInitialFocus, SetInitialFocus)
412 IPC_MESSAGE_HANDLER(AutomationMsg_TabReposition, OnTabReposition)
413 IPC_MESSAGE_HANDLER(AutomationMsg_ForwardContextMenuCommandToChrome,
414 OnForwardContextMenuCommandToChrome)
415 IPC_MESSAGE_HANDLER(AutomationMsg_NavigateInExternalTab,
416 NavigateInExternalTab)
417 IPC_MESSAGE_HANDLER(AutomationMsg_NavigateExternalTabAtIndex,
418 NavigateExternalTabAtIndex)
419 IPC_MESSAGE_HANDLER(AutomationMsg_ConnectExternalTab, ConnectExternalTab)
420 IPC_MESSAGE_HANDLER(AutomationMsg_SetEnableExtensionAutomation,
421 SetEnableExtensionAutomation)
422 IPC_MESSAGE_HANDLER(AutomationMsg_HandleMessageFromExternalHost,
423 OnMessageFromExternalHost)
[email protected]bdd5a9c92010-06-14 18:21:00424 IPC_MESSAGE_HANDLER(AutomationMsg_BrowserMove, OnBrowserMoved)
[email protected]d9d8f0c2010-09-17 21:47:16425 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_RunUnloadHandlers,
426 OnRunUnloadHandlers)
[email protected]7f860dd82010-08-09 23:18:05427 IPC_MESSAGE_HANDLER(AutomationMsg_SetZoomLevel, OnSetZoomLevel)
[email protected]bdd5a9c92010-06-14 18:21:00428#endif // defined(OS_WIN)
429#if defined(OS_CHROMEOS)
430 IPC_MESSAGE_HANDLER_DELAY_REPLY(AutomationMsg_LoginWithUserAndPass,
431 LoginWithUserAndPass)
432#endif // defined(OS_CHROMEOS)
[email protected]a95986a82010-12-24 06:19:28433 IPC_MESSAGE_UNHANDLED(handled = false;OnUnhandledMessage())
initial.commit09911bf2008-07-26 23:55:29434 IPC_END_MESSAGE_MAP()
[email protected]a95986a82010-12-24 06:19:28435 return handled;
initial.commit09911bf2008-07-26 23:55:29436}
437
[email protected]89c75df32010-09-14 16:45:34438void AutomationProvider::OnUnhandledMessage() {
439 // We should not hang here. Print a message to indicate what's going on,
440 // and disconnect the channel to notify the caller about the error
441 // in a way it can't ignore, and make any further attempts to send
442 // messages fail fast.
443 LOG(ERROR) << "AutomationProvider received a message it can't handle. "
444 << "Please make sure that you use switches::kTestingChannelID "
445 << "for test code (TestingAutomationProvider), and "
446 << "switches::kAutomationClientChannelID for everything else "
447 << "(like ChromeFrame). Closing the automation channel.";
448 channel_->Close();
449}
450
[email protected]fc2e0872009-08-21 22:14:41451// This task just adds another task to the event queue. This is useful if
452// you want to ensure that any tasks added to the event queue after this one
453// have already been processed by the time |task| is run.
454class InvokeTaskLaterTask : public Task {
455 public:
456 explicit InvokeTaskLaterTask(Task* task) : task_(task) {}
457 virtual ~InvokeTaskLaterTask() {}
458
459 virtual void Run() {
460 MessageLoop::current()->PostTask(FROM_HERE, task_);
461 }
462
463 private:
464 Task* task_;
465
466 DISALLOW_COPY_AND_ASSIGN(InvokeTaskLaterTask);
467};
468
initial.commit09911bf2008-07-26 23:55:29469void AutomationProvider::HandleUnused(const IPC::Message& message, int handle) {
470 if (window_tracker_->ContainsHandle(handle)) {
471 window_tracker_->Remove(window_tracker_->GetResource(handle));
472 }
473}
474
475void AutomationProvider::OnChannelError() {
[email protected]5fb40dc2010-10-22 20:35:27476 VLOG(1) << "AutomationProxy went away, shutting down app.";
[email protected]295039bd2008-08-15 04:32:57477 AutomationProviderList::GetInstance()->RemoveProvider(this);
initial.commit09911bf2008-07-26 23:55:29478}
479
initial.commit09911bf2008-07-26 23:55:29480bool AutomationProvider::Send(IPC::Message* msg) {
[email protected]295039bd2008-08-15 04:32:57481 DCHECK(channel_.get());
482 return channel_->Send(msg);
initial.commit09911bf2008-07-26 23:55:29483}
484
485Browser* AutomationProvider::FindAndActivateTab(
486 NavigationController* controller) {
487 int tab_index;
488 Browser* browser = Browser::GetBrowserForController(controller, &tab_index);
489 if (browser)
490 browser->SelectTabContentsAt(tab_index, true);
491
492 return browser;
493}
494
[email protected]4f999132009-03-31 18:08:40495void AutomationProvider::HandleFindRequest(
496 int handle,
497 const AutomationMsg_Find_Params& params,
498 IPC::Message* reply_message) {
initial.commit09911bf2008-07-26 23:55:29499 if (!tab_tracker_->ContainsHandle(handle)) {
[email protected]f9e3c522010-10-08 00:41:26500 AutomationMsg_Find::WriteReplyParams(reply_message, -1, -1);
[email protected]71f65dd2009-02-11 19:14:56501 Send(reply_message);
initial.commit09911bf2008-07-26 23:55:29502 return;
503 }
504
505 NavigationController* nav = tab_tracker_->GetResource(handle);
[email protected]7f0005a2009-04-15 03:25:11506 TabContents* tab_contents = nav->tab_contents();
initial.commit09911bf2008-07-26 23:55:29507
[email protected]f9e3c522010-10-08 00:41:26508 SendFindRequest(tab_contents,
509 false,
510 params.search_string,
511 params.forward,
512 params.match_case,
513 params.find_next,
514 reply_message);
515}
initial.commit09911bf2008-07-26 23:55:29516
[email protected]f9e3c522010-10-08 00:41:26517void AutomationProvider::SendFindRequest(
518 TabContents* tab_contents,
519 bool with_json,
520 const string16& search_string,
521 bool forward,
522 bool match_case,
523 bool find_next,
524 IPC::Message* reply_message) {
525 int request_id = FindInPageNotificationObserver::kFindInPageRequestId;
[email protected]7694f5e42010-10-18 22:41:17526 FindInPageNotificationObserver* observer =
[email protected]f9e3c522010-10-08 00:41:26527 new FindInPageNotificationObserver(this,
528 tab_contents,
529 with_json,
[email protected]7694f5e42010-10-18 22:41:17530 reply_message);
531 if (!with_json) {
532 find_in_page_observer_.reset(observer);
533 }
[email protected]f9e3c522010-10-08 00:41:26534 tab_contents->set_current_find_request_id(request_id);
[email protected]57c6a652009-05-04 07:58:34535 tab_contents->render_view_host()->StartFinding(
536 FindInPageNotificationObserver::kFindInPageRequestId,
[email protected]f9e3c522010-10-08 00:41:26537 search_string,
538 forward,
539 match_case,
540 find_next);
initial.commit09911bf2008-07-26 23:55:29541}
542
[email protected]a7eee32f2009-05-22 18:08:17543class SetProxyConfigTask : public Task {
544 public:
[email protected]be180c802009-10-23 06:33:31545 SetProxyConfigTask(URLRequestContextGetter* request_context_getter,
546 const std::string& new_proxy_config)
[email protected]2aa336e2010-04-06 21:05:25547 : request_context_getter_(request_context_getter),
548 proxy_config_(new_proxy_config) {}
[email protected]a7eee32f2009-05-22 18:08:17549 virtual void Run() {
550 // First, deserialize the JSON string. If this fails, log and bail.
551 JSONStringValueSerializer deserializer(proxy_config_);
[email protected]ba399672010-04-06 15:42:39552 std::string error_msg;
553 scoped_ptr<Value> root(deserializer.Deserialize(NULL, &error_msg));
[email protected]a7eee32f2009-05-22 18:08:17554 if (!root.get() || root->GetType() != Value::TYPE_DICTIONARY) {
555 DLOG(WARNING) << "Received bad JSON string for ProxyConfig: "
[email protected]ba399672010-04-06 15:42:39556 << error_msg;
[email protected]a7eee32f2009-05-22 18:08:17557 return;
558 }
559
560 scoped_ptr<DictionaryValue> dict(
561 static_cast<DictionaryValue*>(root.release()));
562 // Now put together a proxy configuration from the deserialized string.
563 net::ProxyConfig pc;
564 PopulateProxyConfig(*dict.get(), &pc);
565
[email protected]be180c802009-10-23 06:33:31566 net::ProxyService* proxy_service =
567 request_context_getter_->GetURLRequestContext()->proxy_service();
568 DCHECK(proxy_service);
[email protected]a7eee32f2009-05-22 18:08:17569 scoped_ptr<net::ProxyConfigService> proxy_config_service(
570 new net::ProxyConfigServiceFixed(pc));
[email protected]be180c802009-10-23 06:33:31571 proxy_service->ResetConfigService(proxy_config_service.release());
[email protected]a7eee32f2009-05-22 18:08:17572 }
573
574 void PopulateProxyConfig(const DictionaryValue& dict, net::ProxyConfig* pc) {
575 DCHECK(pc);
576 bool no_proxy = false;
577 if (dict.GetBoolean(automation::kJSONProxyNoProxy, &no_proxy)) {
578 // Make no changes to the ProxyConfig.
579 return;
580 }
581 bool auto_config;
582 if (dict.GetBoolean(automation::kJSONProxyAutoconfig, &auto_config)) {
[email protected]ed4ed0f2010-02-24 00:20:48583 pc->set_auto_detect(true);
[email protected]a7eee32f2009-05-22 18:08:17584 }
585 std::string pac_url;
586 if (dict.GetString(automation::kJSONProxyPacUrl, &pac_url)) {
[email protected]ed4ed0f2010-02-24 00:20:48587 pc->set_pac_url(GURL(pac_url));
[email protected]a7eee32f2009-05-22 18:08:17588 }
589 std::string proxy_bypass_list;
590 if (dict.GetString(automation::kJSONProxyBypassList, &proxy_bypass_list)) {
[email protected]ed4ed0f2010-02-24 00:20:48591 pc->proxy_rules().bypass_rules.ParseFromString(proxy_bypass_list);
[email protected]a7eee32f2009-05-22 18:08:17592 }
593 std::string proxy_server;
594 if (dict.GetString(automation::kJSONProxyServer, &proxy_server)) {
[email protected]ed4ed0f2010-02-24 00:20:48595 pc->proxy_rules().ParseFromString(proxy_server);
[email protected]a7eee32f2009-05-22 18:08:17596 }
597 }
598
599 private:
[email protected]be180c802009-10-23 06:33:31600 scoped_refptr<URLRequestContextGetter> request_context_getter_;
[email protected]a7eee32f2009-05-22 18:08:17601 std::string proxy_config_;
602};
603
604
605void AutomationProvider::SetProxyConfig(const std::string& new_proxy_config) {
[email protected]be180c802009-10-23 06:33:31606 URLRequestContextGetter* context_getter = Profile::GetDefaultRequestContext();
607 if (!context_getter) {
[email protected]a7eee32f2009-05-22 18:08:17608 FilePath user_data_dir;
609 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
610 ProfileManager* profile_manager = g_browser_process->profile_manager();
611 DCHECK(profile_manager);
612 Profile* profile = profile_manager->GetDefaultProfile(user_data_dir);
613 DCHECK(profile);
[email protected]be180c802009-10-23 06:33:31614 context_getter = profile->GetRequestContext();
[email protected]a7eee32f2009-05-22 18:08:17615 }
[email protected]be180c802009-10-23 06:33:31616 DCHECK(context_getter);
[email protected]a7eee32f2009-05-22 18:08:17617
[email protected]e0d586c2010-10-06 03:57:24618 BrowserThread::PostTask(
619 BrowserThread::IO, FROM_HERE,
[email protected]be180c802009-10-23 06:33:31620 new SetProxyConfigTask(context_getter, new_proxy_config));
[email protected]a7eee32f2009-05-22 18:08:17621}
622
[email protected]57c6a652009-05-04 07:58:34623TabContents* AutomationProvider::GetTabContentsForHandle(
[email protected]20e93d12008-08-28 16:31:57624 int handle, NavigationController** tab) {
[email protected]20e93d12008-08-28 16:31:57625 if (tab_tracker_->ContainsHandle(handle)) {
626 NavigationController* nav_controller = tab_tracker_->GetResource(handle);
[email protected]57c6a652009-05-04 07:58:34627 if (tab)
628 *tab = nav_controller;
629 return nav_controller->tab_contents();
[email protected]20e93d12008-08-28 16:31:57630 }
[email protected]57c6a652009-05-04 07:58:34631 return NULL;
[email protected]20e93d12008-08-28 16:31:57632}
633
[email protected]97fa6ce32008-12-19 01:48:16634// Gets the current used encoding name of the page in the specified tab.
[email protected]71f65dd2009-02-11 19:14:56635void AutomationProvider::OverrideEncoding(int tab_handle,
[email protected]41fc0322009-09-04 22:23:40636 const std::string& encoding_name,
[email protected]71f65dd2009-02-11 19:14:56637 bool* success) {
638 *success = false;
[email protected]97fa6ce32008-12-19 01:48:16639 if (tab_tracker_->ContainsHandle(tab_handle)) {
640 NavigationController* nav = tab_tracker_->GetResource(tab_handle);
[email protected]2f2afba2010-04-01 01:53:19641 if (!nav)
642 return;
[email protected]97fa6ce32008-12-19 01:48:16643 Browser* browser = FindAndActivateTab(nav);
[email protected]97fa6ce32008-12-19 01:48:16644
[email protected]2f2afba2010-04-01 01:53:19645 // If the browser has UI, simulate what a user would do.
646 // Activate the tab and then click the encoding menu.
647 if (browser &&
648 browser->command_updater()->IsCommandEnabled(IDC_ENCODING_MENU)) {
[email protected]97fa6ce32008-12-19 01:48:16649 int selected_encoding_id =
650 CharacterEncoding::GetCommandIdByCanonicalEncodingName(encoding_name);
651 if (selected_encoding_id) {
652 browser->OverrideEncoding(selected_encoding_id);
[email protected]71f65dd2009-02-11 19:14:56653 *success = true;
[email protected]97fa6ce32008-12-19 01:48:16654 }
[email protected]2f2afba2010-04-01 01:53:19655 } else {
656 // There is no UI, Chrome probably runs as Chrome-Frame mode.
657 // Try to get TabContents and call its override_encoding method.
658 TabContents* contents = nav->tab_contents();
659 if (!contents)
660 return;
661 const std::string selected_encoding =
662 CharacterEncoding::GetCanonicalEncodingNameByAliasName(encoding_name);
663 if (selected_encoding.empty())
664 return;
665 contents->SetOverrideEncoding(selected_encoding);
[email protected]97fa6ce32008-12-19 01:48:16666 }
667 }
[email protected]97fa6ce32008-12-19 01:48:16668}
[email protected]5bcdb312009-01-07 21:43:20669
[email protected]f7a68432009-07-29 23:18:19670void AutomationProvider::SelectAll(int tab_handle) {
671 RenderViewHost* view = GetViewForTab(tab_handle);
672 if (!view) {
673 NOTREACHED();
674 return;
675 }
676
677 view->SelectAll();
678}
679
680void AutomationProvider::Cut(int tab_handle) {
681 RenderViewHost* view = GetViewForTab(tab_handle);
682 if (!view) {
683 NOTREACHED();
684 return;
685 }
686
687 view->Cut();
688}
689
690void AutomationProvider::Copy(int tab_handle) {
691 RenderViewHost* view = GetViewForTab(tab_handle);
692 if (!view) {
693 NOTREACHED();
694 return;
695 }
696
697 view->Copy();
698}
699
700void AutomationProvider::Paste(int tab_handle) {
701 RenderViewHost* view = GetViewForTab(tab_handle);
702 if (!view) {
703 NOTREACHED();
704 return;
705 }
706
707 view->Paste();
708}
709
710void AutomationProvider::ReloadAsync(int tab_handle) {
711 if (tab_tracker_->ContainsHandle(tab_handle)) {
712 NavigationController* tab = tab_tracker_->GetResource(tab_handle);
713 if (!tab) {
714 NOTREACHED();
715 return;
716 }
717
[email protected]106a0812010-03-18 00:15:12718 const bool check_for_repost = true;
719 tab->Reload(check_for_repost);
[email protected]f7a68432009-07-29 23:18:19720 }
721}
722
723void AutomationProvider::StopAsync(int tab_handle) {
724 RenderViewHost* view = GetViewForTab(tab_handle);
725 if (!view) {
[email protected]8b2b3312009-09-14 18:38:36726 // We tolerate StopAsync being called even before a view has been created.
727 // So just log a warning instead of a NOTREACHED().
728 DLOG(WARNING) << "StopAsync: no view for handle " << tab_handle;
[email protected]f7a68432009-07-29 23:18:19729 return;
730 }
731
732 view->Stop();
733}
734
[email protected]1bb5f892009-10-06 01:44:57735void AutomationProvider::OnSetPageFontSize(int tab_handle,
736 int font_size) {
737 AutomationPageFontSize automation_font_size =
738 static_cast<AutomationPageFontSize>(font_size);
739
740 if (automation_font_size < SMALLEST_FONT ||
741 automation_font_size > LARGEST_FONT) {
742 DLOG(ERROR) << "Invalid font size specified : "
743 << font_size;
744 return;
745 }
746
747 if (tab_tracker_->ContainsHandle(tab_handle)) {
748 NavigationController* tab = tab_tracker_->GetResource(tab_handle);
749 DCHECK(tab != NULL);
750 if (tab && tab->tab_contents()) {
751 DCHECK(tab->tab_contents()->profile() != NULL);
752 tab->tab_contents()->profile()->GetPrefs()->SetInteger(
753 prefs::kWebKitDefaultFontSize, font_size);
754 }
755 }
756}
757
[email protected]bc73b4e52010-03-26 04:16:20758void AutomationProvider::RemoveBrowsingData(int remove_mask) {
759 BrowsingDataRemover* remover;
760 remover = new BrowsingDataRemover(profile(),
761 BrowsingDataRemover::EVERYTHING, // All time periods.
762 base::Time());
763 remover->Remove(remove_mask);
764 // BrowsingDataRemover deletes itself.
765}
[email protected]1bb5f892009-10-06 01:44:57766
[email protected]f7a68432009-07-29 23:18:19767RenderViewHost* AutomationProvider::GetViewForTab(int tab_handle) {
768 if (tab_tracker_->ContainsHandle(tab_handle)) {
769 NavigationController* tab = tab_tracker_->GetResource(tab_handle);
770 if (!tab) {
771 NOTREACHED();
772 return NULL;
773 }
774
775 TabContents* tab_contents = tab->tab_contents();
776 if (!tab_contents) {
777 NOTREACHED();
778 return NULL;
779 }
780
781 RenderViewHost* view_host = tab_contents->render_view_host();
782 return view_host;
783 }
784
785 return NULL;
786}
[email protected]675595f2009-08-26 22:32:04787
[email protected]d11c8e92009-10-20 23:26:40788void AutomationProvider::InstallExtension(const FilePath& crx_path,
789 IPC::Message* reply_message) {
[email protected]eaa7dd182010-12-14 11:09:00790 ExtensionService* service = profile_->GetExtensionService();
[email protected]d11c8e92009-10-20 23:26:40791 if (service) {
792 // The observer will delete itself when done.
[email protected]790788ac2010-04-06 17:52:19793 new ExtensionInstallNotificationObserver(this,
794 AutomationMsg_InstallExtension::ID,
795 reply_message);
[email protected]d11c8e92009-10-20 23:26:40796
[email protected]6dfbbf82010-03-12 23:09:16797 scoped_refptr<CrxInstaller> installer(
[email protected]bb461532010-11-26 21:50:23798 new CrxInstaller(service, NULL)); // silent install, no UI
[email protected]6dfbbf82010-03-12 23:09:16799 installer->InstallCrx(crx_path);
[email protected]d11c8e92009-10-20 23:26:40800 } else {
801 AutomationMsg_InstallExtension::WriteReplyParams(
802 reply_message, AUTOMATION_MSG_EXTENSION_INSTALL_FAILED);
803 Send(reply_message);
804 }
805}
806
807void AutomationProvider::LoadExpandedExtension(
808 const FilePath& extension_dir,
809 IPC::Message* reply_message) {
[email protected]eaa7dd182010-12-14 11:09:00810 if (profile_->GetExtensionService()) {
[email protected]d11c8e92009-10-20 23:26:40811 // The observer will delete itself when done.
[email protected]790788ac2010-04-06 17:52:19812 new ExtensionInstallNotificationObserver(
813 this,
814 AutomationMsg_LoadExpandedExtension::ID,
815 reply_message);
[email protected]d11c8e92009-10-20 23:26:40816
[email protected]eaa7dd182010-12-14 11:09:00817 profile_->GetExtensionService()->LoadExtension(extension_dir);
[email protected]d11c8e92009-10-20 23:26:40818 } else {
819 AutomationMsg_LoadExpandedExtension::WriteReplyParams(
820 reply_message, AUTOMATION_MSG_EXTENSION_INSTALL_FAILED);
821 Send(reply_message);
822 }
823}
[email protected]673fd2c02010-02-04 23:10:00824
[email protected]a1e62d12010-03-16 02:18:43825void AutomationProvider::GetEnabledExtensions(
826 std::vector<FilePath>* result) {
[email protected]eaa7dd182010-12-14 11:09:00827 ExtensionService* service = profile_->GetExtensionService();
[email protected]a1e62d12010-03-16 02:18:43828 DCHECK(service);
829 if (service->extensions_enabled()) {
830 const ExtensionList* extensions = service->extensions();
831 DCHECK(extensions);
832 for (size_t i = 0; i < extensions->size(); ++i) {
[email protected]9adb9692010-10-29 23:14:02833 const Extension* extension = (*extensions)[i];
[email protected]a1e62d12010-03-16 02:18:43834 DCHECK(extension);
[email protected]ad588422010-12-21 20:13:19835 // AutomationProvider only exposes non app internal/loaded extensions.
836 if (!extension->is_app() &&
837 (extension->location() == Extension::INTERNAL ||
838 extension->location() == Extension::LOAD)) {
[email protected]237f281672010-03-20 12:37:07839 result->push_back(extension->path());
840 }
[email protected]a1e62d12010-03-16 02:18:43841 }
842 }
843}
844
[email protected]790788ac2010-04-06 17:52:19845void AutomationProvider::WaitForExtensionTestResult(
846 IPC::Message* reply_message) {
847 DCHECK(reply_message_ == NULL);
848 reply_message_ = reply_message;
849 // Call MaybeSendResult, because the result might have come in before
850 // we were waiting on it.
851 extension_test_result_observer_->MaybeSendResult();
852}
853
854void AutomationProvider::InstallExtensionAndGetHandle(
[email protected]d7e5525d2010-04-20 14:37:09855 const FilePath& crx_path, bool with_ui, IPC::Message* reply_message) {
[email protected]eaa7dd182010-12-14 11:09:00856 ExtensionService* service = profile_->GetExtensionService();
[email protected]790788ac2010-04-06 17:52:19857 ExtensionProcessManager* manager = profile_->GetExtensionProcessManager();
858 if (service && manager) {
859 // The observer will delete itself when done.
860 new ExtensionReadyNotificationObserver(
861 manager,
862 this,
863 AutomationMsg_InstallExtensionAndGetHandle::ID,
864 reply_message);
865
[email protected]d7e5525d2010-04-20 14:37:09866 ExtensionInstallUI* client =
867 (with_ui ? new ExtensionInstallUI(profile_) : NULL);
[email protected]bb461532010-11-26 21:50:23868 scoped_refptr<CrxInstaller> installer(new CrxInstaller(service, client));
[email protected]790788ac2010-04-06 17:52:19869 installer->InstallCrx(crx_path);
870 } else {
871 AutomationMsg_InstallExtensionAndGetHandle::WriteReplyParams(
872 reply_message, 0);
873 Send(reply_message);
874 }
875}
876
877void AutomationProvider::UninstallExtension(int extension_handle,
878 bool* success) {
879 *success = false;
[email protected]9adb9692010-10-29 23:14:02880 const Extension* extension = GetExtension(extension_handle);
[email protected]eaa7dd182010-12-14 11:09:00881 ExtensionService* service = profile_->GetExtensionService();
[email protected]790788ac2010-04-06 17:52:19882 if (extension && service) {
883 ExtensionUnloadNotificationObserver observer;
884 service->UninstallExtension(extension->id(), false);
885 // The extension unload notification should have been sent synchronously
886 // with the uninstall. Just to be safe, check that it was received.
887 *success = observer.did_receive_unload_notification();
888 }
889}
890
891void AutomationProvider::EnableExtension(int extension_handle,
892 IPC::Message* reply_message) {
[email protected]9adb9692010-10-29 23:14:02893 const Extension* extension = GetDisabledExtension(extension_handle);
[email protected]eaa7dd182010-12-14 11:09:00894 ExtensionService* service = profile_->GetExtensionService();
[email protected]790788ac2010-04-06 17:52:19895 ExtensionProcessManager* manager = profile_->GetExtensionProcessManager();
896 // Only enable if this extension is disabled.
897 if (extension && service && manager) {
898 // The observer will delete itself when done.
899 new ExtensionReadyNotificationObserver(
900 manager,
901 this,
902 AutomationMsg_EnableExtension::ID,
903 reply_message);
904 service->EnableExtension(extension->id());
905 } else {
906 AutomationMsg_EnableExtension::WriteReplyParams(reply_message, false);
907 Send(reply_message);
908 }
909}
910
911void AutomationProvider::DisableExtension(int extension_handle,
912 bool* success) {
913 *success = false;
[email protected]9adb9692010-10-29 23:14:02914 const Extension* extension = GetEnabledExtension(extension_handle);
[email protected]eaa7dd182010-12-14 11:09:00915 ExtensionService* service = profile_->GetExtensionService();
[email protected]790788ac2010-04-06 17:52:19916 if (extension && service) {
917 ExtensionUnloadNotificationObserver observer;
918 service->DisableExtension(extension->id());
919 // The extension unload notification should have been sent synchronously
920 // with the disable. Just to be safe, check that it was received.
921 *success = observer.did_receive_unload_notification();
922 }
923}
924
925void AutomationProvider::ExecuteExtensionActionInActiveTabAsync(
926 int extension_handle, int browser_handle,
927 IPC::Message* reply_message) {
928 bool success = false;
[email protected]9adb9692010-10-29 23:14:02929 const Extension* extension = GetEnabledExtension(extension_handle);
[email protected]eaa7dd182010-12-14 11:09:00930 ExtensionService* service = profile_->GetExtensionService();
[email protected]790788ac2010-04-06 17:52:19931 ExtensionMessageService* message_service =
932 profile_->GetExtensionMessageService();
933 Browser* browser = browser_tracker_->GetResource(browser_handle);
934 if (extension && service && message_service && browser) {
935 int tab_id = ExtensionTabUtil::GetTabId(browser->GetSelectedTabContents());
936 if (extension->page_action()) {
937 ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted(
938 browser->profile(), extension->id(), "action", tab_id, "", 1);
939 success = true;
940 } else if (extension->browser_action()) {
941 ExtensionBrowserEventRouter::GetInstance()->BrowserActionExecuted(
942 browser->profile(), extension->id(), browser);
943 success = true;
944 }
945 }
946 AutomationMsg_ExecuteExtensionActionInActiveTabAsync::WriteReplyParams(
947 reply_message, success);
948 Send(reply_message);
949}
950
951void AutomationProvider::MoveExtensionBrowserAction(
952 int extension_handle, int index, bool* success) {
953 *success = false;
[email protected]9adb9692010-10-29 23:14:02954 const Extension* extension = GetEnabledExtension(extension_handle);
[email protected]eaa7dd182010-12-14 11:09:00955 ExtensionService* service = profile_->GetExtensionService();
[email protected]790788ac2010-04-06 17:52:19956 if (extension && service) {
957 ExtensionToolbarModel* toolbar = service->toolbar_model();
958 if (toolbar) {
959 if (index >= 0 && index < static_cast<int>(toolbar->size())) {
960 toolbar->MoveBrowserAction(extension, index);
961 *success = true;
962 } else {
963 DLOG(WARNING) << "Attempted to move browser action to invalid index.";
964 }
965 }
966 }
967}
968
969void AutomationProvider::GetExtensionProperty(
970 int extension_handle,
971 AutomationMsg_ExtensionProperty type,
972 bool* success,
973 std::string* value) {
974 *success = false;
[email protected]9adb9692010-10-29 23:14:02975 const Extension* extension = GetExtension(extension_handle);
[email protected]eaa7dd182010-12-14 11:09:00976 ExtensionService* service = profile_->GetExtensionService();
[email protected]790788ac2010-04-06 17:52:19977 if (extension && service) {
978 ExtensionToolbarModel* toolbar = service->toolbar_model();
979 int found_index = -1;
980 int index = 0;
981 switch (type) {
982 case AUTOMATION_MSG_EXTENSION_ID:
983 *value = extension->id();
984 *success = true;
985 break;
986 case AUTOMATION_MSG_EXTENSION_NAME:
987 *value = extension->name();
988 *success = true;
989 break;
990 case AUTOMATION_MSG_EXTENSION_VERSION:
991 *value = extension->VersionString();
992 *success = true;
993 break;
994 case AUTOMATION_MSG_EXTENSION_BROWSER_ACTION_INDEX:
995 if (toolbar) {
996 for (ExtensionList::const_iterator iter = toolbar->begin();
997 iter != toolbar->end(); iter++) {
998 // Skip this extension if we are in incognito mode
999 // and it is not incognito-enabled.
1000 if (profile_->IsOffTheRecord() &&
1001 !service->IsIncognitoEnabled(*iter))
1002 continue;
1003 if (*iter == extension) {
1004 found_index = index;
1005 break;
1006 }
1007 index++;
1008 }
[email protected]528c56d2010-07-30 19:28:441009 *value = base::IntToString(found_index);
[email protected]790788ac2010-04-06 17:52:191010 *success = true;
1011 }
1012 break;
1013 default:
1014 LOG(WARNING) << "Trying to get undefined extension property";
1015 break;
1016 }
1017 }
1018}
1019
[email protected]673fd2c02010-02-04 23:10:001020void AutomationProvider::SaveAsAsync(int tab_handle) {
1021 NavigationController* tab = NULL;
1022 TabContents* tab_contents = GetTabContentsForHandle(tab_handle, &tab);
1023 if (tab_contents)
1024 tab_contents->OnSavePage();
1025}