Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_MANAGER_H_ | 5 #ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_MANAGER_H_ |
| 6 #define CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_MANAGER_H_ | 6 #define CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_MANAGER_H_ |
| 7 | 7 |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <memory> | 10 #include <memory> |
| 11 #include <string> | 11 #include <string> |
| 12 #include <utility> | 12 #include <utility> |
| 13 #include <vector> | 13 #include <vector> |
| 14 | 14 |
| 15 #include "base/callback.h" | 15 #include "base/callback.h" |
| 16 #include "base/compiler_specific.h" | 16 #include "base/compiler_specific.h" |
| 17 #include "base/gtest_prod_util.h" | 17 #include "base/gtest_prod_util.h" |
| 18 #include "base/macros.h" | 18 #include "base/macros.h" |
| 19 #include "base/memory/memory_pressure_listener.h" | 19 #include "base/memory/memory_pressure_listener.h" |
| 20 #include "base/memory/weak_ptr.h" | 20 #include "base/memory/weak_ptr.h" |
| 21 #include "base/observer_list.h" | 21 #include "base/observer_list.h" |
| 22 #include "base/strings/string16.h" | 22 #include "base/strings/string16.h" |
| 23 #include "base/timer/timer.h" | 23 #include "base/timer/timer.h" |
| 24 #include "build/build_config.h" | 24 #include "build/build_config.h" |
| 25 #include "chrome/browser/resource_coordinator/tab_manager_observer.h" | 25 #include "chrome/browser/resource_coordinator/tab_manager_observer.h" |
| 26 #include "chrome/browser/resource_coordinator/tab_stats.h" | 26 #include "chrome/browser/resource_coordinator/tab_stats.h" |
| 27 #include "chrome/browser/ui/browser_tab_strip_tracker.h" | 27 #include "chrome/browser/ui/browser_tab_strip_tracker.h" |
| 28 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h" | 28 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h" |
| 29 #include "content/public/browser/navigation_throttle.h" | |
| 29 | 30 |
| 30 class BrowserList; | 31 class BrowserList; |
| 31 class GURL; | 32 class GURL; |
| 32 class TabStripModel; | 33 class TabStripModel; |
| 33 | 34 |
| 34 namespace base { | 35 namespace base { |
| 35 class TickClock; | 36 class TickClock; |
| 36 } | 37 } |
| 37 | 38 |
| 38 namespace content { | 39 namespace content { |
| 40 class NavigationHandle; | |
| 39 class WebContents; | 41 class WebContents; |
| 40 } | 42 } |
| 41 | 43 |
| 42 namespace resource_coordinator { | 44 namespace resource_coordinator { |
| 43 | 45 |
| 44 #if defined(OS_CHROMEOS) | 46 #if defined(OS_CHROMEOS) |
| 45 class TabManagerDelegate; | 47 class TabManagerDelegate; |
| 46 #endif | 48 #endif |
| 47 | 49 |
| 48 // The TabManager periodically updates (see | 50 // The TabManager periodically updates (see |
| 49 // |kAdjustmentIntervalSeconds| in the source) the status of renderers | 51 // |kAdjustmentIntervalSeconds| in the source) the status of renderers |
| 50 // which are then used by the algorithm embedded here for priority in being | 52 // which are then used by the algorithm embedded here for priority in being |
| 51 // killed upon OOM conditions. | 53 // killed upon OOM conditions. |
| 52 // | 54 // |
| 53 // The algorithm used favors killing tabs that are not selected, not pinned, | 55 // The algorithm used favors killing tabs that are not selected, not pinned, |
| 54 // and have been idle for longest, in that order of priority. | 56 // and have been idle for longest, in that order of priority. |
| 55 // | 57 // |
| 56 // On Chrome OS (via the delegate), the kernel (via /proc/<pid>/oom_score_adj) | 58 // On Chrome OS (via the delegate), the kernel (via /proc/<pid>/oom_score_adj) |
| 57 // will be informed of each renderer's score, which is based on the status, so | 59 // will be informed of each renderer's score, which is based on the status, so |
| 58 // in case Chrome is not able to relieve the pressure quickly enough and the | 60 // in case Chrome is not able to relieve the pressure quickly enough and the |
| 59 // kernel is forced to kill processes, it will be able to do so using the same | 61 // kernel is forced to kill processes, it will be able to do so using the same |
| 60 // algorithm as the one used here. | 62 // algorithm as the one used here. |
| 61 // | 63 // |
| 64 // The TabManager also delays background tabs' navigation when needed in order | |
| 65 // to improve users' experience with the foreground tab. | |
| 66 // | |
| 62 // Note that the browser tests are only active for platforms that use | 67 // Note that the browser tests are only active for platforms that use |
| 63 // TabManager (CrOS only for now) and need to be adjusted accordingly if | 68 // TabManager (CrOS only for now) and need to be adjusted accordingly if |
| 64 // support for new platforms is added. | 69 // support for new platforms is added. |
| 65 class TabManager : public TabStripModelObserver { | 70 class TabManager : public TabStripModelObserver { |
| 66 public: | 71 public: |
| 67 // Needs to be public for DEFINE_WEB_CONTENTS_USER_DATA_KEY. | 72 // Needs to be public for DEFINE_WEB_CONTENTS_USER_DATA_KEY. |
| 68 class WebContentsData; | 73 class WebContentsData; |
| 69 | 74 |
| 70 TabManager(); | 75 TabManager(); |
| 71 ~TabManager() override; | 76 ~TabManager() override; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 139 bool IsTabAutoDiscardable(content::WebContents* contents) const; | 144 bool IsTabAutoDiscardable(content::WebContents* contents) const; |
| 140 | 145 |
| 141 // Sets/clears the auto-discardable state of the tab. | 146 // Sets/clears the auto-discardable state of the tab. |
| 142 void SetTabAutoDiscardableState(content::WebContents* contents, bool state); | 147 void SetTabAutoDiscardableState(content::WebContents* contents, bool state); |
| 143 | 148 |
| 144 // Returns true when a given renderer can be purged if the specified | 149 // Returns true when a given renderer can be purged if the specified |
| 145 // renderer is eligible for purging. | 150 // renderer is eligible for purging. |
| 146 // TODO(tasak): rename this to CanPurgeBackgroundedRenderer. | 151 // TODO(tasak): rename this to CanPurgeBackgroundedRenderer. |
| 147 bool CanSuspendBackgroundedRenderer(int render_process_id) const; | 152 bool CanSuspendBackgroundedRenderer(int render_process_id) const; |
| 148 | 153 |
| 154 // Maybe throttle a tab's navigation based on current system status. | |
| 155 content::NavigationThrottle::ThrottleCheckResult MaybeThrottleNavigation( | |
| 156 content::NavigationHandle* navigation_handle); | |
| 157 | |
| 158 // Notifies TabManager that one navigation has finished. TabManager should | |
| 159 // clean up the navigation handles bookkept before. | |
|
nasko
2017/06/20 15:59:39
nit: s/navigation handles/NavigationHandle objects
Zhen Wang
2017/07/06 18:26:12
Done.
| |
| 160 void OnNavigationDone(content::NavigationHandle* navigation_handle); | |
| 161 | |
| 162 // Notifies TabManager that one tab has finished loading. TabManager can | |
| 163 // decide which tab to load next. | |
| 164 void OnLoadingDone(content::WebContents* contents); | |
| 165 | |
| 166 // Notifies TabManager that one tab WebContents has been destroyed. TabManager | |
| 167 // needs to clean up data related to that tab. | |
| 168 void OnWebContentsDestroyed(content::WebContents* contents); | |
| 169 | |
| 149 // Returns true if |first| is considered less desirable to be killed than | 170 // Returns true if |first| is considered less desirable to be killed than |
| 150 // |second|. | 171 // |second|. |
| 151 static bool CompareTabStats(const TabStats& first, const TabStats& second); | 172 static bool CompareTabStats(const TabStats& first, const TabStats& second); |
| 152 | 173 |
| 153 // Returns a unique ID for a WebContents. Do not cast back to a pointer, as | 174 // Returns a unique ID for a WebContents. Do not cast back to a pointer, as |
| 154 // the WebContents could be deleted if the user closed the tab. | 175 // the WebContents could be deleted if the user closed the tab. |
| 155 static int64_t IdFromWebContents(content::WebContents* web_contents); | 176 static int64_t IdFromWebContents(content::WebContents* web_contents); |
| 156 | 177 |
| 178 // Returns true if the |url| represents an internal Chrome web UI page that | |
| 179 // can be easily reloaded and hence makes a good choice to discard. | |
| 180 static bool IsInternalPage(const GURL& url); | |
| 181 | |
| 157 private: | 182 private: |
| 158 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, PurgeBackgroundRenderer); | 183 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, PurgeBackgroundRenderer); |
| 159 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ActivateTabResetPurgeState); | 184 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ActivateTabResetPurgeState); |
| 160 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ShouldPurgeAtDefaultTime); | 185 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ShouldPurgeAtDefaultTime); |
| 161 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, DefaultTimeToPurgeInCorrectRange); | 186 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, DefaultTimeToPurgeInCorrectRange); |
| 162 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, AutoDiscardable); | 187 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, AutoDiscardable); |
| 163 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, CanOnlyDiscardOnce); | 188 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, CanOnlyDiscardOnce); |
| 164 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ChildProcessNotifications); | 189 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ChildProcessNotifications); |
| 165 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, Comparator); | 190 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, Comparator); |
| 166 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, DiscardedTabKeepsLastActiveTime); | 191 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, DiscardedTabKeepsLastActiveTime); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 199 void OnDiscardedStateChange(content::WebContents* contents, | 224 void OnDiscardedStateChange(content::WebContents* contents, |
| 200 bool is_discarded); | 225 bool is_discarded); |
| 201 | 226 |
| 202 // Called by WebContentsData whenever the auto-discardable state of a | 227 // Called by WebContentsData whenever the auto-discardable state of a |
| 203 // WebContents changes, so that observers can be informed. | 228 // WebContents changes, so that observers can be informed. |
| 204 void OnAutoDiscardableStateChange(content::WebContents* contents, | 229 void OnAutoDiscardableStateChange(content::WebContents* contents, |
| 205 bool is_auto_discardable); | 230 bool is_auto_discardable); |
| 206 | 231 |
| 207 static void PurgeMemoryAndDiscardTab(); | 232 static void PurgeMemoryAndDiscardTab(); |
| 208 | 233 |
| 209 // Returns true if the |url| represents an internal Chrome web UI page that | |
| 210 // can be easily reloaded and hence makes a good choice to discard. | |
| 211 static bool IsInternalPage(const GURL& url); | |
| 212 | |
| 213 // Records UMA histogram statistics for a tab discard. Record statistics for | 234 // Records UMA histogram statistics for a tab discard. Record statistics for |
| 214 // user triggered discards via chrome://discards/ because that allows to | 235 // user triggered discards via chrome://discards/ because that allows to |
| 215 // manually test the system. | 236 // manually test the system. |
| 216 void RecordDiscardStatistics(); | 237 void RecordDiscardStatistics(); |
| 217 | 238 |
| 218 // Record whether an out of memory occured during a recent time interval. This | 239 // Record whether an out of memory occured during a recent time interval. This |
| 219 // allows the normalization of low memory statistics versus usage. | 240 // allows the normalization of low memory statistics versus usage. |
| 220 void RecordRecentTabDiscard(); | 241 void RecordRecentTabDiscard(); |
| 221 | 242 |
| 222 // Purges data structures in the browser that can be easily recomputed. | 243 // Purges data structures in the browser that can be easily recomputed. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 296 // for more details. | 317 // for more details. |
| 297 base::TimeTicks NowTicks() const; | 318 base::TimeTicks NowTicks() const; |
| 298 | 319 |
| 299 // Implementation of DiscardTab. Returns null if no tab was discarded. | 320 // Implementation of DiscardTab. Returns null if no tab was discarded. |
| 300 // Otherwise returns the new web_contents of the discarded tab. | 321 // Otherwise returns the new web_contents of the discarded tab. |
| 301 content::WebContents* DiscardTabImpl(); | 322 content::WebContents* DiscardTabImpl(); |
| 302 | 323 |
| 303 // Returns true if tabs can be discarded only once. | 324 // Returns true if tabs can be discarded only once. |
| 304 bool CanOnlyDiscardOnce() const; | 325 bool CanOnlyDiscardOnce() const; |
| 305 | 326 |
| 327 // Returns true if the navigation should be delayed. | |
| 328 bool ShouldDelayNavigation( | |
| 329 content::NavigationHandle* navigation_handle) const; | |
| 330 | |
| 331 // Start loading the next background tab if needed. | |
| 332 void LoadNextBackgroundTabIfNeeded(); | |
| 333 | |
| 334 // Resume the tab's navigation if it is pending right now. | |
| 335 void ResumeTabNavigationIfNeeded(content::WebContents* contents); | |
| 336 | |
| 337 // Resume navigation. | |
| 338 void ResumeNavigation(content::NavigationHandle* navigation_handle); | |
| 339 | |
| 340 // Remove the pending navigation for the provided web contents. Return the | |
|
nasko
2017/06/20 15:59:39
nit: s/web contents/WebContents/
Zhen Wang
2017/07/06 18:26:12
Done.
| |
| 341 // removed navigation handle. Return nullptr if not exists. | |
|
chrisha
2017/06/20 18:26:54
if it doesn't exist.
Zhen Wang
2017/07/06 18:26:12
Done.
| |
| 342 content::NavigationHandle* RemovePendingNavigationIfNeeded( | |
| 343 content::WebContents* contents); | |
| 344 | |
| 306 // Timer to periodically update the stats of the renderers. | 345 // Timer to periodically update the stats of the renderers. |
| 307 base::RepeatingTimer update_timer_; | 346 base::RepeatingTimer update_timer_; |
| 308 | 347 |
| 309 // Timer to periodically report whether a tab has been discarded since the | 348 // Timer to periodically report whether a tab has been discarded since the |
| 310 // last time the timer has fired. | 349 // last time the timer has fired. |
| 311 base::RepeatingTimer recent_tab_discard_timer_; | 350 base::RepeatingTimer recent_tab_discard_timer_; |
| 312 | 351 |
| 313 // A listener to global memory pressure events. | 352 // A listener to global memory pressure events. |
| 314 std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; | 353 std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; |
| 315 | 354 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 359 // associated Browser objects are crawled. The first of these is considered to | 398 // associated Browser objects are crawled. The first of these is considered to |
| 360 // be the 'active' tab strip model. | 399 // be the 'active' tab strip model. |
| 361 // TODO(chrisha): Factor out tab-strip model enumeration to a helper class, | 400 // TODO(chrisha): Factor out tab-strip model enumeration to a helper class, |
| 362 // and make a delegate that centralizes all testing seams. | 401 // and make a delegate that centralizes all testing seams. |
| 363 using TestTabStripModel = std::pair<const TabStripModel*, bool>; | 402 using TestTabStripModel = std::pair<const TabStripModel*, bool>; |
| 364 std::vector<TestTabStripModel> test_tab_strip_models_; | 403 std::vector<TestTabStripModel> test_tab_strip_models_; |
| 365 | 404 |
| 366 // List of observers that will receive notifications on state changes. | 405 // List of observers that will receive notifications on state changes. |
| 367 base::ObserverList<TabManagerObserver> observers_; | 406 base::ObserverList<TabManagerObserver> observers_; |
| 368 | 407 |
| 408 // The list of navigation handles that are delayed. | |
| 409 std::vector<content::NavigationHandle*> pending_navigations_; | |
| 410 | |
| 411 // The tabs that are currently loading. We will consider loading the next | |
| 412 // background tab when these tabs have finished loading or a background tab | |
| 413 // is brought to foreground. | |
| 414 std::set<content::WebContents*> loading_contents_; | |
| 415 | |
| 369 // Weak pointer factory used for posting delayed tasks. | 416 // Weak pointer factory used for posting delayed tasks. |
| 370 base::WeakPtrFactory<TabManager> weak_ptr_factory_; | 417 base::WeakPtrFactory<TabManager> weak_ptr_factory_; |
| 371 | 418 |
| 372 DISALLOW_COPY_AND_ASSIGN(TabManager); | 419 DISALLOW_COPY_AND_ASSIGN(TabManager); |
| 373 }; | 420 }; |
| 374 | 421 |
| 375 } // namespace resource_coordinator | 422 } // namespace resource_coordinator |
| 376 | 423 |
| 377 #endif // CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_MANAGER_H_ | 424 #endif // CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_MANAGER_H_ |
| OLD | NEW |