1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
// 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_RENDERER_HOST_SAFE_BROWSING_RESOURCE_THROTTLE_H_
#define CHROME_BROWSER_RENDERER_HOST_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"
class ResourceDispatcherHost;
namespace net {
class URLRequest;
}
// 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;
const char* GetNameForLogging() const override;
// SafeBrowsingDabaseManager::Client implementation (called on IO thread):
void OnCheckBrowseUrlResult(const GURL& url,
safe_browsing::SBThreatType result,
const std::string& 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::NetLog::EventType type,
const GURL& url,
const char* name,
const char* value);
void EndNetLogEvent(net::NetLog::EventType 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::BoundNetLog bound_net_log_;
DISALLOW_COPY_AND_ASSIGN(SafeBrowsingResourceThrottle);
};
#endif // CHROME_BROWSER_RENDERER_HOST_SAFE_BROWSING_RESOURCE_THROTTLE_H_
|