Update WebCORSPreflightResultCacheItem to use TimeDelta

This CL updates WebCORSPreflightResultCache to use TimeDelta as the time
type instead of double. And, adds an injection point of TickClock to
WebCORSPreflightResultCacheItem to avoid overriding global time.

Change-Id: Ia8251c0a8ae2edfd107a8ddf22b421942c2683ad
Reviewed-on: https://chromium-review.googlesource.com/790181
Commit-Queue: Taiju Tsuiki <[email protected]>
Reviewed-by: Kinuko Yasuda <[email protected]>
Reviewed-by: Daniel Cheng <[email protected]>
Cr-Commit-Position: refs/heads/master@{#519600}
diff --git a/base/time/default_tick_clock.cc b/base/time/default_tick_clock.cc
index ce62fcc3..ac8dab4 100644
--- a/base/time/default_tick_clock.cc
+++ b/base/time/default_tick_clock.cc
@@ -12,4 +12,10 @@
   return TimeTicks::Now();
 }
 
+// static
+DefaultTickClock* DefaultTickClock::GetInstance() {
+  CR_DEFINE_STATIC_LOCAL(DefaultTickClock, instance, ());
+  return &instance;
+}
+
 }  // namespace base
diff --git a/base/time/default_tick_clock.h b/base/time/default_tick_clock.h
index cb041e6..dce2538 100644
--- a/base/time/default_tick_clock.h
+++ b/base/time/default_tick_clock.h
@@ -18,6 +18,9 @@
 
   // Simply returns TimeTicks::Now().
   TimeTicks NowTicks() override;
+
+  // Returns a shared instance of DefaultTickClock. This is thread-safe.
+  static DefaultTickClock* GetInstance();
 };
 
 }  // namespace base
diff --git a/third_party/WebKit/Source/platform/exported/WebCORSPreflightResultCache.cpp b/third_party/WebKit/Source/platform/exported/WebCORSPreflightResultCache.cpp
index ef14070..bd421f9 100644
--- a/third_party/WebKit/Source/platform/exported/WebCORSPreflightResultCache.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebCORSPreflightResultCache.cpp
@@ -27,6 +27,8 @@
 #include "public/platform/WebCORSPreflightResultCache.h"
 
 #include <memory>
+#include "base/time/default_tick_clock.h"
+#include "base/time/tick_clock.h"
 #include "platform/loader/fetch/FetchUtils.h"
 #include "platform/loader/fetch/ResourceResponse.h"
 #include "platform/network/http_names.h"
@@ -41,16 +43,16 @@
 
 // These values are at the discretion of the user agent.
 
-constexpr unsigned kDefaultPreflightCacheTimeoutSeconds = 5;
+constexpr TimeDelta kDefaultPreflightCacheTimeout = TimeDelta::FromSeconds(5);
 
 // Should be short enough to minimize the risk of using a poisoned cache after
 // switching to a secure network.
-constexpr unsigned kMaxPreflightCacheTimeoutSeconds = 600;
+constexpr TimeDelta kMaxPreflightCacheTimeout = TimeDelta::FromSeconds(600);
 
-bool ParseAccessControlMaxAge(const String& string, unsigned& expiry_delta) {
+bool ParseAccessControlMaxAge(const String& string, TimeDelta& expiry_delta) {
   // FIXME: this will not do the correct thing for a number starting with a '+'
   bool ok = false;
-  expiry_delta = string.ToUIntStrict(&ok);
+  expiry_delta = TimeDelta::FromSeconds(string.ToUIntStrict(&ok));
   return ok;
 }
 
@@ -95,19 +97,23 @@
 }  // namespace
 
 WebCORSPreflightResultCacheItem::WebCORSPreflightResultCacheItem(
-    network::mojom::FetchCredentialsMode credentials_mode)
-    : absolute_expiry_time_(0),
-      credentials_(credentials_mode ==
-                   network::mojom::FetchCredentialsMode::kInclude) {}
+    network::mojom::FetchCredentialsMode credentials_mode,
+    base::TickClock* clock)
+    : credentials_(credentials_mode ==
+                   network::mojom::FetchCredentialsMode::kInclude),
+      clock_(clock) {}
 
 // static
 std::unique_ptr<WebCORSPreflightResultCacheItem>
 WebCORSPreflightResultCacheItem::Create(
     const network::mojom::FetchCredentialsMode credentials_mode,
     const WebHTTPHeaderMap& response_header,
-    WebString& error_description) {
+    WebString& error_description,
+    base::TickClock* clock) {
   std::unique_ptr<WebCORSPreflightResultCacheItem> item =
-      base::WrapUnique(new WebCORSPreflightResultCacheItem(credentials_mode));
+      base::WrapUnique(new WebCORSPreflightResultCacheItem(
+          credentials_mode,
+          clock ? clock : base::DefaultTickClock::GetInstance()));
 
   if (!item->Parse(response_header, error_description))
     return nullptr;
@@ -145,17 +151,17 @@
     return false;
   }
 
-  unsigned expiry_delta;
+  TimeDelta expiry_delta;
   if (ParseAccessControlMaxAge(
           response_header_map.Get(HTTPNames::Access_Control_Max_Age),
           expiry_delta)) {
-    if (expiry_delta > kMaxPreflightCacheTimeoutSeconds)
-      expiry_delta = kMaxPreflightCacheTimeoutSeconds;
+    if (expiry_delta > kMaxPreflightCacheTimeout)
+      expiry_delta = kMaxPreflightCacheTimeout;
   } else {
-    expiry_delta = kDefaultPreflightCacheTimeoutSeconds;
+    expiry_delta = kDefaultPreflightCacheTimeout;
   }
 
