Infobar material design refresh: layout
[chromium-blink-merge.git] / chrome / browser / ui / toolbar / back_forward_menu_model_unittest.cc
blob66c4092dba9600cba339e79a9c2d0c23d02a3868
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.
5 #include "chrome/browser/ui/toolbar/back_forward_menu_model.h"
7 #include "base/strings/string16.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/time/time.h"
11 #include "chrome/browser/favicon/favicon_service_factory.h"
12 #include "chrome/browser/history/history_service_factory.h"
13 #include "chrome/browser/profiles/profile_manager.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_tabstrip.h"
16 #include "chrome/browser/ui/tabs/tab_strip_model.h"
17 #include "chrome/common/url_constants.h"
18 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
19 #include "chrome/test/base/test_browser_window.h"
20 #include "chrome/test/base/testing_profile.h"
21 #include "components/history/core/browser/history_service.h"
22 #include "content/public/browser/navigation_controller.h"
23 #include "content/public/browser/navigation_entry.h"
24 #include "content/public/browser/web_contents.h"
25 #include "content/public/test/web_contents_tester.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "third_party/skia/include/core/SkBitmap.h"
28 #include "ui/gfx/codec/png_codec.h"
30 using base::ASCIIToUTF16;
31 using content::WebContentsTester;
33 namespace {
35 // Creates a bitmap of the specified color.
36 SkBitmap CreateBitmap(SkColor color) {
37 SkBitmap bitmap;
38 bitmap.allocN32Pixels(16, 16);
39 bitmap.eraseColor(color);
40 return bitmap;
43 class FaviconDelegate : public ui::MenuModelDelegate {
44 public:
45 FaviconDelegate() : was_called_(false) {}
47 void OnIconChanged(int model_index) override {
48 was_called_ = true;
49 base::MessageLoop::current()->Quit();
52 bool was_called() const { return was_called_; }
54 private:
55 bool was_called_;
57 DISALLOW_COPY_AND_ASSIGN(FaviconDelegate);
60 } // namespace
62 class BackFwdMenuModelTest : public ChromeRenderViewHostTestHarness {
63 public:
64 void ValidateModel(BackForwardMenuModel* model, int history_items,
65 int chapter_stops) {
66 int h = std::min(BackForwardMenuModel::kMaxHistoryItems, history_items);
67 int c = std::min(BackForwardMenuModel::kMaxChapterStops, chapter_stops);
68 EXPECT_EQ(h, model->GetHistoryItemCount());
69 EXPECT_EQ(c, model->GetChapterStopCount(h));
70 if (h > 0)
71 h += 2; // Separator and View History link.
72 if (c > 0)
73 ++c;
74 EXPECT_EQ(h + c, model->GetItemCount());
77 void LoadURLAndUpdateState(const char* url, const char* title) {
78 NavigateAndCommit(GURL(url));
79 controller().GetLastCommittedEntry()->SetTitle(base::UTF8ToUTF16(title));
82 // Navigate back or forward the given amount and commits the entry (which
83 // will be pending after we ask to navigate there).
84 void NavigateToOffset(int offset) {
85 controller().GoToOffset(offset);
86 WebContentsTester::For(web_contents())->CommitPendingNavigation();
89 // Same as NavigateToOffset but goes to an absolute index.
90 void NavigateToIndex(int index) {
91 controller().GoToIndex(index);
92 WebContentsTester::For(web_contents())->CommitPendingNavigation();
95 // Goes back/forward and commits the load.
96 void GoBack() {
97 controller().GoBack();
98 WebContentsTester::For(web_contents())->CommitPendingNavigation();
100 void GoForward() {
101 controller().GoForward();
102 WebContentsTester::For(web_contents())->CommitPendingNavigation();
106 TEST_F(BackFwdMenuModelTest, BasicCase) {
107 scoped_ptr<BackForwardMenuModel> back_model(new BackForwardMenuModel(
108 NULL, BackForwardMenuModel::BACKWARD_MENU));
109 back_model->set_test_web_contents(web_contents());
111 scoped_ptr<BackForwardMenuModel> forward_model(new BackForwardMenuModel(
112 NULL, BackForwardMenuModel::FORWARD_MENU));
113 forward_model->set_test_web_contents(web_contents());
115 EXPECT_EQ(0, back_model->GetItemCount());
116 EXPECT_EQ(0, forward_model->GetItemCount());
117 EXPECT_FALSE(back_model->ItemHasCommand(1));
119 // Seed the controller with a few URLs
120 LoadURLAndUpdateState("http://www.a.com/1", "A1");
121 LoadURLAndUpdateState("http://www.a.com/2", "A2");
122 LoadURLAndUpdateState("http://www.a.com/3", "A3");
123 LoadURLAndUpdateState("http://www.b.com/1", "B1");
124 LoadURLAndUpdateState("http://www.b.com/2", "B2");
125 LoadURLAndUpdateState("http://www.c.com/1", "C1");
126 LoadURLAndUpdateState("http://www.c.com/2", "C2");
127 LoadURLAndUpdateState("http://www.c.com/3", "C3");
129 // There're two more items here: a separator and a "Show Full History".
130 EXPECT_EQ(9, back_model->GetItemCount());
131 EXPECT_EQ(0, forward_model->GetItemCount());
132 EXPECT_EQ(ASCIIToUTF16("C2"), back_model->GetLabelAt(0));
133 EXPECT_EQ(ASCIIToUTF16("A1"), back_model->GetLabelAt(6));
134 EXPECT_EQ(back_model->GetShowFullHistoryLabel(),
135 back_model->GetLabelAt(8));
137 EXPECT_TRUE(back_model->ItemHasCommand(0));
138 EXPECT_TRUE(back_model->ItemHasCommand(6));
139 EXPECT_TRUE(back_model->IsSeparator(7));
140 EXPECT_TRUE(back_model->ItemHasCommand(8));
141 EXPECT_FALSE(back_model->ItemHasCommand(9));
142 EXPECT_FALSE(back_model->ItemHasCommand(9));
144 NavigateToOffset(-7);
146 EXPECT_EQ(0, back_model->GetItemCount());
147 EXPECT_EQ(9, forward_model->GetItemCount());
148 EXPECT_EQ(ASCIIToUTF16("A2"), forward_model->GetLabelAt(0));
149 EXPECT_EQ(ASCIIToUTF16("C3"), forward_model->GetLabelAt(6));
150 EXPECT_EQ(forward_model->GetShowFullHistoryLabel(),
151 forward_model->GetLabelAt(8));
153 EXPECT_TRUE(forward_model->ItemHasCommand(0));
154 EXPECT_TRUE(forward_model->ItemHasCommand(6));
155 EXPECT_TRUE(forward_model->IsSeparator(7));
156 EXPECT_TRUE(forward_model->ItemHasCommand(8));
157 EXPECT_FALSE(forward_model->ItemHasCommand(7));
158 EXPECT_FALSE(forward_model->ItemHasCommand(9));
160 NavigateToOffset(4);
162 EXPECT_EQ(6, back_model->GetItemCount());
163 EXPECT_EQ(5, forward_model->GetItemCount());
164 EXPECT_EQ(ASCIIToUTF16("B1"), back_model->GetLabelAt(0));
165 EXPECT_EQ(ASCIIToUTF16("A1"), back_model->GetLabelAt(3));
166 EXPECT_EQ(back_model->GetShowFullHistoryLabel(),
167 back_model->GetLabelAt(5));
168 EXPECT_EQ(ASCIIToUTF16("C1"), forward_model->GetLabelAt(0));
169 EXPECT_EQ(ASCIIToUTF16("C3"), forward_model->GetLabelAt(2));
170 EXPECT_EQ(forward_model->GetShowFullHistoryLabel(),
171 forward_model->GetLabelAt(4));
174 TEST_F(BackFwdMenuModelTest, MaxItemsTest) {
175 scoped_ptr<BackForwardMenuModel> back_model(new BackForwardMenuModel(
176 NULL, BackForwardMenuModel::BACKWARD_MENU));
177 back_model->set_test_web_contents(web_contents());
179 scoped_ptr<BackForwardMenuModel> forward_model(new BackForwardMenuModel(
180 NULL, BackForwardMenuModel::FORWARD_MENU));
181 forward_model->set_test_web_contents(web_contents());
183 // Seed the controller with 32 URLs
184 LoadURLAndUpdateState("http://www.a.com/1", "A1");
185 LoadURLAndUpdateState("http://www.a.com/2", "A2");
186 LoadURLAndUpdateState("http://www.a.com/3", "A3");
187 LoadURLAndUpdateState("http://www.b.com/1", "B1");
188 LoadURLAndUpdateState("http://www.b.com/2", "B2");
189 LoadURLAndUpdateState("http://www.b.com/3", "B3");
190 LoadURLAndUpdateState("http://www.c.com/1", "C1");
191 LoadURLAndUpdateState("http://www.c.com/2", "C2");
192 LoadURLAndUpdateState("http://www.c.com/3", "C3");
193 LoadURLAndUpdateState("http://www.d.com/1", "D1");
194 LoadURLAndUpdateState("http://www.d.com/2", "D2");
195 LoadURLAndUpdateState("http://www.d.com/3", "D3");
196 LoadURLAndUpdateState("http://www.e.com/1", "E1");
197 LoadURLAndUpdateState("http://www.e.com/2", "E2");
198 LoadURLAndUpdateState("http://www.e.com/3", "E3");
199 LoadURLAndUpdateState("http://www.f.com/1", "F1");
200 LoadURLAndUpdateState("http://www.f.com/2", "F2");
201 LoadURLAndUpdateState("http://www.f.com/3", "F3");
202 LoadURLAndUpdateState("http://www.g.com/1", "G1");
203 LoadURLAndUpdateState("http://www.g.com/2", "G2");
204 LoadURLAndUpdateState("http://www.g.com/3", "G3");
205 LoadURLAndUpdateState("http://www.h.com/1", "H1");
206 LoadURLAndUpdateState("http://www.h.com/2", "H2");
207 LoadURLAndUpdateState("http://www.h.com/3", "H3");
208 LoadURLAndUpdateState("http://www.i.com/1", "I1");
209 LoadURLAndUpdateState("http://www.i.com/2", "I2");
210 LoadURLAndUpdateState("http://www.i.com/3", "I3");
211 LoadURLAndUpdateState("http://www.j.com/1", "J1");
212 LoadURLAndUpdateState("http://www.j.com/2", "J2");
213 LoadURLAndUpdateState("http://www.j.com/3", "J3");
214 LoadURLAndUpdateState("http://www.k.com/1", "K1");
215 LoadURLAndUpdateState("http://www.k.com/2", "K2");
217 // Also there're two more for a separator and a "Show Full History".
218 int chapter_stop_offset = 6;
219 EXPECT_EQ(BackForwardMenuModel::kMaxHistoryItems + 2 + chapter_stop_offset,
220 back_model->GetItemCount());
221 EXPECT_EQ(0, forward_model->GetItemCount());
222 EXPECT_EQ(ASCIIToUTF16("K1"), back_model->GetLabelAt(0));
223 EXPECT_EQ(back_model->GetShowFullHistoryLabel(),
224 back_model->GetLabelAt(BackForwardMenuModel::kMaxHistoryItems + 1 +
225 chapter_stop_offset));
227 // Test for out of bounds (beyond Show Full History).
228 EXPECT_FALSE(back_model->ItemHasCommand(
229 BackForwardMenuModel::kMaxHistoryItems + chapter_stop_offset + 2));
231 EXPECT_TRUE(back_model->ItemHasCommand(
232 BackForwardMenuModel::kMaxHistoryItems - 1));
233 EXPECT_TRUE(back_model->IsSeparator(
234 BackForwardMenuModel::kMaxHistoryItems));
236 NavigateToIndex(0);
238 EXPECT_EQ(BackForwardMenuModel::kMaxHistoryItems + 2 + chapter_stop_offset,
239 forward_model->GetItemCount());
240 EXPECT_EQ(0, back_model->GetItemCount());
241 EXPECT_EQ(ASCIIToUTF16("A2"), forward_model->GetLabelAt(0));
242 EXPECT_EQ(forward_model->GetShowFullHistoryLabel(),
243 forward_model->GetLabelAt(BackForwardMenuModel::kMaxHistoryItems + 1 +
244 chapter_stop_offset));
246 // Out of bounds
247 EXPECT_FALSE(forward_model->ItemHasCommand(
248 BackForwardMenuModel::kMaxHistoryItems + 2 + chapter_stop_offset));
250 EXPECT_TRUE(forward_model->ItemHasCommand(
251 BackForwardMenuModel::kMaxHistoryItems - 1));
252 EXPECT_TRUE(forward_model->IsSeparator(
253 BackForwardMenuModel::kMaxHistoryItems));
256 TEST_F(BackFwdMenuModelTest, ChapterStops) {
257 scoped_ptr<BackForwardMenuModel> back_model(new BackForwardMenuModel(
258 NULL, BackForwardMenuModel::BACKWARD_MENU));
259 back_model->set_test_web_contents(web_contents());
261 scoped_ptr<BackForwardMenuModel> forward_model(new BackForwardMenuModel(
262 NULL, BackForwardMenuModel::FORWARD_MENU));
263 forward_model->set_test_web_contents(web_contents());
265 // Seed the controller with 32 URLs.
266 int i = 0;
267 LoadURLAndUpdateState("http://www.a.com/1", "A1");
268 ValidateModel(back_model.get(), i++, 0);
269 LoadURLAndUpdateState("http://www.a.com/2", "A2");
270 ValidateModel(back_model.get(), i++, 0);
271 LoadURLAndUpdateState("http://www.a.com/3", "A3");
272 ValidateModel(back_model.get(), i++, 0);
273 LoadURLAndUpdateState("http://www.b.com/1", "B1");
274 ValidateModel(back_model.get(), i++, 0);
275 LoadURLAndUpdateState("http://www.b.com/2", "B2");
276 ValidateModel(back_model.get(), i++, 0);
277 // i = 5
278 LoadURLAndUpdateState("http://www.b.com/3", "B3");
279 ValidateModel(back_model.get(), i++, 0);
280 LoadURLAndUpdateState("http://www.c.com/1", "C1");
281 ValidateModel(back_model.get(), i++, 0);
282 LoadURLAndUpdateState("http://www.c.com/2", "C2");
283 ValidateModel(back_model.get(), i++, 0);
284 LoadURLAndUpdateState("http://www.c.com/3", "C3");
285 ValidateModel(back_model.get(), i++, 0);
286 LoadURLAndUpdateState("http://www.d.com/1", "D1");
287 ValidateModel(back_model.get(), i++, 0);
288 // i = 10
289 LoadURLAndUpdateState("http://www.d.com/2", "D2");
290 ValidateModel(back_model.get(), i++, 0);
291 LoadURLAndUpdateState("http://www.d.com/3", "D3");
292 ValidateModel(back_model.get(), i++, 0);
293 LoadURLAndUpdateState("http://www.e.com/1", "E1");
294 ValidateModel(back_model.get(), i++, 0);
295 LoadURLAndUpdateState("http://www.e.com/2", "E2");
296 ValidateModel(back_model.get(), i++, 0);
297 LoadURLAndUpdateState("http://www.e.com/3", "E3");
298 ValidateModel(back_model.get(), i++, 0);
299 // i = 15
300 LoadURLAndUpdateState("http://www.f.com/1", "F1");
301 ValidateModel(back_model.get(), i++, 1);
302 LoadURLAndUpdateState("http://www.f.com/2", "F2");
303 ValidateModel(back_model.get(), i++, 1);
304 LoadURLAndUpdateState("http://www.f.com/3", "F3");
305 ValidateModel(back_model.get(), i++, 1);
306 LoadURLAndUpdateState("http://www.g.com/1", "G1");
307 ValidateModel(back_model.get(), i++, 2);
308 LoadURLAndUpdateState("http://www.g.com/2", "G2");
309 ValidateModel(back_model.get(), i++, 2);
310 // i = 20
311 LoadURLAndUpdateState("http://www.g.com/3", "G3");
312 ValidateModel(back_model.get(), i++, 2);
313 LoadURLAndUpdateState("http://www.h.com/1", "H1");
314 ValidateModel(back_model.get(), i++, 3);
315 LoadURLAndUpdateState("http://www.h.com/2", "H2");
316 ValidateModel(back_model.get(), i++, 3);
317 LoadURLAndUpdateState("http://www.h.com/3", "H3");
318 ValidateModel(back_model.get(), i++, 3);
319 LoadURLAndUpdateState("http://www.i.com/1", "I1");
320 ValidateModel(back_model.get(), i++, 4);
321 // i = 25
322 LoadURLAndUpdateState("http://www.i.com/2", "I2");
323 ValidateModel(back_model.get(), i++, 4);
324 LoadURLAndUpdateState("http://www.i.com/3", "I3");
325 ValidateModel(back_model.get(), i++, 4);
326 LoadURLAndUpdateState("http://www.j.com/1", "J1");
327 ValidateModel(back_model.get(), i++, 5);
328 LoadURLAndUpdateState("http://www.j.com/2", "J2");
329 ValidateModel(back_model.get(), i++, 5);
330 LoadURLAndUpdateState("http://www.j.com/3", "J3");
331 ValidateModel(back_model.get(), i++, 5);
332 // i = 30
333 LoadURLAndUpdateState("http://www.k.com/1", "K1");
334 ValidateModel(back_model.get(), i++, 6);
335 LoadURLAndUpdateState("http://www.k.com/2", "K2");
336 ValidateModel(back_model.get(), i++, 6);
337 // i = 32
338 LoadURLAndUpdateState("http://www.k.com/3", "K3");
339 ValidateModel(back_model.get(), i++, 6);
341 // A chapter stop is defined as the last page the user
342 // browsed to within the same domain.
344 // Check to see if the chapter stops have the right labels.
345 int index = BackForwardMenuModel::kMaxHistoryItems;
346 // Empty string indicates item is a separator.
347 EXPECT_EQ(base::string16(), back_model->GetLabelAt(index++));
348 EXPECT_EQ(ASCIIToUTF16("F3"), back_model->GetLabelAt(index++));
349 EXPECT_EQ(ASCIIToUTF16("E3"), back_model->GetLabelAt(index++));
350 EXPECT_EQ(ASCIIToUTF16("D3"), back_model->GetLabelAt(index++));
351 EXPECT_EQ(ASCIIToUTF16("C3"), back_model->GetLabelAt(index++));
352 // The menu should only show a maximum of 5 chapter stops.
353 EXPECT_EQ(ASCIIToUTF16("B3"), back_model->GetLabelAt(index));
354 // Empty string indicates item is a separator.
355 EXPECT_EQ(base::string16(), back_model->GetLabelAt(index + 1));
356 EXPECT_EQ(back_model->GetShowFullHistoryLabel(),
357 back_model->GetLabelAt(index + 2));
359 // If we go back two we should still see the same chapter stop at the end.
360 GoBack();
361 EXPECT_EQ(ASCIIToUTF16("B3"), back_model->GetLabelAt(index));
362 GoBack();
363 EXPECT_EQ(ASCIIToUTF16("B3"), back_model->GetLabelAt(index));
364 // But if we go back again, it should change.
365 GoBack();
366 EXPECT_EQ(ASCIIToUTF16("A3"), back_model->GetLabelAt(index));
367 GoBack();
368 EXPECT_EQ(ASCIIToUTF16("A3"), back_model->GetLabelAt(index));
369 GoBack();
370 EXPECT_EQ(ASCIIToUTF16("A3"), back_model->GetLabelAt(index));
371 GoBack();
372 // It is now a separator.
373 EXPECT_EQ(base::string16(), back_model->GetLabelAt(index));
374 // Undo our position change.
375 NavigateToOffset(6);
377 // Go back enough to make sure no chapter stops should appear.
378 NavigateToOffset(-BackForwardMenuModel::kMaxHistoryItems);
379 ValidateModel(forward_model.get(), BackForwardMenuModel::kMaxHistoryItems, 0);
380 // Go forward (still no chapter stop)
381 GoForward();
382 ValidateModel(forward_model.get(),
383 BackForwardMenuModel::kMaxHistoryItems - 1, 0);
384 // Go back two (one chapter stop should show up)
385 GoBack();
386 GoBack();
387 ValidateModel(forward_model.get(),
388 BackForwardMenuModel::kMaxHistoryItems, 1);
390 // Go to beginning.
391 NavigateToIndex(0);
393 // Check to see if the chapter stops have the right labels.
394 index = BackForwardMenuModel::kMaxHistoryItems;
395 // Empty string indicates item is a separator.
396 EXPECT_EQ(base::string16(), forward_model->GetLabelAt(index++));
397 EXPECT_EQ(ASCIIToUTF16("E3"), forward_model->GetLabelAt(index++));
398 EXPECT_EQ(ASCIIToUTF16("F3"), forward_model->GetLabelAt(index++));
399 EXPECT_EQ(ASCIIToUTF16("G3"), forward_model->GetLabelAt(index++));
400 EXPECT_EQ(ASCIIToUTF16("H3"), forward_model->GetLabelAt(index++));
401 // The menu should only show a maximum of 5 chapter stops.
402 EXPECT_EQ(ASCIIToUTF16("I3"), forward_model->GetLabelAt(index));
403 // Empty string indicates item is a separator.
404 EXPECT_EQ(base::string16(), forward_model->GetLabelAt(index + 1));
405 EXPECT_EQ(forward_model->GetShowFullHistoryLabel(),
406 forward_model->GetLabelAt(index + 2));
408 // If we advance one we should still see the same chapter stop at the end.
409 GoForward();
410 EXPECT_EQ(ASCIIToUTF16("I3"), forward_model->GetLabelAt(index));
411 // But if we advance one again, it should change.
412 GoForward();
413 EXPECT_EQ(ASCIIToUTF16("J3"), forward_model->GetLabelAt(index));
414 GoForward();
415 EXPECT_EQ(ASCIIToUTF16("J3"), forward_model->GetLabelAt(index));
416 GoForward();
417 EXPECT_EQ(ASCIIToUTF16("J3"), forward_model->GetLabelAt(index));
418 GoForward();
419 EXPECT_EQ(ASCIIToUTF16("K3"), forward_model->GetLabelAt(index));
421 // Now test the boundary cases by using the chapter stop function directly.
422 // Out of bounds, first too far right (incrementing), then too far left.
423 EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(33, false));
424 EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(-1, true));
425 // Test being at end and going right, then at beginning going left.
426 EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(32, true));
427 EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(0, false));
428 // Test success: beginning going right and end going left.
429 EXPECT_EQ(2, back_model->GetIndexOfNextChapterStop(0, true));
430 EXPECT_EQ(29, back_model->GetIndexOfNextChapterStop(32, false));
431 // Now see when the chapter stops begin to show up.
432 EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(1, false));
433 EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(2, false));
434 EXPECT_EQ(2, back_model->GetIndexOfNextChapterStop(3, false));
435 // Now see when the chapter stops end.
436 EXPECT_EQ(32, back_model->GetIndexOfNextChapterStop(30, true));
437 EXPECT_EQ(32, back_model->GetIndexOfNextChapterStop(31, true));
438 EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(32, true));
440 // Bug found during review (two different sites, but first wasn't considered
441 // a chapter-stop).
442 // Go to A1;
443 NavigateToIndex(0);
444 LoadURLAndUpdateState("http://www.b.com/1", "B1");
445 EXPECT_EQ(0, back_model->GetIndexOfNextChapterStop(1, false));
446 EXPECT_EQ(1, back_model->GetIndexOfNextChapterStop(0, true));
448 // Now see if it counts 'www.x.com' and 'mail.x.com' as same domain, which
449 // it should.
450 // Go to A1.
451 NavigateToIndex(0);
452 LoadURLAndUpdateState("http://mail.a.com/2", "A2-mai");
453 LoadURLAndUpdateState("http://www.b.com/1", "B1");
454 LoadURLAndUpdateState("http://mail.b.com/2", "B2-mai");
455 LoadURLAndUpdateState("http://new.site.com", "new");
456 EXPECT_EQ(1, back_model->GetIndexOfNextChapterStop(0, true));
457 EXPECT_EQ(3, back_model->GetIndexOfNextChapterStop(1, true));
458 EXPECT_EQ(3, back_model->GetIndexOfNextChapterStop(2, true));
459 EXPECT_EQ(4, back_model->GetIndexOfNextChapterStop(3, true));
460 // And try backwards as well.
461 EXPECT_EQ(3, back_model->GetIndexOfNextChapterStop(4, false));
462 EXPECT_EQ(1, back_model->GetIndexOfNextChapterStop(3, false));
463 EXPECT_EQ(1, back_model->GetIndexOfNextChapterStop(2, false));
464 EXPECT_EQ(-1, back_model->GetIndexOfNextChapterStop(1, false));
467 TEST_F(BackFwdMenuModelTest, EscapeLabel) {
468 scoped_ptr<BackForwardMenuModel> back_model(new BackForwardMenuModel(
469 NULL, BackForwardMenuModel::BACKWARD_MENU));
470 back_model->set_test_web_contents(web_contents());
472 EXPECT_EQ(0, back_model->GetItemCount());
473 EXPECT_FALSE(back_model->ItemHasCommand(1));
475 LoadURLAndUpdateState("http://www.a.com/1", "A B");
476 LoadURLAndUpdateState("http://www.a.com/1", "A & B");
477 LoadURLAndUpdateState("http://www.a.com/2", "A && B");
478 LoadURLAndUpdateState("http://www.a.com/2", "A &&& B");
479 LoadURLAndUpdateState("http://www.a.com/3", "");
481 EXPECT_EQ(6, back_model->GetItemCount());
483 // On Mac ui::MenuModel::GetLabelAt should return unescaped strings.
484 #if defined(OS_MACOSX)
485 EXPECT_EQ(ASCIIToUTF16("A B"), back_model->GetLabelAt(3));
486 EXPECT_EQ(ASCIIToUTF16("A & B"), back_model->GetLabelAt(2));
487 EXPECT_EQ(ASCIIToUTF16("A && B"), back_model->GetLabelAt(1));
488 EXPECT_EQ(ASCIIToUTF16("A &&& B"), back_model->GetLabelAt(0));
489 #else
490 EXPECT_EQ(ASCIIToUTF16("A B"), back_model->GetLabelAt(3));
491 EXPECT_EQ(ASCIIToUTF16("A && B"), back_model->GetLabelAt(2));
492 EXPECT_EQ(ASCIIToUTF16("A &&&& B"), back_model->GetLabelAt(1));
493 EXPECT_EQ(ASCIIToUTF16("A &&&&&& B"), back_model->GetLabelAt(0));
494 #endif // defined(OS_MACOSX)
497 // Test asynchronous loading of favicon from history service.
498 TEST_F(BackFwdMenuModelTest, FaviconLoadTest) {
499 ASSERT_TRUE(profile()->CreateHistoryService(true, false));
500 profile()->CreateFaviconService();
501 Browser::CreateParams native_params(profile(), chrome::GetActiveDesktop());
502 scoped_ptr<Browser> browser(
503 chrome::CreateBrowserWithTestWindowForParams(&native_params));
504 FaviconDelegate favicon_delegate;
506 BackForwardMenuModel back_model(
507 browser.get(), BackForwardMenuModel::BACKWARD_MENU);
508 back_model.set_test_web_contents(controller().GetWebContents());
509 back_model.SetMenuModelDelegate(&favicon_delegate);
511 SkBitmap new_icon_bitmap(CreateBitmap(SK_ColorRED));
513 GURL url1 = GURL("http://www.a.com/1");
514 GURL url2 = GURL("http://www.a.com/2");
515 GURL url1_favicon("http://www.a.com/1/favicon.ico");
517 NavigateAndCommit(url1);
518 // Navigate to a new URL so that url1 will be in the BackForwardMenuModel.
519 NavigateAndCommit(url2);
521 // Set the desired favicon for url1.
522 HistoryServiceFactory::GetForProfile(profile(),
523 ServiceAccessType::EXPLICIT_ACCESS)
524 ->AddPage(url1, base::Time::Now(), history::SOURCE_BROWSED);
525 FaviconServiceFactory::GetForProfile(profile(),
526 ServiceAccessType::EXPLICIT_ACCESS)
527 ->SetFavicons(url1, url1_favicon, favicon_base::FAVICON,
528 gfx::Image::CreateFrom1xBitmap(new_icon_bitmap));
530 // Will return the current icon (default) but start an anync call
531 // to retrieve the favicon from the favicon service.
532 gfx::Image default_icon;
533 back_model.GetIconAt(0, &default_icon);
535 // Make the favicon service run GetFavIconForURL,
536 // FaviconDelegate.OnIconChanged will be called.
537 base::MessageLoop::current()->Run();
539 // Verify that the callback executed.
540 EXPECT_TRUE(favicon_delegate.was_called());
542 // Verify the bitmaps match.
543 gfx::Image valid_icon;
544 // This time we will get the new favicon returned.
545 back_model.GetIconAt(0, &valid_icon);
547 SkBitmap default_icon_bitmap = *default_icon.ToSkBitmap();
548 SkBitmap valid_icon_bitmap = *valid_icon.ToSkBitmap();
550 SkAutoLockPixels a(new_icon_bitmap);
551 SkAutoLockPixels b(valid_icon_bitmap);
552 SkAutoLockPixels c(default_icon_bitmap);
553 // Verify we did not get the default favicon.
554 EXPECT_NE(0, memcmp(default_icon_bitmap.getPixels(),
555 valid_icon_bitmap.getPixels(),
556 default_icon_bitmap.getSize()));
557 // Verify we did get the expected favicon.
558 EXPECT_EQ(0, memcmp(new_icon_bitmap.getPixels(),
559 valid_icon_bitmap.getPixels(),
560 new_icon_bitmap.getSize()));
562 // Make sure the browser deconstructor doesn't have problems.
563 browser->tab_strip_model()->CloseAllTabs();
564 // This is required to prevent the message loop from hanging.
565 profile()->DestroyHistoryService();