Update mojo surfaces bindings and mojo/cc/ glue
[chromium-blink-merge.git] / chrome / browser / safe_browsing / safe_browsing_test.cc
blob761811cbab518ed6dfe9f6852f348f95f8721917
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
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.
17 #include <vector>
19 #include "base/bind.h"
20 #include "base/command_line.h"
21 #include "base/environment.h"
22 #include "base/path_service.h"
23 #include "base/strings/string_number_conversions.h"
24 #include "base/strings/string_split.h"
25 #include "base/strings/stringprintf.h"
26 #include "base/strings/utf_string_conversions.h"
27 #include "base/synchronization/lock.h"
28 #include "base/test/test_timeouts.h"
29 #include "base/threading/platform_thread.h"
30 #include "base/threading/thread.h"
31 #include "base/time/time.h"
32 #include "chrome/browser/browser_process.h"
33 #include "chrome/browser/chrome_notification_types.h"
34 #include "chrome/browser/profiles/profile.h"
35 #include "chrome/browser/safe_browsing/database_manager.h"
36 #include "chrome/browser/safe_browsing/local_safebrowsing_test_server.h"
37 #include "chrome/browser/safe_browsing/protocol_manager.h"
38 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
39 #include "chrome/browser/ui/browser.h"
40 #include "chrome/common/chrome_switches.h"
41 #include "chrome/common/url_constants.h"
42 #include "chrome/test/base/in_process_browser_test.h"
43 #include "chrome/test/base/ui_test_utils.h"
44 #include "content/public/browser/browser_context.h"
45 #include "content/public/test/test_browser_thread.h"
46 #include "net/base/load_flags.h"
47 #include "net/base/net_log.h"
48 #include "net/dns/host_resolver.h"
49 #include "net/test/python_utils.h"
50 #include "net/url_request/url_fetcher.h"
51 #include "net/url_request/url_fetcher_delegate.h"
52 #include "net/url_request/url_request_status.h"
53 #include "testing/gtest/include/gtest/gtest.h"
55 using content::BrowserThread;
57 namespace {
59 const base::FilePath::CharType kDataFile[] =
60 FILE_PATH_LITERAL("testing_input_nomac.dat");
61 const char kUrlVerifyPath[] = "safebrowsing/verify_urls";
62 const char kDBVerifyPath[] = "safebrowsing/verify_database";
63 const char kTestCompletePath[] = "test_complete";
65 struct PhishingUrl {
66 std::string url;
67 std::string list_name;
68 bool is_phishing;
71 // Parses server response for verify_urls. The expected format is:
73 // first.random.url.com/ internal-test-shavar yes
74 // second.random.url.com/ internal-test-shavar yes
75 // ...
76 bool ParsePhishingUrls(const std::string& data,
77 std::vector<PhishingUrl>* phishing_urls) {
78 if (data.empty())
79 return false;
81 std::vector<std::string> urls;
82 base::SplitString(data, '\n', &urls);
83 for (size_t i = 0; i < urls.size(); ++i) {
84 if (urls[i].empty())
85 continue;
86 PhishingUrl phishing_url;
87 std::vector<std::string> record_parts;
88 base::SplitString(urls[i], '\t', &record_parts);
89 if (record_parts.size() != 3) {
90 LOG(ERROR) << "Unexpected URL format in phishing URL list: "
91 << urls[i];
92 return false;
94 phishing_url.url = std::string(url::kHttpScheme) + "://" + record_parts[0];
95 phishing_url.list_name = record_parts[1];
96 if (record_parts[2] == "yes") {
97 phishing_url.is_phishing = true;
98 } else if (record_parts[2] == "no") {
99 phishing_url.is_phishing = false;
100 } else {
101 LOG(ERROR) << "Unrecognized expectation in " << urls[i]
102 << ": " << record_parts[2];
103 return false;
105 phishing_urls->push_back(phishing_url);
107 return true;
110 class FakeSafeBrowsingService : public SafeBrowsingService {
111 public:
112 explicit FakeSafeBrowsingService(const std::string& url_prefix)
113 : url_prefix_(url_prefix) {}
115 virtual SafeBrowsingProtocolConfig GetProtocolConfig() const OVERRIDE {
116 SafeBrowsingProtocolConfig config;
117 config.url_prefix = url_prefix_;
118 // Makes sure the auto update is not triggered. The tests will force the
119 // update when needed.
120 config.disable_auto_update = true;
121 #if defined(OS_ANDROID)
122 config.disable_connection_check = true;
123 #endif
124 config.client_name = "browser_tests";
125 return config;
128 private:
129 virtual ~FakeSafeBrowsingService() {}
131 std::string url_prefix_;
133 DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService);
136 // Factory that creates FakeSafeBrowsingService instances.
137 class TestSafeBrowsingServiceFactory : public SafeBrowsingServiceFactory {
138 public:
139 explicit TestSafeBrowsingServiceFactory(const std::string& url_prefix)
140 : url_prefix_(url_prefix) {}
142 virtual SafeBrowsingService* CreateSafeBrowsingService() OVERRIDE {
143 return new FakeSafeBrowsingService(url_prefix_);
146 private:
147 std::string url_prefix_;
150 } // namespace
152 // This starts the browser and keeps status of states related to SafeBrowsing.
153 class SafeBrowsingServerTest : public InProcessBrowserTest {
154 public:
155 SafeBrowsingServerTest()
156 : safe_browsing_service_(NULL),
157 is_database_ready_(true),
158 is_update_scheduled_(false),
159 is_checked_url_in_db_(false),
160 is_checked_url_safe_(false) {
163 virtual ~SafeBrowsingServerTest() {
166 void UpdateSafeBrowsingStatus() {
167 ASSERT_TRUE(safe_browsing_service_);
168 base::AutoLock lock(update_status_mutex_);
169 last_update_ = safe_browsing_service_->protocol_manager_->last_update();
170 is_update_scheduled_ =
171 safe_browsing_service_->protocol_manager_->update_timer_.IsRunning();
174 void ForceUpdate() {
175 content::WindowedNotificationObserver observer(
176 chrome::NOTIFICATION_SAFE_BROWSING_UPDATE_COMPLETE,
177 content::Source<SafeBrowsingDatabaseManager>(database_manager()));
178 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
179 base::Bind(&SafeBrowsingServerTest::ForceUpdateOnIOThread,
180 this));
181 observer.Wait();
184 void ForceUpdateOnIOThread() {
185 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
186 ASSERT_TRUE(safe_browsing_service_);
187 safe_browsing_service_->protocol_manager_->ForceScheduleNextUpdate(
188 base::TimeDelta::FromSeconds(0));
191 void CheckIsDatabaseReady() {
192 base::AutoLock lock(update_status_mutex_);
193 is_database_ready_ = !database_manager()->database_update_in_progress_;
196 void CheckUrl(SafeBrowsingDatabaseManager::Client* helper, const GURL& url) {
197 ASSERT_TRUE(safe_browsing_service_);
198 base::AutoLock lock(update_status_mutex_);
199 if (database_manager()->CheckBrowseUrl(url, helper)) {
200 is_checked_url_in_db_ = false;
201 is_checked_url_safe_ = true;
202 } else {
203 // In this case, Safebrowsing service will fetch the full hash
204 // from the server and examine that. Once it is done,
205 // set_is_checked_url_safe() will be called via callback.
206 is_checked_url_in_db_ = true;
210 SafeBrowsingDatabaseManager* database_manager() {
211 return safe_browsing_service_->database_manager().get();
214 bool is_checked_url_in_db() {
215 base::AutoLock l(update_status_mutex_);
216 return is_checked_url_in_db_;
219 void set_is_checked_url_safe(bool safe) {
220 base::AutoLock l(update_status_mutex_);
221 is_checked_url_safe_ = safe;
224 bool is_checked_url_safe() {
225 base::AutoLock l(update_status_mutex_);
226 return is_checked_url_safe_;
229 bool is_database_ready() {
230 base::AutoLock l(update_status_mutex_);
231 return is_database_ready_;
234 base::Time last_update() {
235 base::AutoLock l(update_status_mutex_);
236 return last_update_;
239 bool is_update_scheduled() {
240 base::AutoLock l(update_status_mutex_);
241 return is_update_scheduled_;
244 base::MessageLoop* SafeBrowsingMessageLoop() {
245 return database_manager()->safe_browsing_thread_->message_loop();
248 const net::SpawnedTestServer& test_server() const {
249 return *test_server_;
252 protected:
253 bool InitSafeBrowsingService() {
254 safe_browsing_service_ = g_browser_process->safe_browsing_service();
255 return safe_browsing_service_ != NULL;
258 virtual void SetUp() OVERRIDE {
259 base::FilePath datafile_path;
260 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &datafile_path));
262 datafile_path = datafile_path.Append(FILE_PATH_LITERAL("third_party"))
263 .Append(FILE_PATH_LITERAL("safe_browsing"))
264 .Append(FILE_PATH_LITERAL("testing"))
265 .Append(kDataFile);
266 test_server_.reset(new LocalSafeBrowsingTestServer(datafile_path));
267 ASSERT_TRUE(test_server_->Start());
268 LOG(INFO) << "server is " << test_server_->host_port_pair().ToString();
270 // Point to the testing server for all SafeBrowsing requests.
271 std::string url_prefix = test_server_->GetURL("safebrowsing").spec();
272 sb_factory_.reset(new TestSafeBrowsingServiceFactory(url_prefix));
273 SafeBrowsingService::RegisterFactory(sb_factory_.get());
275 InProcessBrowserTest::SetUp();
278 virtual void TearDown() OVERRIDE {
279 InProcessBrowserTest::TearDown();
281 SafeBrowsingService::RegisterFactory(NULL);
284 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
285 // This test uses loopback. No need to use IPv6 especially it makes
286 // local requests slow on Windows trybot when ipv6 local address [::1]
287 // is not setup.
288 command_line->AppendSwitch(switches::kDisableIPv6);
290 // TODO(lzheng): The test server does not understand download related
291 // requests. We need to fix the server.
292 command_line->AppendSwitch(switches::kSbDisableDownloadProtection);
294 // TODO(gcasto): Generate new testing data that includes the
295 // client-side phishing whitelist.
296 command_line->AppendSwitch(
297 switches::kDisableClientSidePhishingDetection);
299 // TODO(kalman): Generate new testing data that includes the extension
300 // blacklist.
301 command_line->AppendSwitch(switches::kSbDisableExtensionBlacklist);
303 // TODO(tburkard): Generate new testing data that includes the side-effect
304 // free whitelist.
305 command_line->AppendSwitch(switches::kSbDisableSideEffectFreeWhitelist);
308 void SetTestStep(int step) {
309 std::string test_step = base::StringPrintf("test_step=%d", step);
310 safe_browsing_service_->protocol_manager_->set_additional_query(test_step);
313 private:
314 scoped_ptr<TestSafeBrowsingServiceFactory> sb_factory_;
316 SafeBrowsingService* safe_browsing_service_;
318 scoped_ptr<net::SpawnedTestServer> test_server_;
320 // Protects all variables below since they are read on UI thread
321 // but updated on IO thread or safebrowsing thread.
322 base::Lock update_status_mutex_;
324 // States associated with safebrowsing service updates.
325 bool is_database_ready_;
326 base::Time last_update_;
327 bool is_update_scheduled_;
328 // Indicates if there is a match between a URL's prefix and safebrowsing
329 // database (thus potentially it is a phishing URL).
330 bool is_checked_url_in_db_;
331 // True if last verified URL is not a phishing URL and thus it is safe.
332 bool is_checked_url_safe_;
334 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServerTest);
337 // A ref counted helper class that handles callbacks between IO thread and UI
338 // thread.
339 class SafeBrowsingServerTestHelper
340 : public base::RefCountedThreadSafe<SafeBrowsingServerTestHelper>,
341 public SafeBrowsingDatabaseManager::Client,
342 public net::URLFetcherDelegate {
343 public:
344 SafeBrowsingServerTestHelper(SafeBrowsingServerTest* safe_browsing_test,
345 net::URLRequestContextGetter* request_context)
346 : safe_browsing_test_(safe_browsing_test),
347 response_status_(net::URLRequestStatus::FAILED),
348 request_context_(request_context) {
351 // Callbacks for SafeBrowsingDatabaseManager::Client.
352 virtual void OnCheckBrowseUrlResult(const GURL& url,
353 SBThreatType threat_type) OVERRIDE {
354 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
355 EXPECT_TRUE(safe_browsing_test_->is_checked_url_in_db());
356 safe_browsing_test_->set_is_checked_url_safe(
357 threat_type == SB_THREAT_TYPE_SAFE);
358 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
359 base::Bind(&SafeBrowsingServerTestHelper::OnCheckUrlDone, this));
362 virtual void OnBlockingPageComplete(bool proceed) {
363 NOTREACHED() << "Not implemented.";
366 // Functions and callbacks related to CheckUrl. These are used to verify
367 // phishing URLs.
368 void CheckUrl(const GURL& url) {
369 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
370 base::Bind(&SafeBrowsingServerTestHelper::CheckUrlOnIOThread,
371 this, url));
372 content::RunMessageLoop();
374 void CheckUrlOnIOThread(const GURL& url) {
375 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
376 safe_browsing_test_->CheckUrl(this, url);
377 if (!safe_browsing_test_->is_checked_url_in_db()) {
378 // Ends the checking since this URL's prefix is not in database.
379 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
380 base::Bind(&SafeBrowsingServerTestHelper::OnCheckUrlDone, this));
382 // Otherwise, OnCheckUrlDone is called in OnUrlCheckResult since
383 // safebrowsing service further fetches hashes from safebrowsing server.
386 void OnCheckUrlDone() {
387 StopUILoop();
390 // Updates status from IO Thread.
391 void CheckStatusOnIOThread() {
392 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
393 safe_browsing_test_->UpdateSafeBrowsingStatus();
394 safe_browsing_test_->SafeBrowsingMessageLoop()->PostTask(FROM_HERE,
395 base::Bind(&SafeBrowsingServerTestHelper::CheckIsDatabaseReady, this));
398 // Checks status in SafeBrowsing Thread.
399 void CheckIsDatabaseReady() {
400 EXPECT_EQ(base::MessageLoop::current(),
401 safe_browsing_test_->SafeBrowsingMessageLoop());
402 safe_browsing_test_->CheckIsDatabaseReady();
403 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
404 base::Bind(&SafeBrowsingServerTestHelper::OnWaitForStatusUpdateDone,
405 this));
408 void OnWaitForStatusUpdateDone() {
409 StopUILoop();
412 // Update safebrowsing status.
413 void UpdateStatus() {
414 BrowserThread::PostTask(
415 BrowserThread::IO,
416 FROM_HERE,
417 base::Bind(&SafeBrowsingServerTestHelper::CheckStatusOnIOThread, this));
418 // Will continue after OnWaitForStatusUpdateDone().
419 content::RunMessageLoop();
422 // Calls test server to fetch database for verification.
423 net::URLRequestStatus::Status FetchDBToVerify(
424 const net::SpawnedTestServer& test_server,
425 int test_step) {
426 // TODO(lzheng): Remove chunk_type=add once it is not needed by the server.
427 std::string path = base::StringPrintf(
428 "%s?client=chromium&appver=1.0&pver=3.0&test_step=%d&chunk_type=add",
429 kDBVerifyPath, test_step);
430 return FetchUrl(test_server.GetURL(path));
433 // Calls test server to fetch URLs for verification.
434 net::URLRequestStatus::Status FetchUrlsToVerify(
435 const net::SpawnedTestServer& test_server,
436 int test_step) {
437 std::string path = base::StringPrintf(
438 "%s?client=chromium&appver=1.0&pver=3.0&test_step=%d",
439 kUrlVerifyPath, test_step);
440 return FetchUrl(test_server.GetURL(path));
443 // Calls test server to check if test data is done. E.g.: if there is a
444 // bad URL that server expects test to fetch full hash but the test didn't,
445 // this verification will fail.
446 net::URLRequestStatus::Status VerifyTestComplete(
447 const net::SpawnedTestServer& test_server,
448 int test_step) {
449 std::string path = base::StringPrintf(
450 "%s?test_step=%d", kTestCompletePath, test_step);
451 return FetchUrl(test_server.GetURL(path));
454 // Callback for URLFetcher.
455 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE {
456 source->GetResponseAsString(&response_data_);
457 response_status_ = source->GetStatus().status();
458 StopUILoop();
461 const std::string& response_data() {
462 return response_data_;
465 private:
466 friend class base::RefCountedThreadSafe<SafeBrowsingServerTestHelper>;
467 virtual ~SafeBrowsingServerTestHelper() {}
469 // Stops UI loop after desired status is updated.
470 void StopUILoop() {
471 EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
472 base::MessageLoopForUI::current()->Quit();
475 // Fetch a URL. If message_loop_started is true, starts the message loop
476 // so the caller could wait till OnURLFetchComplete is called.
477 net::URLRequestStatus::Status FetchUrl(const GURL& url) {
478 url_fetcher_.reset(net::URLFetcher::Create(
479 url, net::URLFetcher::GET, this));
480 url_fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE);
481 url_fetcher_->SetRequestContext(request_context_);
482 url_fetcher_->Start();
483 content::RunMessageLoop();
484 return response_status_;
487 base::OneShotTimer<SafeBrowsingServerTestHelper> check_update_timer_;
488 SafeBrowsingServerTest* safe_browsing_test_;
489 scoped_ptr<net::URLFetcher> url_fetcher_;
490 std::string response_data_;
491 net::URLRequestStatus::Status response_status_;
492 net::URLRequestContextGetter* request_context_;
493 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServerTestHelper);
496 // TODO(shess): Disabled pending new data for third_party/safe_browsing/testing/
497 IN_PROC_BROWSER_TEST_F(SafeBrowsingServerTest,
498 DISABLED_SafeBrowsingServerTest) {
499 LOG(INFO) << "Start test";
500 ASSERT_TRUE(InitSafeBrowsingService());
502 net::URLRequestContextGetter* request_context =
503 browser()->profile()->GetRequestContext();
504 scoped_refptr<SafeBrowsingServerTestHelper> safe_browsing_helper(
505 new SafeBrowsingServerTestHelper(this, request_context));
506 int last_step = 0;
508 // Waits and makes sure safebrowsing update is not happening.
509 // The wait will stop once OnWaitForStatusUpdateDone in
510 // safe_browsing_helper is called and status from safe_browsing_service_
511 // is checked.
512 safe_browsing_helper->UpdateStatus();
513 EXPECT_TRUE(is_database_ready());
514 EXPECT_FALSE(is_update_scheduled());
515 EXPECT_TRUE(last_update().is_null());
516 // Starts updates. After each update, the test will fetch a list of URLs with
517 // expected results to verify with safebrowsing service. If there is no error,
518 // the test moves on to the next step to get more update chunks.
519 // This repeats till there is no update data.
520 for (int step = 1;; step++) {
521 // Every step should be a fresh start.
522 SCOPED_TRACE(base::StringPrintf("step=%d", step));
523 EXPECT_TRUE(is_database_ready());
524 EXPECT_FALSE(is_update_scheduled());
526 // Starts safebrowsing update on IO thread. Waits till scheduled
527 // update finishes.
528 base::Time now = base::Time::Now();
529 SetTestStep(step);
530 ForceUpdate();
532 safe_browsing_helper->UpdateStatus();
533 EXPECT_TRUE(is_database_ready());
534 EXPECT_FALSE(is_update_scheduled());
535 EXPECT_FALSE(last_update().is_null());
536 if (last_update() < now) {
537 // This means no data available anymore.
538 break;
541 // Fetches URLs to verify and waits till server responses with data.
542 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
543 safe_browsing_helper->FetchUrlsToVerify(test_server(), step));
545 std::vector<PhishingUrl> phishing_urls;
546 EXPECT_TRUE(ParsePhishingUrls(safe_browsing_helper->response_data(),
547 &phishing_urls));
548 EXPECT_GT(phishing_urls.size(), 0U);
549 for (size_t j = 0; j < phishing_urls.size(); ++j) {
550 // Verifes with server if a URL is a phishing URL and waits till server
551 // responses.
552 safe_browsing_helper->CheckUrl(GURL(phishing_urls[j].url));
553 if (phishing_urls[j].is_phishing) {
554 EXPECT_TRUE(is_checked_url_in_db())
555 << phishing_urls[j].url
556 << " is_phishing: " << phishing_urls[j].is_phishing
557 << " test step: " << step;
558 EXPECT_FALSE(is_checked_url_safe())
559 << phishing_urls[j].url
560 << " is_phishing: " << phishing_urls[j].is_phishing
561 << " test step: " << step;
562 } else {
563 EXPECT_TRUE(is_checked_url_safe())
564 << phishing_urls[j].url
565 << " is_phishing: " << phishing_urls[j].is_phishing
566 << " test step: " << step;
569 // TODO(lzheng): We should verify the fetched database with local
570 // database to make sure they match.
571 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
572 safe_browsing_helper->FetchDBToVerify(test_server(), step));
573 EXPECT_GT(safe_browsing_helper->response_data().size(), 0U);
574 last_step = step;
577 // Verifies with server if test is done and waits till server responses.
578 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
579 safe_browsing_helper->VerifyTestComplete(test_server(), last_step));
580 EXPECT_EQ("yes", safe_browsing_helper->response_data());