blob: d97c7df4654bfa8082e8c9df2e2b35f236d39d2c [file] [log] [blame]
// Copyright (c) 2012 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/tab_contents/navigation_metrics_recorder.h"
#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "components/navigation_metrics/navigation_metrics.h"
#include "components/rappor/public/rappor_utils.h"
#include "components/rappor/rappor_service_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/common/frame_navigate_params.h"
#include "net/base/data_url.h"
#include "url/gurl.h"
#include "url/origin.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
#endif
namespace {
// List of mime types that can run JavaScript.
static const struct MimeTypePair {
const char* const mime_type;
NavigationMetricsRecorder::MimeType histogram_value;
} kScriptingMimeTypes[] = {
{"text/html", NavigationMetricsRecorder::MIME_TYPE_HTML},
{"application/xhtml+xml", NavigationMetricsRecorder::MIME_TYPE_XHTML},
{"application/pdf", NavigationMetricsRecorder::MIME_TYPE_PDF},
{"image/svg+xml", NavigationMetricsRecorder::MIME_TYPE_SVG}};
void RecordDataURLMimeType(const std::string& mime_type) {
NavigationMetricsRecorder::MimeType value =
NavigationMetricsRecorder::MIME_TYPE_OTHER;
for (const MimeTypePair& pair : kScriptingMimeTypes) {
if (mime_type == pair.mime_type) {
value = pair.histogram_value;
break;
}
}
UMA_HISTOGRAM_ENUMERATION("Navigation.MainFrameScheme.DataUrl.MimeType",
value, NavigationMetricsRecorder::MIME_TYPE_MAX);
}
} // namespace
DEFINE_WEB_CONTENTS_USER_DATA_KEY(NavigationMetricsRecorder);
NavigationMetricsRecorder::NavigationMetricsRecorder(
content::WebContents* web_contents)
: content::WebContentsObserver(web_contents),
rappor_service_(g_browser_process->rappor_service()) {}
NavigationMetricsRecorder::~NavigationMetricsRecorder() {
}
void NavigationMetricsRecorder::set_rappor_service_for_testing(
rappor::RapporServiceImpl* service) {
rappor_service_ = service;
}
void NavigationMetricsRecorder::DidFinishNavigation(
content::NavigationHandle* navigation_handle) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (!navigation_handle->IsInMainFrame() || !navigation_handle->HasCommitted())
return;
content::BrowserContext* context = web_contents()->GetBrowserContext();
content::NavigationEntry* last_committed_entry =
web_contents()->GetController().GetLastCommittedEntry();
navigation_metrics::RecordMainFrameNavigation(
last_committed_entry->GetVirtualURL(),
navigation_handle->IsSameDocument(), context->IsOffTheRecord());
// Record the domain and registry of the URL that resulted in a navigation to
// a |data:| URL, either by redirects or user clicking a link.
if (last_committed_entry->GetVirtualURL().SchemeIs(url::kDataScheme) &&
!ui::PageTransitionCoreTypeIs(navigation_handle->GetPageTransition(),
ui::PAGE_TRANSITION_TYPED)) {
if (!navigation_handle->GetPreviousURL().is_empty()) {
// TODO(meacer): Remove once data URL navigations are blocked.
rappor::SampleDomainAndRegistryFromGURL(
rappor_service_, "Navigation.Scheme.Data",
navigation_handle->GetPreviousURL());
}
// Also record the mime type of the data: URL.
std::string mime_type;
std::string charset;
// TODO(meacer): Remove once data URL navigations are blocked.
if (net::DataURL::Parse(last_committed_entry->GetVirtualURL(), &mime_type,
&charset, nullptr)) {
RecordDataURLMimeType(mime_type);
}
}
}