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 tab has finished loading. TabManager can | |
| 159 // decide which tab to load next. | |
| 160 void HasFinishedLoadingTab(content::WebContents* contents); | |
| 161 | |
| 149 // Returns true if |first| is considered less desirable to be killed than | 162 // Returns true if |first| is considered less desirable to be killed than |
| 150 // |second|. | 163 // |second|. |
| 151 static bool CompareTabStats(const TabStats& first, const TabStats& second); | 164 static bool CompareTabStats(const TabStats& first, const TabStats& second); |
| 152 | 165 |
| 153 // Returns a unique ID for a WebContents. Do not cast back to a pointer, as | 166 // 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. | 167 // the WebContents could be deleted if the user closed the tab. |
| 155 static int64_t IdFromWebContents(content::WebContents* web_contents); | 168 static int64_t IdFromWebContents(content::WebContents* web_contents); |
| 156 | 169 |
| 170 // Returns true if the |url| represents an internal Chrome web UI page that | |
| 171 // can be easily reloaded and hence makes a good choice to discard. | |
| 172 static bool IsInternalPage(const GURL& url); | |
| 173 | |
| 157 private: | 174 private: |
| 158 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, PurgeBackgroundRenderer); | 175 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, PurgeBackgroundRenderer); |
| 159 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ActivateTabResetPurgeState); | 176 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ActivateTabResetPurgeState); |
| 160 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ShouldPurgeAtDefaultTime); | 177 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ShouldPurgeAtDefaultTime); |
| 161 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, DefaultTimeToPurgeInCorrectRange); | 178 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, DefaultTimeToPurgeInCorrectRange); |
| 162 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, AutoDiscardable); | 179 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, AutoDiscardable); |
| 163 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, CanOnlyDiscardOnce); | 180 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, CanOnlyDiscardOnce); |
| 164 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ChildProcessNotifications); | 181 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ChildProcessNotifications); |
| 165 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, Comparator); | 182 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, Comparator); |
| 166 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, DiscardedTabKeepsLastActiveTime); | 183 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, DiscardedTabKeepsLastActiveTime); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 198 void OnDiscardedStateChange(content::WebContents* contents, | 215 void OnDiscardedStateChange(content::WebContents* contents, |
| 199 bool is_discarded); | 216 bool is_discarded); |
| 200 | 217 |
| 201 // Called by WebContentsData whenever the auto-discardable state of a | 218 // Called by WebContentsData whenever the auto-discardable state of a |
| 202 // WebContents changes, so that observers can be informed. | 219 // WebContents changes, so that observers can be informed. |
| 203 void OnAutoDiscardableStateChange(content::WebContents* contents, | 220 void OnAutoDiscardableStateChange(content::WebContents* contents, |
| 204 bool is_auto_discardable); | 221 bool is_auto_discardable); |
| 205 | 222 |
| 206 static void PurgeMemoryAndDiscardTab(); | 223 static void PurgeMemoryAndDiscardTab(); |
| 207 | 224 |
| 208 // Returns true if the |url| represents an internal Chrome web UI page that | |
| 209 // can be easily reloaded and hence makes a good choice to discard. | |
| 210 static bool IsInternalPage(const GURL& url); | |
| 211 | |
| 212 // Records UMA histogram statistics for a tab discard. Record statistics for | 225 // Records UMA histogram statistics for a tab discard. Record statistics for |
| 213 // user triggered discards via chrome://discards/ because that allows to | 226 // user triggered discards via chrome://discards/ because that allows to |
| 214 // manually test the system. | 227 // manually test the system. |
| 215 void RecordDiscardStatistics(); | 228 void RecordDiscardStatistics(); |
| 216 | 229 |
| 217 // Record whether an out of memory occured during a recent time interval. This | 230 // Record whether an out of memory occured during a recent time interval. This |
| 218 // allows the normalization of low memory statistics versus usage. | 231 // allows the normalization of low memory statistics versus usage. |
| 219 void RecordRecentTabDiscard(); | 232 void RecordRecentTabDiscard(); |
| 220 | 233 |
| 221 // Purges data structures in the browser that can be easily recomputed. | 234 // Purges data structures in the browser that can be easily recomputed. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 295 // for more details. | 308 // for more details. |
| 296 base::TimeTicks NowTicks() const; | 309 base::TimeTicks NowTicks() const; |
| 297 | 310 |
| 298 // Implementation of DiscardTab. Returns null if no tab was discarded. | 311 // Implementation of DiscardTab. Returns null if no tab was discarded. |
| 299 // Otherwise returns the new web_contents of the discarded tab. | 312 // Otherwise returns the new web_contents of the discarded tab. |
| 300 content::WebContents* DiscardTabImpl(); | 313 content::WebContents* DiscardTabImpl(); |
| 301 | 314 |
| 302 // Returns true if tabs can be discarded only once. | 315 // Returns true if tabs can be discarded only once. |
| 303 bool CanOnlyDiscardOnce() const; | 316 bool CanOnlyDiscardOnce() const; |
| 304 | 317 |
| 318 // Returns true if the navigation should be delay. | |
|
chrisha
2017/06/15 21:02:24
delayed*
Zhen Wang
2017/06/19 23:00:12
Done.
| |
| 319 bool ShouldDelayNavigation( | |
| 320 content::NavigationHandle* navigation_handle) const; | |
| 321 | |
| 322 // Resume the tab's navigation if it is pending right now. | |
| 323 void ResumeTabNavigationIfNeeded(content::WebContents* contents); | |
| 324 | |
| 305 // Timer to periodically update the stats of the renderers. | 325 // Timer to periodically update the stats of the renderers. |
| 306 base::RepeatingTimer update_timer_; | 326 base::RepeatingTimer update_timer_; |
| 307 | 327 |
| 308 // Timer to periodically report whether a tab has been discarded since the | 328 // Timer to periodically report whether a tab has been discarded since the |
| 309 // last time the timer has fired. | 329 // last time the timer has fired. |
| 310 base::RepeatingTimer recent_tab_discard_timer_; | 330 base::RepeatingTimer recent_tab_discard_timer_; |
| 311 | 331 |
| 312 // A listener to global memory pressure events. | 332 // A listener to global memory pressure events. |
| 313 std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; | 333 std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; |
| 314 | 334 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 358 // associated Browser objects are crawled. The first of these is considered to | 378 // associated Browser objects are crawled. The first of these is considered to |
| 359 // be the 'active' tab strip model. | 379 // be the 'active' tab strip model. |
| 360 // TODO(chrisha): Factor out tab-strip model enumeration to a helper class, | 380 // TODO(chrisha): Factor out tab-strip model enumeration to a helper class, |
| 361 // and make a delegate that centralizes all testing seams. | 381 // and make a delegate that centralizes all testing seams. |
| 362 using TestTabStripModel = std::pair<const TabStripModel*, bool>; | 382 using TestTabStripModel = std::pair<const TabStripModel*, bool>; |
| 363 std::vector<TestTabStripModel> test_tab_strip_models_; | 383 std::vector<TestTabStripModel> test_tab_strip_models_; |
| 364 | 384 |
| 365 // List of observers that will receive notifications on state changes. | 385 // List of observers that will receive notifications on state changes. |
| 366 base::ObserverList<TabManagerObserver> observers_; | 386 base::ObserverList<TabManagerObserver> observers_; |
| 367 | 387 |
| 388 // The list of navigation handles that are throttled. | |
| 389 std::vector<content::NavigationHandle*> pending_navigations_; | |
| 390 | |
| 391 // The tab that is currently loading. If multiple tabs are loading | |
| 392 // simultaneously, it corresponds to the lastest one. We will consider loading | |
| 393 // the next background tab when this tab has finished loading. | |
| 394 // TODO(zhenw): This is a native algorithm. It should be updated to use | |
|
nasko
2017/06/15 20:01:58
nit: Did you mean "naive" instead of "native"?
Zhen Wang
2017/06/19 23:00:12
Right. Updated to naive. Thanks for catching this!
| |
| 395 // smarter ways, e.g., making sure all loading tabs have finished. | |
| 396 content::WebContents* loading_contents_; | |
|
chrisha
2017/06/15 21:02:24
We have loading states being worked on in another
Zhen Wang
2017/06/19 23:00:12
Now I have rebased this CL on the other CL and I c
chrisha
2017/06/20 18:26:54
sgtm
| |
| 397 | |
| 368 // Weak pointer factory used for posting delayed tasks. | 398 // Weak pointer factory used for posting delayed tasks. |
| 369 base::WeakPtrFactory<TabManager> weak_ptr_factory_; | 399 base::WeakPtrFactory<TabManager> weak_ptr_factory_; |
| 370 | 400 |
| 371 DISALLOW_COPY_AND_ASSIGN(TabManager); | 401 DISALLOW_COPY_AND_ASSIGN(TabManager); |
| 372 }; | 402 }; |
| 373 | 403 |
| 374 } // namespace resource_coordinator | 404 } // namespace resource_coordinator |
| 375 | 405 |
| 376 #endif // CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_MANAGER_H_ | 406 #endif // CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_MANAGER_H_ |
| OLD | NEW |