1// Copyright 2013 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/browser.h"
6
7#include "chrome/browser/ui/browser_commands.h"
8#include "chrome/browser/ui/tabs/tab_strip_model.h"
9#include "chrome/test/base/browser_with_test_window_test.h"
10#include "content/public/browser/site_instance.h"
11#include "content/public/browser/web_contents.h"
12#include "content/public/test/web_contents_tester.h"
13
14// Both tests below require a tab strip, so skip the file entirely on platforms
15// without one.
16#if !defined(OS_ANDROID) && !defined(OS_IOS)
17
18using content::SiteInstance;
19using content::WebContents;
20using content::WebContentsTester;
21
22class BrowserUnitTest : public BrowserWithTestWindowTest {
23 public:
24  BrowserUnitTest() {}
25  virtual ~BrowserUnitTest() {}
26
27  // Caller owns the memory.
28  WebContents* CreateTestWebContents() {
29    return WebContentsTester::CreateTestWebContents(
30        profile(), SiteInstance::Create(profile()));
31  }
32
33 private:
34  DISALLOW_COPY_AND_ASSIGN(BrowserUnitTest);
35};
36
37// Ensure crashed tabs are not reloaded when selected. crbug.com/232323
38TEST_F(BrowserUnitTest, ReloadCrashedTab) {
39  TabStripModel* tab_strip_model = browser()->tab_strip_model();
40
41  // Start with a single foreground tab. |tab_strip_model| owns the memory.
42  WebContents* contents1 = CreateTestWebContents();
43  tab_strip_model->AppendWebContents(contents1, true);
44  WebContentsTester::For(contents1)->NavigateAndCommit(GURL("about:blank"));
45  WebContentsTester::For(contents1)->TestSetIsLoading(false);
46  EXPECT_TRUE(tab_strip_model->IsTabSelected(0));
47  EXPECT_FALSE(contents1->IsLoading());
48
49  // Add a second tab in the background.
50  WebContents* contents2 = CreateTestWebContents();
51  tab_strip_model->AppendWebContents(contents2, false);
52  WebContentsTester::For(contents2)->NavigateAndCommit(GURL("about:blank"));
53  WebContentsTester::For(contents2)->TestSetIsLoading(false);
54  EXPECT_EQ(2, browser()->tab_strip_model()->count());
55  EXPECT_TRUE(tab_strip_model->IsTabSelected(0));
56  EXPECT_FALSE(contents2->IsLoading());
57
58  // Simulate the second tab crashing.
59  contents2->SetIsCrashed(base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
60  EXPECT_TRUE(contents2->IsCrashed());
61
62  // Selecting the second tab does not cause a load or clear the crash.
63  tab_strip_model->ActivateTabAt(1, true);
64  EXPECT_TRUE(tab_strip_model->IsTabSelected(1));
65  EXPECT_FALSE(contents2->IsLoading());
66  EXPECT_TRUE(contents2->IsCrashed());
67}
68
69class BrowserBookmarkBarTest : public BrowserWithTestWindowTest {
70 public:
71  BrowserBookmarkBarTest() {}
72  virtual ~BrowserBookmarkBarTest() {}
73
74 protected:
75  BookmarkBar::State window_bookmark_bar_state() const {
76    return static_cast<BookmarkBarStateTestBrowserWindow*>(
77        browser()->window())->bookmark_bar_state();
78  }
79
80  // BrowserWithTestWindowTest:
81  virtual void SetUp() OVERRIDE {
82    BrowserWithTestWindowTest::SetUp();
83    static_cast<BookmarkBarStateTestBrowserWindow*>(
84        browser()->window())->set_browser(browser());
85  }
86
87  virtual BrowserWindow* CreateBrowserWindow() OVERRIDE {
88    return new BookmarkBarStateTestBrowserWindow();
89  }
90
91 private:
92  class BookmarkBarStateTestBrowserWindow : public TestBrowserWindow {
93   public:
94    BookmarkBarStateTestBrowserWindow()
95        : browser_(NULL),
96          bookmark_bar_state_(BookmarkBar::HIDDEN) {}
97    virtual ~BookmarkBarStateTestBrowserWindow() {}
98
99    void set_browser(Browser* browser) { browser_ = browser; }
100
101    BookmarkBar::State bookmark_bar_state() const {
102      return bookmark_bar_state_;
103    }
104
105   private:
106    // TestBrowserWindow:
107    virtual void BookmarkBarStateChanged(
108        BookmarkBar::AnimateChangeType change_type) OVERRIDE {
109      bookmark_bar_state_ = browser_->bookmark_bar_state();
110      TestBrowserWindow::BookmarkBarStateChanged(change_type);
111    }
112
113    virtual void OnActiveTabChanged(content::WebContents* old_contents,
114                                    content::WebContents* new_contents,
115                                    int index,
116                                    int reason) OVERRIDE {
117      bookmark_bar_state_ = browser_->bookmark_bar_state();
118      TestBrowserWindow::OnActiveTabChanged(old_contents, new_contents, index,
119                                            reason);
120    }
121
122    Browser* browser_;  // Weak ptr.
123    BookmarkBar::State bookmark_bar_state_;
124
125    DISALLOW_COPY_AND_ASSIGN(BookmarkBarStateTestBrowserWindow);
126  };
127
128  DISALLOW_COPY_AND_ASSIGN(BrowserBookmarkBarTest);
129};
130
131// Ensure bookmark bar states in Browser and BrowserWindow are in sync after
132// Browser::ActiveTabChanged() calls BrowserWindow::OnActiveTabChanged().
133TEST_F(BrowserBookmarkBarTest, StateOnActiveTabChanged) {
134  ASSERT_EQ(BookmarkBar::HIDDEN, browser()->bookmark_bar_state());
135  ASSERT_EQ(BookmarkBar::HIDDEN, window_bookmark_bar_state());
136
137  GURL ntp_url("chrome://newtab");
138  GURL non_ntp_url("http://foo");
139
140  // Open a tab to NTP.
141  AddTab(browser(), ntp_url);
142  EXPECT_EQ(BookmarkBar::DETACHED, browser()->bookmark_bar_state());
143  EXPECT_EQ(BookmarkBar::DETACHED, window_bookmark_bar_state());
144
145  // Navigate 1st tab to a non-NTP URL.
146  NavigateAndCommitActiveTab(non_ntp_url);
147  EXPECT_EQ(BookmarkBar::HIDDEN, browser()->bookmark_bar_state());
148  EXPECT_EQ(BookmarkBar::HIDDEN, window_bookmark_bar_state());
149
150  // Open a tab to NTP at index 0.
151  AddTab(browser(), ntp_url);
152  EXPECT_EQ(BookmarkBar::DETACHED, browser()->bookmark_bar_state());
153  EXPECT_EQ(BookmarkBar::DETACHED, window_bookmark_bar_state());
154
155  // Activate the 2nd tab which is non-NTP.
156  browser()->tab_strip_model()->ActivateTabAt(1, true);
157  EXPECT_EQ(BookmarkBar::HIDDEN, browser()->bookmark_bar_state());
158  EXPECT_EQ(BookmarkBar::HIDDEN, window_bookmark_bar_state());
159
160  // Toggle bookmark bar while 2nd tab (non-NTP) is active.
161  chrome::ToggleBookmarkBar(browser());
162  EXPECT_EQ(BookmarkBar::SHOW, browser()->bookmark_bar_state());
163  EXPECT_EQ(BookmarkBar::SHOW, window_bookmark_bar_state());
164
165  // Activate the 1st tab which is NTP.
166  browser()->tab_strip_model()->ActivateTabAt(0, true);
167  EXPECT_EQ(BookmarkBar::SHOW, browser()->bookmark_bar_state());
168  EXPECT_EQ(BookmarkBar::SHOW, window_bookmark_bar_state());
169
170  // Activate the 2nd tab which is non-NTP.
171  browser()->tab_strip_model()->ActivateTabAt(1, true);
172  EXPECT_EQ(BookmarkBar::SHOW, browser()->bookmark_bar_state());
173  EXPECT_EQ(BookmarkBar::SHOW, window_bookmark_bar_state());
174}
175
176#endif  // !defined(OS_ANDROID) && !defined(OS_IOS)
177