// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This test uses the safebrowsing test server published at
// http://code.google.com/p/google-safe-browsing/ to test the safebrowsing
// protocol implemetation. Details of the safebrowsing testing flow is
// documented at
// http://code.google.com/p/google-safe-browsing/wiki/ProtocolTesting
//
// This test launches safebrowsing test server and issues several update
// requests against that server. Each update would get different data and after
// each update, the test will get a list of URLs from the test server to verify
// its repository. The test will succeed only if all updates are performed and
// URLs match what the server expected.

#include <vector>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/environment.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/safe_browsing/database_manager.h"
#include "chrome/browser/safe_browsing/local_safebrowsing_test_server.h"
#include "chrome/browser/safe_browsing/protocol_manager.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "content/public/browser/browser_context.h"
#include "content/public/test/test_browser_thread.h"
#include "content/public/test/test_utils.h"
#include "net/base/load_flags.h"
#include "net/base/net_log.h"
#include "net/dns/host_resolver.h"
#include "net/test/python_utils.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "net/url_request/url_request_status.h"
#include "testing/gtest/include/gtest/gtest.h"

using content::BrowserThread;

namespace {

const base::FilePath::CharType kDataFile[] =
    FILE_PATH_LITERAL("testing_input_nomac.dat");
const char kUrlVerifyPath[] = "safebrowsing/verify_urls";
const char kDBVerifyPath[] = "safebrowsing/verify_database";
const char kTestCompletePath[] = "test_complete";

struct PhishingUrl {
  std::string url;
  std::string list_name;
  bool is_phishing;
};

// Parses server response for verify_urls. The expected format is:
//
// first.random.url.com/   internal-test-shavar   yes
// second.random.url.com/  internal-test-shavar   yes
// ...
bool ParsePhishingUrls(const std::string& data,
                       std::vector<PhishingUrl>* phishing_urls) {
  if (data.empty())
    return false;

  std::vector<std::string> urls;
  base::SplitString(data, '\n', &urls);
  for (size_t i = 0; i < urls.size(); ++i) {
    if (urls[i].empty())
      continue;
    PhishingUrl phishing_url;
    std::vector<std::string> record_parts;
    base::SplitString(urls[i], '\t', &record_parts);
    if (record_parts.size() != 3) {
      LOG(ERROR) << "Unexpected URL format in phishing URL list: "
                 << urls[i];
      return false;
    }
    phishing_url.url = std::string(url::kHttpScheme) + "://" + record_parts[0];
    phishing_url.list_name = record_parts[1];
    if (record_parts[2] == "yes") {
      phishing_url.is_phishing = true;
    } else if (record_parts[2] == "no") {
      phishing_url.is_phishing = false;
    } else {
      LOG(ERROR) << "Unrecognized expectation in " << urls[i]
                 << ": " << record_parts[2];
      return false;
    }
    phishing_urls->push_back(phishing_url);
  }
  return true;
}

class FakeSafeBrowsingService : public SafeBrowsingService {
 public:
  explicit FakeSafeBrowsingService(const std::string& url_prefix)
      : url_prefix_(url_prefix) {}

  SafeBrowsingProtocolConfig GetProtocolConfig() const override {
    SafeBrowsingProtocolConfig config;
    config.url_prefix = url_prefix_;
    // Makes sure the auto update is not triggered. The tests will force the
    // update when needed.
    config.disable_auto_update = true;
#if defined(OS_ANDROID)
    config.disable_connection_check = true;
#endif
    config.client_name = "browser_tests";
    return config;
  }

 private:
  ~FakeSafeBrowsingService() override {}

  std::string url_prefix_;

  DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService);
};

// Factory that creates FakeSafeBrowsingService instances.
class TestSafeBrowsingServiceFactory : public SafeBrowsingServiceFactory {
 public:
  explicit TestSafeBrowsingServiceFactory(const std::string& url_prefix)
      : url_prefix_(url_prefix) {}

  SafeBrowsingService* CreateSafeBrowsingService() override {
    return new FakeSafeBrowsingService(url_prefix_);
  }

 private:
  std::string url_prefix_;
};

}  // namespace

