Home | History | Annotate | Download | only in safe_browsing
      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 "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"
     54 
     55 using content::BrowserThread;
     56 
     57 namespace {
     58 
     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";
     64 
     65 struct PhishingUrl {
     66   std::string url;
     67   std::string list_name;
     68   bool is_phishing;
     69 };
     70 
     71 // Parses server response for verify_urls. The expected format is:
     72 //
     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;
     80 
     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;
     93     }
     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;
    104     }
    105     phishing_urls->push_back(phishing_url);
    106   }
    107   return true;
    108 }
    109 
    110 class FakeSafeBrowsingService : public SafeBrowsingService {
    111  public:
    112   explicit FakeSafeBrowsingService(const std::string& url_prefix)
    113       : url_prefix_(url_prefix) {}
    114 
    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;
    126   }
    127 
    128  private:
    129   virtual ~FakeSafeBrowsingService() {}
    130 
    131   std::string url_prefix_;
    132 
    133   DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService);
    134 };
    135 
    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) {}
    141 
    142   virtual SafeBrowsingService* CreateSafeBrowsingService() OVERRIDE {
    143     return new FakeSafeBrowsingService(url_prefix_);
    144   }
    145 
    146  private:
    147   std::string url_prefix_;
    148 };
    149 
    150 }  // namespace
    151 
    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) {
    161   }
    162 
    163   virtual ~SafeBrowsingServerTest() {
    164   }
    165 
    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();
    172   }
    173 
    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();
    182   }
    183 
    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));
    189   }
    190 
    191   void CheckIsDatabaseReady() {
    192     base::AutoLock lock(update_status_mutex_);
    193     is_database_ready_ = !database_manager()->database_update_in_progress_;
    194   }
    195 
    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;
    207     }
    208   }
    209 
    210   SafeBrowsingDatabaseManager* database_manager() {
    211     return safe_browsing_service_->database_manager().get();
    212   }
    213 
    214   bool is_checked_url_in_db() {
    215     base::AutoLock l(update_status_mutex_);
    216     return is_checked_url_in_db_;
    217   }
    218 
    219   void set_is_checked_url_safe(bool safe) {
    220     base::AutoLock l(update_status_mutex_);
    221     is_checked_url_safe_ = safe;
    222   }
    223 
    224   bool is_checked_url_safe() {
    225     base::AutoLock l(update_status_mutex_);
    226     return is_checked_url_safe_;
    227   }
    228 
    229   bool is_database_ready() {
    230     base::AutoLock l(update_status_mutex_);
    231     return is_database_ready_;
    232   }
    233 
    234   base::Time last_update() {
    235     base::AutoLock l(update_status_mutex_);
    236     return last_update_;
    237   }
    238 
    239   bool is_update_scheduled() {
    240     base::AutoLock l(update_status_mutex_);
    241     return is_update_scheduled_;
    242   }
    243 
    244   base::MessageLoop* SafeBrowsingMessageLoop() {
    245     return database_manager()->safe_browsing_thread_->message_loop();
    246   }
    247 
    248   const net::SpawnedTestServer& test_server() const {
    249     return *test_server_;
    250   }
    251 
    252  protected:
    253   bool InitSafeBrowsingService() {
    254     safe_browsing_service_ = g_browser_process->safe_browsing_service();
    255     return safe_browsing_service_ != NULL;
    256   }
    257 
    258   virtual void SetUp() OVERRIDE {
    259     base::FilePath datafile_path;
    260     ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &datafile_path));
    261 
    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();
    269 
    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());
    274 
    275     InProcessBrowserTest::SetUp();
    276   }
    277 
    278   virtual void TearDown() OVERRIDE {
    279     InProcessBrowserTest::TearDown();
    280 
    281     SafeBrowsingService::RegisterFactory(NULL);
    282   }
    283 
    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);
    289 
    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);
    293 
    294     // TODO(gcasto): Generate new testing data that includes the
    295     // client-side phishing whitelist.
    296     command_line->AppendSwitch(
    297         switches::kDisableClientSidePhishingDetection);
    298 
    299     // TODO(kalman): Generate new testing data that includes the extension
    300     // blacklist.
    301     command_line->AppendSwitch(switches::kSbDisableExtensionBlacklist);
    302 
    303     // TODO(tburkard): Generate new testing data that includes the side-effect
    304     // free whitelist.
    305     command_line->AppendSwitch(switches::kSbDisableSideEffectFreeWhitelist);
    306   }
    307 
    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);
    311   }
    312 
    313  private:
    314   scoped_ptr<TestSafeBrowsingServiceFactory> sb_factory_;
    315 
    316   SafeBrowsingService* safe_browsing_service_;
    317 
    318   scoped_ptr<net::SpawnedTestServer> test_server_;
    319 
    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_;
    323 
    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_;
    333 
    334   DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServerTest);
    335 };
    336 
    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) {
    349   }
    350 
    351   // Callbacks for SafeBrowsingDatabaseManager::Client.
    352   virtual void OnCheckBrowseUrlResult(const GURL& url,
    353                                       SBThreatType threat_type,
    354                                       const std::string& metadata) OVERRIDE {
    355     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
    356     EXPECT_TRUE(safe_browsing_test_->is_checked_url_in_db());
    357     safe_browsing_test_->set_is_checked_url_safe(
    358         threat_type == SB_THREAT_TYPE_SAFE);
    359     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
    360         base::Bind(&SafeBrowsingServerTestHelper::OnCheckUrlDone, this));
    361   }
    362 
    363   virtual void OnBlockingPageComplete(bool proceed) {
    364     NOTREACHED() << "Not implemented.";
    365   }
    366 
    367   // Functions and callbacks related to CheckUrl. These are used to verify
    368   // phishing URLs.
    369   void CheckUrl(const GURL& url) {
    370     BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
    371         base::Bind(&SafeBrowsingServerTestHelper::CheckUrlOnIOThread,
    372                    this, url));
    373     content::RunMessageLoop();
    374   }
    375   void CheckUrlOnIOThread(const GURL& url) {
    376     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
    377     safe_browsing_test_->CheckUrl(this, url);
    378     if (!safe_browsing_test_->is_checked_url_in_db()) {
    379       // Ends the checking since this URL's prefix is not in database.
    380       BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
    381         base::Bind(&SafeBrowsingServerTestHelper::OnCheckUrlDone, this));
    382     }
    383     // Otherwise, OnCheckUrlDone is called in OnUrlCheckResult since
    384     // safebrowsing service further fetches hashes from safebrowsing server.
    385   }
    386 
    387   void OnCheckUrlDone() {
    388     StopUILoop();
    389   }
    390 
    391   // Updates status from IO Thread.
    392   void CheckStatusOnIOThread() {
    393     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
    394     safe_browsing_test_->UpdateSafeBrowsingStatus();
    395     safe_browsing_test_->SafeBrowsingMessageLoop()->PostTask(FROM_HERE,
    396         base::Bind(&SafeBrowsingServerTestHelper::CheckIsDatabaseReady, this));
    397   }
    398 
    399   // Checks status in SafeBrowsing Thread.
    400   void CheckIsDatabaseReady() {
    401     EXPECT_EQ(base::MessageLoop::current(),
    402               safe_browsing_test_->SafeBrowsingMessageLoop());
    403     safe_browsing_test_->CheckIsDatabaseReady();
    404     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
    405         base::Bind(&SafeBrowsingServerTestHelper::OnWaitForStatusUpdateDone,
    406                    this));
    407   }
    408 
    409   void OnWaitForStatusUpdateDone() {
    410     StopUILoop();
    411   }
    412 
    413   // Update safebrowsing status.
    414   void UpdateStatus() {
    415     BrowserThread::PostTask(
    416         BrowserThread::IO,
    417         FROM_HERE,
    418         base::Bind(&SafeBrowsingServerTestHelper::CheckStatusOnIOThread, this));
    419     // Will continue after OnWaitForStatusUpdateDone().
    420     content::RunMessageLoop();
    421   }
    422 
    423   // Calls test server to fetch database for verification.
    424   net::URLRequestStatus::Status FetchDBToVerify(
    425       const net::SpawnedTestServer& test_server,
    426       int test_step) {
    427     // TODO(lzheng): Remove chunk_type=add once it is not needed by the server.
    428     std::string path = base::StringPrintf(
    429         "%s?client=chromium&appver=1.0&pver=3.0&test_step=%d&chunk_type=add",
    430         kDBVerifyPath, test_step);
    431     return FetchUrl(test_server.GetURL(path));
    432   }
    433 
    434   // Calls test server to fetch URLs for verification.
    435   net::URLRequestStatus::Status FetchUrlsToVerify(
    436       const net::SpawnedTestServer& test_server,
    437       int test_step) {
    438     std::string path = base::StringPrintf(
    439         "%s?client=chromium&appver=1.0&pver=3.0&test_step=%d",
    440         kUrlVerifyPath, test_step);
    441     return FetchUrl(test_server.GetURL(path));
    442   }
    443 
    444   // Calls test server to check if test data is done. E.g.: if there is a
    445   // bad URL that server expects test to fetch full hash but the test didn't,
    446   // this verification will fail.
    447   net::URLRequestStatus::Status VerifyTestComplete(
    448       const net::SpawnedTestServer& test_server,
    449       int test_step) {
    450     std::string path = base::StringPrintf(
    451         "%s?test_step=%d", kTestCompletePath, test_step);
    452     return FetchUrl(test_server.GetURL(path));
    453   }
    454 
    455   // Callback for URLFetcher.
    456   virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE {
    457     source->GetResponseAsString(&response_data_);
    458     response_status_ = source->GetStatus().status();
    459     StopUILoop();
    460   }
    461 
    462   const std::string& response_data() {
    463     return response_data_;
    464   }
    465 
    466  private:
    467   friend class base::RefCountedThreadSafe<SafeBrowsingServerTestHelper>;
    468   virtual ~SafeBrowsingServerTestHelper() {}
    469 
    470   // Stops UI loop after desired status is updated.
    471   void StopUILoop() {
    472     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
    473     base::MessageLoopForUI::current()->Quit();
    474   }
    475 
    476   // Fetch a URL. If message_loop_started is true, starts the message loop
    477   // so the caller could wait till OnURLFetchComplete is called.
    478   net::URLRequestStatus::Status FetchUrl(const GURL& url) {
    479     url_fetcher_.reset(net::URLFetcher::Create(
    480         url, net::URLFetcher::GET, this));
    481     url_fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE);
    482     url_fetcher_->SetRequestContext(request_context_);
    483     url_fetcher_->Start();
    484     content::RunMessageLoop();
    485     return response_status_;
    486   }
    487 
    488   base::OneShotTimer<SafeBrowsingServerTestHelper> check_update_timer_;
    489   SafeBrowsingServerTest* safe_browsing_test_;
    490   scoped_ptr<net::URLFetcher> url_fetcher_;
    491   std::string response_data_;
    492   net::URLRequestStatus::Status response_status_;
    493   net::URLRequestContextGetter* request_context_;
    494   DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServerTestHelper);
    495 };
    496 
    497 // TODO(shess): Disabled pending new data for third_party/safe_browsing/testing/
    498 IN_PROC_BROWSER_TEST_F(SafeBrowsingServerTest,
    499                        DISABLED_SafeBrowsingServerTest) {
    500   LOG(INFO) << "Start test";
    501   ASSERT_TRUE(InitSafeBrowsingService());
    502 
    503   net::URLRequestContextGetter* request_context =
    504       browser()->profile()->GetRequestContext();
    505   scoped_refptr<SafeBrowsingServerTestHelper> safe_browsing_helper(
    506       new SafeBrowsingServerTestHelper(this, request_context));
    507   int last_step = 0;
    508 
    509   // Waits and makes sure safebrowsing update is not happening.
    510   // The wait will stop once OnWaitForStatusUpdateDone in
    511   // safe_browsing_helper is called and status from safe_browsing_service_
    512   // is checked.
    513   safe_browsing_helper->UpdateStatus();
    514   EXPECT_TRUE(is_database_ready());
    515   EXPECT_FALSE(is_update_scheduled());
    516   EXPECT_TRUE(last_update().is_null());
    517   // Starts updates. After each update, the test will fetch a list of URLs with
    518   // expected results to verify with safebrowsing service. If there is no error,
    519   // the test moves on to the next step to get more update chunks.
    520   // This repeats till there is no update data.
    521   for (int step = 1;; step++) {
    522     // Every step should be a fresh start.
    523     SCOPED_TRACE(base::StringPrintf("step=%d", step));
    524     EXPECT_TRUE(is_database_ready());
    525     EXPECT_FALSE(is_update_scheduled());
    526 
    527     // Starts safebrowsing update on IO thread. Waits till scheduled
    528     // update finishes.
    529     base::Time now = base::Time::Now();
    530     SetTestStep(step);
    531     ForceUpdate();
    532 
    533     safe_browsing_helper->UpdateStatus();
    534     EXPECT_TRUE(is_database_ready());
    535     EXPECT_FALSE(is_update_scheduled());
    536     EXPECT_FALSE(last_update().is_null());
    537     if (last_update() < now) {
    538       // This means no data available anymore.
    539       break;
    540     }
    541 
    542     // Fetches URLs to verify and waits till server responses with data.
    543     EXPECT_EQ(net::URLRequestStatus::SUCCESS,
    544               safe_browsing_helper->FetchUrlsToVerify(test_server(), step));
    545 
    546     std::vector<PhishingUrl> phishing_urls;
    547     EXPECT_TRUE(ParsePhishingUrls(safe_browsing_helper->response_data(),
    548                                   &phishing_urls));
    549     EXPECT_GT(phishing_urls.size(), 0U);
    550     for (size_t j = 0; j < phishing_urls.size(); ++j) {
    551       // Verifes with server if a URL is a phishing URL and waits till server
    552       // responses.
    553       safe_browsing_helper->CheckUrl(GURL(phishing_urls[j].url));
    554       if (phishing_urls[j].is_phishing) {
    555         EXPECT_TRUE(is_checked_url_in_db())
    556             << phishing_urls[j].url
    557             << " is_phishing: " << phishing_urls[j].is_phishing
    558             << " test step: " << step;
    559         EXPECT_FALSE(is_checked_url_safe())
    560             << phishing_urls[j].url
    561             << " is_phishing: " << phishing_urls[j].is_phishing
    562             << " test step: " << step;
    563       } else {
    564         EXPECT_TRUE(is_checked_url_safe())
    565             << phishing_urls[j].url
    566             << " is_phishing: " << phishing_urls[j].is_phishing
    567             << " test step: " << step;
    568       }
    569     }
    570     // TODO(lzheng): We should verify the fetched database with local
    571     // database to make sure they match.
    572     EXPECT_EQ(net::URLRequestStatus::SUCCESS,
    573               safe_browsing_helper->FetchDBToVerify(test_server(), step));
    574     EXPECT_GT(safe_browsing_helper->response_data().size(), 0U);
    575     last_step = step;
    576   }
    577 
    578   // Verifies with server if test is done and waits till server responses.
    579   EXPECT_EQ(net::URLRequestStatus::SUCCESS,
    580             safe_browsing_helper->VerifyTestComplete(test_server(), last_step));
    581   EXPECT_EQ("yes", safe_browsing_helper->response_data());
    582 }
    583