blob: ba7924fbb149fc07d4a8dbdc55fb4b333c18fec5 [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.
#ifndef CHROME_BROWSER_LOADER_SAFE_BROWSING_RESOURCE_THROTTLE_H_
#define CHROME_BROWSER_LOADER_SAFE_BROWSING_RESOURCE_THROTTLE_H_
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
#include "chrome/browser/safe_browsing/ui_manager.h"
#include "components/safe_browsing_db/database_manager.h"
#include "content/public/browser/resource_throttle.h"
#include "content/public/common/resource_type.h"
#include "net/log/net_log.h"
#include "net/log/net_log_event_type.h"
#include "url/gurl.h"
class ResourceDispatcherHost;
namespace net {
class URLRequest;
}
namespace safe_browsing {
class V4LocalDatabaseManager;
}
// SafeBrowsingResourceThrottle checks that URLs are "safe" before
// navigating to them. To be considered "safe", a URL must not appear in the
// malware/phishing blacklists (see SafeBrowsingService for details).
//
// On desktop (ifdef SAFE_BROWSING_DB_LOCAL)
// -----------------------------------------
// This check is done before requesting the original URL, and additionally
// before following any subsequent redirect. In the common case the check
// completes synchronously (no match in the in-memory DB), so the request's
// flow is un-interrupted. However if the URL fails this quick check, it
// has the possibility of being on the blacklist. Now the request is
// deferred (prevented from starting), and a more expensive safe browsing
// check is begun (fetches the full hashes).
//
// On mobile (ifdef SAFE_BROWSING_DB_REMOTE):
// -----------------------------------------
// The check is started and runs in parallel with the resource load. If the
// check is not complete by the time the headers are loaded, the request is
// suspended until the URL is classified. We let the headers load on mobile
// since the RemoteSafeBrowsingDatabase checks always have some non-zero
// latency -- there no synchronous pass. This parallelism helps
// performance. Redirects are handled the same way as desktop so they
// always defer.
//
//
// Note that the safe browsing check takes at most kCheckUrlTimeoutMs
// milliseconds. If it takes longer than this, then the system defaults to
// treating the URL as safe.
//
// If the URL is classified as dangerous, a warning page is thrown up and
// the request remains suspended. If the user clicks "proceed" on warning
// page, we resume the request.
//
// Note: The ResourceThrottle interface is called in this order:
// WillStartRequest once, WillRedirectRequest zero or more times, and then
// WillProcessReponse once.
class SafeBrowsingResourceThrottle
: public content::ResourceThrottle,
public safe_browsing::SafeBrowsingDatabaseManager::Client,
public base::SupportsWeakPtr<SafeBrowsingResourceThrottle> {
public:
// Will construct a SafeBrowsingResourceThrottle, or return NULL
// if on Android and not in the field trial.
static SafeBrowsingResourceThrottle* MaybeCreate(
net::URLRequest* request,
content::ResourceType resource_type,
safe_browsing::SafeBrowsingService* sb_service);
// content::ResourceThrottle implementation (called on IO thread):
void WillStartRequest(bool* defer) override;
void WillRedirectRequest(const net::RedirectInfo& redirect_info,
bool* defer) override;
void WillProcessResponse(bool* defer) override;
bool MustProcessResponseBeforeReadingBody() override;
const char* GetNameForLogging() const override;
// SafeBrowsingDabaseManager::Client implementation (called on IO thread):
void OnCheckBrowseUrlResult(
const GURL& url,
safe_browsing::SBThreatType result,
const safe_browsing::ThreatMetadata& metadata) override;
protected:
SafeBrowsingResourceThrottle(const net::URLRequest* request,
content::ResourceType resource_type,
safe_browsing::SafeBrowsingService* sb_service);
private:
// Describes what phase of the check a throttle is in.
enum State {
// Haven't started checking or checking is complete. Not deferred.
STATE_NONE,
// We have one outstanding URL-check. Could be deferred.
STATE_CHECKING_URL,
// We're displaying a blocking page. Could be deferred.
STATE_DISPLAYING_BLOCKING_PAGE,
};
// Describes what stage of the request got paused by the check.
enum DeferState {
DEFERRED_NONE,
DEFERRED_START,
DEFERRED_REDIRECT,
DEFERRED_UNCHECKED_REDIRECT, // unchecked_redirect_url_ is populated.
DEFERRED_PROCESSING,
};
~SafeBrowsingResourceThrottle() override;
// SafeBrowsingService::UrlCheckCallback implementation.
void OnBlockingPageComplete(bool proceed);
// Starts running |url| through the safe browsing check. Returns true if the
// URL is safe to visit. Otherwise returns false and will call
// OnBrowseUrlResult() when the check has completed.
bool CheckUrl(const GURL& url);
// Callback for when the safe browsing check (which was initiated by
// StartCheckingUrl()) has taken longer than kCheckUrlTimeoutMs.
void OnCheckUrlTimeout();
// Starts displaying the safe browsing interstitial page if it's not
// prerendering. Called on the UI thread.
static void StartDisplayingBlockingPage(
const base::WeakPtr<SafeBrowsingResourceThrottle>& throttle,
scoped_refptr<safe_browsing::SafeBrowsingUIManager> ui_manager,
const safe_browsing::SafeBrowsingUIManager::UnsafeResource& resource);
// Called on the IO thread if the request turned out to be for a prerendered
// page.
void Cancel();
// Resumes the request, by continuing the deferred action (either starting the
// request, or following a redirect).
void ResumeRequest();
// For marking network events. |name| and |value| can be null.
void BeginNetLogEvent(net::NetLogEventType type,
const GURL& url,
const char* name,
const char* value);
void EndNetLogEvent(net::NetLogEventType type,
const char* name,
const char* value);
State state_;
DeferState defer_state_;
// The result of the most recent safe browsing check. Only valid to read this
// when state_ != STATE_CHECKING_URL.
safe_browsing::SBThreatType threat_type_;
// The time when we started deferring the request.
base::TimeTicks defer_start_time_;
// Timer to abort the safe browsing check if it takes too long.
base::OneShotTimer timer_;
// The redirect chain for this resource
std::vector<GURL> redirect_urls_;
// If in DEFERRED_UNCHECKED_REDIRECT state, this is the
// URL we still need to check before resuming.
GURL unchecked_redirect_url_;
GURL url_being_checked_;
scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> database_manager_;
scoped_refptr<safe_browsing::SafeBrowsingUIManager> ui_manager_;
const net::URLRequest* request_;
const content::ResourceType resource_type_;
net::NetLogWithSource net_log_with_source_;
scoped_refptr<safe_browsing::V4LocalDatabaseManager>
v4_local_database_manager_;
DISALLOW_COPY_AND_ASSIGN(SafeBrowsingResourceThrottle);
};
#endif // CHROME_BROWSER_LOADER_SAFE_BROWSING_RESOURCE_THROTTLE_H_