blob: 87c3587c5c1d752238758c1f1d261d4fce273328 [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
feltbc2eda2d2015-06-23 02:06:035#include "base/memory/scoped_ptr.h"
clamy4edbf0e2015-12-02 13:35:416#include "base/run_loop.h"
feltbc2eda2d2015-06-23 02:06:037#include "chrome/browser/safe_browsing/safe_browsing_service.h"
feltbc2eda2d2015-06-23 02:06:038#include "chrome/browser/safe_browsing/ui_manager.h"
feltfb118572015-08-18 05:22:019#include "chrome/test/base/chrome_render_view_host_test_harness.h"
10#include "chrome/test/base/testing_profile.h"
vakhfa183fa2016-03-29 17:33:3711#include "components/safe_browsing_db/util.h"
feltfb118572015-08-18 05:22:0112#include "content/public/browser/render_process_host.h"
13#include "content/public/browser/render_view_host.h"
14#include "content/public/browser/web_contents.h"
feltbc2eda2d2015-06-23 02:06:0315#include "content/public/test/test_browser_thread_bundle.h"
feltfb118572015-08-18 05:22:0116#include "content/public/test/web_contents_tester.h"
feltbc2eda2d2015-06-23 02:06:0317#include "testing/gtest/include/gtest/gtest.h"
18#include "url/gurl.h"
19
clamy4edbf0e2015-12-02 13:35:4120using content::BrowserThread;
21
feltfb118572015-08-18 05:22:0122static const char* kGoodURL = "https://www.good.com";
23static const char* kBadURL = "https://www.malware.com";
24static const char* kBadURLWithPath = "https://www.malware.com/index.html";
mattmbfc4060d2015-12-18 23:11:3825static const char* kAnotherBadURL = "https://www.badware.com";
26static const char* kLandingURL = "https://www.landing.com";
feltfb118572015-08-18 05:22:0127
vakh9a474d832015-11-13 01:43:0928namespace safe_browsing {
29
clamy4edbf0e2015-12-02 13:35:4130class SafeBrowsingCallbackWaiter {
31 public:
32 SafeBrowsingCallbackWaiter() {}
33
34 bool callback_called() const { return callback_called_; }
35 bool proceed() const { return proceed_; }
36
37 void OnBlockingPageDone(bool proceed) {
38 DCHECK_CURRENTLY_ON(BrowserThread::UI);
39 callback_called_ = true;
40 proceed_ = proceed;
41 loop_.Quit();
42 }
43
44 void OnBlockingPageDoneOnIO(bool proceed) {
45 DCHECK_CURRENTLY_ON(BrowserThread::IO);
46 BrowserThread::PostTask(
47 BrowserThread::UI, FROM_HERE,
48 base::Bind(&SafeBrowsingCallbackWaiter::OnBlockingPageDone,
49 base::Unretained(this), proceed));
50 }
51
52 void WaitForCallback() {
53 DCHECK_CURRENTLY_ON(BrowserThread::UI);
54 loop_.Run();
55 }
56
57 private:
58 bool callback_called_ = false;
59 bool proceed_ = false;
60 base::RunLoop loop_;
61};
62
feltfb118572015-08-18 05:22:0163class SafeBrowsingUIManagerTest : public ChromeRenderViewHostTestHarness {
feltbc2eda2d2015-06-23 02:06:0364 public:
65 SafeBrowsingUIManagerTest() : ui_manager_(new SafeBrowsingUIManager(NULL)) {}
feltfb118572015-08-18 05:22:0166
feltbc2eda2d2015-06-23 02:06:0367 ~SafeBrowsingUIManagerTest() override{};
68
clamy4edbf0e2015-12-02 13:35:4169 void SetUp() override {
70 SetThreadBundleOptions(content::TestBrowserThreadBundle::REAL_IO_THREAD);
71 ChromeRenderViewHostTestHarness::SetUp();
72 }
feltfb118572015-08-18 05:22:0173
74 void TearDown() override { ChromeRenderViewHostTestHarness::TearDown(); }
75
feltbc2eda2d2015-06-23 02:06:0376 bool IsWhitelisted(SafeBrowsingUIManager::UnsafeResource resource) {
77 return ui_manager_->IsWhitelisted(resource);
78 }
79
80 void AddToWhitelist(SafeBrowsingUIManager::UnsafeResource resource) {
feltfb118572015-08-18 05:22:0181 ui_manager_->AddToWhitelist(resource);
82 }
83
mattmbfc4060d2015-12-18 23:11:3884 SafeBrowsingUIManager::UnsafeResource MakeUnsafeResource(
85 const char* url,
86 bool is_subresource) {
feltfb118572015-08-18 05:22:0187 SafeBrowsingUIManager::UnsafeResource resource;
88 resource.url = GURL(url);
mattmbfc4060d2015-12-18 23:11:3889 resource.is_subresource = is_subresource;
feltfb118572015-08-18 05:22:0190 resource.render_process_host_id =
91 web_contents()->GetRenderProcessHost()->GetID();
jialiule9661552016-01-11 23:39:2892 resource.render_frame_id = web_contents()->GetMainFrame()->GetRoutingID();
feltfb118572015-08-18 05:22:0193 resource.threat_type = SB_THREAT_TYPE_URL_MALWARE;
94 return resource;
95 }
96
mattmbfc4060d2015-12-18 23:11:3897 SafeBrowsingUIManager::UnsafeResource MakeUnsafeResourceAndStartNavigation(
feltfb118572015-08-18 05:22:0198 const char* url) {
mattmbfc4060d2015-12-18 23:11:3899 SafeBrowsingUIManager::UnsafeResource resource =
100 MakeUnsafeResource(url, false /* is_subresource */);
feltfb118572015-08-18 05:22:01101
mattmbfc4060d2015-12-18 23:11:38102 // The WC doesn't have a URL without a navigation. A main-frame malware
103 // unsafe resource must be a pending navigation.
104 content::WebContentsTester::For(web_contents())->StartNavigation(GURL(url));
feltfb118572015-08-18 05:22:01105 return resource;
feltbc2eda2d2015-06-23 02:06:03106 }
107
clamy4edbf0e2015-12-02 13:35:41108 void SimulateBlockingPageDone(
109 const std::vector<SafeBrowsingUIManager::UnsafeResource>& resources,
110 bool proceed) {
111 ui_manager_->OnBlockingPageDone(resources, proceed);
112 }
113
feltbc2eda2d2015-06-23 02:06:03114 private:
115 scoped_refptr<SafeBrowsingUIManager> ui_manager_;
feltbc2eda2d2015-06-23 02:06:03116};
117
118TEST_F(SafeBrowsingUIManagerTest, Whitelist) {
feltfb118572015-08-18 05:22:01119 SafeBrowsingUIManager::UnsafeResource resource =
mattmbfc4060d2015-12-18 23:11:38120 MakeUnsafeResourceAndStartNavigation(kBadURL);
feltbc2eda2d2015-06-23 02:06:03121 AddToWhitelist(resource);
122 EXPECT_TRUE(IsWhitelisted(resource));
123}
124
feltfb118572015-08-18 05:22:01125TEST_F(SafeBrowsingUIManagerTest, WhitelistIgnoresSitesNotAdded) {
126 SafeBrowsingUIManager::UnsafeResource resource =
mattmbfc4060d2015-12-18 23:11:38127 MakeUnsafeResourceAndStartNavigation(kGoodURL);
feltbc2eda2d2015-06-23 02:06:03128 EXPECT_FALSE(IsWhitelisted(resource));
feltfb118572015-08-18 05:22:01129}
130
131TEST_F(SafeBrowsingUIManagerTest, WhitelistIgnoresPath) {
132 SafeBrowsingUIManager::UnsafeResource resource =
mattmbfc4060d2015-12-18 23:11:38133 MakeUnsafeResourceAndStartNavigation(kBadURL);
feltbc2eda2d2015-06-23 02:06:03134 AddToWhitelist(resource);
135 EXPECT_TRUE(IsWhitelisted(resource));
feltfb118572015-08-18 05:22:01136
mattmbfc4060d2015-12-18 23:11:38137 content::WebContentsTester::For(web_contents())->CommitPendingNavigation();
138
feltfb118572015-08-18 05:22:01139 SafeBrowsingUIManager::UnsafeResource resource_path =
mattmbfc4060d2015-12-18 23:11:38140 MakeUnsafeResourceAndStartNavigation(kBadURLWithPath);
feltfb118572015-08-18 05:22:01141 EXPECT_TRUE(IsWhitelisted(resource_path));
feltbc2eda2d2015-06-23 02:06:03142}
143
feltfb118572015-08-18 05:22:01144TEST_F(SafeBrowsingUIManagerTest, WhitelistIgnoresThreatType) {
145 SafeBrowsingUIManager::UnsafeResource resource =
mattmbfc4060d2015-12-18 23:11:38146 MakeUnsafeResourceAndStartNavigation(kBadURL);
feltfb118572015-08-18 05:22:01147 AddToWhitelist(resource);
148 EXPECT_TRUE(IsWhitelisted(resource));
feltbc2eda2d2015-06-23 02:06:03149
feltfb118572015-08-18 05:22:01150 SafeBrowsingUIManager::UnsafeResource resource_phishing =
mattmbfc4060d2015-12-18 23:11:38151 MakeUnsafeResource(kBadURL, false /* is_subresource */);
feltfb118572015-08-18 05:22:01152 resource_phishing.threat_type = SB_THREAT_TYPE_URL_PHISHING;
153 EXPECT_TRUE(IsWhitelisted(resource_phishing));
feltbc2eda2d2015-06-23 02:06:03154}
155
mattmbfc4060d2015-12-18 23:11:38156TEST_F(SafeBrowsingUIManagerTest, WhitelistWithUnrelatedPendingLoad) {
157 // Commit load of landing page.
158 NavigateAndCommit(GURL(kLandingURL));
159 {
160 // Simulate subresource malware hit on the landing page.
161 SafeBrowsingUIManager::UnsafeResource resource =
162 MakeUnsafeResource(kBadURL, true /* is_subresource */);
163
164 // Start pending load to unrelated site.
165 content::WebContentsTester::For(web_contents())
166 ->StartNavigation(GURL(kGoodURL));
167
168 // Whitelist the resource on the landing page.
169 AddToWhitelist(resource);
170 EXPECT_TRUE(IsWhitelisted(resource));
171 }
172
173 // Commit the pending load of unrelated site.
174 content::WebContentsTester::For(web_contents())->CommitPendingNavigation();
175 {
176 // The unrelated site is not on the whitelist, even if the same subresource
177 // was on it.
178 SafeBrowsingUIManager::UnsafeResource resource =
179 MakeUnsafeResource(kBadURL, true /* is_subresource */);
180 EXPECT_FALSE(IsWhitelisted(resource));
181 }
182
183 // Navigate back to the original landing url.
184 NavigateAndCommit(GURL(kLandingURL));
185 {
186 SafeBrowsingUIManager::UnsafeResource resource =
187 MakeUnsafeResource(kBadURL, true /* is_subresource */);
188 // Original resource url is whitelisted.
189 EXPECT_TRUE(IsWhitelisted(resource));
190 }
191 {
192 // A different malware subresource on the same page is also whitelisted.
193 // (The whitelist is by the page url, not the resource url.)
194 SafeBrowsingUIManager::UnsafeResource resource2 =
195 MakeUnsafeResource(kAnotherBadURL, true /* is_subresource */);
196 EXPECT_TRUE(IsWhitelisted(resource2));
197 }
198}
199
clamy4edbf0e2015-12-02 13:35:41200TEST_F(SafeBrowsingUIManagerTest, UICallbackProceed) {
201 SafeBrowsingUIManager::UnsafeResource resource =
mattmbfc4060d2015-12-18 23:11:38202 MakeUnsafeResourceAndStartNavigation(kBadURL);
clamy4edbf0e2015-12-02 13:35:41203 SafeBrowsingCallbackWaiter waiter;
204 resource.callback =
205 base::Bind(&SafeBrowsingCallbackWaiter::OnBlockingPageDone,
206 base::Unretained(&waiter));
207 resource.callback_thread =
208 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
209 std::vector<SafeBrowsingUIManager::UnsafeResource> resources;
210 resources.push_back(resource);
211 SimulateBlockingPageDone(resources, true);
212 EXPECT_TRUE(IsWhitelisted(resource));
213 waiter.WaitForCallback();
214 EXPECT_TRUE(waiter.callback_called());
215 EXPECT_TRUE(waiter.proceed());
216}
217
218TEST_F(SafeBrowsingUIManagerTest, UICallbackDontProceed) {
219 SafeBrowsingUIManager::UnsafeResource resource =
mattmbfc4060d2015-12-18 23:11:38220 MakeUnsafeResourceAndStartNavigation(kBadURL);
clamy4edbf0e2015-12-02 13:35:41221 SafeBrowsingCallbackWaiter waiter;
222 resource.callback =
223 base::Bind(&SafeBrowsingCallbackWaiter::OnBlockingPageDone,
224 base::Unretained(&waiter));
225 resource.callback_thread =
226 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
227 std::vector<SafeBrowsingUIManager::UnsafeResource> resources;
228 resources.push_back(resource);
229 SimulateBlockingPageDone(resources, false);
230 EXPECT_FALSE(IsWhitelisted(resource));
231 waiter.WaitForCallback();
232 EXPECT_TRUE(waiter.callback_called());
233 EXPECT_FALSE(waiter.proceed());
234}
235
236TEST_F(SafeBrowsingUIManagerTest, IOCallbackProceed) {
237 SafeBrowsingUIManager::UnsafeResource resource =
mattmbfc4060d2015-12-18 23:11:38238 MakeUnsafeResourceAndStartNavigation(kBadURL);
clamy4edbf0e2015-12-02 13:35:41239 SafeBrowsingCallbackWaiter waiter;
240 resource.callback =
241 base::Bind(&SafeBrowsingCallbackWaiter::OnBlockingPageDoneOnIO,
242 base::Unretained(&waiter));
243 resource.callback_thread =
244 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
245 std::vector<SafeBrowsingUIManager::UnsafeResource> resources;
246 resources.push_back(resource);
247 SimulateBlockingPageDone(resources, true);
248 EXPECT_TRUE(IsWhitelisted(resource));
249 waiter.WaitForCallback();
250 EXPECT_TRUE(waiter.callback_called());
251 EXPECT_TRUE(waiter.proceed());
252}
253
254TEST_F(SafeBrowsingUIManagerTest, IOCallbackDontProceed) {
255 SafeBrowsingUIManager::UnsafeResource resource =
mattmbfc4060d2015-12-18 23:11:38256 MakeUnsafeResourceAndStartNavigation(kBadURL);
clamy4edbf0e2015-12-02 13:35:41257 SafeBrowsingCallbackWaiter waiter;
258 resource.callback =
259 base::Bind(&SafeBrowsingCallbackWaiter::OnBlockingPageDoneOnIO,
260 base::Unretained(&waiter));
261 resource.callback_thread =
262 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
263 std::vector<SafeBrowsingUIManager::UnsafeResource> resources;
264 resources.push_back(resource);
265 SimulateBlockingPageDone(resources, false);
266 EXPECT_FALSE(IsWhitelisted(resource));
267 waiter.WaitForCallback();
268 EXPECT_TRUE(waiter.callback_called());
269 EXPECT_FALSE(waiter.proceed());
270}
271
vakh9a474d832015-11-13 01:43:09272} // namespace safe_browsing