diff options
author | brettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-08-19 17:38:12 +0000 |
---|---|---|
committer | brettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-08-19 17:38:12 +0000 |
commit | 6cf85906b0504908e3fd0fafa46be78903bfd6b9 (patch) | |
tree | 564d578de2118da6012571178e9f557da2e164a5 /chrome | |
parent | dfcb522ab183af2bfd6924e32bf43a8bd173097c (diff) | |
download | chromium_src-6cf85906b0504908e3fd0fafa46be78903bfd6b9.zip chromium_src-6cf85906b0504908e3fd0fafa46be78903bfd6b9.tar.gz chromium_src-6cf85906b0504908e3fd0fafa46be78903bfd6b9.tar.bz2 |
Cleans up notifications for the NavigationController. There were several
notifications before and some of them were very unclear and misused (STATE_CHANGED). This one, and PRUNED were called unnecessarily in some cases as well.
I replaced STATE_CHANGED and INDEX_CHANGED with ENTRY_COMMITTED which is more clear and covers (I think!) all the cases that the callers care about.
I added a simple notification testing helper class, and used in the navigation controller unit tests to make sure we get the proper notifications. I had to change NotificationSource/Details to have a = and copy constructor so I can track them easily in my helper. I don't see why this would be bad.
BUG=1325636,1321376,1325779
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@1039 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/alternate_nav_url_fetcher.cc | 6 | ||||
-rw-r--r-- | chrome/browser/jsmessage_box_handler.cc | 6 | ||||
-rw-r--r-- | chrome/browser/navigation_controller.cc | 33 | ||||
-rw-r--r-- | chrome/browser/navigation_controller.h | 5 | ||||
-rw-r--r-- | chrome/browser/navigation_controller_base.cc | 25 | ||||
-rw-r--r-- | chrome/browser/navigation_controller_base.h | 2 | ||||
-rw-r--r-- | chrome/browser/navigation_controller_unittest.cc | 136 | ||||
-rw-r--r-- | chrome/browser/session_service.cc | 6 | ||||
-rw-r--r-- | chrome/browser/ssl_manager.cc | 6 | ||||
-rw-r--r-- | chrome/browser/ssl_policy.cc | 1 | ||||
-rw-r--r-- | chrome/browser/views/location_bar_view.cc | 6 | ||||
-rw-r--r-- | chrome/common/notification_details.h | 5 | ||||
-rw-r--r-- | chrome/common/notification_source.h | 5 | ||||
-rw-r--r-- | chrome/common/notification_types.h | 36 | ||||
-rw-r--r-- | chrome/test/test_notification_tracker.cc | 105 | ||||
-rw-r--r-- | chrome/test/test_notification_tracker.h | 105 | ||||
-rw-r--r-- | chrome/test/unit/unittests.vcproj | 16 |
17 files changed, 418 insertions, 86 deletions
diff --git a/chrome/browser/alternate_nav_url_fetcher.cc b/chrome/browser/alternate_nav_url_fetcher.cc index a791106..e86105b 100644 --- a/chrome/browser/alternate_nav_url_fetcher.cc +++ b/chrome/browser/alternate_nav_url_fetcher.cc @@ -41,14 +41,14 @@ AlternateNavURLFetcher::AlternateNavURLFetcher( state_(NOT_STARTED), navigated_to_entry_(false) { NotificationService::current()->AddObserver(this, - NOTIFY_NAV_STATE_CHANGED, NotificationService::AllSources()); + NOTIFY_NAV_ENTRY_PENDING, NotificationService::AllSources()); } AlternateNavURLFetcher::~AlternateNavURLFetcher() { if (state_ == NOT_STARTED) { // Never caught the NavigationController notification. NotificationService::current()->RemoveObserver(this, - NOTIFY_NAV_STATE_CHANGED, NotificationService::AllSources()); + NOTIFY_NAV_ENTRY_PENDING, NotificationService::AllSources()); } // Otherwise, Observe() removed the observer already. } @@ -69,7 +69,7 @@ void AlternateNavURLFetcher::Observe(NotificationType type, controller_->SetAlternateNavURLFetcher(this); NotificationService::current()->RemoveObserver(this, - NOTIFY_NAV_STATE_CHANGED, NotificationService::AllSources()); + NOTIFY_NAV_ENTRY_PENDING, NotificationService::AllSources()); DCHECK_EQ(NOT_STARTED, state_); state_ = IN_PROGRESS; diff --git a/chrome/browser/jsmessage_box_handler.cc b/chrome/browser/jsmessage_box_handler.cc index 09b9757..549981a 100644 --- a/chrome/browser/jsmessage_box_handler.cc +++ b/chrome/browser/jsmessage_box_handler.cc @@ -63,7 +63,7 @@ void JavascriptMessageBoxHandler::RunJavascriptMessageBox( JavascriptMessageBoxHandler::~JavascriptMessageBoxHandler() { NotificationService::current()-> - RemoveObserver(this, NOTIFY_NAV_STATE_CHANGED, + RemoveObserver(this, NOTIFY_NAV_ENTRY_COMMITTED, NotificationService::AllSources()); NotificationService::current()-> RemoveObserver(this, NOTIFY_TAB_CONTENTS_DESTROYED, @@ -188,7 +188,7 @@ void JavascriptMessageBoxHandler::Observe(NotificationType type, if (!web_contents_) return; - if (type == NOTIFY_NAV_STATE_CHANGED && + if (type == NOTIFY_NAV_ENTRY_COMMITTED && Source<NavigationController>(source).ptr() == web_contents_->controller()) web_contents_gone = true; @@ -230,7 +230,7 @@ JavascriptMessageBoxHandler::JavascriptMessageBoxHandler( // Make sure we get navigation notifications so we know when our parent // contents will disappear or navigate to a different page. NotificationService::current()-> - AddObserver(this, NOTIFY_NAV_STATE_CHANGED, + AddObserver(this, NOTIFY_NAV_ENTRY_COMMITTED, NotificationService::AllSources()); NotificationService::current()-> AddObserver(this, NOTIFY_TAB_CONTENTS_DESTROYED, diff --git a/chrome/browser/navigation_controller.cc b/chrome/browser/navigation_controller.cc index 91b404a4..5100922 100644 --- a/chrome/browser/navigation_controller.cc +++ b/chrome/browser/navigation_controller.cc @@ -349,13 +349,6 @@ const SkBitmap& NavigationController::GetLazyFavIcon() const { } } -void NavigationController::EntryUpdated(NavigationEntry* entry) { - if (entry == GetActiveEntry()) { - // Someone has modified our active navigation entry. - NotifyNavigationStateChanged(); - } -} - void NavigationController::SetAlternateNavURLFetcher( AlternateNavURLFetcher* alternate_nav_url_fetcher) { DCHECK(!alternate_nav_url_fetcher_.get()); @@ -423,17 +416,10 @@ void NavigationController::DiscardPendingEntry() { DCHECK(from_contents != active_contents_); ScheduleTabContentsCollection(from_contents->type()); } - - // Note: this may be redundant in some cases. we may want to optimize away - // the redundant notifications. - NotifyNavigationStateChanged(); } void NavigationController::InsertEntry(NavigationEntry* entry) { NavigationControllerBase::InsertEntry(entry); - NotificationService::current()->Notify(NOTIFY_NAV_INDEX_CHANGED, - Source<NavigationController>(this), - NotificationService::NoDetails()); active_contents_->NotifyDidNavigate(NAVIGATION_NEW, 0); } @@ -473,19 +459,16 @@ void NavigationController::NavigateToPendingEntry(bool reload) { from_contents->delegate()->ReplaceContents(from_contents, contents); } - if (contents->Navigate(*pending_entry_, reload)) { - // Note: this is redundant if navigation completed synchronously because - // DidNavigateToEntry call this as well. - NotifyNavigationStateChanged(); - } else { + if (!contents->Navigate(*pending_entry_, reload)) DiscardPendingEntry(); - } } -void NavigationController::NotifyNavigationStateChanged() { +void NavigationController::NotifyNavigationEntryCommitted() { // Reset the Alternate Nav URL Fetcher if we're loading some page it doesn't // care about. We must do this before calling Notify() below as that may // result in the creation of a new fetcher. + // + // TODO(brettw) bug 1324500: this logic should be moved out of the controller! const NavigationEntry* const entry = GetActiveEntry(); if (!entry || (entry->unique_id() != alternate_nav_url_fetcher_entry_unique_id_)) { @@ -500,7 +483,7 @@ void NavigationController::NotifyNavigationStateChanged() { active_contents_->NotifyNavigationStateChanged( TabContents::INVALIDATE_EVERYTHING); - NotificationService::current()->Notify(NOTIFY_NAV_STATE_CHANGED, + NotificationService::current()->Notify(NOTIFY_NAV_ENTRY_COMMITTED, Source<NavigationController>(this), NotificationService::NoDetails()); } @@ -520,12 +503,6 @@ void NavigationController::IndexOfActiveEntryChanged( nav_type = NAVIGATION_REPLACE; } active_contents_->NotifyDidNavigate(nav_type, relative_navigation_offset); - if (GetCurrentEntryIndex() != -1) { - NotificationService::current()->Notify( - NOTIFY_NAV_INDEX_CHANGED, - Source<NavigationController>(this), - NotificationService::NoDetails()); - } } TabContents* NavigationController::GetTabContentsCreateIfNecessary( diff --git a/chrome/browser/navigation_controller.h b/chrome/browser/navigation_controller.h index 136540e..4378b04 100644 --- a/chrome/browser/navigation_controller.h +++ b/chrome/browser/navigation_controller.h @@ -133,9 +133,6 @@ class NavigationController : public NavigationControllerBase { const std::wstring& GetLazyTitle() const; const SkBitmap& GetLazyFavIcon() const; - // Called when |entry| has been updated outside its NavigationController. - void EntryUpdated(NavigationEntry* entry); - void SetAlternateNavURLFetcher( AlternateNavURLFetcher* alternate_nav_url_fetcher); @@ -200,7 +197,7 @@ class NavigationController : public NavigationControllerBase { virtual int GetMaxPageID() const; virtual void NavigateToPendingEntry(bool reload); - virtual void NotifyNavigationStateChanged(); + virtual void NotifyNavigationEntryCommitted(); // Lets the history database know navigation entries have been removed. virtual void NotifyPrunedEntries(); diff --git a/chrome/browser/navigation_controller_base.cc b/chrome/browser/navigation_controller_base.cc index f2b921d..e086e82 100644 --- a/chrome/browser/navigation_controller_base.cc +++ b/chrome/browser/navigation_controller_base.cc @@ -33,6 +33,8 @@ #include "base/logging.h" #include "chrome/browser/navigation_entry.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/notification_types.h" #include "webkit/glue/webkit_glue.h" // The maximum number of entries that a navigation controller can store. @@ -209,6 +211,12 @@ void NavigationControllerBase::LoadEntry(NavigationEntry* entry) { // TODO(pkasting): http://b/1113085 Should this use DiscardPendingEntry()? DiscardPendingEntryInternal(); pending_entry_ = entry; + // TODO(brettw) the reinterpret cast can be removed once we combine the + // NavigationController and the NavigationControllerBase. + NotificationService::current()->Notify( + NOTIFY_NAV_ENTRY_PENDING, + Source<NavigationController>(reinterpret_cast<NavigationController*>(this)), + NotificationService::NoDetails()); NavigateToPendingEntry(false); } @@ -241,6 +249,7 @@ void NavigationControllerBase::DidNavigateToEntry(NavigationEntry* entry) { // active WebContents, because we have just navigated to it. if (entry->GetPageID() > GetMaxPageID()) { InsertEntry(entry); + NotifyNavigationEntryCommitted(); return; } @@ -298,7 +307,7 @@ void NavigationControllerBase::DidNavigateToEntry(NavigationEntry* entry) { delete entry; - NotifyNavigationStateChanged(); + NotifyNavigationEntryCommitted(); } void NavigationControllerBase::DiscardPendingEntry() { @@ -337,12 +346,15 @@ void NavigationControllerBase::InsertEntry(NavigationEntry* entry) { // Prune any entries which are in front of the current entry. if (current_size > 0) { + bool pruned = false; while (last_committed_entry_index_ < (current_size - 1)) { + pruned = true; delete entries_[current_size - 1]; entries_.pop_back(); current_size--; } - NotifyPrunedEntries(); + if (pruned) // Only notify if we did prune something. + NotifyPrunedEntries(); } if (entries_.size() >= max_entry_count_) @@ -350,8 +362,6 @@ void NavigationControllerBase::InsertEntry(NavigationEntry* entry) { entries_.push_back(entry); last_committed_entry_index_ = static_cast<int>(entries_.size()) - 1; - - NotifyNavigationStateChanged(); } void NavigationControllerBase::RemoveLastEntry() { @@ -370,10 +380,11 @@ void NavigationControllerBase::RemoveLastEntry() { NotifyPrunedEntries(); } - NotifyNavigationStateChanged(); } void NavigationControllerBase::RemoveEntryAtIndex(int index) { + // TODO(brettw) this is only called to remove the first one when we've got + // too many entries. It should probably be more specific for this case. if (index >= static_cast<int>(entries_.size()) || index == pending_entry_index_ || index == last_committed_entry_index_) { NOTREACHED(); @@ -390,8 +401,8 @@ void NavigationControllerBase::RemoveEntryAtIndex(int index) { last_committed_entry_index_ = -1; } - NotifyPrunedEntries(); - NotifyNavigationStateChanged(); + // TODO(brettw) bug 1324021: we probably need some notification here so the + // session service can stay in sync. } void NavigationControllerBase::ResetInternal() { diff --git a/chrome/browser/navigation_controller_base.h b/chrome/browser/navigation_controller_base.h index e712ff3..0faf365 100644 --- a/chrome/browser/navigation_controller_base.h +++ b/chrome/browser/navigation_controller_base.h @@ -175,7 +175,7 @@ class NavigationControllerBase { // Allows the derived class to issue notifications that a load has been // committed. - virtual void NotifyNavigationStateChanged() {} + virtual void NotifyNavigationEntryCommitted() {} // Invoked when entries have been pruned, or removed. For example, if the // current entries are [google, digg, yahoo], with the current entry google, diff --git a/chrome/browser/navigation_controller_unittest.cc b/chrome/browser/navigation_controller_unittest.cc index 9176df6..d815a54 100644 --- a/chrome/browser/navigation_controller_unittest.cc +++ b/chrome/browser/navigation_controller_unittest.cc @@ -39,7 +39,9 @@ #include "chrome/browser/tab_contents.h" #include "chrome/browser/tab_contents_delegate.h" #include "chrome/browser/tab_contents_factory.h" +#include "chrome/common/notification_types.h" #include "chrome/common/stl_util-inl.h" +#include "chrome/test/test_notification_tracker.h" #include "chrome/test/testing_profile.h" #include "net/base/net_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -290,6 +292,16 @@ class NavigationControllerHistoryTest : public NavigationControllerTest { std::wstring profile_path_; }; +void RegisterForAllNavNotifications(TestNotificationTracker* tracker, + NavigationController* controller) { + tracker->ListenFor(NOTIFY_NAV_ENTRY_COMMITTED, + Source<NavigationController>(controller)); + tracker->ListenFor(NOTIFY_NAV_LIST_PRUNED, + Source<NavigationController>(controller)); + tracker->ListenFor(NOTIFY_NAV_ENTRY_CHANGED, + Source<NavigationController>(controller)); +} + } // namespace TEST_F(NavigationControllerTest, Defaults) { @@ -306,12 +318,18 @@ TEST_F(NavigationControllerTest, Defaults) { } TEST_F(NavigationControllerTest, LoadURL) { + TestNotificationTracker notifications; + RegisterForAllNavNotifications(¬ifications, contents->controller()); + const GURL url1("test1:foo1"); const GURL url2("test1:foo2"); contents->controller()->LoadURL(url1, PageTransition::TYPED); + // Creating a pending notification should not have issued any of the + // notifications we're listening for. + EXPECT_EQ(0, notifications.size()); - // the load should now be pending + // The load should now be pending. EXPECT_TRUE(contents->pending_entry()); EXPECT_EQ(contents->controller()->GetEntryCount(), 0); EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), -1); @@ -322,9 +340,14 @@ TEST_F(NavigationControllerTest, LoadURL) { EXPECT_FALSE(contents->controller()->CanGoForward()); EXPECT_EQ(contents->GetMaxPageID(), -1); + // We should have gotten no notifications from the preceeding checks. + EXPECT_EQ(0, notifications.size()); + contents->CompleteNavigation(0); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); - // the load should now be committed + // The load should now be committed. EXPECT_EQ(contents->controller()->GetEntryCount(), 1); EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0); EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1); @@ -334,10 +357,10 @@ TEST_F(NavigationControllerTest, LoadURL) { EXPECT_FALSE(contents->controller()->CanGoForward()); EXPECT_EQ(contents->GetMaxPageID(), 0); - // load another... + // Load another... contents->controller()->LoadURL(url2, PageTransition::TYPED); - // the load should now be pending + // The load should now be pending. EXPECT_TRUE(contents->pending_entry()); EXPECT_EQ(contents->controller()->GetEntryCount(), 1); EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0); @@ -350,8 +373,10 @@ TEST_F(NavigationControllerTest, LoadURL) { EXPECT_EQ(contents->GetMaxPageID(), 0); contents->CompleteNavigation(1); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); - // the load should now be committed + // The load should now be committed. EXPECT_EQ(contents->controller()->GetEntryCount(), 2); EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 1); EXPECT_EQ(contents->controller()->GetPendingEntryIndex(), -1); @@ -365,13 +390,23 @@ TEST_F(NavigationControllerTest, LoadURL) { // Tests what happens when the same page is loaded again. Should not create a // new session history entry. TEST_F(NavigationControllerTest, LoadURL_SamePage) { + TestNotificationTracker notifications; + RegisterForAllNavNotifications(¬ifications, contents->controller()); + const GURL url1("test1:foo1"); contents->controller()->LoadURL(url1, PageTransition::TYPED); + EXPECT_EQ(0, notifications.size()); contents->CompleteNavigation(0); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); + contents->controller()->LoadURL(url1, PageTransition::TYPED); + EXPECT_EQ(0, notifications.size()); contents->CompleteNavigation(0); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); // should not have produced a new session history entry EXPECT_EQ(contents->controller()->GetEntryCount(), 1); @@ -384,14 +419,21 @@ TEST_F(NavigationControllerTest, LoadURL_SamePage) { } TEST_F(NavigationControllerTest, LoadURL_Discarded) { + TestNotificationTracker notifications; + RegisterForAllNavNotifications(¬ifications, contents->controller()); + const GURL url1("test1:foo1"); const GURL url2("test1:foo2"); contents->controller()->LoadURL(url1, PageTransition::TYPED); + EXPECT_EQ(0, notifications.size()); contents->CompleteNavigation(0); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); contents->controller()->LoadURL(url2, PageTransition::TYPED); contents->controller()->DiscardPendingEntry(); + EXPECT_EQ(0, notifications.size()); // should not have produced a new session history entry EXPECT_EQ(contents->controller()->GetEntryCount(), 1); @@ -404,12 +446,19 @@ TEST_F(NavigationControllerTest, LoadURL_Discarded) { } TEST_F(NavigationControllerTest, Reload) { + TestNotificationTracker notifications; + RegisterForAllNavNotifications(¬ifications, contents->controller()); + const GURL url1("test1:foo1"); contents->controller()->LoadURL(url1, PageTransition::TYPED); + EXPECT_EQ(0, notifications.size()); contents->CompleteNavigation(0); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); contents->controller()->Reload(); + EXPECT_EQ(0, notifications.size()); // the reload is pending... EXPECT_EQ(contents->controller()->GetEntryCount(), 1); @@ -421,6 +470,8 @@ TEST_F(NavigationControllerTest, Reload) { EXPECT_FALSE(contents->controller()->CanGoForward()); contents->CompleteNavigation(0); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); // now the reload is committed... EXPECT_EQ(contents->controller()->GetEntryCount(), 1); @@ -434,17 +485,25 @@ TEST_F(NavigationControllerTest, Reload) { // Tests what happens when a reload navigation produces a new page. TEST_F(NavigationControllerTest, Reload_GeneratesNewPage) { + TestNotificationTracker notifications; + RegisterForAllNavNotifications(¬ifications, contents->controller()); + const GURL url1("test1:foo1"); const GURL url2("test1:foo2"); contents->controller()->LoadURL(url1, PageTransition::TYPED); contents->CompleteNavigation(0); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); contents->controller()->Reload(); + EXPECT_EQ(0, notifications.size()); contents->pending_entry()->SetURL(url2); contents->pending_entry()->SetTransitionType(PageTransition::LINK); contents->CompleteNavigation(1); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); // now the reload is committed... EXPECT_EQ(contents->controller()->GetEntryCount(), 2); @@ -458,16 +517,24 @@ TEST_F(NavigationControllerTest, Reload_GeneratesNewPage) { // Tests what happens when we navigate back successfully TEST_F(NavigationControllerTest, Back) { + TestNotificationTracker notifications; + RegisterForAllNavNotifications(¬ifications, contents->controller()); + const GURL url1("test1:foo1"); const GURL url2("test1:foo2"); contents->controller()->LoadURL(url1, PageTransition::TYPED); contents->CompleteNavigation(0); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); contents->controller()->LoadURL(url2, PageTransition::TYPED); contents->CompleteNavigation(1); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); contents->controller()->GoBack(); + EXPECT_EQ(0, notifications.size()); // should now have a pending navigation to go back... EXPECT_EQ(contents->controller()->GetEntryCount(), 2); @@ -479,6 +546,8 @@ TEST_F(NavigationControllerTest, Back) { EXPECT_TRUE(contents->controller()->CanGoForward()); contents->CompleteNavigation(0); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); // the back navigation completed successfully EXPECT_EQ(contents->controller()->GetEntryCount(), 2); @@ -492,17 +561,25 @@ TEST_F(NavigationControllerTest, Back) { // Tests what happens when a back navigation produces a new page. TEST_F(NavigationControllerTest, Back_GeneratesNewPage) { + TestNotificationTracker notifications; + RegisterForAllNavNotifications(¬ifications, contents->controller()); + const GURL url1("test1:foo1"); const GURL url2("test1:foo2"); const GURL url3("test1:foo3"); contents->controller()->LoadURL(url1, PageTransition::TYPED); contents->CompleteNavigation(0); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); contents->controller()->LoadURL(url2, PageTransition::TYPED); contents->CompleteNavigation(1); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); contents->controller()->GoBack(); + EXPECT_EQ(0, notifications.size()); // should now have a pending navigation to go back... EXPECT_EQ(contents->controller()->GetEntryCount(), 2); @@ -516,6 +593,8 @@ TEST_F(NavigationControllerTest, Back_GeneratesNewPage) { contents->pending_entry()->SetURL(url3); contents->pending_entry()->SetTransitionType(PageTransition::LINK); contents->CompleteNavigation(2); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); // the back navigation resulted in a completely new navigation. // TODO(darin): perhaps this behavior will be confusing to users? @@ -530,17 +609,26 @@ TEST_F(NavigationControllerTest, Back_GeneratesNewPage) { // Tests what happens when we navigate forward successfully TEST_F(NavigationControllerTest, Forward) { + TestNotificationTracker notifications; + RegisterForAllNavNotifications(¬ifications, contents->controller()); + const GURL url1("test1:foo1"); const GURL url2("test1:foo2"); contents->controller()->LoadURL(url1, PageTransition::TYPED); contents->CompleteNavigation(0); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); contents->controller()->LoadURL(url2, PageTransition::TYPED); contents->CompleteNavigation(1); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); contents->controller()->GoBack(); contents->CompleteNavigation(0); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); contents->controller()->GoForward(); @@ -554,6 +642,8 @@ TEST_F(NavigationControllerTest, Forward) { EXPECT_FALSE(contents->controller()->CanGoForward()); contents->CompleteNavigation(1); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); // the forward navigation completed successfully EXPECT_EQ(contents->controller()->GetEntryCount(), 2); @@ -567,20 +657,30 @@ TEST_F(NavigationControllerTest, Forward) { // Tests what happens when a forward navigation produces a new page. TEST_F(NavigationControllerTest, Forward_GeneratesNewPage) { + TestNotificationTracker notifications; + RegisterForAllNavNotifications(¬ifications, contents->controller()); + const GURL url1("test1:foo1"); const GURL url2("test1:foo2"); const GURL url3("test1:foo3"); contents->controller()->LoadURL(url1, PageTransition::TYPED); contents->CompleteNavigation(0); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); contents->controller()->LoadURL(url2, PageTransition::TYPED); contents->CompleteNavigation(1); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); contents->controller()->GoBack(); contents->CompleteNavigation(0); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); contents->controller()->GoForward(); + EXPECT_EQ(0, notifications.size()); // should now have a pending navigation to go forward... EXPECT_EQ(contents->controller()->GetEntryCount(), 2); @@ -594,6 +694,9 @@ TEST_F(NavigationControllerTest, Forward_GeneratesNewPage) { contents->pending_entry()->SetURL(url3); contents->pending_entry()->SetTransitionType(PageTransition::LINK); contents->CompleteNavigation(2); + EXPECT_TRUE(notifications.Check3AndReset(NOTIFY_NAV_LIST_PRUNED, + NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); EXPECT_EQ(contents->controller()->GetEntryCount(), 2); EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 1); @@ -605,17 +708,24 @@ TEST_F(NavigationControllerTest, Forward_GeneratesNewPage) { } TEST_F(NavigationControllerTest, LinkClick) { + TestNotificationTracker notifications; + RegisterForAllNavNotifications(¬ifications, contents->controller()); + const GURL url1("test1:foo1"); const GURL url2("test1:foo2"); contents->controller()->LoadURL(url1, PageTransition::TYPED); contents->CompleteNavigation(0); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); contents->set_pending_entry(new NavigationEntry(kTestContentsType1, NULL, 0, url2, std::wstring(), PageTransition::LINK)); contents->CompleteNavigation(1); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); // should not have produced a new session history entry EXPECT_EQ(contents->controller()->GetEntryCount(), 2); @@ -628,11 +738,16 @@ TEST_F(NavigationControllerTest, LinkClick) { } TEST_F(NavigationControllerTest, SwitchTypes) { + TestNotificationTracker notifications; + RegisterForAllNavNotifications(¬ifications, contents->controller()); + const GURL url1("test1:foo"); const GURL url2("test2:foo"); contents->controller()->LoadURL(url1, PageTransition::TYPED); contents->CompleteNavigation(0); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); TestContents* initial_contents = contents; @@ -642,6 +757,8 @@ TEST_F(NavigationControllerTest, SwitchTypes) { ASSERT_TRUE(initial_contents != contents); contents->CompleteNavigation(0); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); // A second navigation entry should have been committed even though the // PageIDs are the same. PageIDs are scoped to the tab contents type. @@ -657,6 +774,8 @@ TEST_F(NavigationControllerTest, SwitchTypes) { contents->controller()->GoBack(); ASSERT_TRUE(initial_contents == contents); // switched again! contents->CompleteNavigation(0); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); EXPECT_EQ(contents->controller()->GetEntryCount(), 2); EXPECT_EQ(contents->controller()->GetLastCommittedEntryIndex(), 0); @@ -673,20 +792,27 @@ TEST_F(NavigationControllerTest, SwitchTypes) { // Tests what happens when we begin to navigate to a new contents type, but // then that navigation gets discarded instead. TEST_F(NavigationControllerTest, SwitchTypes_Discard) { + TestNotificationTracker notifications; + RegisterForAllNavNotifications(¬ifications, contents->controller()); + const GURL url1("test1:foo"); const GURL url2("test2:foo"); contents->controller()->LoadURL(url1, PageTransition::TYPED); contents->CompleteNavigation(0); + EXPECT_TRUE(notifications.Check2AndReset(NOTIFY_NAV_ENTRY_COMMITTED, + NOTIFY_NAV_ENTRY_CHANGED)); TestContents* initial_contents = contents; contents->controller()->LoadURL(url2, PageTransition::TYPED); + EXPECT_EQ(0, notifications.size()); // The tab contents should have been replaced ASSERT_TRUE(initial_contents != contents); contents->controller()->DiscardPendingEntry(); + EXPECT_EQ(0, notifications.size()); // The tab contents should have been replaced back ASSERT_TRUE(initial_contents == contents); diff --git a/chrome/browser/session_service.cc b/chrome/browser/session_service.cc index 9ed3d9f..da72060 100644 --- a/chrome/browser/session_service.cc +++ b/chrome/browser/session_service.cc @@ -160,7 +160,7 @@ SessionService::~SessionService() { NotificationService::current()->RemoveObserver( this, NOTIFY_NAV_ENTRY_CHANGED, NotificationService::AllSources()); NotificationService::current()->RemoveObserver( - this, NOTIFY_NAV_INDEX_CHANGED, NotificationService::AllSources()); + this, NOTIFY_NAV_ENTRY_COMMITTED, NotificationService::AllSources()); } void SessionService::ResetFromCurrentBrowsers() { @@ -417,7 +417,7 @@ void SessionService::Init(const std::wstring& path) { NotificationService::current()->AddObserver( this, NOTIFY_NAV_ENTRY_CHANGED, NotificationService::AllSources()); NotificationService::current()->AddObserver( - this, NOTIFY_NAV_INDEX_CHANGED, NotificationService::AllSources()); + this, NOTIFY_NAV_ENTRY_COMMITTED, NotificationService::AllSources()); DCHECK(!path.empty()); commands_since_reset_ = 0; @@ -450,7 +450,7 @@ void SessionService::Observe(NotificationType type, changed->index, *changed->changed_entry); break; } - case NOTIFY_NAV_INDEX_CHANGED: + case NOTIFY_NAV_ENTRY_COMMITTED: SetSelectedNavigationIndex(controller->window_id(), controller->session_id(), controller->GetCurrentEntryIndex()); diff --git a/chrome/browser/ssl_manager.cc b/chrome/browser/ssl_manager.cc index be58f24..8454c09 100644 --- a/chrome/browser/ssl_manager.cc +++ b/chrome/browser/ssl_manager.cc @@ -247,10 +247,8 @@ void SSLManager::SetMaxSecurityStyle(SecurityStyle style) { return; } - if (entry->ssl().security_style() > style) { + if (entry->ssl().security_style() > style) entry->ssl().set_security_style(style); - controller_->EntryUpdated(entry); - } } // Delegate API method. @@ -652,10 +650,10 @@ void SSLManager::DidCommitProvisionalLoad(ProvisionalLoadDetails* details) { // We may not have an entry if this is a navigation to an initial blank // page. Reset the SSL information and add the new data we have. entry->ssl() = NavigationEntry::SSLStatus(); + InitializeEntryIfNeeded(entry); // For security_style. entry->ssl().set_cert_id(details->ssl_cert_id()); entry->ssl().set_cert_status(details->ssl_cert_status()); entry->ssl().set_security_bits(details->ssl_security_bits()); - controller_->EntryUpdated(entry); } if (details->interstitial_page()) { diff --git a/chrome/browser/ssl_policy.cc b/chrome/browser/ssl_policy.cc index dd83357..03e16cc 100644 --- a/chrome/browser/ssl_policy.cc +++ b/chrome/browser/ssl_policy.cc @@ -346,7 +346,6 @@ class DefaultPolicy : public SSLPolicy { NavigationEntry* entry = navigation_controller->GetActiveEntry(); entry->ssl().set_has_mixed_content(); - navigation_controller->EntryUpdated(entry); } void OnDenyCertificate(SSLManager::CertError* error) { diff --git a/chrome/browser/views/location_bar_view.cc b/chrome/browser/views/location_bar_view.cc index f354ef4..edf43bc 100644 --- a/chrome/browser/views/location_bar_view.cc +++ b/chrome/browser/views/location_bar_view.cc @@ -362,9 +362,9 @@ void LocationBarView::OnAutocompleteAccept( scoped_ptr<AlternateNavURLFetcher> fetcher( new AlternateNavURLFetcher(alternate_nav_url)); - // The AlternateNavURLFetcher will listen for the next navigation state - // update notification (expecting it to be a new page load) and hook - // itself in to that loading process. + // The AlternateNavURLFetcher will listen for the pending navigation + // notification that will be issued as a result of the "open URL." It + // will automatically install itself into that navigation controller. controller_->ExecuteCommand(IDC_OPENURL); if (fetcher->state() == AlternateNavURLFetcher::NOT_STARTED) { // I'm not sure this should be reachable, but I'm not also sure enough diff --git a/chrome/common/notification_details.h b/chrome/common/notification_details.h index 9c7fdff..31378c4 100644 --- a/chrome/common/notification_details.h +++ b/chrome/common/notification_details.h @@ -41,6 +41,7 @@ class NotificationDetails { public: NotificationDetails() : ptr_(NULL) {} + NotificationDetails(const NotificationDetails& other) : ptr_(other.ptr_) {} ~NotificationDetails() {} // NotificationDetails can be used as the index for a map; this method @@ -58,12 +59,8 @@ class NotificationDetails { protected: NotificationDetails(void* ptr) : ptr_(ptr) {} - NotificationDetails(const NotificationDetails& other) : ptr_(other.ptr_) {} void* ptr_; - -private: - void operator=(const NotificationDetails&); }; template <class T> diff --git a/chrome/common/notification_source.h b/chrome/common/notification_source.h index 31077e9..049a12d 100644 --- a/chrome/common/notification_source.h +++ b/chrome/common/notification_source.h @@ -40,6 +40,7 @@ // NotificationService::AllSources(). class NotificationSource { public: + NotificationSource(const NotificationSource& other) : ptr_(other.ptr_) { } ~NotificationSource() {} // NotificationSource can be used as the index for a map; this method @@ -56,12 +57,8 @@ class NotificationSource { protected: NotificationSource(void* ptr) : ptr_(ptr) {} - NotificationSource(const NotificationSource& other) : ptr_(other.ptr_) { } void* ptr_; - - private: - void operator=(const NotificationSource&); }; template <class T> diff --git a/chrome/common/notification_types.h b/chrome/common/notification_types.h index 1080ffa..d2392b7 100644 --- a/chrome/common/notification_types.h +++ b/chrome/common/notification_types.h @@ -55,18 +55,35 @@ enum NotificationType { // NavigationController ------------------------------------------------------ - // A NavigationController's state has changed (a new pending load has been - // added, a load has committed, etc.). + // A new pending navigation has been created. Pending entries are created when + // the user requests the navigation. We don't know if it will actually happen + // until it does (at this point, it will be "committed." Note that renderer- + // initiated navigations such as link clicks will never be pending. // - // TODO(brettw) this is vague and I'm not sure that it covers every case. We - // need to figure out the exact cases where this notificaion should be sent - // and make sure it is sent in those cases. - NOTIFY_NAV_STATE_CHANGED, + // This notification is called after the pending entry is created, but before + // we actually try to navigate. The source will be the NavigationController + // that owns the pending entry, and there are no details. + NOTIFY_NAV_ENTRY_PENDING, + + // A new non-pending navigation entry has been created. This will correspond + // to one NavigationController entry being created (in the case of new + // navigations) or renavigated to (for back/forward navigations). + NOTIFY_NAV_ENTRY_COMMITTED, // Indicates that the NavigationController given in the Source has decreased // its back/forward list count. This is usually the result of going back and // then doing a new navigation, meaning all the "forward" items are deleted. - // There are no details. + // + // This normally happens as a result of a new navigation. It will be followed + // by a NOTIFY_NAV_ENTRY_COMMITTED message for the new page that caused the + // pruning. It could also be a result of removing an item from the list to fix + // up after interstitials. + // + // The details are an integer indicating the number of items pruned. + // Watch out: the NavigationController may start throwing entries away once + // the list is a certain size, so you can't use the current size of the + // navigation list to tell how many items were pruned, you have to use the + // details provided here. NOTIFY_NAV_LIST_PRUNED, // Indicates that a NavigationEntry has changed. The source will be the @@ -74,11 +91,6 @@ enum NotificationType { // a NavigationController::EntryChangedDetails struct. NOTIFY_NAV_ENTRY_CHANGED, - // Indicates that the index of the currently active NavigationEntry has - // changed. The source will be the NavigationController whose current item - // changed, and there are no details. - NOTIFY_NAV_INDEX_CHANGED, - // Other load-related (not from NavigationController) ------------------------ // A content load is starting. The source will be a diff --git a/chrome/test/test_notification_tracker.cc b/chrome/test/test_notification_tracker.cc new file mode 100644 index 0000000..e17de73 --- /dev/null +++ b/chrome/test/test_notification_tracker.cc @@ -0,0 +1,105 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/test/test_notification_tracker.h" +#include "chrome/common/notification_types.h" + +TestNotificationTracker::Event::Event() + : type(NOTIFY_ALL), + source(NotificationService::AllSources()), + details(NotificationService::NoDetails()) { +} +TestNotificationTracker::Event::Event(NotificationType t, + NotificationSource s, + NotificationDetails d) + : type(t), + source(s), + details(d) { +} + +TestNotificationTracker::TestNotificationTracker() { +} + +TestNotificationTracker::~TestNotificationTracker() { + NotificationService* service = NotificationService::current(); + for (size_t i = 0; i < listening_.size(); i++) + service->RemoveObserver(this, listening_[i].first, listening_[i].second); + listening_.clear(); +} + +void TestNotificationTracker::ListenFor(NotificationType type, + const NotificationSource& source) { + listening_.push_back(std::make_pair(type, source)); + NotificationService::current()->AddObserver(this, type, source); +} + +void TestNotificationTracker::Reset() { + events_.clear(); +} + +bool TestNotificationTracker::Check1AndReset(NotificationType type) { + if (size() != 1) { + Reset(); + return false; + } + bool success = events_[0].type == type; + Reset(); + return success; +} + +bool TestNotificationTracker::Check2AndReset(NotificationType type1, + NotificationType type2) { + if (size() != 2) { + Reset(); + return false; + } + bool success = events_[0].type == type1 && events_[1].type == type2; + Reset(); + return success; +} + +bool TestNotificationTracker::Check3AndReset(NotificationType type1, + NotificationType type2, + NotificationType type3) { + if (size() != 3) { + Reset(); + return false; + } + bool success = events_[0].type == type1 && + events_[1].type == type2 && + events_[2].type == type3; + Reset(); + return success; +} + +void TestNotificationTracker::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + events_.push_back(Event(type, source, details)); +} diff --git a/chrome/test/test_notification_tracker.h b/chrome/test/test_notification_tracker.h new file mode 100644 index 0000000..ca22f6b --- /dev/null +++ b/chrome/test/test_notification_tracker.h @@ -0,0 +1,105 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CHROME_TEST_NOTIFICATION_TRACKER_H_ +#define CHROME_TEST_NOTIFICATION_TRACKER_H_ + +#include <vector> + +#include "chrome/common/notification_service.h" + +// Provides an easy way for tests to verify that a given set of notifications +// was received during test execution. +class TestNotificationTracker : public NotificationObserver { + public: + // Records one received notification. + struct Event { + Event(); + Event(NotificationType t, NotificationSource s, NotificationDetails d); + + NotificationType type; + NotificationSource source; + NotificationDetails details; + }; + + // By default, it won't listen for any notifications. You'll need to call + // ListenFor for the notifications you are interested in. + TestNotificationTracker(); + + ~TestNotificationTracker(); + + // Makes this object listen for the given notification with the given source. + void ListenFor(NotificationType type, const NotificationSource& source); + + // Makes this object listen for notifications of the given type coming from + // any source. + void ListenForAll(NotificationType type); + + // Clears the list of events. + void Reset(); + + // Given notifications type(sp, returns true if the list of notifications + // were exactly those listed in the given arg(s), and in the same order. + // + // This will also reset the list so that the next call will only check for + // new notifications. Example: + // <do stuff> + // Check1AndReset(NOTIFY_A); + // <do stuff> + // Check2AndReset(NOTIFY_B, NOTIFY_C) + bool Check1AndReset(NotificationType type); + bool Check2AndReset(NotificationType type1, + NotificationType type2); + bool Check3AndReset(NotificationType type1, + NotificationType type2, + NotificationType type3); + + // Returns the number of notifications received since the last reset. + size_t size() const { return events_.size(); } + + // Returns the information about the event at the given index. The index must + // be in [0, size). + const Event& at(size_t i) const { return events_[i]; } + + private: + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + // Lists all type/source combinations that we're listening for. These will + // need to be unregistered when we are destroyed. + std::vector< std::pair<NotificationType, NotificationSource> > listening_; + + // Lists all received since last cleared, in the order they were received. + std::vector<Event> events_; + + DISALLOW_COPY_AND_ASSIGN(TestNotificationTracker); +}; + +#endif // CHROME_TEST_NOTIFICATION_TRACKER_H_ diff --git a/chrome/test/unit/unittests.vcproj b/chrome/test/unit/unittests.vcproj index 9aa1c90..ee496de 100644 --- a/chrome/test/unit/unittests.vcproj +++ b/chrome/test/unit/unittests.vcproj @@ -182,6 +182,14 @@ > </File> <File + RelativePath="..\test_notification_tracker.cc" + > + </File> + <File + RelativePath="..\test_notification_tracker.h" + > + </File> + <File RelativePath="..\testing_browser_process.h" > </File> @@ -194,19 +202,19 @@ > </File> <File - RelativePath="..\ui\view_event_test_base.cc" + RelativePath="..\..\..\net\url_request\url_request_test_job.cc" > </File> <File - RelativePath="..\ui\view_event_test_base.h" + RelativePath="..\..\..\net\url_request\url_request_test_job.h" > </File> <File - RelativePath="..\..\..\net\url_request\url_request_test_job.cc" + RelativePath="..\ui\view_event_test_base.cc" > </File> <File - RelativePath="..\..\..\net\url_request\url_request_test_job.h" + RelativePath="..\ui\view_event_test_base.h" > </File> </Filter> |