| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_MANAGER_H_ |
| #define CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_MANAGER_H_ |
| |
| #include <stdint.h> |
| |
| #include <memory> |
| #include <vector> |
| |
| #include "base/callback_helpers.h" |
| #include "base/gtest_prod_util.h" |
| #include "base/memory/memory_pressure_listener.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/timer/timer.h" |
| #include "build/build_config.h" |
| #include "build/chromeos_buildflags.h" |
| #include "chrome/browser/resource_coordinator/lifecycle_unit.h" |
| #include "chrome/browser/resource_coordinator/lifecycle_unit_observer.h" |
| #include "chrome/browser/resource_coordinator/lifecycle_unit_source_observer.h" |
| #include "chrome/browser/resource_coordinator/lifecycle_unit_state.mojom-forward.h" |
| #include "chrome/browser/resource_coordinator/tab_lifecycle_observer.h" |
| #include "chrome/browser/resource_coordinator/tab_manager_features.h" |
| #include "chrome/browser/resource_coordinator/usage_clock.h" |
| #include "chrome/browser/sessions/session_restore_observer.h" |
| #include "content/public/browser/navigation_throttle.h" |
| #include "ui/gfx/native_widget_types.h" |
| |
| class GURL; |
| |
| namespace content { |
| class WebContents; |
| } // namespace content |
| |
| namespace resource_coordinator { |
| |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| class TabManagerDelegate; |
| #endif |
| |
| // TabManager is responsible for triggering tab lifecycle state transitions. |
| // |
| // Note that the browser tests are only active for platforms that use |
| // TabManager (CrOS only for now) and need to be adjusted accordingly if |
| // support for new platforms is added. |
| // |
| // Tabs are identified by a unique ID vended by this component. These IDs are |
| // not reused in a session. They are stable for a given conceptual tab, and will |
| // follow it through discards, reloads, tab strip operations, etc. |
| // |
| // TODO(fdoray): Rename to LifecycleManager. https://crbug.com/775644 |
| class TabManager : public LifecycleUnitObserver, |
| public LifecycleUnitSourceObserver { |
| public: |
| // Forward declaration of resource coordinator signal observer. |
| class ResourceCoordinatorSignalObserver; |
| |
| using TabDiscardDoneCB = base::ScopedClosureRunner; |
| |
| TabManager(); |
| |
| TabManager(const TabManager&) = delete; |
| TabManager& operator=(const TabManager&) = delete; |
| |
| ~TabManager() override; |
| |
| // Start the Tab Manager. |
| void Start(); |
| |
| // Returns the LifecycleUnits managed by this, sorted from less to most |
| // important to the user. It is unsafe to access a pointer in the returned |
| // vector after a LifecycleUnit has been destroyed. |
| LifecycleUnitVector GetSortedLifecycleUnits(); |
| |
| // Discards a tab to free the memory occupied by its renderer. The tab still |
| // exists in the tab-strip; clicking on it will reload it. If the |reason| is |
| // urgent, an aggressive fast-kill will be attempted if the sudden termination |
| // disablers are allowed to be ignored (e.g. On ChromeOS, we can ignore an |
| // unload handler and fast-kill the tab regardless). |
| void DiscardTab( |
| LifecycleUnitDiscardReason reason, |
| TabDiscardDoneCB tab_discard_done = TabDiscardDoneCB(base::DoNothing())); |
| |
| // Method used by the extensions API to discard tabs. If |contents| is null, |
| // discards the least important tab using DiscardTab(). Otherwise discards |
| // the given contents. Returns the new web_contents or null if no tab |
| // was discarded. |
| content::WebContents* DiscardTabByExtension(content::WebContents* contents); |
| |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| // Discards a tab in response to memory pressure. |
| void DiscardTabFromMemoryPressure(); |
| #endif |
| |
| // TODO(fdoray): Remove these methods. TabManager shouldn't know about tabs. |
| // https://crbug.com/775644 |
| void AddObserver(TabLifecycleObserver* observer); |
| void RemoveObserver(TabLifecycleObserver* observer); |
| |
| // Returns the number of tabs open in all browser instances. |
| int GetTabCount() const; |
| |
| UsageClock* usage_clock() { return &usage_clock_; } |
| |
| private: |
| friend class TabManagerStatsCollectorTest; |
| |
| FRIEND_TEST_ALL_PREFIXES(TabManagerTest, AutoDiscardable); |
| FRIEND_TEST_ALL_PREFIXES(TabManagerTest, CanOnlyDiscardOnce); |
| FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ChildProcessNotifications); |
| FRIEND_TEST_ALL_PREFIXES(TabManagerTest, EnablePageAlmostIdleSignal); |
| FRIEND_TEST_ALL_PREFIXES(TabManagerTest, InvalidOrEmptyURL); |
| FRIEND_TEST_ALL_PREFIXES(TabManagerTest, TabDiscardDoneCallback); |
| FRIEND_TEST_ALL_PREFIXES(TabManagerTest, IsInternalPage); |
| FRIEND_TEST_ALL_PREFIXES(TabManagerTest, IsTabRestoredInForeground); |
| FRIEND_TEST_ALL_PREFIXES(TabManagerTest, OomPressureListener); |
| FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ProtectDevToolsTabsFromDiscarding); |
| FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ProtectPDFPages); |
| FRIEND_TEST_ALL_PREFIXES(TabManagerTest, |
| ProtectRecentlyUsedTabsFromUrgentDiscarding); |
| FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ProtectVideoTabs); |
| FRIEND_TEST_ALL_PREFIXES(TabManagerTest, TabManagerBasics); |
| FRIEND_TEST_ALL_PREFIXES(TabManagerTest, TabManagerWasDiscarded); |
| FRIEND_TEST_ALL_PREFIXES(TabManagerTest, |
| TabManagerWasDiscardedCrossSiteSubFrame); |
| FRIEND_TEST_ALL_PREFIXES(TabManagerTest, |
| TrackingNumberOfLoadedLifecycleUnits); |
| FRIEND_TEST_ALL_PREFIXES(TabManagerTest, UrgentFastShutdownSharedTabProcess); |
| FRIEND_TEST_ALL_PREFIXES(TabManagerTestWithTwoTabs, |
| UrgentFastShutdownSingleTabProcess); |
| FRIEND_TEST_ALL_PREFIXES(TabManagerTest, |
| UrgentFastShutdownWithBeforeunloadHandler); |
| FRIEND_TEST_ALL_PREFIXES(TabManagerTest, UrgentFastShutdownWithUnloadHandler); |
| |
| // Returns true if the |url| represents an internal Chrome web UI page that |
| // can be easily reloaded and hence makes a good choice to discard. |
| static bool IsInternalPage(const GURL& url); |
| |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| // Called by the memory pressure listener when the memory pressure rises. |
| void OnMemoryPressure( |
| base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level); |
| |
| // Called when we finished handling the memory pressure by discarding tabs. |
| void OnTabDiscardDone(); |
| |
| // Register to start listening to memory pressure. Called on startup or end |
| // of tab discards. |
| void RegisterMemoryPressureListener(); |
| |
| // Unregister to stop listening to memory pressure. Called on shutdown or |
| // beginning of tab discards. |
| void UnregisterMemoryPressureListener(); |
| #endif // BUILDFLAG(IS_CHROMEOS_ASH) |
| |
| // Discards the less important LifecycleUnit that supports discarding under |
| // |reason|. |
| content::WebContents* DiscardTabImpl( |
| LifecycleUnitDiscardReason reason, |
| TabDiscardDoneCB tab_discard_done = TabDiscardDoneCB(base::DoNothing())); |
| |
| void OnSessionRestoreStartedLoadingTabs(); |
| void OnSessionRestoreFinishedLoadingTabs(); |
| void OnWillRestoreTab(content::WebContents* contents); |
| |
| // Returns the number of tabs that are not pending load or discarded. |
| int GetNumAliveTabs() const; |
| |
| // LifecycleUnitObserver: |
| void OnLifecycleUnitDestroyed(LifecycleUnit* lifecycle_unit) override; |
| |
| // LifecycleUnitSourceObserver: |
| void OnLifecycleUnitCreated(LifecycleUnit* lifecycle_unit) override; |
| |
| // LifecycleUnits managed by this. |
| LifecycleUnitSet lifecycle_units_; |
| |
| // A listener to global memory pressure events. |
| std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; |
| |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| std::unique_ptr<TabManagerDelegate> delegate_; |
| #endif |
| |
| class TabManagerSessionRestoreObserver; |
| std::unique_ptr<TabManagerSessionRestoreObserver> session_restore_observer_; |
| |
| // A clock that advances when Chrome is in use. |
| UsageClock usage_clock_; |
| |
| // Weak pointer factory used for posting delayed tasks. |
| base::WeakPtrFactory<TabManager> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace resource_coordinator |
| |
| #endif // CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_MANAGER_H_ |