// This starts the browser and keeps status of states related to SafeBrowsing.
class SafeBrowsingServerTest : public InProcessBrowserTest {
 public:
  SafeBrowsingServerTest()
    : safe_browsing_service_(NULL),
      is_database_ready_(true),
      is_update_scheduled_(false),
      is_checked_url_in_db_(false),
      is_checked_url_safe_(false) {
  }

  ~SafeBrowsingServerTest() override {}

  void UpdateSafeBrowsingStatus() {
    ASSERT_TRUE(safe_browsing_service_);
    base::AutoLock lock(update_status_mutex_);
    last_update_ = safe_browsing_service_->protocol_manager_->last_update();
    is_update_scheduled_ =
        safe_browsing_service_->protocol_manager_->update_timer_.IsRunning();
  }

  void ForceUpdate() {
    content::WindowedNotificationObserver observer(
        chrome::NOTIFICATION_SAFE_BROWSING_UPDATE_COMPLETE,
        content::Source<SafeBrowsingDatabaseManager>(database_manager()));
    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
        base::Bind(&SafeBrowsingServerTest::ForceUpdateOnIOThread,
                   this));
    observer.Wait();
  }

  void ForceUpdateOnIOThread() {
    EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
    ASSERT_TRUE(safe_browsing_service_);
    safe_browsing_service_->protocol_manager_->ForceScheduleNextUpdate(
        base::TimeDelta::FromSeconds(0));
  }

  void CheckIsDatabaseReady() {
    base::AutoLock lock(update_status_mutex_);
    is_database_ready_ = !database_manager()->database_update_in_progress_;
  }

  void CheckUrl(SafeBrowsingDatabaseManager::Client* helper, const GURL& url) {
    ASSERT_TRUE(safe_browsing_service_);
    base::AutoLock lock(update_status_mutex_);
    if (database_manager()->CheckBrowseUrl(url, helper)) {
      is_checked_url_in_db_ = false;
      is_checked_url_safe_ = true;
    } else {
      // In this case, Safebrowsing service will fetch the full hash
      // from the server and examine that. Once it is done,
      // set_is_checked_url_safe() will be called via callback.
      is_checked_url_in_db_ = true;
    }
  }

  SafeBrowsingDatabaseManager* database_manager() {
    return safe_browsing_service_->database_manager().get();
  }

  bool is_checked_url_in_db() {
    base::AutoLock l(update_status_mutex_);
    return is_checked_url_in_db_;
  }

  void set_is_checked_url_safe(bool safe) {
    base::AutoLock l(update_status_mutex_);
    is_checked_url_safe_ = safe;
  }

  bool is_checked_url_safe() {
    base::AutoLock l(update_status_mutex_);
    return is_checked_url_safe_;
  }

  bool is_database_ready() {
    base::AutoLock l(update_status_mutex_);
    return is_database_ready_;
  }

  base::Time last_update() {
    base::AutoLock l(update_status_mutex_);
    return last_update_;
  }

  bool is_update_scheduled() {
    base::AutoLock l(update_status_mutex_);
    return is_update_scheduled_;
  }

  base::MessageLoop* SafeBrowsingMessageLoop() {
    return database_manager()->safe_browsing_thread_->message_loop();
  }

  const net::SpawnedTestServer& test_server() const {
    return *test_server_;
  }

 protected:
  bool InitSafeBrowsingService() {
    safe_browsing_service_ = g_browser_process->safe_browsing_service();
    return safe_browsing_service_ != NULL;
  }

  void SetUp() override {
    base::FilePath datafile_path;
    ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &datafile_path));

    datafile_path = datafile_path.Append(FILE_PATH_LITERAL("third_party"))
          .Append(FILE_PATH_LITERAL("safe_browsing"))
          .Append(FILE_PATH_LITERAL("testing"))
          .Append(kDataFile);
    test_server_.reset(new LocalSafeBrowsingTestServer(datafile_path));
    ASSERT_TRUE(test_server_->Start());
    LOG(INFO) << "server is " << test_server_->host_port_pair().ToString();

    // Point to the testing server for all SafeBrowsing requests.
    std::string url_prefix = test_server_->GetURL("safebrowsing").spec();
    sb_factory_.reset(new TestSafeBrowsingServiceFactory(url_prefix));
    SafeBrowsingService::RegisterFactory(sb_factory_.get());

    InProcessBrowserTest::SetUp();
  }

  void TearDown() override {
    InProcessBrowserTest::TearDown();

    SafeBrowsingService::RegisterFactory(NULL);
  }

  void SetUpCommandLine(CommandLine* command_line) override {
    // This test uses loopback. No need to use IPv6 especially it makes
    // local requests slow on Windows trybot when ipv6 local address [::1]
    // is not setup.
    command_line->AppendSwitch(switches::kDisableIPv6);

    // TODO(lzheng): The test server does not understand download related
    // requests. We need to fix the server.
    command_line->AppendSwitch(switches::kSbDisableDownloadProtection);

    // TODO(gcasto): Generate new testing data that includes the
    // client-side phishing whitelist.
    command_line->AppendSwitch(
        switches::kDisableClientSidePhishingDetection);

    // TODO(kalman): Generate new testing data that includes the extension
    // blacklist.
    command_line->AppendSwitch(switches::kSbDisableExtensionBlacklist);

    // TODO(tburkard): Generate new testing data that includes the side-effect
    // free whitelist.
    command_line->AppendSwitch(switches::kSbDisableSideEffectFreeWhitelist);
  }

  void SetTestStep(int step) {
    std::string test_step = base::StringPrintf("test_step=%d", step);
    safe_browsing_service_->protocol_manager_->set_additional_query(test_step);
  }

 private:
  scoped_ptr<TestSafeBrowsingServiceFactory> sb_factory_;

  SafeBrowsingService* safe_browsing_service_;

  scoped_ptr<net::SpawnedTestServer> test_server_;

  // Protects all variables below since they are read on UI thread
  // but updated on IO thread or safebrowsing thread.
  base::Lock update_status_mutex_;

  // States associated with safebrowsing service updates.
  bool is_database_ready_;
  base::Time last_update_;
  bool is_update_scheduled_;
  // Indicates if there is a match between a URL's prefix and safebrowsing
  // database (thus potentially it is a phishing URL).
  bool is_checked_url_in_db_;
  // True if last verified URL is not a phishing URL and thus it is safe.
  bool is_checked_url_safe_;

  DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServerTest);
};

