| // Copyright (c) 2012 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/ui/toolbar/back_forward_menu_model.h" |
| |
| #include "base/path_service.h" |
| #include "base/strings/string16.h" |
| #include "base/strings/string_util.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/time/time.h" |
| #include "chrome/browser/favicon/favicon_service_factory.h" |
| #include "chrome/browser/history/history_service.h" |
| #include "chrome/browser/history/history_service_factory.h" |
| #include "chrome/browser/profiles/profile_manager.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/browser_tabstrip.h" |
| #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| #include "chrome/common/url_constants.h" |
| #include "chrome/test/base/chrome_render_view_host_test_harness.h" |
| #include "chrome/test/base/test_browser_window.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "content/public/browser/navigation_controller.h" |
| #include "content/public/browser/navigation_entry.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/test/web_contents_tester.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/skia/include/core/SkBitmap.h" |
| #include "ui/gfx/codec/png_codec.h" |
| |
| using content::WebContentsTester; |
| |
| namespace { |
| |
| // Creates a bitmap of the specified color. |
| SkBitmap CreateBitmap(SkColor color) { |
| SkBitmap bitmap; |
| bitmap.setConfig(SkBitmap::kARGB_8888_Config, 16, 16); |
| bitmap.allocPixels(); |
| bitmap.eraseColor(color); |
| return bitmap; |
| } |
| |
| class FaviconDelegate : public ui::MenuModelDelegate { |
| public: |
| FaviconDelegate() : was_called_(false) {} |
| |
| virtual void OnIconChanged(int model_index) OVERRIDE { |
| was_called_ = true; |
| base::MessageLoop::current()->Quit(); |
| } |
| |
| bool was_called() const { return was_called_; } |
| |
| private: |
| bool was_called_; |
| |
| DISALLOW_COPY_AND_ASSIGN(FaviconDelegate); |
| }; |
| |
| } // namespace |
| |
| class BackFwdMenuModelTest : public ChromeRenderViewHostTestHarness { |
| public: |
| void ValidateModel(BackForwardMenuModel* model, int history_items, |
| int chapter_stops) { |
| int h = std::min(BackForwardMenuModel::kMaxHistoryItems, history_items); |
| int c = std::min(BackForwardMenuModel::kMaxChapterStops, chapter_stops); |
| EXPECT_EQ(h, model->GetHistoryItemCount()); |
| EXPECT_EQ(c, model->GetChapterStopCount(h)); |
| if (h > 0) |
| h += 2; // Separator and View History link. |
| if (c > 0) |
| ++c; |
| EXPECT_EQ(h + c, model->GetItemCount()); |
| } |
| |
| void LoadURLAndUpdateState(const char* url, const char* title) { |
| NavigateAndCommit(GURL(url)); |
| controller().GetLastCommittedEntry()->SetTitle(UTF8ToUTF16(title)); |
| } |
| |
| // Navigate back or forward the given amount and commits the entry (which |
| // will be pending after we ask to navigate there). |
| void NavigateToOffset(int offset) { |
| controller().GoToOffset(offset); |
| WebContentsTester::For(web_contents())->CommitPendingNavigation(); |
| } |
| |
| // Same as NavigateToOffset but goes to an absolute index. |
| void NavigateToIndex(int index) { |
| controller().GoToIndex(index); |
| WebContentsTester::For(web_contents())->CommitPendingNavigation(); |
| } |
| |
| // Goes back/forward and commits the load. |
| void GoBack() { |
| controller().GoBack(); |
| WebContentsTester::For(web_contents())->CommitPendingNavigation(); |
| } |
| void GoForward() { |
| controller().GoForward(); |
| WebContentsTester::For(web_contents())->CommitPendingNavigation(); |
| } |
| }; |
| |
| TEST_F(BackFwdMenuModelTest, BasicCase) { |
| scoped_ptr<BackForwardMenuModel> back_model(new BackForwardMenuModel( |
| NULL, BackForwardMenuModel::BACKWARD_MENU)); |
| back_model->set_test_web_contents(web_contents()); |
| |
| scoped_ptr<BackForwardMenuModel> forward_model(new BackForwardMenuModel( |
| NULL, BackForwardMenuModel::FORWARD_MENU)); |
| forward_model->set_test_web_contents(web_contents()); |
| |
| EXPECT_EQ(0, back_model->GetItemCount()); |
| EXPECT_EQ(0, forward_model->GetItemCount()); |
| EXPECT_FALSE(back_model->ItemHasCommand(1)); |
| |
| // Seed the controller with a few URLs |
| LoadURLAndUpdateState("http://www.a.com/1", "A1"); |
| LoadURLAndUpdateState("http://www.a.com/2", "A2"); |
| LoadURLAndUpdateState("http://www.a.com/3", "A3"); |
| LoadURLAndUpdateState("http://www.b.com/1", "B1"); |
| LoadURLAndUpdateState("http://www.b.com/2", "B2"); |
| LoadURLAndUpdateState("http://www.c.com/1", "C1"); |
| LoadURLAndUpdateState("http://www.c.com/2", "C2"); |
| LoadURLAndUpdateState("http://www.c.com/3", "C3"); |
| |
| // There're two more items here: a separator and a "Show Full History". |
| EXPECT_EQ(9, back_model->GetItemCount()); |
| EXPECT_EQ(0, forward_model->GetItemCount()); |
| EXPECT_EQ(ASCIIToUTF16("C2"), back_model->GetLabelAt(0)); |
| EXPECT_EQ(ASCIIToUTF16("A1"), back_model->GetLabelAt(6)); |
| EXPECT_EQ(back_model->GetShowFullHistoryLabel(), |
| back_model->GetLabelAt(8)); |
| |
| EXPECT_TRUE(back_model->ItemHasCommand(0)); |
| EXPECT_TRUE(back_model->ItemHasCommand(6)); |
| EXPECT_TRUE(back_model->IsSeparator(7)); |
| EXPECT_TRUE(back_model->ItemHasCommand(8)); |
| EXPECT_FALSE(back_model->ItemHasCommand(9)); |
| EXPECT_FALSE(back_model->ItemHasCommand(9)); |
| |
| NavigateToOffset(-7); |
| |
| EXPECT_EQ(0, back_model->GetItemCount()); |
| EXPECT_EQ(9, forward_model->GetItemCount()); |
| EXPECT_EQ(ASCIIToUTF16("A2"), forward_model->GetLabelAt(0)); |
| EXPECT_EQ(ASCIIToUTF16("C3"), forward_model->GetLabelAt(6)); |
| EXPECT_EQ(forward_model->GetShowFullHistoryLabel(), |
| forward_model->GetLabelAt(8)); |
| |
| EXPECT_TRUE(forward_model->ItemHasCommand(0)); |
| EXPECT_TRUE(forward_model->ItemHasCommand(6)); |
| EXPECT_TRUE(forward_model->IsSeparator(7)); |
| EXPECT_TRUE(forward_model->ItemHasCommand(8)); |
| EXPECT_FALSE(forward_model->ItemHasCommand(7)); |
| EXPECT_FALSE(forward_model->ItemHasCommand(9)); |
| |
| NavigateToOffset(4); |
| |
| EXPECT_EQ(6, back_model->GetItemCount()); |
| EXPECT_EQ(5, forward_model->GetItemCount()); |
| EXPECT_EQ(ASCIIToUTF16("B1"), back_model->GetLabelAt(0)); |
| EXPECT_EQ(ASCIIToUTF16("A1"), back_model->GetLabelAt(3)); |
| EXPECT_EQ(back_model->GetShowFullHistoryLabel(), |
| back_model->GetLabelAt(5)); |
| EXPECT_EQ(ASCIIToUTF16("C1"), forward_model->GetLabelAt(0)); |
| EXPECT_EQ(ASCIIToUTF16("C3"), forward_model->GetLabelAt(2)); |
| EXPECT_EQ(forward_model->GetShowFullHistoryLabel(), |
| forward_model->GetLabelAt(4)); |
| } |
| |
| TEST_F(BackFwdMenuModelTest, MaxItemsTest) { |
| scoped_ptr<BackForwardMenuModel> back_model(new BackForwardMenuModel( |
| NULL, BackForwardMenuModel::BACKWARD_MENU)); |
| back_model->set_test_web_contents(web_contents()); |
| |
| scoped_ptr<BackForwardMenuModel> forward_model(new BackForwardMenuModel( |
| NULL, BackForwardMenuModel::FORWARD_MENU)); |
| forward_model->set_test_web_contents(web_contents()); |
| |
| // Seed the controller with 32 URLs |
| LoadURLAndUpdateState("http://www.a.com/1", "A1"); |
| LoadURLAndUpdateState("http://www.a.com/2", "A2"); |
| LoadURLAndUpdateState("http://www.a.com/3", "A3"); |
| LoadURLAndUpdateState("http://www.b.com/1", "B1"); |
| LoadURLAndUpdateState("http://www.b.com/2", "B2"); |
| LoadURLAndUpdateState("http://www.b.com/3", "B3"); |
| LoadURLAndUpdateState("http://www.c.com/1", "C1"); |
| LoadURLAndUpdateState("http://www.c.com/2", "C2"); |
| LoadURLAndUpdateState("http://www.c.com/3", "C3"); |
| LoadURLAndUpdateState("http://www.d.com/1", "D1"); |
| LoadURLAndUpdateState("http://www.d.com/2", "D2"); |
| LoadURLAndUpdateState("http://www.d.com/3", "D3"); |
| LoadURLAndUpdateState("http://www.e.com/1", "E1"); |
| LoadURLAndUpdateState("http://www.e.com/2", "E2"); |
| LoadURLAndUpdateState("http://www.e.com/3", "E3"); |
| LoadURLAndUpdateState("http://www.f.com/1", "F1"); |
| LoadURLAndUpdateState("http://www.f.com/2", "F2"); |
| LoadURLAndUpdateState("http://www.f.com/3", "F3"); |
| LoadURLAndUpdateState("http://www.g.com/1", "G1"); |
| LoadURLAndUpdateState("http://www.g.com/2", "G2"); |
| LoadURLAndUpdateState("http://www.g.com/3", "G3"); |
| LoadURLAndUpdateState("http://www.h.com/1", "H1"); |
| LoadURLAndUpdateState("http://www.h.com/2", "H2"); |
| LoadURLAndUpdateState("http://www.h.com/3", "H3"); |
| LoadURLAndUpdateState("http://www.i.com/1", "I1"); |
| LoadURLAndUpdateState("http://www.i.com/2", "I2"); |
| LoadURLAndUpdateState("http://www.i.com/3", "I3"); |
| LoadURLAndUpdateState("http://www.j.com/1", "J1"); |
| LoadURLAndUpdateState("http://www.j.com/2", "J2"); |
| LoadURLAndUpdateState("http://www.j.com/3", "J3"); |
| LoadURLAndUpdateState("http://www.k.com/1", "K1"); |
| LoadURLAndUpdateState("http://www.k.com/2", "K2"); |
| |
| // Also there're two more for a separator and a "Show Full History". |
| int chapter_stop_offset = 6; |
| EXPECT_EQ(BackForwardMenuModel::kMaxHistoryItems + 2 + chapter_stop_offset, |
| back_model->GetItemCount()); |
| EXPECT_EQ(0, forward_model->GetItemCount()); |
| EXPECT_EQ(ASCIIToUTF16("K1"), back_model->GetLabelAt(0)); |
| EXPECT_EQ(back_model->GetShowFullHistoryLabel(), |
| back_model->GetLabelAt(BackForwardMenuModel::kMaxHistoryItems + 1 + |
| chapter_stop_offset)); |
| |
| // Test for out of bounds (beyond Show Full History). |
| EXPECT_FALSE(back_model->ItemHasCommand( |
| BackForwardMenuModel::kMaxHistoryItems + chapter_stop_offset + 2)); |
| |
| EXPECT_TRUE(back_model->ItemHasCommand( |
| BackForwardMenuModel::kMaxHistoryItems - 1)); |
| EXPECT_TRUE(back_model->IsSeparator( |
| BackForwardMenuModel::kMaxHistoryItems)); |
| |
| NavigateToIndex(0); |
| |
| EXPECT_EQ(BackForwardMenuModel::kMaxHistoryItems + 2 + chapter_stop_offset, |
| forward_model->GetItemCount()); |
| EXPECT_EQ(0, back_model->GetItemCount()); |
| EXPECT_EQ(ASCIIToUTF16("A2"), forward_model->GetLabelAt(0)); |
| EXPECT_EQ(forward_model->GetShowFullHistoryLabel(), |
| forward_model->GetLabelAt(BackForwardMenuModel::kMaxHistoryItems + 1 + |
| chapter_stop_offset)); |
| |
| // Out of bounds |
| EXPECT_FALSE(forward_model->ItemHasCommand( |
| BackForwardMenuModel::kMaxHistoryItems + 2 + chapter_stop_offset)); |
| |
| EXPECT_TRUE(forward_model->ItemHasCommand( |
| BackForwardMenuModel::kMaxHistoryItems - 1)); |
| EXPECT_TRUE(forward_model->IsSeparator( |
| BackForwardMenuModel::kMaxHistoryItems)); |
| } |
| |
| TEST_F(BackFwdMenuModelTest, ChapterStops) { |
| scoped_ptr<BackForwardMenuModel> back_model(new BackForwardMenuModel( |
| NULL, BackForwardMenuModel::BACKWARD_MENU)); |
| back_model->set_test_web_contents(web_contents()); |
| |
| scoped_ptr<BackForwardMenuModel> forward_model(new BackForwardMenuModel( |
| NULL, BackForwardMenuModel::FORWARD_MENU)); |
| forward_model->set_test_web_contents(web_contents()); |
| |
| // Seed the controller with 32 URLs. |
| int i = 0; |
| LoadURLAndUpdateState("http://www.a.com/1", "A1"); |
| ValidateModel(back_model.get(), i++, 0); |
| LoadURLAndUpdateState("http://www.a.com/2", "A2"); |
| ValidateModel(back_model.get(), i++, 0); |
| LoadURLAndUpdateState("http://www.a.com/3", "A3"); |
| ValidateModel(back_model.get(), i++, 0); |
| LoadURLAndUpdateState("http://www.b.com/1", "B1"); |
| ValidateModel(back_model.get(), i++, 0); |
| LoadURLAndUpdateState("http://www.b.com/2", "B2"); |
| ValidateModel(back_model.get(), i++, 0); |
| // i = 5 |
| LoadURLAndUpdateState("http://www.b.com/3", "B3"); |
| ValidateModel(back_model.get(), i++, 0); |
| LoadURLAndUpdateState("http://www.c.com/1", "C1"); |
| ValidateModel(back_model.get(), i++, 0); |
| LoadURLAndUpdateState("http://www.c.com/2", "C2"); |
| ValidateModel(back_model.get(), i++, 0); |
| LoadURLAndUpdateState("http://www.c.com/3", "C3"); |
| ValidateModel(back_model.get(), i++, 0); |
| LoadURLAndUpdateState("http://www.d.com/1", "D1"); |
| ValidateModel(back_model.get(), i++, 0); |
| // i = 10 |
| LoadURLAndUpdateState("http://www.d.com/2", "D2"); |
| ValidateModel(back_model.get(), i++, 0); |
| LoadURLAndUpdateState("http://www.d.com/3", "D3"); |
| ValidateModel(back_model.get(), i++, 0); |
| LoadURLAndUpdateState("http://www.e.com/1", "E1"); |
| ValidateModel(back_model.get(), i++, 0); |
| LoadURLAndUpdateState("http://www.e.com/2", "E2"); |
| ValidateModel(back_model.get(), i++, 0); |
| LoadURLAndUpdateState("http://www.e.com/3", "E3"); |
| ValidateModel(back_model.get(), i++, 0); |
| // i = 15 |
| LoadURLAndUpdateState("http://www.f.com/1", "F1"); |
| ValidateModel(back_model.get(), i++, 1); |
| LoadURLAndUpdateState("http://www.f.com/2", "F2"); |
| ValidateModel(back_model.get(), i++, 1); |
| LoadURLAndUpdateState("http://www.f.com/3", "F3"); |
| ValidateModel(back_model.get(), i++, 1); |
| LoadURLAndUpdateState("http://www.g.com/1", "G1"); |
| ValidateModel(back_model.get(), i++, 2); |
| LoadURLAndUpdateState("http://www.g.com/2", "G2"); |
| ValidateModel(back_model.get(), i++, 2); |
| // i = 20 |
| LoadURLAndUpdateState("http://www.g.com/3", "G3"); |
| ValidateModel(back_model.get(), i++, 2); |
| LoadURLAndUpdateState("http://www.h.com/1", "H1"); |
| ValidateModel(back_model.get(), i++, 3); |
| LoadURLAndUpdateState("http://www.h.com/2", "H2"); |
| ValidateModel(back_model.get(), i++, 3); |
| LoadURLAndUpdateState("http://www.h.com/3", "H3"); |
| ValidateModel(back_model.get(), i++, 3); |
| LoadURLAndUpdateState("http://www.i.com/1", "I1"); |
| ValidateModel(back_model.get(), i++, 4); |
| // i = 25 |
| LoadURLAndUpdateState("http://www.i.com/2", "I2"); |
| ValidateModel(back_model.get(), i++, 4); |
| LoadURLAndUpdateState("http://www.i.com/3", "I3"); |
| ValidateModel(back_model.get(), i++, 4); |
| LoadURLAndUpdateState("http://www.j.com/1", "J1"); |
| ValidateModel(back_model.get(), i++, 5); |
| LoadURLAndUpdateState("http://www.j.com/2", "J2"); |
| ValidateModel(back_model.get(), i++, 5); |
| LoadURLAndUpdateState("http://www.j.com/3", "J3"); |
| ValidateModel(back_model.get(), i++, 5); |
| // i = 30 |
| LoadURLAndUpdateState("http://www.k.com/1", "K1"); |
| ValidateModel(back_model.get(), i++, 6); |
| LoadURLAndUpdateState("http://www.k.com/2", "K2"); |
| ValidateModel(back_model.get(), i++, 6); |
| // i = 32 |
| LoadURLAndUpdateState("http://www.k.com/3", "K3"); |
| ValidateModel(back_model.get(), i++, 6); |
| |
| // A chapter stop is defined as the last page the user |
| // browsed to within the same domain. |
| |
| // Check to see if the chapter stops have the right labels. |
| int index = BackForwardMenuModel::kMaxHistoryItems; |
| // Empty string indicates item is a separator. |
| EXPECT_EQ(base::string16(), back_model->GetLabelAt(index++)); |
| EXPECT_EQ(ASCIIToUTF16("F3"), back_model->GetLabelAt(index++)); |
| EXPECT_EQ(ASCIIToUTF16("E3"), back_model->GetLabelAt(index++)); |
| EXPECT_EQ(ASCIIToUTF16("D3"), back_model->GetLabelAt(index++)); |
| EXPECT_EQ(ASCIIToUTF16("C3"), back_model->GetLabelAt(index++)); |
| // The menu should only show a maximum of 5 chapter stops. |
| EXPECT_EQ(ASCIIToUTF16("B3"), back_model->GetLabelAt(index)); |
| // Empty string indicates item is a separator. |
| EXPECT_EQ(base::string16(), back_model->GetLabelAt(index + 1)); |
| EXPECT_EQ(back_model->GetShowFullHistoryLabel(), |
| back_model->GetLabelAt(index + 2)); |
| |
| // If we go back two we should still see the same chapter stop at the end. |
| GoBack(); |
| EXPECT_EQ(ASCIIToUTF16("B3"), back_model->GetLabelAt(index)); |
| GoBack(); |
| EXPECT_EQ(ASCIIToUTF16("B3"), back_model->GetLabelAt(index)); |
| // But if we go back again, it should change. |
| GoBack(); |
| EXPECT_EQ(ASCIIToUTF16("A3"), back_model->GetLabelAt(index)); |
| GoBack(); |
| EXPECT_EQ(ASCIIToUTF16("A3"), back_model->GetLabelAt(index)); |
| GoBack(); |
| EXPECT_EQ(ASCIIToUTF16("A3"), back_model->GetLabelAt(index)); |
| GoBack(); |
| // It is now a separator. |
| EXPECT_EQ(base::string16(), back_model->GetLabelAt(index)); |
| // Undo our position change. |
| NavigateToOffset(6); |
| |
| // Go back enough to make sure no chapter stops should appear. |
| NavigateToOffset(-BackForwardMenuModel::kMaxHistoryItems); |
| ValidateModel(forward_model.get(), BackForwardMenuModel::kMaxHistoryItems, 0); |
| // Go forward (still no chapter stop) |
| GoForward(); |
| ValidateModel(forward_model.get(), |
| BackForwardMenuModel::kMaxHistoryItems - 1, 0); |
| // Go back two (one chapter stop should show up) |
| GoBack(); |
| GoBack(); |
| ValidateModel(forward_model.get(), |
| BackForwardMenuModel::kMaxHistoryItems, 1); |
| |
| // Go to beginning. |
| NavigateToIndex(0); |
| |
| // Check to see if the chapter stops have the right labels. |
| index = BackForwardMenuModel::kMaxHistoryItems; |
| // Empty string indicates item is a separator. |
| EXPECT_EQ(base::string16(), forward_model->GetLabelAt(index++)); |
| EXPECT_EQ(ASCIIToUTF16("E3"), forward_model->GetLabelAt(index++)); |
| EXPECT_EQ(ASCIIToUTF16("F3"), forward_model->GetLabelAt(index++)); |
| EXPECT_EQ(ASCIIToUTF16("G3"), forward_model->GetLabelAt(index++)); |
| EXPECT_EQ(ASCIIToUTF16("H3"), forward_model->GetLabelAt(index++)); |
| // The menu should only show a maximum of 5 chapter stops. |
| EXPECT_EQ(ASCIIToUTF16("I3"), forward_model->GetLabelAt(index)); |
| // Empty string indicates item is a separator. |
| EXPECT_EQ(base::string16(), forward_model->GetLabelAt(index + 1)); |
| EXPECT_EQ(forward_model->GetShowFullHistoryLabel(), |
| forward_model->GetLabelAt(index + 2)); |
| |
| // If we advance one we should still see the same chapter stop at the end. |
| GoForward(); |
| EXPECT_EQ(ASCIIToUTF16("I3"), forward_model->GetLabelAt(index)); |
| // But if we advance one again, it should change. |
| GoForward(); |
| EXPECT_EQ(ASCIIToUTF16("J3"), forward_model->GetLabelAt(index)); |
| GoForward(); |
| EXPECT_EQ(ASCIIToUTF16("J3"), forward_model->GetLabelAt(index)); |
| GoForward(); |
| EXPECT_EQ(ASCIIToUTF16("J3"), forward_model->GetLabelAt(index)); |
| GoForward(); |
| EXPECT_EQ(ASCIIToUTF16("K3"), forward_model->GetLabelAt(index)); |
| |
| // Now test the boundary cases by using the chapter stop function directly. |
| // Out of bounds, first too far right (incrementing), then too far left. |
| EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(33, false)); |
| EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(-1, true)); |
| // Test being at end and going right, then at beginning going left. |
| EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(32, true)); |
| EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(0, false)); |
| // Test success: beginning going right and end going left. |
| EXPECT_EQ(2, back_model->GetIndexOfNextChapterStop(0, true)); |
| EXPECT_EQ(29, back_model->GetIndexOfNextChapterStop(32, false)); |
| // Now see when the chapter stops begin to show up. |
| EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(1, false)); |
| EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(2, false)); |
| EXPECT_EQ(2, back_model->GetIndexOfNextChapterStop(3, false)); |
| // Now see when the chapter stops end. |
| EXPECT_EQ(32, back_model->GetIndexOfNextChapterStop(30, true)); |
| EXPECT_EQ(32, back_model->GetIndexOfNextChapterStop(31, true)); |
| EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(32, true)); |
| |
| // Bug found during review (two different sites, but first wasn't considered |
| // a chapter-stop). |
| // Go to A1; |
| NavigateToIndex(0); |
| LoadURLAndUpdateState("http://www.b.com/1", "B1"); |
| EXPECT_EQ(0, back_model->GetIndexOfNextChapterStop(1, false)); |
| EXPECT_EQ(1, back_model->GetIndexOfNextChapterStop(0, true)); |
| |
| // Now see if it counts 'www.x.com' and 'mail.x.com' as same domain, which |
| // it should. |
| // Go to A1. |
| NavigateToIndex(0); |
| LoadURLAndUpdateState("http://mail.a.com/2", "A2-mai"); |
| LoadURLAndUpdateState("http://www.b.com/1", "B1"); |
| LoadURLAndUpdateState("http://mail.b.com/2", "B2-mai"); |
| LoadURLAndUpdateState("http://new.site.com", "new"); |
| EXPECT_EQ(1, back_model->GetIndexOfNextChapterStop(0, true)); |
| EXPECT_EQ(3, back_model->GetIndexOfNextChapterStop(1, true)); |
| EXPECT_EQ(3, back_model->GetIndexOfNextChapterStop(2, true)); |
| EXPECT_EQ(4, back_model->GetIndexOfNextChapterStop(3, true)); |
| // And try backwards as well. |
| EXPECT_EQ(3, back_model->GetIndexOfNextChapterStop(4, false)); |
| EXPECT_EQ(1, back_model->GetIndexOfNextChapterStop(3, false)); |
| EXPECT_EQ(1, back_model->GetIndexOfNextChapterStop(2, false)); |
| EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(1, false)); |
| } |
| |
| TEST_F(BackFwdMenuModelTest, EscapeLabel) { |
| scoped_ptr<BackForwardMenuModel> back_model(new BackForwardMenuModel( |
| NULL, BackForwardMenuModel::BACKWARD_MENU)); |
| back_model->set_test_web_contents(web_contents()); |
| |
| EXPECT_EQ(0, back_model->GetItemCount()); |
| EXPECT_FALSE(back_model->ItemHasCommand(1)); |
| |
| LoadURLAndUpdateState("http://www.a.com/1", "A B"); |
| LoadURLAndUpdateState("http://www.a.com/1", "A & B"); |
| LoadURLAndUpdateState("http://www.a.com/2", "A && B"); |
| LoadURLAndUpdateState("http://www.a.com/2", "A &&& B"); |
| LoadURLAndUpdateState("http://www.a.com/3", ""); |
| |
| EXPECT_EQ(6, back_model->GetItemCount()); |
| |
| // On Mac ui::MenuModel::GetLabelAt should return unescaped strings. |
| #if defined(OS_MACOSX) |
| EXPECT_EQ(ASCIIToUTF16("A B"), back_model->GetLabelAt(3)); |
| EXPECT_EQ(ASCIIToUTF16("A & B"), back_model->GetLabelAt(2)); |
| EXPECT_EQ(ASCIIToUTF16("A && B"), back_model->GetLabelAt(1)); |
| EXPECT_EQ(ASCIIToUTF16("A &&& B"), back_model->GetLabelAt(0)); |
| #else |
| EXPECT_EQ(ASCIIToUTF16("A B"), back_model->GetLabelAt(3)); |
| EXPECT_EQ(ASCIIToUTF16("A && B"), back_model->GetLabelAt(2)); |
| EXPECT_EQ(ASCIIToUTF16("A &&&& B"), back_model->GetLabelAt(1)); |
| EXPECT_EQ(ASCIIToUTF16("A &&&&&& B"), back_model->GetLabelAt(0)); |
| #endif // defined(OS_MACOSX) |
| } |
| |
| // Test asynchronous loading of favicon from history service. |
| TEST_F(BackFwdMenuModelTest, FaviconLoadTest) { |
| ASSERT_TRUE(profile()->CreateHistoryService(true, false)); |
| profile()->CreateFaviconService(); |
| Browser::CreateParams native_params(profile(), chrome::GetActiveDesktop()); |
| scoped_ptr<Browser> browser( |
| chrome::CreateBrowserWithTestWindowForParams(&native_params)); |
| FaviconDelegate favicon_delegate; |
| |
| BackForwardMenuModel back_model( |
| browser.get(), BackForwardMenuModel::BACKWARD_MENU); |
| back_model.set_test_web_contents(controller().GetWebContents()); |
| back_model.SetMenuModelDelegate(&favicon_delegate); |
| |
| SkBitmap new_icon_bitmap(CreateBitmap(SK_ColorRED)); |
| |
| GURL url1 = GURL("http://www.a.com/1"); |
| GURL url2 = GURL("http://www.a.com/2"); |
| GURL url1_favicon("http://www.a.com/1/favicon.ico"); |
| |
| NavigateAndCommit(url1); |
| // Navigate to a new URL so that url1 will be in the BackForwardMenuModel. |
| NavigateAndCommit(url2); |
| |
| // Set the desired favicon for url1. |
| HistoryServiceFactory::GetForProfile( |
| profile(), Profile::EXPLICIT_ACCESS)->AddPage( |
| url1, base::Time::Now(), history::SOURCE_BROWSED); |
| FaviconServiceFactory::GetForProfile( |
| profile(), Profile::EXPLICIT_ACCESS)->SetFavicons( |
| url1, url1_favicon, chrome::FAVICON, |
| gfx::Image::CreateFrom1xBitmap(new_icon_bitmap)); |
| |
| // Will return the current icon (default) but start an anync call |
| // to retrieve the favicon from the favicon service. |
| gfx::Image default_icon; |
| back_model.GetIconAt(0, &default_icon); |
| |
| // Make the favicon service run GetFavIconForURL, |
| // FaviconDelegate.OnIconChanged will be called. |
| base::MessageLoop::current()->Run(); |
| |
| // Verify that the callback executed. |
| EXPECT_TRUE(favicon_delegate.was_called()); |
| |
| // Verify the bitmaps match. |
| gfx::Image valid_icon; |
| // This time we will get the new favicon returned. |
| back_model.GetIconAt(0, &valid_icon); |
| |
| SkBitmap default_icon_bitmap = *default_icon.ToSkBitmap(); |
| SkBitmap valid_icon_bitmap = *valid_icon.ToSkBitmap(); |
| |
| SkAutoLockPixels a(new_icon_bitmap); |
| SkAutoLockPixels b(valid_icon_bitmap); |
| SkAutoLockPixels c(default_icon_bitmap); |
| // Verify we did not get the default favicon. |
| EXPECT_NE(0, memcmp(default_icon_bitmap.getPixels(), |
| valid_icon_bitmap.getPixels(), |
| default_icon_bitmap.getSize())); |
| // Verify we did get the expected favicon. |
| EXPECT_EQ(0, memcmp(new_icon_bitmap.getPixels(), |
| valid_icon_bitmap.getPixels(), |
| new_icon_bitmap.getSize())); |
| |
| // Make sure the browser deconstructor doesn't have problems. |
| browser->tab_strip_model()->CloseAllTabs(); |
| // This is required to prevent the message loop from hanging. |
| profile()->DestroyHistoryService(); |
| } |