blob: b5a3e217e1b39473b1ce4c4a3a446f9932b95a25 [file] [log] [blame]
// 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_H_
#define IOS_CHROME_BROWSER_METRICS_TAB_USAGE_RECORDER_H_
#import <Foundation/Foundation.h>
#include <deque>
#include <map>
#include "base/ios/weak_nsobject.h"
#include "base/macros.h"
#include "base/time/time.h"
#import "ios/chrome/browser/metrics/tab_usage_recorder_delegate.h"
@class Tab;
// Histogram names (visible for testing only).
// The prefix of the histogram names. Used to create a HistogramRecorder.
extern const char kTabUsageHistogramPrefix[];
// The name of the histogram that records the state of the selected tab
// (i.e. the tab being switched to).
extern const char kSelectedTabHistogramName[];
// The name of the histogram that records the number of page loads before an
// evicted tab is selected.
extern const char kPageLoadsBeforeEvictedTabSelected[];
// The name of the histogram tracking the reload time for a previously-evicted
// tab.
extern const char kEvictedTabReloadTime[];
// The name of the histogram for whether or not the reload of a
// previously-evicted tab completed successfully.
extern const char kEvictedTabReloadSuccessRate[];
// The name of the histogram for whether or not the user switched tabs before an
// evicted tab completed reloading.
extern const char kDidUserWaitForEvictedTabReload[];
// The name of the histogram that records time intervals between restores of
// previously-evicted tabs. The first restore seen in a session will record the
// time since the session started.
extern const char kTimeBetweenRestores[];
// The name of the histogram that records time intervals between the last
// restore of a previously-evicted tab and the end of the session.
extern const char kTimeAfterLastRestore[];
// Name of histogram to record whether a memory warning had been recently
// received when a renderer termination occurred.
extern const char kRendererTerminationSawMemoryWarning[];
// Name of histogram to record the number of alive renderers when a renderer
// termination is received.
extern const char kRendererTerminationAliveRenderers[];
// Name of histogram to record the number of renderers that were alive shortly
// before a renderer termination. This metric is being recorded in case the OS
// kills renderers in batches.
extern const char kRendererTerminationRecentlyAliveRenderers[];
// The recently alive renderer count metric counts all renderers that were alive
// x seconds before a renderer termination. |kSecondsBeforeRendererTermination|
// specifies x.
extern const int kSecondsBeforeRendererTermination;
// Reports usage about the lifecycle of a single TabModel's tabs.
class TabUsageRecorder {
public:
enum TabStateWhenSelected {
IN_MEMORY = 0,
EVICTED,
EVICTED_DUE_TO_COLD_START,
PARTIALLY_EVICTED, // Currently, used only by Android.
EVICTED_DUE_TO_BACKGROUNDING, // Deprecated
EVICTED_DUE_TO_INCOGNITO,
RELOADED_DUE_TO_COLD_START_FG_TAB_ON_START, // Android.
RELOADED_DUE_TO_COLD_START_BG_TAB_ON_SWITCH, // Android.
LAZY_LOAD_FOR_OPEN_IN_NEW_TAB, // Android
STOPPED_DUE_TO_LOADING_WHEN_BACKGROUNDING, // Deprecated.
EVICTED_DUE_TO_LOADING_WHEN_BACKGROUNDING, // Deprecated.
EVICTED_DUE_TO_RENDERER_TERMINATION,
TAB_STATE_COUNT,
};
enum LoadDoneState {
LOAD_FAILURE,
LOAD_SUCCESS,
LOAD_DONE_STATE_COUNT,
};
enum EvictedTabUserBehavior {
USER_WAITED,
USER_DID_NOT_WAIT,
USER_LEFT_CHROME,
USER_BEHAVIOR_COUNT,
};
// |delegate| is the TabUsageRecorderDelegate which provides access to the
// Tabs which this TabUsageRecorder is monitoring. |delegate| can be nil.
explicit TabUsageRecorder(id<TabUsageRecorderDelegate> delegate);
virtual ~TabUsageRecorder();
// Called during startup when the tab model is created, or shortly after a
// post-crash launch if the tabs are restored. |tabs| is an array containing
// the tabs being restored in the current tab model. |active_tab| is the tab
// currently in the foreground.
void InitialRestoredTabs(Tab* active_tab, NSArray* tabs);
// Called when a tab is created for immediate selection.
void TabCreatedForSelection(Tab* tab);
// Called when a tab switch is made. Determines what value to record, and
// when to reset the page load counter.
void RecordTabSwitched(Tab* old_tab, Tab* new_tab);
// Called when the tab model which the user is primarily interacting with has
// changed. The |active_tab| is the current tab of the tab model. If the user
// began interacting with |active_tab|, |primary| should be true. If the user
// stopped interacting with |active_tab|, |primary| should be false.
void RecordPrimaryTabModelChange(BOOL primary, Tab* active_tab);
// Called when a page load begins, to keep track of how many page loads
// happen before an evicted tab is seen.
void RecordPageLoadStart(Tab* tab);
// Called when a page load finishes, to track the load time for evicted tabs.
void RecordPageLoadDone(Tab* tab, bool success);
// Called when there is a user-initiated reload.
void RecordReload(Tab* tab);
// Called when WKWebView's renderer is terminated. |tab| contains the tab
// whose renderer was terminated, and |visible| indicates whether or not the
// tab was visible when the renderer terminated.
void RendererTerminated(Tab* tab, bool visible);
// 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_tabs_|. Used for testing.
int EvictedTabsMapSize();
// Resets all tracked data. Used for testing.
void ResetAll();
// Sets the delegate for the TabUsageRecorder.
void SetDelegate(id<TabUsageRecorderDelegate> delegate);
protected:
// 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.
std::deque<base::TimeTicks> termination_timestamps_;
private:
// Clear out all state regarding a current evicted tab.
void ResetEvictedTab();
// Whether or not a tab can be disregarded by the metrics.
bool ShouldIgnoreTab(Tab* tab);
// Whether or not the tab has already been evicted.
bool TabAlreadyEvicted(Tab* tab);
// Returns the state of the given tab. Call only once per tab, as it removes
// the tab from |evicted_tabs_|.
TabStateWhenSelected ExtractTabState(Tab* tab);
// Records various time metrics when a restore of an evicted tab begins.
void RecordRestoreStartTime();
// Clears deleted tabs from |evicted_tabs_|.
void ClearDeletedTabs();
// Number of page loads since the last evicted tab was seen.
unsigned int page_loads_;
// 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.
__unsafe_unretained Tab* evicted_tab_;
// State of |evicted_tab_| at the time it became the current tab.
TabStateWhenSelected evicted_tab_state_;
// 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.
__unsafe_unretained Tab* mode_switch_tab_;
// Keep track of a tab that was created to be immediately selected. It should
// not contribute to the "StatusWhenSwitchedBackToForeground" metric.
__unsafe_unretained Tab* tab_created_selected_;
// 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_tab_reload_start_time_;
// Keep track of the tabs that have a known eviction cause.
std::map<base::WeakNSObject<Tab>, TabStateWhenSelected> evicted_tabs_;
// Reference to TabUsageRecorderDelegate which provides access to the count of
// live tabs monitored by this recorder.
base::WeakNSProtocol<id<TabUsageRecorderDelegate>> recorder_delegate_;
DISALLOW_COPY_AND_ASSIGN(TabUsageRecorder);
};
#endif // IOS_CHROME_BROWSER_METRICS_TAB_USAGE_RECORDER_H_