diff options
author | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-28 00:02:08 +0000 |
---|---|---|
committer | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-28 00:02:08 +0000 |
commit | e12de87eca9b85c26152c32e349d84670c5dcb54 (patch) | |
tree | 20a5c62c9d6658a70a13c723d1f2c22c2b9eeb0d /chrome/browser | |
parent | 9b5d7374459f0deee6dbf7a5aa4dc43aec25e38c (diff) | |
download | chromium_src-e12de87eca9b85c26152c32e349d84670c5dcb54.zip chromium_src-e12de87eca9b85c26152c32e349d84670c5dcb54.tar.gz chromium_src-e12de87eca9b85c26152c32e349d84670c5dcb54.tar.bz2 |
Move observers out of automation_provider.cc to declutter the file.
Also make sure they all use DISALLOW_COPY_AND_ASSIGN.
TEST=none
http://crbug.com/19874
Review URL: http://codereview.chromium.org/176004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@24702 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/automation/automation_provider.cc | 747 | ||||
-rw-r--r-- | chrome/browser/automation/automation_provider_observers.cc | 630 | ||||
-rw-r--r-- | chrome/browser/automation/automation_provider_observers.h | 341 | ||||
-rw-r--r-- | chrome/browser/views/find_bar_win_browsertest.cc | 4 |
4 files changed, 976 insertions, 746 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc index a3c2c09..93aad4d 100644 --- a/chrome/browser/automation/automation_provider.cc +++ b/chrome/browser/automation/automation_provider.cc @@ -21,6 +21,7 @@ #include "chrome/browser/app_modal_dialog_queue.h" #include "chrome/browser/automation/automation_extension_function.h" #include "chrome/browser/automation/automation_provider_list.h" +#include "chrome/browser/automation/automation_provider_observers.h" #include "chrome/browser/automation/extension_automation_constants.h" #include "chrome/browser/automation/extension_port_container.h" #include "chrome/browser/blocked_popup_container.h" @@ -70,752 +71,6 @@ using base::Time; -class InitialLoadObserver : public NotificationObserver { - public: - InitialLoadObserver(size_t tab_count, AutomationProvider* automation) - : automation_(automation), - outstanding_tab_count_(tab_count) { - if (outstanding_tab_count_ > 0) { - registrar_.Add(this, NotificationType::LOAD_START, - NotificationService::AllSources()); - registrar_.Add(this, NotificationType::LOAD_STOP, - NotificationService::AllSources()); - } - } - - ~InitialLoadObserver() { - } - - void ConditionMet() { - registrar_.RemoveAll(); - automation_->Send(new AutomationMsg_InitialLoadsComplete(0)); - } - - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - if (type == NotificationType::LOAD_START) { - if (outstanding_tab_count_ > loading_tabs_.size()) - loading_tabs_.insert(source.map_key()); - } else if (type == NotificationType::LOAD_STOP) { - if (outstanding_tab_count_ > finished_tabs_.size()) { - if (loading_tabs_.find(source.map_key()) != loading_tabs_.end()) - finished_tabs_.insert(source.map_key()); - if (outstanding_tab_count_ == finished_tabs_.size()) - ConditionMet(); - } - } else { - NOTREACHED(); - } - } - - private: - typedef std::set<uintptr_t> TabSet; - - NotificationRegistrar registrar_; - - AutomationProvider* automation_; - size_t outstanding_tab_count_; - TabSet loading_tabs_; - TabSet finished_tabs_; -}; - -// Watches for NewTabUI page loads for performance timing purposes. -class NewTabUILoadObserver : public NotificationObserver { - public: - explicit NewTabUILoadObserver(AutomationProvider* automation) - : automation_(automation) { - registrar_.Add(this, NotificationType::INITIAL_NEW_TAB_UI_LOAD, - NotificationService::AllSources()); - } - - ~NewTabUILoadObserver() { - } - - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - if (type == NotificationType::INITIAL_NEW_TAB_UI_LOAD) { - Details<int> load_time(details); - automation_->Send( - new AutomationMsg_InitialNewTabUILoadComplete(0, *load_time.ptr())); - } else { - NOTREACHED(); - } - } - - private: - NotificationRegistrar registrar_; - AutomationProvider* automation_; -}; - -class NavigationControllerRestoredObserver : public NotificationObserver { - public: - NavigationControllerRestoredObserver(AutomationProvider* automation, - NavigationController* controller, - IPC::Message* reply_message) - : automation_(automation), - controller_(controller), - reply_message_(reply_message) { - if (FinishedRestoring()) { - SendDone(); - } else { - registrar_.Add(this, NotificationType::LOAD_STOP, - NotificationService::AllSources()); - } - } - - ~NavigationControllerRestoredObserver() { - } - - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - if (FinishedRestoring()) { - SendDone(); - registrar_.RemoveAll(); - } - } - - private: - bool FinishedRestoring() { - return (!controller_->needs_reload() && !controller_->pending_entry() && - !controller_->tab_contents()->is_loading()); - } - - void SendDone() { - DCHECK(reply_message_ != NULL); - automation_->Send(reply_message_); - } - - NotificationRegistrar registrar_; - AutomationProvider* automation_; - NavigationController* controller_; - IPC::Message* reply_message_; - - DISALLOW_COPY_AND_ASSIGN(NavigationControllerRestoredObserver); -}; - -class NavigationNotificationObserver : public NotificationObserver { - public: - NavigationNotificationObserver(NavigationController* controller, - AutomationProvider* automation, - IPC::Message* reply_message, - int number_of_navigations) - : automation_(automation), - reply_message_(reply_message), - controller_(controller), - navigations_remaining_(number_of_navigations), - navigation_started_(false) { - DCHECK_LT(0, navigations_remaining_); - Source<NavigationController> source(controller_); - registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED, source); - registrar_.Add(this, NotificationType::LOAD_START, source); - registrar_.Add(this, NotificationType::LOAD_STOP, source); - registrar_.Add(this, NotificationType::AUTH_NEEDED, source); - registrar_.Add(this, NotificationType::AUTH_SUPPLIED, source); - } - - ~NavigationNotificationObserver() { - if (reply_message_) { - // This means we did not receive a notification for this navigation. - // Send over a failed navigation status back to the caller to ensure that - // the caller does not hang waiting for the response. - IPC::ParamTraits<AutomationMsg_NavigationResponseValues>::Write( - reply_message_, AUTOMATION_MSG_NAVIGATION_ERROR); - automation_->Send(reply_message_); - reply_message_ = NULL; - } - - automation_->RemoveNavigationStatusListener(this); - } - - void ConditionMet(AutomationMsg_NavigationResponseValues navigation_result) { - DCHECK(reply_message_ != NULL); - - IPC::ParamTraits<AutomationMsg_NavigationResponseValues>::Write( - reply_message_, navigation_result); - automation_->Send(reply_message_); - reply_message_ = NULL; - - delete this; - } - - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - // We listen for 2 events to determine when the navigation started because: - // - when this is used by the WaitForNavigation method, we might be invoked - // afer the load has started (but not after the entry was committed, as - // WaitForNavigation compares times of the last navigation). - // - when this is used with a page requiring authentication, we will not get - // a NotificationType::NAV_ENTRY_COMMITTED until after we authenticate, so - // we need the NotificationType::LOAD_START. - if (type == NotificationType::NAV_ENTRY_COMMITTED || - type == NotificationType::LOAD_START) { - navigation_started_ = true; - } else if (type == NotificationType::LOAD_STOP) { - if (navigation_started_) { - navigation_started_ = false; - if (--navigations_remaining_ == 0) - ConditionMet(AUTOMATION_MSG_NAVIGATION_SUCCESS); - } - } else if (type == NotificationType::AUTH_SUPPLIED) { - // The LoginHandler for this tab is no longer valid. - automation_->RemoveLoginHandler(controller_); - - // Treat this as if navigation started again, since load start/stop don't - // occur while authentication is ongoing. - navigation_started_ = true; - } else if (type == NotificationType::AUTH_NEEDED) { -#if defined(OS_WIN) - if (navigation_started_) { - // Remember the login handler that wants authentication. - LoginHandler* handler = - Details<LoginNotificationDetails>(details)->handler(); - automation_->AddLoginHandler(controller_, handler); - - // Respond that authentication is needed. - navigation_started_ = false; - ConditionMet(AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED); - } else { - NOTREACHED(); - } -#else - // TODO(port): Enable when we have LoginNotificationDetails etc. - NOTIMPLEMENTED(); -#endif - } else { - NOTREACHED(); - } - } - - private: - NotificationRegistrar registrar_; - AutomationProvider* automation_; - IPC::Message* reply_message_; - NavigationController* controller_; - int navigations_remaining_; - bool navigation_started_; -}; - -class TabStripNotificationObserver : public NotificationObserver { - public: - TabStripNotificationObserver(NotificationType notification, - AutomationProvider* automation) - : automation_(automation), - notification_(notification) { - registrar_.Add(this, notification_, NotificationService::AllSources()); - } - - virtual ~TabStripNotificationObserver() { - } - - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - if (type == notification_) { - ObserveTab(Source<NavigationController>(source).ptr()); - - // If verified, no need to observe anymore - automation_->RemoveTabStripObserver(this); - delete this; - } else { - NOTREACHED(); - } - } - - virtual void ObserveTab(NavigationController* controller) = 0; - - protected: - NotificationRegistrar registrar_; - AutomationProvider* automation_; - NotificationType notification_; -}; - -class TabAppendedNotificationObserver : public TabStripNotificationObserver { - public: - TabAppendedNotificationObserver(Browser* parent, - AutomationProvider* automation, - IPC::Message* reply_message) - : TabStripNotificationObserver(NotificationType::TAB_PARENTED, - automation), - parent_(parent), - reply_message_(reply_message) { - } - - virtual void ObserveTab(NavigationController* controller) { - if (automation_->GetIndexForNavigationController(controller, parent_) == - TabStripModel::kNoTab) { - // This tab notification doesn't belong to the parent_. - return; - } - - automation_->AddNavigationStatusListener(controller, reply_message_, 1); - } - - protected: - Browser* parent_; - IPC::Message* reply_message_; -}; - -class TabClosedNotificationObserver : public TabStripNotificationObserver { - public: - TabClosedNotificationObserver(AutomationProvider* automation, - bool wait_until_closed, - IPC::Message* reply_message) - : TabStripNotificationObserver(wait_until_closed ? - NotificationType::TAB_CLOSED : NotificationType::TAB_CLOSING, - automation), - reply_message_(reply_message), - for_browser_command_(false) { - } - - virtual void ObserveTab(NavigationController* controller) { - if (for_browser_command_) { - AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message_, - true); - } else { - AutomationMsg_CloseTab::WriteReplyParams(reply_message_, true); - } - automation_->Send(reply_message_); - } - - void set_for_browser_command(bool for_browser_command) { - for_browser_command_ = for_browser_command; - } - - protected: - IPC::Message* reply_message_; - bool for_browser_command_; -}; - -class BrowserOpenedNotificationObserver : public NotificationObserver { - public: - BrowserOpenedNotificationObserver(AutomationProvider* automation, - IPC::Message* reply_message) - : automation_(automation), - reply_message_(reply_message), - for_browser_command_(false) { - registrar_.Add(this, NotificationType::BROWSER_OPENED, - NotificationService::AllSources()); - } - - ~BrowserOpenedNotificationObserver() { - } - - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - if (type == NotificationType::BROWSER_OPENED) { - if (for_browser_command_) { - AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message_, - true); - } - automation_->Send(reply_message_); - delete this; - } else { - NOTREACHED(); - } - } - - void set_for_browser_command(bool for_browser_command) { - for_browser_command_ = for_browser_command; - } - - private: - NotificationRegistrar registrar_; - AutomationProvider* automation_; - IPC::Message* reply_message_; - bool for_browser_command_; -}; - -class BrowserClosedNotificationObserver : public NotificationObserver { - public: - BrowserClosedNotificationObserver(Browser* browser, - AutomationProvider* automation, - IPC::Message* reply_message) - : automation_(automation), - reply_message_(reply_message), - for_browser_command_(false) { - registrar_.Add(this, NotificationType::BROWSER_CLOSED, - Source<Browser>(browser)); - } - - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - DCHECK(type == NotificationType::BROWSER_CLOSED); - Details<bool> close_app(details); - DCHECK(reply_message_ != NULL); - if (for_browser_command_) { - AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message_, - true); - } else { - AutomationMsg_CloseBrowser::WriteReplyParams(reply_message_, true, - *(close_app.ptr())); - } - automation_->Send(reply_message_); - reply_message_ = NULL; - delete this; - } - - void set_for_browser_command(bool for_browser_command) { - for_browser_command_ = for_browser_command; - } - - private: - NotificationRegistrar registrar_; - AutomationProvider* automation_; - IPC::Message* reply_message_; - bool for_browser_command_; -}; - -class BrowserCountChangeNotificationObserver : public NotificationObserver { - public: - BrowserCountChangeNotificationObserver(int target_count, - AutomationProvider* automation, - IPC::Message* reply_message) - : target_count_(target_count), - automation_(automation), - reply_message_(reply_message) { - registrar_.Add(this, NotificationType::BROWSER_OPENED, - NotificationService::AllSources()); - registrar_.Add(this, NotificationType::BROWSER_CLOSED, - NotificationService::AllSources()); - } - - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - DCHECK(type == NotificationType::BROWSER_OPENED || - type == NotificationType::BROWSER_CLOSED); - int current_count = static_cast<int>(BrowserList::size()); - if (type == NotificationType::BROWSER_CLOSED) { - // At the time of the notification the browser being closed is not removed - // from the list. The real count is one less than the reported count. - DCHECK_LT(0, current_count); - current_count--; - } - if (current_count == target_count_) { - AutomationMsg_WaitForBrowserWindowCountToBecome::WriteReplyParams( - reply_message_, true); - automation_->Send(reply_message_); - reply_message_ = NULL; - delete this; - } - } - - private: - int target_count_; - NotificationRegistrar registrar_; - AutomationProvider* automation_; - IPC::Message* reply_message_; -}; - -class AppModalDialogShownObserver : public NotificationObserver { - public: - AppModalDialogShownObserver(AutomationProvider* automation, - IPC::Message* reply_message) - : automation_(automation), - reply_message_(reply_message) { - registrar_.Add(this, NotificationType::APP_MODAL_DIALOG_SHOWN, - NotificationService::AllSources()); - } - - ~AppModalDialogShownObserver() { - } - - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - DCHECK(type == NotificationType::APP_MODAL_DIALOG_SHOWN); - AutomationMsg_WaitForAppModalDialogToBeShown::WriteReplyParams( - reply_message_, true); - automation_->Send(reply_message_); - reply_message_ = NULL; - delete this; - } - - private: - NotificationRegistrar registrar_; - AutomationProvider* automation_; - IPC::Message* reply_message_; -}; - -namespace { - -// Define mapping from command to notification -struct CommandNotification { - int command; - NotificationType::Type notification_type; -}; - -const struct CommandNotification command_notifications[] = { - {IDC_DUPLICATE_TAB, NotificationType::TAB_PARENTED}, - {IDC_NEW_TAB, NotificationType::TAB_PARENTED}, - // Returns as soon as the restored tab is created. To further wait until - // the content page is loaded, use WaitForTabToBeRestored. - {IDC_RESTORE_TAB, NotificationType::TAB_PARENTED} -}; - -} // namespace - -class ExecuteBrowserCommandObserver : public NotificationObserver { - public: - ~ExecuteBrowserCommandObserver() { - } - - static bool CreateAndRegisterObserver(AutomationProvider* automation, - Browser* browser, - int command, - IPC::Message* reply_message) { - bool result = true; - switch (command) { - case IDC_NEW_WINDOW: - case IDC_NEW_INCOGNITO_WINDOW: { - BrowserOpenedNotificationObserver* observer = - new BrowserOpenedNotificationObserver(automation, reply_message); - observer->set_for_browser_command(true); - break; - } - case IDC_CLOSE_WINDOW: { - BrowserClosedNotificationObserver* observer = - new BrowserClosedNotificationObserver(browser, automation, - reply_message); - observer->set_for_browser_command(true); - break; - } - case IDC_CLOSE_TAB: { - TabClosedNotificationObserver* observer = - new TabClosedNotificationObserver(automation, true, reply_message); - observer->set_for_browser_command(true); - break; - } - case IDC_BACK: - case IDC_FORWARD: - case IDC_RELOAD: { - automation->AddNavigationStatusListener( - &browser->GetSelectedTabContents()->controller(), - reply_message, 1); - break; - } - default: { - ExecuteBrowserCommandObserver* observer = - new ExecuteBrowserCommandObserver(automation, reply_message); - if (!observer->Register(command)) { - delete observer; - result = false; - } - break; - } - } - return result; - } - - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - if (type == notification_type_) { - AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message_, - true); - automation_->Send(reply_message_); - delete this; - } else { - NOTREACHED(); - } - } - - private: - ExecuteBrowserCommandObserver(AutomationProvider* automation, - IPC::Message* reply_message) - : automation_(automation), - reply_message_(reply_message) { - } - - bool Register(int command) { - if (!GetNotificationType(command, ¬ification_type_)) - return false; - registrar_.Add(this, notification_type_, NotificationService::AllSources()); - return true; - } - - bool GetNotificationType(int command, NotificationType::Type* type) { - if (!type) - return false; - bool found = false; - for (unsigned int i = 0; i < arraysize(command_notifications); i++) { - if (command_notifications[i].command == command) { - *type = command_notifications[i].notification_type; - found = true; - break; - } - } - return found; - } - - NotificationRegistrar registrar_; - AutomationProvider* automation_; - NotificationType::Type notification_type_; - IPC::Message* reply_message_; -}; - -class FindInPageNotificationObserver : public NotificationObserver { - public: - FindInPageNotificationObserver(AutomationProvider* automation, - TabContents* parent_tab, - IPC::Message* reply_message) - : automation_(automation), - active_match_ordinal_(-1), - reply_message_(reply_message) { - registrar_.Add(this, NotificationType::FIND_RESULT_AVAILABLE, - Source<TabContents>(parent_tab)); - } - - ~FindInPageNotificationObserver() { - } - - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - if (type == NotificationType::FIND_RESULT_AVAILABLE) { - Details<FindNotificationDetails> find_details(details); - if (find_details->request_id() == kFindInPageRequestId) { - // We get multiple responses and one of those will contain the ordinal. - // This message comes to us before the final update is sent. - if (find_details->active_match_ordinal() > -1) - active_match_ordinal_ = find_details->active_match_ordinal(); - if (find_details->final_update()) { - if (reply_message_ != NULL) { - AutomationMsg_FindInPage::WriteReplyParams(reply_message_, - active_match_ordinal_, find_details->number_of_matches()); - automation_->Send(reply_message_); - reply_message_ = NULL; - } else { - DLOG(WARNING) << "Multiple final Find messages observed."; - } - } else { - DLOG(INFO) << "Ignoring, since we only care about the final message"; - } - } - } else { - NOTREACHED(); - } - } - - // The Find mechanism is over asynchronous IPC, so a search is kicked off and - // we wait for notification to find out what the results are. As the user is - // typing, new search requests can be issued and the Request ID helps us make - // sense of whether this is the current request or an old one. The unit tests, - // however, which uses this constant issues only one search at a time, so we - // don't need a rolling id to identify each search. But, we still need to - // specify one, so we just use a fixed one - its value does not matter. - static const int kFindInPageRequestId; - - private: - NotificationRegistrar registrar_; - AutomationProvider* automation_; - // We will at some point (before final update) be notified of the ordinal and - // we need to preserve it so we can send it later. - int active_match_ordinal_; - IPC::Message* reply_message_; -}; - -const int FindInPageNotificationObserver::kFindInPageRequestId = -1; - -class DomOperationNotificationObserver : public NotificationObserver { - public: - explicit DomOperationNotificationObserver(AutomationProvider* automation) - : automation_(automation) { - registrar_.Add(this, NotificationType::DOM_OPERATION_RESPONSE, - NotificationService::AllSources()); - } - - ~DomOperationNotificationObserver() { - } - - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - if (NotificationType::DOM_OPERATION_RESPONSE == type) { - Details<DomOperationNotificationDetails> dom_op_details(details); - - IPC::Message* reply_message = automation_->reply_message_release(); - DCHECK(reply_message != NULL); - - AutomationMsg_DomOperation::WriteReplyParams(reply_message, - dom_op_details->json()); - automation_->Send(reply_message); - } - } - - private: - NotificationRegistrar registrar_; - AutomationProvider* automation_; -}; - -#if defined(OS_WIN) -// TODO(port): Enable when printing is ported. -class DocumentPrintedNotificationObserver : public NotificationObserver { - public: - DocumentPrintedNotificationObserver(AutomationProvider* automation, - IPC::Message* reply_message) - : automation_(automation), - success_(false), - reply_message_(reply_message) { - registrar_.Add(this, NotificationType::PRINT_JOB_EVENT, - NotificationService::AllSources()); - } - - ~DocumentPrintedNotificationObserver() { - DCHECK(reply_message_ != NULL); - AutomationMsg_PrintNow::WriteReplyParams(reply_message_, success_); - automation_->Send(reply_message_); - automation_->RemoveNavigationStatusListener(this); - } - - virtual void Observe(NotificationType type, const NotificationSource& source, - const NotificationDetails& details) { - using namespace printing; - DCHECK(type == NotificationType::PRINT_JOB_EVENT); - switch (Details<JobEventDetails>(details)->type()) { - case JobEventDetails::JOB_DONE: { - // Succeeded. - success_ = true; - delete this; - break; - } - case JobEventDetails::USER_INIT_CANCELED: - case JobEventDetails::FAILED: { - // Failed. - delete this; - break; - } - case JobEventDetails::NEW_DOC: - case JobEventDetails::USER_INIT_DONE: - case JobEventDetails::DEFAULT_INIT_DONE: - case JobEventDetails::NEW_PAGE: - case JobEventDetails::PAGE_DONE: - case JobEventDetails::DOC_DONE: - case JobEventDetails::ALL_PAGES_REQUESTED: { - // Don't care. - break; - } - default: { - NOTREACHED(); - break; - } - } - } - - private: - NotificationRegistrar registrar_; - scoped_refptr<AutomationProvider> automation_; - bool success_; - IPC::Message* reply_message_; -}; -#endif // defined(OS_WIN) - class AutomationInterstitialPage : public InterstitialPage { public: AutomationInterstitialPage(TabContents* tab, diff --git a/chrome/browser/automation/automation_provider_observers.cc b/chrome/browser/automation/automation_provider_observers.cc new file mode 100644 index 0000000..fc427bb --- /dev/null +++ b/chrome/browser/automation/automation_provider_observers.cc @@ -0,0 +1,630 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/automation/automation_provider_observers.h" + +#include "base/basictypes.h" +#include "chrome/app/chrome_dll_resource.h" +#include "chrome/browser/automation/automation_provider.h" +#include "chrome/browser/dom_operation_notification_details.h" +#include "chrome/browser/login_prompt.h" +#if defined(OS_WIN) +#include "chrome/browser/printing/print_job.h" +#endif // defined(OS_WIN) +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/notification_service.h" + +InitialLoadObserver::InitialLoadObserver(size_t tab_count, + AutomationProvider* automation) + : automation_(automation), + outstanding_tab_count_(tab_count) { + if (outstanding_tab_count_ > 0) { + registrar_.Add(this, NotificationType::LOAD_START, + NotificationService::AllSources()); + registrar_.Add(this, NotificationType::LOAD_STOP, + NotificationService::AllSources()); + } +} + +InitialLoadObserver::~InitialLoadObserver() { +} + +void InitialLoadObserver::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + if (type == NotificationType::LOAD_START) { + if (outstanding_tab_count_ > loading_tabs_.size()) + loading_tabs_.insert(source.map_key()); + } else if (type == NotificationType::LOAD_STOP) { + if (outstanding_tab_count_ > finished_tabs_.size()) { + if (loading_tabs_.find(source.map_key()) != loading_tabs_.end()) + finished_tabs_.insert(source.map_key()); + if (outstanding_tab_count_ == finished_tabs_.size()) + ConditionMet(); + } + } else { + NOTREACHED(); + } +} + +void InitialLoadObserver::ConditionMet() { + registrar_.RemoveAll(); + automation_->Send(new AutomationMsg_InitialLoadsComplete(0)); +} + +NewTabUILoadObserver::NewTabUILoadObserver(AutomationProvider* automation) + : automation_(automation) { + registrar_.Add(this, NotificationType::INITIAL_NEW_TAB_UI_LOAD, + NotificationService::AllSources()); +} + +NewTabUILoadObserver::~NewTabUILoadObserver() { +} + +void NewTabUILoadObserver::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + if (type == NotificationType::INITIAL_NEW_TAB_UI_LOAD) { + Details<int> load_time(details); + automation_->Send( + new AutomationMsg_InitialNewTabUILoadComplete(0, *load_time.ptr())); + } else { + NOTREACHED(); + } +} + +NavigationControllerRestoredObserver::NavigationControllerRestoredObserver( + AutomationProvider* automation, + NavigationController* controller, + IPC::Message* reply_message) + : automation_(automation), + controller_(controller), + reply_message_(reply_message) { + if (FinishedRestoring()) { + SendDone(); + } else { + registrar_.Add(this, NotificationType::LOAD_STOP, + NotificationService::AllSources()); + } +} + +NavigationControllerRestoredObserver::~NavigationControllerRestoredObserver() { +} + +void NavigationControllerRestoredObserver::Observe( + NotificationType type, const NotificationSource& source, + const NotificationDetails& details) { + if (FinishedRestoring()) { + SendDone(); + registrar_.RemoveAll(); + } +} + +bool NavigationControllerRestoredObserver::FinishedRestoring() { + return (!controller_->needs_reload() && !controller_->pending_entry() && + !controller_->tab_contents()->is_loading()); +} + +void NavigationControllerRestoredObserver::SendDone() { + DCHECK(reply_message_ != NULL); + automation_->Send(reply_message_); +} + +NavigationNotificationObserver::NavigationNotificationObserver( + NavigationController* controller, + AutomationProvider* automation, + IPC::Message* reply_message, + int number_of_navigations) + : automation_(automation), + reply_message_(reply_message), + controller_(controller), + navigations_remaining_(number_of_navigations), + navigation_started_(false) { + DCHECK_LT(0, navigations_remaining_); + Source<NavigationController> source(controller_); + registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED, source); + registrar_.Add(this, NotificationType::LOAD_START, source); + registrar_.Add(this, NotificationType::LOAD_STOP, source); + registrar_.Add(this, NotificationType::AUTH_NEEDED, source); + registrar_.Add(this, NotificationType::AUTH_SUPPLIED, source); +} + +NavigationNotificationObserver::~NavigationNotificationObserver() { + if (reply_message_) { + // This means we did not receive a notification for this navigation. + // Send over a failed navigation status back to the caller to ensure that + // the caller does not hang waiting for the response. + IPC::ParamTraits<AutomationMsg_NavigationResponseValues>::Write( + reply_message_, AUTOMATION_MSG_NAVIGATION_ERROR); + automation_->Send(reply_message_); + reply_message_ = NULL; + } + + automation_->RemoveNavigationStatusListener(this); +} + +void NavigationNotificationObserver::Observe( + NotificationType type, const NotificationSource& source, + const NotificationDetails& details) { + // We listen for 2 events to determine when the navigation started because: + // - when this is used by the WaitForNavigation method, we might be invoked + // afer the load has started (but not after the entry was committed, as + // WaitForNavigation compares times of the last navigation). + // - when this is used with a page requiring authentication, we will not get + // a NotificationType::NAV_ENTRY_COMMITTED until after we authenticate, so + // we need the NotificationType::LOAD_START. + if (type == NotificationType::NAV_ENTRY_COMMITTED || + type == NotificationType::LOAD_START) { + navigation_started_ = true; + } else if (type == NotificationType::LOAD_STOP) { + if (navigation_started_) { + navigation_started_ = false; + if (--navigations_remaining_ == 0) + ConditionMet(AUTOMATION_MSG_NAVIGATION_SUCCESS); + } + } else if (type == NotificationType::AUTH_SUPPLIED) { + // The LoginHandler for this tab is no longer valid. + automation_->RemoveLoginHandler(controller_); + + // Treat this as if navigation started again, since load start/stop don't + // occur while authentication is ongoing. + navigation_started_ = true; + } else if (type == NotificationType::AUTH_NEEDED) { +#if defined(OS_WIN) + if (navigation_started_) { + // Remember the login handler that wants authentication. + LoginHandler* handler = + Details<LoginNotificationDetails>(details)->handler(); + automation_->AddLoginHandler(controller_, handler); + + // Respond that authentication is needed. + navigation_started_ = false; + ConditionMet(AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED); + } else { + NOTREACHED(); + } +#else + // TODO(port): Enable when we have LoginNotificationDetails etc. + NOTIMPLEMENTED(); +#endif + } else { + NOTREACHED(); + } +} + +void NavigationNotificationObserver::ConditionMet( + AutomationMsg_NavigationResponseValues navigation_result) { + DCHECK(reply_message_ != NULL); + + IPC::ParamTraits<AutomationMsg_NavigationResponseValues>::Write( + reply_message_, navigation_result); + automation_->Send(reply_message_); + reply_message_ = NULL; + + delete this; +} + +TabStripNotificationObserver::TabStripNotificationObserver( + NotificationType notification, AutomationProvider* automation) + : automation_(automation), + notification_(notification) { + registrar_.Add(this, notification_, NotificationService::AllSources()); +} + +TabStripNotificationObserver::~TabStripNotificationObserver() { +} + +void TabStripNotificationObserver::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + if (type == notification_) { + ObserveTab(Source<NavigationController>(source).ptr()); + + // If verified, no need to observe anymore + automation_->RemoveTabStripObserver(this); + delete this; + } else { + NOTREACHED(); + } +} + +TabAppendedNotificationObserver::TabAppendedNotificationObserver( + Browser* parent, AutomationProvider* automation, + IPC::Message* reply_message) + : TabStripNotificationObserver(NotificationType::TAB_PARENTED, automation), + parent_(parent), + reply_message_(reply_message) { +} + +void TabAppendedNotificationObserver::ObserveTab( + NavigationController* controller) { + if (automation_->GetIndexForNavigationController(controller, parent_) == + TabStripModel::kNoTab) { + // This tab notification doesn't belong to the parent_. + return; + } + + automation_->AddNavigationStatusListener(controller, reply_message_, 1); +} + +TabClosedNotificationObserver::TabClosedNotificationObserver( + AutomationProvider* automation, bool wait_until_closed, + IPC::Message* reply_message) + : TabStripNotificationObserver(wait_until_closed ? + NotificationType::TAB_CLOSED : NotificationType::TAB_CLOSING, + automation), + reply_message_(reply_message), + for_browser_command_(false) { +} + +void TabClosedNotificationObserver::ObserveTab( + NavigationController* controller) { + if (for_browser_command_) { + AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message_, + true); + } else { + AutomationMsg_CloseTab::WriteReplyParams(reply_message_, true); + } + automation_->Send(reply_message_); +} + +void TabClosedNotificationObserver::set_for_browser_command( + bool for_browser_command) { + for_browser_command_ = for_browser_command; +} + +BrowserOpenedNotificationObserver::BrowserOpenedNotificationObserver( + AutomationProvider* automation, IPC::Message* reply_message) + : automation_(automation), + reply_message_(reply_message), + for_browser_command_(false) { + registrar_.Add(this, NotificationType::BROWSER_OPENED, + NotificationService::AllSources()); +} + +BrowserOpenedNotificationObserver::~BrowserOpenedNotificationObserver() { +} + +void BrowserOpenedNotificationObserver::Observe( + NotificationType type, const NotificationSource& source, + const NotificationDetails& details) { + if (type == NotificationType::BROWSER_OPENED) { + if (for_browser_command_) { + AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message_, + true); + } + automation_->Send(reply_message_); + delete this; + } else { + NOTREACHED(); + } +} + +void BrowserOpenedNotificationObserver::set_for_browser_command( + bool for_browser_command) { + for_browser_command_ = for_browser_command; +} + +BrowserClosedNotificationObserver::BrowserClosedNotificationObserver( + Browser* browser, + AutomationProvider* automation, + IPC::Message* reply_message) + : automation_(automation), + reply_message_(reply_message), + for_browser_command_(false) { + registrar_.Add(this, NotificationType::BROWSER_CLOSED, + Source<Browser>(browser)); +} + +void BrowserClosedNotificationObserver::Observe( + NotificationType type, const NotificationSource& source, + const NotificationDetails& details) { + DCHECK(type == NotificationType::BROWSER_CLOSED); + Details<bool> close_app(details); + DCHECK(reply_message_ != NULL); + if (for_browser_command_) { + AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message_, + true); + } else { + AutomationMsg_CloseBrowser::WriteReplyParams(reply_message_, true, + *(close_app.ptr())); + } + automation_->Send(reply_message_); + reply_message_ = NULL; + delete this; +} + +void BrowserClosedNotificationObserver::set_for_browser_command( + bool for_browser_command) { + for_browser_command_ = for_browser_command; +} + +BrowserCountChangeNotificationObserver::BrowserCountChangeNotificationObserver( + int target_count, + AutomationProvider* automation, + IPC::Message* reply_message) + : target_count_(target_count), + automation_(automation), + reply_message_(reply_message) { + registrar_.Add(this, NotificationType::BROWSER_OPENED, + NotificationService::AllSources()); + registrar_.Add(this, NotificationType::BROWSER_CLOSED, + NotificationService::AllSources()); +} + +void BrowserCountChangeNotificationObserver::Observe( + NotificationType type, const NotificationSource& source, + const NotificationDetails& details) { + DCHECK(type == NotificationType::BROWSER_OPENED || + type == NotificationType::BROWSER_CLOSED); + int current_count = static_cast<int>(BrowserList::size()); + if (type == NotificationType::BROWSER_CLOSED) { + // At the time of the notification the browser being closed is not removed + // from the list. The real count is one less than the reported count. + DCHECK_LT(0, current_count); + current_count--; + } + if (current_count == target_count_) { + AutomationMsg_WaitForBrowserWindowCountToBecome::WriteReplyParams( + reply_message_, true); + automation_->Send(reply_message_); + reply_message_ = NULL; + delete this; + } +} + +AppModalDialogShownObserver::AppModalDialogShownObserver( + AutomationProvider* automation, IPC::Message* reply_message) + : automation_(automation), + reply_message_(reply_message) { + registrar_.Add(this, NotificationType::APP_MODAL_DIALOG_SHOWN, + NotificationService::AllSources()); +} + +AppModalDialogShownObserver::~AppModalDialogShownObserver() { +} + +void AppModalDialogShownObserver::Observe( + NotificationType type, const NotificationSource& source, + const NotificationDetails& details) { + DCHECK(type == NotificationType::APP_MODAL_DIALOG_SHOWN); + AutomationMsg_WaitForAppModalDialogToBeShown::WriteReplyParams( + reply_message_, true); + automation_->Send(reply_message_); + reply_message_ = NULL; + delete this; +} + +namespace { + +// Define mapping from command to notification +struct CommandNotification { + int command; + NotificationType::Type notification_type; +}; + +const struct CommandNotification command_notifications[] = { + {IDC_DUPLICATE_TAB, NotificationType::TAB_PARENTED}, + {IDC_NEW_TAB, NotificationType::TAB_PARENTED}, + // Returns as soon as the restored tab is created. To further wait until + // the content page is loaded, use WaitForTabToBeRestored. + {IDC_RESTORE_TAB, NotificationType::TAB_PARENTED} +}; + +} // namespace + +ExecuteBrowserCommandObserver::~ExecuteBrowserCommandObserver() { +} + +// static +bool ExecuteBrowserCommandObserver::CreateAndRegisterObserver( + AutomationProvider* automation, Browser* browser, int command, + IPC::Message* reply_message) { + bool result = true; + switch (command) { + case IDC_NEW_WINDOW: + case IDC_NEW_INCOGNITO_WINDOW: { + BrowserOpenedNotificationObserver* observer = + new BrowserOpenedNotificationObserver(automation, reply_message); + observer->set_for_browser_command(true); + break; + } + case IDC_CLOSE_WINDOW: { + BrowserClosedNotificationObserver* observer = + new BrowserClosedNotificationObserver(browser, automation, + reply_message); + observer->set_for_browser_command(true); + break; + } + case IDC_CLOSE_TAB: { + TabClosedNotificationObserver* observer = + new TabClosedNotificationObserver(automation, true, reply_message); + observer->set_for_browser_command(true); + break; + } + case IDC_BACK: + case IDC_FORWARD: + case IDC_RELOAD: { + automation->AddNavigationStatusListener( + &browser->GetSelectedTabContents()->controller(), + reply_message, 1); + break; + } + default: { + ExecuteBrowserCommandObserver* observer = + new ExecuteBrowserCommandObserver(automation, reply_message); + if (!observer->Register(command)) { + delete observer; + result = false; + } + break; + } + } + return result; +} + +void ExecuteBrowserCommandObserver::Observe( + NotificationType type, const NotificationSource& source, + const NotificationDetails& details) { + if (type == notification_type_) { + AutomationMsg_WindowExecuteCommand::WriteReplyParams(reply_message_, + true); + automation_->Send(reply_message_); + delete this; + } else { + NOTREACHED(); + } +} + +ExecuteBrowserCommandObserver::ExecuteBrowserCommandObserver( + AutomationProvider* automation, IPC::Message* reply_message) + : automation_(automation), + reply_message_(reply_message) { +} + +bool ExecuteBrowserCommandObserver::Register(int command) { + if (!GetNotificationType(command, ¬ification_type_)) + return false; + registrar_.Add(this, notification_type_, NotificationService::AllSources()); + return true; +} + +bool ExecuteBrowserCommandObserver::GetNotificationType( + int command, NotificationType::Type* type) { + if (!type) + return false; + bool found = false; + for (unsigned int i = 0; i < arraysize(command_notifications); i++) { + if (command_notifications[i].command == command) { + *type = command_notifications[i].notification_type; + found = true; + break; + } + } + return found; +} + +FindInPageNotificationObserver::FindInPageNotificationObserver( + AutomationProvider* automation, TabContents* parent_tab, + IPC::Message* reply_message) + : automation_(automation), + active_match_ordinal_(-1), + reply_message_(reply_message) { + registrar_.Add(this, NotificationType::FIND_RESULT_AVAILABLE, + Source<TabContents>(parent_tab)); +} + +FindInPageNotificationObserver::~FindInPageNotificationObserver() { +} + +void FindInPageNotificationObserver::Observe( + NotificationType type, const NotificationSource& source, + const NotificationDetails& details) { + if (type == NotificationType::FIND_RESULT_AVAILABLE) { + Details<FindNotificationDetails> find_details(details); + if (find_details->request_id() == kFindInPageRequestId) { + // We get multiple responses and one of those will contain the ordinal. + // This message comes to us before the final update is sent. + if (find_details->active_match_ordinal() > -1) + active_match_ordinal_ = find_details->active_match_ordinal(); + if (find_details->final_update()) { + if (reply_message_ != NULL) { + AutomationMsg_FindInPage::WriteReplyParams(reply_message_, + active_match_ordinal_, find_details->number_of_matches()); + automation_->Send(reply_message_); + reply_message_ = NULL; + } else { + DLOG(WARNING) << "Multiple final Find messages observed."; + } + } else { + DLOG(INFO) << "Ignoring, since we only care about the final message"; + } + } + } else { + NOTREACHED(); + } +} + +// static +const int FindInPageNotificationObserver::kFindInPageRequestId = -1; + +DomOperationNotificationObserver::DomOperationNotificationObserver( + AutomationProvider* automation) + : automation_(automation) { + registrar_.Add(this, NotificationType::DOM_OPERATION_RESPONSE, + NotificationService::AllSources()); +} + +DomOperationNotificationObserver::~DomOperationNotificationObserver() { +} + +void DomOperationNotificationObserver::Observe( + NotificationType type, const NotificationSource& source, + const NotificationDetails& details) { + if (NotificationType::DOM_OPERATION_RESPONSE == type) { + Details<DomOperationNotificationDetails> dom_op_details(details); + + IPC::Message* reply_message = automation_->reply_message_release(); + DCHECK(reply_message != NULL); + + AutomationMsg_DomOperation::WriteReplyParams(reply_message, + dom_op_details->json()); + automation_->Send(reply_message); + } +} + +#if defined(OS_WIN) +// TODO(port): Enable when printing is ported. +DocumentPrintedNotificationObserver::DocumentPrintedNotificationObserver( + AutomationProvider* automation, IPC::Message* reply_message) + : automation_(automation), + success_(false), + reply_message_(reply_message) { + registrar_.Add(this, NotificationType::PRINT_JOB_EVENT, + NotificationService::AllSources()); +} + +DocumentPrintedNotificationObserver::~DocumentPrintedNotificationObserver() { + DCHECK(reply_message_ != NULL); + AutomationMsg_PrintNow::WriteReplyParams(reply_message_, success_); + automation_->Send(reply_message_); + automation_->RemoveNavigationStatusListener(this); +} + +void DocumentPrintedNotificationObserver::Observe( + NotificationType type, const NotificationSource& source, + const NotificationDetails& details) { + using namespace printing; + DCHECK(type == NotificationType::PRINT_JOB_EVENT); + switch (Details<JobEventDetails>(details)->type()) { + case JobEventDetails::JOB_DONE: { + // Succeeded. + success_ = true; + delete this; + break; + } + case JobEventDetails::USER_INIT_CANCELED: + case JobEventDetails::FAILED: { + // Failed. + delete this; + break; + } + case JobEventDetails::NEW_DOC: + case JobEventDetails::USER_INIT_DONE: + case JobEventDetails::DEFAULT_INIT_DONE: + case JobEventDetails::NEW_PAGE: + case JobEventDetails::PAGE_DONE: + case JobEventDetails::DOC_DONE: + case JobEventDetails::ALL_PAGES_REQUESTED: { + // Don't care. + break; + } + default: { + NOTREACHED(); + break; + } + } +} +#endif // defined(OS_WIN) diff --git a/chrome/browser/automation/automation_provider_observers.h b/chrome/browser/automation/automation_provider_observers.h new file mode 100644 index 0000000..2dd596e --- /dev/null +++ b/chrome/browser/automation/automation_provider_observers.h @@ -0,0 +1,341 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_AUTOMATION_AUTOMATION_PROVIDER_OBSERVERS_H_ +#define CHROME_BROWSER_AUTOMATION_AUTOMATION_PROVIDER_OBSERVERS_H_ + +#include <set> + +#include "chrome/common/notification_observer.h" +#include "chrome/common/notification_registrar.h" +#include "chrome/common/notification_type.h" +#include "chrome/test/automation/automation_messages.h" + +class AutomationProvider; +class Browser; +class NavigationController; +class TabContents; + +namespace IPC { +class Message; +} + +class InitialLoadObserver : public NotificationObserver { + public: + InitialLoadObserver(size_t tab_count, AutomationProvider* automation); + ~InitialLoadObserver(); + + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + private: + typedef std::set<uintptr_t> TabSet; + + void ConditionMet(); + + NotificationRegistrar registrar_; + + AutomationProvider* automation_; + size_t outstanding_tab_count_; + TabSet loading_tabs_; + TabSet finished_tabs_; + + DISALLOW_COPY_AND_ASSIGN(InitialLoadObserver); +}; + +// Watches for NewTabUI page loads for performance timing purposes. +class NewTabUILoadObserver : public NotificationObserver { + public: + explicit NewTabUILoadObserver(AutomationProvider* automation); + ~NewTabUILoadObserver(); + + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + private: + NotificationRegistrar registrar_; + AutomationProvider* automation_; + + DISALLOW_COPY_AND_ASSIGN(NewTabUILoadObserver); +}; + +class NavigationControllerRestoredObserver : public NotificationObserver { + public: + NavigationControllerRestoredObserver(AutomationProvider* automation, + NavigationController* controller, + IPC::Message* reply_message); + ~NavigationControllerRestoredObserver(); + + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + private: + bool FinishedRestoring(); + void SendDone(); + + NotificationRegistrar registrar_; + AutomationProvider* automation_; + NavigationController* controller_; + IPC::Message* reply_message_; + + DISALLOW_COPY_AND_ASSIGN(NavigationControllerRestoredObserver); +}; + +class NavigationNotificationObserver : public NotificationObserver { + public: + NavigationNotificationObserver(NavigationController* controller, + AutomationProvider* automation, + IPC::Message* reply_message, + int number_of_navigations); + ~NavigationNotificationObserver(); + + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + private: + void ConditionMet(AutomationMsg_NavigationResponseValues navigation_result); + + NotificationRegistrar registrar_; + AutomationProvider* automation_; + IPC::Message* reply_message_; + NavigationController* controller_; + int navigations_remaining_; + bool navigation_started_; + + DISALLOW_COPY_AND_ASSIGN(NavigationNotificationObserver); +}; + +class TabStripNotificationObserver : public NotificationObserver { + public: + TabStripNotificationObserver(NotificationType notification, + AutomationProvider* automation); + virtual ~TabStripNotificationObserver(); + + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + virtual void ObserveTab(NavigationController* controller) = 0; + + protected: + NotificationRegistrar registrar_; + AutomationProvider* automation_; + NotificationType notification_; +}; + +class TabAppendedNotificationObserver : public TabStripNotificationObserver { + public: + TabAppendedNotificationObserver(Browser* parent, + AutomationProvider* automation, + IPC::Message* reply_message); + + virtual void ObserveTab(NavigationController* controller); + + protected: + Browser* parent_; + IPC::Message* reply_message_; + + private: + DISALLOW_COPY_AND_ASSIGN(TabAppendedNotificationObserver); +}; + +class TabClosedNotificationObserver : public TabStripNotificationObserver { + public: + TabClosedNotificationObserver(AutomationProvider* automation, + bool wait_until_closed, + IPC::Message* reply_message); + + virtual void ObserveTab(NavigationController* controller); + + void set_for_browser_command(bool for_browser_command); + + protected: + IPC::Message* reply_message_; + bool for_browser_command_; + + private: + DISALLOW_COPY_AND_ASSIGN(TabClosedNotificationObserver); +}; + +class BrowserOpenedNotificationObserver : public NotificationObserver { + public: + BrowserOpenedNotificationObserver(AutomationProvider* automation, + IPC::Message* reply_message); + ~BrowserOpenedNotificationObserver(); + + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + void set_for_browser_command(bool for_browser_command); + + private: + NotificationRegistrar registrar_; + AutomationProvider* automation_; + IPC::Message* reply_message_; + bool for_browser_command_; + + DISALLOW_COPY_AND_ASSIGN(BrowserOpenedNotificationObserver); +}; + +class BrowserClosedNotificationObserver : public NotificationObserver { + public: + BrowserClosedNotificationObserver(Browser* browser, + AutomationProvider* automation, + IPC::Message* reply_message); + + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + void set_for_browser_command(bool for_browser_command); + + private: + NotificationRegistrar registrar_; + AutomationProvider* automation_; + IPC::Message* reply_message_; + bool for_browser_command_; + + DISALLOW_COPY_AND_ASSIGN(BrowserClosedNotificationObserver); +}; + +class BrowserCountChangeNotificationObserver : public NotificationObserver { + public: + BrowserCountChangeNotificationObserver(int target_count, + AutomationProvider* automation, + IPC::Message* reply_message); + + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + private: + int target_count_; + NotificationRegistrar registrar_; + AutomationProvider* automation_; + IPC::Message* reply_message_; + + DISALLOW_COPY_AND_ASSIGN(BrowserCountChangeNotificationObserver); +}; + +class AppModalDialogShownObserver : public NotificationObserver { + public: + AppModalDialogShownObserver(AutomationProvider* automation, + IPC::Message* reply_message); + ~AppModalDialogShownObserver(); + + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + private: + NotificationRegistrar registrar_; + AutomationProvider* automation_; + IPC::Message* reply_message_; + + DISALLOW_COPY_AND_ASSIGN(AppModalDialogShownObserver); +}; + +class ExecuteBrowserCommandObserver : public NotificationObserver { + public: + ~ExecuteBrowserCommandObserver(); + + static bool CreateAndRegisterObserver(AutomationProvider* automation, + Browser* browser, + int command, + IPC::Message* reply_message); + + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + private: + ExecuteBrowserCommandObserver(AutomationProvider* automation, + IPC::Message* reply_message); + + bool Register(int command); + + bool GetNotificationType(int command, NotificationType::Type* type); + + NotificationRegistrar registrar_; + AutomationProvider* automation_; + NotificationType::Type notification_type_; + IPC::Message* reply_message_; + + DISALLOW_COPY_AND_ASSIGN(ExecuteBrowserCommandObserver); +}; + +class FindInPageNotificationObserver : public NotificationObserver { + public: + FindInPageNotificationObserver(AutomationProvider* automation, + TabContents* parent_tab, + IPC::Message* reply_message); + ~FindInPageNotificationObserver(); + + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + // The Find mechanism is over asynchronous IPC, so a search is kicked off and + // we wait for notification to find out what the results are. As the user is + // typing, new search requests can be issued and the Request ID helps us make + // sense of whether this is the current request or an old one. The unit tests, + // however, which uses this constant issues only one search at a time, so we + // don't need a rolling id to identify each search. But, we still need to + // specify one, so we just use a fixed one - its value does not matter. + static const int kFindInPageRequestId; + + private: + NotificationRegistrar registrar_; + AutomationProvider* automation_; + // We will at some point (before final update) be notified of the ordinal and + // we need to preserve it so we can send it later. + int active_match_ordinal_; + IPC::Message* reply_message_; + + DISALLOW_COPY_AND_ASSIGN(FindInPageNotificationObserver); +}; + +class DomOperationNotificationObserver : public NotificationObserver { + public: + explicit DomOperationNotificationObserver(AutomationProvider* automation); + ~DomOperationNotificationObserver(); + + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + private: + NotificationRegistrar registrar_; + AutomationProvider* automation_; + + DISALLOW_COPY_AND_ASSIGN(DomOperationNotificationObserver); +}; + +#if defined(OS_WIN) +// TODO(port): Enable when printing is ported. +class DocumentPrintedNotificationObserver : public NotificationObserver { + public: + DocumentPrintedNotificationObserver(AutomationProvider* automation, + IPC::Message* reply_message); + ~DocumentPrintedNotificationObserver(); + + virtual void Observe(NotificationType type, const NotificationSource& source, + const NotificationDetails& details); + + private: + NotificationRegistrar registrar_; + scoped_refptr<AutomationProvider> automation_; + bool success_; + IPC::Message* reply_message_; + + DISALLOW_COPY_AND_ASSIGN(DocumentPrintedNotificationObserver); +}; +#endif // defined(OS_WIN) + +#endif // CHROME_BROWSER_AUTOMATION_AUTOMATION_PROVIDER_OBSERVERS_H_ diff --git a/chrome/browser/views/find_bar_win_browsertest.cc b/chrome/browser/views/find_bar_win_browsertest.cc index 3995293..63847fc 100644 --- a/chrome/browser/views/find_bar_win_browsertest.cc +++ b/chrome/browser/views/find_bar_win_browsertest.cc @@ -27,6 +27,8 @@ const std::wstring kPrematureEnd = L"files/find_in_page/premature_end.html"; const std::wstring kMoveIfOver = L"files/find_in_page/move_if_obscuring.html"; const std::wstring kBitstackCrash = L"files/find_in_page/crash_14491.html"; +namespace { + class FindInPageNotificationObserver : public NotificationObserver { public: explicit FindInPageNotificationObserver(TabContents* parent_tab) @@ -76,6 +78,8 @@ class FindInPageNotificationObserver : public NotificationObserver { int current_find_request_id_; }; +} // namespace + typedef enum { BACK = 0, FWD = 1 } FindInPageDirection; typedef enum { IGNORE_CASE = 0, CASE_SENSITIVE = 1 } FindInPageCase; |