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

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

Issue 2108313002: Remove the Pver3 safe_browsing_test server (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update a few files I missed Created 4 years, 5 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
(Empty)
1 // Copyright (c) 2012 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 //
5 // This test uses the safebrowsing test server published at
6 // http://code.google.com/p/google-safe-browsing/ to test the safebrowsing
7 // protocol implemetation. Details of the safebrowsing testing flow is
8 // documented at
9 // http://code.google.com/p/google-safe-browsing/wiki/ProtocolTesting
10 //
11 // This test launches safebrowsing test server and issues several update
12 // requests against that server. Each update would get different data and after
13 // each update, the test will get a list of URLs from the test server to verify
14 // its repository. The test will succeed only if all updates are performed and
15 // URLs match what the server expected.
16
17 #include <vector>
18
19 #include <stddef.h>
20
21 #include "base/bind.h"
22 #include "base/command_line.h"
23 #include "base/environment.h"
24 #include "base/macros.h"
25 #include "base/path_service.h"
26 #include "base/strings/string_number_conversions.h"
27 #include "base/strings/string_split.h"
28 #include "base/strings/stringprintf.h"
29 #include "base/strings/utf_string_conversions.h"
30 #include "base/synchronization/lock.h"
31 #include "base/test/test_timeouts.h"
32 #include "base/threading/platform_thread.h"
33 #include "base/threading/thread.h"
34 #include "base/time/time.h"
35 #include "chrome/browser/browser_process.h"
36 #include "chrome/browser/chrome_notification_types.h"
37 #include "chrome/browser/profiles/profile.h"
38 #include "chrome/browser/safe_browsing/local_database_manager.h"
39 #include "chrome/browser/safe_browsing/local_safebrowsing_test_server.h"
40 #include "chrome/browser/safe_browsing/protocol_manager.h"
41 #include "chrome/browser/safe_browsing/test_safe_browsing_service.h"
42 #include "chrome/browser/ui/browser.h"
43 #include "chrome/common/chrome_switches.h"
44 #include "chrome/common/url_constants.h"
45 #include "chrome/test/base/in_process_browser_test.h"
46 #include "components/safe_browsing_db/database_manager.h"
47 #include "content/public/browser/browser_context.h"
48 #include "content/public/test/test_browser_thread.h"
49 #include "content/public/test/test_utils.h"
50 #include "net/base/load_flags.h"
51 #include "net/dns/host_resolver.h"
52 #include "net/log/net_log.h"
53 #include "net/test/python_utils.h"
54 #include "net/test/spawned_test_server/spawned_test_server.h"
55 #include "net/url_request/url_fetcher.h"
56 #include "net/url_request/url_fetcher_delegate.h"
57 #include "net/url_request/url_request_status.h"
58 #include "testing/gtest/include/gtest/gtest.h"
59
60 using content::BrowserThread;
61
62 #ifndef SAFE_BROWSING_DB_LOCAL
63 #error This test requires the SAFE_BROWSING_DB_LOCAL implementation.
64 #endif
65
66 namespace safe_browsing {
67
68 namespace {
69
70 const base::FilePath::CharType kDataFile[] =
71 FILE_PATH_LITERAL("testing_input_nomac.dat");
72 const char kUrlVerifyPath[] = "safebrowsing/verify_urls";
73 const char kDBVerifyPath[] = "safebrowsing/verify_database";
74 const char kTestCompletePath[] = "test_complete";
75
76 struct PhishingUrl {
77 std::string url;
78 std::string list_name;
79 bool is_phishing;
80 };
81
82 // Parses server response for verify_urls. The expected format is:
83 //
84 // first.random.url.com/ internal-test-shavar yes
85 // second.random.url.com/ internal-test-shavar yes
86 // ...
87 bool ParsePhishingUrls(const std::string& data,
88 std::vector<PhishingUrl>* phishing_urls) {
89 if (data.empty())
90 return false;
91
92 for (const base::StringPiece& url_str : base::SplitStringPiece(
93 data, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
94 PhishingUrl phishing_url;
95 std::vector<std::string> record_parts = base::SplitString(
96 url_str, "\t", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
97 if (record_parts.size() != 3) {
98 LOG(ERROR) << "Unexpected URL format in phishing URL list: "
99 << url_str.as_string();
100 return false;
101 }
102 phishing_url.url = std::string(url::kHttpScheme) + "://" + record_parts[0];
103 phishing_url.list_name = record_parts[1];
104 if (record_parts[2] == "yes") {
105 phishing_url.is_phishing = true;
106 } else if (record_parts[2] == "no") {
107 phishing_url.is_phishing = false;
108 } else {
109 LOG(ERROR) << "Unrecognized expectation in " << url_str.as_string()
110 << ": " << record_parts[2];
111 return false;
112 }
113 phishing_urls->push_back(phishing_url);
114 }
115 return true;
116 }
117
118 } // namespace
119
120 // This starts the browser and keeps status of states related to SafeBrowsing.
121 class SafeBrowsingServerTest : public InProcessBrowserTest {
122 public:
123 SafeBrowsingServerTest()
124 : is_database_ready_(true),
125 is_update_scheduled_(false),
126 is_checked_url_in_db_(false),
127 is_checked_url_safe_(false) {}
128
129 ~SafeBrowsingServerTest() override {}
130
131 void UpdateSafeBrowsingStatus() {
132 ASSERT_TRUE(sb_factory_->test_safe_browsing_service());
133 base::AutoLock lock(update_status_mutex_);
134 last_update_ = sb_factory_->test_safe_browsing_service()
135 ->protocol_manager_->last_update();
136 is_update_scheduled_ = sb_factory_->test_safe_browsing_service()
137 ->protocol_manager_->update_timer_.IsRunning();
138 }
139
140 void ForceUpdate() {
141 content::WindowedNotificationObserver observer(
142 chrome::NOTIFICATION_SAFE_BROWSING_UPDATE_COMPLETE,
143 content::Source<SafeBrowsingDatabaseManager>(database_manager()));
144 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
145 base::Bind(&SafeBrowsingServerTest::ForceUpdateOnIOThread,
146 this));
147 observer.Wait();
148 }
149
150 void ForceUpdateOnIOThread() {
151 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
152 ASSERT_TRUE(sb_factory_->test_safe_browsing_service());
153 sb_factory_->test_safe_browsing_service()
154 ->protocol_manager_->ForceScheduleNextUpdate(
155 base::TimeDelta::FromSeconds(0));
156 }
157
158
159 void CheckIsDatabaseReady() {
160 base::AutoLock lock(update_status_mutex_);
161 is_database_ready_ =
162 !local_database_manager()->database_update_in_progress_;
163 }
164
165 void CheckUrl(SafeBrowsingDatabaseManager::Client* helper, const GURL& url) {
166 ASSERT_TRUE(sb_factory_->test_safe_browsing_service());
167 base::AutoLock lock(update_status_mutex_);
168 if (database_manager()->CheckBrowseUrl(url, helper)) {
169 is_checked_url_in_db_ = false;
170 is_checked_url_safe_ = true;
171 } else {
172 // In this case, Safebrowsing service will fetch the full hash
173 // from the server and examine that. Once it is done,
174 // set_is_checked_url_safe() will be called via callback.
175 is_checked_url_in_db_ = true;
176 }
177 }
178
179 SafeBrowsingDatabaseManager* database_manager() {
180 return sb_factory_->test_safe_browsing_service()->database_manager().get();
181 }
182
183 // TODO(nparker): Remove the need for this by wiring in our own
184 // SafeBrowsingDatabaseManager factory and keep a ptr to the subclass.
185 LocalSafeBrowsingDatabaseManager* local_database_manager() {
186 return static_cast<LocalSafeBrowsingDatabaseManager*>(database_manager());
187 }
188
189
190 bool is_checked_url_in_db() {
191 base::AutoLock l(update_status_mutex_);
192 return is_checked_url_in_db_;
193 }
194
195 void set_is_checked_url_safe(bool safe) {
196 base::AutoLock l(update_status_mutex_);
197 is_checked_url_safe_ = safe;
198 }
199
200 bool is_checked_url_safe() {
201 base::AutoLock l(update_status_mutex_);
202 return is_checked_url_safe_;
203 }
204
205 bool is_database_ready() {
206 base::AutoLock l(update_status_mutex_);
207 return is_database_ready_;
208 }
209
210 base::Time last_update() {
211 base::AutoLock l(update_status_mutex_);
212 return last_update_;
213 }
214
215 bool is_update_scheduled() {
216 base::AutoLock l(update_status_mutex_);
217 return is_update_scheduled_;
218 }
219
220 scoped_refptr<base::SequencedTaskRunner> SafeBrowsingTaskRunner() {
221 return local_database_manager()->safe_browsing_task_runner_;
222 }
223
224 const net::SpawnedTestServer& spawned_test_server() const {
225 return *test_server_;
226 }
227
228 protected:
229 void SetProtocolConfigURLPrefix(const std::string& url_prefix) {
230 SafeBrowsingProtocolConfig config;
231 config.url_prefix = url_prefix;
232 // Makes sure the auto update is not triggered. The tests will force the
233 // update when needed.
234 config.disable_auto_update = true;
235 config.client_name = "browser_tests";
236 sb_factory_->SetTestProtocolConfig(config);
237 }
238
239 void SetUp() override {
240 base::FilePath datafile_path;
241 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &datafile_path));
242
243 datafile_path = datafile_path.Append(FILE_PATH_LITERAL("third_party"))
244 .Append(FILE_PATH_LITERAL("safe_browsing"))
245 .Append(FILE_PATH_LITERAL("testing"))
246 .Append(kDataFile);
247 test_server_.reset(new LocalSafeBrowsingTestServer(datafile_path));
248 ASSERT_TRUE(test_server_->Start());
249 LOG(INFO) << "server is " << test_server_->host_port_pair().ToString();
250
251 sb_factory_.reset(new TestSafeBrowsingServiceFactory());
252 // Point to the testing server for all SafeBrowsing requests.
253 SetProtocolConfigURLPrefix(test_server_->GetURL("safebrowsing").spec());
254 SafeBrowsingService::RegisterFactory(sb_factory_.get());
255
256 InProcessBrowserTest::SetUp();
257 }
258
259 void TearDown() override {
260 InProcessBrowserTest::TearDown();
261
262 SafeBrowsingService::RegisterFactory(NULL);
263 }
264
265 void SetUpCommandLine(base::CommandLine* command_line) override {
266 // TODO(lzheng): The test server does not understand download related
267 // requests. We need to fix the server.
268 command_line->AppendSwitch(switches::kSbDisableDownloadProtection);
269
270 // TODO(gcasto): Generate new testing data that includes the
271 // client-side phishing whitelist.
272 command_line->AppendSwitch(
273 switches::kDisableClientSidePhishingDetection);
274
275 // TODO(kalman): Generate new testing data that includes the extension
276 // blacklist.
277 command_line->AppendSwitch(switches::kSbDisableExtensionBlacklist);
278 }
279
280 void SetTestStep(int step) {
281 std::string test_step = base::StringPrintf("test_step=%d", step);
282 sb_factory_->test_safe_browsing_service()
283 ->protocol_manager_->set_additional_query(test_step);
284 }
285
286 std::unique_ptr<TestSafeBrowsingServiceFactory> sb_factory_;
287
288 private:
289 std::unique_ptr<net::SpawnedTestServer> test_server_;
290
291 // Protects all variables below since they are read on UI thread
292 // but updated on IO thread or safebrowsing thread.
293 base::Lock update_status_mutex_;
294
295 // States associated with safebrowsing service updates.
296 bool is_database_ready_;
297 base::Time last_update_;
298 bool is_update_scheduled_;
299 // Indicates if there is a match between a URL's prefix and safebrowsing
300 // database (thus potentially it is a phishing URL).
301 bool is_checked_url_in_db_;
302 // True if last verified URL is not a phishing URL and thus it is safe.
303 bool is_checked_url_safe_;
304
305 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServerTest);
306 };
307
308 // A ref counted helper class that handles callbacks between IO thread and UI
309 // thread.
310 class SafeBrowsingServerTestHelper
311 : public base::RefCountedThreadSafe<SafeBrowsingServerTestHelper>,
312 public SafeBrowsingDatabaseManager::Client,
313 public net::URLFetcherDelegate {
314 public:
315 SafeBrowsingServerTestHelper(SafeBrowsingServerTest* safe_browsing_test,
316 net::URLRequestContextGetter* request_context)
317 : safe_browsing_test_(safe_browsing_test),
318 response_status_(net::URLRequestStatus::FAILED),
319 request_context_(request_context) {
320 }
321
322 // Callbacks for SafeBrowsingDatabaseManager::Client.
323 void OnCheckBrowseUrlResult(const GURL& url,
324 SBThreatType threat_type,
325 const ThreatMetadata& metadata) override {
326 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
327 EXPECT_TRUE(safe_browsing_test_->is_checked_url_in_db());
328 safe_browsing_test_->set_is_checked_url_safe(
329 threat_type == SB_THREAT_TYPE_SAFE);
330 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
331 base::Bind(&SafeBrowsingServerTestHelper::OnCheckUrlDone, this));
332 }
333
334 virtual void OnBlockingPageComplete(bool proceed) {
335 NOTREACHED() << "Not implemented.";
336 }
337
338 // Functions and callbacks related to CheckUrl. These are used to verify
339 // phishing URLs.
340 void CheckUrl(const GURL& url) {
341 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
342 base::Bind(&SafeBrowsingServerTestHelper::CheckUrlOnIOThread,
343 this, url));
344 content::RunMessageLoop();
345 }
346 void CheckUrlOnIOThread(const GURL& url) {
347 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
348 safe_browsing_test_->CheckUrl(this, url);
349 if (!safe_browsing_test_->is_checked_url_in_db()) {
350 // Ends the checking since this URL's prefix is not in database.
351 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
352 base::Bind(&SafeBrowsingServerTestHelper::OnCheckUrlDone, this));
353 }
354 // Otherwise, OnCheckUrlDone is called in OnUrlCheckResult since
355 // safebrowsing service further fetches hashes from safebrowsing server.
356 }
357
358 void OnCheckUrlDone() {
359 StopUILoop();
360 }
361
362 // Updates status from IO Thread.
363 void CheckStatusOnIOThread() {
364 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
365 safe_browsing_test_->UpdateSafeBrowsingStatus();
366 safe_browsing_test_->SafeBrowsingTaskRunner()->PostTask(
367 FROM_HERE,
368 base::Bind(&SafeBrowsingServerTestHelper::CheckIsDatabaseReady, this));
369 }
370
371 // Checks status in SafeBrowsing Thread.
372 void CheckIsDatabaseReady() {
373 EXPECT_TRUE(safe_browsing_test_->SafeBrowsingTaskRunner()
374 ->RunsTasksOnCurrentThread());
375 safe_browsing_test_->CheckIsDatabaseReady();
376 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
377 base::Bind(&SafeBrowsingServerTestHelper::OnWaitForStatusUpdateDone,
378 this));
379 }
380
381 void OnWaitForStatusUpdateDone() {
382 StopUILoop();
383 }
384
385 // Update safebrowsing status.
386 void UpdateStatus() {
387 BrowserThread::PostTask(
388 BrowserThread::IO,
389 FROM_HERE,
390 base::Bind(&SafeBrowsingServerTestHelper::CheckStatusOnIOThread, this));
391 // Will continue after OnWaitForStatusUpdateDone().
392 content::RunMessageLoop();
393 }
394
395 // Calls test server to fetch database for verification.
396 net::URLRequestStatus::Status FetchDBToVerify(
397 const net::SpawnedTestServer& test_server,
398 int test_step) {
399 // TODO(lzheng): Remove chunk_type=add once it is not needed by the server.
400 std::string path = base::StringPrintf(
401 "%s?client=chromium&appver=1.0&pver=3.0&test_step=%d&chunk_type=add",
402 kDBVerifyPath, test_step);
403 return FetchUrl(test_server.GetURL(path));
404 }
405
406 // Calls test server to fetch URLs for verification.
407 net::URLRequestStatus::Status FetchUrlsToVerify(
408 const net::SpawnedTestServer& test_server,
409 int test_step) {
410 std::string path = base::StringPrintf(
411 "%s?client=chromium&appver=1.0&pver=3.0&test_step=%d",
412 kUrlVerifyPath, test_step);
413 return FetchUrl(test_server.GetURL(path));
414 }
415
416 // Calls test server to check if test data is done. E.g.: if there is a
417 // bad URL that server expects test to fetch full hash but the test didn't,
418 // this verification will fail.
419 net::URLRequestStatus::Status VerifyTestComplete(
420 const net::SpawnedTestServer& test_server,
421 int test_step) {
422 std::string path = base::StringPrintf(
423 "%s?test_step=%d", kTestCompletePath, test_step);
424 return FetchUrl(test_server.GetURL(path));
425 }
426
427 // Callback for URLFetcher.
428 void OnURLFetchComplete(const net::URLFetcher* source) override {
429 source->GetResponseAsString(&response_data_);
430 response_status_ = source->GetStatus().status();
431 StopUILoop();
432 }
433
434 const std::string& response_data() {
435 return response_data_;
436 }
437
438 private:
439 friend class base::RefCountedThreadSafe<SafeBrowsingServerTestHelper>;
440 ~SafeBrowsingServerTestHelper() override {}
441
442 // Stops UI loop after desired status is updated.
443 void StopUILoop() {
444 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
445 base::MessageLoopForUI::current()->QuitWhenIdle();
446 }
447
448 // Fetch a URL. If message_loop_started is true, starts the message loop
449 // so the caller could wait till OnURLFetchComplete is called.
450 net::URLRequestStatus::Status FetchUrl(const GURL& url) {
451 url_fetcher_ = net::URLFetcher::Create(url, net::URLFetcher::GET, this);
452 url_fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE);
453 url_fetcher_->SetRequestContext(request_context_);
454 url_fetcher_->Start();
455 content::RunMessageLoop();
456 return response_status_;
457 }
458
459 base::OneShotTimer check_update_timer_;
460 SafeBrowsingServerTest* safe_browsing_test_;
461 std::unique_ptr<net::URLFetcher> url_fetcher_;
462 std::string response_data_;
463 net::URLRequestStatus::Status response_status_;
464 net::URLRequestContextGetter* request_context_;
465 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServerTestHelper);
466 };
467
468 // TODO(shess): Disabled pending new data for third_party/safe_browsing/testing/
469 IN_PROC_BROWSER_TEST_F(SafeBrowsingServerTest,
470 DISABLED_SafeBrowsingServerTest) {
471 ASSERT_TRUE(sb_factory_->test_safe_browsing_service() != NULL);
472
473 net::URLRequestContextGetter* request_context =
474 browser()->profile()->GetRequestContext();
475 scoped_refptr<SafeBrowsingServerTestHelper> safe_browsing_helper(
476 new SafeBrowsingServerTestHelper(this, request_context));
477 int last_step = 0;
478
479 // Waits and makes sure safebrowsing update is not happening.
480 // The wait will stop once OnWaitForStatusUpdateDone in
481 // safe_browsing_helper is called and status from test_safe_browsing_service
482 // is checked.
483 safe_browsing_helper->UpdateStatus();
484 EXPECT_TRUE(is_database_ready());
485 EXPECT_FALSE(is_update_scheduled());
486 EXPECT_TRUE(last_update().is_null());
487 // Starts updates. After each update, the test will fetch a list of URLs with
488 // expected results to verify with safebrowsing service. If there is no error,
489 // the test moves on to the next step to get more update chunks.
490 // This repeats till there is no update data.
491 for (int step = 1;; step++) {
492 // Every step should be a fresh start.
493 SCOPED_TRACE(base::StringPrintf("step=%d", step));
494 EXPECT_TRUE(is_database_ready());
495 EXPECT_FALSE(is_update_scheduled());
496
497 // Starts safebrowsing update on IO thread. Waits till scheduled
498 // update finishes.
499 base::Time now = base::Time::Now();
500 SetTestStep(step);
501 ForceUpdate();
502
503 safe_browsing_helper->UpdateStatus();
504 EXPECT_TRUE(is_database_ready());
505 EXPECT_FALSE(is_update_scheduled());
506 EXPECT_FALSE(last_update().is_null());
507 if (last_update() < now) {
508 // This means no data available anymore.
509 break;
510 }
511
512 // Fetches URLs to verify and waits till server responses with data.
513 EXPECT_EQ(
514 net::URLRequestStatus::SUCCESS,
515 safe_browsing_helper->FetchUrlsToVerify(spawned_test_server(), step));
516
517 std::vector<PhishingUrl> phishing_urls;
518 EXPECT_TRUE(ParsePhishingUrls(safe_browsing_helper->response_data(),
519 &phishing_urls));
520 EXPECT_GT(phishing_urls.size(), 0U);
521 for (size_t j = 0; j < phishing_urls.size(); ++j) {
522 // Verifes with server if a URL is a phishing URL and waits till server
523 // responses.
524 safe_browsing_helper->CheckUrl(GURL(phishing_urls[j].url));
525 if (phishing_urls[j].is_phishing) {
526 EXPECT_TRUE(is_checked_url_in_db())
527 << phishing_urls[j].url
528 << " is_phishing: " << phishing_urls[j].is_phishing
529 << " test step: " << step;
530 EXPECT_FALSE(is_checked_url_safe())
531 << phishing_urls[j].url
532 << " is_phishing: " << phishing_urls[j].is_phishing
533 << " test step: " << step;
534 } else {
535 EXPECT_TRUE(is_checked_url_safe())
536 << phishing_urls[j].url
537 << " is_phishing: " << phishing_urls[j].is_phishing
538 << " test step: " << step;
539 }
540 }
541 // TODO(lzheng): We should verify the fetched database with local
542 // database to make sure they match.
543 EXPECT_EQ(
544 net::URLRequestStatus::SUCCESS,
545 safe_browsing_helper->FetchDBToVerify(spawned_test_server(), step));
546 EXPECT_GT(safe_browsing_helper->response_data().size(), 0U);
547 last_step = step;
548 }
549
550 // Verifies with server if test is done and waits till server responses.
551 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
552 safe_browsing_helper->VerifyTestComplete(spawned_test_server(),
553 last_step));
554 EXPECT_EQ("yes", safe_browsing_helper->response_data());
555 }
556
557 } // namespace safe_browsing
OLDNEW
« no previous file with comments | « chrome/browser/safe_browsing/local_safebrowsing_test_server.cc ('k') | chrome/browser_tests.isolate » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698