blob: 7705d94622ee3947a8f85cb0ab4318ae2d1c64e5 [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
5#include "chrome/browser/automation/automation_provider.h"
6
7#include "base/path_service.h"
[email protected]1eb89e82008-08-15 12:27:038#include "chrome/app/chrome_dll_resource.h"
initial.commit09911bf2008-07-26 23:55:299#include "chrome/browser/automation/automation_provider_list.h"
10#include "chrome/browser/automation/ui_controls.h"
11#include "chrome/browser/automation/url_request_failed_dns_job.h"
12#include "chrome/browser/automation/url_request_mock_http_job.h"
13#include "chrome/browser/automation/url_request_slow_download_job.h"
[email protected]f3e99e32008-07-30 04:48:3914#include "chrome/browser/browser_window.h"
initial.commit09911bf2008-07-26 23:55:2915#include "chrome/browser/dom_operation_notification_details.h"
[email protected]cdaa8652008-09-13 02:48:5916#include "chrome/browser/download/download_manager.h"
[email protected]37936ee2008-09-14 01:09:5017#include "chrome/browser/download/save_package.h"
initial.commit09911bf2008-07-26 23:55:2918#include "chrome/browser/external_tab_container.h"
19#include "chrome/browser/find_notification_details.h"
20#include "chrome/browser/login_prompt.h"
21#include "chrome/browser/navigation_entry.h"
22#include "chrome/browser/printing/print_job.h"
[email protected]fa83e762008-08-15 21:41:3923#include "chrome/browser/render_view_host.h"
[email protected]8a3422c92008-09-24 17:42:4224#include "chrome/browser/ssl_manager.h"
initial.commit09911bf2008-07-26 23:55:2925#include "chrome/browser/ssl_blocking_page.h"
[email protected]1eb89e82008-08-15 12:27:0326#include "chrome/browser/web_contents.h"
[email protected]c2cbeb92008-09-05 21:36:5727#include "chrome/browser/views/bookmark_bar_view.h"
[email protected]195442e2008-07-31 22:41:2828#include "chrome/browser/views/location_bar_view.h"
initial.commit09911bf2008-07-26 23:55:2929#include "chrome/common/chrome_paths.h"
[email protected]8a3422c92008-09-24 17:42:4230#include "chrome/common/pref_service.h"
initial.commit09911bf2008-07-26 23:55:2931#include "chrome/test/automation/automation_messages.h"
32#include "net/base/cookie_monster.h"
33#include "net/url_request/url_request_filter.h"
34
35class InitialLoadObserver : public NotificationObserver {
36 public:
37 InitialLoadObserver(size_t tab_count, AutomationProvider* automation)
38 : outstanding_tab_count_(tab_count),
39 automation_(automation) {
40 if (outstanding_tab_count_ > 0) {
41 NotificationService* service = NotificationService::current();
42 service->AddObserver(this, NOTIFY_LOAD_START,
43 NotificationService::AllSources());
44 service->AddObserver(this, NOTIFY_LOAD_STOP,
45 NotificationService::AllSources());
46 }
47 }
48
49 ~InitialLoadObserver() {
50 Unregister();
51 }
52
53 void ConditionMet() {
54 Unregister();
55 automation_->Send(new AutomationMsg_InitialLoadsComplete(0));
56 }
57
58 void Unregister() {
59 NotificationService* service = NotificationService::current();
60 service->RemoveObserver(this, NOTIFY_LOAD_START,
61 NotificationService::AllSources());
62 service->RemoveObserver(this, NOTIFY_LOAD_STOP,
63 NotificationService::AllSources());
64 }
65
66 virtual void Observe(NotificationType type,
67 const NotificationSource& source,
68 const NotificationDetails& details) {
69 if (type == NOTIFY_LOAD_START) {
70 if (outstanding_tab_count_ > loading_tabs_.size())
71 loading_tabs_.insert(source.map_key());
72 } else if (type == NOTIFY_LOAD_STOP) {
73 if (outstanding_tab_count_ > finished_tabs_.size()) {
74 if (loading_tabs_.find(source.map_key()) != loading_tabs_.end())
75 finished_tabs_.insert(source.map_key());
76 if (outstanding_tab_count_ == finished_tabs_.size())
77 ConditionMet();
78 }
79 } else {
80 NOTREACHED();
81 }
82 }
83
84 private:
85 typedef std::set<uintptr_t> TabSet;
86
87 AutomationProvider* automation_;
88 size_t outstanding_tab_count_;
89 TabSet loading_tabs_;
90 TabSet finished_tabs_;
91};
92
93// Watches for NewTabUI page loads for performance timing purposes.
94class NewTabUILoadObserver : public NotificationObserver {
95 public:
96 explicit NewTabUILoadObserver(AutomationProvider* automation)
97 : automation_(automation) {
98 NotificationService::current()->
99 AddObserver(this, NOTIFY_INITIAL_NEW_TAB_UI_LOAD,
100 NotificationService::AllSources());
101 }
102
103 ~NewTabUILoadObserver() {
104 Unregister();
105 }
106
107 void Unregister() {
108 NotificationService::current()->
109 RemoveObserver(this, NOTIFY_INITIAL_NEW_TAB_UI_LOAD,
110 NotificationService::AllSources());
111 }
112
113 virtual void Observe(NotificationType type,
114 const NotificationSource& source,
115 const NotificationDetails& details) {
116 if (type == NOTIFY_INITIAL_NEW_TAB_UI_LOAD) {
117 Details<int> load_time(details);
118 automation_->Send(
119 new AutomationMsg_InitialNewTabUILoadComplete(0, *load_time.ptr()));
120 } else {
121 NOTREACHED();
122 }
123 }
124
125 private:
126 AutomationProvider* automation_;
127};
128
129class NavigationControllerRestoredObserver : public NotificationObserver {
130 public:
131 NavigationControllerRestoredObserver(AutomationProvider* automation,
132 NavigationController* controller,
133 int32 routing_id)
134 : automation_(automation),
135 controller_(controller),
136 routing_id_(routing_id) {
137 if (FinishedRestoring()) {
138 registered_ = false;
139 SendDone();
140 } else {
141 registered_ = true;
142 NotificationService* service = NotificationService::current();
143 service->AddObserver(this, NOTIFY_LOAD_STOP,
144 NotificationService::AllSources());
145 }
146 }
147
148 ~NavigationControllerRestoredObserver() {
149 if (registered_)
150 Unregister();
151 }
152
153 virtual void Observe(NotificationType type,
154 const NotificationSource& source,
155 const NotificationDetails& details) {
156 if (FinishedRestoring()) {
157 SendDone();
158 Unregister();
159 }
160 }
161
162 private:
163 void Unregister() {
164 NotificationService* service = NotificationService::current();
165 service->RemoveObserver(this, NOTIFY_LOAD_STOP,
166 NotificationService::AllSources());
167 registered_ = false;
168 }
169
170 bool FinishedRestoring() {
171 return (!controller_->needs_reload() && !controller_->GetPendingEntry() &&
[email protected]d5f942ba2008-09-26 19:30:34172 !controller_->active_contents()->is_loading());
initial.commit09911bf2008-07-26 23:55:29173 }
174
175 void SendDone() {
176 automation_->Send(new AutomationMsg_TabFinishedRestoring(routing_id_));
177 }
178
179 bool registered_;
180 AutomationProvider* automation_;
181 NavigationController* controller_;
182 const int routing_id_;
183
[email protected]5a52f162008-08-27 04:15:31184 DISALLOW_COPY_AND_ASSIGN(NavigationControllerRestoredObserver);
initial.commit09911bf2008-07-26 23:55:29185};
186
initial.commit09911bf2008-07-26 23:55:29187class NavigationNotificationObserver : public NotificationObserver {
188 public:
189 NavigationNotificationObserver(NavigationController* controller,
190 AutomationProvider* automation,
191 IPC::Message* completed_response,
192 IPC::Message* auth_needed_response)
193 : automation_(automation),
194 completed_response_(completed_response),
195 auth_needed_response_(auth_needed_response),
196 controller_(controller),
197 navigation_started_(false) {
198 NotificationService* service = NotificationService::current();
[email protected]8a3422c92008-09-24 17:42:42199 service->AddObserver(this, NOTIFY_NAV_ENTRY_COMMITTED,
200 Source<NavigationController>(controller_));
initial.commit09911bf2008-07-26 23:55:29201 service->AddObserver(this, NOTIFY_LOAD_START,
202 Source<NavigationController>(controller_));
203 service->AddObserver(this, NOTIFY_LOAD_STOP,
204 Source<NavigationController>(controller_));
205 service->AddObserver(this, NOTIFY_AUTH_NEEDED,
206 Source<NavigationController>(controller_));
207 service->AddObserver(this, NOTIFY_AUTH_SUPPLIED,
208 Source<NavigationController>(controller_));
209 }
210
211 ~NavigationNotificationObserver() {
212 if (completed_response_) delete completed_response_;
213 if (auth_needed_response_) delete auth_needed_response_;
214 Unregister();
215 }
216
217 void ConditionMet(IPC::Message** response) {
218 if (*response) {
219 automation_->Send(*response);
220 *response = NULL; // *response is deleted by Send.
221 }
222 automation_->RemoveNavigationStatusListener(this);
223 delete this;
224 }
225
226 void Unregister() {
227 NotificationService* service = NotificationService::current();
[email protected]8a3422c92008-09-24 17:42:42228 service->RemoveObserver(this, NOTIFY_NAV_ENTRY_COMMITTED,
229 Source<NavigationController>(controller_));
initial.commit09911bf2008-07-26 23:55:29230 service->RemoveObserver(this, NOTIFY_LOAD_START,
231 Source<NavigationController>(controller_));
232 service->RemoveObserver(this, NOTIFY_LOAD_STOP,
233 Source<NavigationController>(controller_));
234 service->RemoveObserver(this, NOTIFY_AUTH_NEEDED,
235 Source<NavigationController>(controller_));
236 service->RemoveObserver(this, NOTIFY_AUTH_SUPPLIED,
237 Source<NavigationController>(controller_));
238 }
239
240 virtual void Observe(NotificationType type,
241 const NotificationSource& source,
242 const NotificationDetails& details) {
[email protected]8a3422c92008-09-24 17:42:42243 // We listen for 2 events to determine when the navigation started because:
244 // - when this is used by the WaitForNavigation method, we might be invoked
245 // afer the load has started (but not after the entry was committed, as
246 // WaitForNavigation compares times of the last navigation).
247 // - when this is used with a page requiring authentication, we will not get
248 // a NOTIFY_NAV_ENTRY_COMMITTED until after we authenticate, so we need the
249 // NOTIFY_LOAD_START.
250 if (type == NOTIFY_NAV_ENTRY_COMMITTED || type == NOTIFY_LOAD_START) {
initial.commit09911bf2008-07-26 23:55:29251 navigation_started_ = true;
252 } else if (type == NOTIFY_LOAD_STOP) {
253 if (navigation_started_) {
254 navigation_started_ = false;
255 ConditionMet(&completed_response_);
256 }
257 } else if (type == NOTIFY_AUTH_SUPPLIED) {
258 // The LoginHandler for this tab is no longer valid.
259 automation_->RemoveLoginHandler(controller_);
260
261 // Treat this as if navigation started again, since load start/stop don't
262 // occur while authentication is ongoing.
263 navigation_started_ = true;
264 } else if (type == NOTIFY_AUTH_NEEDED) {
265 if (navigation_started_) {
266 // Remember the login handler that wants authentication.
267 LoginHandler* handler =
268 Details<LoginNotificationDetails>(details)->handler();
269 automation_->AddLoginHandler(controller_, handler);
270
271 // Respond that authentication is needed.
272 navigation_started_ = false;
273 ConditionMet(&auth_needed_response_);
274 } else {
275 NOTREACHED();
276 }
277 } else {
278 NOTREACHED();
279 }
280 }
281
282 private:
283 AutomationProvider* automation_;
284 IPC::Message* completed_response_;
285 IPC::Message* auth_needed_response_;
286 NavigationController* controller_;
287 bool navigation_started_;
288};
289
290class TabStripNotificationObserver : public NotificationObserver {
291 public:
292 TabStripNotificationObserver(Browser* parent, NotificationType notification,
293 AutomationProvider* automation, int32 routing_id)
294 : automation_(automation),
295 notification_(notification),
296 parent_(parent),
297 routing_id_(routing_id) {
298 NotificationService::current()->
299 AddObserver(this, notification_, NotificationService::AllSources());
300 }
301
302 virtual ~TabStripNotificationObserver() {
303 Unregister();
304 }
305
306 void Unregister() {
307 NotificationService::current()->
308 RemoveObserver(this, notification_, NotificationService::AllSources());
309 }
310
311 virtual void Observe(NotificationType type,
312 const NotificationSource& source,
313 const NotificationDetails& details) {
314 if (type == notification_) {
315 ObserveTab(Source<NavigationController>(source).ptr());
316
317 // If verified, no need to observe anymore
318 automation_->RemoveTabStripObserver(this);
319 delete this;
320 } else {
321 NOTREACHED();
322 }
323 }
324
325 virtual void ObserveTab(NavigationController* controller) = 0;
326
327 protected:
328 AutomationProvider* automation_;
329 Browser* parent_;
330 NotificationType notification_;
331 int32 routing_id_;
332};
333
334class TabAppendedNotificationObserver : public TabStripNotificationObserver {
335 public:
336 TabAppendedNotificationObserver(Browser* parent,
337 AutomationProvider* automation, int32 routing_id)
[email protected]534e54b2008-08-13 15:40:09338 : TabStripNotificationObserver(parent, NOTIFY_TAB_PARENTED, automation,
initial.commit09911bf2008-07-26 23:55:29339 routing_id) {
340 }
341
342 virtual void ObserveTab(NavigationController* controller) {
343 int tab_index =
344 automation_->GetIndexForNavigationController(controller, parent_);
345 if (tab_index == TabStripModel::kNoTab) {
346 // This tab notification doesn't belong to the parent_
347 return;
348 }
349
350 // Give the same response even if auth is needed, since it doesn't matter.
351 automation_->AddNavigationStatusListener(controller,
352 new AutomationMsg_AppendTabResponse(routing_id_, tab_index),
353 new AutomationMsg_AppendTabResponse(routing_id_, tab_index));
354 }
355};
356
357class TabClosedNotificationObserver : public TabStripNotificationObserver {
358 public:
359 TabClosedNotificationObserver(Browser* parent,
360 AutomationProvider* automation,
361 int32 routing_id,
362 bool wait_until_closed)
363 : TabStripNotificationObserver(parent,
364 wait_until_closed ? NOTIFY_TAB_CLOSED :
365 NOTIFY_TAB_CLOSING,
366 automation,
367 routing_id) {
368 }
369
370 virtual void ObserveTab(NavigationController* controller) {
371 automation_->Send(new AutomationMsg_CloseTabResponse(routing_id_, true));
372 }
373};
374
375class BrowserClosedNotificationObserver : public NotificationObserver {
376 public:
377 BrowserClosedNotificationObserver(Browser* browser,
378 AutomationProvider* automation,
379 int32 routing_id)
380 : automation_(automation),
381 routing_id_(routing_id) {
382 NotificationService::current()->
383 AddObserver(this, NOTIFY_BROWSER_CLOSED, Source<Browser>(browser));
384 }
385
386 virtual void Observe(NotificationType type,
387 const NotificationSource& source,
388 const NotificationDetails& details) {
389 DCHECK(type == NOTIFY_BROWSER_CLOSED);
390 Details<bool> close_app(details);
391 automation_->Send(
392 new AutomationMsg_CloseBrowserResponse(routing_id_,
393 true,
394 *(close_app.ptr())));
395 delete this;
396 }
397
398 private:
399 AutomationProvider* automation_;
400 int32 routing_id_;
401};
402
403class FindInPageNotificationObserver : public NotificationObserver {
404 public:
405 FindInPageNotificationObserver(AutomationProvider* automation,
406 TabContents* parent_tab,
407 int32 routing_id)
408 : automation_(automation),
409 parent_tab_(parent_tab),
410 routing_id_(routing_id) {
411 NotificationService::current()->
412 AddObserver(this, NOTIFY_FIND_RESULT_AVAILABLE,
413 Source<TabContents>(parent_tab_));
414 }
415
416 ~FindInPageNotificationObserver() {
417 Unregister();
418 }
419
420 void Unregister() {
421 NotificationService::current()->
422 RemoveObserver(this, NOTIFY_FIND_RESULT_AVAILABLE,
423 Source<TabContents>(parent_tab_));
424 }
425
426 virtual void Observe(NotificationType type, const NotificationSource& source,
427 const NotificationDetails& details) {
428 if (type == NOTIFY_FIND_RESULT_AVAILABLE) {
429 Details<FindNotificationDetails> find_details(details);
430 if (find_details->request_id() == kFindInPageRequestId) {
431 if (find_details->final_update()) {
432 automation_->Send(new AutomationMsg_FindInPageResponse(routing_id_,
433 find_details->number_of_matches()));
434 } else {
435 DLOG(INFO) << "Ignoring, since we only care about the final message";
436 }
437 }
438 } else {
439 NOTREACHED();
440 }
441 }
442
443 // The Find mechanism is over asynchronous IPC, so a search is kicked off and
444 // we wait for notification to find out what the results are. As the user is
445 // typing, new search requests can be issued and the Request ID helps us make
446 // sense of whether this is the current request or an old one. The unit tests,
447 // however, which uses this constant issues only one search at a time, so we
448 // don't need a rolling id to identify each search. But, we still need to
449 // specify one, so we just use a fixed one - its value does not matter.
450 static const int kFindInPageRequestId;
451 private:
452 AutomationProvider* automation_;
453 TabContents* parent_tab_;
454 int32 routing_id_;
455};
456
457const int FindInPageNotificationObserver::kFindInPageRequestId = -1;
458
459class DomOperationNotificationObserver : public NotificationObserver {
460 public:
461 explicit DomOperationNotificationObserver(AutomationProvider* automation)
462 : automation_(automation) {
463 NotificationService::current()->
464 AddObserver(this, NOTIFY_DOM_OPERATION_RESPONSE,
465 NotificationService::AllSources());
466 }
467
468 ~DomOperationNotificationObserver() {
469 NotificationService::current()->
470 RemoveObserver(this, NOTIFY_DOM_OPERATION_RESPONSE,
471 NotificationService::AllSources());
472 }
473
474 virtual void Observe(NotificationType type, const NotificationSource& source,
475 const NotificationDetails& details) {
476 if (NOTIFY_DOM_OPERATION_RESPONSE == type) {
477 Details<DomOperationNotificationDetails> dom_op_details(details);
478 automation_->Send(new AutomationMsg_DomOperationResponse(
479 dom_op_details->automation_id(),
480 dom_op_details->json()));
481 }
482 }
483 private:
484 AutomationProvider* automation_;
485};
486
487class DomInspectorNotificationObserver : public NotificationObserver {
488 public:
489 explicit DomInspectorNotificationObserver(AutomationProvider* automation)
490 : automation_(automation) {
491 NotificationService::current()->
492 AddObserver(this, NOTIFY_DOM_INSPECT_ELEMENT_RESPONSE,
493 NotificationService::AllSources());
494 }
495
496 ~DomInspectorNotificationObserver() {
497 NotificationService::current()->
498 RemoveObserver(this, NOTIFY_DOM_INSPECT_ELEMENT_RESPONSE,
499 NotificationService::AllSources());
500 }
501
502 virtual void Observe(NotificationType type, const NotificationSource& source,
503 const NotificationDetails& details) {
504 if (NOTIFY_DOM_INSPECT_ELEMENT_RESPONSE == type) {
505 Details<int> dom_inspect_details(details);
506 automation_->ReceivedInspectElementResponse(*(dom_inspect_details.ptr()));
507 }
508 }
509
510 private:
511 AutomationProvider* automation_;
512};
513
514class DocumentPrintedNotificationObserver : public NotificationObserver {
515 public:
516 DocumentPrintedNotificationObserver(AutomationProvider* automation,
517 int32 routing_id)
518 : automation_(automation),
519 routing_id_(routing_id),
520 success_(false) {
521 NotificationService::current()->
522 AddObserver(this, NOTIFY_PRINT_JOB_EVENT,
523 NotificationService::AllSources());
524 }
525
526 ~DocumentPrintedNotificationObserver() {
527 automation_->Send(
528 new AutomationMsg_PrintNowResponse(routing_id_, success_));
529 automation_->RemoveNavigationStatusListener(this);
530 NotificationService::current()->
531 RemoveObserver(this, NOTIFY_PRINT_JOB_EVENT,
532 NotificationService::AllSources());
533 }
534
535 virtual void Observe(NotificationType type, const NotificationSource& source,
536 const NotificationDetails& details) {
537 using namespace printing;
538 DCHECK(type == NOTIFY_PRINT_JOB_EVENT);
539 switch (Details<JobEventDetails>(details)->type()) {
540 case JobEventDetails::JOB_DONE: {
541 // Succeeded.
542 success_ = true;
543 delete this;
544 break;
545 }
546 case JobEventDetails::USER_INIT_CANCELED:
547 case JobEventDetails::FAILED: {
548 // Failed.
549 delete this;
550 break;
551 }
552 case JobEventDetails::NEW_DOC:
553 case JobEventDetails::USER_INIT_DONE:
554 case JobEventDetails::DEFAULT_INIT_DONE:
555 case JobEventDetails::NEW_PAGE:
556 case JobEventDetails::PAGE_DONE:
557 case JobEventDetails::DOC_DONE:
558 case JobEventDetails::ALL_PAGES_REQUESTED: {
559 // Don't care.
560 break;
561 }
562 default: {
563 NOTREACHED();
564 break;
565 }
566 }
567 }
568
569 private:
570 scoped_refptr<AutomationProvider> automation_;
571 int32 routing_id_;
572 bool success_;
573};
574
575AutomationProvider::AutomationProvider(Profile* profile)
[email protected]295039bd2008-08-15 04:32:57576 : redirect_query_(0),
initial.commit09911bf2008-07-26 23:55:29577 profile_(profile) {
initial.commit09911bf2008-07-26 23:55:29578 browser_tracker_.reset(new AutomationBrowserTracker(this));
579 window_tracker_.reset(new AutomationWindowTracker(this));
580 tab_tracker_.reset(new AutomationTabTracker(this));
581 autocomplete_edit_tracker_.reset(
582 new AutomationAutocompleteEditTracker(this));
583 cwindow_tracker_.reset(new AutomationConstrainedWindowTracker(this));
584 new_tab_ui_load_observer_.reset(new NewTabUILoadObserver(this));
585 dom_operation_observer_.reset(new DomOperationNotificationObserver(this));
586 dom_inspector_observer_.reset(new DomInspectorNotificationObserver(this));
587}
588
589AutomationProvider::~AutomationProvider() {
[email protected]0da050b92008-08-19 19:29:47590 // Make sure that any outstanding NotificationObservers also get destroyed.
591 ObserverList<NotificationObserver>::Iterator it(notification_observer_list_);
[email protected]5a52f162008-08-27 04:15:31592 NotificationObserver* observer;
[email protected]0da050b92008-08-19 19:29:47593 while ((observer = it.GetNext()) != NULL)
594 delete observer;
initial.commit09911bf2008-07-26 23:55:29595}
596
597void AutomationProvider::ConnectToChannel(const std::wstring& channel_id) {
[email protected]295039bd2008-08-15 04:32:57598 channel_.reset(
599 new IPC::ChannelProxy(channel_id, IPC::Channel::MODE_CLIENT, this, NULL,
600 g_browser_process->io_thread()->message_loop()));
601 channel_->Send(new AutomationMsg_Hello(0));
initial.commit09911bf2008-07-26 23:55:29602}
603
604void AutomationProvider::SetExpectedTabCount(size_t expected_tabs) {
605 if (expected_tabs == 0) {
606 Send(new AutomationMsg_InitialLoadsComplete(0));
607 } else {
608 initial_load_observer_.reset(new InitialLoadObserver(expected_tabs, this));
609 }
610}
611
612NotificationObserver* AutomationProvider::AddNavigationStatusListener(
613 NavigationController* tab, IPC::Message* completed_response,
614 IPC::Message* auth_needed_response) {
615 NotificationObserver* observer =
616 new NavigationNotificationObserver(tab, this, completed_response,
617 auth_needed_response);
618 notification_observer_list_.AddObserver(observer);
619
620 return observer;
621}
622
623void AutomationProvider::RemoveNavigationStatusListener(
624 NotificationObserver* obs) {
625 notification_observer_list_.RemoveObserver(obs);
626}
627
628NotificationObserver* AutomationProvider::AddTabStripObserver(
629 Browser* parent, int32 routing_id) {
630 NotificationObserver* observer = new
631 TabAppendedNotificationObserver(parent, this, routing_id);
632 notification_observer_list_.AddObserver(observer);
633
634 return observer;
635}
636
637void AutomationProvider::RemoveTabStripObserver(NotificationObserver* obs) {
638 notification_observer_list_.RemoveObserver(obs);
639}
640
641void AutomationProvider::AddLoginHandler(NavigationController* tab,
642 LoginHandler* handler) {
643 login_handler_map_[tab] = handler;
644}
645
646void AutomationProvider::RemoveLoginHandler(NavigationController* tab) {
647 DCHECK(login_handler_map_[tab]);
648 login_handler_map_.erase(tab);
649}
650
651int AutomationProvider::GetIndexForNavigationController(
652 const NavigationController* controller, const Browser* parent) const {
653 DCHECK(parent);
654 return parent->GetIndexOfController(controller);
655}
656
657void AutomationProvider::OnMessageReceived(const IPC::Message& message) {
658 IPC_BEGIN_MESSAGE_MAP(AutomationProvider, message)
659 IPC_MESSAGE_HANDLER(AutomationMsg_CloseBrowserRequest, CloseBrowser)
660 IPC_MESSAGE_HANDLER(AutomationMsg_ActivateTabRequest, ActivateTab)
661 IPC_MESSAGE_HANDLER(AutomationMsg_ActiveTabIndexRequest, GetActiveTabIndex)
662 IPC_MESSAGE_HANDLER(AutomationMsg_AppendTabRequest, AppendTab)
663 IPC_MESSAGE_HANDLER(AutomationMsg_CloseTabRequest, CloseTab)
664 IPC_MESSAGE_HANDLER(AutomationMsg_GetCookiesRequest, GetCookies)
665 IPC_MESSAGE_HANDLER(AutomationMsg_SetCookieRequest, SetCookie)
666 IPC_MESSAGE_HANDLER(AutomationMsg_NavigateToURLRequest, NavigateToURL)
667 IPC_MESSAGE_HANDLER(AutomationMsg_NavigationAsyncRequest, NavigationAsync)
668 IPC_MESSAGE_HANDLER(AutomationMsg_GoBackRequest, GoBack)
669 IPC_MESSAGE_HANDLER(AutomationMsg_GoForwardRequest, GoForward)
670 IPC_MESSAGE_HANDLER(AutomationMsg_ReloadRequest, Reload)
671 IPC_MESSAGE_HANDLER(AutomationMsg_SetAuthRequest, SetAuth)
672 IPC_MESSAGE_HANDLER(AutomationMsg_CancelAuthRequest, CancelAuth)
673 IPC_MESSAGE_HANDLER(AutomationMsg_NeedsAuthRequest, NeedsAuth)
674 IPC_MESSAGE_HANDLER(AutomationMsg_RedirectsFromRequest, GetRedirectsFrom)
675 IPC_MESSAGE_HANDLER(AutomationMsg_BrowserWindowCountRequest,
676 GetBrowserWindowCount)
677 IPC_MESSAGE_HANDLER(AutomationMsg_BrowserWindowRequest, GetBrowserWindow)
678 IPC_MESSAGE_HANDLER(AutomationMsg_LastActiveBrowserWindowRequest,
679 GetLastActiveBrowserWindow)
680 IPC_MESSAGE_HANDLER(AutomationMsg_ActiveWindowRequest, GetActiveWindow)
681 IPC_MESSAGE_HANDLER(AutomationMsg_IsWindowActiveRequest, IsWindowActive)
682 IPC_MESSAGE_HANDLER(AutomationMsg_ActivateWindow, ActivateWindow);
683 IPC_MESSAGE_HANDLER(AutomationMsg_WindowHWNDRequest, GetWindowHWND)
[email protected]4ae62752008-08-04 23:28:47684 IPC_MESSAGE_HANDLER(AutomationMsg_WindowExecuteCommandRequest,
685 ExecuteBrowserCommand)
initial.commit09911bf2008-07-26 23:55:29686 IPC_MESSAGE_HANDLER(AutomationMsg_WindowViewBoundsRequest,
687 WindowGetViewBounds)
688 IPC_MESSAGE_HANDLER(AutomationMsg_SetWindowVisibleRequest, SetWindowVisible)
689 IPC_MESSAGE_HANDLER(AutomationMsg_WindowClickRequest, WindowSimulateClick)
690 IPC_MESSAGE_HANDLER(AutomationMsg_WindowKeyPressRequest,
691 WindowSimulateKeyPress)
692 IPC_MESSAGE_HANDLER(AutomationMsg_WindowDragRequest, WindowSimulateDrag)
693 IPC_MESSAGE_HANDLER(AutomationMsg_TabCountRequest, GetTabCount)
694 IPC_MESSAGE_HANDLER(AutomationMsg_TabRequest, GetTab)
695 IPC_MESSAGE_HANDLER(AutomationMsg_TabHWNDRequest, GetTabHWND)
696 IPC_MESSAGE_HANDLER(AutomationMsg_TabProcessIDRequest, GetTabProcessID)
697 IPC_MESSAGE_HANDLER(AutomationMsg_TabTitleRequest, GetTabTitle)
698 IPC_MESSAGE_HANDLER(AutomationMsg_TabURLRequest, GetTabURL)
699 IPC_MESSAGE_HANDLER(AutomationMsg_ShelfVisibilityRequest,
700 GetShelfVisibility)
701 IPC_MESSAGE_HANDLER(AutomationMsg_HandleUnused, HandleUnused)
702 IPC_MESSAGE_HANDLER(AutomationMsg_ApplyAcceleratorRequest, ApplyAccelerator)
703 IPC_MESSAGE_HANDLER(AutomationMsg_DomOperationRequest, ExecuteJavascript)
704 IPC_MESSAGE_HANDLER(AutomationMsg_ConstrainedWindowCountRequest,
705 GetConstrainedWindowCount)
706 IPC_MESSAGE_HANDLER(AutomationMsg_ConstrainedWindowRequest,
707 GetConstrainedWindow)
708 IPC_MESSAGE_HANDLER(AutomationMsg_ConstrainedTitleRequest,
709 GetConstrainedTitle)
710 IPC_MESSAGE_HANDLER(AutomationMsg_FindInPageRequest,
711 HandleFindInPageRequest)
712 IPC_MESSAGE_HANDLER(AutomationMsg_GetFocusedViewIDRequest, GetFocusedViewID)
713 IPC_MESSAGE_HANDLER(AutomationMsg_InspectElementRequest,
714 HandleInspectElementRequest)
715 IPC_MESSAGE_HANDLER(AutomationMsg_SetFilteredInet,
716 SetFilteredInet);
717 IPC_MESSAGE_HANDLER(AutomationMsg_DownloadDirectoryRequest,
718 GetDownloadDirectory);
719 IPC_MESSAGE_HANDLER(AutomationMsg_OpenNewBrowserWindow,
720 OpenNewBrowserWindow);
721 IPC_MESSAGE_HANDLER(AutomationMsg_WindowForBrowserRequest,
722 GetWindowForBrowser);
723 IPC_MESSAGE_HANDLER(AutomationMsg_AutocompleteEditForBrowserRequest,
724 GetAutocompleteEditForBrowser);
725 IPC_MESSAGE_HANDLER(AutomationMsg_BrowserForWindowRequest,
726 GetBrowserForWindow);
727 IPC_MESSAGE_HANDLER(AutomationMsg_CreateExternalTab, CreateExternalTab)
728 IPC_MESSAGE_HANDLER(AutomationMsg_NavigateInExternalTabRequest,
729 NavigateInExternalTab)
730 IPC_MESSAGE_HANDLER(AutomationMsg_ShowInterstitialPageRequest,
731 ShowInterstitialPage);
732 IPC_MESSAGE_HANDLER(AutomationMsg_HideInterstitialPageRequest,
733 HideInterstitialPage);
734 IPC_MESSAGE_HANDLER(AutomationMsg_SetAcceleratorsForTab,
735 SetAcceleratorsForTab)
736 IPC_MESSAGE_HANDLER(AutomationMsg_ProcessUnhandledAccelerator,
737 ProcessUnhandledAccelerator)
738 IPC_MESSAGE_HANDLER(AutomationMsg_WaitForTabToBeRestored,
739 WaitForTabToBeRestored)
740 IPC_MESSAGE_HANDLER(AutomationMsg_GetSecurityState,
741 GetSecurityState)
742 IPC_MESSAGE_HANDLER(AutomationMsg_GetPageType,
743 GetPageType)
744 IPC_MESSAGE_HANDLER(AutomationMsg_ActionOnSSLBlockingPage,
745 ActionOnSSLBlockingPage)
746 IPC_MESSAGE_HANDLER(AutomationMsg_BringBrowserToFront, BringBrowserToFront)
747 IPC_MESSAGE_HANDLER(AutomationMsg_IsPageMenuCommandEnabled,
748 IsPageMenuCommandEnabled)
749 IPC_MESSAGE_HANDLER(AutomationMsg_PrintNowRequest, PrintNow)
750 IPC_MESSAGE_HANDLER(AutomationMsg_SavePageRequest, SavePage)
751 IPC_MESSAGE_HANDLER(AutomationMsg_AutocompleteEditGetTextRequest,
752 GetAutocompleteEditText)
753 IPC_MESSAGE_HANDLER(AutomationMsg_AutocompleteEditSetTextRequest,
754 SetAutocompleteEditText)
755 IPC_MESSAGE_HANDLER(AutomationMsg_AutocompleteEditIsQueryInProgressRequest,
756 AutocompleteEditIsQueryInProgress)
757 IPC_MESSAGE_HANDLER(AutomationMsg_AutocompleteEditGetMatchesRequest,
758 AutocompleteEditGetMatches)
759 IPC_MESSAGE_HANDLER(AutomationMsg_ConstrainedWindowBoundsRequest,
760 GetConstrainedWindowBounds)
[email protected]5f8af2a2008-08-06 22:49:45761 IPC_MESSAGE_HANDLER(AutomationMsg_OpenFindInPageRequest,
762 HandleOpenFindInPageRequest)
[email protected]18cb2572008-08-21 20:34:45763 IPC_MESSAGE_HANDLER(AutomationMsg_HandleMessageFromExternalHost,
764 OnMessageFromExternalHost)
[email protected]5a52f162008-08-27 04:15:31765 IPC_MESSAGE_HANDLER(AutomationMsg_FindRequest,
766 HandleFindRequest)
[email protected]20e93d12008-08-28 16:31:57767 IPC_MESSAGE_HANDLER(AutomationMsg_FindWindowVisibilityRequest,
768 GetFindWindowVisibility)
769 IPC_MESSAGE_HANDLER(AutomationMsg_FindWindowLocationRequest,
770 HandleFindWindowLocationRequest)
[email protected]c2cbeb92008-09-05 21:36:57771 IPC_MESSAGE_HANDLER(AutomationMsg_BookmarkBarVisibilityRequest,
772 GetBookmarkBarVisitility)
[email protected]8a3422c92008-09-24 17:42:42773 IPC_MESSAGE_HANDLER(AutomationMsg_GetSSLInfoBarCountRequest,
774 GetSSLInfoBarCount)
775 IPC_MESSAGE_HANDLER(AutomationMsg_ClickSSLInfoBarLinkRequest,
776 ClickSSLInfoBarLink)
777 IPC_MESSAGE_HANDLER(AutomationMsg_GetLastNavigationTimeRequest,
778 GetLastNavigationTime)
779 IPC_MESSAGE_HANDLER(AutomationMsg_WaitForNavigationRequest,
780 WaitForNavigation)
781 IPC_MESSAGE_HANDLER(AutomationMsg_SetIntPreferenceRequest,
782 SetIntPreference)
initial.commit09911bf2008-07-26 23:55:29783 IPC_END_MESSAGE_MAP()
784}
785
786void AutomationProvider::ActivateTab(const IPC::Message& message,
787 int handle, int at_index) {
788 int status = -1;
789 if (browser_tracker_->ContainsHandle(handle) && at_index > -1) {
790 Browser* browser = browser_tracker_->GetResource(handle);
791 if (at_index >= 0 && at_index < browser->tab_count()) {
792 browser->SelectTabContentsAt(at_index, true);
793 status = 0;
794 }
795 }
796 Send(new AutomationMsg_ActivateTabResponse(message.routing_id(), status));
797}
798
799void AutomationProvider::AppendTab(const IPC::Message& message,
800 int handle, const GURL& url) {
801 int append_tab_response = -1; // -1 is the error code
802 NotificationObserver* observer = NULL;
803
804 if (browser_tracker_->ContainsHandle(handle)) {
805 Browser* browser = browser_tracker_->GetResource(handle);
806 observer = AddTabStripObserver(browser, message.routing_id());
807 TabContents* tab_contents =
808 browser->AddTabWithURL(url, PageTransition::TYPED, true, NULL);
809 if (tab_contents) {
810 append_tab_response =
811 GetIndexForNavigationController(tab_contents->controller(), browser);
812 }
813 }
814
815 if (append_tab_response < 0) {
816 // The append tab failed. Remove the TabStripObserver
817 if (observer) {
818 RemoveTabStripObserver(observer);
819 delete observer;
820 }
821
822 // This will be reached only if the tab could not be appended. In case of a
823 // successful tab append, a successful navigation notification triggers the
824 // send.
825 Send(new AutomationMsg_AppendTabResponse(message.routing_id(),
826 append_tab_response));
827 }
828}
829
830void AutomationProvider::NavigateToURL(const IPC::Message& message,
831 int handle, const GURL& url) {
832 int status = AUTOMATION_MSG_NAVIGATION_ERROR;
833
834 if (tab_tracker_->ContainsHandle(handle)) {
835 NavigationController* tab = tab_tracker_->GetResource(handle);
836
837 // Simulate what a user would do. Activate the tab and then navigate.
838 // We could allow navigating in a background tab in future.
839 Browser* browser = FindAndActivateTab(tab);
840
841 if (browser) {
842 AddNavigationStatusListener(tab,
843 new AutomationMsg_NavigateToURLResponse(
844 message.routing_id(), AUTOMATION_MSG_NAVIGATION_SUCCESS),
845 new AutomationMsg_NavigateToURLResponse(
846 message.routing_id(), AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED));
847 // TODO(darin): avoid conversion to GURL
848 browser->OpenURL(url, CURRENT_TAB, PageTransition::TYPED);
849 return;
850 }
851 }
852 Send(new AutomationMsg_NavigateToURLResponse(
853 message.routing_id(), AUTOMATION_MSG_NAVIGATION_ERROR));
854}
855
856void AutomationProvider::NavigationAsync(const IPC::Message& message,
857 int handle, const GURL& url) {
858 bool status = false;
859
860 if (tab_tracker_->ContainsHandle(handle)) {
861 NavigationController* tab = tab_tracker_->GetResource(handle);
862
863 // Simulate what a user would do. Activate the tab and then navigate.
864 // We could allow navigating in a background tab in future.
865 Browser* browser = FindAndActivateTab(tab);
866
867 if (browser) {
868 // Don't add any listener unless a callback mechanism is desired.
869 // TODO(vibhor): Do this if such a requirement arises in future.
870 browser->OpenURL(url, CURRENT_TAB, PageTransition::TYPED);
871 status = true;
872 }
873 }
874
875 Send(new AutomationMsg_NavigationAsyncResponse(message.routing_id(), status));
876}
877
878void AutomationProvider::GoBack(const IPC::Message& message, int handle) {
879 if (tab_tracker_->ContainsHandle(handle)) {
880 NavigationController* tab = tab_tracker_->GetResource(handle);
881 Browser* browser = FindAndActivateTab(tab);
882 if (browser && browser->IsCommandEnabled(IDC_BACK)) {
883 AddNavigationStatusListener(tab,
884 new AutomationMsg_GoBackResponse(
885 message.routing_id(), AUTOMATION_MSG_NAVIGATION_SUCCESS),
886 new AutomationMsg_GoBackResponse(
887 message.routing_id(), AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED));
888 browser->GoBack();
889 return;
890 }
891 }
892 Send(new AutomationMsg_GoBackResponse(message.routing_id(),
893 AUTOMATION_MSG_NAVIGATION_ERROR));
894}
895
896void AutomationProvider::GoForward(const IPC::Message& message, int handle) {
897 if (tab_tracker_->ContainsHandle(handle)) {
898 NavigationController* tab = tab_tracker_->GetResource(handle);
899 Browser* browser = FindAndActivateTab(tab);
900 if (browser && browser->IsCommandEnabled(IDC_FORWARD)) {
901 AddNavigationStatusListener(tab,
902 new AutomationMsg_GoForwardResponse(
903 message.routing_id(), AUTOMATION_MSG_NAVIGATION_SUCCESS),
904 new AutomationMsg_GoForwardResponse(
905 message.routing_id(), AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED));
906 browser->GoForward();
907 return;
908 }
909 }
910 Send(new AutomationMsg_GoForwardResponse(message.routing_id(),
911 AUTOMATION_MSG_NAVIGATION_ERROR));
912}
913
914void AutomationProvider::Reload(const IPC::Message& message, int handle) {
915 if (tab_tracker_->ContainsHandle(handle)) {
916 NavigationController* tab = tab_tracker_->GetResource(handle);
917 Browser* browser = FindAndActivateTab(tab);
918 if (browser && browser->IsCommandEnabled(IDC_RELOAD)) {
919 AddNavigationStatusListener(tab,
920 new AutomationMsg_ReloadResponse(
921 message.routing_id(), AUTOMATION_MSG_NAVIGATION_SUCCESS),
922 new AutomationMsg_ReloadResponse(
923 message.routing_id(), AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED));
924 browser->Reload();
925 return;
926 }
927 }
928 Send(new AutomationMsg_ReloadResponse(message.routing_id(),
929 AUTOMATION_MSG_NAVIGATION_ERROR));
930}
931
932void AutomationProvider::SetAuth(const IPC::Message& message, int tab_handle,
933 const std::wstring& username,
934 const std::wstring& password) {
935 int status = -1;
936
937 if (tab_tracker_->ContainsHandle(tab_handle)) {
938 NavigationController* tab = tab_tracker_->GetResource(tab_handle);
939 LoginHandlerMap::iterator iter = login_handler_map_.find(tab);
940
941 if (iter != login_handler_map_.end()) {
942 // If auth is needed again after this, assume login has failed. This is
943 // not strictly correct, because a navigation can require both proxy and
944 // server auth, but it should be OK for now.
945 LoginHandler* handler = iter->second;
946 AddNavigationStatusListener(tab,
947 new AutomationMsg_SetAuthResponse(message.routing_id(), 0),
948 new AutomationMsg_SetAuthResponse(message.routing_id(), -1));
949 handler->SetAuth(username, password);
950 status = 0;
951 }
952 }
953 if (status < 0) {
954 Send(new AutomationMsg_SetAuthResponse(message.routing_id(), status));
955 }
956}
957
958void AutomationProvider::CancelAuth(const IPC::Message& message,
959 int tab_handle) {
960 int status = -1;
961
962 if (tab_tracker_->ContainsHandle(tab_handle)) {
963 NavigationController* tab = tab_tracker_->GetResource(tab_handle);
964 LoginHandlerMap::iterator iter = login_handler_map_.find(tab);
965
966 if (iter != login_handler_map_.end()) {
967 // If auth is needed again after this, something is screwy.
968 LoginHandler* handler = iter->second;
969 AddNavigationStatusListener(tab,
970 new AutomationMsg_CancelAuthResponse(message.routing_id(), 0),
971 new AutomationMsg_CancelAuthResponse(message.routing_id(), -1));
972 handler->CancelAuth();
973 status = 0;
974 }
975 }
976 if (status < 0) {
977 Send(new AutomationMsg_CancelAuthResponse(message.routing_id(), status));
978 }
979}
980
981void AutomationProvider::NeedsAuth(const IPC::Message& message,
982 int tab_handle) {
983 bool needs_auth = false;
984
985 if (tab_tracker_->ContainsHandle(tab_handle)) {
986 NavigationController* tab = tab_tracker_->GetResource(tab_handle);
987 LoginHandlerMap::iterator iter = login_handler_map_.find(tab);
988
989 if (iter != login_handler_map_.end()) {
990 // The LoginHandler will be in our map IFF the tab needs auth.
991 needs_auth = true;
992 }
993 }
994
995 Send(new AutomationMsg_NeedsAuthResponse(message.routing_id(), needs_auth));
996}
997
998void AutomationProvider::GetRedirectsFrom(const IPC::Message& message,
999 int tab_handle,
1000 const GURL& source_url) {
1001 DCHECK(!redirect_query_) << "Can only handle one redirect query at once.";
1002 if (tab_tracker_->ContainsHandle(tab_handle)) {
1003 NavigationController* tab = tab_tracker_->GetResource(tab_handle);
1004 HistoryService* history_service =
1005 tab->profile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
1006
1007 DCHECK(history_service) << "Tab " << tab_handle << "'s profile " <<
1008 "has no history service";
1009 if (history_service) {
1010 // Schedule a history query for redirects. The response will be sent
1011 // asynchronously from the callback the history system uses to notify us
1012 // that it's done: OnRedirectQueryComplete.
1013 redirect_query_routing_id_ = message.routing_id();
1014 redirect_query_ = history_service->QueryRedirectsFrom(
1015 source_url, &consumer_,
1016 NewCallback(this, &AutomationProvider::OnRedirectQueryComplete));
1017 return; // Response will be sent when query completes.
1018 }
1019 }
1020
1021 // Send failure response.
1022 IPC::Message* msg = new IPC::Message(
1023 message.routing_id(), AutomationMsg_RedirectsFromResponse::ID,
1024 IPC::Message::PRIORITY_NORMAL);
1025 msg->WriteInt(-1); // Negative string count indicates an error.
1026 Send(msg);
1027}
1028
1029void AutomationProvider::GetActiveTabIndex(const IPC::Message& message,
1030 int handle) {
1031 int active_tab_index = -1; // -1 is the error code
1032 if (browser_tracker_->ContainsHandle(handle)) {
1033 Browser* browser = browser_tracker_->GetResource(handle);
1034 active_tab_index = browser->selected_index();
1035 }
1036 Send(new AutomationMsg_ActiveTabIndexResponse(message.routing_id(),
1037 active_tab_index));
1038}
1039
1040void AutomationProvider::GetBrowserWindowCount(const IPC::Message& message) {
1041 Send(new AutomationMsg_BrowserWindowCountResponse(
1042 message.routing_id(), static_cast<int>(BrowserList::size())));
1043}
1044
1045void AutomationProvider::GetBrowserWindow(const IPC::Message& message,
1046 int index) {
1047 int handle = 0;
1048 if (index >= 0) {
1049 BrowserList::const_iterator iter = BrowserList::begin();
1050
1051 for (; (iter != BrowserList::end()) && (index > 0); ++iter, --index);
1052 if (iter != BrowserList::end()) {
1053 handle = browser_tracker_->Add(*iter);
1054 }
1055 }
1056
1057 Send(new AutomationMsg_BrowserWindowResponse(message.routing_id(), handle));
1058}
1059
1060void AutomationProvider::GetLastActiveBrowserWindow(
1061 const IPC::Message& message) {
1062 int handle = 0;
1063 Browser* browser = BrowserList::GetLastActive();
1064 if (browser)
1065 handle = browser_tracker_->Add(browser);
1066 Send(new AutomationMsg_LastActiveBrowserWindowResponse(message.routing_id(),
1067 handle));
1068}
1069
1070BOOL CALLBACK EnumThreadWndProc(HWND hwnd, LPARAM l_param) {
1071 if (hwnd == reinterpret_cast<HWND>(l_param)) {
1072 return FALSE;
1073 }
1074 return TRUE;
1075}
1076
1077void AutomationProvider::GetActiveWindow(const IPC::Message& message) {
1078 HWND window = GetForegroundWindow();
1079
1080 // Let's make sure this window belongs to our process.
1081 if (EnumThreadWindows(::GetCurrentThreadId(),
1082 EnumThreadWndProc,
1083 reinterpret_cast<LPARAM>(window))) {
1084 // We enumerated all the windows and did not find the foreground window,
1085 // it is not our window, ignore it.
1086 Send(new AutomationMsg_ActiveWindowResponse(message.routing_id(), 0));
1087 return;
1088 }
1089
1090 int handle = window_tracker_->Add(window);
1091 Send(new AutomationMsg_ActiveWindowResponse(message.routing_id(), handle));
1092}
1093
1094void AutomationProvider::GetWindowHWND(const IPC::Message& message,
1095 int handle) {
1096 HWND win32_handle = window_tracker_->GetResource(handle);
1097 Send(new AutomationMsg_WindowHWNDResponse(message.routing_id(),
1098 win32_handle));
1099}
1100
[email protected]4ae62752008-08-04 23:28:471101void AutomationProvider::ExecuteBrowserCommand(const IPC::Message& message,
1102 int handle,
1103 int command) {
[email protected]4ae62752008-08-04 23:28:471104 bool success = false;
1105 if (browser_tracker_->ContainsHandle(handle)) {
1106 Browser* browser = browser_tracker_->GetResource(handle);
1107 if (browser->SupportsCommand(command) &&
1108 browser->IsCommandEnabled(command)) {
1109 browser->ExecuteCommand(command);
1110 success = true;
1111 }
1112 }
1113 Send(new AutomationMsg_WindowExecuteCommandResponse(message.routing_id(),
1114 success));
1115}
1116
initial.commit09911bf2008-07-26 23:55:291117void AutomationProvider::WindowGetViewBounds(const IPC::Message& message,
1118 int handle,
1119 int view_id,
1120 bool screen_coordinates) {
1121 bool succeeded = false;
1122 CRect bounds;
1123 bounds.SetRect(0, 0, 0, 0);
1124
1125 void* iter = NULL;
1126 if (window_tracker_->ContainsHandle(handle)) {
1127 HWND hwnd = window_tracker_->GetResource(handle);
1128 ChromeViews::RootView* root_view =
1129 ChromeViews::HWNDViewContainer::FindRootView(hwnd);
1130 if (root_view) {
1131 ChromeViews::View* view = root_view->GetViewByID(view_id);
1132 if (view) {
1133 succeeded = true;
1134 CPoint point(0, 0);
1135 if (screen_coordinates)
1136 ChromeViews::View::ConvertPointToScreen(view, &point);
1137 else
1138 ChromeViews::View::ConvertPointToView(view, root_view, &point);
1139 view->GetLocalBounds(&bounds, false);
1140 bounds.MoveToXY(point.x, point.y);
1141 }
1142 }
1143 }
1144
1145 Send(new AutomationMsg_WindowViewBoundsResponse(
1146 message.routing_id(), succeeded, gfx::Rect(bounds)));
1147}
1148
1149// This task enqueues a mouse event on the event loop, so that the view
1150// that it's being sent to can do the requisite post-processing.
1151class MouseEventTask : public Task {
1152 public:
1153 MouseEventTask(ChromeViews::View* view,
1154 ChromeViews::Event::EventType type,
1155 POINT point,
1156 int flags)
1157 : view_(view), type_(type), point_(point), flags_(flags) {}
1158 virtual ~MouseEventTask() {}
1159
1160 virtual void Run() {
1161 ChromeViews::MouseEvent event(type_, point_.x, point_.y, flags_);
1162 // We need to set the cursor position before we process the event because
1163 // some code (tab dragging, for instance) queries the actual cursor location
1164 // rather than the location of the mouse event. Note that the reason why
1165 // the drag code moved away from using mouse event locations was because
1166 // our conversion to screen location doesn't work well with multiple
1167 // monitors, so this only works reliably in a single monitor setup.
1168 CPoint screen_location = CPoint(point_.x, point_.y);
1169 view_->ConvertPointToScreen(view_, &screen_location);
1170 ::SetCursorPos(screen_location.x, screen_location.y);
1171 switch (type_) {
1172 case ChromeViews::Event::ET_MOUSE_PRESSED:
1173 view_->OnMousePressed(event);
1174 break;
1175
1176 case ChromeViews::Event::ET_MOUSE_DRAGGED:
1177 view_->OnMouseDragged(event);
1178 break;
1179
1180 case ChromeViews::Event::ET_MOUSE_RELEASED:
1181 view_->OnMouseReleased(event, false);
1182 break;
1183
1184 default:
1185 NOTREACHED();
1186 }
1187 }
1188
1189 private:
1190 ChromeViews::View* view_;
1191 ChromeViews::Event::EventType type_;
1192 POINT point_;
1193 int flags_;
1194
[email protected]5a52f162008-08-27 04:15:311195 DISALLOW_COPY_AND_ASSIGN(MouseEventTask);
initial.commit09911bf2008-07-26 23:55:291196};
1197
1198void AutomationProvider::ScheduleMouseEvent(ChromeViews::View* view,
1199 ChromeViews::Event::EventType type,
1200 POINT point,
1201 int flags) {
1202 MessageLoop::current()->PostTask(FROM_HERE,
1203 new MouseEventTask(view, type, point, flags));
1204}
1205
1206// This task just adds another task to the event queue. This is useful if
1207// you want to ensure that any tasks added to the event queue after this one
1208// have already been processed by the time |task| is run.
1209class InvokeTaskLaterTask : public Task {
1210 public:
1211 explicit InvokeTaskLaterTask(Task* task) : task_(task) {}
1212 virtual ~InvokeTaskLaterTask() {}
1213
1214 virtual void Run() {
1215 MessageLoop::current()->PostTask(FROM_HERE, task_);
1216 }
1217
1218 private:
1219 Task* task_;
1220
[email protected]5a52f162008-08-27 04:15:311221 DISALLOW_COPY_AND_ASSIGN(InvokeTaskLaterTask);
initial.commit09911bf2008-07-26 23:55:291222};
1223
1224// This task sends a WindowDragResponse message with the appropriate
1225// routing ID to the automation proxy. This is implemented as a task so that
1226// we know that the mouse events (and any tasks that they spawn on the message
1227// loop) have been processed by the time this is sent.
1228class WindowDragResponseTask : public Task {
1229 public:
1230 WindowDragResponseTask(AutomationProvider* provider, int routing_id)
1231 : provider_(provider), routing_id_(routing_id) {}
1232 virtual ~WindowDragResponseTask() {}
1233
1234 virtual void Run() {
1235 provider_->Send(new AutomationMsg_WindowDragResponse(routing_id_, true));
1236 }
1237
1238 private:
1239 AutomationProvider* provider_;
1240 int routing_id_;
1241
[email protected]5a52f162008-08-27 04:15:311242 DISALLOW_COPY_AND_ASSIGN(WindowDragResponseTask);
initial.commit09911bf2008-07-26 23:55:291243};
1244
1245void AutomationProvider::WindowSimulateClick(const IPC::Message& message,
1246 int handle,
1247 POINT click,
1248 int flags) {
1249 HWND hwnd = 0;
1250
1251 if (window_tracker_->ContainsHandle(handle)) {
1252 hwnd = window_tracker_->GetResource(handle);
1253
initial.commit09911bf2008-07-26 23:55:291254 ui_controls::SendMouseMove(click.x, click.y);
1255
1256 ui_controls::MouseButton button = ui_controls::LEFT;
1257 if ((flags & ChromeViews::Event::EF_LEFT_BUTTON_DOWN) ==
1258 ChromeViews::Event::EF_LEFT_BUTTON_DOWN) {
1259 button = ui_controls::LEFT;
1260 } else if ((flags & ChromeViews::Event::EF_RIGHT_BUTTON_DOWN) ==
1261 ChromeViews::Event::EF_RIGHT_BUTTON_DOWN) {
1262 button = ui_controls::RIGHT;
1263 } else if ((flags & ChromeViews::Event::EF_MIDDLE_BUTTON_DOWN) ==
1264 ChromeViews::Event::EF_MIDDLE_BUTTON_DOWN) {
1265 button = ui_controls::MIDDLE;
1266 } else {
1267 NOTREACHED();
1268 }
1269 ui_controls::SendMouseClick(button);
1270 }
1271}
1272
1273void AutomationProvider::WindowSimulateDrag(const IPC::Message& message,
1274 int handle,
1275 std::vector<POINT> drag_path,
[email protected]5e0f30c2008-08-14 22:52:441276 int flags,
1277 bool press_escape_en_route) {
initial.commit09911bf2008-07-26 23:55:291278 bool succeeded = false;
1279 if (browser_tracker_->ContainsHandle(handle) && (drag_path.size() > 1)) {
1280 succeeded = true;
1281
[email protected]0307076a2008-08-01 20:42:271282 UINT down_message = 0;
1283 UINT up_message = 0;
1284 WPARAM wparam_flags = 0;
1285 if (flags & ChromeViews::Event::EF_SHIFT_DOWN)
1286 wparam_flags |= MK_SHIFT;
1287 if (flags & ChromeViews::Event::EF_CONTROL_DOWN)
1288 wparam_flags |= MK_CONTROL;
1289 if (flags & ChromeViews::Event::EF_LEFT_BUTTON_DOWN) {
1290 wparam_flags |= MK_LBUTTON;
1291 down_message = WM_LBUTTONDOWN;
1292 up_message = WM_LBUTTONUP;
1293 }
1294 if (flags & ChromeViews::Event::EF_MIDDLE_BUTTON_DOWN) {
1295 wparam_flags |= MK_MBUTTON;
1296 down_message = WM_MBUTTONDOWN;
1297 up_message = WM_MBUTTONUP;
1298 }
1299 if (flags & ChromeViews::Event::EF_RIGHT_BUTTON_DOWN) {
1300 wparam_flags |= MK_RBUTTON;
1301 down_message = WM_LBUTTONDOWN;
1302 up_message = WM_LBUTTONUP;
1303 }
1304
initial.commit09911bf2008-07-26 23:55:291305 Browser* browser = browser_tracker_->GetResource(handle);
1306 DCHECK(browser);
[email protected]0307076a2008-08-01 20:42:271307 HWND top_level_hwnd = browser->GetTopLevelHWND();
1308 SetCursorPos(drag_path[0].x, drag_path[0].y);
1309 SendMessage(top_level_hwnd, down_message, wparam_flags,
1310 MAKELPARAM(drag_path[0].x, drag_path[0].y));
initial.commit09911bf2008-07-26 23:55:291311 for (int i = 1; i < static_cast<int>(drag_path.size()); ++i) {
[email protected]0307076a2008-08-01 20:42:271312 SetCursorPos(drag_path[i].x, drag_path[i].y);
1313 SendMessage(top_level_hwnd, WM_MOUSEMOVE, wparam_flags,
1314 MAKELPARAM(drag_path[i].x, drag_path[i].y));
initial.commit09911bf2008-07-26 23:55:291315 }
1316 POINT end = drag_path[drag_path.size() - 1];
[email protected]0307076a2008-08-01 20:42:271317 SetCursorPos(end.x, end.y);
[email protected]5e0f30c2008-08-14 22:52:441318
1319 if (press_escape_en_route) {
1320 // Press Escape.
1321 ui_controls::SendKeyPress(VK_ESCAPE,
1322 ((flags & ChromeViews::Event::EF_CONTROL_DOWN)
1323 == ChromeViews::Event::EF_CONTROL_DOWN),
1324 ((flags & ChromeViews::Event::EF_SHIFT_DOWN) ==
1325 ChromeViews::Event::EF_SHIFT_DOWN),
1326 ((flags & ChromeViews::Event::EF_ALT_DOWN) ==
1327 ChromeViews::Event::EF_ALT_DOWN));
1328 }
[email protected]0307076a2008-08-01 20:42:271329 SendMessage(top_level_hwnd, up_message, wparam_flags,
1330 MAKELPARAM(end.x, end.y));
initial.commit09911bf2008-07-26 23:55:291331
1332 MessageLoop::current()->PostTask(FROM_HERE,
1333 new InvokeTaskLaterTask(
1334 new WindowDragResponseTask(this, message.routing_id())));
1335 } else {
1336 Send(new AutomationMsg_WindowDragResponse(message.routing_id(), true));
1337 }
1338}
1339
1340void AutomationProvider::WindowSimulateKeyPress(const IPC::Message& message,
1341 int handle,
1342 wchar_t key,
1343 int flags) {
1344 if (!window_tracker_->ContainsHandle(handle))
1345 return;
1346
1347 // The key event is sent to whatever window is active.
1348 ui_controls::SendKeyPress(key,
1349 ((flags & ChromeViews::Event::EF_CONTROL_DOWN) ==
1350 ChromeViews::Event::EF_CONTROL_DOWN),
1351 ((flags & ChromeViews::Event::EF_SHIFT_DOWN) ==
1352 ChromeViews::Event::EF_SHIFT_DOWN),
1353 ((flags & ChromeViews::Event::EF_ALT_DOWN) ==
1354 ChromeViews::Event::EF_ALT_DOWN));
1355}
1356
1357void AutomationProvider::GetFocusedViewID(const IPC::Message& message,
1358 int handle) {
1359 int view_id = -1;
1360 if (window_tracker_->ContainsHandle(handle)) {
1361 HWND hwnd = window_tracker_->GetResource(handle);
1362 ChromeViews::FocusManager* focus_manager =
1363 ChromeViews::FocusManager::GetFocusManager(hwnd);
1364 DCHECK(focus_manager);
1365 ChromeViews::View* focused_view = focus_manager->GetFocusedView();
1366 if (focused_view)
1367 view_id = focused_view->GetID();
1368 }
1369 Send(new AutomationMsg_GetFocusedViewIDResponse(message.routing_id(),
1370 view_id));
1371}
1372
1373void AutomationProvider::SetWindowVisible(const IPC::Message& message,
1374 int handle, bool visible) {
1375 if (window_tracker_->ContainsHandle(handle)) {
1376 HWND hwnd = window_tracker_->GetResource(handle);
1377 ::ShowWindow(hwnd, visible ? SW_SHOW : SW_HIDE);
1378 Send(new AutomationMsg_SetWindowVisibleResponse(message.routing_id(),
1379 true));
1380 } else {
1381 Send(new AutomationMsg_SetWindowVisibleResponse(message.routing_id(),
1382 false));
1383 }
1384}
1385
1386void AutomationProvider::IsWindowActive(const IPC::Message& message,
1387 int handle) {
1388 if (window_tracker_->ContainsHandle(handle)) {
1389 HWND hwnd = window_tracker_->GetResource(handle);
1390 bool is_active = ::GetForegroundWindow() == hwnd;
1391 Send(new AutomationMsg_IsWindowActiveResponse(
1392 message.routing_id(), true, is_active));
1393 } else {
1394 Send(new AutomationMsg_IsWindowActiveResponse(message.routing_id(),
1395 false, false));
1396 }
1397}
1398
1399void AutomationProvider::ActivateWindow(const IPC::Message& message,
1400 int handle) {
1401 if (window_tracker_->ContainsHandle(handle)) {
1402 ::SetActiveWindow(window_tracker_->GetResource(handle));
1403 }
1404}
1405
1406void AutomationProvider::GetTabCount(const IPC::Message& message, int handle) {
1407 int tab_count = -1; // -1 is the error code
1408
1409 if (browser_tracker_->ContainsHandle(handle)) {
1410 Browser* browser = browser_tracker_->GetResource(handle);
1411 tab_count = browser->tab_count();
1412 }
1413
1414 Send(new AutomationMsg_TabCountResponse(message.routing_id(), tab_count));
1415}
1416
1417void AutomationProvider::GetTab(const IPC::Message& message,
1418 int win_handle, int tab_index) {
1419 void* iter = NULL;
1420 int tab_handle = 0;
1421 if (browser_tracker_->ContainsHandle(win_handle) && (tab_index >= 0)) {
1422 Browser* browser = browser_tracker_->GetResource(win_handle);
1423 if (tab_index < browser->tab_count()) {
1424 TabContents* tab_contents =
1425 browser->GetTabContentsAt(tab_index);
1426 tab_handle = tab_tracker_->Add(tab_contents->controller());
1427 }
1428 }
1429
1430 Send(new AutomationMsg_TabResponse(message.routing_id(), tab_handle));
1431}
1432
1433void AutomationProvider::GetTabTitle(const IPC::Message& message, int handle) {
1434 int title_string_size = -1; // -1 is the error code
1435 std::wstring title;
1436 if (tab_tracker_->ContainsHandle(handle)) {
1437 NavigationController* tab = tab_tracker_->GetResource(handle);
[email protected]1e5645ff2008-08-27 18:09:071438 title = tab->GetActiveEntry()->title();
initial.commit09911bf2008-07-26 23:55:291439 title_string_size = static_cast<int>(title.size());
1440 }
1441
1442 Send(new AutomationMsg_TabTitleResponse(message.routing_id(),
1443 title_string_size, title));
1444}
1445
1446void AutomationProvider::HandleUnused(const IPC::Message& message, int handle) {
1447 if (window_tracker_->ContainsHandle(handle)) {
1448 window_tracker_->Remove(window_tracker_->GetResource(handle));
1449 }
1450}
1451
1452void AutomationProvider::OnChannelError() {
1453 LOG(ERROR) << "AutomationProxy went away, shutting down app.";
[email protected]295039bd2008-08-15 04:32:571454 AutomationProviderList::GetInstance()->RemoveProvider(this);
initial.commit09911bf2008-07-26 23:55:291455}
1456
1457// TODO(brettw) change this to accept GURLs when history supports it
1458void AutomationProvider::OnRedirectQueryComplete(
1459 HistoryService::Handle request_handle,
1460 GURL from_url,
1461 bool success,
1462 HistoryService::RedirectList* redirects) {
1463 DCHECK(request_handle == redirect_query_);
1464
1465 // Respond to the pending request for the redirect list.
1466 IPC::Message* msg = new IPC::Message(redirect_query_routing_id_,
1467 AutomationMsg_RedirectsFromResponse::ID,
1468 IPC::Message::PRIORITY_NORMAL);
1469 if (success) {
1470 msg->WriteInt(static_cast<int>(redirects->size()));
1471 for (size_t i = 0; i < redirects->size(); i++)
1472 IPC::ParamTraits<GURL>::Write(msg, redirects->at(i));
1473 } else {
1474 msg->WriteInt(-1); // Negative count indicates failure.
1475 }
1476
1477 Send(msg);
1478 redirect_query_ = NULL;
1479}
1480
1481bool AutomationProvider::Send(IPC::Message* msg) {
[email protected]295039bd2008-08-15 04:32:571482 DCHECK(channel_.get());
1483 return channel_->Send(msg);
initial.commit09911bf2008-07-26 23:55:291484}
1485
1486Browser* AutomationProvider::FindAndActivateTab(
1487 NavigationController* controller) {
1488 int tab_index;
1489 Browser* browser = Browser::GetBrowserForController(controller, &tab_index);
1490 if (browser)
1491 browser->SelectTabContentsAt(tab_index, true);
1492
1493 return browser;
1494}
1495
1496void AutomationProvider::GetCookies(const IPC::Message& message,
1497 const GURL& url, int handle) {
1498 std::string value;
1499
1500 if (url.is_valid() && tab_tracker_->ContainsHandle(handle)) {
1501 NavigationController* tab = tab_tracker_->GetResource(handle);
1502 value =
1503 tab->profile()->GetRequestContext()->cookie_store()->GetCookies(url);
1504 }
1505
1506 Send(new AutomationMsg_GetCookiesResponse(message.routing_id(),
1507 static_cast<int>(value.size()), value));
1508}
1509
1510void AutomationProvider::SetCookie(const IPC::Message& message,
1511 const GURL& url,
1512 const std::string value,
1513 int handle) {
1514 int response_value = -1;
1515
1516 if (url.is_valid() && tab_tracker_->ContainsHandle(handle)) {
1517 NavigationController* tab = tab_tracker_->GetResource(handle);
1518 URLRequestContext* context = tab->profile()->GetRequestContext();
1519 if (context->cookie_store()->SetCookie(url, value))
1520 response_value = 1;
1521 }
1522
1523 Send(new AutomationMsg_SetCookieResponse(message.routing_id(),
1524 response_value));
1525}
1526
1527void AutomationProvider::GetTabURL(const IPC::Message& message, int handle) {
1528 bool success = false;
1529 GURL url;
1530 if (tab_tracker_->ContainsHandle(handle)) {
1531 NavigationController* tab = tab_tracker_->GetResource(handle);
1532 // Return what the user would see in the location bar.
[email protected]1e5645ff2008-08-27 18:09:071533 url = tab->GetActiveEntry()->display_url();
initial.commit09911bf2008-07-26 23:55:291534 success = true;
1535 }
1536
1537 Send(new AutomationMsg_TabURLResponse(message.routing_id(), success, url));
1538}
1539
1540void AutomationProvider::GetTabHWND(const IPC::Message& message, int handle) {
1541 HWND tab_hwnd = NULL;
1542
1543 if (tab_tracker_->ContainsHandle(handle)) {
1544 NavigationController* tab = tab_tracker_->GetResource(handle);
1545 tab_hwnd = tab->active_contents()->GetContainerHWND();
1546 }
1547
1548 Send(new AutomationMsg_TabHWNDResponse(message.routing_id(), tab_hwnd));
1549}
1550
1551void AutomationProvider::GetTabProcessID(
1552 const IPC::Message& message, int handle) {
1553 int process_id = -1;
1554
1555 if (tab_tracker_->ContainsHandle(handle)) {
1556 process_id = 0;
1557 NavigationController* tab = tab_tracker_->GetResource(handle);
1558 if (tab->active_contents()->AsWebContents()) {
1559 WebContents* web_contents = tab->active_contents()->AsWebContents();
1560 if (web_contents->process()) {
1561 process_id =
1562 process_util::GetProcId(web_contents->process()->process());
1563 }
1564 }
1565 }
1566
1567 Send(new AutomationMsg_TabProcessIDResponse(message.routing_id(),
1568 process_id));
1569}
1570
1571void AutomationProvider::ApplyAccelerator(int handle, int id) {
1572 if (browser_tracker_->ContainsHandle(handle)) {
1573 Browser* browser = browser_tracker_->GetResource(handle);
1574 browser->controller()->ExecuteCommand(id);
1575 }
1576}
1577
1578void AutomationProvider::ExecuteJavascript(const IPC::Message& message,
1579 int handle,
1580 const std::wstring& frame_xpath,
1581 const std::wstring& script) {
1582 bool succeeded = false;
[email protected]20e93d12008-08-28 16:31:571583 WebContents* web_contents = GetWebContentsForHandle(handle, NULL);
1584 if (web_contents) {
1585 // Set the routing id of this message with the controller.
1586 // This routing id needs to be remembered for the reverse
1587 // communication while sending back the response of
1588 // this javascript execution.
1589 std::wstring url;
1590 SStringPrintf(&url,
1591 L"javascript:void(window.domAutomationController.setAutomationId(%d));",
1592 message.routing_id());
initial.commit09911bf2008-07-26 23:55:291593
[email protected]1f5af4442008-09-25 22:11:061594 web_contents->render_view_host()->ExecuteJavascriptInWebFrame(
1595 frame_xpath, url);
1596 web_contents->render_view_host()->ExecuteJavascriptInWebFrame(
1597 frame_xpath, script);
[email protected]20e93d12008-08-28 16:31:571598 succeeded = true;
initial.commit09911bf2008-07-26 23:55:291599 }
1600
1601 if (!succeeded) {
1602 Send(new AutomationMsg_DomOperationResponse(message.routing_id(), ""));
1603 }
1604}
1605
1606void AutomationProvider::GetShelfVisibility(const IPC::Message& message,
1607 int handle) {
1608 bool visible = false;
[email protected]20e93d12008-08-28 16:31:571609
1610 WebContents* web_contents = GetWebContentsForHandle(handle, NULL);
1611 if (web_contents)
1612 visible = web_contents->IsDownloadShelfVisible();
initial.commit09911bf2008-07-26 23:55:291613
1614 Send(new AutomationMsg_ShelfVisibilityResponse(message.routing_id(),
1615 visible));
1616}
1617
1618void AutomationProvider::GetConstrainedWindowCount(const IPC::Message& message,
1619 int handle) {
1620 int count = -1; // -1 is the error code
1621 if (tab_tracker_->ContainsHandle(handle)) {
1622 NavigationController* nav_controller = tab_tracker_->GetResource(handle);
1623 TabContents* tab_contents = nav_controller->active_contents();
1624 if (tab_contents) {
1625 count = static_cast<int>(tab_contents->child_windows_.size());
1626 }
1627 }
1628
1629 Send(new AutomationMsg_ConstrainedWindowCountResponse(message.routing_id(),
1630 count));
1631}
1632
1633void AutomationProvider::GetConstrainedWindow(const IPC::Message& message,
1634 int handle, int index) {
1635 int cwindow_handle = 0;
1636 if (tab_tracker_->ContainsHandle(handle) && index >= 0) {
1637 NavigationController* nav_controller =
1638 tab_tracker_->GetResource(handle);
1639 TabContents* tab = nav_controller->active_contents();
[email protected]d5f942ba2008-09-26 19:30:341640 if (tab && index < static_cast<int>(tab->child_windows_.size())) {
1641 ConstrainedWindow* window = tab->child_windows_[index];
initial.commit09911bf2008-07-26 23:55:291642 cwindow_handle = cwindow_tracker_->Add(window);
1643 }
1644 }
1645
1646 Send(new AutomationMsg_ConstrainedWindowResponse(message.routing_id(),
1647 cwindow_handle));
1648}
1649
1650void AutomationProvider::GetConstrainedTitle(const IPC::Message& message,
1651 int handle) {
1652 int title_string_size = -1; // -1 is the error code
1653 std::wstring title;
1654 if (cwindow_tracker_->ContainsHandle(handle)) {
1655 ConstrainedWindow* window = cwindow_tracker_->GetResource(handle);
1656 title = window->GetWindowTitle();
1657 title_string_size = static_cast<int>(title.size());
1658 }
1659
1660 Send(new AutomationMsg_ConstrainedTitleResponse(message.routing_id(),
1661 title_string_size, title));
1662}
1663
1664void AutomationProvider::GetConstrainedWindowBounds(const IPC::Message& message,
1665 int handle) {
1666 bool exists = false;
1667 gfx::Rect rect(0, 0, 0, 0);
1668 if (cwindow_tracker_->ContainsHandle(handle)) {
1669 ConstrainedWindow* window = cwindow_tracker_->GetResource(handle);
1670 if (window) {
1671 exists = true;
1672 rect = window->GetCurrentBounds();
1673 }
1674 }
1675
1676 Send(new AutomationMsg_ConstrainedWindowBoundsResponse(message.routing_id(),
1677 exists, rect));
1678}
1679
1680void AutomationProvider::HandleFindInPageRequest(
1681 const IPC::Message& message, int handle, const std::wstring& find_request,
1682 int forward, int match_case) {
[email protected]5a52f162008-08-27 04:15:311683 NOTREACHED() << "This function has been deprecated."
1684 << "Please use HandleFindRequest instead.";
1685 Send(new AutomationMsg_FindInPageResponse(message.routing_id(), -1));
1686 return;
1687}
1688
1689void AutomationProvider::HandleFindRequest(const IPC::Message& message,
1690 int handle, const FindInPageRequest& request) {
initial.commit09911bf2008-07-26 23:55:291691 if (!tab_tracker_->ContainsHandle(handle)) {
1692 Send(new AutomationMsg_FindInPageResponse(message.routing_id(), -1));
1693 return;
1694 }
1695
1696 NavigationController* nav = tab_tracker_->GetResource(handle);
1697 TabContents* tab_contents = nav->active_contents();
1698
1699 find_in_page_observer_.reset(new
1700 FindInPageNotificationObserver(this, tab_contents, message.routing_id()));
1701
[email protected]edc28612008-08-14 20:23:361702 // The find in page dialog must be up for us to get the notification that the
1703 // find was complete
1704 if (tab_contents->AsWebContents()) {
1705 NavigationController* tab = tab_tracker_->GetResource(handle);
1706 Browser* browser = Browser::GetBrowserForController(tab, NULL);
1707 tab_contents->AsWebContents()->OpenFindInPageWindow(*browser);
1708 }
1709
initial.commit09911bf2008-07-26 23:55:291710 tab_contents->StartFinding(
1711 FindInPageNotificationObserver::kFindInPageRequestId,
[email protected]5a52f162008-08-27 04:15:311712 request.search_string, request.forward, request.match_case,
1713 request.find_next);
initial.commit09911bf2008-07-26 23:55:291714}
1715
[email protected]5f8af2a2008-08-06 22:49:451716void AutomationProvider::HandleOpenFindInPageRequest(
1717 const IPC::Message& message, int handle) {
[email protected]20e93d12008-08-28 16:31:571718 NavigationController* tab = NULL;
1719 WebContents* web_contents = GetWebContentsForHandle(handle, &tab);
1720 if (web_contents) {
[email protected]5f8af2a2008-08-06 22:49:451721 Browser* browser = Browser::GetBrowserForController(tab, NULL);
[email protected]20e93d12008-08-28 16:31:571722 web_contents->OpenFindInPageWindow(*browser);
[email protected]5f8af2a2008-08-06 22:49:451723 }
1724}
1725
[email protected]20e93d12008-08-28 16:31:571726void AutomationProvider::GetFindWindowVisibility(const IPC::Message& message,
1727 int handle) {
1728 bool visible = false;
1729 WebContents* web_contents = GetWebContentsForHandle(handle, NULL);
1730 if (web_contents)
1731 visible = web_contents->IsFindWindowFullyVisible();
1732
1733 Send(new AutomationMsg_FindWindowVisibilityResponse(message.routing_id(),
1734 visible));
1735}
1736
1737void AutomationProvider::HandleFindWindowLocationRequest(
1738 const IPC::Message& message, int handle) {
1739 int x = -1, y = -1;
1740 WebContents* web_contents = GetWebContentsForHandle(handle, NULL);
1741 if (web_contents)
1742 web_contents->GetFindInPageWindowLocation(&x, &y);
1743
1744 Send(new AutomationMsg_FindWindowLocationResponse(message.routing_id(),
1745 x, y));
1746}
1747
[email protected]c2cbeb92008-09-05 21:36:571748void AutomationProvider::GetBookmarkBarVisitility(const IPC::Message& message,
1749 int handle) {
1750 bool visible = false;
1751 bool animating = false;
1752
1753 void* iter = NULL;
1754 if (browser_tracker_->ContainsHandle(handle)) {
1755 Browser* browser = browser_tracker_->GetResource(handle);
1756 if (browser) {
1757 BookmarkBarView* bookmark_bar = browser->window()->GetBookmarkBarView();
1758 if (bookmark_bar) {
1759 animating = bookmark_bar->IsAnimating();
1760 visible = browser->window()->IsBookmarkBarVisible();
1761 }
1762 }
1763 }
1764
1765 Send(new AutomationMsg_BookmarkBarVisibilityResponse(message.routing_id(),
1766 visible, animating));
1767}
1768
initial.commit09911bf2008-07-26 23:55:291769void AutomationProvider::HandleInspectElementRequest(
1770 const IPC::Message& message, int handle, int x, int y) {
[email protected]20e93d12008-08-28 16:31:571771 WebContents* web_contents = GetWebContentsForHandle(handle, NULL);
1772 if (web_contents) {
[email protected]1f5af4442008-09-25 22:11:061773 web_contents->render_view_host()->InspectElementAt(x, y);
initial.commit09911bf2008-07-26 23:55:291774 inspect_element_routing_id_ = message.routing_id();
1775 } else {
1776 Send(new AutomationMsg_InspectElementResponse(message.routing_id(), -1));
1777 }
1778}
1779
1780void AutomationProvider::ReceivedInspectElementResponse(int num_resources) {
1781 Send(new AutomationMsg_InspectElementResponse(inspect_element_routing_id_,
1782 num_resources));
1783}
1784
1785// Helper class for making changes to the URLRequest ProtocolFactory on the
1786// IO thread.
1787class SetFilteredInetTask : public Task {
1788 public:
1789 explicit SetFilteredInetTask(bool enabled) : enabled_(enabled) { }
1790 virtual void Run() {
1791 if (enabled_) {
1792 URLRequestFilter::GetInstance()->ClearHandlers();
1793
1794 URLRequestFailedDnsJob::AddUITestUrls();
1795 URLRequestSlowDownloadJob::AddUITestUrls();
1796
1797 std::wstring root_http;
1798 PathService::Get(chrome::DIR_TEST_DATA, &root_http);
1799 URLRequestMockHTTPJob::AddUITestUrls(root_http);
1800 } else {
1801 // Revert to the default handlers.
1802 URLRequestFilter::GetInstance()->ClearHandlers();
1803 }
1804 }
1805 private:
1806 bool enabled_;
1807};
1808
1809void AutomationProvider::SetFilteredInet(const IPC::Message& message,
1810 bool enabled) {
1811 // Since this involves changing the URLRequest ProtocolFactory, we want to
1812 // run on the main thread.
1813 g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
1814 new SetFilteredInetTask(enabled));
1815}
1816
1817void AutomationProvider::GetDownloadDirectory(const IPC::Message& message,
1818 int handle) {
1819 DLOG(INFO) << "Handling download directory request";
1820 std::wstring download_directory;
1821 if (tab_tracker_->ContainsHandle(handle)) {
1822 NavigationController* tab = tab_tracker_->GetResource(handle);
1823 DownloadManager* dlm = tab->profile()->GetDownloadManager();
1824 DCHECK(dlm);
1825 download_directory = dlm->download_path();
1826 }
1827
1828 Send(new AutomationMsg_DownloadDirectoryResponse(message.routing_id(),
1829 download_directory));
1830}
1831
1832void AutomationProvider::OpenNewBrowserWindow(int show_command) {
1833 // We may have no current browser windows open so don't rely on
1834 // asking an existing browser to execute the IDC_NEWWINDOW command
1835 Browser::OpenNewBrowserWindow(profile_, show_command);
1836}
1837
1838void AutomationProvider::GetWindowForBrowser(const IPC::Message& message,
1839 int browser_handle) {
1840 bool success = false;
1841 int window_handle = 0;
1842
1843 if (browser_tracker_->ContainsHandle(browser_handle)) {
1844 Browser* browser = browser_tracker_->GetResource(browser_handle);
1845 HWND hwnd = browser->GetTopLevelHWND();
1846 // Add() returns the existing handle for the resource if any.
1847 window_handle = window_tracker_->Add(hwnd);
1848 success = true;
1849 }
1850 Send(new AutomationMsg_WindowForBrowserResponse(message.routing_id(),
1851 success, window_handle));
1852}
1853
1854void AutomationProvider::GetAutocompleteEditForBrowser(
1855 const IPC::Message& message,
1856 int browser_handle) {
1857 bool success = false;
1858 int autocomplete_edit_handle = 0;
1859
1860 if (browser_tracker_->ContainsHandle(browser_handle)) {
1861 Browser* browser = browser_tracker_->GetResource(browser_handle);
1862 LocationBarView* loc_bar_view = browser->GetLocationBarView();
[email protected]81c21222008-09-10 19:35:521863 AutocompleteEditView* edit_view = loc_bar_view->location_entry();
initial.commit09911bf2008-07-26 23:55:291864 // Add() returns the existing handle for the resource if any.
[email protected]81c21222008-09-10 19:35:521865 autocomplete_edit_handle = autocomplete_edit_tracker_->Add(edit_view);
initial.commit09911bf2008-07-26 23:55:291866 success = true;
1867 }
1868 Send(new AutomationMsg_AutocompleteEditForBrowserResponse(
1869 message.routing_id(), success, autocomplete_edit_handle));
1870}
1871
1872void AutomationProvider::GetBrowserForWindow(const IPC::Message& message,
1873 int window_handle) {
1874 bool success = false;
1875 int browser_handle = 0;
1876
1877 if (window_tracker_->ContainsHandle(window_handle)) {
1878 HWND window = window_tracker_->GetResource(window_handle);
1879 BrowserList::const_iterator iter = BrowserList::begin();
1880 Browser* browser = NULL;
1881 for (;iter != BrowserList::end(); ++iter) {
1882 if (window == (*iter)->GetTopLevelHWND()) {
1883 browser = *iter;
1884 break;
1885 }
1886 }
1887 if (browser) {
1888 // Add() returns the existing handle for the resource if any.
1889 browser_handle = browser_tracker_->Add(browser);
1890 success = true;
1891 }
1892 }
1893 Send(new AutomationMsg_BrowserForWindowResponse(message.routing_id(),
1894 success, browser_handle));
1895}
1896
1897void AutomationProvider::ShowInterstitialPage(const IPC::Message& message,
1898 int tab_handle,
1899 const std::string& html_text) {
1900 if (tab_tracker_->ContainsHandle(tab_handle)) {
1901 NavigationController* controller = tab_tracker_->GetResource(tab_handle);
1902 TabContents* tab_contents = controller->active_contents();
1903 if (tab_contents->type() == TAB_CONTENTS_WEB) {
1904 AddNavigationStatusListener(controller,
1905 new AutomationMsg_ShowInterstitialPageResponse(message.routing_id(),
1906 true),
1907 NULL);
1908 WebContents* web_contents = tab_contents->AsWebContents();
1909 web_contents->ShowInterstitialPage(html_text, NULL);
1910 return;
1911 }
1912 }
1913 Send(new AutomationMsg_ShowInterstitialPageResponse(message.routing_id(),
1914 false));
1915}
1916
1917void AutomationProvider::HideInterstitialPage(const IPC::Message& message,
1918 int tab_handle) {
[email protected]20e93d12008-08-28 16:31:571919 WebContents* web_contents = GetWebContentsForHandle(tab_handle, NULL);
1920 if (web_contents) {
1921 web_contents->HideInterstitialPage(false, false);
1922 Send(new AutomationMsg_HideInterstitialPageResponse(message.routing_id(),
1923 true));
1924 return;
initial.commit09911bf2008-07-26 23:55:291925 }
1926 Send(new AutomationMsg_HideInterstitialPageResponse(message.routing_id(),
1927 false));
1928}
1929
1930void AutomationProvider::CloseTab(const IPC::Message& message,
1931 int tab_handle,
1932 bool wait_until_closed) {
1933 if (tab_tracker_->ContainsHandle(tab_handle)) {
1934 NavigationController* controller = tab_tracker_->GetResource(tab_handle);
1935 int index;
1936 Browser* browser = Browser::GetBrowserForController(controller, &index);
1937 DCHECK(browser);
1938 TabClosedNotificationObserver* observer =
1939 new TabClosedNotificationObserver(browser, this, message.routing_id(),
1940 wait_until_closed);
1941 browser->CloseContents(controller->active_contents());
1942 } else {
1943 Send(new AutomationMsg_CloseTabResponse(message.routing_id(), false));
1944 }
1945}
1946
1947void AutomationProvider::CloseBrowser(const IPC::Message& message,
1948 int browser_handle) {
1949 if (browser_tracker_->ContainsHandle(browser_handle)) {
1950 Browser* browser = browser_tracker_->GetResource(browser_handle);
1951 new BrowserClosedNotificationObserver(browser, this, message.routing_id());
[email protected]f3e99e32008-07-30 04:48:391952 browser->window()->Close();
initial.commit09911bf2008-07-26 23:55:291953 } else {
1954 NOTREACHED();
1955 }
1956}
1957
1958void AutomationProvider::CreateExternalTab(const IPC::Message& message) {
1959 int tab_handle = 0;
1960 HWND tab_container_window = NULL;
1961 ExternalTabContainer *external_tab_container =
1962 new ExternalTabContainer(this);
1963 external_tab_container->Init(profile_);
1964 TabContents* tab_contents = external_tab_container->tab_contents();
1965 if (tab_contents) {
1966 tab_handle = tab_tracker_->Add(tab_contents->controller());
1967 tab_container_window = *external_tab_container;
1968 }
1969 Send(new AutomationMsg_CreateExternalTabResponse(message.routing_id(),
1970 tab_container_window,
1971 tab_handle));
1972}
1973
1974void AutomationProvider::NavigateInExternalTab(const IPC::Message& message,
1975 int handle, const GURL& url) {
1976 bool status = false;
1977
1978 if (tab_tracker_->ContainsHandle(handle)) {
1979 NavigationController* tab = tab_tracker_->GetResource(handle);
1980 tab->LoadURL(url, PageTransition::TYPED);
1981 status = true;
1982 }
1983
1984 Send(new AutomationMsg_NavigateInExternalTabResponse(message.routing_id(),
1985 status));
1986}
1987
1988void AutomationProvider::SetAcceleratorsForTab(const IPC::Message& message,
1989 int handle,
1990 HACCEL accel_table,
1991 int accel_entry_count) {
1992 bool status = false;
1993 if (tab_tracker_->ContainsHandle(handle)) {
1994 NavigationController* tab = tab_tracker_->GetResource(handle);
1995 TabContents* tab_contents = tab->GetTabContents(TAB_CONTENTS_WEB);
1996 ExternalTabContainer* external_tab_container =
1997 ExternalTabContainer::GetContainerForTab(
1998 tab_contents->GetContainerHWND());
1999 // This call is only valid on an externally hosted tab
2000 if (external_tab_container) {
2001 external_tab_container->SetAccelerators(accel_table,
2002 accel_entry_count);
2003 status = true;
2004 }
2005 }
2006 Send(new AutomationMsg_SetAcceleratorsForTabResponse(message.routing_id(),
2007 status));
2008}
2009
2010void AutomationProvider::ProcessUnhandledAccelerator(
2011 const IPC::Message& message, int handle, const MSG& msg) {
2012 if (tab_tracker_->ContainsHandle(handle)) {
2013 NavigationController* tab = tab_tracker_->GetResource(handle);
2014 TabContents* tab_contents = tab->GetTabContents(TAB_CONTENTS_WEB);
2015 ExternalTabContainer* external_tab_container =
2016 ExternalTabContainer::GetContainerForTab(
2017 tab_contents->GetContainerHWND());
2018 // This call is only valid on an externally hosted tab
2019 if (external_tab_container) {
2020 external_tab_container->ProcessUnhandledAccelerator(msg);
2021 }
2022 }
2023 // This message expects no response.
2024}
2025
2026void AutomationProvider::WaitForTabToBeRestored(
2027 const IPC::Message& message,
2028 int tab_handle) {
2029 if (tab_tracker_->ContainsHandle(tab_handle)) {
2030 NavigationController* tab = tab_tracker_->GetResource(tab_handle);
2031 restore_tracker_.reset(
2032 new NavigationControllerRestoredObserver(this, tab,
2033 message.routing_id()));
2034 }
2035}
2036
2037void AutomationProvider::GetSecurityState(const IPC::Message& message,
2038 int handle) {
2039 if (tab_tracker_->ContainsHandle(handle)) {
2040 NavigationController* tab = tab_tracker_->GetResource(handle);
2041 NavigationEntry* entry = tab->GetActiveEntry();
2042 Send(new AutomationMsg_GetSecurityStateResponse(message.routing_id(), true,
[email protected]eb34392b2008-08-19 15:42:202043 entry->ssl().security_style(), entry->ssl().cert_status(),
2044 entry->ssl().content_status()));
initial.commit09911bf2008-07-26 23:55:292045 } else {
2046 Send(new AutomationMsg_GetSecurityStateResponse(message.routing_id(), false,
2047 SECURITY_STYLE_UNKNOWN,
2048 0, 0));
2049 }
2050}
2051
2052void AutomationProvider::GetPageType(const IPC::Message& message, int handle) {
2053 if (tab_tracker_->ContainsHandle(handle)) {
2054 NavigationController* tab = tab_tracker_->GetResource(handle);
2055 NavigationEntry* entry = tab->GetActiveEntry();
[email protected]1e5645ff2008-08-27 18:09:072056 NavigationEntry::PageType page_type = entry->page_type();
initial.commit09911bf2008-07-26 23:55:292057 // In order to return the proper result when an interstitial is shown and
2058 // no navigation entry were created for it we need to ask the WebContents.
2059 if (page_type == NavigationEntry::NORMAL_PAGE &&
2060 tab->active_contents()->AsWebContents() &&
[email protected]b6e09ac2008-08-12 16:11:092061 tab->active_contents()->AsWebContents()->showing_interstitial_page())
initial.commit09911bf2008-07-26 23:55:292062 page_type = NavigationEntry::INTERSTITIAL_PAGE;
2063
2064 Send(new AutomationMsg_GetPageTypeResponse(message.routing_id(), true,
2065 page_type));
2066 } else {
2067 Send(new AutomationMsg_GetPageTypeResponse(message.routing_id(), false,
2068 NavigationEntry::NORMAL_PAGE));
2069 }
2070}
2071
2072void AutomationProvider::ActionOnSSLBlockingPage(const IPC::Message& message,
2073 int handle, bool proceed) {
2074 if (tab_tracker_->ContainsHandle(handle)) {
2075 NavigationController* tab = tab_tracker_->GetResource(handle);
2076 NavigationEntry* entry = tab->GetActiveEntry();
[email protected]1e5645ff2008-08-27 18:09:072077 if (entry->page_type() == NavigationEntry::INTERSTITIAL_PAGE) {
initial.commit09911bf2008-07-26 23:55:292078 TabContents* tab_contents = tab->GetTabContents(TAB_CONTENTS_WEB);
2079 SSLBlockingPage* ssl_blocking_page =
2080 SSLBlockingPage::GetSSLBlockingPage(tab_contents);
2081 if (ssl_blocking_page) {
2082 if (proceed) {
2083 AddNavigationStatusListener(tab,
2084 new AutomationMsg_ActionOnSSLBlockingPageResponse(
2085 message.routing_id(), true),
2086 new AutomationMsg_ActionOnSSLBlockingPageResponse(
2087 message.routing_id(), true));
2088 ssl_blocking_page->Proceed();
2089 return;
2090 }
2091 ssl_blocking_page->DontProceed();
2092 Send(new AutomationMsg_ActionOnSSLBlockingPageResponse(
2093 message.routing_id(), true));
2094 return;
2095 }
2096 }
2097 }
2098 // We failed.
2099 Send(new AutomationMsg_ActionOnSSLBlockingPageResponse(message.routing_id(),
2100 false));
2101}
2102
2103void AutomationProvider::BringBrowserToFront(const IPC::Message& message,
2104 int browser_handle) {
2105 if (browser_tracker_->ContainsHandle(browser_handle)) {
2106 Browser* browser = browser_tracker_->GetResource(browser_handle);
2107 browser->MoveToFront(true);
2108 Send(new AutomationMsg_BringBrowserToFrontResponse(message.routing_id(),
2109 true));
2110 } else {
2111 Send(new AutomationMsg_BringBrowserToFrontResponse(message.routing_id(),
2112 false));
2113 }
2114}
2115
2116void AutomationProvider::IsPageMenuCommandEnabled(const IPC::Message& message,
2117 int browser_handle,
2118 int message_num) {
2119 if (browser_tracker_->ContainsHandle(browser_handle)) {
2120 Browser* browser = browser_tracker_->GetResource(browser_handle);
2121 bool menu_item_enabled =
2122 browser->controller()->IsCommandEnabled(message_num);
2123 Send(new AutomationMsg_IsPageMenuCommandEnabledResponse(
2124 message.routing_id(), menu_item_enabled));
2125 } else {
2126 Send(new AutomationMsg_IsPageMenuCommandEnabledResponse(
2127 message.routing_id(), false));
2128 }
2129}
2130
2131void AutomationProvider::PrintNow(const IPC::Message& message, int tab_handle) {
[email protected]20e93d12008-08-28 16:31:572132 NavigationController* tab = NULL;
2133 WebContents* web_contents = GetWebContentsForHandle(tab_handle, &tab);
2134 if (web_contents) {
initial.commit09911bf2008-07-26 23:55:292135 FindAndActivateTab(tab);
[email protected]20e93d12008-08-28 16:31:572136 notification_observer_list_.AddObserver(
2137 new DocumentPrintedNotificationObserver(this, message.routing_id()));
2138 if (web_contents->PrintNow())
2139 return;
initial.commit09911bf2008-07-26 23:55:292140 }
2141 Send(new AutomationMsg_PrintNowResponse(message.routing_id(), false));
2142}
2143
2144void AutomationProvider::SavePage(const IPC::Message& message,
2145 int tab_handle,
2146 const std::wstring& file_name,
2147 const std::wstring& dir_path,
2148 int type) {
2149 if (!tab_tracker_->ContainsHandle(tab_handle)) {
2150 Send(new AutomationMsg_SavePageResponse(message.routing_id(), false));
2151 return;
2152 }
2153
2154 NavigationController* nav = tab_tracker_->GetResource(tab_handle);
2155 Browser* browser = FindAndActivateTab(nav);
2156 DCHECK(browser);
2157 if (!browser->IsCommandEnabled(IDC_SAVEPAGE)) {
2158 Send(new AutomationMsg_SavePageResponse(message.routing_id(), false));
2159 return;
2160 }
2161
2162 TabContents* tab_contents = nav->active_contents();
2163 if (tab_contents->type() != TAB_CONTENTS_WEB) {
2164 Send(new AutomationMsg_SavePageResponse(message.routing_id(), false));
2165 return;
2166 }
2167
2168 SavePackage::SavePackageType save_type =
2169 static_cast<SavePackage::SavePackageType>(type);
2170 DCHECK(save_type >= SavePackage::SAVE_AS_ONLY_HTML &&
2171 save_type <= SavePackage::SAVE_AS_COMPLETE_HTML);
2172 tab_contents->AsWebContents()->SavePage(file_name, dir_path, save_type);
2173
2174 Send(new AutomationMsg_SavePageResponse(
2175 message.routing_id(), true));
2176}
2177
2178void AutomationProvider::GetAutocompleteEditText(const IPC::Message& message,
2179 int autocomplete_edit_handle) {
2180 bool success = false;
2181 std::wstring text;
2182 if (autocomplete_edit_tracker_->ContainsHandle(autocomplete_edit_handle)) {
[email protected]81c21222008-09-10 19:35:522183 text = autocomplete_edit_tracker_->GetResource(autocomplete_edit_handle)->
2184 GetText();
initial.commit09911bf2008-07-26 23:55:292185 success = true;
2186 }
2187 Send(new AutomationMsg_AutocompleteEditGetTextResponse(message.routing_id(),
2188 success, text));
2189}
2190
2191void AutomationProvider::SetAutocompleteEditText(const IPC::Message& message,
2192 int autocomplete_edit_handle,
2193 const std::wstring& text) {
2194 bool success = false;
2195 if (autocomplete_edit_tracker_->ContainsHandle(autocomplete_edit_handle)) {
[email protected]81c21222008-09-10 19:35:522196 autocomplete_edit_tracker_->GetResource(autocomplete_edit_handle)->
2197 SetUserText(text);
initial.commit09911bf2008-07-26 23:55:292198 success = true;
2199 }
2200 Send(new AutomationMsg_AutocompleteEditSetTextResponse(
2201 message.routing_id(), success));
2202}
2203
2204void AutomationProvider::AutocompleteEditGetMatches(
2205 const IPC::Message& message,
2206 int autocomplete_edit_handle) {
2207 bool success = false;
2208 std::vector<AutocompleteMatchData> matches;
2209 if (autocomplete_edit_tracker_->ContainsHandle(autocomplete_edit_handle)) {
[email protected]81c21222008-09-10 19:35:522210 const AutocompleteResult* result = autocomplete_edit_tracker_->
2211 GetResource(autocomplete_edit_handle)->model()->latest_result();
initial.commit09911bf2008-07-26 23:55:292212 for (AutocompleteResult::const_iterator i = result->begin();
2213 i != result->end(); ++i)
2214 matches.push_back(AutocompleteMatchData(*i));
2215 success = true;
2216 }
2217 Send(new AutomationMsg_AutocompleteEditGetMatchesResponse(
2218 message.routing_id(), success, matches));
2219}
2220
2221void AutomationProvider::AutocompleteEditIsQueryInProgress(
2222 const IPC::Message& message,
2223 int autocomplete_edit_handle) {
2224 bool success = false;
2225 bool query_in_progress = false;
2226 if (autocomplete_edit_tracker_->ContainsHandle(autocomplete_edit_handle)) {
[email protected]81c21222008-09-10 19:35:522227 query_in_progress = autocomplete_edit_tracker_->
2228 GetResource(autocomplete_edit_handle)->model()->query_in_progress();
initial.commit09911bf2008-07-26 23:55:292229 success = true;
2230 }
2231 Send(new AutomationMsg_AutocompleteEditIsQueryInProgressResponse(
2232 message.routing_id(), success, query_in_progress));
2233}
2234
[email protected]18cb2572008-08-21 20:34:452235void AutomationProvider::OnMessageFromExternalHost(
2236 int handle, const std::string& target, const std::string& message) {
[email protected]fa83e762008-08-15 21:41:392237 if (tab_tracker_->ContainsHandle(handle)) {
2238 NavigationController* tab = tab_tracker_->GetResource(handle);
2239 if (!tab) {
2240 NOTREACHED();
2241 return;
2242 }
2243 TabContents* tab_contents = tab->GetTabContents(TAB_CONTENTS_WEB);
2244 if (!tab_contents) {
2245 NOTREACHED();
2246 return;
2247 }
2248
2249 WebContents* web_contents = tab_contents->AsWebContents();
2250 if (!web_contents) {
2251 NOTREACHED();
2252 return;
2253 }
2254
2255 RenderViewHost* view_host = web_contents->render_view_host();
2256 if (!view_host) {
2257 return;
2258 }
2259
[email protected]18cb2572008-08-21 20:34:452260 view_host->ForwardMessageFromExternalHost(target, message);
[email protected]fa83e762008-08-15 21:41:392261 }
2262}
2263
[email protected]20e93d12008-08-28 16:31:572264WebContents* AutomationProvider::GetWebContentsForHandle(
2265 int handle, NavigationController** tab) {
2266 WebContents* web_contents = NULL;
2267 if (tab_tracker_->ContainsHandle(handle)) {
2268 NavigationController* nav_controller = tab_tracker_->GetResource(handle);
2269 TabContents* tab_contents = nav_controller->active_contents();
2270 if (tab_contents && tab_contents->type() == TAB_CONTENTS_WEB) {
2271 web_contents = tab_contents->AsWebContents();
2272 if (tab)
2273 *tab = nav_controller;
2274 }
2275 }
2276 return web_contents;
2277}
2278
initial.commit09911bf2008-07-26 23:55:292279TestingAutomationProvider::TestingAutomationProvider(Profile* profile)
2280 : AutomationProvider(profile) {
2281 BrowserList::AddObserver(this);
2282 NotificationService::current()->AddObserver(this, NOTIFY_SESSION_END,
2283 NotificationService::AllSources());
2284}
2285
2286TestingAutomationProvider::~TestingAutomationProvider() {
2287 NotificationService::current()->RemoveObserver(this, NOTIFY_SESSION_END,
2288 NotificationService::AllSources());
2289 BrowserList::RemoveObserver(this);
2290}
2291
2292void TestingAutomationProvider::OnChannelError() {
2293 BrowserList::CloseAllBrowsers(true);
2294 AutomationProvider::OnChannelError();
2295}
2296
2297void TestingAutomationProvider::OnBrowserRemoving(const Browser* browser) {
2298 // For backwards compatibility with the testing automation interface, we
2299 // want the automation provider (and hence the process) to go away when the
2300 // last browser goes away.
2301 if (BrowserList::size() == 1) {
2302 // If you change this, update Observer for NOTIFY_SESSION_END below.
[email protected]295039bd2008-08-15 04:32:572303 MessageLoop::current()->PostTask(FROM_HERE,
2304 NewRunnableMethod(this, &TestingAutomationProvider::OnRemoveProvider));
initial.commit09911bf2008-07-26 23:55:292305 }
2306}
2307
2308void TestingAutomationProvider::Observe(NotificationType type,
2309 const NotificationSource& source,
2310 const NotificationDetails& details) {
2311 DCHECK(type == NOTIFY_SESSION_END);
2312 // OnBrowserRemoving does a ReleaseLater. When session end is received we exit
2313 // before the task runs resulting in this object not being deleted. This
2314 // Release balance out the Release scheduled by OnBrowserRemoving.
2315 Release();
2316}
[email protected]295039bd2008-08-15 04:32:572317
2318void TestingAutomationProvider::OnRemoveProvider() {
2319 AutomationProviderList::GetInstance()->RemoveProvider(this);
2320}
[email protected]8a3422c92008-09-24 17:42:422321
2322void AutomationProvider::GetSSLInfoBarCount(const IPC::Message& message,
2323 int handle) {
2324 int count = -1; // -1 means error.
2325 if (tab_tracker_->ContainsHandle(handle)) {
2326 NavigationController* nav_controller = tab_tracker_->GetResource(handle);
2327 if (nav_controller) {
2328 count = static_cast<int>(nav_controller->ssl_manager()->
2329 visible_info_bars_.size());
2330 }
2331 }
2332 Send(new AutomationMsg_GetSSLInfoBarCountResponse(message.routing_id(),
2333 count));
2334}
2335
2336void AutomationProvider::ClickSSLInfoBarLink(const IPC::Message& message,
2337 int handle,
2338 int info_bar_index,
2339 bool wait_for_navigation) {
2340 bool success = false;
2341 if (tab_tracker_->ContainsHandle(handle)) {
2342 NavigationController* nav_controller = tab_tracker_->GetResource(handle);
2343 if (nav_controller) {
2344 int count = static_cast<int>(nav_controller->ssl_manager()->
2345 visible_info_bars_.size());
2346 if (info_bar_index >= 0 && info_bar_index < count) {
2347 if (wait_for_navigation) {
2348 AddNavigationStatusListener(nav_controller,
2349 new AutomationMsg_ClickSSLInfoBarLinkResponse(
2350 message.routing_id(), true),
2351 new AutomationMsg_ClickSSLInfoBarLinkResponse(
2352 message.routing_id(), true));
2353 }
2354 SSLManager::SSLInfoBar* info_bar =
2355 nav_controller->ssl_manager()->visible_info_bars_.
2356 GetElementAt(info_bar_index);
2357 info_bar->LinkActivated(NULL, 0); // Parameters are not used.
2358 success = true;
2359 }
2360 }
2361 }
2362 if (!wait_for_navigation || !success)
2363 Send(new AutomationMsg_ClickSSLInfoBarLinkResponse(message.routing_id(),
2364 success));
2365}
2366
2367void AutomationProvider::GetLastNavigationTime(const IPC::Message& message,
2368 int handle) {
2369 Time time = tab_tracker_->GetLastNavigationTime(handle);
2370 Send(new AutomationMsg_GetLastNavigationTimeResponse(message.routing_id(),
2371 time.ToInternalValue()));
2372}
2373
2374void AutomationProvider::WaitForNavigation(const IPC::Message& message,
2375 int handle,
2376 int64 last_navigation_time) {
2377 NavigationController* controller = NULL;
2378 if (tab_tracker_->ContainsHandle(handle))
2379 controller = tab_tracker_->GetResource(handle);
2380
2381 Time time = tab_tracker_->GetLastNavigationTime(handle);
2382 if (time.ToInternalValue() > last_navigation_time || !controller) {
2383 Send(new AutomationMsg_WaitForNavigationResponse(message.routing_id(),
2384 controller != NULL));
2385 return;
2386 }
2387
2388 AddNavigationStatusListener(controller,
2389 new AutomationMsg_WaitForNavigationResponse(message.routing_id(),
2390 true),
2391 new AutomationMsg_WaitForNavigationResponse(message.routing_id(),
2392 true));
2393}
2394
2395void AutomationProvider::SetIntPreference(const IPC::Message& message,
2396 int handle,
2397 std::wstring name,
2398 int value) {
2399 bool success = false;
2400 if (browser_tracker_->ContainsHandle(handle)) {
2401 Browser* browser = browser_tracker_->GetResource(handle);
2402 browser->profile()->GetPrefs()->SetInteger(name.c_str(), value);
2403 success = true;
2404 }
2405 Send(new AutomationMsg_SetIntPreferenceResponse(message.routing_id(),
2406 success));
2407}