| Index: ios/net/cookies/cookie_creation_time_manager.mm
|
| diff --git a/ios/net/cookies/cookie_creation_time_manager.mm b/ios/net/cookies/cookie_creation_time_manager.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..665b6a39f59f8059ed2268d8ed065fa9b11f5554
|
| --- /dev/null
|
| +++ b/ios/net/cookies/cookie_creation_time_manager.mm
|
| @@ -0,0 +1,120 @@
|
| +// 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.
|
| +
|
| +#include "ios/net/cookies/cookie_creation_time_manager.h"
|
| +
|
| +#include <Foundation/Foundation.h>
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/strings/sys_string_conversions.h"
|
| +#include "base/time/time.h"
|
| +
|
| +// Key holding the creation-time in NSHTTPCookie properties.
|
| +// This key is undocumented, and its value has type NSNumber.
|
| +NSString* const kHTTPCookieCreated = @"Created";
|
| +
|
| +namespace {
|
| +
|
| +// Gets the creation date of a NSHTTPCookie, reading a undocumented property.
|
| +base::Time GetCreationTimeFromObject(NSHTTPCookie* cookie) {
|
| + // The "Created" key is not documented.
|
| + // Return a null time if the key is missing.
|
| + id created = [[cookie properties] objectForKey:kHTTPCookieCreated];
|
| + DCHECK(created && [created isKindOfClass:[NSNumber class]]);
|
| + if (!created || ![created isKindOfClass:[NSNumber class]])
|
| + return base::Time();
|
| + // created is the time from January 1st, 2001 in seconds.
|
| + CFAbsoluteTime absolute_time = [(NSNumber*)created doubleValue];
|
| + // If the cookie has been created using |-initWithProperties:|, the creation
|
| + // date property is (incorrectly) set to 1.0. Treat that as an invalid time.
|
| + if (absolute_time < 2.0)
|
| + return base::Time();
|
| + return base::Time::FromCFAbsoluteTime(absolute_time);
|
| +}
|
| +
|
| +// Gets a string that can be used as a unique identifier for |cookie|.
|
| +std::string GetCookieUniqueID(NSHTTPCookie* cookie) {
|
| + return base::SysNSStringToUTF8([cookie name]) + ";" +
|
| + base::SysNSStringToUTF8([cookie domain]) + ";" +
|
| + base::SysNSStringToUTF8([cookie path]);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +namespace net {
|
| +
|
| +CookieCreationTimeManager::CookieCreationTimeManager() {
|
| +}
|
| +
|
| +CookieCreationTimeManager::~CookieCreationTimeManager() {
|
| +}
|
| +
|
| +void CookieCreationTimeManager::SetCreationTime(
|
| + NSHTTPCookie* cookie,
|
| + const base::Time& creation_time) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + DCHECK(unique_times_.find(creation_time) == unique_times_.end());
|
| +
|
| + // If the cookie overrides an existing cookie, remove its creation time.
|
| + auto it = creation_times_.find(GetCookieUniqueID(cookie));
|
| + if (it != creation_times_.end()) {
|
| + size_t erased = unique_times_.erase(it->second);
|
| + DCHECK_EQ(1u, erased);
|
| + }
|
| +
|
| + unique_times_.insert(creation_time);
|
| + creation_times_[GetCookieUniqueID(cookie)] = creation_time;
|
| +}
|
| +
|
| +base::Time CookieCreationTimeManager::MakeUniqueCreationTime(
|
| + const base::Time& creation_time) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + auto it = unique_times_.find(creation_time);
|
| +
|
| + if (it == unique_times_.end())
|
| + return creation_time;
|
| +
|
| + // If the time already exist, increment until we find a time available.
|
| + // |unique_times_| is sorted according to time, so we can traverse it from
|
| + // |it|.
|
| + base::Time time = creation_time;
|
| + do {
|
| + DCHECK(time == *it);
|
| + ++it;
|
| + time = base::Time::FromInternalValue(time.ToInternalValue() + 1);
|
| + } while (it != unique_times_.end() && *it == time);
|
| +
|
| + return time;
|
| +}
|
| +
|
| +base::Time CookieCreationTimeManager::GetCreationTime(NSHTTPCookie* cookie) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + base::hash_map<std::string, base::Time>::iterator it =
|
| + creation_times_.find(GetCookieUniqueID(cookie));
|
| + if (it != creation_times_.end())
|
| + return it->second;
|
| +
|
| + base::Time native_creation_time = GetCreationTimeFromObject(cookie);
|
| + native_creation_time = MakeUniqueCreationTime(native_creation_time);
|
| + SetCreationTime(cookie, native_creation_time);
|
| + return native_creation_time;
|
| +}
|
| +
|
| +void CookieCreationTimeManager::DeleteCreationTime(NSHTTPCookie* cookie) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + auto it = creation_times_.find(GetCookieUniqueID(cookie));
|
| + if (it != creation_times_.end()) {
|
| + size_t erased = unique_times_.erase(it->second);
|
| + DCHECK_EQ(1u, erased);
|
| + creation_times_.erase(it);
|
| + }
|
| +}
|
| +
|
| +void CookieCreationTimeManager::Clear() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + creation_times_.clear();
|
| + unique_times_.clear();
|
| +}
|
| +
|
| +} // namespace net
|
|
|