ExtensionSyncService: listen for relevant changes instead of being explicitly called...
[chromium-blink-merge.git] / chrome / browser / memory / oom_priority_manager_browsertest.cc
blobe651299e17ec98e9f41759ef58e2c13a345605aa
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 "base/command_line.h"
6 #include "base/memory/memory_pressure_listener.h"
7 #include "chrome/browser/browser_process.h"
8 #include "chrome/browser/memory/oom_priority_manager.h"
9 #include "chrome/browser/ui/browser.h"
10 #include "chrome/browser/ui/browser_commands.h"
11 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
12 #include "chrome/browser/ui/tabs/tab_strip_model.h"
13 #include "chrome/common/chrome_switches.h"
14 #include "chrome/common/url_constants.h"
15 #include "chrome/test/base/in_process_browser_test.h"
16 #include "content/public/browser/notification_service.h"
17 #include "content/public/browser/notification_types.h"
18 #include "content/public/test/test_utils.h"
19 #include "url/gurl.h"
21 using content::OpenURLParams;
23 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
25 namespace memory {
26 namespace {
28 class OomPriorityManagerTest : public InProcessBrowserTest {
29 public:
30 // Tab discarding is enabled by default on CrOS, on other platforms, force it
31 // by setting the command line flag.
32 void SetUpCommandLine(base::CommandLine* command_line) override {
33 #if !defined(OS_CHROMEOS)
34 command_line->AppendSwitch(switches::kEnableTabDiscarding);
35 #endif
40 IN_PROC_BROWSER_TEST_F(OomPriorityManagerTest, OomPriorityManagerBasics) {
41 using content::WindowedNotificationObserver;
42 OomPriorityManager* oom_priority_manager =
43 g_browser_process->GetOomPriorityManager();
44 ASSERT_TRUE(oom_priority_manager);
45 EXPECT_FALSE(oom_priority_manager->recent_tab_discard());
47 // Get three tabs open.
48 WindowedNotificationObserver load1(
49 content::NOTIFICATION_NAV_ENTRY_COMMITTED,
50 content::NotificationService::AllSources());
51 OpenURLParams open1(GURL(chrome::kChromeUIAboutURL), content::Referrer(),
52 CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false);
53 browser()->OpenURL(open1);
54 load1.Wait();
56 WindowedNotificationObserver load2(
57 content::NOTIFICATION_NAV_ENTRY_COMMITTED,
58 content::NotificationService::AllSources());
59 OpenURLParams open2(GURL(chrome::kChromeUICreditsURL), content::Referrer(),
60 NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_TYPED, false);
61 browser()->OpenURL(open2);
62 load2.Wait();
64 WindowedNotificationObserver load3(
65 content::NOTIFICATION_NAV_ENTRY_COMMITTED,
66 content::NotificationService::AllSources());
67 OpenURLParams open3(GURL(chrome::kChromeUITermsURL), content::Referrer(),
68 NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_TYPED, false);
69 browser()->OpenURL(open3);
70 load3.Wait();
72 EXPECT_EQ(3, browser()->tab_strip_model()->count());
74 // Navigate the current (third) tab to a different URL, so we can test
75 // back/forward later.
76 WindowedNotificationObserver load4(
77 content::NOTIFICATION_NAV_ENTRY_COMMITTED,
78 content::NotificationService::AllSources());
79 OpenURLParams open4(GURL(chrome::kChromeUIVersionURL), content::Referrer(),
80 CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false);
81 browser()->OpenURL(open4);
82 load4.Wait();
84 // Navigate the third tab again, such that we have three navigation entries.
85 WindowedNotificationObserver load5(
86 content::NOTIFICATION_NAV_ENTRY_COMMITTED,
87 content::NotificationService::AllSources());
88 OpenURLParams open5(GURL("chrome://dns"), content::Referrer(), CURRENT_TAB,
89 ui::PAGE_TRANSITION_TYPED, false);
90 browser()->OpenURL(open5);
91 load5.Wait();
93 EXPECT_EQ(3, browser()->tab_strip_model()->count());
95 // Discard a tab. It should kill the first tab, since it was the oldest
96 // and was not selected.
97 EXPECT_TRUE(oom_priority_manager->DiscardTab());
98 EXPECT_EQ(3, browser()->tab_strip_model()->count());
99 EXPECT_TRUE(browser()->tab_strip_model()->IsTabDiscarded(0));
100 EXPECT_FALSE(browser()->tab_strip_model()->IsTabDiscarded(1));
101 EXPECT_FALSE(browser()->tab_strip_model()->IsTabDiscarded(2));
102 EXPECT_TRUE(oom_priority_manager->recent_tab_discard());
104 // Run discard again, make sure it kills the second tab.
105 EXPECT_TRUE(oom_priority_manager->DiscardTab());
106 EXPECT_EQ(3, browser()->tab_strip_model()->count());
107 EXPECT_TRUE(browser()->tab_strip_model()->IsTabDiscarded(0));
108 EXPECT_TRUE(browser()->tab_strip_model()->IsTabDiscarded(1));
109 EXPECT_FALSE(browser()->tab_strip_model()->IsTabDiscarded(2));
111 // Kill the third tab. It should not kill the last tab, since it is active
112 // tab.
113 EXPECT_FALSE(oom_priority_manager->DiscardTab());
114 EXPECT_TRUE(browser()->tab_strip_model()->IsTabDiscarded(0));
115 EXPECT_TRUE(browser()->tab_strip_model()->IsTabDiscarded(1));
116 EXPECT_FALSE(browser()->tab_strip_model()->IsTabDiscarded(2));
118 // Kill the third tab after making second tab active.
119 browser()->tab_strip_model()->ActivateTabAt(1, true);
120 EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
121 EXPECT_FALSE(browser()->tab_strip_model()->IsTabDiscarded(1));
122 browser()->tab_strip_model()->DiscardWebContentsAt(2);
123 EXPECT_TRUE(browser()->tab_strip_model()->IsTabDiscarded(2));
125 // Force creation of the FindBarController.
126 browser()->GetFindBarController();
128 // Select the first tab. It should reload.
129 WindowedNotificationObserver reload1(
130 content::NOTIFICATION_NAV_ENTRY_COMMITTED,
131 content::NotificationService::AllSources());
132 chrome::SelectNumberedTab(browser(), 0);
133 reload1.Wait();
134 // Make sure the FindBarController gets the right WebContents.
135 EXPECT_EQ(browser()->GetFindBarController()->web_contents(),
136 browser()->tab_strip_model()->GetActiveWebContents());
137 EXPECT_EQ(0, 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_TRUE(browser()->tab_strip_model()->IsTabDiscarded(2));
142 // Select the third tab. It should reload.
143 WindowedNotificationObserver reload2(
144 content::NOTIFICATION_NAV_ENTRY_COMMITTED,
145 content::NotificationService::AllSources());
146 chrome::SelectNumberedTab(browser(), 2);
147 reload2.Wait();
148 EXPECT_EQ(2, browser()->tab_strip_model()->active_index());
149 EXPECT_FALSE(browser()->tab_strip_model()->IsTabDiscarded(0));
150 EXPECT_FALSE(browser()->tab_strip_model()->IsTabDiscarded(1));
151 EXPECT_FALSE(browser()->tab_strip_model()->IsTabDiscarded(2));
153 // Navigate the third tab back twice. We used to crash here due to
154 // crbug.com/121373.
155 EXPECT_TRUE(chrome::CanGoBack(browser()));
156 EXPECT_FALSE(chrome::CanGoForward(browser()));
157 WindowedNotificationObserver back1(
158 content::NOTIFICATION_NAV_ENTRY_COMMITTED,
159 content::NotificationService::AllSources());
160 chrome::GoBack(browser(), CURRENT_TAB);
161 back1.Wait();
162 EXPECT_TRUE(chrome::CanGoBack(browser()));
163 EXPECT_TRUE(chrome::CanGoForward(browser()));
164 WindowedNotificationObserver back2(
165 content::NOTIFICATION_NAV_ENTRY_COMMITTED,
166 content::NotificationService::AllSources());
167 chrome::GoBack(browser(), CURRENT_TAB);
168 back2.Wait();
169 EXPECT_FALSE(chrome::CanGoBack(browser()));
170 EXPECT_TRUE(chrome::CanGoForward(browser()));
173 // Test that the MemoryPressureListener event is properly triggering a tab
174 // discard upon |MEMORY_PRESSURE_LEVEL_CRITICAL| event.
175 IN_PROC_BROWSER_TEST_F(OomPriorityManagerTest, OomPressureListener) {
176 OomPriorityManager* oom_priority_manager =
177 g_browser_process->GetOomPriorityManager();
178 ASSERT_TRUE(oom_priority_manager);
180 // Get three tabs open.
181 content::WindowedNotificationObserver load1(
182 content::NOTIFICATION_NAV_ENTRY_COMMITTED,
183 content::NotificationService::AllSources());
184 OpenURLParams open1(GURL(chrome::kChromeUIAboutURL), content::Referrer(),
185 CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false);
186 browser()->OpenURL(open1);
187 load1.Wait();
189 content::WindowedNotificationObserver load2(
190 content::NOTIFICATION_NAV_ENTRY_COMMITTED,
191 content::NotificationService::AllSources());
192 OpenURLParams open2(GURL(chrome::kChromeUICreditsURL), content::Referrer(),
193 NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_TYPED, false);
194 browser()->OpenURL(open2);
195 load2.Wait();
196 EXPECT_FALSE(oom_priority_manager->recent_tab_discard());
198 // Nothing should happen with a moderate memory pressure event.
199 base::MemoryPressureListener::NotifyMemoryPressure(
200 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
201 EXPECT_FALSE(oom_priority_manager->recent_tab_discard());
203 // A critical memory pressure event should discard a tab.
204 base::MemoryPressureListener::NotifyMemoryPressure(
205 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
206 // Coming here, an asynchronous operation will collect system stats. Once in,
207 // a tab should get discarded. As such we need to give it 10s time to discard.
208 const int kTimeoutTimeInMS = 10000;
209 const int kIntervalTimeInMS = 5;
210 int timeout = kTimeoutTimeInMS / kIntervalTimeInMS;
211 while (--timeout) {
212 base::PlatformThread::Sleep(
213 base::TimeDelta::FromMilliseconds(kIntervalTimeInMS));
214 base::RunLoop().RunUntilIdle();
215 if (oom_priority_manager->recent_tab_discard())
216 break;
218 EXPECT_TRUE(oom_priority_manager->recent_tab_discard());
221 } // namespace
222 } // namespace memory
224 #endif // OS_WIN || OS_CHROMEOS