| Index: chrome/browser/page_load_metrics/page_load_tracker.cc
|
| diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc b/chrome/browser/page_load_metrics/page_load_tracker.cc
|
| similarity index 63%
|
| copy from chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
|
| copy to chrome/browser/page_load_metrics/page_load_tracker.cc
|
| index c58e4d517126fcb62f499914f485d4707e4332f8..1ae615a77ed7268ffae00c73071a2e9829c972c1 100644
|
| --- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
|
| +++ b/chrome/browser/page_load_metrics/page_load_tracker.cc
|
| @@ -1,38 +1,25 @@
|
| -// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Copyright 2016 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 "chrome/browser/page_load_metrics/metrics_web_contents_observer.h"
|
| +#include "chrome/browser/page_load_metrics/page_load_tracker.h"
|
|
|
| #include <algorithm>
|
| #include <ostream>
|
| #include <string>
|
| #include <utility>
|
|
|
| -#include "base/location.h"
|
| #include "base/logging.h"
|
| #include "base/memory/ptr_util.h"
|
| #include "base/metrics/histogram_macros.h"
|
| #include "base/metrics/user_metrics.h"
|
| -#include "chrome/browser/page_load_metrics/browser_page_track_decider.h"
|
| +#include "chrome/browser/page_load_metrics/page_load_metrics_embedder_interface.h"
|
| #include "chrome/browser/page_load_metrics/page_load_metrics_util.h"
|
| -#include "chrome/common/page_load_metrics/page_load_metrics_messages.h"
|
| #include "chrome/common/page_load_metrics/page_load_timing.h"
|
| -#include "content/public/browser/browser_thread.h"
|
| #include "content/public/browser/navigation_details.h"
|
| #include "content/public/browser/navigation_handle.h"
|
| -#include "content/public/browser/render_frame_host.h"
|
| -#include "content/public/browser/render_view_host.h"
|
| -#include "content/public/browser/web_contents.h"
|
| -#include "content/public/browser/web_contents_observer.h"
|
| -#include "content/public/browser/web_contents_user_data.h"
|
| -#include "ipc/ipc_message.h"
|
| -#include "ipc/ipc_message_macros.h"
|
| #include "ui/base/page_transition_types.h"
|
|
|
| -DEFINE_WEB_CONTENTS_USER_DATA_KEY(
|
| - page_load_metrics::MetricsWebContentsObserver);
|
| -
|
| // This macro invokes the specified method on each observer, passing the
|
| // variable length arguments as the method's arguments, and removes the observer
|
| // from the list of observers if the given method returns STOP_OBSERVING.
|
| @@ -70,6 +57,42 @@ const char kPageLoadCompletedAfterAppBackground[] =
|
|
|
| } // namespace internal
|
|
|
| +void RecordInternalError(InternalErrorLoadEvent event) {
|
| + UMA_HISTOGRAM_ENUMERATION(internal::kErrorEvents, event, ERR_LAST_ENTRY);
|
| +}
|
| +
|
| +// TODO(csharrison): Add a case for client side redirects, which is what JS
|
| +// initiated window.location / window.history navigations get set to.
|
| +UserAbortType AbortTypeForPageTransition(ui::PageTransition transition) {
|
| + if (transition & ui::PAGE_TRANSITION_CLIENT_REDIRECT) {
|
| + return ABORT_CLIENT_REDIRECT;
|
| + }
|
| + if (ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_RELOAD))
|
| + return ABORT_RELOAD;
|
| + if (transition & ui::PAGE_TRANSITION_FORWARD_BACK)
|
| + return ABORT_FORWARD_BACK;
|
| + if (ui::PageTransitionIsNewNavigation(transition))
|
| + return ABORT_NEW_NAVIGATION;
|
| + NOTREACHED()
|
| + << "AbortTypeForPageTransition received unexpected ui::PageTransition: "
|
| + << transition;
|
| + return ABORT_OTHER;
|
| +}
|
| +
|
| +void LogAbortChainSameURLHistogram(int aborted_chain_size_same_url) {
|
| + if (aborted_chain_size_same_url > 0) {
|
| + UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeSameURL,
|
| + aborted_chain_size_same_url);
|
| + }
|
| +}
|
| +
|
| +// TODO(crbug.com/617904): Browser initiated navigations should have
|
| +// HasUserGesture() set to true. Update this once we get enough data from just
|
| +// renderer initiated aborts.
|
| +bool IsNavigationUserInitiated(content::NavigationHandle* handle) {
|
| + return handle->HasUserGesture();
|
| +}
|
| +
|
| namespace {
|
|
|
| // Helper to allow use of Optional<> values in LOG() messages.
|
| @@ -215,40 +238,11 @@ bool IsValidPageLoadTiming(const PageLoadTiming& timing) {
|
| return true;
|
| }
|
|
|
| -void RecordInternalError(InternalErrorLoadEvent event) {
|
| - UMA_HISTOGRAM_ENUMERATION(internal::kErrorEvents, event, ERR_LAST_ENTRY);
|
| -}
|
| -
|
| void RecordAppBackgroundPageLoadCompleted(bool completed_after_background) {
|
| UMA_HISTOGRAM_BOOLEAN(internal::kPageLoadCompletedAfterAppBackground,
|
| completed_after_background);
|
| }
|
|
|
| -// TODO(csharrison): Add a case for client side redirects, which is what JS
|
| -// initiated window.location / window.history navigations get set to.
|
| -UserAbortType AbortTypeForPageTransition(ui::PageTransition transition) {
|
| - if (transition & ui::PAGE_TRANSITION_CLIENT_REDIRECT) {
|
| - return ABORT_CLIENT_REDIRECT;
|
| - }
|
| - if (ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_RELOAD))
|
| - return ABORT_RELOAD;
|
| - if (transition & ui::PAGE_TRANSITION_FORWARD_BACK)
|
| - return ABORT_FORWARD_BACK;
|
| - if (ui::PageTransitionIsNewNavigation(transition))
|
| - return ABORT_NEW_NAVIGATION;
|
| - NOTREACHED()
|
| - << "AbortTypeForPageTransition received unexpected ui::PageTransition: "
|
| - << transition;
|
| - return ABORT_OTHER;
|
| -}
|
| -
|
| -void LogAbortChainSameURLHistogram(int aborted_chain_size_same_url) {
|
| - if (aborted_chain_size_same_url > 0) {
|
| - UMA_HISTOGRAM_COUNTS(internal::kAbortChainSizeSameURL,
|
| - aborted_chain_size_same_url);
|
| - }
|
| -}
|
| -
|
| void DispatchObserverTimingCallbacks(PageLoadMetricsObserver* observer,
|
| const PageLoadTiming& last_timing,
|
| const PageLoadTiming& new_timing,
|
| @@ -281,13 +275,6 @@ void DispatchObserverTimingCallbacks(PageLoadMetricsObserver* observer,
|
| observer->OnLoadingBehaviorObserved(extra_info);
|
| }
|
|
|
| -// TODO(crbug.com/617904): Browser initiated navigations should have
|
| -// HasUserGesture() set to true. Update this once we get enough data from just
|
| -// renderer initiated aborts.
|
| -bool IsNavigationUserInitiated(content::NavigationHandle* handle) {
|
| - return handle->HasUserGesture();
|
| -}
|
| -
|
| } // namespace
|
|
|
| PageLoadTracker::PageLoadTracker(
|
| @@ -688,412 +675,4 @@ void PageLoadTracker::UpdateAbortInternal(UserAbortType abort_type,
|
| }
|
| }
|
|
|
| -// static
|
| -MetricsWebContentsObserver::MetricsWebContentsObserver(
|
| - content::WebContents* web_contents,
|
| - std::unique_ptr<PageLoadMetricsEmbedderInterface> embedder_interface)
|
| - : content::WebContentsObserver(web_contents),
|
| - in_foreground_(false),
|
| - embedder_interface_(std::move(embedder_interface)),
|
| - has_navigated_(false) {
|
| - RegisterInputEventObserver(web_contents->GetRenderViewHost());
|
| -}
|
| -
|
| -MetricsWebContentsObserver* MetricsWebContentsObserver::CreateForWebContents(
|
| - content::WebContents* web_contents,
|
| - std::unique_ptr<PageLoadMetricsEmbedderInterface> embedder_interface) {
|
| - DCHECK(web_contents);
|
| -
|
| - MetricsWebContentsObserver* metrics = FromWebContents(web_contents);
|
| - if (!metrics) {
|
| - metrics = new MetricsWebContentsObserver(web_contents,
|
| - std::move(embedder_interface));
|
| - web_contents->SetUserData(UserDataKey(), metrics);
|
| - }
|
| - return metrics;
|
| -}
|
| -
|
| -MetricsWebContentsObserver::~MetricsWebContentsObserver() {
|
| - // TODO(csharrison): Use a more user-initiated signal for CLOSE.
|
| - NotifyAbortAllLoads(ABORT_CLOSE, false);
|
| -}
|
| -
|
| -void MetricsWebContentsObserver::RegisterInputEventObserver(
|
| - content::RenderViewHost* host) {
|
| - if (host != nullptr)
|
| - host->GetWidget()->AddInputEventObserver(this);
|
| -}
|
| -
|
| -void MetricsWebContentsObserver::UnregisterInputEventObserver(
|
| - content::RenderViewHost* host) {
|
| - if (host != nullptr)
|
| - host->GetWidget()->RemoveInputEventObserver(this);
|
| -}
|
| -
|
| -void MetricsWebContentsObserver::RenderViewHostChanged(
|
| - content::RenderViewHost* old_host,
|
| - content::RenderViewHost* new_host) {
|
| - UnregisterInputEventObserver(old_host);
|
| - RegisterInputEventObserver(new_host);
|
| -}
|
| -
|
| -bool MetricsWebContentsObserver::OnMessageReceived(
|
| - const IPC::Message& message,
|
| - content::RenderFrameHost* render_frame_host) {
|
| - DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| - bool handled = true;
|
| - IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(MetricsWebContentsObserver, message,
|
| - render_frame_host)
|
| - IPC_MESSAGE_HANDLER(PageLoadMetricsMsg_TimingUpdated, OnTimingUpdated)
|
| - IPC_MESSAGE_UNHANDLED(handled = false)
|
| - IPC_END_MESSAGE_MAP()
|
| - return handled;
|
| -}
|
| -
|
| -void MetricsWebContentsObserver::WillStartNavigationRequest(
|
| - content::NavigationHandle* navigation_handle) {
|
| - if (!navigation_handle->IsInMainFrame())
|
| - return;
|
| -
|
| - std::unique_ptr<PageLoadTracker> last_aborted =
|
| - NotifyAbortedProvisionalLoadsNewNavigation(navigation_handle);
|
| -
|
| - int chain_size_same_url = 0;
|
| - int chain_size = 0;
|
| - if (last_aborted) {
|
| - if (last_aborted->MatchesOriginalNavigation(navigation_handle)) {
|
| - chain_size_same_url = last_aborted->aborted_chain_size_same_url() + 1;
|
| - } else if (last_aborted->aborted_chain_size_same_url() > 0) {
|
| - LogAbortChainSameURLHistogram(
|
| - last_aborted->aborted_chain_size_same_url());
|
| - }
|
| - chain_size = last_aborted->aborted_chain_size() + 1;
|
| - }
|
| -
|
| - if (!ShouldTrackNavigation(navigation_handle))
|
| - return;
|
| -
|
| - // Pass in the last committed url to the PageLoadTracker. If the MWCO has
|
| - // never observed a committed load, use the last committed url from this
|
| - // WebContent's opener. This is more accurate than using referrers due to
|
| - // referrer sanitizing and origin referrers. Note that this could potentially
|
| - // be inaccurate if the opener has since navigated.
|
| - content::WebContents* opener = web_contents()->GetOpener();
|
| - const GURL& opener_url =
|
| - !has_navigated_ && opener
|
| - ? web_contents()->GetOpener()->GetLastCommittedURL()
|
| - : GURL::EmptyGURL();
|
| - const GURL& currently_committed_url =
|
| - committed_load_ ? committed_load_->committed_url() : opener_url;
|
| - has_navigated_ = true;
|
| -
|
| - // We can have two provisional loads in some cases. E.g. a same-site
|
| - // navigation can have a concurrent cross-process navigation started
|
| - // from the omnibox.
|
| - DCHECK_GT(2ul, provisional_loads_.size());
|
| - // Passing raw pointers to observers_ and embedder_interface_ is safe because
|
| - // the MetricsWebContentsObserver owns them both list and they are torn down
|
| - // after the PageLoadTracker. The PageLoadTracker does not hold on to
|
| - // committed_load_ or navigation_handle beyond the scope of the constructor.
|
| - provisional_loads_.insert(std::make_pair(
|
| - navigation_handle,
|
| - base::MakeUnique<PageLoadTracker>(
|
| - in_foreground_, embedder_interface_.get(), currently_committed_url,
|
| - navigation_handle, chain_size, chain_size_same_url)));
|
| -}
|
| -
|
| -void MetricsWebContentsObserver::OnRequestComplete(
|
| - content::ResourceType resource_type,
|
| - bool was_cached,
|
| - int net_error) {
|
| - // For simplicity, only count subresources. Navigations are hard to attribute
|
| - // here because we won't have a committed load by the time data streams in
|
| - // from the IO thread.
|
| - if (resource_type == content::RESOURCE_TYPE_MAIN_FRAME &&
|
| - net_error != net::OK) {
|
| - return;
|
| - }
|
| - if (!committed_load_)
|
| - return;
|
| - committed_load_->OnLoadedSubresource(was_cached);
|
| -}
|
| -
|
| -const PageLoadExtraInfo
|
| -MetricsWebContentsObserver::GetPageLoadExtraInfoForCommittedLoad() {
|
| - DCHECK(committed_load_);
|
| - return committed_load_->ComputePageLoadExtraInfo();
|
| -}
|
| -
|
| -void MetricsWebContentsObserver::DidFinishNavigation(
|
| - content::NavigationHandle* navigation_handle) {
|
| - if (!navigation_handle->IsInMainFrame())
|
| - return;
|
| -
|
| - std::unique_ptr<PageLoadTracker> finished_nav(
|
| - std::move(provisional_loads_[navigation_handle]));
|
| - provisional_loads_.erase(navigation_handle);
|
| -
|
| - // Ignore same-page navigations.
|
| - if (navigation_handle->HasCommitted() && navigation_handle->IsSamePage()) {
|
| - if (finished_nav)
|
| - finished_nav->StopTracking();
|
| - return;
|
| - }
|
| -
|
| - // Ignore internally generated aborts for navigations with HTTP responses that
|
| - // don't commit, such as HTTP 204 responses and downloads.
|
| - if (!navigation_handle->HasCommitted() &&
|
| - navigation_handle->GetNetErrorCode() == net::ERR_ABORTED &&
|
| - navigation_handle->GetResponseHeaders()) {
|
| - if (finished_nav)
|
| - finished_nav->StopTracking();
|
| - return;
|
| - }
|
| -
|
| - const bool should_track =
|
| - finished_nav && ShouldTrackNavigation(navigation_handle);
|
| -
|
| - if (finished_nav && !should_track)
|
| - finished_nav->StopTracking();
|
| -
|
| - if (navigation_handle->HasCommitted()) {
|
| - // Notify other loads that they may have been aborted by this committed
|
| - // load. is_certainly_browser_timestamp is set to false because
|
| - // NavigationStart() could be set in either the renderer or browser process.
|
| - NotifyAbortAllLoadsWithTimestamp(
|
| - AbortTypeForPageTransition(navigation_handle->GetPageTransition()),
|
| - IsNavigationUserInitiated(navigation_handle),
|
| - navigation_handle->NavigationStart(), false);
|
| -
|
| - if (should_track) {
|
| - HandleCommittedNavigationForTrackedLoad(navigation_handle,
|
| - std::move(finished_nav));
|
| - } else {
|
| - committed_load_.reset();
|
| - }
|
| - } else if (should_track) {
|
| - HandleFailedNavigationForTrackedLoad(navigation_handle,
|
| - std::move(finished_nav));
|
| - }
|
| -}
|
| -
|
| -// Handle a pre-commit error. Navigations that result in an error page will be
|
| -// ignored.
|
| -void MetricsWebContentsObserver::HandleFailedNavigationForTrackedLoad(
|
| - content::NavigationHandle* navigation_handle,
|
| - std::unique_ptr<PageLoadTracker> tracker) {
|
| - tracker->FailedProvisionalLoad(navigation_handle);
|
| -
|
| - net::Error error = navigation_handle->GetNetErrorCode();
|
| -
|
| - // net::OK: This case occurs when the NavigationHandle finishes and reports
|
| - // !HasCommitted(), but reports no net::Error. This should not occur
|
| - // pre-PlzNavigate, but afterwards it should represent the navigation stopped
|
| - // by the user before it was ready to commit.
|
| - // net::ERR_ABORTED: An aborted provisional load has error
|
| - // net::ERR_ABORTED.
|
| - if ((error == net::OK) || (error == net::ERR_ABORTED)) {
|
| - tracker->NotifyAbort(ABORT_OTHER, false, base::TimeTicks::Now(), true);
|
| - aborted_provisional_loads_.push_back(std::move(tracker));
|
| - }
|
| -}
|
| -
|
| -void MetricsWebContentsObserver::HandleCommittedNavigationForTrackedLoad(
|
| - content::NavigationHandle* navigation_handle,
|
| - std::unique_ptr<PageLoadTracker> tracker) {
|
| - if (!navigation_handle->HasUserGesture() &&
|
| - (navigation_handle->GetPageTransition() &
|
| - ui::PAGE_TRANSITION_CLIENT_REDIRECT) != 0 &&
|
| - committed_load_)
|
| - committed_load_->NotifyClientRedirectTo(*tracker);
|
| -
|
| - committed_load_ = std::move(tracker);
|
| - committed_load_->Commit(navigation_handle);
|
| -}
|
| -
|
| -void MetricsWebContentsObserver::NavigationStopped() {
|
| - // TODO(csharrison): Use a more user-initiated signal for STOP.
|
| - NotifyAbortAllLoads(ABORT_STOP, false);
|
| -}
|
| -
|
| -void MetricsWebContentsObserver::OnInputEvent(
|
| - const blink::WebInputEvent& event) {
|
| - // Ignore browser navigation or reload which comes with type Undefined.
|
| - if (event.type == blink::WebInputEvent::Type::Undefined)
|
| - return;
|
| -
|
| - if (committed_load_)
|
| - committed_load_->OnInputEvent(event);
|
| -}
|
| -
|
| -void MetricsWebContentsObserver::FlushMetricsOnAppEnterBackground() {
|
| - // Signal to observers that we've been backgrounded, in cases where the
|
| - // FlushMetricsOnAppEnterBackground callback gets invoked before the
|
| - // associated WasHidden callback.
|
| - WasHidden();
|
| -
|
| - if (committed_load_)
|
| - committed_load_->FlushMetricsOnAppEnterBackground();
|
| - for (const auto& kv : provisional_loads_) {
|
| - kv.second->FlushMetricsOnAppEnterBackground();
|
| - }
|
| - for (const auto& tracker : aborted_provisional_loads_) {
|
| - tracker->FlushMetricsOnAppEnterBackground();
|
| - }
|
| -}
|
| -
|
| -void MetricsWebContentsObserver::DidRedirectNavigation(
|
| - content::NavigationHandle* navigation_handle) {
|
| - if (!navigation_handle->IsInMainFrame())
|
| - return;
|
| - auto it = provisional_loads_.find(navigation_handle);
|
| - if (it == provisional_loads_.end())
|
| - return;
|
| - it->second->Redirect(navigation_handle);
|
| -}
|
| -
|
| -void MetricsWebContentsObserver::WasShown() {
|
| - if (in_foreground_)
|
| - return;
|
| - in_foreground_ = true;
|
| - if (committed_load_)
|
| - committed_load_->WebContentsShown();
|
| - for (const auto& kv : provisional_loads_) {
|
| - kv.second->WebContentsShown();
|
| - }
|
| -}
|
| -
|
| -void MetricsWebContentsObserver::WasHidden() {
|
| - if (!in_foreground_)
|
| - return;
|
| - in_foreground_ = false;
|
| - if (committed_load_)
|
| - committed_load_->WebContentsHidden();
|
| - for (const auto& kv : provisional_loads_) {
|
| - kv.second->WebContentsHidden();
|
| - }
|
| -}
|
| -
|
| -// This will occur when the process for the main RenderFrameHost exits, either
|
| -// normally or from a crash. We eagerly log data from the last committed load if
|
| -// we have one. Don't notify aborts here because this is probably not user
|
| -// initiated. If it is (e.g. browser shutdown), other code paths will take care
|
| -// of notifying.
|
| -void MetricsWebContentsObserver::RenderProcessGone(
|
| - base::TerminationStatus status) {
|
| - // Other code paths will be run for normal renderer shutdown. Note that we
|
| - // sometimes get the STILL_RUNNING value on fast shutdown.
|
| - if (status == base::TERMINATION_STATUS_NORMAL_TERMINATION ||
|
| - status == base::TERMINATION_STATUS_STILL_RUNNING) {
|
| - return;
|
| - }
|
| -
|
| - // If this is a crash, eagerly log the aborted provisional loads and the
|
| - // committed load. |provisional_loads_| don't need to be destroyed here
|
| - // because their lifetime is tied to the NavigationHandle.
|
| - committed_load_.reset();
|
| - aborted_provisional_loads_.clear();
|
| -}
|
| -
|
| -void MetricsWebContentsObserver::NotifyAbortAllLoads(UserAbortType abort_type,
|
| - bool user_initiated) {
|
| - NotifyAbortAllLoadsWithTimestamp(abort_type, user_initiated,
|
| - base::TimeTicks::Now(), true);
|
| -}
|
| -
|
| -void MetricsWebContentsObserver::NotifyAbortAllLoadsWithTimestamp(
|
| - UserAbortType abort_type,
|
| - bool user_initiated,
|
| - base::TimeTicks timestamp,
|
| - bool is_certainly_browser_timestamp) {
|
| - if (committed_load_) {
|
| - committed_load_->NotifyAbort(abort_type, user_initiated, timestamp,
|
| - is_certainly_browser_timestamp);
|
| - }
|
| - for (const auto& kv : provisional_loads_) {
|
| - kv.second->NotifyAbort(abort_type, user_initiated, timestamp,
|
| - is_certainly_browser_timestamp);
|
| - }
|
| - for (const auto& tracker : aborted_provisional_loads_) {
|
| - if (tracker->IsLikelyProvisionalAbort(timestamp)) {
|
| - tracker->UpdateAbort(abort_type, user_initiated, timestamp,
|
| - is_certainly_browser_timestamp);
|
| - }
|
| - }
|
| - aborted_provisional_loads_.clear();
|
| -}
|
| -
|
| -std::unique_ptr<PageLoadTracker>
|
| -MetricsWebContentsObserver::NotifyAbortedProvisionalLoadsNewNavigation(
|
| - content::NavigationHandle* new_navigation) {
|
| - // If there are multiple aborted loads that can be attributed to this one,
|
| - // just count the latest one for simplicity. Other loads will fall into the
|
| - // OTHER bucket, though there shouldn't be very many.
|
| - if (aborted_provisional_loads_.size() == 0)
|
| - return nullptr;
|
| - if (aborted_provisional_loads_.size() > 1)
|
| - RecordInternalError(ERR_NAVIGATION_SIGNALS_MULIPLE_ABORTED_LOADS);
|
| -
|
| - std::unique_ptr<PageLoadTracker> last_aborted_load =
|
| - std::move(aborted_provisional_loads_.back());
|
| - aborted_provisional_loads_.pop_back();
|
| -
|
| - base::TimeTicks timestamp = new_navigation->NavigationStart();
|
| - if (last_aborted_load->IsLikelyProvisionalAbort(timestamp)) {
|
| - last_aborted_load->UpdateAbort(
|
| - AbortTypeForPageTransition(new_navigation->GetPageTransition()),
|
| - IsNavigationUserInitiated(new_navigation), timestamp, false);
|
| - }
|
| -
|
| - aborted_provisional_loads_.clear();
|
| - return last_aborted_load;
|
| -}
|
| -
|
| -void MetricsWebContentsObserver::OnTimingUpdated(
|
| - content::RenderFrameHost* render_frame_host,
|
| - const PageLoadTiming& timing,
|
| - const PageLoadMetadata& metadata) {
|
| - // We may receive notifications from frames that have been navigated away
|
| - // from. We simply ignore them.
|
| - if (render_frame_host != web_contents()->GetMainFrame()) {
|
| - RecordInternalError(ERR_IPC_FROM_WRONG_FRAME);
|
| - return;
|
| - }
|
| -
|
| - // While timings arriving for the wrong frame are expected, we do not expect
|
| - // any of the errors below. Thus, we track occurrences of all errors below,
|
| - // rather than returning early after encountering an error.
|
| -
|
| - bool error = false;
|
| - if (!committed_load_) {
|
| - RecordInternalError(ERR_IPC_WITH_NO_RELEVANT_LOAD);
|
| - error = true;
|
| - }
|
| -
|
| - if (!web_contents()->GetLastCommittedURL().SchemeIsHTTPOrHTTPS()) {
|
| - RecordInternalError(ERR_IPC_FROM_BAD_URL_SCHEME);
|
| - error = true;
|
| - }
|
| -
|
| - if (error)
|
| - return;
|
| -
|
| - if (!committed_load_->UpdateTiming(timing, metadata)) {
|
| - // If the page load tracker cannot update its timing, something is wrong
|
| - // with the IPC (it's from another load, or it's invalid in some other way).
|
| - // We expect this to be a rare occurrence.
|
| - RecordInternalError(ERR_BAD_TIMING_IPC);
|
| - }
|
| -}
|
| -
|
| -bool MetricsWebContentsObserver::ShouldTrackNavigation(
|
| - content::NavigationHandle* navigation_handle) const {
|
| - DCHECK(navigation_handle->IsInMainFrame());
|
| - DCHECK(!navigation_handle->HasCommitted() ||
|
| - !navigation_handle->IsSamePage());
|
| -
|
| - return BrowserPageTrackDecider(embedder_interface_.get(), web_contents(),
|
| - navigation_handle).ShouldTrack();
|
| -}
|
| -
|
| } // namespace page_load_metrics
|
|
|