blob: 1456adc99ce06ee63becf67cced107ec26b2e137 [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 }
[email protected]d5798082008-09-29 21:02:03222 automation_->RemoveNavigationStatusListener(this);
initial.commit09911bf2008-07-26 23:55:29223 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
[email protected]cbab76d2008-10-13 22:42:47575class AutomationInterstitialPage : public InterstitialPage {
576 public:
577 AutomationInterstitialPage(TabContents* tab,
578 const GURL& url,
579 const std::string& contents)
580 : InterstitialPage(tab, true, url),
581 contents_(contents) {
582 }
583
584 virtual std::string GetHTMLContents() { return contents_; }
585
586 private:
587 std::string contents_;
588
589 DISALLOW_COPY_AND_ASSIGN(AutomationInterstitialPage);
590};
591
initial.commit09911bf2008-07-26 23:55:29592AutomationProvider::AutomationProvider(Profile* profile)
[email protected]295039bd2008-08-15 04:32:57593 : redirect_query_(0),
initial.commit09911bf2008-07-26 23:55:29594 profile_(profile) {
initial.commit09911bf2008-07-26 23:55:29595 browser_tracker_.reset(new AutomationBrowserTracker(this));
596 window_tracker_.reset(new AutomationWindowTracker(this));
597 tab_tracker_.reset(new AutomationTabTracker(this));
598 autocomplete_edit_tracker_.reset(
599 new AutomationAutocompleteEditTracker(this));
600 cwindow_tracker_.reset(new AutomationConstrainedWindowTracker(this));
601 new_tab_ui_load_observer_.reset(new NewTabUILoadObserver(this));
602 dom_operation_observer_.reset(new DomOperationNotificationObserver(this));
603 dom_inspector_observer_.reset(new DomInspectorNotificationObserver(this));
604}
605
606AutomationProvider::~AutomationProvider() {
[email protected]0da050b92008-08-19 19:29:47607 // Make sure that any outstanding NotificationObservers also get destroyed.
608 ObserverList<NotificationObserver>::Iterator it(notification_observer_list_);
[email protected]5a52f162008-08-27 04:15:31609 NotificationObserver* observer;
[email protected]0da050b92008-08-19 19:29:47610 while ((observer = it.GetNext()) != NULL)
611 delete observer;
initial.commit09911bf2008-07-26 23:55:29612}
613
614void AutomationProvider::ConnectToChannel(const std::wstring& channel_id) {
[email protected]295039bd2008-08-15 04:32:57615 channel_.reset(
616 new IPC::ChannelProxy(channel_id, IPC::Channel::MODE_CLIENT, this, NULL,
617 g_browser_process->io_thread()->message_loop()));
618 channel_->Send(new AutomationMsg_Hello(0));
initial.commit09911bf2008-07-26 23:55:29619}
620
621void AutomationProvider::SetExpectedTabCount(size_t expected_tabs) {
622 if (expected_tabs == 0) {
623 Send(new AutomationMsg_InitialLoadsComplete(0));
624 } else {
625 initial_load_observer_.reset(new InitialLoadObserver(expected_tabs, this));
626 }
627}
628
629NotificationObserver* AutomationProvider::AddNavigationStatusListener(
630 NavigationController* tab, IPC::Message* completed_response,
631 IPC::Message* auth_needed_response) {
632 NotificationObserver* observer =
633 new NavigationNotificationObserver(tab, this, completed_response,
634 auth_needed_response);
635 notification_observer_list_.AddObserver(observer);
636
637 return observer;
638}
639
640void AutomationProvider::RemoveNavigationStatusListener(
641 NotificationObserver* obs) {
642 notification_observer_list_.RemoveObserver(obs);
643}
644
645NotificationObserver* AutomationProvider::AddTabStripObserver(
646 Browser* parent, int32 routing_id) {
647 NotificationObserver* observer = new
648 TabAppendedNotificationObserver(parent, this, routing_id);
649 notification_observer_list_.AddObserver(observer);
650
651 return observer;
652}
653
654void AutomationProvider::RemoveTabStripObserver(NotificationObserver* obs) {
655 notification_observer_list_.RemoveObserver(obs);
656}
657
658void AutomationProvider::AddLoginHandler(NavigationController* tab,
659 LoginHandler* handler) {
660 login_handler_map_[tab] = handler;
661}
662
663void AutomationProvider::RemoveLoginHandler(NavigationController* tab) {
664 DCHECK(login_handler_map_[tab]);
665 login_handler_map_.erase(tab);
666}
667
668int AutomationProvider::GetIndexForNavigationController(
669 const NavigationController* controller, const Browser* parent) const {
670 DCHECK(parent);
671 return parent->GetIndexOfController(controller);
672}
673
674void AutomationProvider::OnMessageReceived(const IPC::Message& message) {
675 IPC_BEGIN_MESSAGE_MAP(AutomationProvider, message)
676 IPC_MESSAGE_HANDLER(AutomationMsg_CloseBrowserRequest, CloseBrowser)
677 IPC_MESSAGE_HANDLER(AutomationMsg_ActivateTabRequest, ActivateTab)
678 IPC_MESSAGE_HANDLER(AutomationMsg_ActiveTabIndexRequest, GetActiveTabIndex)
679 IPC_MESSAGE_HANDLER(AutomationMsg_AppendTabRequest, AppendTab)
680 IPC_MESSAGE_HANDLER(AutomationMsg_CloseTabRequest, CloseTab)
681 IPC_MESSAGE_HANDLER(AutomationMsg_GetCookiesRequest, GetCookies)
682 IPC_MESSAGE_HANDLER(AutomationMsg_SetCookieRequest, SetCookie)
683 IPC_MESSAGE_HANDLER(AutomationMsg_NavigateToURLRequest, NavigateToURL)
684 IPC_MESSAGE_HANDLER(AutomationMsg_NavigationAsyncRequest, NavigationAsync)
685 IPC_MESSAGE_HANDLER(AutomationMsg_GoBackRequest, GoBack)
686 IPC_MESSAGE_HANDLER(AutomationMsg_GoForwardRequest, GoForward)
687 IPC_MESSAGE_HANDLER(AutomationMsg_ReloadRequest, Reload)
688 IPC_MESSAGE_HANDLER(AutomationMsg_SetAuthRequest, SetAuth)
689 IPC_MESSAGE_HANDLER(AutomationMsg_CancelAuthRequest, CancelAuth)
690 IPC_MESSAGE_HANDLER(AutomationMsg_NeedsAuthRequest, NeedsAuth)
691 IPC_MESSAGE_HANDLER(AutomationMsg_RedirectsFromRequest, GetRedirectsFrom)
692 IPC_MESSAGE_HANDLER(AutomationMsg_BrowserWindowCountRequest,
693 GetBrowserWindowCount)
694 IPC_MESSAGE_HANDLER(AutomationMsg_BrowserWindowRequest, GetBrowserWindow)
695 IPC_MESSAGE_HANDLER(AutomationMsg_LastActiveBrowserWindowRequest,
696 GetLastActiveBrowserWindow)
697 IPC_MESSAGE_HANDLER(AutomationMsg_ActiveWindowRequest, GetActiveWindow)
698 IPC_MESSAGE_HANDLER(AutomationMsg_IsWindowActiveRequest, IsWindowActive)
699 IPC_MESSAGE_HANDLER(AutomationMsg_ActivateWindow, ActivateWindow);
700 IPC_MESSAGE_HANDLER(AutomationMsg_WindowHWNDRequest, GetWindowHWND)
[email protected]4ae62752008-08-04 23:28:47701 IPC_MESSAGE_HANDLER(AutomationMsg_WindowExecuteCommandRequest,
702 ExecuteBrowserCommand)
initial.commit09911bf2008-07-26 23:55:29703 IPC_MESSAGE_HANDLER(AutomationMsg_WindowViewBoundsRequest,
704 WindowGetViewBounds)
705 IPC_MESSAGE_HANDLER(AutomationMsg_SetWindowVisibleRequest, SetWindowVisible)
706 IPC_MESSAGE_HANDLER(AutomationMsg_WindowClickRequest, WindowSimulateClick)
707 IPC_MESSAGE_HANDLER(AutomationMsg_WindowKeyPressRequest,
708 WindowSimulateKeyPress)
709 IPC_MESSAGE_HANDLER(AutomationMsg_WindowDragRequest, WindowSimulateDrag)
710 IPC_MESSAGE_HANDLER(AutomationMsg_TabCountRequest, GetTabCount)
711 IPC_MESSAGE_HANDLER(AutomationMsg_TabRequest, GetTab)
712 IPC_MESSAGE_HANDLER(AutomationMsg_TabHWNDRequest, GetTabHWND)
713 IPC_MESSAGE_HANDLER(AutomationMsg_TabProcessIDRequest, GetTabProcessID)
714 IPC_MESSAGE_HANDLER(AutomationMsg_TabTitleRequest, GetTabTitle)
715 IPC_MESSAGE_HANDLER(AutomationMsg_TabURLRequest, GetTabURL)
716 IPC_MESSAGE_HANDLER(AutomationMsg_ShelfVisibilityRequest,
717 GetShelfVisibility)
718 IPC_MESSAGE_HANDLER(AutomationMsg_HandleUnused, HandleUnused)
719 IPC_MESSAGE_HANDLER(AutomationMsg_ApplyAcceleratorRequest, ApplyAccelerator)
720 IPC_MESSAGE_HANDLER(AutomationMsg_DomOperationRequest, ExecuteJavascript)
721 IPC_MESSAGE_HANDLER(AutomationMsg_ConstrainedWindowCountRequest,
722 GetConstrainedWindowCount)
723 IPC_MESSAGE_HANDLER(AutomationMsg_ConstrainedWindowRequest,
724 GetConstrainedWindow)
725 IPC_MESSAGE_HANDLER(AutomationMsg_ConstrainedTitleRequest,
726 GetConstrainedTitle)
727 IPC_MESSAGE_HANDLER(AutomationMsg_FindInPageRequest,
728 HandleFindInPageRequest)
729 IPC_MESSAGE_HANDLER(AutomationMsg_GetFocusedViewIDRequest, GetFocusedViewID)
730 IPC_MESSAGE_HANDLER(AutomationMsg_InspectElementRequest,
731 HandleInspectElementRequest)
732 IPC_MESSAGE_HANDLER(AutomationMsg_SetFilteredInet,
733 SetFilteredInet);
734 IPC_MESSAGE_HANDLER(AutomationMsg_DownloadDirectoryRequest,
735 GetDownloadDirectory);
736 IPC_MESSAGE_HANDLER(AutomationMsg_OpenNewBrowserWindow,
737 OpenNewBrowserWindow);
738 IPC_MESSAGE_HANDLER(AutomationMsg_WindowForBrowserRequest,
739 GetWindowForBrowser);
740 IPC_MESSAGE_HANDLER(AutomationMsg_AutocompleteEditForBrowserRequest,
741 GetAutocompleteEditForBrowser);
742 IPC_MESSAGE_HANDLER(AutomationMsg_BrowserForWindowRequest,
743 GetBrowserForWindow);
744 IPC_MESSAGE_HANDLER(AutomationMsg_CreateExternalTab, CreateExternalTab)
745 IPC_MESSAGE_HANDLER(AutomationMsg_NavigateInExternalTabRequest,
746 NavigateInExternalTab)
747 IPC_MESSAGE_HANDLER(AutomationMsg_ShowInterstitialPageRequest,
748 ShowInterstitialPage);
749 IPC_MESSAGE_HANDLER(AutomationMsg_HideInterstitialPageRequest,
750 HideInterstitialPage);
751 IPC_MESSAGE_HANDLER(AutomationMsg_SetAcceleratorsForTab,
752 SetAcceleratorsForTab)
753 IPC_MESSAGE_HANDLER(AutomationMsg_ProcessUnhandledAccelerator,
754 ProcessUnhandledAccelerator)
755 IPC_MESSAGE_HANDLER(AutomationMsg_WaitForTabToBeRestored,
756 WaitForTabToBeRestored)
757 IPC_MESSAGE_HANDLER(AutomationMsg_GetSecurityState,
758 GetSecurityState)
759 IPC_MESSAGE_HANDLER(AutomationMsg_GetPageType,
760 GetPageType)
761 IPC_MESSAGE_HANDLER(AutomationMsg_ActionOnSSLBlockingPage,
762 ActionOnSSLBlockingPage)
763 IPC_MESSAGE_HANDLER(AutomationMsg_BringBrowserToFront, BringBrowserToFront)
764 IPC_MESSAGE_HANDLER(AutomationMsg_IsPageMenuCommandEnabled,
765 IsPageMenuCommandEnabled)
766 IPC_MESSAGE_HANDLER(AutomationMsg_PrintNowRequest, PrintNow)
767 IPC_MESSAGE_HANDLER(AutomationMsg_SavePageRequest, SavePage)
768 IPC_MESSAGE_HANDLER(AutomationMsg_AutocompleteEditGetTextRequest,
769 GetAutocompleteEditText)
770 IPC_MESSAGE_HANDLER(AutomationMsg_AutocompleteEditSetTextRequest,
771 SetAutocompleteEditText)
772 IPC_MESSAGE_HANDLER(AutomationMsg_AutocompleteEditIsQueryInProgressRequest,
773 AutocompleteEditIsQueryInProgress)
774 IPC_MESSAGE_HANDLER(AutomationMsg_AutocompleteEditGetMatchesRequest,
775 AutocompleteEditGetMatches)
776 IPC_MESSAGE_HANDLER(AutomationMsg_ConstrainedWindowBoundsRequest,
777 GetConstrainedWindowBounds)
[email protected]5f8af2a2008-08-06 22:49:45778 IPC_MESSAGE_HANDLER(AutomationMsg_OpenFindInPageRequest,
779 HandleOpenFindInPageRequest)
[email protected]18cb2572008-08-21 20:34:45780 IPC_MESSAGE_HANDLER(AutomationMsg_HandleMessageFromExternalHost,
781 OnMessageFromExternalHost)
[email protected]5a52f162008-08-27 04:15:31782 IPC_MESSAGE_HANDLER(AutomationMsg_FindRequest,
783 HandleFindRequest)
[email protected]20e93d12008-08-28 16:31:57784 IPC_MESSAGE_HANDLER(AutomationMsg_FindWindowVisibilityRequest,
785 GetFindWindowVisibility)
786 IPC_MESSAGE_HANDLER(AutomationMsg_FindWindowLocationRequest,
787 HandleFindWindowLocationRequest)
[email protected]c2cbeb92008-09-05 21:36:57788 IPC_MESSAGE_HANDLER(AutomationMsg_BookmarkBarVisibilityRequest,
789 GetBookmarkBarVisitility)
[email protected]8a3422c92008-09-24 17:42:42790 IPC_MESSAGE_HANDLER(AutomationMsg_GetSSLInfoBarCountRequest,
791 GetSSLInfoBarCount)
792 IPC_MESSAGE_HANDLER(AutomationMsg_ClickSSLInfoBarLinkRequest,
793 ClickSSLInfoBarLink)
794 IPC_MESSAGE_HANDLER(AutomationMsg_GetLastNavigationTimeRequest,
795 GetLastNavigationTime)
796 IPC_MESSAGE_HANDLER(AutomationMsg_WaitForNavigationRequest,
797 WaitForNavigation)
798 IPC_MESSAGE_HANDLER(AutomationMsg_SetIntPreferenceRequest,
799 SetIntPreference)
initial.commit09911bf2008-07-26 23:55:29800 IPC_END_MESSAGE_MAP()
801}
802
803void AutomationProvider::ActivateTab(const IPC::Message& message,
804 int handle, int at_index) {
805 int status = -1;
806 if (browser_tracker_->ContainsHandle(handle) && at_index > -1) {
807 Browser* browser = browser_tracker_->GetResource(handle);
808 if (at_index >= 0 && at_index < browser->tab_count()) {
809 browser->SelectTabContentsAt(at_index, true);
810 status = 0;
811 }
812 }
813 Send(new AutomationMsg_ActivateTabResponse(message.routing_id(), status));
814}
815
816void AutomationProvider::AppendTab(const IPC::Message& message,
817 int handle, const GURL& url) {
818 int append_tab_response = -1; // -1 is the error code
819 NotificationObserver* observer = NULL;
820
821 if (browser_tracker_->ContainsHandle(handle)) {
822 Browser* browser = browser_tracker_->GetResource(handle);
823 observer = AddTabStripObserver(browser, message.routing_id());
824 TabContents* tab_contents =
825 browser->AddTabWithURL(url, PageTransition::TYPED, true, NULL);
826 if (tab_contents) {
827 append_tab_response =
828 GetIndexForNavigationController(tab_contents->controller(), browser);
829 }
830 }
831
832 if (append_tab_response < 0) {
833 // The append tab failed. Remove the TabStripObserver
834 if (observer) {
835 RemoveTabStripObserver(observer);
836 delete observer;
837 }
838
839 // This will be reached only if the tab could not be appended. In case of a
840 // successful tab append, a successful navigation notification triggers the
841 // send.
842 Send(new AutomationMsg_AppendTabResponse(message.routing_id(),
843 append_tab_response));
844 }
845}
846
847void AutomationProvider::NavigateToURL(const IPC::Message& message,
848 int handle, const GURL& url) {
849 int status = AUTOMATION_MSG_NAVIGATION_ERROR;
850
851 if (tab_tracker_->ContainsHandle(handle)) {
852 NavigationController* tab = tab_tracker_->GetResource(handle);
853
854 // Simulate what a user would do. Activate the tab and then navigate.
855 // We could allow navigating in a background tab in future.
856 Browser* browser = FindAndActivateTab(tab);
857
858 if (browser) {
859 AddNavigationStatusListener(tab,
860 new AutomationMsg_NavigateToURLResponse(
861 message.routing_id(), AUTOMATION_MSG_NAVIGATION_SUCCESS),
862 new AutomationMsg_NavigateToURLResponse(
863 message.routing_id(), AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED));
864 // TODO(darin): avoid conversion to GURL
865 browser->OpenURL(url, CURRENT_TAB, PageTransition::TYPED);
866 return;
867 }
868 }
869 Send(new AutomationMsg_NavigateToURLResponse(
870 message.routing_id(), AUTOMATION_MSG_NAVIGATION_ERROR));
871}
872
873void AutomationProvider::NavigationAsync(const IPC::Message& message,
874 int handle, const GURL& url) {
875 bool status = false;
876
877 if (tab_tracker_->ContainsHandle(handle)) {
878 NavigationController* tab = tab_tracker_->GetResource(handle);
879
880 // Simulate what a user would do. Activate the tab and then navigate.
881 // We could allow navigating in a background tab in future.
882 Browser* browser = FindAndActivateTab(tab);
883
884 if (browser) {
885 // Don't add any listener unless a callback mechanism is desired.
886 // TODO(vibhor): Do this if such a requirement arises in future.
887 browser->OpenURL(url, CURRENT_TAB, PageTransition::TYPED);
888 status = true;
889 }
890 }
891
892 Send(new AutomationMsg_NavigationAsyncResponse(message.routing_id(), status));
893}
894
895void AutomationProvider::GoBack(const IPC::Message& message, int handle) {
896 if (tab_tracker_->ContainsHandle(handle)) {
897 NavigationController* tab = tab_tracker_->GetResource(handle);
898 Browser* browser = FindAndActivateTab(tab);
899 if (browser && browser->IsCommandEnabled(IDC_BACK)) {
900 AddNavigationStatusListener(tab,
901 new AutomationMsg_GoBackResponse(
902 message.routing_id(), AUTOMATION_MSG_NAVIGATION_SUCCESS),
903 new AutomationMsg_GoBackResponse(
904 message.routing_id(), AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED));
905 browser->GoBack();
906 return;
907 }
908 }
909 Send(new AutomationMsg_GoBackResponse(message.routing_id(),
910 AUTOMATION_MSG_NAVIGATION_ERROR));
911}
912
913void AutomationProvider::GoForward(const IPC::Message& message, int handle) {
914 if (tab_tracker_->ContainsHandle(handle)) {
915 NavigationController* tab = tab_tracker_->GetResource(handle);
916 Browser* browser = FindAndActivateTab(tab);
917 if (browser && browser->IsCommandEnabled(IDC_FORWARD)) {
918 AddNavigationStatusListener(tab,
919 new AutomationMsg_GoForwardResponse(
920 message.routing_id(), AUTOMATION_MSG_NAVIGATION_SUCCESS),
921 new AutomationMsg_GoForwardResponse(
922 message.routing_id(), AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED));
923 browser->GoForward();
924 return;
925 }
926 }
927 Send(new AutomationMsg_GoForwardResponse(message.routing_id(),
928 AUTOMATION_MSG_NAVIGATION_ERROR));
929}
930
931void AutomationProvider::Reload(const IPC::Message& message, int handle) {
932 if (tab_tracker_->ContainsHandle(handle)) {
933 NavigationController* tab = tab_tracker_->GetResource(handle);
934 Browser* browser = FindAndActivateTab(tab);
935 if (browser && browser->IsCommandEnabled(IDC_RELOAD)) {
936 AddNavigationStatusListener(tab,
937 new AutomationMsg_ReloadResponse(
938 message.routing_id(), AUTOMATION_MSG_NAVIGATION_SUCCESS),
939 new AutomationMsg_ReloadResponse(
940 message.routing_id(), AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED));
941 browser->Reload();
942 return;
943 }
944 }
945 Send(new AutomationMsg_ReloadResponse(message.routing_id(),
946 AUTOMATION_MSG_NAVIGATION_ERROR));
947}
948
949void AutomationProvider::SetAuth(const IPC::Message& message, int tab_handle,
950 const std::wstring& username,
951 const std::wstring& password) {
952 int status = -1;
953
954 if (tab_tracker_->ContainsHandle(tab_handle)) {
955 NavigationController* tab = tab_tracker_->GetResource(tab_handle);
956 LoginHandlerMap::iterator iter = login_handler_map_.find(tab);
957
958 if (iter != login_handler_map_.end()) {
959 // If auth is needed again after this, assume login has failed. This is
960 // not strictly correct, because a navigation can require both proxy and
961 // server auth, but it should be OK for now.
962 LoginHandler* handler = iter->second;
963 AddNavigationStatusListener(tab,
964 new AutomationMsg_SetAuthResponse(message.routing_id(), 0),
965 new AutomationMsg_SetAuthResponse(message.routing_id(), -1));
966 handler->SetAuth(username, password);
967 status = 0;
968 }
969 }
970 if (status < 0) {
971 Send(new AutomationMsg_SetAuthResponse(message.routing_id(), status));
972 }
973}
974
975void AutomationProvider::CancelAuth(const IPC::Message& message,
976 int tab_handle) {
977 int status = -1;
978
979 if (tab_tracker_->ContainsHandle(tab_handle)) {
980 NavigationController* tab = tab_tracker_->GetResource(tab_handle);
981 LoginHandlerMap::iterator iter = login_handler_map_.find(tab);
982
983 if (iter != login_handler_map_.end()) {
984 // If auth is needed again after this, something is screwy.
985 LoginHandler* handler = iter->second;
986 AddNavigationStatusListener(tab,
987 new AutomationMsg_CancelAuthResponse(message.routing_id(), 0),
988 new AutomationMsg_CancelAuthResponse(message.routing_id(), -1));
989 handler->CancelAuth();
990 status = 0;
991 }
992 }
993 if (status < 0) {
994 Send(new AutomationMsg_CancelAuthResponse(message.routing_id(), status));
995 }
996}
997
998void AutomationProvider::NeedsAuth(const IPC::Message& message,
999 int tab_handle) {
1000 bool needs_auth = false;
1001
1002 if (tab_tracker_->ContainsHandle(tab_handle)) {
1003 NavigationController* tab = tab_tracker_->GetResource(tab_handle);
1004 LoginHandlerMap::iterator iter = login_handler_map_.find(tab);
1005
1006 if (iter != login_handler_map_.end()) {
1007 // The LoginHandler will be in our map IFF the tab needs auth.
1008 needs_auth = true;
1009 }
1010 }
1011
1012 Send(new AutomationMsg_NeedsAuthResponse(message.routing_id(), needs_auth));
1013}
1014
1015void AutomationProvider::GetRedirectsFrom(const IPC::Message& message,
1016 int tab_handle,
1017 const GURL& source_url) {
1018 DCHECK(!redirect_query_) << "Can only handle one redirect query at once.";
1019 if (tab_tracker_->ContainsHandle(tab_handle)) {
1020 NavigationController* tab = tab_tracker_->GetResource(tab_handle);
1021 HistoryService* history_service =
1022 tab->profile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
1023
1024 DCHECK(history_service) << "Tab " << tab_handle << "'s profile " <<
1025 "has no history service";
1026 if (history_service) {
1027 // Schedule a history query for redirects. The response will be sent
1028 // asynchronously from the callback the history system uses to notify us
1029 // that it's done: OnRedirectQueryComplete.
1030 redirect_query_routing_id_ = message.routing_id();
1031 redirect_query_ = history_service->QueryRedirectsFrom(
1032 source_url, &consumer_,
1033 NewCallback(this, &AutomationProvider::OnRedirectQueryComplete));
1034 return; // Response will be sent when query completes.
1035 }
1036 }
1037
1038 // Send failure response.
1039 IPC::Message* msg = new IPC::Message(
1040 message.routing_id(), AutomationMsg_RedirectsFromResponse::ID,
1041 IPC::Message::PRIORITY_NORMAL);
1042 msg->WriteInt(-1); // Negative string count indicates an error.
1043 Send(msg);
1044}
1045
1046void AutomationProvider::GetActiveTabIndex(const IPC::Message& message,
1047 int handle) {
1048 int active_tab_index = -1; // -1 is the error code
1049 if (browser_tracker_->ContainsHandle(handle)) {
1050 Browser* browser = browser_tracker_->GetResource(handle);
1051 active_tab_index = browser->selected_index();
1052 }
1053 Send(new AutomationMsg_ActiveTabIndexResponse(message.routing_id(),
1054 active_tab_index));
1055}
1056
1057void AutomationProvider::GetBrowserWindowCount(const IPC::Message& message) {
1058 Send(new AutomationMsg_BrowserWindowCountResponse(
1059 message.routing_id(), static_cast<int>(BrowserList::size())));
1060}
1061
1062void AutomationProvider::GetBrowserWindow(const IPC::Message& message,
1063 int index) {
1064 int handle = 0;
1065 if (index >= 0) {
1066 BrowserList::const_iterator iter = BrowserList::begin();
1067
1068 for (; (iter != BrowserList::end()) && (index > 0); ++iter, --index);
1069 if (iter != BrowserList::end()) {
1070 handle = browser_tracker_->Add(*iter);
1071 }
1072 }
1073
1074 Send(new AutomationMsg_BrowserWindowResponse(message.routing_id(), handle));
1075}
1076
1077void AutomationProvider::GetLastActiveBrowserWindow(
1078 const IPC::Message& message) {
1079 int handle = 0;
1080 Browser* browser = BrowserList::GetLastActive();
1081 if (browser)
1082 handle = browser_tracker_->Add(browser);
1083 Send(new AutomationMsg_LastActiveBrowserWindowResponse(message.routing_id(),
1084 handle));
1085}
1086
1087BOOL CALLBACK EnumThreadWndProc(HWND hwnd, LPARAM l_param) {
1088 if (hwnd == reinterpret_cast<HWND>(l_param)) {
1089 return FALSE;
1090 }
1091 return TRUE;
1092}
1093
1094void AutomationProvider::GetActiveWindow(const IPC::Message& message) {
1095 HWND window = GetForegroundWindow();
1096
1097 // Let's make sure this window belongs to our process.
1098 if (EnumThreadWindows(::GetCurrentThreadId(),
1099 EnumThreadWndProc,
1100 reinterpret_cast<LPARAM>(window))) {
1101 // We enumerated all the windows and did not find the foreground window,
1102 // it is not our window, ignore it.
1103 Send(new AutomationMsg_ActiveWindowResponse(message.routing_id(), 0));
1104 return;
1105 }
1106
1107 int handle = window_tracker_->Add(window);
1108 Send(new AutomationMsg_ActiveWindowResponse(message.routing_id(), handle));
1109}
1110
1111void AutomationProvider::GetWindowHWND(const IPC::Message& message,
1112 int handle) {
1113 HWND win32_handle = window_tracker_->GetResource(handle);
1114 Send(new AutomationMsg_WindowHWNDResponse(message.routing_id(),
1115 win32_handle));
1116}
1117
[email protected]4ae62752008-08-04 23:28:471118void AutomationProvider::ExecuteBrowserCommand(const IPC::Message& message,
1119 int handle,
1120 int command) {
[email protected]4ae62752008-08-04 23:28:471121 bool success = false;
1122 if (browser_tracker_->ContainsHandle(handle)) {
1123 Browser* browser = browser_tracker_->GetResource(handle);
1124 if (browser->SupportsCommand(command) &&
1125 browser->IsCommandEnabled(command)) {
1126 browser->ExecuteCommand(command);
1127 success = true;
1128 }
1129 }
1130 Send(new AutomationMsg_WindowExecuteCommandResponse(message.routing_id(),
1131 success));
1132}
1133
initial.commit09911bf2008-07-26 23:55:291134void AutomationProvider::WindowGetViewBounds(const IPC::Message& message,
1135 int handle,
1136 int view_id,
1137 bool screen_coordinates) {
1138 bool succeeded = false;
1139 CRect bounds;
1140 bounds.SetRect(0, 0, 0, 0);
1141
1142 void* iter = NULL;
1143 if (window_tracker_->ContainsHandle(handle)) {
1144 HWND hwnd = window_tracker_->GetResource(handle);
1145 ChromeViews::RootView* root_view =
1146 ChromeViews::HWNDViewContainer::FindRootView(hwnd);
1147 if (root_view) {
1148 ChromeViews::View* view = root_view->GetViewByID(view_id);
1149 if (view) {
1150 succeeded = true;
1151 CPoint point(0, 0);
1152 if (screen_coordinates)
1153 ChromeViews::View::ConvertPointToScreen(view, &point);
1154 else
1155 ChromeViews::View::ConvertPointToView(view, root_view, &point);
1156 view->GetLocalBounds(&bounds, false);
1157 bounds.MoveToXY(point.x, point.y);
1158 }
1159 }
1160 }
1161
1162 Send(new AutomationMsg_WindowViewBoundsResponse(
1163 message.routing_id(), succeeded, gfx::Rect(bounds)));
1164}
1165
1166// This task enqueues a mouse event on the event loop, so that the view
1167// that it's being sent to can do the requisite post-processing.
1168class MouseEventTask : public Task {
1169 public:
1170 MouseEventTask(ChromeViews::View* view,
1171 ChromeViews::Event::EventType type,
1172 POINT point,
1173 int flags)
1174 : view_(view), type_(type), point_(point), flags_(flags) {}
1175 virtual ~MouseEventTask() {}
1176
1177 virtual void Run() {
1178 ChromeViews::MouseEvent event(type_, point_.x, point_.y, flags_);
1179 // We need to set the cursor position before we process the event because
1180 // some code (tab dragging, for instance) queries the actual cursor location
1181 // rather than the location of the mouse event. Note that the reason why
1182 // the drag code moved away from using mouse event locations was because
1183 // our conversion to screen location doesn't work well with multiple
1184 // monitors, so this only works reliably in a single monitor setup.
1185 CPoint screen_location = CPoint(point_.x, point_.y);
1186 view_->ConvertPointToScreen(view_, &screen_location);
1187 ::SetCursorPos(screen_location.x, screen_location.y);
1188 switch (type_) {
1189 case ChromeViews::Event::ET_MOUSE_PRESSED:
1190 view_->OnMousePressed(event);
1191 break;
1192
1193 case ChromeViews::Event::ET_MOUSE_DRAGGED:
1194 view_->OnMouseDragged(event);
1195 break;
1196
1197 case ChromeViews::Event::ET_MOUSE_RELEASED:
1198 view_->OnMouseReleased(event, false);
1199 break;
1200
1201 default:
1202 NOTREACHED();
1203 }
1204 }
1205
1206 private:
1207 ChromeViews::View* view_;
1208 ChromeViews::Event::EventType type_;
1209 POINT point_;
1210 int flags_;
1211
[email protected]5a52f162008-08-27 04:15:311212 DISALLOW_COPY_AND_ASSIGN(MouseEventTask);
initial.commit09911bf2008-07-26 23:55:291213};
1214
1215void AutomationProvider::ScheduleMouseEvent(ChromeViews::View* view,
1216 ChromeViews::Event::EventType type,
1217 POINT point,
1218 int flags) {
1219 MessageLoop::current()->PostTask(FROM_HERE,
1220 new MouseEventTask(view, type, point, flags));
1221}
1222
1223// This task just adds another task to the event queue. This is useful if
1224// you want to ensure that any tasks added to the event queue after this one
1225// have already been processed by the time |task| is run.
1226class InvokeTaskLaterTask : public Task {
1227 public:
1228 explicit InvokeTaskLaterTask(Task* task) : task_(task) {}
1229 virtual ~InvokeTaskLaterTask() {}
1230
1231 virtual void Run() {
1232 MessageLoop::current()->PostTask(FROM_HERE, task_);
1233 }
1234
1235 private:
1236 Task* task_;
1237
[email protected]5a52f162008-08-27 04:15:311238 DISALLOW_COPY_AND_ASSIGN(InvokeTaskLaterTask);
initial.commit09911bf2008-07-26 23:55:291239};
1240
1241// This task sends a WindowDragResponse message with the appropriate
1242// routing ID to the automation proxy. This is implemented as a task so that
1243// we know that the mouse events (and any tasks that they spawn on the message
1244// loop) have been processed by the time this is sent.
1245class WindowDragResponseTask : public Task {
1246 public:
1247 WindowDragResponseTask(AutomationProvider* provider, int routing_id)
1248 : provider_(provider), routing_id_(routing_id) {}
1249 virtual ~WindowDragResponseTask() {}
1250
1251 virtual void Run() {
1252 provider_->Send(new AutomationMsg_WindowDragResponse(routing_id_, true));
1253 }
1254
1255 private:
1256 AutomationProvider* provider_;
1257 int routing_id_;
1258
[email protected]5a52f162008-08-27 04:15:311259 DISALLOW_COPY_AND_ASSIGN(WindowDragResponseTask);
initial.commit09911bf2008-07-26 23:55:291260};
1261
1262void AutomationProvider::WindowSimulateClick(const IPC::Message& message,
1263 int handle,
1264 POINT click,
1265 int flags) {
1266 HWND hwnd = 0;
1267
1268 if (window_tracker_->ContainsHandle(handle)) {
1269 hwnd = window_tracker_->GetResource(handle);
1270
initial.commit09911bf2008-07-26 23:55:291271 ui_controls::SendMouseMove(click.x, click.y);
1272
1273 ui_controls::MouseButton button = ui_controls::LEFT;
1274 if ((flags & ChromeViews::Event::EF_LEFT_BUTTON_DOWN) ==
1275 ChromeViews::Event::EF_LEFT_BUTTON_DOWN) {
1276 button = ui_controls::LEFT;
1277 } else if ((flags & ChromeViews::Event::EF_RIGHT_BUTTON_DOWN) ==
1278 ChromeViews::Event::EF_RIGHT_BUTTON_DOWN) {
1279 button = ui_controls::RIGHT;
1280 } else if ((flags & ChromeViews::Event::EF_MIDDLE_BUTTON_DOWN) ==
1281 ChromeViews::Event::EF_MIDDLE_BUTTON_DOWN) {
1282 button = ui_controls::MIDDLE;
1283 } else {
1284 NOTREACHED();
1285 }
1286 ui_controls::SendMouseClick(button);
1287 }
1288}
1289
1290void AutomationProvider::WindowSimulateDrag(const IPC::Message& message,
1291 int handle,
1292 std::vector<POINT> drag_path,
[email protected]5e0f30c2008-08-14 22:52:441293 int flags,
1294 bool press_escape_en_route) {
initial.commit09911bf2008-07-26 23:55:291295 bool succeeded = false;
1296 if (browser_tracker_->ContainsHandle(handle) && (drag_path.size() > 1)) {
1297 succeeded = true;
1298
[email protected]0307076a2008-08-01 20:42:271299 UINT down_message = 0;
1300 UINT up_message = 0;
1301 WPARAM wparam_flags = 0;
1302 if (flags & ChromeViews::Event::EF_SHIFT_DOWN)
1303 wparam_flags |= MK_SHIFT;
1304 if (flags & ChromeViews::Event::EF_CONTROL_DOWN)
1305 wparam_flags |= MK_CONTROL;
1306 if (flags & ChromeViews::Event::EF_LEFT_BUTTON_DOWN) {
1307 wparam_flags |= MK_LBUTTON;
1308 down_message = WM_LBUTTONDOWN;
1309 up_message = WM_LBUTTONUP;
1310 }
1311 if (flags & ChromeViews::Event::EF_MIDDLE_BUTTON_DOWN) {
1312 wparam_flags |= MK_MBUTTON;
1313 down_message = WM_MBUTTONDOWN;
1314 up_message = WM_MBUTTONUP;
1315 }
1316 if (flags & ChromeViews::Event::EF_RIGHT_BUTTON_DOWN) {
1317 wparam_flags |= MK_RBUTTON;
1318 down_message = WM_LBUTTONDOWN;
1319 up_message = WM_LBUTTONUP;
1320 }
1321
initial.commit09911bf2008-07-26 23:55:291322 Browser* browser = browser_tracker_->GetResource(handle);
1323 DCHECK(browser);
[email protected]0307076a2008-08-01 20:42:271324 HWND top_level_hwnd = browser->GetTopLevelHWND();
1325 SetCursorPos(drag_path[0].x, drag_path[0].y);
1326 SendMessage(top_level_hwnd, down_message, wparam_flags,
1327 MAKELPARAM(drag_path[0].x, drag_path[0].y));
initial.commit09911bf2008-07-26 23:55:291328 for (int i = 1; i < static_cast<int>(drag_path.size()); ++i) {
[email protected]0307076a2008-08-01 20:42:271329 SetCursorPos(drag_path[i].x, drag_path[i].y);
1330 SendMessage(top_level_hwnd, WM_MOUSEMOVE, wparam_flags,
1331 MAKELPARAM(drag_path[i].x, drag_path[i].y));
initial.commit09911bf2008-07-26 23:55:291332 }
1333 POINT end = drag_path[drag_path.size() - 1];
[email protected]0307076a2008-08-01 20:42:271334 SetCursorPos(end.x, end.y);
[email protected]5e0f30c2008-08-14 22:52:441335
1336 if (press_escape_en_route) {
1337 // Press Escape.
1338 ui_controls::SendKeyPress(VK_ESCAPE,
1339 ((flags & ChromeViews::Event::EF_CONTROL_DOWN)
1340 == ChromeViews::Event::EF_CONTROL_DOWN),
1341 ((flags & ChromeViews::Event::EF_SHIFT_DOWN) ==
1342 ChromeViews::Event::EF_SHIFT_DOWN),
1343 ((flags & ChromeViews::Event::EF_ALT_DOWN) ==
1344 ChromeViews::Event::EF_ALT_DOWN));
1345 }
[email protected]0307076a2008-08-01 20:42:271346 SendMessage(top_level_hwnd, up_message, wparam_flags,
1347 MAKELPARAM(end.x, end.y));
initial.commit09911bf2008-07-26 23:55:291348
1349 MessageLoop::current()->PostTask(FROM_HERE,
1350 new InvokeTaskLaterTask(
1351 new WindowDragResponseTask(this, message.routing_id())));
1352 } else {
1353 Send(new AutomationMsg_WindowDragResponse(message.routing_id(), true));
1354 }
1355}
1356
1357void AutomationProvider::WindowSimulateKeyPress(const IPC::Message& message,
1358 int handle,
1359 wchar_t key,
1360 int flags) {
1361 if (!window_tracker_->ContainsHandle(handle))
1362 return;
1363
1364 // The key event is sent to whatever window is active.
1365 ui_controls::SendKeyPress(key,
1366 ((flags & ChromeViews::Event::EF_CONTROL_DOWN) ==
1367 ChromeViews::Event::EF_CONTROL_DOWN),
1368 ((flags & ChromeViews::Event::EF_SHIFT_DOWN) ==
1369 ChromeViews::Event::EF_SHIFT_DOWN),
1370 ((flags & ChromeViews::Event::EF_ALT_DOWN) ==
1371 ChromeViews::Event::EF_ALT_DOWN));
1372}
1373
1374void AutomationProvider::GetFocusedViewID(const IPC::Message& message,
1375 int handle) {
1376 int view_id = -1;
1377 if (window_tracker_->ContainsHandle(handle)) {
1378 HWND hwnd = window_tracker_->GetResource(handle);
1379 ChromeViews::FocusManager* focus_manager =
1380 ChromeViews::FocusManager::GetFocusManager(hwnd);
1381 DCHECK(focus_manager);
1382 ChromeViews::View* focused_view = focus_manager->GetFocusedView();
1383 if (focused_view)
1384 view_id = focused_view->GetID();
1385 }
1386 Send(new AutomationMsg_GetFocusedViewIDResponse(message.routing_id(),
1387 view_id));
1388}
1389
1390void AutomationProvider::SetWindowVisible(const IPC::Message& message,
1391 int handle, bool visible) {
1392 if (window_tracker_->ContainsHandle(handle)) {
1393 HWND hwnd = window_tracker_->GetResource(handle);
1394 ::ShowWindow(hwnd, visible ? SW_SHOW : SW_HIDE);
1395 Send(new AutomationMsg_SetWindowVisibleResponse(message.routing_id(),
1396 true));
1397 } else {
1398 Send(new AutomationMsg_SetWindowVisibleResponse(message.routing_id(),
1399 false));
1400 }
1401}
1402
1403void AutomationProvider::IsWindowActive(const IPC::Message& message,
1404 int handle) {
1405 if (window_tracker_->ContainsHandle(handle)) {
1406 HWND hwnd = window_tracker_->GetResource(handle);
1407 bool is_active = ::GetForegroundWindow() == hwnd;
1408 Send(new AutomationMsg_IsWindowActiveResponse(
1409 message.routing_id(), true, is_active));
1410 } else {
1411 Send(new AutomationMsg_IsWindowActiveResponse(message.routing_id(),
1412 false, false));
1413 }
1414}
1415
1416void AutomationProvider::ActivateWindow(const IPC::Message& message,
1417 int handle) {
1418 if (window_tracker_->ContainsHandle(handle)) {
1419 ::SetActiveWindow(window_tracker_->GetResource(handle));
1420 }
1421}
1422
1423void AutomationProvider::GetTabCount(const IPC::Message& message, int handle) {
1424 int tab_count = -1; // -1 is the error code
1425
1426 if (browser_tracker_->ContainsHandle(handle)) {
1427 Browser* browser = browser_tracker_->GetResource(handle);
1428 tab_count = browser->tab_count();
1429 }
1430
1431 Send(new AutomationMsg_TabCountResponse(message.routing_id(), tab_count));
1432}
1433
1434void AutomationProvider::GetTab(const IPC::Message& message,
1435 int win_handle, int tab_index) {
1436 void* iter = NULL;
1437 int tab_handle = 0;
1438 if (browser_tracker_->ContainsHandle(win_handle) && (tab_index >= 0)) {
1439 Browser* browser = browser_tracker_->GetResource(win_handle);
1440 if (tab_index < browser->tab_count()) {
1441 TabContents* tab_contents =
1442 browser->GetTabContentsAt(tab_index);
1443 tab_handle = tab_tracker_->Add(tab_contents->controller());
1444 }
1445 }
1446
1447 Send(new AutomationMsg_TabResponse(message.routing_id(), tab_handle));
1448}
1449
1450void AutomationProvider::GetTabTitle(const IPC::Message& message, int handle) {
1451 int title_string_size = -1; // -1 is the error code
1452 std::wstring title;
1453 if (tab_tracker_->ContainsHandle(handle)) {
1454 NavigationController* tab = tab_tracker_->GetResource(handle);
[email protected]1e5645ff2008-08-27 18:09:071455 title = tab->GetActiveEntry()->title();
initial.commit09911bf2008-07-26 23:55:291456 title_string_size = static_cast<int>(title.size());
1457 }
1458
1459 Send(new AutomationMsg_TabTitleResponse(message.routing_id(),
1460 title_string_size, title));
1461}
1462
1463void AutomationProvider::HandleUnused(const IPC::Message& message, int handle) {
1464 if (window_tracker_->ContainsHandle(handle)) {
1465 window_tracker_->Remove(window_tracker_->GetResource(handle));
1466 }
1467}
1468
1469void AutomationProvider::OnChannelError() {
1470 LOG(ERROR) << "AutomationProxy went away, shutting down app.";
[email protected]295039bd2008-08-15 04:32:571471 AutomationProviderList::GetInstance()->RemoveProvider(this);
initial.commit09911bf2008-07-26 23:55:291472}
1473
1474// TODO(brettw) change this to accept GURLs when history supports it
1475void AutomationProvider::OnRedirectQueryComplete(
1476 HistoryService::Handle request_handle,
1477 GURL from_url,
1478 bool success,
1479 HistoryService::RedirectList* redirects) {
1480 DCHECK(request_handle == redirect_query_);
1481
1482 // Respond to the pending request for the redirect list.
1483 IPC::Message* msg = new IPC::Message(redirect_query_routing_id_,
1484 AutomationMsg_RedirectsFromResponse::ID,
1485 IPC::Message::PRIORITY_NORMAL);
1486 if (success) {
1487 msg->WriteInt(static_cast<int>(redirects->size()));
1488 for (size_t i = 0; i < redirects->size(); i++)
1489 IPC::ParamTraits<GURL>::Write(msg, redirects->at(i));
1490 } else {
1491 msg->WriteInt(-1); // Negative count indicates failure.
1492 }
1493
1494 Send(msg);
1495 redirect_query_ = NULL;
1496}
1497
1498bool AutomationProvider::Send(IPC::Message* msg) {
[email protected]295039bd2008-08-15 04:32:571499 DCHECK(channel_.get());
1500 return channel_->Send(msg);
initial.commit09911bf2008-07-26 23:55:291501}
1502
1503Browser* AutomationProvider::FindAndActivateTab(
1504 NavigationController* controller) {
1505 int tab_index;
1506 Browser* browser = Browser::GetBrowserForController(controller, &tab_index);
1507 if (browser)
1508 browser->SelectTabContentsAt(tab_index, true);
1509
1510 return browser;
1511}
1512
1513void AutomationProvider::GetCookies(const IPC::Message& message,
1514 const GURL& url, int handle) {
1515 std::string value;
1516
1517 if (url.is_valid() && tab_tracker_->ContainsHandle(handle)) {
1518 NavigationController* tab = tab_tracker_->GetResource(handle);
1519 value =
1520 tab->profile()->GetRequestContext()->cookie_store()->GetCookies(url);
1521 }
1522
1523 Send(new AutomationMsg_GetCookiesResponse(message.routing_id(),
1524 static_cast<int>(value.size()), value));
1525}
1526
1527void AutomationProvider::SetCookie(const IPC::Message& message,
1528 const GURL& url,
1529 const std::string value,
1530 int handle) {
1531 int response_value = -1;
1532
1533 if (url.is_valid() && tab_tracker_->ContainsHandle(handle)) {
1534 NavigationController* tab = tab_tracker_->GetResource(handle);
1535 URLRequestContext* context = tab->profile()->GetRequestContext();
1536 if (context->cookie_store()->SetCookie(url, value))
1537 response_value = 1;
1538 }
1539
1540 Send(new AutomationMsg_SetCookieResponse(message.routing_id(),
1541 response_value));
1542}
1543
1544void AutomationProvider::GetTabURL(const IPC::Message& message, int handle) {
1545 bool success = false;
1546 GURL url;
1547 if (tab_tracker_->ContainsHandle(handle)) {
1548 NavigationController* tab = tab_tracker_->GetResource(handle);
1549 // Return what the user would see in the location bar.
[email protected]1e5645ff2008-08-27 18:09:071550 url = tab->GetActiveEntry()->display_url();
initial.commit09911bf2008-07-26 23:55:291551 success = true;
1552 }
1553
1554 Send(new AutomationMsg_TabURLResponse(message.routing_id(), success, url));
1555}
1556
1557void AutomationProvider::GetTabHWND(const IPC::Message& message, int handle) {
1558 HWND tab_hwnd = NULL;
1559
1560 if (tab_tracker_->ContainsHandle(handle)) {
1561 NavigationController* tab = tab_tracker_->GetResource(handle);
1562 tab_hwnd = tab->active_contents()->GetContainerHWND();
1563 }
1564
1565 Send(new AutomationMsg_TabHWNDResponse(message.routing_id(), tab_hwnd));
1566}
1567
1568void AutomationProvider::GetTabProcessID(
1569 const IPC::Message& message, int handle) {
1570 int process_id = -1;
1571
1572 if (tab_tracker_->ContainsHandle(handle)) {
1573 process_id = 0;
1574 NavigationController* tab = tab_tracker_->GetResource(handle);
1575 if (tab->active_contents()->AsWebContents()) {
1576 WebContents* web_contents = tab->active_contents()->AsWebContents();
1577 if (web_contents->process()) {
1578 process_id =
1579 process_util::GetProcId(web_contents->process()->process());
1580 }
1581 }
1582 }
1583
1584 Send(new AutomationMsg_TabProcessIDResponse(message.routing_id(),
1585 process_id));
1586}
1587
1588void AutomationProvider::ApplyAccelerator(int handle, int id) {
1589 if (browser_tracker_->ContainsHandle(handle)) {
1590 Browser* browser = browser_tracker_->GetResource(handle);
1591 browser->controller()->ExecuteCommand(id);
1592 }
1593}
1594
1595void AutomationProvider::ExecuteJavascript(const IPC::Message& message,
1596 int handle,
1597 const std::wstring& frame_xpath,
1598 const std::wstring& script) {
1599 bool succeeded = false;
[email protected]20e93d12008-08-28 16:31:571600 WebContents* web_contents = GetWebContentsForHandle(handle, NULL);
1601 if (web_contents) {
1602 // Set the routing id of this message with the controller.
1603 // This routing id needs to be remembered for the reverse
1604 // communication while sending back the response of
1605 // this javascript execution.
1606 std::wstring url;
1607 SStringPrintf(&url,
1608 L"javascript:void(window.domAutomationController.setAutomationId(%d));",
1609 message.routing_id());
initial.commit09911bf2008-07-26 23:55:291610
[email protected]1f5af4442008-09-25 22:11:061611 web_contents->render_view_host()->ExecuteJavascriptInWebFrame(
1612 frame_xpath, url);
1613 web_contents->render_view_host()->ExecuteJavascriptInWebFrame(
1614 frame_xpath, script);
[email protected]20e93d12008-08-28 16:31:571615 succeeded = true;
initial.commit09911bf2008-07-26 23:55:291616 }
1617
1618 if (!succeeded) {
1619 Send(new AutomationMsg_DomOperationResponse(message.routing_id(), ""));
1620 }
1621}
1622
1623void AutomationProvider::GetShelfVisibility(const IPC::Message& message,
1624 int handle) {
1625 bool visible = false;
[email protected]20e93d12008-08-28 16:31:571626
1627 WebContents* web_contents = GetWebContentsForHandle(handle, NULL);
1628 if (web_contents)
1629 visible = web_contents->IsDownloadShelfVisible();
initial.commit09911bf2008-07-26 23:55:291630
1631 Send(new AutomationMsg_ShelfVisibilityResponse(message.routing_id(),
1632 visible));
1633}
1634
1635void AutomationProvider::GetConstrainedWindowCount(const IPC::Message& message,
1636 int handle) {
1637 int count = -1; // -1 is the error code
1638 if (tab_tracker_->ContainsHandle(handle)) {
1639 NavigationController* nav_controller = tab_tracker_->GetResource(handle);
1640 TabContents* tab_contents = nav_controller->active_contents();
1641 if (tab_contents) {
1642 count = static_cast<int>(tab_contents->child_windows_.size());
1643 }
1644 }
1645
1646 Send(new AutomationMsg_ConstrainedWindowCountResponse(message.routing_id(),
1647 count));
1648}
1649
1650void AutomationProvider::GetConstrainedWindow(const IPC::Message& message,
1651 int handle, int index) {
1652 int cwindow_handle = 0;
1653 if (tab_tracker_->ContainsHandle(handle) && index >= 0) {
1654 NavigationController* nav_controller =
1655 tab_tracker_->GetResource(handle);
1656 TabContents* tab = nav_controller->active_contents();
[email protected]d5f942ba2008-09-26 19:30:341657 if (tab && index < static_cast<int>(tab->child_windows_.size())) {
1658 ConstrainedWindow* window = tab->child_windows_[index];
initial.commit09911bf2008-07-26 23:55:291659 cwindow_handle = cwindow_tracker_->Add(window);
1660 }
1661 }
1662
1663 Send(new AutomationMsg_ConstrainedWindowResponse(message.routing_id(),
1664 cwindow_handle));
1665}
1666
1667void AutomationProvider::GetConstrainedTitle(const IPC::Message& message,
1668 int handle) {
1669 int title_string_size = -1; // -1 is the error code
1670 std::wstring title;
1671 if (cwindow_tracker_->ContainsHandle(handle)) {
1672 ConstrainedWindow* window = cwindow_tracker_->GetResource(handle);
1673 title = window->GetWindowTitle();
1674 title_string_size = static_cast<int>(title.size());
1675 }
1676
1677 Send(new AutomationMsg_ConstrainedTitleResponse(message.routing_id(),
1678 title_string_size, title));
1679}
1680
1681void AutomationProvider::GetConstrainedWindowBounds(const IPC::Message& message,
1682 int handle) {
1683 bool exists = false;
1684 gfx::Rect rect(0, 0, 0, 0);
1685 if (cwindow_tracker_->ContainsHandle(handle)) {
1686 ConstrainedWindow* window = cwindow_tracker_->GetResource(handle);
1687 if (window) {
1688 exists = true;
1689 rect = window->GetCurrentBounds();
1690 }
1691 }
1692
1693 Send(new AutomationMsg_ConstrainedWindowBoundsResponse(message.routing_id(),
1694 exists, rect));
1695}
1696
1697void AutomationProvider::HandleFindInPageRequest(
1698 const IPC::Message& message, int handle, const std::wstring& find_request,
1699 int forward, int match_case) {
[email protected]5a52f162008-08-27 04:15:311700 NOTREACHED() << "This function has been deprecated."
1701 << "Please use HandleFindRequest instead.";
1702 Send(new AutomationMsg_FindInPageResponse(message.routing_id(), -1));
1703 return;
1704}
1705
1706void AutomationProvider::HandleFindRequest(const IPC::Message& message,
1707 int handle, const FindInPageRequest& request) {
initial.commit09911bf2008-07-26 23:55:291708 if (!tab_tracker_->ContainsHandle(handle)) {
1709 Send(new AutomationMsg_FindInPageResponse(message.routing_id(), -1));
1710 return;
1711 }
1712
1713 NavigationController* nav = tab_tracker_->GetResource(handle);
1714 TabContents* tab_contents = nav->active_contents();
1715
1716 find_in_page_observer_.reset(new
1717 FindInPageNotificationObserver(this, tab_contents, message.routing_id()));
1718
[email protected]edc28612008-08-14 20:23:361719 // The find in page dialog must be up for us to get the notification that the
1720 // find was complete
1721 if (tab_contents->AsWebContents()) {
1722 NavigationController* tab = tab_tracker_->GetResource(handle);
1723 Browser* browser = Browser::GetBrowserForController(tab, NULL);
1724 tab_contents->AsWebContents()->OpenFindInPageWindow(*browser);
1725 }
1726
initial.commit09911bf2008-07-26 23:55:291727 tab_contents->StartFinding(
1728 FindInPageNotificationObserver::kFindInPageRequestId,
[email protected]5a52f162008-08-27 04:15:311729 request.search_string, request.forward, request.match_case,
1730 request.find_next);
initial.commit09911bf2008-07-26 23:55:291731}
1732
[email protected]5f8af2a2008-08-06 22:49:451733void AutomationProvider::HandleOpenFindInPageRequest(
1734 const IPC::Message& message, int handle) {
[email protected]20e93d12008-08-28 16:31:571735 NavigationController* tab = NULL;
1736 WebContents* web_contents = GetWebContentsForHandle(handle, &tab);
1737 if (web_contents) {
[email protected]5f8af2a2008-08-06 22:49:451738 Browser* browser = Browser::GetBrowserForController(tab, NULL);
[email protected]20e93d12008-08-28 16:31:571739 web_contents->OpenFindInPageWindow(*browser);
[email protected]5f8af2a2008-08-06 22:49:451740 }
1741}
1742
[email protected]20e93d12008-08-28 16:31:571743void AutomationProvider::GetFindWindowVisibility(const IPC::Message& message,
1744 int handle) {
1745 bool visible = false;
1746 WebContents* web_contents = GetWebContentsForHandle(handle, NULL);
1747 if (web_contents)
1748 visible = web_contents->IsFindWindowFullyVisible();
1749
1750 Send(new AutomationMsg_FindWindowVisibilityResponse(message.routing_id(),
1751 visible));
1752}
1753
1754void AutomationProvider::HandleFindWindowLocationRequest(
1755 const IPC::Message& message, int handle) {
1756 int x = -1, y = -1;
1757 WebContents* web_contents = GetWebContentsForHandle(handle, NULL);
1758 if (web_contents)
1759 web_contents->GetFindInPageWindowLocation(&x, &y);
1760
1761 Send(new AutomationMsg_FindWindowLocationResponse(message.routing_id(),
1762 x, y));
1763}
1764
[email protected]c2cbeb92008-09-05 21:36:571765void AutomationProvider::GetBookmarkBarVisitility(const IPC::Message& message,
1766 int handle) {
1767 bool visible = false;
1768 bool animating = false;
1769
1770 void* iter = NULL;
1771 if (browser_tracker_->ContainsHandle(handle)) {
1772 Browser* browser = browser_tracker_->GetResource(handle);
1773 if (browser) {
1774 BookmarkBarView* bookmark_bar = browser->window()->GetBookmarkBarView();
1775 if (bookmark_bar) {
1776 animating = bookmark_bar->IsAnimating();
1777 visible = browser->window()->IsBookmarkBarVisible();
1778 }
1779 }
1780 }
1781
1782 Send(new AutomationMsg_BookmarkBarVisibilityResponse(message.routing_id(),
1783 visible, animating));
1784}
1785
initial.commit09911bf2008-07-26 23:55:291786void AutomationProvider::HandleInspectElementRequest(
1787 const IPC::Message& message, int handle, int x, int y) {
[email protected]20e93d12008-08-28 16:31:571788 WebContents* web_contents = GetWebContentsForHandle(handle, NULL);
1789 if (web_contents) {
[email protected]1f5af4442008-09-25 22:11:061790 web_contents->render_view_host()->InspectElementAt(x, y);
initial.commit09911bf2008-07-26 23:55:291791 inspect_element_routing_id_ = message.routing_id();
1792 } else {
1793 Send(new AutomationMsg_InspectElementResponse(message.routing_id(), -1));
1794 }
1795}
1796
1797void AutomationProvider::ReceivedInspectElementResponse(int num_resources) {
1798 Send(new AutomationMsg_InspectElementResponse(inspect_element_routing_id_,
1799 num_resources));
1800}
1801
1802// Helper class for making changes to the URLRequest ProtocolFactory on the
1803// IO thread.
1804class SetFilteredInetTask : public Task {
1805 public:
1806 explicit SetFilteredInetTask(bool enabled) : enabled_(enabled) { }
1807 virtual void Run() {
1808 if (enabled_) {
1809 URLRequestFilter::GetInstance()->ClearHandlers();
1810
1811 URLRequestFailedDnsJob::AddUITestUrls();
1812 URLRequestSlowDownloadJob::AddUITestUrls();
1813
1814 std::wstring root_http;
1815 PathService::Get(chrome::DIR_TEST_DATA, &root_http);
1816 URLRequestMockHTTPJob::AddUITestUrls(root_http);
1817 } else {
1818 // Revert to the default handlers.
1819 URLRequestFilter::GetInstance()->ClearHandlers();
1820 }
1821 }
1822 private:
1823 bool enabled_;
1824};
1825
1826void AutomationProvider::SetFilteredInet(const IPC::Message& message,
1827 bool enabled) {
1828 // Since this involves changing the URLRequest ProtocolFactory, we want to
1829 // run on the main thread.
1830 g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
1831 new SetFilteredInetTask(enabled));
1832}
1833
1834void AutomationProvider::GetDownloadDirectory(const IPC::Message& message,
1835 int handle) {
1836 DLOG(INFO) << "Handling download directory request";
1837 std::wstring download_directory;
1838 if (tab_tracker_->ContainsHandle(handle)) {
1839 NavigationController* tab = tab_tracker_->GetResource(handle);
1840 DownloadManager* dlm = tab->profile()->GetDownloadManager();
1841 DCHECK(dlm);
1842 download_directory = dlm->download_path();
1843 }
1844
1845 Send(new AutomationMsg_DownloadDirectoryResponse(message.routing_id(),
1846 download_directory));
1847}
1848
1849void AutomationProvider::OpenNewBrowserWindow(int show_command) {
1850 // We may have no current browser windows open so don't rely on
1851 // asking an existing browser to execute the IDC_NEWWINDOW command
1852 Browser::OpenNewBrowserWindow(profile_, show_command);
1853}
1854
1855void AutomationProvider::GetWindowForBrowser(const IPC::Message& message,
1856 int browser_handle) {
1857 bool success = false;
1858 int window_handle = 0;
1859
1860 if (browser_tracker_->ContainsHandle(browser_handle)) {
1861 Browser* browser = browser_tracker_->GetResource(browser_handle);
1862 HWND hwnd = browser->GetTopLevelHWND();
1863 // Add() returns the existing handle for the resource if any.
1864 window_handle = window_tracker_->Add(hwnd);
1865 success = true;
1866 }
1867 Send(new AutomationMsg_WindowForBrowserResponse(message.routing_id(),
1868 success, window_handle));
1869}
1870
1871void AutomationProvider::GetAutocompleteEditForBrowser(
1872 const IPC::Message& message,
1873 int browser_handle) {
1874 bool success = false;
1875 int autocomplete_edit_handle = 0;
1876
1877 if (browser_tracker_->ContainsHandle(browser_handle)) {
1878 Browser* browser = browser_tracker_->GetResource(browser_handle);
1879 LocationBarView* loc_bar_view = browser->GetLocationBarView();
[email protected]81c21222008-09-10 19:35:521880 AutocompleteEditView* edit_view = loc_bar_view->location_entry();
initial.commit09911bf2008-07-26 23:55:291881 // Add() returns the existing handle for the resource if any.
[email protected]81c21222008-09-10 19:35:521882 autocomplete_edit_handle = autocomplete_edit_tracker_->Add(edit_view);
initial.commit09911bf2008-07-26 23:55:291883 success = true;
1884 }
1885 Send(new AutomationMsg_AutocompleteEditForBrowserResponse(
1886 message.routing_id(), success, autocomplete_edit_handle));
1887}
1888
1889void AutomationProvider::GetBrowserForWindow(const IPC::Message& message,
1890 int window_handle) {
1891 bool success = false;
1892 int browser_handle = 0;
1893
1894 if (window_tracker_->ContainsHandle(window_handle)) {
1895 HWND window = window_tracker_->GetResource(window_handle);
1896 BrowserList::const_iterator iter = BrowserList::begin();
1897 Browser* browser = NULL;
1898 for (;iter != BrowserList::end(); ++iter) {
1899 if (window == (*iter)->GetTopLevelHWND()) {
1900 browser = *iter;
1901 break;
1902 }
1903 }
1904 if (browser) {
1905 // Add() returns the existing handle for the resource if any.
1906 browser_handle = browser_tracker_->Add(browser);
1907 success = true;
1908 }
1909 }
1910 Send(new AutomationMsg_BrowserForWindowResponse(message.routing_id(),
1911 success, browser_handle));
1912}
1913
1914void AutomationProvider::ShowInterstitialPage(const IPC::Message& message,
1915 int tab_handle,
1916 const std::string& html_text) {
1917 if (tab_tracker_->ContainsHandle(tab_handle)) {
1918 NavigationController* controller = tab_tracker_->GetResource(tab_handle);
1919 TabContents* tab_contents = controller->active_contents();
1920 if (tab_contents->type() == TAB_CONTENTS_WEB) {
1921 AddNavigationStatusListener(controller,
1922 new AutomationMsg_ShowInterstitialPageResponse(message.routing_id(),
1923 true),
1924 NULL);
1925 WebContents* web_contents = tab_contents->AsWebContents();
[email protected]cbab76d2008-10-13 22:42:471926 AutomationInterstitialPage* interstitial =
1927 new AutomationInterstitialPage(web_contents,
1928 GURL("about:interstitial"),
1929 html_text);
1930 web_contents->ShowInterstitialPage(interstitial);
initial.commit09911bf2008-07-26 23:55:291931 return;
1932 }
1933 }
1934 Send(new AutomationMsg_ShowInterstitialPageResponse(message.routing_id(),
1935 false));
1936}
1937
1938void AutomationProvider::HideInterstitialPage(const IPC::Message& message,
1939 int tab_handle) {
[email protected]20e93d12008-08-28 16:31:571940 WebContents* web_contents = GetWebContentsForHandle(tab_handle, NULL);
1941 if (web_contents) {
1942 web_contents->HideInterstitialPage(false, false);
1943 Send(new AutomationMsg_HideInterstitialPageResponse(message.routing_id(),
1944 true));
1945 return;
initial.commit09911bf2008-07-26 23:55:291946 }
1947 Send(new AutomationMsg_HideInterstitialPageResponse(message.routing_id(),
1948 false));
1949}
1950
1951void AutomationProvider::CloseTab(const IPC::Message& message,
1952 int tab_handle,
1953 bool wait_until_closed) {
1954 if (tab_tracker_->ContainsHandle(tab_handle)) {
1955 NavigationController* controller = tab_tracker_->GetResource(tab_handle);
1956 int index;
1957 Browser* browser = Browser::GetBrowserForController(controller, &index);
1958 DCHECK(browser);
1959 TabClosedNotificationObserver* observer =
1960 new TabClosedNotificationObserver(browser, this, message.routing_id(),
1961 wait_until_closed);
1962 browser->CloseContents(controller->active_contents());
1963 } else {
1964 Send(new AutomationMsg_CloseTabResponse(message.routing_id(), false));
1965 }
1966}
1967
1968void AutomationProvider::CloseBrowser(const IPC::Message& message,
1969 int browser_handle) {
1970 if (browser_tracker_->ContainsHandle(browser_handle)) {
1971 Browser* browser = browser_tracker_->GetResource(browser_handle);
1972 new BrowserClosedNotificationObserver(browser, this, message.routing_id());
[email protected]f3e99e32008-07-30 04:48:391973 browser->window()->Close();
initial.commit09911bf2008-07-26 23:55:291974 } else {
1975 NOTREACHED();
1976 }
1977}
1978
1979void AutomationProvider::CreateExternalTab(const IPC::Message& message) {
1980 int tab_handle = 0;
1981 HWND tab_container_window = NULL;
1982 ExternalTabContainer *external_tab_container =
1983 new ExternalTabContainer(this);
1984 external_tab_container->Init(profile_);
1985 TabContents* tab_contents = external_tab_container->tab_contents();
1986 if (tab_contents) {
1987 tab_handle = tab_tracker_->Add(tab_contents->controller());
1988 tab_container_window = *external_tab_container;
1989 }
1990 Send(new AutomationMsg_CreateExternalTabResponse(message.routing_id(),
1991 tab_container_window,
1992 tab_handle));
1993}
1994
1995void AutomationProvider::NavigateInExternalTab(const IPC::Message& message,
1996 int handle, const GURL& url) {
1997 bool status = false;
1998
1999 if (tab_tracker_->ContainsHandle(handle)) {
2000 NavigationController* tab = tab_tracker_->GetResource(handle);
2001 tab->LoadURL(url, PageTransition::TYPED);
2002 status = true;
2003 }
2004
2005 Send(new AutomationMsg_NavigateInExternalTabResponse(message.routing_id(),
2006 status));
2007}
2008
2009void AutomationProvider::SetAcceleratorsForTab(const IPC::Message& message,
2010 int handle,
2011 HACCEL accel_table,
2012 int accel_entry_count) {
2013 bool status = false;
2014 if (tab_tracker_->ContainsHandle(handle)) {
2015 NavigationController* tab = tab_tracker_->GetResource(handle);
2016 TabContents* tab_contents = tab->GetTabContents(TAB_CONTENTS_WEB);
2017 ExternalTabContainer* external_tab_container =
2018 ExternalTabContainer::GetContainerForTab(
2019 tab_contents->GetContainerHWND());
2020 // This call is only valid on an externally hosted tab
2021 if (external_tab_container) {
2022 external_tab_container->SetAccelerators(accel_table,
2023 accel_entry_count);
2024 status = true;
2025 }
2026 }
2027 Send(new AutomationMsg_SetAcceleratorsForTabResponse(message.routing_id(),
2028 status));
2029}
2030
2031void AutomationProvider::ProcessUnhandledAccelerator(
2032 const IPC::Message& message, int handle, const MSG& msg) {
2033 if (tab_tracker_->ContainsHandle(handle)) {
2034 NavigationController* tab = tab_tracker_->GetResource(handle);
2035 TabContents* tab_contents = tab->GetTabContents(TAB_CONTENTS_WEB);
2036 ExternalTabContainer* external_tab_container =
2037 ExternalTabContainer::GetContainerForTab(
2038 tab_contents->GetContainerHWND());
2039 // This call is only valid on an externally hosted tab
2040 if (external_tab_container) {
2041 external_tab_container->ProcessUnhandledAccelerator(msg);
2042 }
2043 }
2044 // This message expects no response.
2045}
2046
2047void AutomationProvider::WaitForTabToBeRestored(
2048 const IPC::Message& message,
2049 int tab_handle) {
2050 if (tab_tracker_->ContainsHandle(tab_handle)) {
2051 NavigationController* tab = tab_tracker_->GetResource(tab_handle);
2052 restore_tracker_.reset(
2053 new NavigationControllerRestoredObserver(this, tab,
2054 message.routing_id()));
2055 }
2056}
2057
2058void AutomationProvider::GetSecurityState(const IPC::Message& message,
2059 int handle) {
2060 if (tab_tracker_->ContainsHandle(handle)) {
2061 NavigationController* tab = tab_tracker_->GetResource(handle);
2062 NavigationEntry* entry = tab->GetActiveEntry();
2063 Send(new AutomationMsg_GetSecurityStateResponse(message.routing_id(), true,
[email protected]eb34392b2008-08-19 15:42:202064 entry->ssl().security_style(), entry->ssl().cert_status(),
2065 entry->ssl().content_status()));
initial.commit09911bf2008-07-26 23:55:292066 } else {
2067 Send(new AutomationMsg_GetSecurityStateResponse(message.routing_id(), false,
2068 SECURITY_STYLE_UNKNOWN,
2069 0, 0));
2070 }
2071}
2072
2073void AutomationProvider::GetPageType(const IPC::Message& message, int handle) {
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 NavigationEntry::PageType page_type = entry->page_type();
initial.commit09911bf2008-07-26 23:55:292078 // In order to return the proper result when an interstitial is shown and
2079 // no navigation entry were created for it we need to ask the WebContents.
2080 if (page_type == NavigationEntry::NORMAL_PAGE &&
2081 tab->active_contents()->AsWebContents() &&
[email protected]b6e09ac2008-08-12 16:11:092082 tab->active_contents()->AsWebContents()->showing_interstitial_page())
initial.commit09911bf2008-07-26 23:55:292083 page_type = NavigationEntry::INTERSTITIAL_PAGE;
2084
2085 Send(new AutomationMsg_GetPageTypeResponse(message.routing_id(), true,
2086 page_type));
2087 } else {
2088 Send(new AutomationMsg_GetPageTypeResponse(message.routing_id(), false,
2089 NavigationEntry::NORMAL_PAGE));
2090 }
2091}
2092
2093void AutomationProvider::ActionOnSSLBlockingPage(const IPC::Message& message,
2094 int handle, bool proceed) {
2095 if (tab_tracker_->ContainsHandle(handle)) {
2096 NavigationController* tab = tab_tracker_->GetResource(handle);
2097 NavigationEntry* entry = tab->GetActiveEntry();
[email protected]1e5645ff2008-08-27 18:09:072098 if (entry->page_type() == NavigationEntry::INTERSTITIAL_PAGE) {
initial.commit09911bf2008-07-26 23:55:292099 TabContents* tab_contents = tab->GetTabContents(TAB_CONTENTS_WEB);
[email protected]cbab76d2008-10-13 22:42:472100 InterstitialPage* ssl_blocking_page =
2101 InterstitialPage::GetInterstitialPage(tab_contents);
initial.commit09911bf2008-07-26 23:55:292102 if (ssl_blocking_page) {
2103 if (proceed) {
2104 AddNavigationStatusListener(tab,
2105 new AutomationMsg_ActionOnSSLBlockingPageResponse(
2106 message.routing_id(), true),
2107 new AutomationMsg_ActionOnSSLBlockingPageResponse(
2108 message.routing_id(), true));
2109 ssl_blocking_page->Proceed();
2110 return;
2111 }
2112 ssl_blocking_page->DontProceed();
2113 Send(new AutomationMsg_ActionOnSSLBlockingPageResponse(
2114 message.routing_id(), true));
2115 return;
2116 }
2117 }
2118 }
2119 // We failed.
2120 Send(new AutomationMsg_ActionOnSSLBlockingPageResponse(message.routing_id(),
2121 false));
2122}
2123
2124void AutomationProvider::BringBrowserToFront(const IPC::Message& message,
2125 int browser_handle) {
2126 if (browser_tracker_->ContainsHandle(browser_handle)) {
2127 Browser* browser = browser_tracker_->GetResource(browser_handle);
2128 browser->MoveToFront(true);
2129 Send(new AutomationMsg_BringBrowserToFrontResponse(message.routing_id(),
2130 true));
2131 } else {
2132 Send(new AutomationMsg_BringBrowserToFrontResponse(message.routing_id(),
2133 false));
2134 }
2135}
2136
2137void AutomationProvider::IsPageMenuCommandEnabled(const IPC::Message& message,
2138 int browser_handle,
2139 int message_num) {
2140 if (browser_tracker_->ContainsHandle(browser_handle)) {
2141 Browser* browser = browser_tracker_->GetResource(browser_handle);
2142 bool menu_item_enabled =
2143 browser->controller()->IsCommandEnabled(message_num);
2144 Send(new AutomationMsg_IsPageMenuCommandEnabledResponse(
2145 message.routing_id(), menu_item_enabled));
2146 } else {
2147 Send(new AutomationMsg_IsPageMenuCommandEnabledResponse(
2148 message.routing_id(), false));
2149 }
2150}
2151
2152void AutomationProvider::PrintNow(const IPC::Message& message, int tab_handle) {
[email protected]20e93d12008-08-28 16:31:572153 NavigationController* tab = NULL;
2154 WebContents* web_contents = GetWebContentsForHandle(tab_handle, &tab);
2155 if (web_contents) {
initial.commit09911bf2008-07-26 23:55:292156 FindAndActivateTab(tab);
[email protected]20e93d12008-08-28 16:31:572157 notification_observer_list_.AddObserver(
2158 new DocumentPrintedNotificationObserver(this, message.routing_id()));
2159 if (web_contents->PrintNow())
2160 return;
initial.commit09911bf2008-07-26 23:55:292161 }
2162 Send(new AutomationMsg_PrintNowResponse(message.routing_id(), false));
2163}
2164
2165void AutomationProvider::SavePage(const IPC::Message& message,
2166 int tab_handle,
2167 const std::wstring& file_name,
2168 const std::wstring& dir_path,
2169 int type) {
2170 if (!tab_tracker_->ContainsHandle(tab_handle)) {
2171 Send(new AutomationMsg_SavePageResponse(message.routing_id(), false));
2172 return;
2173 }
2174
2175 NavigationController* nav = tab_tracker_->GetResource(tab_handle);
2176 Browser* browser = FindAndActivateTab(nav);
2177 DCHECK(browser);
2178 if (!browser->IsCommandEnabled(IDC_SAVEPAGE)) {
2179 Send(new AutomationMsg_SavePageResponse(message.routing_id(), false));
2180 return;
2181 }
2182
2183 TabContents* tab_contents = nav->active_contents();
2184 if (tab_contents->type() != TAB_CONTENTS_WEB) {
2185 Send(new AutomationMsg_SavePageResponse(message.routing_id(), false));
2186 return;
2187 }
2188
2189 SavePackage::SavePackageType save_type =
2190 static_cast<SavePackage::SavePackageType>(type);
2191 DCHECK(save_type >= SavePackage::SAVE_AS_ONLY_HTML &&
2192 save_type <= SavePackage::SAVE_AS_COMPLETE_HTML);
2193 tab_contents->AsWebContents()->SavePage(file_name, dir_path, save_type);
2194
2195 Send(new AutomationMsg_SavePageResponse(
2196 message.routing_id(), true));
2197}
2198
2199void AutomationProvider::GetAutocompleteEditText(const IPC::Message& message,
2200 int autocomplete_edit_handle) {
2201 bool success = false;
2202 std::wstring text;
2203 if (autocomplete_edit_tracker_->ContainsHandle(autocomplete_edit_handle)) {
[email protected]81c21222008-09-10 19:35:522204 text = autocomplete_edit_tracker_->GetResource(autocomplete_edit_handle)->
2205 GetText();
initial.commit09911bf2008-07-26 23:55:292206 success = true;
2207 }
2208 Send(new AutomationMsg_AutocompleteEditGetTextResponse(message.routing_id(),
2209 success, text));
2210}
2211
2212void AutomationProvider::SetAutocompleteEditText(const IPC::Message& message,
2213 int autocomplete_edit_handle,
2214 const std::wstring& text) {
2215 bool success = false;
2216 if (autocomplete_edit_tracker_->ContainsHandle(autocomplete_edit_handle)) {
[email protected]81c21222008-09-10 19:35:522217 autocomplete_edit_tracker_->GetResource(autocomplete_edit_handle)->
2218 SetUserText(text);
initial.commit09911bf2008-07-26 23:55:292219 success = true;
2220 }
2221 Send(new AutomationMsg_AutocompleteEditSetTextResponse(
2222 message.routing_id(), success));
2223}
2224
2225void AutomationProvider::AutocompleteEditGetMatches(
2226 const IPC::Message& message,
2227 int autocomplete_edit_handle) {
2228 bool success = false;
2229 std::vector<AutocompleteMatchData> matches;
2230 if (autocomplete_edit_tracker_->ContainsHandle(autocomplete_edit_handle)) {
[email protected]8deeb952008-10-09 18:21:272231 const AutocompleteResult& result = autocomplete_edit_tracker_->
2232 GetResource(autocomplete_edit_handle)->model()->result();
2233 for (AutocompleteResult::const_iterator i = result.begin();
2234 i != result.end(); ++i)
initial.commit09911bf2008-07-26 23:55:292235 matches.push_back(AutocompleteMatchData(*i));
2236 success = true;
2237 }
2238 Send(new AutomationMsg_AutocompleteEditGetMatchesResponse(
2239 message.routing_id(), success, matches));
2240}
2241
2242void AutomationProvider::AutocompleteEditIsQueryInProgress(
2243 const IPC::Message& message,
2244 int autocomplete_edit_handle) {
2245 bool success = false;
2246 bool query_in_progress = false;
2247 if (autocomplete_edit_tracker_->ContainsHandle(autocomplete_edit_handle)) {
[email protected]81c21222008-09-10 19:35:522248 query_in_progress = autocomplete_edit_tracker_->
2249 GetResource(autocomplete_edit_handle)->model()->query_in_progress();
initial.commit09911bf2008-07-26 23:55:292250 success = true;
2251 }
2252 Send(new AutomationMsg_AutocompleteEditIsQueryInProgressResponse(
2253 message.routing_id(), success, query_in_progress));
2254}
2255
[email protected]18cb2572008-08-21 20:34:452256void AutomationProvider::OnMessageFromExternalHost(
2257 int handle, const std::string& target, const std::string& message) {
[email protected]fa83e762008-08-15 21:41:392258 if (tab_tracker_->ContainsHandle(handle)) {
2259 NavigationController* tab = tab_tracker_->GetResource(handle);
2260 if (!tab) {
2261 NOTREACHED();
2262 return;
2263 }
2264 TabContents* tab_contents = tab->GetTabContents(TAB_CONTENTS_WEB);
2265 if (!tab_contents) {
2266 NOTREACHED();
2267 return;
2268 }
2269
2270 WebContents* web_contents = tab_contents->AsWebContents();
2271 if (!web_contents) {
2272 NOTREACHED();
2273 return;
2274 }
2275
2276 RenderViewHost* view_host = web_contents->render_view_host();
2277 if (!view_host) {
2278 return;
2279 }
2280
[email protected]18cb2572008-08-21 20:34:452281 view_host->ForwardMessageFromExternalHost(target, message);
[email protected]fa83e762008-08-15 21:41:392282 }
2283}
2284
[email protected]20e93d12008-08-28 16:31:572285WebContents* AutomationProvider::GetWebContentsForHandle(
2286 int handle, NavigationController** tab) {
2287 WebContents* web_contents = NULL;
2288 if (tab_tracker_->ContainsHandle(handle)) {
2289 NavigationController* nav_controller = tab_tracker_->GetResource(handle);
2290 TabContents* tab_contents = nav_controller->active_contents();
2291 if (tab_contents && tab_contents->type() == TAB_CONTENTS_WEB) {
2292 web_contents = tab_contents->AsWebContents();
2293 if (tab)
2294 *tab = nav_controller;
2295 }
2296 }
2297 return web_contents;
2298}
2299
initial.commit09911bf2008-07-26 23:55:292300TestingAutomationProvider::TestingAutomationProvider(Profile* profile)
2301 : AutomationProvider(profile) {
2302 BrowserList::AddObserver(this);
2303 NotificationService::current()->AddObserver(this, NOTIFY_SESSION_END,
2304 NotificationService::AllSources());
2305}
2306
2307TestingAutomationProvider::~TestingAutomationProvider() {
2308 NotificationService::current()->RemoveObserver(this, NOTIFY_SESSION_END,
2309 NotificationService::AllSources());
2310 BrowserList::RemoveObserver(this);
2311}
2312
2313void TestingAutomationProvider::OnChannelError() {
2314 BrowserList::CloseAllBrowsers(true);
2315 AutomationProvider::OnChannelError();
2316}
2317
2318void TestingAutomationProvider::OnBrowserRemoving(const Browser* browser) {
2319 // For backwards compatibility with the testing automation interface, we
2320 // want the automation provider (and hence the process) to go away when the
2321 // last browser goes away.
2322 if (BrowserList::size() == 1) {
2323 // If you change this, update Observer for NOTIFY_SESSION_END below.
[email protected]295039bd2008-08-15 04:32:572324 MessageLoop::current()->PostTask(FROM_HERE,
2325 NewRunnableMethod(this, &TestingAutomationProvider::OnRemoveProvider));
initial.commit09911bf2008-07-26 23:55:292326 }
2327}
2328
2329void TestingAutomationProvider::Observe(NotificationType type,
2330 const NotificationSource& source,
2331 const NotificationDetails& details) {
2332 DCHECK(type == NOTIFY_SESSION_END);
2333 // OnBrowserRemoving does a ReleaseLater. When session end is received we exit
2334 // before the task runs resulting in this object not being deleted. This
2335 // Release balance out the Release scheduled by OnBrowserRemoving.
2336 Release();
2337}
[email protected]295039bd2008-08-15 04:32:572338
2339void TestingAutomationProvider::OnRemoveProvider() {
2340 AutomationProviderList::GetInstance()->RemoveProvider(this);
2341}
[email protected]8a3422c92008-09-24 17:42:422342
2343void AutomationProvider::GetSSLInfoBarCount(const IPC::Message& message,
2344 int handle) {
2345 int count = -1; // -1 means error.
2346 if (tab_tracker_->ContainsHandle(handle)) {
2347 NavigationController* nav_controller = tab_tracker_->GetResource(handle);
2348 if (nav_controller) {
2349 count = static_cast<int>(nav_controller->ssl_manager()->
2350 visible_info_bars_.size());
2351 }
2352 }
2353 Send(new AutomationMsg_GetSSLInfoBarCountResponse(message.routing_id(),
2354 count));
2355}
2356
2357void AutomationProvider::ClickSSLInfoBarLink(const IPC::Message& message,
2358 int handle,
2359 int info_bar_index,
2360 bool wait_for_navigation) {
2361 bool success = false;
2362 if (tab_tracker_->ContainsHandle(handle)) {
2363 NavigationController* nav_controller = tab_tracker_->GetResource(handle);
2364 if (nav_controller) {
2365 int count = static_cast<int>(nav_controller->ssl_manager()->
2366 visible_info_bars_.size());
2367 if (info_bar_index >= 0 && info_bar_index < count) {
2368 if (wait_for_navigation) {
2369 AddNavigationStatusListener(nav_controller,
2370 new AutomationMsg_ClickSSLInfoBarLinkResponse(
2371 message.routing_id(), true),
2372 new AutomationMsg_ClickSSLInfoBarLinkResponse(
2373 message.routing_id(), true));
2374 }
2375 SSLManager::SSLInfoBar* info_bar =
2376 nav_controller->ssl_manager()->visible_info_bars_.
2377 GetElementAt(info_bar_index);
2378 info_bar->LinkActivated(NULL, 0); // Parameters are not used.
2379 success = true;
2380 }
2381 }
2382 }
2383 if (!wait_for_navigation || !success)
2384 Send(new AutomationMsg_ClickSSLInfoBarLinkResponse(message.routing_id(),
2385 success));
2386}
2387
2388void AutomationProvider::GetLastNavigationTime(const IPC::Message& message,
2389 int handle) {
2390 Time time = tab_tracker_->GetLastNavigationTime(handle);
2391 Send(new AutomationMsg_GetLastNavigationTimeResponse(message.routing_id(),
2392 time.ToInternalValue()));
2393}
2394
2395void AutomationProvider::WaitForNavigation(const IPC::Message& message,
2396 int handle,
2397 int64 last_navigation_time) {
2398 NavigationController* controller = NULL;
2399 if (tab_tracker_->ContainsHandle(handle))
2400 controller = tab_tracker_->GetResource(handle);
2401
2402 Time time = tab_tracker_->GetLastNavigationTime(handle);
2403 if (time.ToInternalValue() > last_navigation_time || !controller) {
2404 Send(new AutomationMsg_WaitForNavigationResponse(message.routing_id(),
2405 controller != NULL));
2406 return;
2407 }
2408
2409 AddNavigationStatusListener(controller,
2410 new AutomationMsg_WaitForNavigationResponse(message.routing_id(),
2411 true),
2412 new AutomationMsg_WaitForNavigationResponse(message.routing_id(),
2413 true));
2414}
2415
2416void AutomationProvider::SetIntPreference(const IPC::Message& message,
2417 int handle,
2418 std::wstring name,
2419 int value) {
2420 bool success = false;
2421 if (browser_tracker_->ContainsHandle(handle)) {
2422 Browser* browser = browser_tracker_->GetResource(handle);
2423 browser->profile()->GetPrefs()->SetInteger(name.c_str(), value);
2424 success = true;
2425 }
2426 Send(new AutomationMsg_SetIntPreferenceResponse(message.routing_id(),
2427 success));
2428}