blob: da8bfda1d4cd0147d7bf65812271974cb989d3e7 [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 "ios/chrome/browser/net/ios_chrome_network_delegate.h"
#include <stdlib.h>
#include "base/base_paths.h"
#include "base/debug/alias.h"
#include "base/debug/dump_without_crashing.h"
#include "base/debug/stack_trace.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
#include "base/path_service.h"
#include "base/profiler/scoped_tracker.h"
#include "components/prefs/pref_member.h"
#include "components/prefs/pref_service.h"
#include "ios/chrome/browser/pref_names.h"
#include "ios/web/public/web_thread.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/cookies/cookie_options.h"
#include "net/http/http_status_code.h"
#include "net/url_request/url_request.h"
namespace {
const char kDNTHeader[] = "DNT";
void ReportInvalidReferrerSendOnUI() {
base::RecordAction(
base::UserMetricsAction("Net.URLRequest_StartJob_InvalidReferrer"));
}
void ReportInvalidReferrerSend(const GURL& target_url,
const GURL& referrer_url) {
LOG(ERROR) << "Cancelling request to " << target_url
<< " with invalid referrer " << referrer_url;
// Record information to help debug http://crbug.com/422871
if (!target_url.SchemeIsHTTPOrHTTPS())
return;
web::WebThread::PostTask(web::WebThread::UI, FROM_HERE,
base::Bind(&ReportInvalidReferrerSendOnUI));
base::debug::DumpWithoutCrashing();
NOTREACHED();
}
// Record network errors that HTTP requests complete with, including OK and
// ABORTED.
void RecordNetworkErrorHistograms(const net::URLRequest* request,
int net_error) {
if (request->url().SchemeIs("http")) {
UMA_HISTOGRAM_SPARSE_SLOWLY("Net.HttpRequestCompletionErrorCodes",
std::abs(net_error));
if (request->load_flags() & net::LOAD_MAIN_FRAME_DEPRECATED) {
UMA_HISTOGRAM_SPARSE_SLOWLY(
"Net.HttpRequestCompletionErrorCodes.MainFrame", std::abs(net_error));
}
}
}
} // namespace
IOSChromeNetworkDelegate::IOSChromeNetworkDelegate()
: enable_do_not_track_(nullptr) {}
IOSChromeNetworkDelegate::~IOSChromeNetworkDelegate() {}
// static
void IOSChromeNetworkDelegate::InitializePrefsOnUIThread(
BooleanPrefMember* enable_do_not_track,
PrefService* pref_service) {
DCHECK_CURRENTLY_ON(web::WebThread::UI);
if (enable_do_not_track) {
enable_do_not_track->Init(prefs::kEnableDoNotTrack, pref_service);
enable_do_not_track->MoveToThread(
web::WebThread::GetTaskRunnerForThread(web::WebThread::IO));
}
}
int IOSChromeNetworkDelegate::OnBeforeURLRequest(
net::URLRequest* request,
const net::CompletionCallback& callback,
GURL* new_url) {
// TODO(mmenke): Remove ScopedTracker below once crbug.com/456327 is fixed.
tracked_objects::ScopedTracker tracking_profile1(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"456327 URLRequest::IOSChromeNetworkDelegate::OnBeforeURLRequest"));
// TODO(mmenke): Remove ScopedTracker below once crbug.com/456327 is fixed.
tracked_objects::ScopedTracker tracking_profile2(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"456327 URLRequest::IOSChromeNetworkDelegate::OnBeforeURLRequest 2"));
if (enable_do_not_track_ && enable_do_not_track_->GetValue())
request->SetExtraRequestHeaderByName(kDNTHeader, "1", true /* override */);
// TODO(mmenke): Remove ScopedTracker below once crbug.com/456327 is fixed.
tracked_objects::ScopedTracker tracking_profile4(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"456327 URLRequest::IOSChromeNetworkDelegate::OnBeforeURLRequest 4"));
return net::OK;
}
void IOSChromeNetworkDelegate::OnCompleted(net::URLRequest* request,
bool started,
int net_error) {
RecordNetworkErrorHistograms(request, net_error);
}
net::NetworkDelegate::AuthRequiredResponse
IOSChromeNetworkDelegate::OnAuthRequired(
net::URLRequest* request,
const net::AuthChallengeInfo& auth_info,
const AuthCallback& callback,
net::AuthCredentials* credentials) {
return net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
}
bool IOSChromeNetworkDelegate::OnCanGetCookies(
const net::URLRequest& request,
const net::CookieList& cookie_list) {
// Null during tests, or when we're running in the system context.
if (!cookie_settings_)
return true;
return cookie_settings_->IsCookieAccessAllowed(
request.url(), request.first_party_for_cookies());
}
bool IOSChromeNetworkDelegate::OnCanSetCookie(const net::URLRequest& request,
const std::string& cookie_line,
net::CookieOptions* options) {
// Null during tests, or when we're running in the system context.
if (!cookie_settings_)
return true;
return cookie_settings_->IsCookieAccessAllowed(
request.url(), request.first_party_for_cookies());
}
bool IOSChromeNetworkDelegate::OnCanAccessFile(
const net::URLRequest& request,
const base::FilePath& original_path,
const base::FilePath& absolute_path) const {
return true;
}
bool IOSChromeNetworkDelegate::OnCanEnablePrivacyMode(
const GURL& url,
const GURL& first_party_for_cookies) const {
// Null during tests, or when we're running in the system context.
if (!cookie_settings_.get())
return false;
return !cookie_settings_->IsCookieAccessAllowed(url, first_party_for_cookies);
}
bool IOSChromeNetworkDelegate::
OnCancelURLRequestWithPolicyViolatingReferrerHeader(
const net::URLRequest& request,
const GURL& target_url,
const GURL& referrer_url) const {
ReportInvalidReferrerSend(target_url, referrer_url);
return true;
}