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

Side by Side Diff: chrome/browser/ui/tabs/mru_tab_controller_unittest.cc

Issue 10117016: Implementation for switching between recently used tabs using ctrl tilde or quoteleft. Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Uploading patch for review after rebase. Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/tabs/mru_tab_controller.h"
6
7 #include <map>
8 #include <string>
9
10 #include "base/stl_util.h"
11 #include "base/string_number_conversions.h"
12 #include "base/string_split.h"
13 #include "base/utf_string_conversions.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_tabstrip.h"
16 #include "chrome/browser/ui/tab_contents/tab_contents.h"
17 #include "chrome/browser/ui/tabs/tab_strip_model.h"
18 #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h"
19 #include "chrome/browser/ui/tabs/tab_strip_model_order_controller.h"
20 #include "chrome/browser/ui/tabs/test_tab_strip_model_delegate.h"
21 #include "chrome/common/url_constants.h"
22 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
23 #include "chrome/test/base/testing_profile.h"
24 #include "content/public/browser/web_contents.h"
25 #include "content/public/test/test_browser_thread.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27
28 using content::BrowserThread;
29 using content::SiteInstance;
30 using content::WebContents;
31
32 class TabStripDummyDelegate : public TestTabStripModelDelegate {
33 public:
34 explicit TabStripDummyDelegate(TabContents* dummy)
35 : dummy_contents_(dummy),
36 can_close_(true),
37 run_unload_(false) {}
38 virtual ~TabStripDummyDelegate() {}
39
40 void set_can_close(bool value) { can_close_ = value; }
41 void set_run_unload_listener(bool value) { run_unload_ = value; }
42
43 // Overridden from TabStripModelDelegate:
44 virtual TabContents* CreateTabContentsForURL(
45 const GURL& url,
46 const content::Referrer& referrer,
47 Profile* profile,
48 content::PageTransition transition,
49 bool defer_load,
50 SiteInstance* instance) const OVERRIDE {
51 if (url == GURL(chrome::kChromeUINewTabURL))
52 return dummy_contents_;
53 return NULL;
54 }
55 virtual bool RunUnloadListenerBeforeClosing(TabContents* contents) OVERRIDE {
56 return run_unload_;
57 }
58 virtual bool CanCloseContents(std::vector<int>* indices) OVERRIDE {
59 if (!can_close_)
60 indices->clear();
61 return can_close_;
62 }
63
64 private:
65 // A dummy TabContents we give to callers that expect us to actually
66 // build a Destinations tab for them.
67 TabContents* dummy_contents_;
68
69 // Whether tabs can be closed.
70 bool can_close_;
71
72 // Whether to report that we need to run an unload listener before closing.
73 bool run_unload_;
74
75 DISALLOW_COPY_AND_ASSIGN(TabStripDummyDelegate);
76 };
77
78 class MRUTabControllerTest : public ChromeRenderViewHostTestHarness {
79 public:
80 MRUTabControllerTest() : browser_thread_(BrowserThread::UI, &message_loop_) {
81 }
82
83 TabContents* CreateTabContents() {
84 return chrome::TabContentsFactory(
85 profile(), NULL, MSG_ROUTING_NONE, NULL, NULL);
86 }
87
88 TabContents* CreateTabContentsWithSharedRPH(
89 WebContents* web_contents) {
90 TabContents* retval = chrome::TabContentsFactory(profile(),
91 web_contents->GetRenderViewHost()->GetSiteInstance(), MSG_ROUTING_NONE,
92 NULL, NULL);
93 EXPECT_EQ(retval->web_contents()->GetRenderProcessHost(),
94 web_contents->GetRenderProcessHost());
95 return retval;
96 }
97
98 // Forwards a URL "load" request through to our dummy TabContents
99 // implementation.
100 void LoadURL(WebContents* con, const std::wstring& url) {
101 controller().LoadURL(GURL(WideToUTF16(url)), content::Referrer(),
102 content::PAGE_TRANSITION_LINK, std::string());
103 }
104
105 void GoBack(WebContents* contents) {
106 controller().GoBack();
107 }
108
109 void GoForward(WebContents* contents) {
110 controller().GoForward();
111 }
112
113 void SwitchTabTo(WebContents* contents) {
114 // contents()->DidBecomeSelected();
115 }
116
117 // Sets the id of the specified contents.
118 void SetID(WebContents* contents, int id) {
119 GetIDAccessor()->SetProperty(contents->GetPropertyBag(), id);
120 }
121
122 // Returns the id of the specified contents.
123 int GetID(WebContents* contents) {
124 return *GetIDAccessor()->GetProperty(contents->GetPropertyBag());
125 }
126
127 // Returns the state of the given tab strip as a string. The state consists
128 // of the ID of each tab contents followed by a 'p' if pinned. For example,
129 // if the model consists of two tabs with ids 2 and 1, with the first
130 // tab pinned, this returns "2p 1".
131 std::string GetPinnedState(const TabStripModel& model) {
132 std::string actual;
133 for (int i = 0; i < model.count(); ++i) {
134 if (i > 0)
135 actual += " ";
136
137 actual +=
138 base::IntToString(GetID(model.GetTabContentsAt(i)->web_contents()));
139
140 if (model.IsAppTab(i))
141 actual += "a";
142
143 if (model.IsTabPinned(i))
144 actual += "p";
145 }
146 return actual;
147 }
148
149 std::string GetIndicesClosedByCommandAsString(
150 const TabStripModel& model,
151 int index,
152 TabStripModel::ContextMenuCommand id) const {
153 std::vector<int> indices = model.GetIndicesClosedByCommand(index, id);
154 std::string result;
155 for (size_t i = 0; i < indices.size(); ++i) {
156 if (i != 0)
157 result += " ";
158 result += base::IntToString(indices[i]);
159 }
160 return result;
161 }
162
163 void PrepareTabstripForSelectionTest(TabStripModel* model,
164 int tab_count,
165 int pinned_count,
166 const std::string& selected_tabs) {
167 for (int i = 0; i < tab_count; ++i) {
168 TabContents* contents = CreateTabContents();
169 SetID(contents->web_contents(), i);
170 model->AppendTabContents(contents, true);
171 }
172 for (int i = 0; i < pinned_count; ++i)
173 model->SetTabPinned(i, true);
174
175 TabStripSelectionModel selection_model;
176 std::vector<std::string> selection;
177 base::SplitStringAlongWhitespace(selected_tabs, &selection);
178 for (size_t i = 0; i < selection.size(); ++i) {
179 int value;
180 ASSERT_TRUE(base::StringToInt(selection[i], &value));
181 selection_model.AddIndexToSelection(value);
182 }
183 selection_model.set_active(selection_model.selected_indices()[0]);
184 model->SetSelectionFromModel(selection_model);
185 }
186
187 private:
188 base::PropertyAccessor<int>* GetIDAccessor() {
189 static base::PropertyAccessor<int> accessor;
190 return &accessor;
191 }
192
193 content::TestBrowserThread browser_thread_;
194
195 std::wstring test_dir_;
196 std::wstring profile_path_;
197 };
198
199 static int GetInsertionIndex(TabStripModel* tabstrip,
200 TabContents* contents) {
201 return tabstrip->order_controller()->DetermineInsertionIndex(
202 contents, content::PAGE_TRANSITION_LINK, false);
203 }
204
205 static void InsertTabContentses(TabStripModel* tabstrip,
206 TabContents* contents1,
207 TabContents* contents2,
208 TabContents* contents3) {
209 tabstrip->InsertTabContentsAt(GetInsertionIndex(tabstrip, contents1),
210 contents1, TabStripModel::ADD_INHERIT_GROUP);
211 tabstrip->InsertTabContentsAt(GetInsertionIndex(tabstrip, contents2),
212 contents2, TabStripModel::ADD_INHERIT_GROUP);
213 tabstrip->InsertTabContentsAt(GetInsertionIndex(tabstrip, contents3),
214 contents3, TabStripModel::ADD_INHERIT_GROUP);
215 }
216
217 // Test toggling between mru tabs
218 TEST_F(MRUTabControllerTest, ToggleMRUTabs) {
219 TabStripDummyDelegate delegate(NULL);
220 TabStripModel tabstrip(&delegate, profile());
221 MRUTabController controller(&tabstrip);
222
223 EXPECT_TRUE(tabstrip.empty());
224
225 TabContents* opener_contents = CreateTabContents();
226 tabstrip.AppendTabContents(opener_contents, true);
227
228 TabContents* contents1 = CreateTabContents();
229 TabContents* contents2 = CreateTabContents();
230 TabContents* contents3 = CreateTabContents();
231
232 InsertTabContentses(&tabstrip, contents1, contents2, contents3);
233 EXPECT_EQ(contents1, tabstrip.GetTabContentsAt(1));
234 EXPECT_EQ(contents2, tabstrip.GetTabContentsAt(2));
235 EXPECT_EQ(contents3, tabstrip.GetTabContentsAt(3));
236
237 EXPECT_EQ(0, tabstrip.active_index());
238 tabstrip.ActivateTabAt(2, true);
239 EXPECT_EQ(2, tabstrip.active_index());
240
241 EXPECT_EQ(0, tabstrip.GetIndexOfTabContents(controller.GetPreviousMRUTab()));
242
243 tabstrip.CloseAllTabs();
244 // TabStripModel should now be empty.
245 EXPECT_TRUE(tabstrip.empty());
246 }
247
248 // Test toggling between mru tabs
249 TEST_F(MRUTabControllerTest, PauseStackAndToggle) {
250 TabStripDummyDelegate delegate(NULL);
251 TabStripModel tabstrip(&delegate, profile());
252 MRUTabController controller(&tabstrip);
253
254 EXPECT_TRUE(tabstrip.empty());
255
256 TabContents* opener_contents = CreateTabContents();
257 tabstrip.AppendTabContents(opener_contents, true);
258
259 TabContents* contents1 = CreateTabContents();
260 TabContents* contents2 = CreateTabContents();
261 TabContents* contents3 = CreateTabContents();
262
263 InsertTabContentses(&tabstrip, contents1, contents2, contents3);
264 EXPECT_EQ(contents1, tabstrip.GetTabContentsAt(1));
265 EXPECT_EQ(contents2, tabstrip.GetTabContentsAt(2));
266 EXPECT_EQ(contents3, tabstrip.GetTabContentsAt(3));
267
268 EXPECT_EQ(0, tabstrip.active_index());
269 controller.PauseStackUpdates();
270 tabstrip.ActivateTabAt(1, true);
271 EXPECT_EQ(1, tabstrip.active_index());
272 tabstrip.ActivateTabAt(2, true);
273 EXPECT_EQ(2, tabstrip.active_index());
274 tabstrip.ActivateTabAt(3, true);
275 EXPECT_EQ(3, tabstrip.active_index());
276
277 // Commit the active tab changes now.
278 controller.CommitActiveTabChanges();
279 tabstrip.ActivateTabAt(0, true);
280 EXPECT_EQ(0, tabstrip.active_index());
281
282 // Previous MRU tab would be 3
283 EXPECT_EQ(3, tabstrip.GetIndexOfTabContents(controller.GetPreviousMRUTab()));
284
285 tabstrip.CloseAllTabs();
286 // TabStripModel should now be empty.
287 EXPECT_TRUE(tabstrip.empty());
288 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698