Add ICU message format support
[chromium-blink-merge.git] / ios / net / cookies / cookie_creation_time_manager.mm
blob665b6a39f59f8059ed2268d8ed065fa9b11f5554
1 // Copyright (c) 2012 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.
5 #include "ios/net/cookies/cookie_creation_time_manager.h"
7 #include <Foundation/Foundation.h>
9 #include "base/logging.h"
10 #include "base/strings/sys_string_conversions.h"
11 #include "base/time/time.h"
13 // Key holding the creation-time in NSHTTPCookie properties.
14 // This key is undocumented, and its value has type NSNumber.
15 NSString* const kHTTPCookieCreated = @"Created";
17 namespace {
19 // Gets the creation date of a NSHTTPCookie, reading a undocumented property.
20 base::Time GetCreationTimeFromObject(NSHTTPCookie* cookie) {
21   // The "Created" key is not documented.
22   // Return a null time if the key is missing.
23   id created = [[cookie properties] objectForKey:kHTTPCookieCreated];
24   DCHECK(created && [created isKindOfClass:[NSNumber class]]);
25   if (!created || ![created isKindOfClass:[NSNumber class]])
26     return base::Time();
27   // created is the time from January 1st, 2001 in seconds.
28   CFAbsoluteTime absolute_time = [(NSNumber*)created doubleValue];
29   // If the cookie has been created using |-initWithProperties:|, the creation
30   // date property is (incorrectly) set to 1.0. Treat that as an invalid time.
31   if (absolute_time < 2.0)
32     return base::Time();
33   return base::Time::FromCFAbsoluteTime(absolute_time);
36 // Gets a string that can be used as a unique identifier for |cookie|.
37 std::string GetCookieUniqueID(NSHTTPCookie* cookie) {
38   return base::SysNSStringToUTF8([cookie name]) + ";" +
39          base::SysNSStringToUTF8([cookie domain]) + ";" +
40          base::SysNSStringToUTF8([cookie path]);
43 }  // namespace
45 namespace net {
47 CookieCreationTimeManager::CookieCreationTimeManager() {
50 CookieCreationTimeManager::~CookieCreationTimeManager() {
53 void CookieCreationTimeManager::SetCreationTime(
54     NSHTTPCookie* cookie,
55     const base::Time& creation_time) {
56   DCHECK(thread_checker_.CalledOnValidThread());
57   DCHECK(unique_times_.find(creation_time) == unique_times_.end());
59   // If the cookie overrides an existing cookie, remove its creation time.
60   auto it = creation_times_.find(GetCookieUniqueID(cookie));
61   if (it != creation_times_.end()) {
62     size_t erased = unique_times_.erase(it->second);
63     DCHECK_EQ(1u, erased);
64   }
66   unique_times_.insert(creation_time);
67   creation_times_[GetCookieUniqueID(cookie)] = creation_time;
70 base::Time CookieCreationTimeManager::MakeUniqueCreationTime(
71     const base::Time& creation_time) {
72   DCHECK(thread_checker_.CalledOnValidThread());
73   auto it = unique_times_.find(creation_time);
75   if (it == unique_times_.end())
76     return creation_time;
78   // If the time already exist, increment until we find a time available.
79   // |unique_times_| is sorted according to time, so we can traverse it from
80   // |it|.
81   base::Time time = creation_time;
82   do {
83     DCHECK(time == *it);
84     ++it;
85     time = base::Time::FromInternalValue(time.ToInternalValue() + 1);
86   } while (it != unique_times_.end() && *it == time);
88   return time;
91 base::Time CookieCreationTimeManager::GetCreationTime(NSHTTPCookie* cookie) {
92   DCHECK(thread_checker_.CalledOnValidThread());
93   base::hash_map<std::string, base::Time>::iterator it =
94       creation_times_.find(GetCookieUniqueID(cookie));
95   if (it != creation_times_.end())
96     return it->second;
98   base::Time native_creation_time = GetCreationTimeFromObject(cookie);
99   native_creation_time = MakeUniqueCreationTime(native_creation_time);
100   SetCreationTime(cookie, native_creation_time);
101   return native_creation_time;
104 void CookieCreationTimeManager::DeleteCreationTime(NSHTTPCookie* cookie) {
105   DCHECK(thread_checker_.CalledOnValidThread());
106   auto it = creation_times_.find(GetCookieUniqueID(cookie));
107   if (it != creation_times_.end()) {
108     size_t erased = unique_times_.erase(it->second);
109     DCHECK_EQ(1u, erased);
110     creation_times_.erase(it);
111   }
114 void CookieCreationTimeManager::Clear() {
115   DCHECK(thread_checker_.CalledOnValidThread());
116   creation_times_.clear();
117   unique_times_.clear();
120 }  // namespace net