-  absolute_expiry_time_ = CurrentTime() + expiry_delta;
+  absolute_expiry_time_ = clock_->NowTicks() + expiry_delta;
 
   return true;
 }
@@ -205,7 +211,7 @@
     const WebHTTPHeaderMap& request_headers) const {
   WebString ignored_explanation;
 
-  if (absolute_expiry_time_ < CurrentTime())
+  if (absolute_expiry_time_ < clock_->NowTicks())
     return false;
   if (!credentials_ &&
       credentials_mode == network::mojom::FetchCredentialsMode::kInclude) {
diff --git a/third_party/WebKit/Source/platform/exported/WebCORSPreflightResultCacheTest.cpp b/third_party/WebKit/Source/platform/exported/WebCORSPreflightResultCacheTest.cpp
index 35d6e7c..2a108b2c 100644
--- a/third_party/WebKit/Source/platform/exported/WebCORSPreflightResultCacheTest.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebCORSPreflightResultCacheTest.cpp
@@ -4,6 +4,7 @@
 
 #include "public/platform/WebCORSPreflightResultCache.h"
 
+#include "base/test/simple_test_tick_clock.h"
 #include "platform/network/HTTPHeaderMap.h"
 #include "platform/testing/URLTestHelpers.h"
 #include "platform/weborigin/KURL.h"
@@ -14,12 +15,6 @@
 
 namespace test {
 
-static double current_time = 1000.0;
-
-static double MockTimeFunction() {
-  return current_time;
-}
-
 class TestWebCORSPreflightResultCache : public WebCORSPreflightResultCache {
  public:
   TestWebCORSPreflightResultCache() = default;
@@ -68,13 +63,15 @@
     WebString error_description;
     std::unique_ptr<WebCORSPreflightResultCacheItem> item =
         WebCORSPreflightResultCacheItem::Create(
-            credentials_mode, response_header, error_description);
+            credentials_mode, response_header, error_description, clock());
 
     EXPECT_TRUE(item);
 
     return item;
   }
 
+  base::SimpleTestTickClock* clock() { return &clock_; }
+
   // This is by no means a robust parser and works only for the headers strings
   // used in this tests.
   HTTPHeaderMap ParseHeaderString(std::string headers) {
@@ -92,6 +89,9 @@
 
     return header_map;
   }
+
+ private:
+  base::SimpleTestTickClock clock_;
 };
 
 TEST_F(WebCORSPreflightResultCacheTest, CacheTimeout) {
@@ -101,8 +101,6 @@
 
   test::TestWebCORSPreflightResultCache cache;
 
-  TimeFunction previous = SetTimeFunctionsForTesting(test::MockTimeFunction);
-
   // Cache should be empty:
   EXPECT_EQ(0, cache.CacheSize());
 
@@ -124,7 +122,7 @@
       HTTPHeaderMap()));
 
   // Advance time by ten seconds:
-  test::current_time += 10;
+  clock()->Advance(TimeDelta::FromSeconds(10));
 
   // Cache entry should now be expired:
   EXPECT_FALSE(cache.CanSkipPreflight(
@@ -143,8 +141,6 @@
   // Cache size should be 0, with the expired entry removed by call to
   // CanSkipPreflight():
   EXPECT_EQ(0, cache.CacheSize());
-
-  SetTimeFunctionsForTesting(previous);
 }
 
 TEST_F(WebCORSPreflightResultCacheTest, CacheSize) {
diff --git a/third_party/WebKit/public/platform/WebCORSPreflightResultCache.h b/third_party/WebKit/public/platform/WebCORSPreflightResultCache.h
index c5f6794..76d40986 100644
--- a/third_party/WebKit/public/platform/WebCORSPreflightResultCache.h
+++ b/third_party/WebKit/public/platform/WebCORSPreflightResultCache.h
@@ -30,6 +30,7 @@
 #include <memory>
 #include <string>
 #include "base/containers/flat_set.h"
+#include "base/time/time.h"
 #include "platform/loader/fetch/ResourceLoaderOptions.h"
 #include "public/platform/WebHTTPHeaderMap.h"
 #include "public/platform/WebHTTPHeaderSet.h"
@@ -38,6 +39,10 @@
 #include "public/platform/WebURLRequest.h"
 #include "public/platform/WebURLResponse.h"
 
+namespace base {
+class TickClock;
+}
+
 namespace blink {
 
 // Represents an entry of the CORS-preflight cache.
@@ -52,7 +57,8 @@
   static std::unique_ptr<WebCORSPreflightResultCacheItem> Create(
       const network::mojom::FetchCredentialsMode,
       const WebHTTPHeaderMap&,
-      WebString& error_description);
+      WebString& error_description,
+      base::TickClock* = nullptr);
 
   bool AllowsCrossOriginMethod(const WebString& method,
                                WebString& error_description) const;
@@ -63,8 +69,8 @@
                      const WebHTTPHeaderMap& request_headers) const;
 
  private:
-  explicit WebCORSPreflightResultCacheItem(
-      network::mojom::FetchCredentialsMode);
+  WebCORSPreflightResultCacheItem(network::mojom::FetchCredentialsMode,
+                                  base::TickClock*);
 
   bool Parse(const WebHTTPHeaderMap& response_header,
              WebString& error_description);
@@ -72,12 +78,13 @@
   // FIXME: A better solution to holding onto the absolute expiration time might
   // be to start a timer for the expiration delta that removes this from the
   // cache when it fires.
-  double absolute_expiry_time_;
+  base::TimeTicks absolute_expiry_time_;
 
   // Corresponds to the fields of the CORS-preflight cache with the same name.
   bool credentials_;
   base::flat_set<std::string> methods_;
   WebHTTPHeaderSet headers_;
+  base::TickClock* clock_;
 };
 
 class BLINK_PLATFORM_EXPORT WebCORSPreflightResultCache {