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     config.client_name = "browser_tests";
    122     return config;
    123   }
    124 
    125  private:
    126   virtual ~FakeSafeBrowsingService() {}
    127 
    128   std::string url_prefix_;
    129 
    130   DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService);
    131 };
    132 
    133 // Factory that creates FakeSafeBrowsingService instances.
    134 class TestSafeBrowsingServiceFactory : public SafeBrowsingServiceFactory {
    135  public:
    136   explicit TestSafeBrowsingServiceFactory(const std::string& url_prefix)
    137       : url_prefix_(url_prefix) {}
    138 
    139   virtual SafeBrowsingService* CreateSafeBrowsingService() OVERRIDE {
    140     return new FakeSafeBrowsingService(url_prefix_);
    141   }
    142 
    143  private:
    144   std::string url_prefix_;
    145 };
    146 
    147 }  // namespace
    148 
    149 // This starts the browser and keeps status of states related to SafeBrowsing.
    150 class SafeBrowsingServerTest : public InProcessBrowserTest {
    151  public:
    152   SafeBrowsingServerTest()
    153     : safe_browsing_service_(NULL),
    154       is_database_ready_(true),
    155       is_update_scheduled_(false),
    156       is_checked_url_in_db_(false),
    157       is_checked_url_safe_(false) {
    158   }
    159 
    160   virtual ~SafeBrowsingServerTest() {
    161   }
    162 
    163   void UpdateSafeBrowsingStatus() {
    164     ASSERT_TRUE(safe_browsing_service_);
    165     base::AutoLock lock(update_status_mutex_);
    166     last_update_ = safe_browsing_service_->protocol_manager_->last_update();
    167     is_update_scheduled_ =
    168         safe_browsing_service_->protocol_manager_->update_timer_.IsRunning();
    169   }
    170 
    171   void ForceUpdate() {
    172     content::WindowedNotificationObserver observer(
    173         chrome::NOTIFICATION_SAFE_BROWSING_UPDATE_COMPLETE,
    174         content::Source<SafeBrowsingDatabaseManager>(database_manager()));
    175     BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
    176         base::Bind(&SafeBrowsingServerTest::ForceUpdateOnIOThread,
    177                    this));
    178     observer.Wait();
    179   }
    180 
    181   void ForceUpdateOnIOThread() {
    182     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
    183     ASSERT_TRUE(safe_browsing_service_);
    184     safe_browsing_service_->protocol_manager_->ForceScheduleNextUpdate(
    185         base::TimeDelta::FromSeconds(0));
    186   }
    187 
    188   void CheckIsDatabaseReady() {
    189     base::AutoLock lock(update_status_mutex_);
    190     is_database_ready_ = !database_manager()->database_update_in_progress_;
    191   }
    192 
    193   void CheckUrl(SafeBrowsingDatabaseManager::Client* helper, const GURL& url) {
    194     ASSERT_TRUE(safe_browsing_service_);
    195     base::AutoLock lock(update_status_mutex_);
    196     if (database_manager()->CheckBrowseUrl(url, helper)) {
    197       is_checked_url_in_db_ = false;
    198       is_checked_url_safe_ = true;
    199     } else {
    200       // In this case, Safebrowsing service will fetch the full hash
    201       // from the server and examine that. Once it is done,
    202       // set_is_checked_url_safe() will be called via callback.
    203       is_checked_url_in_db_ = true;
    204     }
    205   }
    206 
    207   SafeBrowsingDatabaseManager* database_manager() {
    208     return safe_browsing_service_->database_manager().get();
    209   }
    210 
    211   bool is_checked_url_in_db() {
    212     base::AutoLock l(update_status_mutex_);
    213     return is_checked_url_in_db_;
    214   }
    215 
    216   void set_is_checked_url_safe(bool safe) {
    217     base::AutoLock l(update_status_mutex_);
    218     is_checked_url_safe_ = safe;
    219   }
    220 
    221   bool is_checked_url_safe() {
    222     base::AutoLock l(update_status_mutex_);
    223     return is_checked_url_safe_;
    224   }
    225 
    226   bool is_database_ready() {
    227     base::AutoLock l(update_status_mutex_);
    228     return is_database_ready_;
    229   }
    230 
    231   base::Time last_update() {
    232     base::AutoLock l(update_status_mutex_);
    233     return last_update_;
    234   }
    235 
    236   bool is_update_scheduled() {
    237     base::AutoLock l(update_status_mutex_);
    238     return is_update_scheduled_;
    239   }
    240 
    241   base::MessageLoop* SafeBrowsingMessageLoop() {
    242     return database_manager()->safe_browsing_thread_->message_loop();
    243   }
    244 
    245   const net::SpawnedTestServer& test_server() const {
    246     return *test_server_;
    247   }
    248 
    249  protected:
    250   bool InitSafeBrowsingService() {
    251     safe_browsing_service_ = g_browser_process->safe_browsing_service();
    252     return safe_browsing_service_ != NULL;
    253   }
    254 
    255   virtual void SetUp() OVERRIDE {
    256     base::FilePath datafile_path;
    257     ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &datafile_path));
    258 
    259     datafile_path = datafile_path.Append(FILE_PATH_LITERAL("third_party"))
    260           .Append(FILE_PATH_LITERAL("safe_browsing"))
    261           .Append(FILE_PATH_LITERAL("testing"))
    262           .Append(kDataFile);
    263     test_server_.reset(new LocalSafeBrowsingTestServer(datafile_path));
    264     ASSERT_TRUE(test_server_->Start());
    265     LOG(INFO) << "server is " << test_server_->host_port_pair().ToString();
    266 
    267     // Point to the testing server for all SafeBrowsing requests.
    268     std::string url_prefix = test_server_->GetURL("safebrowsing").spec();
    269     sb_factory_.reset(new TestSafeBrowsingServiceFactory(url_prefix));
    270     SafeBrowsingService::RegisterFactory(sb_factory_.get());
    271 
    272     InProcessBrowserTest::SetUp();
    273   }
    274 
    275   virtual void TearDown() OVERRIDE {
    276     InProcessBrowserTest::TearDown();
    277 
    278     SafeBrowsingService::RegisterFactory(NULL);
    279   }
    280 
    281   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    282     // This test uses loopback. No need to use IPv6 especially it makes
    283     // local requests slow on Windows trybot when ipv6 local address [::1]
    284     // is not setup.
    285     command_line->AppendSwitch(switches::kDisableIPv6);
    286 
    287     // TODO(lzheng): The test server does not understand download related
    288     // requests. We need to fix the server.
    289     command_line->AppendSwitch(switches::kSbDisableDownloadProtection);
    290 
    291     // TODO(gcasto): Generate new testing data that includes the
    292     // client-side phishing whitelist.
    293     command_line->AppendSwitch(
    294         switches::kDisableClientSidePhishingDetection);
    295 
    296     // TODO(kalman): Generate new testing data that includes the extension
    297     // blacklist.
    298     command_line->AppendSwitch(switches::kSbDisableExtensionBlacklist);
    299 
    300     // TODO(tburkard): Generate new testing data that includes the side-effect
    301     // free whitelist.
    302     command_line->AppendSwitch(switches::kSbDisableSideEffectFreeWhitelist);
    303   }
    304 
    305   void SetTestStep(int step) {
    306     std::string test_step = base::StringPrintf("test_step=%d", step);
    307     safe_browsing_service_->protocol_manager_->set_additional_query(test_step);
    308   }
    309 
    310  private:
    311   scoped_ptr<TestSafeBrowsingServiceFactory> sb_factory_;
    312 
    313   SafeBrowsingService* safe_browsing_service_;
    314 
    315   scoped_ptr<net::SpawnedTestServer> test_server_;
    316 
    317   // Protects all variables below since they are read on UI thread
    318   // but updated on IO thread or safebrowsing thread.
    319   base::Lock update_status_mutex_;
    320 
    321   // States associated with safebrowsing service updates.
    322   bool is_database_ready_;
    323   base::Time last_update_;
    324   bool is_update_scheduled_;
    325   // Indicates if there is a match between a URL's prefix and safebrowsing
    326   // database (thus potentially it is a phishing URL).
    327   bool is_checked_url_in_db_;
    328   // True if last verified URL is not a phishing URL and thus it is safe.
    329   bool is_checked_url_safe_;
    330 
    331   DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServerTest);
    332 };
    333 
    334 // A ref counted helper class that handles callbacks between IO thread and UI
    335 // thread.
    336 class SafeBrowsingServerTestHelper
    337     : public base::RefCountedThreadSafe<SafeBrowsingServerTestHelper>,
    338       public SafeBrowsingDatabaseManager::Client,
    339       public net::URLFetcherDelegate {
    340  public:
    341   SafeBrowsingServerTestHelper(SafeBrowsingServerTest* safe_browsing_test,
    342                                net::URLRequestContextGetter* request_context)
    343       : safe_browsing_test_(safe_browsing_test),
    344         response_status_(net::URLRequestStatus::FAILED),
    345         request_context_(request_context) {
    346   }
    347 
    348   // Callbacks for SafeBrowsingDatabaseManager::Client.
    349   virtual void OnCheckBrowseUrlResult(const GURL& url,
    350                                       SBThreatType threat_type) OVERRIDE {
    351     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
    352     EXPECT_TRUE(safe_browsing_test_->is_checked_url_in_db());
    353     safe_browsing_test_->set_is_checked_url_safe(
    354         threat_type == SB_THREAT_TYPE_SAFE);
    355     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
    356         base::Bind(&SafeBrowsingServerTestHelper::OnCheckUrlDone, this));
    357   }
    358 
    359   virtual void OnBlockingPageComplete(bool proceed) {
    360     NOTREACHED() << "Not implemented.";
    361   }
    362 
    363   // Functions and callbacks related to CheckUrl. These are used to verify
    364   // phishing URLs.
    365   void CheckUrl(const GURL& url) {
    366     BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
    367         base::Bind(&SafeBrowsingServerTestHelper::CheckUrlOnIOThread,
    368                    this, url));
    369     content::RunMessageLoop();
    370   }
    371   void CheckUrlOnIOThread(const GURL& url) {
    372     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
    373     safe_browsing_test_->CheckUrl(this, url);
    374     if (!safe_browsing_test_->is_checked_url_in_db()) {
    375       // Ends the checking since this URL's prefix is not in database.
    376       BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
    377         base::Bind(&SafeBrowsingServerTestHelper::OnCheckUrlDone, this));
    378     }
    379     // Otherwise, OnCheckUrlDone is called in OnUrlCheckResult since
    380     // safebrowsing service further fetches hashes from safebrowsing server.
    381   }
    382 
    383   void OnCheckUrlDone() {
    384     StopUILoop();
    385   }
    386 
    387   // Updates status from IO Thread.
    388   void CheckStatusOnIOThread() {
    389     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
    390     safe_browsing_test_->UpdateSafeBrowsingStatus();
    391     safe_browsing_test_->SafeBrowsingMessageLoop()->PostTask(FROM_HERE,
    392         base::Bind(&SafeBrowsingServerTestHelper::CheckIsDatabaseReady, this));
    393   }
    394 
    395   // Checks status in SafeBrowsing Thread.
    396   void CheckIsDatabaseReady() {
    397     EXPECT_EQ(base::MessageLoop::current(),
    398               safe_browsing_test_->SafeBrowsingMessageLoop());
    399     safe_browsing_test_->CheckIsDatabaseReady();
    400     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
    401         base::Bind(&SafeBrowsingServerTestHelper::OnWaitForStatusUpdateDone,
    402                    this));
    403   }
    404 
    405   void OnWaitForStatusUpdateDone() {
    406     StopUILoop();
    407   }
    408 
    409   // Update safebrowsing status.
    410   void UpdateStatus() {
    411     BrowserThread::PostTask(
    412         BrowserThread::IO,
    413         FROM_HERE,
    414         base::Bind(&SafeBrowsingServerTestHelper::CheckStatusOnIOThread, this));
    415     // Will continue after OnWaitForStatusUpdateDone().
    416     content::RunMessageLoop();
    417   }
    418 
    419   // Calls test server to fetch database for verification.
    420   net::URLRequestStatus::Status FetchDBToVerify(
    421       const net::SpawnedTestServer& test_server,
    422       int test_step) {
    423     // TODO(lzheng): Remove chunk_type=add once it is not needed by the server.
    424     std::string path = base::StringPrintf(
    425         "%s?client=chromium&appver=1.0&pver=3.0&test_step=%d&chunk_type=add",
    426         kDBVerifyPath, test_step);
    427     return FetchUrl(test_server.GetURL(path));
    428   }
    429 
    430   // Calls test server to fetch URLs for verification.
    431   net::URLRequestStatus::Status FetchUrlsToVerify(
    432       const net::SpawnedTestServer& test_server,
    433       int test_step) {
    434     std::string path = base::StringPrintf(
    435         "%s?client=chromium&appver=1.0&pver=3.0&test_step=%d",
    436         kUrlVerifyPath, test_step);
    437     return FetchUrl(test_server.GetURL(path));
    438   }
    439 
    440   // Calls test server to check if test data is done. E.g.: if there is a
    441   // bad URL that server expects test to fetch full hash but the test didn't,
    442   // this verification will fail.
    443   net::URLRequestStatus::Status VerifyTestComplete(
    444       const net::SpawnedTestServer& test_server,
    445       int test_step) {
    446     std::string path = base::StringPrintf(
    447         "%s?test_step=%d", kTestCompletePath, test_step);
    448     return FetchUrl(test_server.GetURL(path));
    449   }
    450 
    451   // Callback for URLFetcher.
    452   virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE {
    453     source->GetResponseAsString(&response_data_);
    454     response_status_ = source->GetStatus().status();
    455     StopUILoop();
    456   }
    457 
    458   const std::string& response_data() {
    459     return response_data_;
    460   }
    461 
    462  private:
    463   friend class base::RefCountedThreadSafe<SafeBrowsingServerTestHelper>;
    464   virtual ~SafeBrowsingServerTestHelper() {}
    465 
    466   // Stops UI loop after desired status is updated.
    467   void StopUILoop() {
    468     EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
    469     base::MessageLoopForUI::current()->Quit();
    470   }
    471 
    472   // Fetch a URL. If message_loop_started is true, starts the message loop
    473   // so the caller could wait till OnURLFetchComplete is called.
    474   net::URLRequestStatus::Status FetchUrl(const GURL& url) {
    475     url_fetcher_.reset(net::URLFetcher::Create(
    476         url, net::URLFetcher::GET, this));
    477     url_fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE);
    478     url_fetcher_->SetRequestContext(request_context_);
    479     url_fetcher_->Start();
    480     content::RunMessageLoop();
    481     return response_status_;
    482   }
    483 
    484   base::OneShotTimer<SafeBrowsingServerTestHelper> check_update_timer_;
    485   SafeBrowsingServerTest* safe_browsing_test_;
    486   scoped_ptr<net::URLFetcher> url_fetcher_;
    487   std::string response_data_;
    488   net::URLRequestStatus::Status response_status_;
    489   net::URLRequestContextGetter* request_context_;
    490   DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServerTestHelper);
    491 };
    492 
    493 // TODO(shess): Disabled pending new data for third_party/safe_browsing/testing/
    494 IN_PROC_BROWSER_TEST_F(SafeBrowsingServerTest,
    495                        DISABLED_SafeBrowsingServerTest) {
    496   LOG(INFO) << "Start test";
    497   ASSERT_TRUE(InitSafeBrowsingService());
    498 
    499   net::URLRequestContextGetter* request_context =
    500       browser()->profile()->GetRequestContext();
    501   scoped_refptr<SafeBrowsingServerTestHelper> safe_browsing_helper(
    502       new SafeBrowsingServerTestHelper(this, request_context));
    503   int last_step = 0;
    504 
    505   // Waits and makes sure safebrowsing update is not happening.
    506   // The wait will stop once OnWaitForStatusUpdateDone in
    507   // safe_browsing_helper is called and status from safe_browsing_service_
    508   // is checked.
    509   safe_browsing_helper->UpdateStatus();
    510   EXPECT_TRUE(is_database_ready());
    511   EXPECT_FALSE(is_update_scheduled());
    512   EXPECT_TRUE(last_update().is_null());
    513   // Starts updates. After each update, the test will fetch a list of URLs with
    514   // expected results to verify with safebrowsing service. If there is no error,
    515   // the test moves on to the next step to get more update chunks.
    516   // This repeats till there is no update data.
    517   for (int step = 1;; step++) {
    518     // Every step should be a fresh start.
    519     SCOPED_TRACE(base::StringPrintf("step=%d", step));
    520     EXPECT_TRUE(is_database_ready());
    521     EXPECT_FALSE(is_update_scheduled());
    522 
    523     // Starts safebrowsing update on IO thread. Waits till scheduled
    524     // update finishes.
    525     base::Time now = base::Time::Now();
    526     SetTestStep(step);
    527     ForceUpdate();
    528 
    529     safe_browsing_helper->UpdateStatus();
    530     EXPECT_TRUE(is_database_ready());
    531     EXPECT_FALSE(is_update_scheduled());
    532     EXPECT_FALSE(last_update().is_null());
    533     if (last_update() < now) {
    534       // This means no data available anymore.
    535       break;
    536     }
    537 
    538     // Fetches URLs to verify and waits till server responses with data.
    539     EXPECT_EQ(net::URLRequestStatus::SUCCESS,
    540               safe_browsing_helper->FetchUrlsToVerify(test_server(), step));
    541 
    542     std::vector<PhishingUrl> phishing_urls;
    543     EXPECT_TRUE(ParsePhishingUrls(safe_browsing_helper->response_data(),
    544                                   &phishing_urls));
    545     EXPECT_GT(phishing_urls.size(), 0U);
    546     for (size_t j = 0; j < phishing_urls.size(); ++j) {
    547       // Verifes with server if a URL is a phishing URL and waits till server
    548       // responses.
    549       safe_browsing_helper->CheckUrl(GURL(phishing_urls[j].url));
    550       if (phishing_urls[j].is_phishing) {
    551         EXPECT_TRUE(is_checked_url_in_db())
    552             << phishing_urls[j].url
    553             << " is_phishing: " << phishing_urls[j].is_phishing
    554             << " test step: " << step;
    555         EXPECT_FALSE(is_checked_url_safe())
    556             << phishing_urls[j].url
    557             << " is_phishing: " << phishing_urls[j].is_phishing
    558             << " test step: " << step;
    559       } else {
    560         EXPECT_TRUE(is_checked_url_safe())
    561             << phishing_urls[j].url
    562             << " is_phishing: " << phishing_urls[j].is_phishing
    563             << " test step: " << step;
    564       }
    565     }
    566     // TODO(lzheng): We should verify the fetched database with local
    567     // database to make sure they match.
    568     EXPECT_EQ(net::URLRequestStatus::SUCCESS,
    569               safe_browsing_helper->FetchDBToVerify(test_server(), step));
    570     EXPECT_GT(safe_browsing_helper->response_data().size(), 0U);
    571     last_step = step;
    572   }
    573 
    574   // Verifies with server if test is done and waits till server responses.
    575   EXPECT_EQ(net::URLRequestStatus::SUCCESS,
    576             safe_browsing_helper->VerifyTestComplete(test_server(), last_step));
    577   EXPECT_EQ("yes", safe_browsing_helper->response_data());
    578 }
    579