// A ref counted helper class that handles callbacks between IO thread and UI
// thread.
class SafeBrowsingServerTestHelper
    : public base::RefCountedThreadSafe<SafeBrowsingServerTestHelper>,
      public SafeBrowsingDatabaseManager::Client,
      public net::URLFetcherDelegate {
 public:
  SafeBrowsingServerTestHelper(SafeBrowsingServerTest* safe_browsing_test,
                               net::URLRequestContextGetter* request_context)
      : safe_browsing_test_(safe_browsing_test),
        response_status_(net::URLRequestStatus::FAILED),
        request_context_(request_context) {
  }

  // Callbacks for SafeBrowsingDatabaseManager::Client.
  void OnCheckBrowseUrlResult(const GURL& url,
                              SBThreatType threat_type,
                              const std::string& metadata) override {
    EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
    EXPECT_TRUE(safe_browsing_test_->is_checked_url_in_db());
    safe_browsing_test_->set_is_checked_url_safe(
        threat_type == SB_THREAT_TYPE_SAFE);
    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
        base::Bind(&SafeBrowsingServerTestHelper::OnCheckUrlDone, this));
  }

  virtual void OnBlockingPageComplete(bool proceed) {
    NOTREACHED() << "Not implemented.";
  }

  // Functions and callbacks related to CheckUrl. These are used to verify
  // phishing URLs.
  void CheckUrl(const GURL& url) {
    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
        base::Bind(&SafeBrowsingServerTestHelper::CheckUrlOnIOThread,
                   this, url));
    content::RunMessageLoop();
  }
  void CheckUrlOnIOThread(const GURL& url) {
    EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
    safe_browsing_test_->CheckUrl(this, url);
    if (!safe_browsing_test_->is_checked_url_in_db()) {
      // Ends the checking since this URL's prefix is not in database.
      BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
        base::Bind(&SafeBrowsingServerTestHelper::OnCheckUrlDone, this));
    }
    // Otherwise, OnCheckUrlDone is called in OnUrlCheckResult since
    // safebrowsing service further fetches hashes from safebrowsing server.
  }

  void OnCheckUrlDone() {
    StopUILoop();
  }

  // Updates status from IO Thread.
  void CheckStatusOnIOThread() {
    EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
    safe_browsing_test_->UpdateSafeBrowsingStatus();
    safe_browsing_test_->SafeBrowsingMessageLoop()->PostTask(FROM_HERE,
        base::Bind(&SafeBrowsingServerTestHelper::CheckIsDatabaseReady, this));
  }

  // Checks status in SafeBrowsing Thread.
  void CheckIsDatabaseReady() {
    EXPECT_EQ(base::MessageLoop::current(),
              safe_browsing_test_->SafeBrowsingMessageLoop());
    safe_browsing_test_->CheckIsDatabaseReady();
    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
        base::Bind(&SafeBrowsingServerTestHelper::OnWaitForStatusUpdateDone,
                   this));
  }

  void OnWaitForStatusUpdateDone() {
    StopUILoop();
  }

  // Update safebrowsing status.
  void UpdateStatus() {
    BrowserThread::PostTask(
        BrowserThread::IO,
        FROM_HERE,
        base::Bind(&SafeBrowsingServerTestHelper::CheckStatusOnIOThread, this));
    // Will continue after OnWaitForStatusUpdateDone().
    content::RunMessageLoop();
  }

  // Calls test server to fetch database for verification.
  net::URLRequestStatus::Status FetchDBToVerify(
      const net::SpawnedTestServer& test_server,
      int test_step) {
    // TODO(lzheng): Remove chunk_type=add once it is not needed by the server.
    std::string path = base::StringPrintf(
        "%s?client=chromium&appver=1.0&pver=3.0&test_step=%d&chunk_type=add",
        kDBVerifyPath, test_step);
    return FetchUrl(test_server.GetURL(path));
  }

  // Calls test server to fetch URLs for verification.
  net::URLRequestStatus::Status FetchUrlsToVerify(
      const net::SpawnedTestServer& test_server,
      int test_step) {
    std::string path = base::StringPrintf(
        "%s?client=chromium&appver=1.0&pver=3.0&test_step=%d",
        kUrlVerifyPath, test_step);
    return FetchUrl(test_server.GetURL(path));
  }

  // Calls test server to check if test data is done. E.g.: if there is a
  // bad URL that server expects test to fetch full hash but the test didn't,
  // this verification will fail.
  net::URLRequestStatus::Status VerifyTestComplete(
      const net::SpawnedTestServer& test_server,
      int test_step) {
    std::string path = base::StringPrintf(
        "%s?test_step=%d", kTestCompletePath, test_step);
    return FetchUrl(test_server.GetURL(path));
  }

  // Callback for URLFetcher.
  void OnURLFetchComplete(const net::URLFetcher* source) override {
    source->GetResponseAsString(&response_data_);
    response_status_ = source->GetStatus().status();
    StopUILoop();
  }

  const std::string& response_data() {
    return response_data_;
  }

 private:
  friend class base::RefCountedThreadSafe<SafeBrowsingServerTestHelper>;
  ~SafeBrowsingServerTestHelper() override {}

  // Stops UI loop after desired status is updated.
  void StopUILoop() {
    EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
    base::MessageLoopForUI::current()->Quit();
  }

  // Fetch a URL. If message_loop_started is true, starts the message loop
  // so the caller could wait till OnURLFetchComplete is called.
  net::URLRequestStatus::Status FetchUrl(const GURL& url) {
    url_fetcher_.reset(net::URLFetcher::Create(
        url, net::URLFetcher::GET, this));
    url_fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE);
    url_fetcher_->SetRequestContext(request_context_);
    url_fetcher_->Start();
    content::RunMessageLoop();
    return response_status_;
  }

  base::OneShotTimer<SafeBrowsingServerTestHelper> check_update_timer_;
  SafeBrowsingServerTest* safe_browsing_test_;
  scoped_ptr<net::URLFetcher> url_fetcher_;
  std::string response_data_;
  net::URLRequestStatus::Status response_status_;
  net::URLRequestContextGetter* request_context_;
  DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServerTestHelper);
};

