| Index: ios/net/cookies/system_cookie_util.mm
|
| diff --git a/ios/net/cookies/system_cookie_util.mm b/ios/net/cookies/system_cookie_util.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..5414e0f7894e514f143325c711c977b85ef492ab
|
| --- /dev/null
|
| +++ b/ios/net/cookies/system_cookie_util.mm
|
| @@ -0,0 +1,153 @@
|
| +// Copyright 2014 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/system_cookie_util.h"
|
| +
|
| +#import <Foundation/Foundation.h>
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/metrics/histogram.h"
|
| +#include "base/strings/stringprintf.h"
|
| +#include "base/strings/sys_string_conversions.h"
|
| +#include "net/cookies/cookie_constants.h"
|
| +#include "url/gurl.h"
|
| +
|
| +namespace net {
|
| +
|
| +namespace {
|
| +
|
| +// Used to report cookie loss events in UMA.
|
| +enum CookieLossType {
|
| + LOSS,
|
| + NOT_ENOUGH_COOKIES, // Not enough cookies, error checking is disabled.
|
| + NO_LOSS,
|
| + COOKIE_LOSS_ENUM_COUNT
|
| +};
|
| +
|
| +// Undocumented property of NSHTTPCookie.
|
| +NSString* const kNSHTTPCookieHttpOnly = @"HttpOnly";
|
| +
|
| +// Key in NSUserDefaults telling wether a low cookie count must be reported as
|
| +// an error.
|
| +NSString* const kCheckCookieLossKey = @"CookieUtilIOSCheckCookieLoss";
|
| +
|
| +// When the cookie count reaches |kCookieThresholdHigh|, and then drops below
|
| +// |kCookieThresholdLow|, an error is reported.
|
| +// Cookies count immediately after installation may fluctuate due to session
|
| +// cookies that can expire quickly. In order to catch true cookie loss, it is
|
| +// better to wait till a sufficiently large number of cookies have been
|
| +// accumulated before checking for sudden drop in cookies count.
|
| +const size_t kCookieThresholdHigh = 100;
|
| +const size_t kCookieThresholdLow = 30;
|
| +
|
| +// Updates the cookie loss histograms.
|
| +// |event| determines which histogram is updated, and |loss| is the value to add
|
| +// to this histogram.
|
| +void ReportUMACookieLoss(CookieLossType loss, CookieEvent event) {
|
| + // Histogram macros require constant histogram names. Use the string constants
|
| + // explicitly instead of using a variable.
|
| + switch (event) {
|
| + case COOKIES_READ:
|
| + UMA_HISTOGRAM_ENUMERATION("CookieStoreIOS.LossOnRead", loss,
|
| + COOKIE_LOSS_ENUM_COUNT);
|
| + break;
|
| + case COOKIES_APPLICATION_FOREGROUNDED:
|
| + UMA_HISTOGRAM_ENUMERATION("CookieStoreIOS.LossOnForegrounding", loss,
|
| + COOKIE_LOSS_ENUM_COUNT);
|
| + break;
|
| + }
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// Converts NSHTTPCookie to net::CanonicalCookie.
|
| +net::CanonicalCookie CanonicalCookieFromSystemCookie(
|
| + NSHTTPCookie* cookie,
|
| + const base::Time& ceation_time) {
|
| + return net::CanonicalCookie(
|
| + GURL(), base::SysNSStringToUTF8([cookie name]),
|
| + base::SysNSStringToUTF8([cookie value]),
|
| + base::SysNSStringToUTF8([cookie domain]),
|
| + base::SysNSStringToUTF8([cookie path]), ceation_time,
|
| + base::Time::FromDoubleT([[cookie expiresDate] timeIntervalSince1970]),
|
| + base::Time(), [cookie isSecure], [cookie isHTTPOnly], false,
|
| + net::COOKIE_PRIORITY_DEFAULT);
|
| +}
|
| +
|
| +// Converts net::CanonicalCookie to NSHTTPCookie.
|
| +NSHTTPCookie* SystemCookieFromCanonicalCookie(
|
| + const net::CanonicalCookie& cookie) {
|
| + NSString* cookie_domain = base::SysUTF8ToNSString(cookie.Domain());
|
| + NSString* cookie_name = base::SysUTF8ToNSString(cookie.Name());
|
| + NSString* cookie_path = base::SysUTF8ToNSString(cookie.Path());
|
| + NSString* cookie_value = base::SysUTF8ToNSString(cookie.Value());
|
| + if (!cookie_domain || !cookie_name || !cookie_path || !cookie_value) {
|
| + DLOG(ERROR) << "Cannot create system cookie: " << cookie.DebugString();
|
| + return nil;
|
| + }
|
| + NSMutableDictionary* properties =
|
| + [NSMutableDictionary dictionaryWithDictionary:@{
|
| + NSHTTPCookieDomain : cookie_domain,
|
| + NSHTTPCookieName : cookie_name,
|
| + NSHTTPCookiePath : cookie_path,
|
| + NSHTTPCookieValue : cookie_value,
|
| + }];
|
| + if (cookie.IsPersistent()) {
|
| + NSDate* expiry =
|
| + [NSDate dateWithTimeIntervalSince1970:cookie.ExpiryDate().ToDoubleT()];
|
| + [properties setObject:expiry forKey:NSHTTPCookieExpires];
|
| + }
|
| + if (cookie.IsSecure())
|
| + [properties setObject:@"Y" forKey:NSHTTPCookieSecure];
|
| + if (cookie.IsHttpOnly())
|
| + [properties setObject:@YES forKey:kNSHTTPCookieHttpOnly];
|
| + NSHTTPCookie* system_cookie = [NSHTTPCookie cookieWithProperties:properties];
|
| + DCHECK(system_cookie);
|
| + return system_cookie;
|
| +}
|
| +
|
| +void CheckForCookieLoss(size_t cookie_count, CookieEvent event) {
|
| + NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
|
| + BOOL check_cookie_loss = [defaults boolForKey:kCheckCookieLossKey];
|
| +
|
| + // Start reporting errors if the cookie count goes above kCookieThresholdHigh.
|
| + if (!check_cookie_loss && cookie_count >= kCookieThresholdHigh) {
|
| + [defaults setBool:YES forKey:kCheckCookieLossKey];
|
| + [defaults synchronize];
|
| + return;
|
| + }
|
| +
|
| + if (!check_cookie_loss) {
|
| + // Error reporting is disabled.
|
| + ReportUMACookieLoss(NOT_ENOUGH_COOKIES, event);
|
| + return;
|
| + }
|
| +
|
| + if (cookie_count > kCookieThresholdLow) {
|
| + // No cookie loss.
|
| + ReportUMACookieLoss(NO_LOSS, event);
|
| + return;
|
| + }
|
| +
|
| +#if 0
|
| + // TODO(ios): [Merge 277884]: crbug.com/386074 ERROR_REPORT is no longer
|
| + // supported.
|
| + LOG(ERROR_REPORT) << "Possible cookie issue (crbug/370024)\nCookie count: "
|
| + << cookie_count;
|
| +#endif
|
| +
|
| + ReportUMACookieLoss(LOSS, event);
|
| +
|
| + // Disable reporting until the cookie count rises above kCookieThresholdHigh
|
| + // again.
|
| + ResetCookieCountMetrics();
|
| +}
|
| +
|
| +void ResetCookieCountMetrics() {
|
| + NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
|
| + [defaults setBool:NO forKey:kCheckCookieLossKey];
|
| + [defaults synchronize];
|
| +}
|
| +
|
| +} // namespace net
|
|
|