| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef IOS_CHROME_BROWSER_METRICS_TAB_USAGE_RECORDER_BROWSER_AGENT_H_ |
| #define IOS_CHROME_BROWSER_METRICS_TAB_USAGE_RECORDER_BROWSER_AGENT_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <vector> |
| |
| #include "base/containers/circular_deque.h" |
| #include "base/macros.h" |
| #include "base/observer_list.h" |
| #include "base/time/time.h" |
| #include "ios/chrome/browser/main/browser_observer.h" |
| #include "ios/chrome/browser/main/browser_user_data.h" |
| #include "ios/chrome/browser/metrics/tab_usage_recorder_metrics.h" |
| #include "ios/chrome/browser/sessions/session_restoration_observer.h" |
| #import "ios/chrome/browser/web_state_list/web_state_list_observer.h" |
| #include "ios/web/common/user_agent.h" |
| #include "ios/web/public/web_state_observer.h" |
| |
| class PrerenderService; |
| class WebStateList; |
| |
| namespace web { |
| class WebState; |
| } |
| |
| // Reports usage about the lifecycle of a single Browser's tabs. |
| class TabUsageRecorderBrowserAgent |
| : BrowserObserver, |
| public BrowserUserData<TabUsageRecorderBrowserAgent>, |
| web::WebStateObserver, |
| public WebStateListObserver, |
| public SessionRestorationObserver { |
| public: |
| // Not copyable or moveable |
| TabUsageRecorderBrowserAgent(const TabUsageRecorderBrowserAgent&) = delete; |
| TabUsageRecorderBrowserAgent& operator=(const TabUsageRecorderBrowserAgent&) = |
| delete; |
| |
| ~TabUsageRecorderBrowserAgent() override; |
| |
| // Called during startup when the tab model is created, or shortly after a |
| // post-crash launch if the tabs are restored. |web_states| is an array |
| // containing/ the tabs being restored in the current tab model. |
| // |active_web_state| is the tab currently in the foreground. |
| void InitialRestoredTabs(web::WebState* active_web_state, |
| const std::vector<web::WebState*>& web_states); |
| |
| // Called when a tab switch is made. Determines what value to record, and |
| // when to reset the page load counter. |
| void RecordTabSwitched(web::WebState* old_web_state, |
| web::WebState* new_web_state); |
| |
| // Called when the tab model which the user is primarily interacting with has |
| // changed. The |active_web_state| is the current tab of the tab model. If the |
| // user began interacting with |active_web_state|, |primary_tab_model| should |
| // be true. If the user stopped interacting with |active_web_state|, |
| // |primary_tab_model| should be false. |
| void RecordPrimaryTabModelChange(bool primary_tab_model, |
| web::WebState* active_web_state); |
| |
| // Called when a page load begins, to keep track of how many page loads |
| // happen before an evicted tab is seen. |
| void RecordPageLoadStart(web::WebState* web_state); |
| |
| // Called when a page load finishes, to track the load time for evicted tabs. |
| void RecordPageLoadDone(web::WebState* web_state, bool success); |
| |
| // Called when there is a user-initiated reload. |
| void RecordReload(web::WebState* web_state); |
| |
| // Called when WKWebView's renderer is terminated. |tab| contains the tab |
| // whose renderer was terminated, |tab_visible| indicates whether or not |
| // the tab was visible when the renderer terminated and |application_active| |
| // indicates whether the application was in the foreground or background. |
| void RendererTerminated(web::WebState* web_state, |
| bool web_state_visible, |
| bool application_active); |
| |
| // Called when the app has been backgrounded. |
| void AppDidEnterBackground(); |
| |
| // Called when the app has been foregrounded. |
| void AppWillEnterForeground(); |
| |
| // Resets the page load count. |
| void ResetPageLoads(); |
| |
| // Size of |evicted_web_states_|. Used for testing. |
| int EvictedTabsMapSize(); |
| |
| // Resets all tracked data. Used for testing. |
| void ResetAll(); |
| |
| private: |
| // TODO(crbug.com/731724): remove this once the code has been refactored not |
| // to depends on injecting values in |termination_timestamps_|. |
| friend class TabUsageRecorderBrowserAgentTest; |
| explicit TabUsageRecorderBrowserAgent(Browser* browser); |
| |
| friend class BrowserUserData<TabUsageRecorderBrowserAgent>; |
| BROWSER_USER_DATA_KEY_DECL(); |
| |
| // BrowserObserver methods |
| void BrowserDestroyed(Browser* browser) override; |
| |
| // Clear out all state regarding a current evicted tab. |
| void ResetEvictedTab(); |
| |
| // Whether or not a tab can be disregarded by the metrics. |
| bool ShouldIgnoreWebState(web::WebState* web_state); |
| |
| // Whether or not the tab has already been evicted. |
| bool WebStateAlreadyEvicted(web::WebState* web_state); |
| |
| // Returns the state of the given tab. Call only once per tab, as it removes |
| // the tab from |evicted_web_states_|. |
| tab_usage_recorder::TabStateWhenSelected ExtractWebStateState( |
| web::WebState* web_state); |
| |
| // Records various time metrics when a restore of an evicted tab begins. |
| void RecordRestoreStartTime(); |
| |
| // Returns the number of WebState that are still alive (in-memory). |
| int GetLiveWebStatesCount() const; |
| |
| // Called before one of the tracked WebState is destroyed. The WebState is |
| // still valid but will become invalid afterwards, so any reference to it |
| // should be removed. |
| void OnWebStateDestroyed(web::WebState* web_state); |
| |
| // Returns whether |agent_type| and |other_agent_type| are different user |
| // agent types. If either of them is web::UserAgentType::NONE, then return |
| // false. |
| bool IsTransitionBetweenDesktopAndMobileUserAgent( |
| web::UserAgentType agent_type, |
| web::UserAgentType other_agent_type); |
| |
| // Returns whether RecordPageLoadStart should be called for the given |
| // navigation. |
| bool ShouldRecordPageLoadStartForNavigation( |
| web::NavigationContext* navigation); |
| |
| // web::WebStateObserver implementation. |
| void DidStartNavigation(web::WebState* web_state, |
| web::NavigationContext* navigation_context) override; |
| void PageLoaded( |
| web::WebState* web_state, |
| web::PageLoadCompletionStatus load_completion_status) override; |
| void RenderProcessGone(web::WebState* web_state) override; |
| void WebStateDestroyed(web::WebState* web_state) override; |
| |
| // WebStateListObserver implementation. |
| void WebStateInsertedAt(WebStateList* web_state_list, |
| web::WebState* web_state, |
| int index, |
| bool activating) override; |
| void WebStateReplacedAt(WebStateList* web_state_list, |
| web::WebState* old_web_state, |
| web::WebState* new_web_state, |
| int index) override; |
| void WebStateDetachedAt(WebStateList* web_state_list, |
| web::WebState* web_state, |
| int index) override; |
| void WebStateActivatedAt(WebStateList* web_state_list, |
| web::WebState* old_web_state, |
| web::WebState* new_web_state, |
| int active_index, |
| ActiveWebStateChangeReason reason) override; |
| |
| // SessionRestorationObserver implementation. |
| void SessionRestorationFinished( |
| const std::vector<web::WebState*>& restored_web_states) override; |
| |
| // Keep track of when the most recent tab restore begins, to record the time |
| // between evicted-tab-reloads. |
| base::TimeTicks restore_start_time_; |
| |
| // Keep track of the timestamps of renderer terminations in order to find the |
| // number of recently alive tabs when a renderer termination occurs. |
| base::circular_deque<base::TimeTicks> termination_timestamps_; |
| |
| // Number of page loads since the last evicted tab was seen. |
| unsigned int page_loads_ = 0; |
| |
| // Keep track of the current tab, but only if it has been evicted. |
| // This is kept as a pointer value only - it should never be dereferenced. |
| web::WebState* evicted_web_state_ = nullptr; |
| |
| // State of |evicted_web_state_| at the time it became the current tab. |
| tab_usage_recorder::TabStateWhenSelected evicted_web_state_state_ = |
| tab_usage_recorder::IN_MEMORY; |
| |
| // Keep track of the tab last selected when this tab model was switched |
| // away from to another mode (e.g. to incognito). |
| // Kept as a pointer value only - it should never be dereferenced. |
| web::WebState* mode_switch_web_state_ = nullptr; |
| |
| // Keep track of a tab that was created to be immediately selected. It should |
| // not contribute to the "StatusWhenSwitchedBackToForeground" metric. |
| web::WebState* web_state_created_selected_ = nullptr; |
| |
| // Keep track of when the evicted tab starts to reload, so that the total |
| // time it takes to reload can be recorded. |
| base::TimeTicks evicted_web_state_reload_start_time_; |
| |
| // Keep track of the tabs that have a known eviction cause. |
| std::map<web::WebState*, tab_usage_recorder::TabStateWhenSelected> |
| evicted_web_states_; |
| |
| // The WebStateList containing all the monitored tabs. |
| WebStateList* web_state_list_; // weak |
| |
| // The PrerenderService used to check whether a tab is pre-rendering. May |
| // be null during unit testing. |
| PrerenderService* prerender_service_; |
| |
| // Observers for NSNotificationCenter notifications. |
| __strong id<NSObject> application_backgrounding_observer_; |
| __strong id<NSObject> application_foregrounding_observer_; |
| }; |
| |
| #endif // IOS_CHROME_BROWSER_METRICS_TAB_USAGE_RECORDER_BROWSER_AGENT_H_ |