// TODO(shess): Disabled pending new data for third_party/safe_browsing/testing/
IN_PROC_BROWSER_TEST_F(SafeBrowsingServerTest,
                       DISABLED_SafeBrowsingServerTest) {
  LOG(INFO) << "Start test";
  ASSERT_TRUE(InitSafeBrowsingService());

  net::URLRequestContextGetter* request_context =
      browser()->profile()->GetRequestContext();
  scoped_refptr<SafeBrowsingServerTestHelper> safe_browsing_helper(
      new SafeBrowsingServerTestHelper(this, request_context));
  int last_step = 0;

  // Waits and makes sure safebrowsing update is not happening.
  // The wait will stop once OnWaitForStatusUpdateDone in
  // safe_browsing_helper is called and status from safe_browsing_service_
  // is checked.
  safe_browsing_helper->UpdateStatus();
  EXPECT_TRUE(is_database_ready());
  EXPECT_FALSE(is_update_scheduled());
  EXPECT_TRUE(last_update().is_null());
  // Starts updates. After each update, the test will fetch a list of URLs with
  // expected results to verify with safebrowsing service. If there is no error,
  // the test moves on to the next step to get more update chunks.
  // This repeats till there is no update data.
  for (int step = 1;; step++) {
    // Every step should be a fresh start.
    SCOPED_TRACE(base::StringPrintf("step=%d", step));
    EXPECT_TRUE(is_database_ready());
    EXPECT_FALSE(is_update_scheduled());

    // Starts safebrowsing update on IO thread. Waits till scheduled
    // update finishes.
    base::Time now = base::Time::Now();
    SetTestStep(step);
    ForceUpdate();

    safe_browsing_helper->UpdateStatus();
    EXPECT_TRUE(is_database_ready());
    EXPECT_FALSE(is_update_scheduled());
    EXPECT_FALSE(last_update().is_null());
    if (last_update() < now) {
      // This means no data available anymore.
      break;
    }

    // Fetches URLs to verify and waits till server responses with data.
    EXPECT_EQ(net::URLRequestStatus::SUCCESS,
              safe_browsing_helper->FetchUrlsToVerify(test_server(), step));

    std::vector<PhishingUrl> phishing_urls;
    EXPECT_TRUE(ParsePhishingUrls(safe_browsing_helper->response_data(),
                                  &phishing_urls));
    EXPECT_GT(phishing_urls.size(), 0U);
    for (size_t j = 0; j < phishing_urls.size(); ++j) {
      // Verifes with server if a URL is a phishing URL and waits till server
      // responses.
      safe_browsing_helper->CheckUrl(GURL(phishing_urls[j].url));
      if (phishing_urls[j].is_phishing) {
        EXPECT_TRUE(is_checked_url_in_db())
            << phishing_urls[j].url
            << " is_phishing: " << phishing_urls[j].is_phishing
            << " test step: " << step;
        EXPECT_FALSE(is_checked_url_safe())
            << phishing_urls[j].url
            << " is_phishing: " << phishing_urls[j].is_phishing
            << " test step: " << step;
      } else {
        EXPECT_TRUE(is_checked_url_safe())
            << phishing_urls[j].url
            << " is_phishing: " << phishing_urls[j].is_phishing
            << " test step: " << step;
      }
    }
    // TODO(lzheng): We should verify the fetched database with local
    // database to make sure they match.
    EXPECT_EQ(net::URLRequestStatus::SUCCESS,
              safe_browsing_helper->FetchDBToVerify(test_server(), step));
    EXPECT_GT(safe_browsing_helper->response_data().size(), 0U);
    last_step = step;
  }

  // Verifies with server if test is done and waits till server responses.
  EXPECT_EQ(net::URLRequestStatus::SUCCESS,
            safe_browsing_helper->VerifyTestComplete(test_server(), last_step));
  EXPECT_EQ("yes", safe_browsing_helper->response_data());
}
