blob: 32af062814b798b47a58dd670fd6b3038535c8d1 [file] [log] [blame]
// Copyright 2017 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 "components/safe_browsing/renderer/renderer_url_loader_throttle.h"
#include "base/logging.h"
#include "components/safe_browsing/common/utils.h"
#include "content/public/common/resource_request.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "net/url_request/redirect_info.h"
namespace safe_browsing {
RendererURLLoaderThrottle::RendererURLLoaderThrottle(
mojom::SafeBrowsing* safe_browsing,
int render_frame_id)
: safe_browsing_(safe_browsing),
render_frame_id_(render_frame_id),
weak_factory_(this) {}
RendererURLLoaderThrottle::~RendererURLLoaderThrottle() = default;
void RendererURLLoaderThrottle::WillStartRequest(
const content::ResourceRequest& request,
bool* defer) {
DCHECK_EQ(0u, pending_checks_);
DCHECK(!blocked_);
DCHECK(!url_checker_);
pending_checks_++;
// Use a weak pointer to self because |safe_browsing_| is not owned by this
// object.
safe_browsing_->CreateCheckerAndCheck(
render_frame_id_, mojo::MakeRequest(&url_checker_), request.url,
request.method, request.headers, request.load_flags,
request.resource_type, request.has_user_gesture,
base::BindOnce(&RendererURLLoaderThrottle::OnCheckUrlResult,
weak_factory_.GetWeakPtr()));
safe_browsing_ = nullptr;
url_checker_.set_connection_error_handler(base::BindOnce(
&RendererURLLoaderThrottle::OnConnectionError, base::Unretained(this)));
}
void RendererURLLoaderThrottle::WillRedirectRequest(
const net::RedirectInfo& redirect_info,
bool* defer) {
// If |blocked_| is true, the resource load has been canceled and there
// shouldn't be such a notification.
DCHECK(!blocked_);
if (!url_checker_) {
DCHECK_EQ(0u, pending_checks_);
return;
}
pending_checks_++;
url_checker_->CheckUrl(
redirect_info.new_url, redirect_info.new_method,
base::BindOnce(&RendererURLLoaderThrottle::OnCheckUrlResult,
base::Unretained(this)));
}
void RendererURLLoaderThrottle::WillProcessResponse(bool* defer) {
// If |blocked_| is true, the resource load has been canceled and there
// shouldn't be such a notification.
DCHECK(!blocked_);
if (pending_checks_ == 0) {
LogDelay(base::TimeDelta());
return;
}
DCHECK(!deferred_);
deferred_ = true;
defer_start_time_ = base::TimeTicks::Now();
*defer = true;
}
void RendererURLLoaderThrottle::OnCheckUrlResult(bool proceed,
bool showed_interstitial) {
if (blocked_ || !url_checker_)
return;
DCHECK_LT(0u, pending_checks_);
pending_checks_--;
if (proceed) {
if (pending_checks_ == 0 && deferred_) {
LogDelay(base::TimeTicks::Now() - defer_start_time_);
deferred_ = false;
delegate_->Resume();
}
} else {
url_checker_.reset();
blocked_ = true;
pending_checks_ = 0;
delegate_->CancelWithError(net::ERR_ABORTED);
}
}
void RendererURLLoaderThrottle::OnConnectionError() {
DCHECK(!blocked_);
// If a service-side disconnect happens, treat all URLs as if they are safe.
url_checker_.reset();
pending_checks_ = 0;
if (deferred_) {
deferred_ = false;
LogDelay(base::TimeTicks::Now() - defer_start_time_);
delegate_->Resume();
}
}
} // namespace safe_browsing