Home | History | Annotate | Download | only in autocheckout
      1 // Copyright 2013 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 #include <cmath>
      6 
      7 #include "base/command_line.h"
      8 #include "base/format_macros.h"
      9 #include "base/memory/scoped_ptr.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "base/strings/stringprintf.h"
     12 #include "components/autofill/content/browser/autocheckout/whitelist_manager.h"
     13 #include "components/autofill/core/browser/autofill_metrics.h"
     14 #include "components/autofill/core/common/autofill_switches.h"
     15 #include "content/public/test/test_browser_thread_bundle.h"
     16 #include "net/base/net_errors.h"
     17 #include "net/http/http_status_code.h"
     18 #include "net/url_request/test_url_fetcher_factory.h"
     19 #include "net/url_request/url_fetcher_delegate.h"
     20 #include "net/url_request/url_request_status.h"
     21 #include "testing/gmock/include/gmock/gmock.h"
     22 #include "testing/gtest/include/gtest/gtest.h"
     23 #include "url/gurl.h"
     24 
     25 namespace {
     26 
     27 const int64 kTestDownloadInterval = 3;  // 3 seconds
     28 
     29 // First 4 retry delays are 3, 18, 108, 648 seconds, and following retries
     30 // capped at one hour.
     31 const int64 kBackoffDelaysInMs[] = {
     32     3000, 18000, 108000, 648000, 3600000, 3600000 };
     33 
     34 const char kDownloadWhitelistResponse[] =
     35     "https://www.merchant1.com/checkout/\n"
     36     "https://cart.merchant2.com/";
     37 
     38 }  // namespace
     39 
     40 namespace autofill {
     41 namespace autocheckout {
     42 
     43 class WhitelistManagerTest;
     44 
     45 class MockAutofillMetrics : public AutofillMetrics {
     46  public:
     47   MockAutofillMetrics() {}
     48   MOCK_CONST_METHOD2(LogAutocheckoutWhitelistDownloadDuration,
     49       void(const base::TimeDelta& duration,
     50            AutofillMetrics::AutocheckoutWhitelistDownloadStatus));
     51  private:
     52   DISALLOW_COPY_AND_ASSIGN(MockAutofillMetrics);
     53 };
     54 
     55 class TestWhitelistManager : public WhitelistManager {
     56  public:
     57   TestWhitelistManager()
     58       : WhitelistManager(),
     59         did_start_download_timer_(false) {}
     60 
     61   virtual void ScheduleDownload(base::TimeDelta interval) OVERRIDE {
     62     did_start_download_timer_ = false;
     63     download_interval_ = interval;
     64     return WhitelistManager::ScheduleDownload(interval);
     65   }
     66 
     67   virtual void StartDownloadTimer(base::TimeDelta interval) OVERRIDE {
     68     WhitelistManager::StartDownloadTimer(interval);
     69     did_start_download_timer_ = true;
     70   }
     71 
     72   bool did_start_download_timer() const {
     73     return did_start_download_timer_;
     74   }
     75 
     76   void TriggerDownload() {
     77     WhitelistManager::TriggerDownload();
     78   }
     79 
     80   void StopDownloadTimer() {
     81     WhitelistManager::StopDownloadTimer();
     82   }
     83 
     84   const base::TimeDelta& download_interval() const {
     85     return download_interval_;
     86   }
     87 
     88   const std::vector<std::string>& url_prefixes() const {
     89     return WhitelistManager::url_prefixes();
     90   }
     91 
     92   virtual const AutofillMetrics& GetMetricLogger() const OVERRIDE {
     93       return mock_metrics_logger_;
     94   }
     95 
     96  private:
     97   bool did_start_download_timer_;
     98   base::TimeDelta download_interval_;
     99 
    100   MockAutofillMetrics mock_metrics_logger_;
    101 
    102   DISALLOW_COPY_AND_ASSIGN(TestWhitelistManager);
    103 };
    104 
    105 class WhitelistManagerTest : public testing::Test {
    106  public:
    107   WhitelistManagerTest()
    108       : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {}
    109 
    110  protected:
    111   void CreateWhitelistManager() {
    112     if (!whitelist_manager_.get()) {
    113       whitelist_manager_.reset(new TestWhitelistManager());
    114     }
    115   }
    116 
    117   void DownloadWhitelist(int response_code, const std::string& response) {
    118     // Create and register factory.
    119     net::TestURLFetcherFactory factory;
    120 
    121     CreateWhitelistManager();
    122 
    123     AutofillMetrics::AutocheckoutWhitelistDownloadStatus status;
    124     if (response_code == net::HTTP_OK)
    125       status = AutofillMetrics::AUTOCHECKOUT_WHITELIST_DOWNLOAD_SUCCEEDED;
    126     else
    127       status = AutofillMetrics::AUTOCHECKOUT_WHITELIST_DOWNLOAD_FAILED;
    128     EXPECT_CALL(
    129         static_cast<const MockAutofillMetrics&>(
    130             whitelist_manager_->GetMetricLogger()),
    131         LogAutocheckoutWhitelistDownloadDuration(testing::_, status)).Times(1);
    132 
    133     whitelist_manager_->TriggerDownload();
    134     net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
    135     ASSERT_TRUE(fetcher);
    136     fetcher->set_response_code(response_code);
    137     fetcher->SetResponseString(response);
    138     fetcher->delegate()->OnURLFetchComplete(fetcher);
    139   }
    140 
    141  protected:
    142   scoped_ptr<TestWhitelistManager> whitelist_manager_;
    143 
    144  private:
    145   content::TestBrowserThreadBundle thread_bundle_;
    146 };
    147 
    148 TEST_F(WhitelistManagerTest, DownloadWhitelist) {
    149   CommandLine::ForCurrentProcess()->AppendSwitch(
    150       switches::kEnableExperimentalFormFilling);
    151   DownloadWhitelist(net::HTTP_OK, kDownloadWhitelistResponse);
    152   ASSERT_EQ(2U, whitelist_manager_->url_prefixes().size());
    153   EXPECT_EQ("https://www.merchant1.com/checkout/",
    154             whitelist_manager_->url_prefixes()[0]);
    155   EXPECT_EQ("https://cart.merchant2.com/",
    156             whitelist_manager_->url_prefixes()[1]);
    157 }
    158 
    159 TEST_F(WhitelistManagerTest, DoNotDownloadWhitelistWhenSwitchIsOff) {
    160   CreateWhitelistManager();
    161   whitelist_manager_->ScheduleDownload(
    162       base::TimeDelta::FromSeconds(kTestDownloadInterval));
    163   EXPECT_FALSE(whitelist_manager_->did_start_download_timer());
    164 }
    165 
    166 TEST_F(WhitelistManagerTest, DoNotDownloadWhitelistIfAlreadyScheduled) {
    167   CommandLine::ForCurrentProcess()->AppendSwitch(
    168       switches::kEnableExperimentalFormFilling);
    169   CreateWhitelistManager();
    170   // First attempt should schedule a download.
    171   whitelist_manager_->ScheduleDownload(
    172       base::TimeDelta::FromSeconds(kTestDownloadInterval));
    173   EXPECT_TRUE(whitelist_manager_->did_start_download_timer());
    174   // Second attempt should NOT schedule a download while there is already one.
    175   whitelist_manager_->ScheduleDownload(
    176       base::TimeDelta::FromSeconds(kTestDownloadInterval));
    177   EXPECT_FALSE(whitelist_manager_->did_start_download_timer());
    178   // It should schedule a new download when not in backoff mode.
    179   whitelist_manager_->StopDownloadTimer();
    180   whitelist_manager_->ScheduleDownload(
    181       base::TimeDelta::FromSeconds(kTestDownloadInterval));
    182   EXPECT_TRUE(whitelist_manager_->did_start_download_timer());
    183 }
    184 
    185 TEST_F(WhitelistManagerTest, DownloadWhitelistFailed) {
    186   CommandLine::ForCurrentProcess()->AppendSwitch(
    187       switches::kEnableExperimentalFormFilling);
    188   DownloadWhitelist(net::HTTP_INTERNAL_SERVER_ERROR,
    189                     kDownloadWhitelistResponse);
    190   EXPECT_EQ(0U, whitelist_manager_->url_prefixes().size());
    191 
    192   whitelist_manager_->StopDownloadTimer();
    193   DownloadWhitelist(net::HTTP_OK, kDownloadWhitelistResponse);
    194   EXPECT_EQ(2U, whitelist_manager_->url_prefixes().size());
    195 
    196   whitelist_manager_->StopDownloadTimer();
    197   DownloadWhitelist(net::HTTP_INTERNAL_SERVER_ERROR,
    198                     kDownloadWhitelistResponse);
    199   EXPECT_EQ(2U, whitelist_manager_->url_prefixes().size());
    200 }
    201 
    202 TEST_F(WhitelistManagerTest, DownloadWhitelistRetry) {
    203   CommandLine::ForCurrentProcess()->AppendSwitch(
    204       switches::kEnableExperimentalFormFilling);
    205 
    206   for (size_t i = 0; i < arraysize(kBackoffDelaysInMs); ++i) {
    207     DownloadWhitelist(net::HTTP_INTERNAL_SERVER_ERROR,
    208                       kDownloadWhitelistResponse);
    209     SCOPED_TRACE(base::StringPrintf("Testing retry %" PRIuS
    210                                     ", expecting delay: %" PRId64,
    211                                     i,
    212                                     kBackoffDelaysInMs[i]));
    213     EXPECT_EQ(
    214         kBackoffDelaysInMs[i],
    215         whitelist_manager_->download_interval().InMillisecondsRoundedUp());
    216   }
    217 }
    218 
    219 TEST_F(WhitelistManagerTest, GetMatchedURLPrefix) {
    220   CommandLine::ForCurrentProcess()->AppendSwitch(
    221       switches::kEnableExperimentalFormFilling);
    222   DownloadWhitelist(net::HTTP_OK, kDownloadWhitelistResponse);
    223   EXPECT_EQ(2U, whitelist_manager_->url_prefixes().size());
    224 
    225   // Empty url.
    226   EXPECT_EQ(std::string(),
    227             whitelist_manager_->GetMatchedURLPrefix(GURL(std::string())));
    228   EXPECT_EQ(std::string(),
    229             whitelist_manager_->GetMatchedURLPrefix(GURL()));
    230 
    231   // Positive tests.
    232   EXPECT_EQ("https://www.merchant1.com/checkout/",
    233             whitelist_manager_->GetMatchedURLPrefix(
    234                 GURL("https://www.merchant1.com/checkout/")));
    235   EXPECT_EQ("https://www.merchant1.com/checkout/",
    236             whitelist_manager_->GetMatchedURLPrefix(
    237                 GURL("https://www.merchant1.com/checkout/Shipping")));
    238   EXPECT_EQ("https://www.merchant1.com/checkout/",
    239             whitelist_manager_->GetMatchedURLPrefix(
    240                 GURL("https://www.merchant1.com/checkout/?a=b&c=d")));
    241   EXPECT_EQ("https://cart.merchant2.com/",
    242             whitelist_manager_->GetMatchedURLPrefix(
    243                 GURL("https://cart.merchant2.com/")));
    244   EXPECT_EQ("https://cart.merchant2.com/",
    245             whitelist_manager_->GetMatchedURLPrefix(
    246                 GURL("https://cart.merchant2.com/ShippingInfo")));
    247   EXPECT_EQ("https://cart.merchant2.com/",
    248             whitelist_manager_->GetMatchedURLPrefix(
    249                 GURL("https://cart.merchant2.com/ShippingInfo?a=b&c=d")));
    250 
    251   // Negative tests.
    252   EXPECT_EQ(std::string(),
    253             whitelist_manager_->GetMatchedURLPrefix(
    254                 GURL("https://www.merchant1.com/checkout")));
    255   EXPECT_EQ(std::string(),
    256             whitelist_manager_->GetMatchedURLPrefix(
    257                 GURL("https://www.merchant1.com/")));
    258   EXPECT_EQ(std::string(),
    259             whitelist_manager_->GetMatchedURLPrefix(
    260                 GURL("https://www.merchant1.com/Building")));
    261   EXPECT_EQ(std::string(),
    262             whitelist_manager_->GetMatchedURLPrefix(
    263                 GURL("https://www.merchant2.com/cart")));
    264   EXPECT_EQ(std::string(),
    265             whitelist_manager_->GetMatchedURLPrefix(
    266                 GURL("a random string")));
    267 
    268   // Test different cases in schema, host and path.
    269   EXPECT_EQ(std::string(),
    270             whitelist_manager_->GetMatchedURLPrefix(
    271                 GURL("http://www.merchant1.com/checkout/")));
    272   EXPECT_EQ(std::string(),
    273             whitelist_manager_->GetMatchedURLPrefix(
    274                 GURL("www.merchant1.com/checkout/")));
    275   EXPECT_EQ("https://www.merchant1.com/checkout/",
    276             whitelist_manager_->GetMatchedURLPrefix(
    277                 GURL("https://www.Merchant1.com/checkout/")));
    278   EXPECT_EQ(std::string(),
    279             whitelist_manager_->GetMatchedURLPrefix(
    280                 GURL("https://www.merchant1.com/CheckOut/")));
    281 }
    282 
    283 TEST_F(WhitelistManagerTest, BypassWhitelist) {
    284   CommandLine::ForCurrentProcess()->AppendSwitch(
    285       switches::kEnableExperimentalFormFilling);
    286   CommandLine::ForCurrentProcess()->AppendSwitch(
    287       switches::kBypassAutocheckoutWhitelist);
    288   DownloadWhitelist(net::HTTP_OK, kDownloadWhitelistResponse);
    289   EXPECT_EQ(2U, whitelist_manager_->url_prefixes().size());
    290 
    291   // Empty url.
    292   EXPECT_EQ(std::string(),
    293             whitelist_manager_->GetMatchedURLPrefix(GURL(std::string())));
    294   // Positive tests.
    295   EXPECT_EQ("https://www.merchant1.com/checkout/",
    296             whitelist_manager_->GetMatchedURLPrefix(
    297                 GURL("https://www.merchant1.com/checkout/")));
    298   EXPECT_EQ("https://cart.merchant2.com/",
    299             whitelist_manager_->GetMatchedURLPrefix(
    300                 GURL("https://cart.merchant2.com/ShippingInfo?a=b&c=d")));
    301   // Bypass other urls.
    302   EXPECT_EQ(std::string("https://bypass.me/"),
    303             whitelist_manager_->GetMatchedURLPrefix(
    304                 GURL("https://bypass.me/")));
    305 }
    306 
    307 }  // namespace autocheckout
    308 }  // namespace autofill
    309 
    310