blob: fb6ba19cb7a71325e367fe388bd15aef168cd0bb [file] [log] [blame]
feltbc2eda2d2015-06-23 02:06:031// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
dcheng7bacc0e2016-04-11 20:10:545#include "chrome/browser/safe_browsing/ui_manager.h"
6
clamy4edbf0e2015-12-02 13:35:417#include "base/run_loop.h"
feltbc2eda2d2015-06-23 02:06:038#include "chrome/browser/safe_browsing/safe_browsing_service.h"
scottmg22e4f25a2016-08-15 21:09:039#include "chrome/browser/safe_browsing/ui_manager.h"
feltfb118572015-08-18 05:22:0110#include "chrome/test/base/chrome_render_view_host_test_harness.h"
11#include "chrome/test/base/testing_profile.h"
vakhfa183fa2016-03-29 17:33:3712#include "components/safe_browsing_db/util.h"
feltfb118572015-08-18 05:22:0113#include "content/public/browser/render_process_host.h"
14#include "content/public/browser/render_view_host.h"
15#include "content/public/browser/web_contents.h"
feltbc2eda2d2015-06-23 02:06:0316#include "content/public/test/test_browser_thread_bundle.h"
feltfb118572015-08-18 05:22:0117#include "content/public/test/web_contents_tester.h"
feltbc2eda2d2015-06-23 02:06:0318#include "testing/gtest/include/gtest/gtest.h"
19#include "url/gurl.h"
20
clamy4edbf0e2015-12-02 13:35:4121using content::BrowserThread;
22
feltfb118572015-08-18 05:22:0123static const char* kGoodURL = "https://www.good.com";
24static const char* kBadURL = "https://www.malware.com";
25static const char* kBadURLWithPath = "https://www.malware.com/index.html";
mattmbfc4060d2015-12-18 23:11:3826static const char* kAnotherBadURL = "https://www.badware.com";
27static const char* kLandingURL = "https://www.landing.com";
feltfb118572015-08-18 05:22:0128
vakh9a474d832015-11-13 01:43:0929namespace safe_browsing {
30
clamy4edbf0e2015-12-02 13:35:4131class SafeBrowsingCallbackWaiter {
32 public:
33 SafeBrowsingCallbackWaiter() {}
34
35 bool callback_called() const { return callback_called_; }
36 bool proceed() const { return proceed_; }
37
38 void OnBlockingPageDone(bool proceed) {
39 DCHECK_CURRENTLY_ON(BrowserThread::UI);
40 callback_called_ = true;
41 proceed_ = proceed;
42 loop_.Quit();
43 }
44
45 void OnBlockingPageDoneOnIO(bool proceed) {
46 DCHECK_CURRENTLY_ON(BrowserThread::IO);
47 BrowserThread::PostTask(
48 BrowserThread::UI, FROM_HERE,
49 base::Bind(&SafeBrowsingCallbackWaiter::OnBlockingPageDone,
50 base::Unretained(this), proceed));
51 }
52
53 void WaitForCallback() {
54 DCHECK_CURRENTLY_ON(BrowserThread::UI);
55 loop_.Run();
56 }
57
58 private:
59 bool callback_called_ = false;
60 bool proceed_ = false;
61 base::RunLoop loop_;
62};
63
feltfb118572015-08-18 05:22:0164class SafeBrowsingUIManagerTest : public ChromeRenderViewHostTestHarness {
feltbc2eda2d2015-06-23 02:06:0365 public:
66 SafeBrowsingUIManagerTest() : ui_manager_(new SafeBrowsingUIManager(NULL)) {}
feltfb118572015-08-18 05:22:0167
feltbc2eda2d2015-06-23 02:06:0368 ~SafeBrowsingUIManagerTest() override{};
69
clamy4edbf0e2015-12-02 13:35:4170 void SetUp() override {
71 SetThreadBundleOptions(content::TestBrowserThreadBundle::REAL_IO_THREAD);
72 ChromeRenderViewHostTestHarness::SetUp();
73 }
feltfb118572015-08-18 05:22:0174
75 void TearDown() override { ChromeRenderViewHostTestHarness::TearDown(); }
76
feltbc2eda2d2015-06-23 02:06:0377 bool IsWhitelisted(SafeBrowsingUIManager::UnsafeResource resource) {
78 return ui_manager_->IsWhitelisted(resource);
79 }
80
81 void AddToWhitelist(SafeBrowsingUIManager::UnsafeResource resource) {
felt49e363a2016-08-26 13:46:0882 ui_manager_->AddToWhitelistUrlSet(resource, false);
feltfb118572015-08-18 05:22:0183 }
84
mattmbfc4060d2015-12-18 23:11:3885 SafeBrowsingUIManager::UnsafeResource MakeUnsafeResource(
86 const char* url,
87 bool is_subresource) {
feltfb118572015-08-18 05:22:0188 SafeBrowsingUIManager::UnsafeResource resource;
89 resource.url = GURL(url);
mattmbfc4060d2015-12-18 23:11:3890 resource.is_subresource = is_subresource;
scottmg22e4f25a2016-08-15 21:09:0391 resource.web_contents_getter =
92 SafeBrowsingUIManager::UnsafeResource::GetWebContentsGetter(
93 web_contents()->GetRenderProcessHost()->GetID(),
94 web_contents()->GetMainFrame()->GetRoutingID());
feltfb118572015-08-18 05:22:0195 resource.threat_type = SB_THREAT_TYPE_URL_MALWARE;
96 return resource;
97 }
98
mattmbfc4060d2015-12-18 23:11:3899 SafeBrowsingUIManager::UnsafeResource MakeUnsafeResourceAndStartNavigation(
feltfb118572015-08-18 05:22:01100 const char* url) {
mattmbfc4060d2015-12-18 23:11:38101 SafeBrowsingUIManager::UnsafeResource resource =
102 MakeUnsafeResource(url, false /* is_subresource */);
feltfb118572015-08-18 05:22:01103
mattmbfc4060d2015-12-18 23:11:38104 // The WC doesn't have a URL without a navigation. A main-frame malware
105 // unsafe resource must be a pending navigation.
106 content::WebContentsTester::For(web_contents())->StartNavigation(GURL(url));
feltfb118572015-08-18 05:22:01107 return resource;
feltbc2eda2d2015-06-23 02:06:03108 }
109
clamy4edbf0e2015-12-02 13:35:41110 void SimulateBlockingPageDone(
111 const std::vector<SafeBrowsingUIManager::UnsafeResource>& resources,
112 bool proceed) {
113 ui_manager_->OnBlockingPageDone(resources, proceed);
114 }
115
feltbc2eda2d2015-06-23 02:06:03116 private:
117 scoped_refptr<SafeBrowsingUIManager> ui_manager_;
feltbc2eda2d2015-06-23 02:06:03118};
119
120TEST_F(SafeBrowsingUIManagerTest, Whitelist) {
feltfb118572015-08-18 05:22:01121 SafeBrowsingUIManager::UnsafeResource resource =
mattmbfc4060d2015-12-18 23:11:38122 MakeUnsafeResourceAndStartNavigation(kBadURL);
feltbc2eda2d2015-06-23 02:06:03123 AddToWhitelist(resource);
124 EXPECT_TRUE(IsWhitelisted(resource));
125}
126
feltfb118572015-08-18 05:22:01127TEST_F(SafeBrowsingUIManagerTest, WhitelistIgnoresSitesNotAdded) {
128 SafeBrowsingUIManager::UnsafeResource resource =
mattmbfc4060d2015-12-18 23:11:38129 MakeUnsafeResourceAndStartNavigation(kGoodURL);
feltbc2eda2d2015-06-23 02:06:03130 EXPECT_FALSE(IsWhitelisted(resource));
feltfb118572015-08-18 05:22:01131}
132
133TEST_F(SafeBrowsingUIManagerTest, WhitelistIgnoresPath) {
134 SafeBrowsingUIManager::UnsafeResource resource =
mattmbfc4060d2015-12-18 23:11:38135 MakeUnsafeResourceAndStartNavigation(kBadURL);
feltbc2eda2d2015-06-23 02:06:03136 AddToWhitelist(resource);
137 EXPECT_TRUE(IsWhitelisted(resource));
feltfb118572015-08-18 05:22:01138
mattmbfc4060d2015-12-18 23:11:38139 content::WebContentsTester::For(web_contents())->CommitPendingNavigation();
140
feltfb118572015-08-18 05:22:01141 SafeBrowsingUIManager::UnsafeResource resource_path =
mattmbfc4060d2015-12-18 23:11:38142 MakeUnsafeResourceAndStartNavigation(kBadURLWithPath);
feltfb118572015-08-18 05:22:01143 EXPECT_TRUE(IsWhitelisted(resource_path));
feltbc2eda2d2015-06-23 02:06:03144}
145
feltfb118572015-08-18 05:22:01146TEST_F(SafeBrowsingUIManagerTest, WhitelistIgnoresThreatType) {
147 SafeBrowsingUIManager::UnsafeResource resource =
mattmbfc4060d2015-12-18 23:11:38148 MakeUnsafeResourceAndStartNavigation(kBadURL);
feltfb118572015-08-18 05:22:01149 AddToWhitelist(resource);
150 EXPECT_TRUE(IsWhitelisted(resource));
feltbc2eda2d2015-06-23 02:06:03151
feltfb118572015-08-18 05:22:01152 SafeBrowsingUIManager::UnsafeResource resource_phishing =
mattmbfc4060d2015-12-18 23:11:38153 MakeUnsafeResource(kBadURL, false /* is_subresource */);
feltfb118572015-08-18 05:22:01154 resource_phishing.threat_type = SB_THREAT_TYPE_URL_PHISHING;
155 EXPECT_TRUE(IsWhitelisted(resource_phishing));
feltbc2eda2d2015-06-23 02:06:03156}
157
mattmbfc4060d2015-12-18 23:11:38158TEST_F(SafeBrowsingUIManagerTest, WhitelistWithUnrelatedPendingLoad) {
159 // Commit load of landing page.
160 NavigateAndCommit(GURL(kLandingURL));
161 {
162 // Simulate subresource malware hit on the landing page.
163 SafeBrowsingUIManager::UnsafeResource resource =
164 MakeUnsafeResource(kBadURL, true /* is_subresource */);
165
166 // Start pending load to unrelated site.
167 content::WebContentsTester::For(web_contents())
168 ->StartNavigation(GURL(kGoodURL));
169
170 // Whitelist the resource on the landing page.
171 AddToWhitelist(resource);
172 EXPECT_TRUE(IsWhitelisted(resource));
173 }
174
175 // Commit the pending load of unrelated site.
176 content::WebContentsTester::For(web_contents())->CommitPendingNavigation();
177 {
178 // The unrelated site is not on the whitelist, even if the same subresource
179 // was on it.
180 SafeBrowsingUIManager::UnsafeResource resource =
181 MakeUnsafeResource(kBadURL, true /* is_subresource */);
182 EXPECT_FALSE(IsWhitelisted(resource));
183 }
184
185 // Navigate back to the original landing url.
186 NavigateAndCommit(GURL(kLandingURL));
187 {
188 SafeBrowsingUIManager::UnsafeResource resource =
189 MakeUnsafeResource(kBadURL, true /* is_subresource */);
190 // Original resource url is whitelisted.
191 EXPECT_TRUE(IsWhitelisted(resource));
192 }
193 {
194 // A different malware subresource on the same page is also whitelisted.
195 // (The whitelist is by the page url, not the resource url.)
196 SafeBrowsingUIManager::UnsafeResource resource2 =
197 MakeUnsafeResource(kAnotherBadURL, true /* is_subresource */);
198 EXPECT_TRUE(IsWhitelisted(resource2));
199 }
200}
201
clamy4edbf0e2015-12-02 13:35:41202TEST_F(SafeBrowsingUIManagerTest, UICallbackProceed) {
203 SafeBrowsingUIManager::UnsafeResource resource =
mattmbfc4060d2015-12-18 23:11:38204 MakeUnsafeResourceAndStartNavigation(kBadURL);
clamy4edbf0e2015-12-02 13:35:41205 SafeBrowsingCallbackWaiter waiter;
206 resource.callback =
207 base::Bind(&SafeBrowsingCallbackWaiter::OnBlockingPageDone,
208 base::Unretained(&waiter));
209 resource.callback_thread =
thestig529ad8a2016-07-08 20:30:12210 BrowserThread::GetTaskRunnerForThread(BrowserThread::UI);
clamy4edbf0e2015-12-02 13:35:41211 std::vector<SafeBrowsingUIManager::UnsafeResource> resources;
212 resources.push_back(resource);
213 SimulateBlockingPageDone(resources, true);
214 EXPECT_TRUE(IsWhitelisted(resource));
215 waiter.WaitForCallback();
216 EXPECT_TRUE(waiter.callback_called());
217 EXPECT_TRUE(waiter.proceed());
218}
219
220TEST_F(SafeBrowsingUIManagerTest, UICallbackDontProceed) {
221 SafeBrowsingUIManager::UnsafeResource resource =
mattmbfc4060d2015-12-18 23:11:38222 MakeUnsafeResourceAndStartNavigation(kBadURL);
clamy4edbf0e2015-12-02 13:35:41223 SafeBrowsingCallbackWaiter waiter;
224 resource.callback =
225 base::Bind(&SafeBrowsingCallbackWaiter::OnBlockingPageDone,
226 base::Unretained(&waiter));
227 resource.callback_thread =
thestig529ad8a2016-07-08 20:30:12228 BrowserThread::GetTaskRunnerForThread(BrowserThread::UI);
clamy4edbf0e2015-12-02 13:35:41229 std::vector<SafeBrowsingUIManager::UnsafeResource> resources;
230 resources.push_back(resource);
231 SimulateBlockingPageDone(resources, false);
232 EXPECT_FALSE(IsWhitelisted(resource));
233 waiter.WaitForCallback();
234 EXPECT_TRUE(waiter.callback_called());
235 EXPECT_FALSE(waiter.proceed());
236}
237
238TEST_F(SafeBrowsingUIManagerTest, IOCallbackProceed) {
239 SafeBrowsingUIManager::UnsafeResource resource =
mattmbfc4060d2015-12-18 23:11:38240 MakeUnsafeResourceAndStartNavigation(kBadURL);
clamy4edbf0e2015-12-02 13:35:41241 SafeBrowsingCallbackWaiter waiter;
242 resource.callback =
243 base::Bind(&SafeBrowsingCallbackWaiter::OnBlockingPageDoneOnIO,
244 base::Unretained(&waiter));
245 resource.callback_thread =
thestig529ad8a2016-07-08 20:30:12246 BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
clamy4edbf0e2015-12-02 13:35:41247 std::vector<SafeBrowsingUIManager::UnsafeResource> resources;
248 resources.push_back(resource);
249 SimulateBlockingPageDone(resources, true);
250 EXPECT_TRUE(IsWhitelisted(resource));
251 waiter.WaitForCallback();
252 EXPECT_TRUE(waiter.callback_called());
253 EXPECT_TRUE(waiter.proceed());
254}
255
256TEST_F(SafeBrowsingUIManagerTest, IOCallbackDontProceed) {
257 SafeBrowsingUIManager::UnsafeResource resource =
mattmbfc4060d2015-12-18 23:11:38258 MakeUnsafeResourceAndStartNavigation(kBadURL);
clamy4edbf0e2015-12-02 13:35:41259 SafeBrowsingCallbackWaiter waiter;
260 resource.callback =
261 base::Bind(&SafeBrowsingCallbackWaiter::OnBlockingPageDoneOnIO,
262 base::Unretained(&waiter));
263 resource.callback_thread =
thestig529ad8a2016-07-08 20:30:12264 BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
clamy4edbf0e2015-12-02 13:35:41265 std::vector<SafeBrowsingUIManager::UnsafeResource> resources;
266 resources.push_back(resource);
267 SimulateBlockingPageDone(resources, false);
268 EXPECT_FALSE(IsWhitelisted(resource));
269 waiter.WaitForCallback();
270 EXPECT_TRUE(waiter.callback_called());
271 EXPECT_FALSE(waiter.proceed());
272}
273
vakh9a474d832015-11-13 01:43:09274} // namespace safe_browsing