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/browser_process.h"
6#include "chrome/browser/browser_process_platform_part_chromeos.h"
7#include "chrome/browser/chromeos/memory/oom_priority_manager.h"
8#include "chrome/browser/ui/browser.h"
9#include "chrome/browser/ui/browser_commands.h"
10#include "chrome/browser/ui/find_bar/find_bar_controller.h"
11#include "chrome/browser/ui/tabs/tab_strip_model.h"
12#include "chrome/common/url_constants.h"
13#include "chrome/test/base/in_process_browser_test.h"
14#include "content/public/browser/notification_service.h"
15#include "content/public/browser/notification_types.h"
16#include "content/public/test/test_utils.h"
17#include "url/gurl.h"
18
19using content::OpenURLParams;
20
21namespace {
22
23typedef InProcessBrowserTest OomPriorityManagerTest;
24
25IN_PROC_BROWSER_TEST_F(OomPriorityManagerTest, OomPriorityManagerBasics) {
26  using content::WindowedNotificationObserver;
27
28  chromeos::OomPriorityManager* oom_priority_manager =
29      g_browser_process->platform_part()->oom_priority_manager();
30  EXPECT_FALSE(oom_priority_manager->recent_tab_discard());
31
32  // Get three tabs open.
33  WindowedNotificationObserver load1(
34      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
35      content::NotificationService::AllSources());
36  OpenURLParams open1(GURL(chrome::kChromeUIAboutURL), content::Referrer(),
37                      CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false);
38  browser()->OpenURL(open1);
39  load1.Wait();
40
41  WindowedNotificationObserver load2(
42      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
43      content::NotificationService::AllSources());
44  OpenURLParams open2(GURL(chrome::kChromeUICreditsURL), content::Referrer(),
45                      NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_TYPED,
46                      false);
47  browser()->OpenURL(open2);
48  load2.Wait();
49
50  WindowedNotificationObserver load3(
51      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
52      content::NotificationService::AllSources());
53  OpenURLParams open3(GURL(chrome::kChromeUITermsURL), content::Referrer(),
54                      NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_TYPED,
55                      false);
56  browser()->OpenURL(open3);
57  load3.Wait();
58
59  EXPECT_EQ(3, browser()->tab_strip_model()->count());
60
61  // Navigate the current (third) tab to a different URL, so we can test
62  // back/forward later.
63  WindowedNotificationObserver load4(
64      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
65      content::NotificationService::AllSources());
66  OpenURLParams open4(GURL(chrome::kChromeUIVersionURL), content::Referrer(),
67                      CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
68                      false);
69  browser()->OpenURL(open4);
70  load4.Wait();
71
72  // Navigate the third tab again, such that we have three navigation entries.
73  WindowedNotificationObserver load5(
74      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
75      content::NotificationService::AllSources());
76  OpenURLParams open5(GURL("chrome://dns"), content::Referrer(),
77                      CURRENT_TAB, ui::PAGE_TRANSITION_TYPED,
78                      false);
79  browser()->OpenURL(open5);
80  load5.Wait();
81
82  EXPECT_EQ(3, browser()->tab_strip_model()->count());
83
84  // Discard a tab.  It should kill the first tab, since it was the oldest
85  // and was not selected.
86  EXPECT_TRUE(oom_priority_manager->DiscardTab());
87  EXPECT_EQ(3, browser()->tab_strip_model()->count());
88  EXPECT_TRUE(browser()->tab_strip_model()->IsTabDiscarded(0));
89  EXPECT_FALSE(browser()->tab_strip_model()->IsTabDiscarded(1));
90  EXPECT_FALSE(browser()->tab_strip_model()->IsTabDiscarded(2));
91  EXPECT_TRUE(oom_priority_manager->recent_tab_discard());
92
93  // Run discard again, make sure it kills the second tab.
94  EXPECT_TRUE(oom_priority_manager->DiscardTab());
95  EXPECT_EQ(3, browser()->tab_strip_model()->count());
96  EXPECT_TRUE(browser()->tab_strip_model()->IsTabDiscarded(0));
97  EXPECT_TRUE(browser()->tab_strip_model()->IsTabDiscarded(1));
98  EXPECT_FALSE(browser()->tab_strip_model()->IsTabDiscarded(2));
99
100  // Kill the third tab. It should not kill the last tab, since it is active
101  // tab.
102  EXPECT_FALSE(oom_priority_manager->DiscardTab());
103  EXPECT_TRUE(browser()->tab_strip_model()->IsTabDiscarded(0));
104  EXPECT_TRUE(browser()->tab_strip_model()->IsTabDiscarded(1));
105  EXPECT_FALSE(browser()->tab_strip_model()->IsTabDiscarded(2));
106
107  // Kill the third tab after making second tab active.
108  browser()->tab_strip_model()->ActivateTabAt(1, true);
109  EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
110  EXPECT_FALSE(browser()->tab_strip_model()->IsTabDiscarded(1));
111  browser()->tab_strip_model()->DiscardWebContentsAt(2);
112  EXPECT_TRUE(browser()->tab_strip_model()->IsTabDiscarded(2));
113
114  // Force creation of the FindBarController.
115  browser()->GetFindBarController();
116
117  // Select the first tab.  It should reload.
118  WindowedNotificationObserver reload1(
119      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
120      content::NotificationService::AllSources());
121  chrome::SelectNumberedTab(browser(), 0);
122  reload1.Wait();
123  // Make sure the FindBarController gets the right WebContents.
124  EXPECT_EQ(browser()->GetFindBarController()->web_contents(),
125            browser()->tab_strip_model()->GetActiveWebContents());
126  EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
127  EXPECT_FALSE(browser()->tab_strip_model()->IsTabDiscarded(0));
128  EXPECT_FALSE(browser()->tab_strip_model()->IsTabDiscarded(1));
129  EXPECT_TRUE(browser()->tab_strip_model()->IsTabDiscarded(2));
130
131  // Select the third tab. It should reload.
132  WindowedNotificationObserver reload2(
133      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
134      content::NotificationService::AllSources());
135  chrome::SelectNumberedTab(browser(), 2);
136  reload2.Wait();
137  EXPECT_EQ(2, browser()->tab_strip_model()->active_index());
138  EXPECT_FALSE(browser()->tab_strip_model()->IsTabDiscarded(0));
139  EXPECT_FALSE(browser()->tab_strip_model()->IsTabDiscarded(1));
140  EXPECT_FALSE(browser()->tab_strip_model()->IsTabDiscarded(2));
141
142  // Navigate the third tab back twice.  We used to crash here due to
143  // crbug.com/121373.
144  EXPECT_TRUE(chrome::CanGoBack(browser()));
145  EXPECT_FALSE(chrome::CanGoForward(browser()));
146  WindowedNotificationObserver back1(
147      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
148      content::NotificationService::AllSources());
149  chrome::GoBack(browser(), CURRENT_TAB);
150  back1.Wait();
151  EXPECT_TRUE(chrome::CanGoBack(browser()));
152  EXPECT_TRUE(chrome::CanGoForward(browser()));
153  WindowedNotificationObserver back2(
154      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
155      content::NotificationService::AllSources());
156  chrome::GoBack(browser(), CURRENT_TAB);
157  back2.Wait();
158  EXPECT_FALSE(chrome::CanGoBack(browser()));
159  EXPECT_TRUE(chrome::CanGoForward(browser()));
160}
161
162}  // namespace
163