1// Copyright (c) 2011 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/command_line.h"
20#include "base/environment.h"
21#include "base/path_service.h"
22#include "base/process_util.h"
23#include "base/string_number_conversions.h"
24#include "base/string_util.h"
25#include "base/string_split.h"
26#include "base/synchronization/lock.h"
27#include "base/threading/platform_thread.h"
28#include "base/time.h"
29#include "base/utf_string_conversions.h"
30#include "chrome/browser/browser_process.h"
31#include "chrome/browser/profiles/profile.h"
32#include "chrome/browser/safe_browsing/protocol_manager.h"
33#include "chrome/browser/safe_browsing/safe_browsing_service.h"
34#include "chrome/common/chrome_switches.h"
35#include "chrome/common/url_constants.h"
36#include "chrome/test/in_process_browser_test.h"
37#include "content/browser/browser_thread.h"
38#include "content/browser/renderer_host/resource_dispatcher_host.h"
39#include "base/test/test_timeouts.h"
40#include "chrome/test/ui_test_utils.h"
41#include "net/base/host_resolver.h"
42#include "net/base/load_flags.h"
43#include "net/base/net_log.h"
44#include "net/test/python_utils.h"
45#include "testing/gtest/include/gtest/gtest.h"
46
47namespace {
48
49const FilePath::CharType kDataFile[] = FILE_PATH_LITERAL("testing_input.dat");
50const char kUrlVerifyPath[] = "/safebrowsing/verify_urls";
51const char kDBVerifyPath[] = "/safebrowsing/verify_database";
52const char kDBResetPath[] = "/reset";
53const char kTestCompletePath[] = "/test_complete";
54
55struct PhishingUrl {
56  std::string url;
57  std::string list_name;
58  bool is_phishing;
59};
60
61// Parses server response for verify_urls. The expected format is:
62//
63// first.random.url.com/   internal-test-shavar   yes
64// second.random.url.com/  internal-test-shavar   yes
65// ...
66bool ParsePhishingUrls(const std::string& data,
67                       std::vector<PhishingUrl>* phishing_urls) {
68  if (data.empty())
69    return false;
70
71  std::vector<std::string> urls;
72  base::SplitString(data, '\n', &urls);
73  for (size_t i = 0; i < urls.size(); ++i) {
74    if (urls[i].empty())
75      continue;
76    PhishingUrl phishing_url;
77    std::vector<std::string> record_parts;
78    base::SplitString(urls[i], '\t', &record_parts);
79    if (record_parts.size() != 3) {
80      LOG(ERROR) << "Unexpected URL format in phishing URL list: "
81                 << urls[i];
82      return false;
83    }
84    phishing_url.url = std::string(chrome::kHttpScheme) +
85        "://" + record_parts[0];
86    phishing_url.list_name = record_parts[1];
87    if (record_parts[2] == "yes") {
88      phishing_url.is_phishing = true;
89    } else if (record_parts[2] == "no") {
90      phishing_url.is_phishing = false;
91    } else {
92      LOG(ERROR) << "Unrecognized expectation in " << urls[i]
93                 << ": " << record_parts[2];
94      return false;
95    }
96    phishing_urls->push_back(phishing_url);
97  }
98  return true;
99}
100
101}  // namespace
102
103class SafeBrowsingTestServer {
104 public:
105  explicit SafeBrowsingTestServer(const FilePath& datafile)
106      : datafile_(datafile),
107        server_handle_(base::kNullProcessHandle) {
108  }
109
110  ~SafeBrowsingTestServer() {
111    EXPECT_EQ(base::kNullProcessHandle, server_handle_);
112  }
113
114  // Start the python server test suite.
115  bool Start() {
116    // Get path to python server script
117    FilePath testserver_path;
118    if (!PathService::Get(base::DIR_SOURCE_ROOT, &testserver_path)) {
119      LOG(ERROR) << "Failed to get DIR_SOURCE_ROOT";
120      return false;
121    }
122    testserver_path = testserver_path
123        .Append(FILE_PATH_LITERAL("third_party"))
124        .Append(FILE_PATH_LITERAL("safe_browsing"))
125        .Append(FILE_PATH_LITERAL("testing"));
126    AppendToPythonPath(testserver_path);
127    FilePath testserver = testserver_path.Append(
128        FILE_PATH_LITERAL("safebrowsing_test_server.py"));
129
130    FilePath pyproto_code_dir;
131    if (!GetPyProtoPath(&pyproto_code_dir)) {
132      LOG(ERROR) << "Failed to get generated python protobuf dir";
133      return false;
134    }
135    AppendToPythonPath(pyproto_code_dir);
136    pyproto_code_dir = pyproto_code_dir.Append(FILE_PATH_LITERAL("google"));
137    AppendToPythonPath(pyproto_code_dir);
138
139    FilePath python_runtime;
140    EXPECT_TRUE(GetPythonRunTime(&python_runtime));
141    CommandLine cmd_line(python_runtime);
142    FilePath datafile = testserver_path.Append(datafile_);
143    cmd_line.AppendArgPath(testserver);
144    cmd_line.AppendSwitchASCII("port", StringPrintf("%d", kPort_));
145    cmd_line.AppendSwitchPath("datafile", datafile);
146
147    if (!base::LaunchApp(cmd_line, false, true, &server_handle_)) {
148      LOG(ERROR) << "Failed to launch server: "
149                 << cmd_line.command_line_string();
150      return false;
151    }
152    return true;
153  }
154
155  // Stop the python server test suite.
156  bool Stop() {
157    if (server_handle_ == base::kNullProcessHandle)
158      return true;
159
160    // First check if the process has already terminated.
161    if (!base::WaitForSingleProcess(server_handle_, 0) &&
162        !base::KillProcess(server_handle_, 1, true)) {
163      VLOG(1) << "Kill failed?";
164      return false;
165    }
166
167    base::CloseProcessHandle(server_handle_);
168    server_handle_ = base::kNullProcessHandle;
169    VLOG(1) << "Stopped.";
170    return true;
171  }
172
173  static const char* Host() {
174    return kHost_;
175  }
176
177  static int Port() {
178    return kPort_;
179  }
180
181 private:
182  static const char kHost_[];
183  static const int kPort_;
184  FilePath datafile_;
185  base::ProcessHandle server_handle_;
186  DISALLOW_COPY_AND_ASSIGN(SafeBrowsingTestServer);
187};
188
189const char SafeBrowsingTestServer::kHost_[] = "localhost";
190const int SafeBrowsingTestServer::kPort_ = 40102;
191
192// This starts the browser and keeps status of states related to SafeBrowsing.
193class SafeBrowsingServiceTest : public InProcessBrowserTest {
194 public:
195  SafeBrowsingServiceTest()
196    : safe_browsing_service_(NULL),
197      is_database_ready_(true),
198      is_initial_request_(false),
199      is_update_scheduled_(false),
200      is_checked_url_in_db_(false),
201      is_checked_url_safe_(false) {
202  }
203
204  virtual ~SafeBrowsingServiceTest() {
205  }
206
207  void UpdateSafeBrowsingStatus() {
208    ASSERT_TRUE(safe_browsing_service_);
209    base::AutoLock lock(update_status_mutex_);
210    is_initial_request_ =
211        safe_browsing_service_->protocol_manager_->is_initial_request();
212    last_update_ = safe_browsing_service_->protocol_manager_->last_update();
213    is_update_scheduled_ =
214        safe_browsing_service_->protocol_manager_->update_timer_.IsRunning();
215  }
216
217  void ForceUpdate() {
218    ASSERT_TRUE(safe_browsing_service_);
219    safe_browsing_service_->protocol_manager_->ForceScheduleNextUpdate(0);
220  }
221
222  void CheckIsDatabaseReady() {
223    base::AutoLock lock(update_status_mutex_);
224    is_database_ready_ =
225        !safe_browsing_service_->database_update_in_progress_;
226  }
227
228  void CheckUrl(SafeBrowsingService::Client* helper, const GURL& url) {
229    ASSERT_TRUE(safe_browsing_service_);
230    base::AutoLock lock(update_status_mutex_);
231    if (safe_browsing_service_->CheckBrowseUrl(url, helper)) {
232      is_checked_url_in_db_ = false;
233      is_checked_url_safe_ = true;
234    } else {
235      // In this case, Safebrowsing service will fetch the full hash
236      // from the server and examine that. Once it is done,
237      // set_is_checked_url_safe() will be called via callback.
238      is_checked_url_in_db_ = true;
239    }
240  }
241
242  bool is_checked_url_in_db() {
243    base::AutoLock l(update_status_mutex_);
244    return is_checked_url_in_db_;
245  }
246
247  void set_is_checked_url_safe(bool safe) {
248    base::AutoLock l(update_status_mutex_);
249    is_checked_url_safe_ = safe;
250  }
251
252  bool is_checked_url_safe() {
253    base::AutoLock l(update_status_mutex_);
254    return is_checked_url_safe_;
255  }
256
257  bool is_database_ready() {
258    base::AutoLock l(update_status_mutex_);
259    return is_database_ready_;
260  }
261
262  bool is_initial_request() {
263    base::AutoLock l(update_status_mutex_);
264    return is_initial_request_;
265  }
266
267  base::Time last_update() {
268    base::AutoLock l(update_status_mutex_);
269    return last_update_;
270  }
271
272  bool is_update_scheduled() {
273    base::AutoLock l(update_status_mutex_);
274    return is_update_scheduled_;
275  }
276
277  MessageLoop* SafeBrowsingMessageLoop() {
278    return safe_browsing_service_->safe_browsing_thread_->message_loop();
279  }
280
281 protected:
282  bool InitSafeBrowsingService() {
283    safe_browsing_service_ =
284        g_browser_process->resource_dispatcher_host()->safe_browsing_service();
285    return safe_browsing_service_ != NULL;
286  }
287
288  virtual void SetUpCommandLine(CommandLine* command_line) {
289    // Makes sure the auto update is not triggered. This test will force the
290    // update when needed.
291    command_line->AppendSwitch(switches::kSbDisableAutoUpdate);
292
293    // This test uses loopback. No need to use IPv6 especially it makes
294    // local requests slow on Windows trybot when ipv6 local address [::1]
295    // is not setup.
296    command_line->AppendSwitch(switches::kDisableIPv6);
297
298    // TODO(lzheng): The test server does not understand download related
299    // requests. We need to fix the server.
300    command_line->AppendSwitch(switches::kSbDisableDownloadProtection);
301
302    // In this test, we fetch SafeBrowsing data and Mac key from the same
303    // server. Although in real production, they are served from different
304    // servers.
305    std::string url_prefix =
306        StringPrintf("http://%s:%d/safebrowsing",
307                     SafeBrowsingTestServer::Host(),
308                     SafeBrowsingTestServer::Port());
309    command_line->AppendSwitchASCII(switches::kSbInfoURLPrefix, url_prefix);
310    command_line->AppendSwitchASCII(switches::kSbMacKeyURLPrefix, url_prefix);
311  }
312
313  void SetTestStep(int step) {
314    std::string test_step = StringPrintf("test_step=%d", step);
315    safe_browsing_service_->protocol_manager_->set_additional_query(test_step);
316  }
317
318 private:
319  SafeBrowsingService* safe_browsing_service_;
320
321  // Protects all variables below since they are read on UI thread
322  // but updated on IO thread or safebrowsing thread.
323  base::Lock update_status_mutex_;
324
325  // States associated with safebrowsing service updates.
326  bool is_database_ready_;
327  bool is_initial_request_;
328  base::Time last_update_;
329  bool is_update_scheduled_;
330  // Indicates if there is a match between a URL's prefix and safebrowsing
331  // database (thus potentially it is a phishing URL).
332  bool is_checked_url_in_db_;
333  // True if last verified URL is not a phishing URL and thus it is safe.
334  bool is_checked_url_safe_;
335
336  DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServiceTest);
337};
338
339// A ref counted helper class that handles callbacks between IO thread and UI
340// thread.
341class SafeBrowsingServiceTestHelper
342    : public base::RefCountedThreadSafe<SafeBrowsingServiceTestHelper>,
343      public SafeBrowsingService::Client,
344      public URLFetcher::Delegate {
345 public:
346  explicit SafeBrowsingServiceTestHelper(
347      SafeBrowsingServiceTest* safe_browsing_test)
348      : safe_browsing_test_(safe_browsing_test),
349        response_status_(net::URLRequestStatus::FAILED) {
350  }
351
352  // Callbacks for SafeBrowsingService::Client.
353  virtual void OnBrowseUrlCheckResult(
354      const GURL& url, SafeBrowsingService::UrlCheckResult result) {
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        result == SafeBrowsingService::SAFE);
359    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
360                            NewRunnableMethod(this,
361                            &SafeBrowsingServiceTestHelper::OnCheckUrlDone));
362  }
363  virtual void OnDownloadUrlCheckResult(
364      const std::vector<GURL>& url_chain,
365      SafeBrowsingService::UrlCheckResult result) {
366    // TODO(lzheng): Add test for DownloadUrl.
367  }
368
369  virtual void OnBlockingPageComplete(bool proceed) {
370    NOTREACHED() << "Not implemented.";
371  }
372
373  // Functions and callbacks to start the safebrowsing database update.
374  void ForceUpdate() {
375    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
376        NewRunnableMethod(this,
377        &SafeBrowsingServiceTestHelper::ForceUpdateInIOThread));
378    // Will continue after OnForceUpdateDone().
379    ui_test_utils::RunMessageLoop();
380  }
381  void ForceUpdateInIOThread() {
382    EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
383    safe_browsing_test_->ForceUpdate();
384    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
385        NewRunnableMethod(this,
386        &SafeBrowsingServiceTestHelper::OnForceUpdateDone));
387  }
388  void OnForceUpdateDone() {
389    StopUILoop();
390  }
391
392  // Functions and callbacks related to CheckUrl. These are used to verify
393  // phishing URLs.
394  void CheckUrl(const GURL& url) {
395    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, NewRunnableMethod(
396        this, &SafeBrowsingServiceTestHelper::CheckUrlOnIOThread, url));
397    ui_test_utils::RunMessageLoop();
398  }
399  void CheckUrlOnIOThread(const GURL& url) {
400    EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
401    safe_browsing_test_->CheckUrl(this, url);
402    if (!safe_browsing_test_->is_checked_url_in_db()) {
403      // Ends the checking since this URL's prefix is not in database.
404      BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod(
405          this, &SafeBrowsingServiceTestHelper::OnCheckUrlDone));
406    }
407    // Otherwise, OnCheckUrlDone is called in OnUrlCheckResult since
408    // safebrowsing service further fetches hashes from safebrowsing server.
409  }
410
411  void OnCheckUrlDone() {
412    StopUILoop();
413  }
414
415  // Updates status from IO Thread.
416  void CheckStatusOnIOThread() {
417    EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
418    safe_browsing_test_->UpdateSafeBrowsingStatus();
419    safe_browsing_test_->SafeBrowsingMessageLoop()->PostTask(
420        FROM_HERE, NewRunnableMethod(this,
421        &SafeBrowsingServiceTestHelper::CheckIsDatabaseReady));
422  }
423
424  // Checks status in SafeBrowsing Thread.
425  void CheckIsDatabaseReady() {
426    EXPECT_EQ(MessageLoop::current(),
427              safe_browsing_test_->SafeBrowsingMessageLoop());
428    safe_browsing_test_->CheckIsDatabaseReady();
429    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod(
430        this, &SafeBrowsingServiceTestHelper::OnWaitForStatusUpdateDone));
431  }
432
433  void OnWaitForStatusUpdateDone() {
434    StopUILoop();
435  }
436
437  // Wait for a given period to get safebrowsing status updated.
438  void WaitForStatusUpdate(int64 wait_time_msec) {
439    BrowserThread::PostDelayedTask(
440        BrowserThread::IO,
441        FROM_HERE,
442        NewRunnableMethod(this,
443            &SafeBrowsingServiceTestHelper::CheckStatusOnIOThread),
444        wait_time_msec);
445    // Will continue after OnWaitForStatusUpdateDone().
446    ui_test_utils::RunMessageLoop();
447  }
448
449  void WaitTillServerReady(const char* host, int port) {
450    response_status_ = net::URLRequestStatus::FAILED;
451    GURL url(StringPrintf("http://%s:%d%s?test_step=0",
452                          host, port, kDBResetPath));
453    // TODO(lzheng): We should have a way to reliably tell when a server is
454    // ready so we could get rid of the Sleep and retry loop.
455    while (true) {
456      if (FetchUrl(url) == net::URLRequestStatus::SUCCESS)
457        break;
458      // Wait and try again if last fetch was failed. The loop will hit the
459      // timeout in OutOfProcTestRunner if the fetch can not get success
460      // response.
461      base::PlatformThread::Sleep(TestTimeouts::action_timeout_ms());
462    }
463  }
464
465  // Calls test server to fetch database for verification.
466  net::URLRequestStatus::Status FetchDBToVerify(const char* host, int port,
467                                                int test_step) {
468    // TODO(lzheng): Remove chunk_type=add once it is not needed by the server.
469    GURL url(StringPrintf("http://%s:%d%s?"
470                          "client=chromium&appver=1.0&pver=2.2&test_step=%d&"
471                          "chunk_type=add",
472                          host, port, kDBVerifyPath, test_step));
473    return FetchUrl(url);
474  }
475
476  // Calls test server to fetch URLs for verification.
477  net::URLRequestStatus::Status FetchUrlsToVerify(const char* host, int port,
478                                                  int test_step) {
479    GURL url(StringPrintf("http://%s:%d%s?"
480                          "client=chromium&appver=1.0&pver=2.2&test_step=%d",
481                          host, port, kUrlVerifyPath, test_step));
482    return FetchUrl(url);
483  }
484
485  // Calls test server to check if test data is done. E.g.: if there is a
486  // bad URL that server expects test to fetch full hash but the test didn't,
487  // this verification will fail.
488  net::URLRequestStatus::Status VerifyTestComplete(const char* host, int port,
489                                                   int test_step) {
490    GURL url(StringPrintf("http://%s:%d%s?test_step=%d",
491                          host, port, kTestCompletePath, test_step));
492    return FetchUrl(url);
493  }
494
495  // Callback for URLFetcher.
496  virtual void OnURLFetchComplete(const URLFetcher* source,
497                                  const GURL& url,
498                                  const net::URLRequestStatus& status,
499                                  int response_code,
500                                  const ResponseCookies& cookies,
501                                  const std::string& data) {
502    response_data_ = data;
503    response_status_ = status.status();
504    StopUILoop();
505  }
506
507  const std::string& response_data() {
508    return response_data_;
509  }
510
511 private:
512  // Stops UI loop after desired status is updated.
513  void StopUILoop() {
514    EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
515    MessageLoopForUI::current()->Quit();
516  }
517
518  // Fetch a URL. If message_loop_started is true, starts the message loop
519  // so the caller could wait till OnURLFetchComplete is called.
520  net::URLRequestStatus::Status FetchUrl(const GURL& url) {
521    url_fetcher_.reset(new URLFetcher(url, URLFetcher::GET, this));
522    url_fetcher_->set_load_flags(net::LOAD_DISABLE_CACHE);
523    url_fetcher_->set_request_context(Profile::GetDefaultRequestContext());
524    url_fetcher_->Start();
525    ui_test_utils::RunMessageLoop();
526    return response_status_;
527  }
528
529  base::OneShotTimer<SafeBrowsingServiceTestHelper> check_update_timer_;
530  SafeBrowsingServiceTest* safe_browsing_test_;
531  scoped_ptr<URLFetcher> url_fetcher_;
532  std::string response_data_;
533  net::URLRequestStatus::Status response_status_;
534  DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServiceTestHelper);
535};
536
537IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, SafeBrowsingSystemTest) {
538  LOG(INFO) << "Start test";
539  const char* server_host = SafeBrowsingTestServer::Host();
540  int server_port = SafeBrowsingTestServer::Port();
541  ASSERT_TRUE(InitSafeBrowsingService());
542
543  scoped_refptr<SafeBrowsingServiceTestHelper> safe_browsing_helper(
544      new SafeBrowsingServiceTestHelper(this));
545  int last_step = 0;
546  FilePath datafile_path = FilePath(kDataFile);
547  SafeBrowsingTestServer test_server(datafile_path);
548  ASSERT_TRUE(test_server.Start());
549
550  // Make sure the server is running.
551  safe_browsing_helper->WaitTillServerReady(server_host, server_port);
552
553  // Waits and makes sure safebrowsing update is not happening.
554  // The wait will stop once OnWaitForStatusUpdateDone in
555  // safe_browsing_helper is called and status from safe_browsing_service_
556  // is checked.
557  safe_browsing_helper->WaitForStatusUpdate(0);
558  EXPECT_TRUE(is_database_ready());
559  EXPECT_TRUE(is_initial_request());
560  EXPECT_FALSE(is_update_scheduled());
561  EXPECT_TRUE(last_update().is_null());
562  // Starts updates. After each update, the test will fetch a list of URLs with
563  // expected results to verify with safebrowsing service. If there is no error,
564  // the test moves on to the next step to get more update chunks.
565  // This repeats till there is no update data.
566  for (int step = 1;; step++) {
567    // Every step should be a fresh start.
568    SCOPED_TRACE(StringPrintf("step=%d", step));
569    EXPECT_TRUE(is_database_ready());
570    EXPECT_FALSE(is_update_scheduled());
571
572    // Starts safebrowsing update on IO thread. Waits till scheduled
573    // update finishes. Stops waiting after kMaxWaitSecPerStep if the update
574    // could not finish.
575    base::Time now = base::Time::Now();
576    SetTestStep(step);
577    safe_browsing_helper->ForceUpdate();
578
579    do {
580      // Periodically pull the status.
581      safe_browsing_helper->WaitForStatusUpdate(
582          TestTimeouts::action_timeout_ms());
583    } while (is_update_scheduled() || is_initial_request() ||
584             !is_database_ready());
585
586
587    if (last_update() < now) {
588      // This means no data available anymore.
589      break;
590    }
591
592    // Fetches URLs to verify and waits till server responses with data.
593    EXPECT_EQ(net::URLRequestStatus::SUCCESS,
594              safe_browsing_helper->FetchUrlsToVerify(server_host,
595                                                      server_port,
596                                                      step));
597
598    std::vector<PhishingUrl> phishing_urls;
599    EXPECT_TRUE(ParsePhishingUrls(safe_browsing_helper->response_data(),
600                                  &phishing_urls));
601    EXPECT_GT(phishing_urls.size(), 0U);
602    for (size_t j = 0; j < phishing_urls.size(); ++j) {
603      // Verifes with server if a URL is a phishing URL and waits till server
604      // responses.
605      safe_browsing_helper->CheckUrl(GURL(phishing_urls[j].url));
606      if (phishing_urls[j].is_phishing) {
607        EXPECT_TRUE(is_checked_url_in_db())
608            << phishing_urls[j].url
609            << " is_phishing: " << phishing_urls[j].is_phishing
610            << " test step: " << step;
611        EXPECT_FALSE(is_checked_url_safe())
612            << phishing_urls[j].url
613            << " is_phishing: " << phishing_urls[j].is_phishing
614            << " test step: " << step;
615      } else {
616        EXPECT_TRUE(is_checked_url_safe())
617            << phishing_urls[j].url
618            << " is_phishing: " << phishing_urls[j].is_phishing
619            << " test step: " << step;
620      }
621    }
622    // TODO(lzheng): We should verify the fetched database with local
623    // database to make sure they match.
624    EXPECT_EQ(net::URLRequestStatus::SUCCESS,
625              safe_browsing_helper->FetchDBToVerify(server_host,
626                                                    server_port,
627                                                    step));
628    EXPECT_GT(safe_browsing_helper->response_data().size(), 0U);
629    last_step = step;
630  }
631
632  // Verifies with server if test is done and waits till server responses.
633  EXPECT_EQ(net::URLRequestStatus::SUCCESS,
634            safe_browsing_helper->VerifyTestComplete(server_host,
635                                                     server_port,
636                                                     last_step));
637  EXPECT_EQ("yes", safe_browsing_helper->response_data());
638  test_server.Stop();
639}
640