| 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_MEMORY_TAB_MANAGER_H_ | 5 #ifndef CHROME_BROWSER_MEMORY_TAB_MANAGER_H_ |
| 6 #define CHROME_BROWSER_MEMORY_TAB_MANAGER_H_ | 6 #define CHROME_BROWSER_MEMORY_TAB_MANAGER_H_ |
| 7 | 7 |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <memory> | 10 #include <memory> |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 // Returns the auto-discardable state of the tab. When true, the tab is | 140 // Returns the auto-discardable state of the tab. When true, the tab is |
| 141 // eligible to be automatically discarded when critical memory pressure hits, | 141 // eligible to be automatically discarded when critical memory pressure hits, |
| 142 // otherwise the tab is ignored and will never be automatically discarded. | 142 // otherwise the tab is ignored and will never be automatically discarded. |
| 143 // Note that this property doesn't block the discarding of the tab via other | 143 // Note that this property doesn't block the discarding of the tab via other |
| 144 // methods (about:discards for instance). | 144 // methods (about:discards for instance). |
| 145 bool IsTabAutoDiscardable(content::WebContents* contents) const; | 145 bool IsTabAutoDiscardable(content::WebContents* contents) const; |
| 146 | 146 |
| 147 // Sets/clears the auto-discardable state of the tab. | 147 // Sets/clears the auto-discardable state of the tab. |
| 148 void SetTabAutoDiscardableState(content::WebContents* contents, bool state); | 148 void SetTabAutoDiscardableState(content::WebContents* contents, bool state); |
| 149 | 149 |
| 150 // Returns true when a given renderer can suspend when it is backgrounded. | 150 // Returns true when a given renderer can be purged if the specified |
| 151 // renderer is eligible for purging. |
| 152 // TODO(tasak): rename this to CanPurgeBackgroundedRenderer. |
| 151 bool CanSuspendBackgroundedRenderer(int render_process_id) const; | 153 bool CanSuspendBackgroundedRenderer(int render_process_id) const; |
| 152 | 154 |
| 153 // Returns true if |first| is considered less desirable to be killed than | 155 // Returns true if |first| is considered less desirable to be killed than |
| 154 // |second|. | 156 // |second|. |
| 155 static bool CompareTabStats(const TabStats& first, const TabStats& second); | 157 static bool CompareTabStats(const TabStats& first, const TabStats& second); |
| 156 | 158 |
| 157 // Returns a unique ID for a WebContents. Do not cast back to a pointer, as | 159 // Returns a unique ID for a WebContents. Do not cast back to a pointer, as |
| 158 // the WebContents could be deleted if the user closed the tab. | 160 // the WebContents could be deleted if the user closed the tab. |
| 159 static int64_t IdFromWebContents(content::WebContents* web_contents); | 161 static int64_t IdFromWebContents(content::WebContents* web_contents); |
| 160 | 162 |
| 161 private: | 163 private: |
| 162 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, | 164 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, PurgeBackgroundRenderer); |
| 163 ActivateTabResetPurgeAndSuspendState); | 165 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ActivateTabResetPurgeState); |
| 164 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, NextPurgeAndSuspendState); | 166 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ShouldPurgeAtDefaultTime); |
| 167 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, DefaultTimeToPurgeInCorrectRange); |
| 165 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, AutoDiscardable); | 168 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, AutoDiscardable); |
| 166 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, CanOnlyDiscardOnce); | 169 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, CanOnlyDiscardOnce); |
| 167 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ChildProcessNotifications); | 170 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ChildProcessNotifications); |
| 168 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, Comparator); | 171 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, Comparator); |
| 169 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, DiscardedTabKeepsLastActiveTime); | 172 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, DiscardedTabKeepsLastActiveTime); |
| 170 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, DiscardWebContentsAt); | 173 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, DiscardWebContentsAt); |
| 171 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, InvalidOrEmptyURL); | 174 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, InvalidOrEmptyURL); |
| 172 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, IsInternalPage); | 175 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, IsInternalPage); |
| 173 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, OomPressureListener); | 176 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, OomPressureListener); |
| 174 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ProtectPDFPages); | 177 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ProtectPDFPages); |
| 175 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ProtectRecentlyUsedTabs); | 178 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ProtectRecentlyUsedTabs); |
| 176 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ProtectVideoTabs); | 179 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ProtectVideoTabs); |
| 177 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ReloadDiscardedTabContextMenu); | 180 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ReloadDiscardedTabContextMenu); |
| 178 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, TabManagerBasics); | 181 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, TabManagerBasics); |
| 179 FRIEND_TEST_ALL_PREFIXES(TabManagerWebContentsDataTest, PurgeAndSuspendState); | |
| 180 | 182 |
| 181 // The time of the first purging after a renderer is backgrounded. | 183 // The time of the first purging after a renderer is backgrounded. |
| 182 // The initial value was chosen because most of users activate backgrounded | 184 // The initial value was chosen because most of users activate backgrounded |
| 183 // tabs within 30 minutes. (c.f. Tabs.StateTransfer.Time_Inactive_Active) | 185 // tabs within 30 minutes. (c.f. Tabs.StateTransfer.Time_Inactive_Active) |
| 184 static constexpr base::TimeDelta kDefaultTimeToFirstPurge = | 186 static constexpr base::TimeDelta kDefaultMinTimeToPurge = |
| 185 base::TimeDelta::FromMinutes(30); | 187 base::TimeDelta::FromMinutes(30); |
| 186 | 188 |
| 189 // The min/max time to purge ratio. The max time to purge is set to be |
| 190 // min time to purge times this value. |
| 191 const int kMinMaxTimeToPurgeRatio = 2; |
| 192 |
| 187 // This is needed so WebContentsData can call OnDiscardedStateChange, and | 193 // This is needed so WebContentsData can call OnDiscardedStateChange, and |
| 188 // can use PurgeAndSuspendState. | 194 // can use PurgeState. |
| 189 friend class WebContentsData; | 195 friend class WebContentsData; |
| 190 | 196 |
| 197 // Finds TabStripModel which has a WebContents whose id is the given |
| 198 // web_contents_id, and returns the WebContents index and the TabStripModel. |
| 199 int FindTabStripModelById(int64_t target_web_contents_id, |
| 200 TabStripModel** model) const; |
| 201 |
| 191 // Called by WebContentsData whenever the discard state of a WebContents | 202 // Called by WebContentsData whenever the discard state of a WebContents |
| 192 // changes, so that observers can be informed. | 203 // changes, so that observers can be informed. |
| 193 void OnDiscardedStateChange(content::WebContents* contents, | 204 void OnDiscardedStateChange(content::WebContents* contents, |
| 194 bool is_discarded); | 205 bool is_discarded); |
| 195 | 206 |
| 196 // Called by WebContentsData whenever the auto-discardable state of a | 207 // Called by WebContentsData whenever the auto-discardable state of a |
| 197 // WebContents changes, so that observers can be informed. | 208 // WebContents changes, so that observers can be informed. |
| 198 void OnAutoDiscardableStateChange(content::WebContents* contents, | 209 void OnAutoDiscardableStateChange(content::WebContents* contents, |
| 199 bool is_auto_discardable); | 210 bool is_auto_discardable); |
| 200 | 211 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 // If |active_model| is true, consider its first tab as being active. | 262 // If |active_model| is true, consider its first tab as being active. |
| 252 void AddTabStats(const TabStripModel* model, | 263 void AddTabStats(const TabStripModel* model, |
| 253 bool is_app, | 264 bool is_app, |
| 254 bool active_model, | 265 bool active_model, |
| 255 TabStatsList* stats_list) const; | 266 TabStatsList* stats_list) const; |
| 256 | 267 |
| 257 // Callback for when |update_timer_| fires. Takes care of executing the tasks | 268 // Callback for when |update_timer_| fires. Takes care of executing the tasks |
| 258 // that need to be run periodically (see comment in implementation). | 269 // that need to be run periodically (see comment in implementation). |
| 259 void UpdateTimerCallback(); | 270 void UpdateTimerCallback(); |
| 260 | 271 |
| 261 // Initially PurgeAndSuspendState is RUNNING. | |
| 262 // RUNNING => SUSPENDED | |
| 263 // - A tab has been backgrounded for more than purge-and-suspend-time | |
| 264 // seconds. | |
| 265 // SUSPENDED => RESUMED | |
| 266 // - A suspended tab is still suspended (i.e. last active time < last | |
| 267 // purge-and-suspend modified time), and | |
| 268 // - kMaxTimeRendererAllowedToBeSuspendedBeforeResume time passes since | |
| 269 // since the tab was suspended. | |
| 270 // RESUMED => SUSPENDED | |
| 271 // - A resumed tab is still backgrounded (i.e. last active time < last | |
| 272 // purge-and-suspend modified time), and | |
| 273 // - kSuspendedRendererLengthOfResumption time passes since the tab was | |
| 274 // resumed. | |
| 275 // SUSPENDED, RESUMED, RUNNING => RUNNING | |
| 276 // - When ActiveTabChaged, the newly activated tab's state will be RUNNING. | |
| 277 enum PurgeAndSuspendState { | |
| 278 RUNNING, | |
| 279 RESUMED, | |
| 280 SUSPENDED, | |
| 281 }; | |
| 282 // Returns WebContents whose contents id matches the given tab_contents_id. | 272 // Returns WebContents whose contents id matches the given tab_contents_id. |
| 283 content::WebContents* GetWebContentsById(int64_t tab_contents_id) const; | 273 content::WebContents* GetWebContentsById(int64_t tab_contents_id) const; |
| 284 | 274 |
| 285 // Returns the next state of the purge and suspend. | 275 // Returns a random time-to-purge whose min value is min_time_to_purge and max |
| 286 PurgeAndSuspendState GetNextPurgeAndSuspendState( | 276 // value is min_time_to_purge * kMinMaxTimeToPurgeRatio. |
| 287 content::WebContents* content, | 277 base::TimeDelta GetTimeToPurge(base::TimeDelta min_time_to_purge) const; |
| 288 base::TimeTicks current_time, | |
| 289 const base::TimeDelta& time_to_first_suspension) const; | |
| 290 | 278 |
| 291 // Purges and suspends renderers in backgrounded tabs. | 279 // Returns true if the tab specified by |content| is now eligible to have |
| 292 void PurgeAndSuspendBackgroundedTabs(); | 280 // its memory purged. |
| 281 bool ShouldPurgeNow(content::WebContents* content) const; |
| 282 |
| 283 // Purges renderers in backgrounded tabs if the following conditions are |
| 284 // satisfied: |
| 285 // - the renderers are not purged yet, |
| 286 // - the renderers are not playing media, |
| 287 // (CanPurgeBackgroundedRenderer returns true) |
| 288 // - the renderers are left inactive and background for time-to-purge. |
| 289 // If renderers are purged, their internal states become 'purged'. |
| 290 // The state is reset to be 'not purged' only when they are activated |
| 291 // (=ActiveTabChanged is invoked). |
| 292 void PurgeBackgroundedTabsIfNeeded(); |
| 293 | 293 |
| 294 // Does the actual discard by destroying the WebContents in |model| at |index| | 294 // Does the actual discard by destroying the WebContents in |model| at |index| |
| 295 // and replacing it by an empty one. Returns the new WebContents or NULL if | 295 // and replacing it by an empty one. Returns the new WebContents or NULL if |
| 296 // the operation fails (return value used only in testing). | 296 // the operation fails (return value used only in testing). |
| 297 content::WebContents* DiscardWebContentsAt(int index, TabStripModel* model); | 297 content::WebContents* DiscardWebContentsAt(int index, TabStripModel* model); |
| 298 | 298 |
| 299 // Called by the memory pressure listener when the memory pressure rises. | 299 // Called by the memory pressure listener when the memory pressure rises. |
| 300 void OnMemoryPressure( | 300 void OnMemoryPressure( |
| 301 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level); | 301 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level); |
| 302 | 302 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 // used for statistics normalized by usage. | 365 // used for statistics normalized by usage. |
| 366 bool recent_tab_discard_; | 366 bool recent_tab_discard_; |
| 367 | 367 |
| 368 // Whether a tab can only ever discarded once. | 368 // Whether a tab can only ever discarded once. |
| 369 bool discard_once_; | 369 bool discard_once_; |
| 370 | 370 |
| 371 // This allows protecting tabs for a certain amount of time after being | 371 // This allows protecting tabs for a certain amount of time after being |
| 372 // backgrounded. | 372 // backgrounded. |
| 373 base::TimeDelta minimum_protection_time_; | 373 base::TimeDelta minimum_protection_time_; |
| 374 | 374 |
| 375 // A backgrounded renderer will be suspended when this time passes. | 375 // A backgrounded renderer will be purged when this time passes. |
| 376 base::TimeDelta time_to_first_suspension_; | 376 base::TimeDelta min_time_to_purge_; |
| 377 | 377 |
| 378 #if defined(OS_CHROMEOS) | 378 #if defined(OS_CHROMEOS) |
| 379 std::unique_ptr<TabManagerDelegate> delegate_; | 379 std::unique_ptr<TabManagerDelegate> delegate_; |
| 380 #endif | 380 #endif |
| 381 | 381 |
| 382 // Responsible for automatically registering this class as an observer of all | 382 // Responsible for automatically registering this class as an observer of all |
| 383 // TabStripModels. Automatically tracks browsers as they come and go. | 383 // TabStripModels. Automatically tracks browsers as they come and go. |
| 384 BrowserTabStripTracker browser_tab_strip_tracker_; | 384 BrowserTabStripTracker browser_tab_strip_tracker_; |
| 385 | 385 |
| 386 // Pointer to a test clock. If this is set, NowTicks() returns the value of | 386 // Pointer to a test clock. If this is set, NowTicks() returns the value of |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 426 | 426 |
| 427 // Weak pointer factory used for posting delayed tasks to task_runner_. | 427 // Weak pointer factory used for posting delayed tasks to task_runner_. |
| 428 base::WeakPtrFactory<TabManager> weak_ptr_factory_; | 428 base::WeakPtrFactory<TabManager> weak_ptr_factory_; |
| 429 | 429 |
| 430 DISALLOW_COPY_AND_ASSIGN(TabManager); | 430 DISALLOW_COPY_AND_ASSIGN(TabManager); |
| 431 }; | 431 }; |
| 432 | 432 |
| 433 } // namespace memory | 433 } // namespace memory |
| 434 | 434 |
| 435 #endif // CHROME_BROWSER_MEMORY_TAB_MANAGER_H_ | 435 #endif // CHROME_BROWSER_MEMORY_TAB_MANAGER_H_ |
| OLD | NEW |