| Index: chrome/browser/ui/tabs/mru_tab_controller_unittest.cc
|
| diff --git a/chrome/browser/ui/tabs/mru_tab_controller_unittest.cc b/chrome/browser/ui/tabs/mru_tab_controller_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..2d99bfcbb6713461f254a54ebed1cd2cc6bf5091
|
| --- /dev/null
|
| +++ b/chrome/browser/ui/tabs/mru_tab_controller_unittest.cc
|
| @@ -0,0 +1,288 @@
|
| +// 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/tabs/mru_tab_controller.h"
|
| +
|
| +#include <map>
|
| +#include <string>
|
| +
|
| +#include "base/stl_util.h"
|
| +#include "base/string_number_conversions.h"
|
| +#include "base/string_split.h"
|
| +#include "base/utf_string_conversions.h"
|
| +#include "chrome/browser/ui/browser.h"
|
| +#include "chrome/browser/ui/browser_tabstrip.h"
|
| +#include "chrome/browser/ui/tab_contents/tab_contents.h"
|
| +#include "chrome/browser/ui/tabs/tab_strip_model.h"
|
| +#include "chrome/browser/ui/tabs/tab_strip_model_delegate.h"
|
| +#include "chrome/browser/ui/tabs/tab_strip_model_order_controller.h"
|
| +#include "chrome/browser/ui/tabs/test_tab_strip_model_delegate.h"
|
| +#include "chrome/common/url_constants.h"
|
| +#include "chrome/test/base/chrome_render_view_host_test_harness.h"
|
| +#include "chrome/test/base/testing_profile.h"
|
| +#include "content/public/browser/web_contents.h"
|
| +#include "content/public/test/test_browser_thread.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +using content::BrowserThread;
|
| +using content::SiteInstance;
|
| +using content::WebContents;
|
| +
|
| +class TabStripDummyDelegate : public TestTabStripModelDelegate {
|
| + public:
|
| + explicit TabStripDummyDelegate(TabContents* dummy)
|
| + : dummy_contents_(dummy),
|
| + can_close_(true),
|
| + run_unload_(false) {}
|
| + virtual ~TabStripDummyDelegate() {}
|
| +
|
| + void set_can_close(bool value) { can_close_ = value; }
|
| + void set_run_unload_listener(bool value) { run_unload_ = value; }
|
| +
|
| + // Overridden from TabStripModelDelegate:
|
| + virtual TabContents* CreateTabContentsForURL(
|
| + const GURL& url,
|
| + const content::Referrer& referrer,
|
| + Profile* profile,
|
| + content::PageTransition transition,
|
| + bool defer_load,
|
| + SiteInstance* instance) const OVERRIDE {
|
| + if (url == GURL(chrome::kChromeUINewTabURL))
|
| + return dummy_contents_;
|
| + return NULL;
|
| + }
|
| + virtual bool RunUnloadListenerBeforeClosing(TabContents* contents) OVERRIDE {
|
| + return run_unload_;
|
| + }
|
| + virtual bool CanCloseContents(std::vector<int>* indices) OVERRIDE {
|
| + if (!can_close_)
|
| + indices->clear();
|
| + return can_close_;
|
| + }
|
| +
|
| + private:
|
| + // A dummy TabContents we give to callers that expect us to actually
|
| + // build a Destinations tab for them.
|
| + TabContents* dummy_contents_;
|
| +
|
| + // Whether tabs can be closed.
|
| + bool can_close_;
|
| +
|
| + // Whether to report that we need to run an unload listener before closing.
|
| + bool run_unload_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(TabStripDummyDelegate);
|
| +};
|
| +
|
| +class MRUTabControllerTest : public ChromeRenderViewHostTestHarness {
|
| + public:
|
| + MRUTabControllerTest() : browser_thread_(BrowserThread::UI, &message_loop_) {
|
| + }
|
| +
|
| + TabContents* CreateTabContents() {
|
| + return chrome::TabContentsFactory(
|
| + profile(), NULL, MSG_ROUTING_NONE, NULL, NULL);
|
| + }
|
| +
|
| + TabContents* CreateTabContentsWithSharedRPH(
|
| + WebContents* web_contents) {
|
| + TabContents* retval = chrome::TabContentsFactory(profile(),
|
| + web_contents->GetRenderViewHost()->GetSiteInstance(), MSG_ROUTING_NONE,
|
| + NULL, NULL);
|
| + EXPECT_EQ(retval->web_contents()->GetRenderProcessHost(),
|
| + web_contents->GetRenderProcessHost());
|
| + return retval;
|
| + }
|
| +
|
| + // Forwards a URL "load" request through to our dummy TabContents
|
| + // implementation.
|
| + void LoadURL(WebContents* con, const std::wstring& url) {
|
| + controller().LoadURL(GURL(WideToUTF16(url)), content::Referrer(),
|
| + content::PAGE_TRANSITION_LINK, std::string());
|
| + }
|
| +
|
| + void GoBack(WebContents* contents) {
|
| + controller().GoBack();
|
| + }
|
| +
|
| + void GoForward(WebContents* contents) {
|
| + controller().GoForward();
|
| + }
|
| +
|
| + void SwitchTabTo(WebContents* contents) {
|
| + // contents()->DidBecomeSelected();
|
| + }
|
| +
|
| + // Sets the id of the specified contents.
|
| + void SetID(WebContents* contents, int id) {
|
| + GetIDAccessor()->SetProperty(contents->GetPropertyBag(), id);
|
| + }
|
| +
|
| + // Returns the id of the specified contents.
|
| + int GetID(WebContents* contents) {
|
| + return *GetIDAccessor()->GetProperty(contents->GetPropertyBag());
|
| + }
|
| +
|
| + // Returns the state of the given tab strip as a string. The state consists
|
| + // of the ID of each tab contents followed by a 'p' if pinned. For example,
|
| + // if the model consists of two tabs with ids 2 and 1, with the first
|
| + // tab pinned, this returns "2p 1".
|
| + std::string GetPinnedState(const TabStripModel& model) {
|
| + std::string actual;
|
| + for (int i = 0; i < model.count(); ++i) {
|
| + if (i > 0)
|
| + actual += " ";
|
| +
|
| + actual +=
|
| + base::IntToString(GetID(model.GetTabContentsAt(i)->web_contents()));
|
| +
|
| + if (model.IsAppTab(i))
|
| + actual += "a";
|
| +
|
| + if (model.IsTabPinned(i))
|
| + actual += "p";
|
| + }
|
| + return actual;
|
| + }
|
| +
|
| + std::string GetIndicesClosedByCommandAsString(
|
| + const TabStripModel& model,
|
| + int index,
|
| + TabStripModel::ContextMenuCommand id) const {
|
| + std::vector<int> indices = model.GetIndicesClosedByCommand(index, id);
|
| + std::string result;
|
| + for (size_t i = 0; i < indices.size(); ++i) {
|
| + if (i != 0)
|
| + result += " ";
|
| + result += base::IntToString(indices[i]);
|
| + }
|
| + return result;
|
| + }
|
| +
|
| + void PrepareTabstripForSelectionTest(TabStripModel* model,
|
| + int tab_count,
|
| + int pinned_count,
|
| + const std::string& selected_tabs) {
|
| + for (int i = 0; i < tab_count; ++i) {
|
| + TabContents* contents = CreateTabContents();
|
| + SetID(contents->web_contents(), i);
|
| + model->AppendTabContents(contents, true);
|
| + }
|
| + for (int i = 0; i < pinned_count; ++i)
|
| + model->SetTabPinned(i, true);
|
| +
|
| + TabStripSelectionModel selection_model;
|
| + std::vector<std::string> selection;
|
| + base::SplitStringAlongWhitespace(selected_tabs, &selection);
|
| + for (size_t i = 0; i < selection.size(); ++i) {
|
| + int value;
|
| + ASSERT_TRUE(base::StringToInt(selection[i], &value));
|
| + selection_model.AddIndexToSelection(value);
|
| + }
|
| + selection_model.set_active(selection_model.selected_indices()[0]);
|
| + model->SetSelectionFromModel(selection_model);
|
| + }
|
| +
|
| + private:
|
| + base::PropertyAccessor<int>* GetIDAccessor() {
|
| + static base::PropertyAccessor<int> accessor;
|
| + return &accessor;
|
| + }
|
| +
|
| + content::TestBrowserThread browser_thread_;
|
| +
|
| + std::wstring test_dir_;
|
| + std::wstring profile_path_;
|
| +};
|
| +
|
| +static int GetInsertionIndex(TabStripModel* tabstrip,
|
| + TabContents* contents) {
|
| + return tabstrip->order_controller()->DetermineInsertionIndex(
|
| + contents, content::PAGE_TRANSITION_LINK, false);
|
| +}
|
| +
|
| +static void InsertTabContentses(TabStripModel* tabstrip,
|
| + TabContents* contents1,
|
| + TabContents* contents2,
|
| + TabContents* contents3) {
|
| + tabstrip->InsertTabContentsAt(GetInsertionIndex(tabstrip, contents1),
|
| + contents1, TabStripModel::ADD_INHERIT_GROUP);
|
| + tabstrip->InsertTabContentsAt(GetInsertionIndex(tabstrip, contents2),
|
| + contents2, TabStripModel::ADD_INHERIT_GROUP);
|
| + tabstrip->InsertTabContentsAt(GetInsertionIndex(tabstrip, contents3),
|
| + contents3, TabStripModel::ADD_INHERIT_GROUP);
|
| +}
|
| +
|
| +// Test toggling between mru tabs
|
| +TEST_F(MRUTabControllerTest, ToggleMRUTabs) {
|
| + TabStripDummyDelegate delegate(NULL);
|
| + TabStripModel tabstrip(&delegate, profile());
|
| + MRUTabController controller(&tabstrip);
|
| +
|
| + EXPECT_TRUE(tabstrip.empty());
|
| +
|
| + TabContents* opener_contents = CreateTabContents();
|
| + tabstrip.AppendTabContents(opener_contents, true);
|
| +
|
| + TabContents* contents1 = CreateTabContents();
|
| + TabContents* contents2 = CreateTabContents();
|
| + TabContents* contents3 = CreateTabContents();
|
| +
|
| + InsertTabContentses(&tabstrip, contents1, contents2, contents3);
|
| + EXPECT_EQ(contents1, tabstrip.GetTabContentsAt(1));
|
| + EXPECT_EQ(contents2, tabstrip.GetTabContentsAt(2));
|
| + EXPECT_EQ(contents3, tabstrip.GetTabContentsAt(3));
|
| +
|
| + EXPECT_EQ(0, tabstrip.active_index());
|
| + tabstrip.ActivateTabAt(2, true);
|
| + EXPECT_EQ(2, tabstrip.active_index());
|
| +
|
| + EXPECT_EQ(0, tabstrip.GetIndexOfTabContents(controller.GetPreviousMRUTab()));
|
| +
|
| + tabstrip.CloseAllTabs();
|
| + // TabStripModel should now be empty.
|
| + EXPECT_TRUE(tabstrip.empty());
|
| +}
|
| +
|
| +// Test toggling between mru tabs
|
| +TEST_F(MRUTabControllerTest, PauseStackAndToggle) {
|
| + TabStripDummyDelegate delegate(NULL);
|
| + TabStripModel tabstrip(&delegate, profile());
|
| + MRUTabController controller(&tabstrip);
|
| +
|
| + EXPECT_TRUE(tabstrip.empty());
|
| +
|
| + TabContents* opener_contents = CreateTabContents();
|
| + tabstrip.AppendTabContents(opener_contents, true);
|
| +
|
| + TabContents* contents1 = CreateTabContents();
|
| + TabContents* contents2 = CreateTabContents();
|
| + TabContents* contents3 = CreateTabContents();
|
| +
|
| + InsertTabContentses(&tabstrip, contents1, contents2, contents3);
|
| + EXPECT_EQ(contents1, tabstrip.GetTabContentsAt(1));
|
| + EXPECT_EQ(contents2, tabstrip.GetTabContentsAt(2));
|
| + EXPECT_EQ(contents3, tabstrip.GetTabContentsAt(3));
|
| +
|
| + EXPECT_EQ(0, tabstrip.active_index());
|
| + controller.PauseStackUpdates();
|
| + tabstrip.ActivateTabAt(1, true);
|
| + EXPECT_EQ(1, tabstrip.active_index());
|
| + tabstrip.ActivateTabAt(2, true);
|
| + EXPECT_EQ(2, tabstrip.active_index());
|
| + tabstrip.ActivateTabAt(3, true);
|
| + EXPECT_EQ(3, tabstrip.active_index());
|
| +
|
| + // Commit the active tab changes now.
|
| + controller.CommitActiveTabChanges();
|
| + tabstrip.ActivateTabAt(0, true);
|
| + EXPECT_EQ(0, tabstrip.active_index());
|
| +
|
| + // Previous MRU tab would be 3
|
| + EXPECT_EQ(3, tabstrip.GetIndexOfTabContents(controller.GetPreviousMRUTab()));
|
| +
|
| + tabstrip.CloseAllTabs();
|
| + // TabStripModel should now be empty.
|
| + EXPECT_TRUE(tabstrip.empty());
|
| +}
|
|
|