Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(243)

Side by Side Diff: chrome/browser/automation/automation_provider_observers.cc

Issue 176004: Move observers out of automation_provider.cc to declutter the file. (Closed)
Patch Set: Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2009 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.
4
5 #include "chrome/browser/automation/automation_provider_observers.h"
6
7 #include "base/basictypes.h"
8 #include "chrome/app/chrome_dll_resource.h"
9 #include "chrome/browser/automation/automation_provider.h"
10 #include "chrome/browser/dom_operation_notification_details.h"
11 #include "chrome/browser/login_prompt.h"
12 #if defined(OS_WIN)
13 #include "chrome/browser/printing/print_job.h"
14 #endif // defined(OS_WIN)
15 #include "chrome/browser/tab_contents/navigation_controller.h"
16 #include "chrome/browser/tab_contents/tab_contents.h"
17 #include "chrome/common/notification_service.h"
18
19 InitialLoadObserver::InitialLoadObserver(size_t tab_count,
20 AutomationProvider* automation)
21 : automation_(automation),
22 outstanding_tab_count_(tab_count) {
23 if (outstanding_tab_count_ > 0) {
24 registrar_.Add(this, NotificationType::LOAD_START,
25 NotificationService::AllSources());
26 registrar_.Add(this, NotificationType::LOAD_STOP,
27 NotificationService::AllSources());
28 }
29 }
30
31 InitialLoadObserver::~InitialLoadObserver() {
32 }
33
34 void InitialLoadObserver::Observe(NotificationType type,
35 const NotificationSource& source,
36 const NotificationDetails& details) {
37 if (type == NotificationType::LOAD_START) {
38 if (outstanding_tab_count_ > loading_tabs_.size())
39 loading_tabs_.insert(source.map_key());
40 } else if (type == NotificationType::LOAD_STOP) {
41 if (outstanding_tab_count_ > finished_tabs_.size()) {
42 if (loading_tabs_.find(source.map_key()) != loading_tabs_.end())
43 finished_tabs_.insert(source.map_key());
44 if (outstanding_tab_count_ == finished_tabs_.size())
45 ConditionMet();
46 }
47 } else {
48 NOTREACHED();
49 }
50 }
51
52 void InitialLoadObserver::ConditionMet() {
53 registrar_.RemoveAll();
54 automation_->Send(new AutomationMsg_InitialLoadsComplete(0));
55 }
56
57 NewTabUILoadObserver::NewTabUILoadObserver(AutomationProvider* automation)
58 : automation_(automation) {
59 registrar_.Add(this, NotificationType::INITIAL_NEW_TAB_UI_LOAD,
60 NotificationService::AllSources());
61 }
62
63 NewTabUILoadObserver::~NewTabUILoadObserver() {
64 }
65
66 void NewTabUILoadObserver::Observe(NotificationType type,
67 const NotificationSource& source,
68 const NotificationDetails& details) {
69 if (type == NotificationType::INITIAL_NEW_TAB_UI_LOAD) {
70 Details<int> load_time(details);
71 automation_->Send(
72 new AutomationMsg_InitialNewTabUILoadComplete(0, *load_time.ptr()));
73 } else {
74 NOTREACHED();
75 }
76 }
77
78 NavigationControllerRestoredObserver::NavigationControllerRestoredObserver(
79 AutomationProvider* automation,
80 NavigationController* controller,
81 IPC::Message* reply_message)
82 : automation_(automation),
83 controller_(controller),
84 reply_message_(reply_message) {
85 if (FinishedRestoring()) {
86 SendDone();
87 } else {
88 registrar_.Add(this, NotificationType::LOAD_STOP,
89 NotificationService::AllSources());
90 }
91 }
92
93 NavigationControllerRestoredObserver::~NavigationControllerRestoredObserver() {
94 }
95
96 void NavigationControllerRestoredObserver::Observe(
97 NotificationType type, const NotificationSource& source,
98 const NotificationDetails& details) {
99 if (FinishedRestoring()) {
100 SendDone();
101 registrar_.RemoveAll();
102 }
103 }
104
105 bool NavigationControllerRestoredObserver::FinishedRestoring() {
106 return (!controller_->needs_reload() && !controller_->pending_entry() &&
107 !controller_->tab_contents()->is_loading());
108 }
109
110 void NavigationControllerRestoredObserver::SendDone() {
111 DCHECK(reply_message_ != NULL);
112 automation_->Send(reply_message_);
113 }
114
115 NavigationNotificationObserver::NavigationNotificationObserver(
116 NavigationController* controller,
117 AutomationProvider* automation,
118 IPC::Message* reply_message,
119 int number_of_navigations)
120 : automation_(automation),
121 reply_message_(reply_message),
122 controller_(controller),
123 navigations_remaining_(number_of_navigations),
124 navigation_started_(false) {
125 DCHECK_LT(0, navigations_remaining_);
126 Source<NavigationController> source(controller_);
127 registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED, source);
128 registrar_.Add(this, NotificationType::LOAD_START, source);
129 registrar_.Add(this, NotificationType::LOAD_STOP, source);
130 registrar_.Add(this, NotificationType::AUTH_NEEDED, source);
131 registrar_.Add(this, NotificationType::AUTH_SUPPLIED, source);
132 }
133
134 NavigationNotificationObserver::~NavigationNotificationObserver() {
135 if (reply_message_) {
136 // This means we did not receive a notification for this navigation.
137 // Send over a failed navigation status back to the caller to ensure that
138 // the caller does not hang waiting for the response.
139 IPC::ParamTraits<AutomationMsg_NavigationResponseValues>::Write(
140 reply_message_, AUTOMATION_MSG_NAVIGATION_ERROR);
141 automation_->Send(reply_message_);
142 reply_message_ = NULL;
143 }
144
145 automation_->RemoveNavigationStatusListener(this);
146 }
147
148 void NavigationNotificationObserver::Observe(
149 NotificationType type, const NotificationSource& source,
150 const NotificationDetails& details) {
151 // We listen for 2 events to determine when the navigation started because:
152 // - when this is used by the WaitForNavigation method, we might be invoked
153 // afer the load has started (but not after the entry was committed, as
154 // WaitForNavigation compares times of the last navigation).
155 // - when this is used with a page requiring authentication, we will not get
156 // a NotificationType::NAV_ENTRY_COMMITTED until after we authenticate, so
157 // we need the NotificationType::LOAD_START.
158 if (type == NotificationType::NAV_ENTRY_COMMITTED ||
159 type == NotificationType::LOAD_START) {
160 navigation_started_ = true;
161 } else if (type == NotificationType::LOAD_STOP) {
162 if (navigation_started_) {
163 navigation_started_ = false;
164 if (--navigations_remaining_ == 0)
165 ConditionMet(AUTOMATION_MSG_NAVIGATION_SUCCESS);
166 }
167 } else if (type == NotificationType::AUTH_SUPPLIED) {
168 // The LoginHandler for this tab is no longer valid.
169 automation_->RemoveLoginHandler(controller_);
170
171 // Treat this as if navigation started again, since load start/stop don't
172 // occur while authentication is ongoing.
173 navigation_started_ = true;
174 } else if (type == NotificationType::AUTH_NEEDED) {
175 #if defined(OS_WIN)
176 if (navigation_started_) {
177 // Remember the login handler that wants authentication.
178 LoginHandler* handler =
179 Details<LoginNotificationDetails>(details)->handler();
180 automation_->AddLoginHandler(controller_, handler);
181
182 // Respond that authentication is needed.
183 navigation_started_ = false;
184 ConditionMet(AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED);
185 } else {
186 NOTREACHED();
187 }
188 #else
189 // TODO(port): Enable when we have LoginNotificationDetails etc.
190 NOTIMPLEMENTED();
191 #endif
192 } else {
193 NOTREACHED();
194 }
195 }
196
197 void NavigationNotificationObserver::ConditionMet(
198 AutomationMsg_NavigationResponseValues navigation_result) {
199 DCHECK(reply_message_ != NULL);
200
201 IPC::ParamTraits<AutomationMsg_NavigationResponseValues>::Write(
202 reply_message_, navigation_result);
203 automation_->Send(reply_message_);
204 reply_message_ = NULL;
205
206 delete this;
207 }
208
209 TabStripNotificationObserver::TabStripNotificationObserver(
210 NotificationType notification, AutomationProvider* automation)
211 : automation_(automation),
212 notification_(notification) {
213 registrar_.Add(this, notification_, NotificationService::AllSources());
214 }
215
216 TabStripNotificationObserver::~TabStripNotificationObserver() {
217 }
218
219 void TabStripNotificationObserver::Observe(NotificationType type,
220 const NotificationSource& source,
221 const NotificationDetails& details) {
222 if (type == notification_) {
223 ObserveTab(Source<NavigationController>(source).ptr());
224
225 // If verified, no need to observe anymore
226 automation_->RemoveTabStripObserver(this);
227 delete this;
228 } else {
229 NOTREACHED();
230 }
231 }
232
233 TabAppendedNotificationObserver::TabAppendedNotificationObserver(
234 Browser* parent, AutomationProvider* automation,
235 IPC::Message* reply_message)
236 : TabStripNotificationObserver(NotificationType::TAB_PARENTED, automation),
237 parent_(parent),
238 reply_message_(reply_message) {
239 }
240
241 void TabAppendedNotificationObserver::ObserveTab(
242 NavigationController* controller) {
243 if (automation_->GetIndexForNavigationController(controller, parent_) ==
244 TabStripModel::kNoTab) {
245 // This tab notification doesn't belong to the parent_.
246 return;
247 }
248
249 automation_->AddNavigationStatusListener(controller, reply_message_, 1);
250 }
251
252 TabClosedNotificationObserver::TabClosedNotificationObserver(
253 AutomationProvider* automation, bool wait_until_closed,
254 IPC::Message* reply_message)
255 : TabStripNotificationObserver(wait_until_closed ?
256 NotificationType::TAB_CLOSED : NotificationType::TAB_CLOSING,
257 automation),
258 reply_message_(reply_message),
259 for_browser_command_(false) {
260 }
261
262 void TabClosedNotificationObserver::ObserveTab(
263 NavigationController* controller) {
264 if (for_browser_command_) {
265 AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message_,
266 true);
267 } else {
268 AutomationMsg_CloseTab::WriteReplyParams(reply_message_, true);
269 }
270 automation_->Send(reply_message_);
271 }
272
273 void TabClosedNotificationObserver::set_for_browser_command(
274 bool for_browser_command) {
275 for_browser_command_ = for_browser_command;
276 }
277
278 BrowserOpenedNotificationObserver::BrowserOpenedNotificationObserver(
279 AutomationProvider* automation, IPC::Message* reply_message)
280 : automation_(automation),
281 reply_message_(reply_message),
282 for_browser_command_(false) {
283 registrar_.Add(this, NotificationType::BROWSER_OPENED,
284 NotificationService::AllSources());
285 }
286
287 BrowserOpenedNotificationObserver::~BrowserOpenedNotificationObserver() {
288 }
289
290 void BrowserOpenedNotificationObserver::Observe(
291 NotificationType type, const NotificationSource& source,
292 const NotificationDetails& details) {
293 if (type == NotificationType::BROWSER_OPENED) {
294 if (for_browser_command_) {
295 AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message_,
296 true);
297 }
298 automation_->Send(reply_message_);
299 delete this;
300 } else {
301 NOTREACHED();
302 }
303 }
304
305 void BrowserOpenedNotificationObserver::set_for_browser_command(
306 bool for_browser_command) {
307 for_browser_command_ = for_browser_command;
308 }
309
310 BrowserClosedNotificationObserver::BrowserClosedNotificationObserver(
311 Browser* browser,
312 AutomationProvider* automation,
313 IPC::Message* reply_message)
314 : automation_(automation),
315 reply_message_(reply_message),
316 for_browser_command_(false) {
317 registrar_.Add(this, NotificationType::BROWSER_CLOSED,
318 Source<Browser>(browser));
319 }
320
321 void BrowserClosedNotificationObserver::Observe(
322 NotificationType type, const NotificationSource& source,
323 const NotificationDetails& details) {
324 DCHECK(type == NotificationType::BROWSER_CLOSED);
325 Details<bool> close_app(details);
326 DCHECK(reply_message_ != NULL);
327 if (for_browser_command_) {
328 AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message_,
329 true);
330 } else {
331 AutomationMsg_CloseBrowser::WriteReplyParams(reply_message_, true,
332 *(close_app.ptr()));
333 }
334 automation_->Send(reply_message_);
335 reply_message_ = NULL;
336 delete this;
337 }
338
339 void BrowserClosedNotificationObserver::set_for_browser_command(
340 bool for_browser_command) {
341 for_browser_command_ = for_browser_command;
342 }
343
344 BrowserCountChangeNotificationObserver::BrowserCountChangeNotificationObserver(
345 int target_count,
346 AutomationProvider* automation,
347 IPC::Message* reply_message)
348 : target_count_(target_count),
349 automation_(automation),
350 reply_message_(reply_message) {
351 registrar_.Add(this, NotificationType::BROWSER_OPENED,
352 NotificationService::AllSources());
353 registrar_.Add(this, NotificationType::BROWSER_CLOSED,
354 NotificationService::AllSources());
355 }
356
357 void BrowserCountChangeNotificationObserver::Observe(
358 NotificationType type, const NotificationSource& source,
359 const NotificationDetails& details) {
360 DCHECK(type == NotificationType::BROWSER_OPENED ||
361 type == NotificationType::BROWSER_CLOSED);
362 int current_count = static_cast<int>(BrowserList::size());
363 if (type == NotificationType::BROWSER_CLOSED) {
364 // At the time of the notification the browser being closed is not removed
365 // from the list. The real count is one less than the reported count.
366 DCHECK_LT(0, current_count);
367 current_count--;
368 }
369 if (current_count == target_count_) {
370 AutomationMsg_WaitForBrowserWindowCountToBecome::WriteReplyParams(
371 reply_message_, true);
372 automation_->Send(reply_message_);
373 reply_message_ = NULL;
374 delete this;
375 }
376 }
377
378 AppModalDialogShownObserver::AppModalDialogShownObserver(
379 AutomationProvider* automation, IPC::Message* reply_message)
380 : automation_(automation),
381 reply_message_(reply_message) {
382 registrar_.Add(this, NotificationType::APP_MODAL_DIALOG_SHOWN,
383 NotificationService::AllSources());
384 }
385
386 AppModalDialogShownObserver::~AppModalDialogShownObserver() {
387 }
388
389 void AppModalDialogShownObserver::Observe(
390 NotificationType type, const NotificationSource& source,
391 const NotificationDetails& details) {
392 DCHECK(type == NotificationType::APP_MODAL_DIALOG_SHOWN);
393 AutomationMsg_WaitForAppModalDialogToBeShown::WriteReplyParams(
394 reply_message_, true);
395 automation_->Send(reply_message_);
396 reply_message_ = NULL;
397 delete this;
398 }
399
400 namespace {
401
402 // Define mapping from command to notification
403 struct CommandNotification {
404 int command;
405 NotificationType::Type notification_type;
406 };
407
408 const struct CommandNotification command_notifications[] = {
409 {IDC_DUPLICATE_TAB, NotificationType::TAB_PARENTED},
410 {IDC_NEW_TAB, NotificationType::TAB_PARENTED},
411 // Returns as soon as the restored tab is created. To further wait until
412 // the content page is loaded, use WaitForTabToBeRestored.
413 {IDC_RESTORE_TAB, NotificationType::TAB_PARENTED}
414 };
415
416 } // namespace
417
418 ExecuteBrowserCommandObserver::~ExecuteBrowserCommandObserver() {
419 }
420
421 // static
422 bool ExecuteBrowserCommandObserver::CreateAndRegisterObserver(
423 AutomationProvider* automation, Browser* browser, int command,
424 IPC::Message* reply_message) {
425 bool result = true;
426 switch (command) {
427 case IDC_NEW_WINDOW:
428 case IDC_NEW_INCOGNITO_WINDOW: {
429 BrowserOpenedNotificationObserver* observer =
430 new BrowserOpenedNotificationObserver(automation, reply_message);
431 observer->set_for_browser_command(true);
432 break;
433 }
434 case IDC_CLOSE_WINDOW: {
435 BrowserClosedNotificationObserver* observer =
436 new BrowserClosedNotificationObserver(browser, automation,
437 reply_message);
438 observer->set_for_browser_command(true);
439 break;
440 }
441 case IDC_CLOSE_TAB: {
442 TabClosedNotificationObserver* observer =
443 new TabClosedNotificationObserver(automation, true, reply_message);
444 observer->set_for_browser_command(true);
445 break;
446 }
447 case IDC_BACK:
448 case IDC_FORWARD:
449 case IDC_RELOAD: {
450 automation->AddNavigationStatusListener(
451 &browser->GetSelectedTabContents()->controller(),
452 reply_message, 1);
453 break;
454 }
455 default: {
456 ExecuteBrowserCommandObserver* observer =
457 new ExecuteBrowserCommandObserver(automation, reply_message);
458 if (!observer->Register(command)) {
459 delete observer;
460 result = false;
461 }
462 break;
463 }
464 }
465 return result;
466 }
467
468 void ExecuteBrowserCommandObserver::Observe(
469 NotificationType type, const NotificationSource& source,
470 const NotificationDetails& details) {
471 if (type == notification_type_) {
472 AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message_,
473 true);
474 automation_->Send(reply_message_);
475 delete this;
476 } else {
477 NOTREACHED();
478 }
479 }
480
481 ExecuteBrowserCommandObserver::ExecuteBrowserCommandObserver(
482 AutomationProvider* automation, IPC::Message* reply_message)
483 : automation_(automation),
484 reply_message_(reply_message) {
485 }
486
487 bool ExecuteBrowserCommandObserver::Register(int command) {
488 if (!GetNotificationType(command, &notification_type_))
489 return false;
490 registrar_.Add(this, notification_type_, NotificationService::AllSources());
491 return true;
492 }
493
494 bool ExecuteBrowserCommandObserver::GetNotificationType(
495 int command, NotificationType::Type* type) {
496 if (!type)
497 return false;
498 bool found = false;
499 for (unsigned int i = 0; i < arraysize(command_notifications); i++) {
500 if (command_notifications[i].command == command) {
501 *type = command_notifications[i].notification_type;
502 found = true;
503 break;
504 }
505 }
506 return found;
507 }
508
509 FindInPageNotificationObserver::FindInPageNotificationObserver(
510 AutomationProvider* automation, TabContents* parent_tab,
511 IPC::Message* reply_message)
512 : automation_(automation),
513 active_match_ordinal_(-1),
514 reply_message_(reply_message) {
515 registrar_.Add(this, NotificationType::FIND_RESULT_AVAILABLE,
516 Source<TabContents>(parent_tab));
517 }
518
519 FindInPageNotificationObserver::~FindInPageNotificationObserver() {
520 }
521
522 void FindInPageNotificationObserver::Observe(
523 NotificationType type, const NotificationSource& source,
524 const NotificationDetails& details) {
525 if (type == NotificationType::FIND_RESULT_AVAILABLE) {
526 Details<FindNotificationDetails> find_details(details);
527 if (find_details->request_id() == kFindInPageRequestId) {
528 // We get multiple responses and one of those will contain the ordinal.
529 // This message comes to us before the final update is sent.
530 if (find_details->active_match_ordinal() > -1)
531 active_match_ordinal_ = find_details->active_match_ordinal();
532 if (find_details->final_update()) {
533 if (reply_message_ != NULL) {
534 AutomationMsg_FindInPage::WriteReplyParams(reply_message_,
535 active_match_ordinal_, find_details->number_of_matches());
536 automation_->Send(reply_message_);
537 reply_message_ = NULL;
538 } else {
539 DLOG(WARNING) << "Multiple final Find messages observed.";
540 }
541 } else {
542 DLOG(INFO) << "Ignoring, since we only care about the final message";
543 }
544 }
545 } else {
546 NOTREACHED();
547 }
548 }
549
550 // static
551 const int FindInPageNotificationObserver::kFindInPageRequestId = -1;
552
553 DomOperationNotificationObserver::DomOperationNotificationObserver(
554 AutomationProvider* automation)
555 : automation_(automation) {
556 registrar_.Add(this, NotificationType::DOM_OPERATION_RESPONSE,
557 NotificationService::AllSources());
558 }
559
560 DomOperationNotificationObserver::~DomOperationNotificationObserver() {
561 }
562
563 void DomOperationNotificationObserver::Observe(
564 NotificationType type, const NotificationSource& source,
565 const NotificationDetails& details) {
566 if (NotificationType::DOM_OPERATION_RESPONSE == type) {
567 Details<DomOperationNotificationDetails> dom_op_details(details);
568
569 IPC::Message* reply_message = automation_->reply_message_release();
570 DCHECK(reply_message != NULL);
571
572 AutomationMsg_DomOperation::WriteReplyParams(reply_message,
573 dom_op_details->json());
574 automation_->Send(reply_message);
575 }
576 }
577
578 #if defined(OS_WIN)
579 // TODO(port): Enable when printing is ported.
580 DocumentPrintedNotificationObserver::DocumentPrintedNotificationObserver(
581 AutomationProvider* automation, IPC::Message* reply_message)
582 : automation_(automation),
583 success_(false),
584 reply_message_(reply_message) {
585 registrar_.Add(this, NotificationType::PRINT_JOB_EVENT,
586 NotificationService::AllSources());
587 }
588
589 DocumentPrintedNotificationObserver::~DocumentPrintedNotificationObserver() {
590 DCHECK(reply_message_ != NULL);
591 AutomationMsg_PrintNow::WriteReplyParams(reply_message_, success_);
592 automation_->Send(reply_message_);
593 automation_->RemoveNavigationStatusListener(this);
594 }
595
596 void DocumentPrintedNotificationObserver::Observe(
597 NotificationType type, const NotificationSource& source,
598 const NotificationDetails& details) {
599 using namespace printing;
600 DCHECK(type == NotificationType::PRINT_JOB_EVENT);
601 switch (Details<JobEventDetails>(details)->type()) {
602 case JobEventDetails::JOB_DONE: {
603 // Succeeded.
604 success_ = true;
605 delete this;
606 break;
607 }
608 case JobEventDetails::USER_INIT_CANCELED:
609 case JobEventDetails::FAILED: {
610 // Failed.
611 delete this;
612 break;
613 }
614 case JobEventDetails::NEW_DOC:
615 case JobEventDetails::USER_INIT_DONE:
616 case JobEventDetails::DEFAULT_INIT_DONE:
617 case JobEventDetails::NEW_PAGE:
618 case JobEventDetails::PAGE_DONE:
619 case JobEventDetails::DOC_DONE:
620 case JobEventDetails::ALL_PAGES_REQUESTED: {
621 // Don't care.
622 break;
623 }
624 default: {
625 NOTREACHED();
626 break;
627 }
628 }
629 }
630 #endif // defined(OS_WIN)
OLDNEW
« no previous file with comments | « chrome/browser/automation/automation_provider_observers.h ('k') | chrome/browser/views/find_bar_win_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698