blob: 3c65eb6efb439bd586cabec19d7632df80178fab [file] [log] [blame]
// Copyright 2015 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.
#include "base/metrics/histogram_macros.h"
#include "base/optional.h"
#include "base/time/time.h"
#include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
#include "chrome/common/page_load_metrics/page_load_metrics_util.h"
#include "third_party/blink/public/platform/web_loading_behavior_flag.h"
// Up to 10 minutes, with 100 buckets.
#define PAGE_LOAD_HISTOGRAM(name, sample) \
base::TimeDelta::FromMilliseconds(10), \
base::TimeDelta::FromMinutes(10), 100)
// Up to 1 hour, with 100 buckets.
#define PAGE_LOAD_LONG_HISTOGRAM(name, sample) \
base::TimeDelta::FromMilliseconds(10), \
base::TimeDelta::FromHours(1), 100)
// Records |bytes| to |histogram_name| in kilobytes (i.e., bytes / 1024).
#define PAGE_BYTES_HISTOGRAM(histogram_name, bytes) \
histogram_name, static_cast<int>((bytes) / 1024), 1, 500 * 1024, 50)
namespace page_load_metrics {
struct PageLoadExtraInfo;
// Reasons a page load can be aborted.
enum PageAbortReason {
// Represents no abort.
// The page was reloaded, possibly by the user.
// The page was navigated away from, via a back or forward navigation.
// If the page load is replaced by a new navigation. This includes link
// clicks, typing in the omnibox (not a reload), and form submissions.
// The page load was stopped (e.g. the user presses the stop X button).
// Page load ended due to closing the tab or browser.
// The page load was backgrounded, e.g. the browser was minimized or the user
// switched tabs. Note that the same page may be foregrounded in the future,
// so this is not a 'terminal' abort type.
// We don't know why the page load ended. This is the value we assign to a
// terminated provisional load if the only signal we get is the load finished
// without committing, either without error or with net::ERR_ABORTED.
// Information related to a page load abort.
struct PageAbortInfo {
: reason(ABORT_NONE),
user_initiated_info(UserInitiatedInfo::NotUserInitiated()) {}
PageAbortInfo(PageAbortReason reason,
UserInitiatedInfo user_initiated_info,
base::TimeDelta time_to_abort)
: reason(reason),
time_to_abort(time_to_abort) {}
// The reason / cause for the abort.
const PageAbortReason reason;
// The fields below are only valid if reason != ABORT_NONE.
// Information about whether the abort was initiated by a user.
const UserInitiatedInfo user_initiated_info;
// The time from navigation start to the time the page load was aborted.
const base::TimeDelta time_to_abort;
// Returns true if:
// - We have timing information for the event.
// - The page load started while the page was in the foreground.
// - The event occurred prior to the page being moved to the background.
// When a page is backgrounded, some events (e.g. paint) are delayed. Since
// these data points can skew the mean, they should not be mixed with timing
// events that occurred in the foreground.
// If the event time delta and background time delta are equal, we still
// consider the event to be logged in the foreground histogram since any
// background specific handling would not yet have been applied to that event.
bool WasStartedInForegroundOptionalEventInForeground(
const base::Optional<base::TimeDelta>& event,
const PageLoadExtraInfo& info);
// Returns true if:
// - We have timing information for the event.
// - The page load started in the background.
// - Moved to the foreground prior to the event.
// - Not moved back to the background prior to the event.
bool WasStartedInBackgroundOptionalEventInForeground(
const base::Optional<base::TimeDelta>& event,
const PageLoadExtraInfo& info);
PageAbortInfo GetPageAbortInfo(const PageLoadExtraInfo& info);
// Get the duration of time that the page spent in the foreground, from
// navigation start until one of the following events:
// * the load of the main resource fails
// * the page load is stopped
// * the tab hosting the page is closed
// * the render process hosting the page goes away
// * a new navigation which later commits is initiated in the same tab
// * the tab hosting the page is backgrounded
base::Optional<base::TimeDelta> GetInitialForegroundDuration(
const PageLoadExtraInfo& info,
base::TimeTicks app_background_time);
// Whether the given loading behavior was observed in any frame (either the main
// frame or a subframe).
bool DidObserveLoadingBehaviorInAnyFrame(
const page_load_metrics::PageLoadExtraInfo& info,
blink::WebLoadingBehaviorFlag behavior);
// Whether the given url has a Google Search hostname.
// Examples:
// -> true
// -> true
// -> false
// -> false
bool IsGoogleSearchHostname(const GURL& url);
// Whether the given url is for a Google Search results page. See
// for additional details.
// Examples:
// -> true
// -> true
// -> false
// -> false
bool IsGoogleSearchResultUrl(const GURL& url);
// Whether the given url is a Google Search redirector URL.
bool IsGoogleSearchRedirectorUrl(const GURL& url);
// Whether the given query string contains the given component. The query
// parameter should contain the query string of a URL (the portion following
// the question mark, excluding the question mark). The component must fully
// match a component in the query string. For example, 'foo=bar' would match
// the query string 'a=b&foo=bar&c=d' but would not match 'a=b&zzzfoo=bar&c=d'
// since, though foo=bar appears in the query string, the key specified in the
// component 'foo' does not match the full key in the query string
// 'zzzfoo'. For QueryContainsComponent, the component should of the form
// 'key=value'. For QueryContainsComponentPrefix, the component should be of
// the form 'key=' (where the value is not specified).
// Note: The heuristic used by these functions will not find a component at the
// beginning of the query string if the component starts with a delimiter
// character ('?' or '#'). For example, '?foo=bar' will match the query string
// 'a=b&?foo=bar' but not the query string '?foo=bar&a=b'.
bool QueryContainsComponent(const base::StringPiece query,
const base::StringPiece component);
bool QueryContainsComponentPrefix(const base::StringPiece query,
const base::StringPiece component);
} // namespace page_load_metrics