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 25namespace { 26 27const 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. 31const int64 kBackoffDelaysInMs[] = { 32 3000, 18000, 108000, 648000, 3600000, 3600000 }; 33 34const char kDownloadWhitelistResponse[] = 35 "https://www.merchant1.com/checkout/\n" 36 "https://cart.merchant2.com/"; 37 38} // namespace 39 40namespace autofill { 41namespace autocheckout { 42 43class WhitelistManagerTest; 44 45class 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 55class 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 105class 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 148TEST_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 159TEST_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 166TEST_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 185TEST_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 202TEST_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 219TEST_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 283TEST_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