Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(206)

Side by Side Diff: chrome/browser/safe_browsing/mojo_safe_browsing_impl.cc

Issue 2924723002: Network service: SafeBrowsing check for frame-resources from browser. (Closed)
Patch Set: . Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/safe_browsing/mojo_safe_browsing_impl.h" 5 #include "chrome/browser/safe_browsing/mojo_safe_browsing_impl.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/memory/ptr_util.h" 9 #include "base/memory/ptr_util.h"
10 #include "base/memory/weak_ptr.h" 10 #include "chrome/browser/safe_browsing/safe_browsing_url_checker_impl.h"
11 #include "base/timer/timer.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/prerender/prerender_contents.h"
14 #include "chrome/browser/safe_browsing/ui_manager.h" 11 #include "chrome/browser/safe_browsing/ui_manager.h"
15 #include "components/safe_browsing_db/database_manager.h" 12 #include "components/safe_browsing_db/database_manager.h"
16 #include "content/public/browser/browser_thread.h" 13 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/render_frame_host.h" 14 #include "content/public/browser/render_frame_host.h"
18 #include "content/public/browser/web_contents.h" 15 #include "content/public/browser/web_contents.h"
19 #include "content/public/common/resource_type.h" 16 #include "content/public/common/resource_type.h"
20 #include "mojo/public/cpp/bindings/strong_binding.h" 17 #include "mojo/public/cpp/bindings/strong_binding.h"
21 #include "net/base/load_flags.h" 18 #include "net/base/load_flags.h"
22 19
23 namespace safe_browsing { 20 namespace safe_browsing {
24 namespace { 21 namespace {
25 22
26 // TODO(yzshen): Share such value with safe_browsing::BaseResourceThrottle.
27 // Maximum time in milliseconds to wait for the SafeBrowsing service reputation
28 // check. After this amount of time the outstanding check will be aborted, and
29 // the resource will be treated as if it were safe.
30 const int kCheckUrlTimeoutMs = 5000;
31
32 content::WebContents* GetWebContentsFromID(int render_process_id, 23 content::WebContents* GetWebContentsFromID(int render_process_id,
33 int render_frame_id) { 24 int render_frame_id) {
34 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 25 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
35 content::RenderFrameHost* render_frame_host = 26 content::RenderFrameHost* render_frame_host =
36 content::RenderFrameHost::FromID(render_process_id, render_frame_id); 27 content::RenderFrameHost::FromID(render_process_id, render_frame_id);
37 if (!render_frame_host) 28 if (!render_frame_host)
38 return nullptr; 29 return nullptr;
39 30
40 return content::WebContents::FromRenderFrameHost(render_frame_host); 31 return content::WebContents::FromRenderFrameHost(render_frame_host);
41 } 32 }
42 33
43 // TODO(yzshen): Handle the case where SafeBrowsing is not enabled, or 34 // This class wraps a base::OnceCallback<void(bool)> and runs it on destruction,
44 // !database_manager()->IsSupported(). 35 // if it hasn't been run yet.
45 // TODO(yzshen): Make sure it also works on Andorid. 36 class BooleanCallbackWrapper {
46 // TODO(yzshen): Do all the logging like what BaseResourceThrottle does.
47 class SafeBrowsingUrlCheckerImpl : public mojom::SafeBrowsingUrlChecker,
48 public SafeBrowsingDatabaseManager::Client {
49 public: 37 public:
50 SafeBrowsingUrlCheckerImpl( 38 using BooleanCallback = base::OnceCallback<void(bool)>;
51 int load_flags, 39
52 content::ResourceType resource_type, 40 explicit BooleanCallbackWrapper(BooleanCallback callback)
53 scoped_refptr<SafeBrowsingDatabaseManager> database_manager, 41 : callback_(std::move(callback)) {}
54 scoped_refptr<SafeBrowsingUIManager> ui_manager, 42 ~BooleanCallbackWrapper() {
55 int render_process_id, 43 if (callback_)
56 int render_frame_id) 44 Run(false);
57 : load_flags_(load_flags),
58 resource_type_(resource_type),
59 render_process_id_(render_process_id),
60 render_frame_id_(render_frame_id),
61 database_manager_(std::move(database_manager)),
62 ui_manager_(std::move(ui_manager)),
63 weak_factory_(this) {
64 DCHECK_NE(resource_type, content::RESOURCE_TYPE_MAIN_FRAME);
65 DCHECK_NE(resource_type, content::RESOURCE_TYPE_SUB_FRAME);
66 } 45 }
67 46
68 ~SafeBrowsingUrlCheckerImpl() override { 47 void Run(bool value) { std::move(callback_).Run(value); }
69 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
70
71 if (state_ == STATE_CHECKING_URL)
72 database_manager_->CancelCheck(this);
73
74 for (size_t i = next_index_; i < callbacks_.size(); ++i)
75 std::move(callbacks_[i]).Run(false);
76 }
77
78 // mojom::SafeBrowsingUrlChecker implementation.
79 void CheckUrl(const GURL& url, CheckUrlCallback callback) override {
80 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
81
82 DVLOG(1) << "SafeBrowsingUrlCheckerImpl checks URL: " << url;
83 urls_.push_back(url);
84 callbacks_.push_back(std::move(callback));
85
86 ProcessUrls();
87 }
88 48
89 private: 49 private:
90 // SafeBrowsingDatabaseManager::Client implementation: 50 BooleanCallback callback_;
91 void OnCheckBrowseUrlResult(const GURL& url,
92 SBThreatType threat_type,
93 const ThreatMetadata& metadata) override {
94 DCHECK_EQ(STATE_CHECKING_URL, state_);
95 DCHECK_LT(next_index_, urls_.size());
96 DCHECK_EQ(urls_[next_index_], url);
97
98 timer_.Stop();
99 if (threat_type == SB_THREAT_TYPE_SAFE) {
100 state_ = STATE_NONE;
101 std::move(callbacks_[next_index_]).Run(true);
102 next_index_++;
103 ProcessUrls();
104 return;
105 }
106
107 if (load_flags_ & net::LOAD_PREFETCH) {
108 BlockAndProcessUrls();
109 return;
110 }
111
112 security_interstitials::UnsafeResource resource;
113 resource.url = url;
114 resource.original_url = urls_[0];
115 if (urls_.size() > 1)
116 resource.redirect_urls =
117 std::vector<GURL>(urls_.begin() + 1, urls_.end());
118 resource.is_subresource = true;
119 resource.is_subframe = false;
120 resource.threat_type = threat_type;
121 resource.threat_metadata = metadata;
122 resource.callback =
123 base::Bind(&SafeBrowsingUrlCheckerImpl::OnBlockingPageComplete,
124 weak_factory_.GetWeakPtr());
125 resource.callback_thread = content::BrowserThread::GetTaskRunnerForThread(
126 content::BrowserThread::IO);
127 resource.web_contents_getter =
128 base::Bind(&GetWebContentsFromID, render_process_id_, render_frame_id_);
129 resource.threat_source = database_manager_->GetThreatSource();
130
131 state_ = STATE_DISPLAYING_BLOCKING_PAGE;
132
133 content::BrowserThread::PostTask(
134 content::BrowserThread::UI, FROM_HERE,
135 base::Bind(&SafeBrowsingUrlCheckerImpl::StartDisplayingBlockingPage,
136 weak_factory_.GetWeakPtr(), ui_manager_, resource));
137 }
138
139 static void StartDisplayingBlockingPage(
140 const base::WeakPtr<SafeBrowsingUrlCheckerImpl>& checker,
141 scoped_refptr<BaseUIManager> ui_manager,
142 const security_interstitials::UnsafeResource& resource) {
143 content::WebContents* web_contents = resource.web_contents_getter.Run();
144 if (web_contents) {
145 prerender::PrerenderContents* prerender_contents =
146 prerender::PrerenderContents::FromWebContents(web_contents);
147 if (prerender_contents) {
148 prerender_contents->Destroy(prerender::FINAL_STATUS_SAFE_BROWSING);
149 } else {
150 ui_manager->DisplayBlockingPage(resource);
151 return;
152 }
153 }
154
155 // Tab is gone or it's being prerendered.
156 content::BrowserThread::PostTask(
157 content::BrowserThread::IO, FROM_HERE,
158 base::BindOnce(&SafeBrowsingUrlCheckerImpl::BlockAndProcessUrls,
159 checker));
160 }
161
162 void OnCheckUrlTimeout() {
163 database_manager_->CancelCheck(this);
164
165 OnCheckBrowseUrlResult(urls_[next_index_],
166 safe_browsing::SB_THREAT_TYPE_SAFE,
167 ThreatMetadata());
168 }
169
170 void ProcessUrls() {
171 DCHECK_NE(STATE_BLOCKED, state_);
172
173 if (state_ == STATE_CHECKING_URL ||
174 state_ == STATE_DISPLAYING_BLOCKING_PAGE) {
175 return;
176 }
177
178 while (next_index_ < urls_.size()) {
179 DCHECK_EQ(STATE_NONE, state_);
180 // TODO(yzshen): Consider moving CanCheckResourceType() to the renderer
181 // side. That would save some IPCs. It requires a method on the
182 // SafeBrowsing mojo interface to query all supported resource types.
183 if (!database_manager_->CanCheckResourceType(resource_type_) ||
184 database_manager_->CheckBrowseUrl(urls_[next_index_], this)) {
185 std::move(callbacks_[next_index_]).Run(true);
186 next_index_++;
187 continue;
188 }
189
190 state_ = STATE_CHECKING_URL;
191 // Start a timer to abort the check if it takes too long.
192 timer_.Start(FROM_HERE,
193 base::TimeDelta::FromMilliseconds(kCheckUrlTimeoutMs), this,
194 &SafeBrowsingUrlCheckerImpl::OnCheckUrlTimeout);
195
196 break;
197 }
198 }
199
200 void BlockAndProcessUrls() {
201 DVLOG(1) << "SafeBrowsingUrlCheckerImpl blocks URL: " << urls_[next_index_];
202 state_ = STATE_BLOCKED;
203
204 // If user decided to not proceed through a warning, mark all the remaining
205 // redirects as "bad".
206 for (; next_index_ < callbacks_.size(); ++next_index_)
207 std::move(callbacks_[next_index_]).Run(false);
208 }
209
210 void OnBlockingPageComplete(bool proceed) {
211 DCHECK_EQ(STATE_DISPLAYING_BLOCKING_PAGE, state_);
212
213 if (proceed) {
214 state_ = STATE_NONE;
215 std::move(callbacks_[next_index_]).Run(true);
216 next_index_++;
217 ProcessUrls();
218 } else {
219 BlockAndProcessUrls();
220 }
221 }
222
223 enum State {
224 // Haven't started checking or checking is complete.
225 STATE_NONE,
226 // We have one outstanding URL-check.
227 STATE_CHECKING_URL,
228 // We're displaying a blocking page.
229 STATE_DISPLAYING_BLOCKING_PAGE,
230 // The blocking page has returned *not* to proceed.
231 STATE_BLOCKED
232 };
233
234 const int load_flags_;
235 const content::ResourceType resource_type_;
236 const int render_process_id_;
237 const int render_frame_id_;
238 scoped_refptr<SafeBrowsingDatabaseManager> database_manager_;
239 scoped_refptr<BaseUIManager> ui_manager_;
240
241 // The redirect chain for this resource, including the original URL and
242 // subsequent redirect URLs.
243 std::vector<GURL> urls_;
244 // Callbacks corresponding to |urls_| to report check results. |urls_| and
245 // |callbacks_| are always of the same size.
246 std::vector<CheckUrlCallback> callbacks_;
247 // |urls_| before |next_index_| have been checked. If |next_index_| is smaller
248 // than the size of |urls_|, the URL at |next_index_| is being processed.
249 size_t next_index_ = 0;
250
251 State state_ = STATE_NONE;
252
253 // Timer to abort the SafeBrowsing check if it takes too long.
254 base::OneShotTimer timer_;
255
256 base::WeakPtrFactory<SafeBrowsingUrlCheckerImpl> weak_factory_;
257
258 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingUrlCheckerImpl);
259 }; 51 };
260 52
261 } // namespace 53 } // namespace
262 54
263 MojoSafeBrowsingImpl::MojoSafeBrowsingImpl( 55 MojoSafeBrowsingImpl::MojoSafeBrowsingImpl(
264 scoped_refptr<SafeBrowsingDatabaseManager> database_manager, 56 scoped_refptr<SafeBrowsingDatabaseManager> database_manager,
265 scoped_refptr<SafeBrowsingUIManager> ui_manager, 57 scoped_refptr<SafeBrowsingUIManager> ui_manager,
266 int render_process_id) 58 int render_process_id)
267 : database_manager_(std::move(database_manager)), 59 : database_manager_(std::move(database_manager)),
268 ui_manager_(std::move(ui_manager)), 60 ui_manager_(std::move(ui_manager)),
(...skipping 20 matching lines...) Expand all
289 void MojoSafeBrowsingImpl::CreateCheckerAndCheck( 81 void MojoSafeBrowsingImpl::CreateCheckerAndCheck(
290 int32_t render_frame_id, 82 int32_t render_frame_id,
291 mojom::SafeBrowsingUrlCheckerRequest request, 83 mojom::SafeBrowsingUrlCheckerRequest request,
292 const GURL& url, 84 const GURL& url,
293 int32_t load_flags, 85 int32_t load_flags,
294 content::ResourceType resource_type, 86 content::ResourceType resource_type,
295 CreateCheckerAndCheckCallback callback) { 87 CreateCheckerAndCheckCallback callback) {
296 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 88 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
297 auto checker_impl = base::MakeUnique<SafeBrowsingUrlCheckerImpl>( 89 auto checker_impl = base::MakeUnique<SafeBrowsingUrlCheckerImpl>(
298 static_cast<int>(load_flags), resource_type, database_manager_, 90 static_cast<int>(load_flags), resource_type, database_manager_,
299 ui_manager_, render_process_id_, static_cast<int>(render_frame_id)); 91 ui_manager_,
300 checker_impl->CheckUrl(url, std::move(callback)); 92 base::Bind(&GetWebContentsFromID, render_process_id_,
93 static_cast<int>(render_frame_id)));
94
95 checker_impl->CheckUrl(
96 url, base::BindOnce(
97 &BooleanCallbackWrapper::Run,
98 base::Owned(new BooleanCallbackWrapper(std::move(callback)))));
301 mojo::MakeStrongBinding(std::move(checker_impl), std::move(request)); 99 mojo::MakeStrongBinding(std::move(checker_impl), std::move(request));
302 } 100 }
303 101
304 } // namespace safe_browsing 102 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698