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