Add ICU message format support
[chromium-blink-merge.git] / ios / net / cookies / system_cookie_util.mm
blob5414e0f7894e514f143325c711c977b85ef492ab
1 // Copyright 2014 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/system_cookie_util.h"
7 #import <Foundation/Foundation.h>
9 #include "base/logging.h"
10 #include "base/metrics/histogram.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/strings/sys_string_conversions.h"
13 #include "net/cookies/cookie_constants.h"
14 #include "url/gurl.h"
16 namespace net {
18 namespace {
20 // Used to report cookie loss events in UMA.
21 enum CookieLossType {
22   LOSS,
23   NOT_ENOUGH_COOKIES,  // Not enough cookies, error checking is disabled.
24   NO_LOSS,
25   COOKIE_LOSS_ENUM_COUNT
28 // Undocumented property of NSHTTPCookie.
29 NSString* const kNSHTTPCookieHttpOnly = @"HttpOnly";
31 // Key in NSUserDefaults telling wether a low cookie count must be reported as
32 // an error.
33 NSString* const kCheckCookieLossKey = @"CookieUtilIOSCheckCookieLoss";
35 // When the cookie count reaches |kCookieThresholdHigh|, and then drops below
36 // |kCookieThresholdLow|, an error is reported.
37 // Cookies count immediately after installation may fluctuate due to session
38 // cookies that can expire quickly. In order to catch true cookie loss, it is
39 // better to wait till a sufficiently large number of cookies have been
40 // accumulated before checking for sudden drop in cookies count.
41 const size_t kCookieThresholdHigh = 100;
42 const size_t kCookieThresholdLow = 30;
44 // Updates the cookie loss histograms.
45 // |event| determines which histogram is updated, and |loss| is the value to add
46 // to this histogram.
47 void ReportUMACookieLoss(CookieLossType loss, CookieEvent event) {
48   // Histogram macros require constant histogram names. Use the string constants
49   // explicitly instead of using a variable.
50   switch (event) {
51     case COOKIES_READ:
52       UMA_HISTOGRAM_ENUMERATION("CookieStoreIOS.LossOnRead", loss,
53                                 COOKIE_LOSS_ENUM_COUNT);
54       break;
55     case COOKIES_APPLICATION_FOREGROUNDED:
56       UMA_HISTOGRAM_ENUMERATION("CookieStoreIOS.LossOnForegrounding", loss,
57                                 COOKIE_LOSS_ENUM_COUNT);
58       break;
59   }
62 }  // namespace
64 // Converts NSHTTPCookie to net::CanonicalCookie.
65 net::CanonicalCookie CanonicalCookieFromSystemCookie(
66     NSHTTPCookie* cookie,
67     const base::Time& ceation_time) {
68   return net::CanonicalCookie(
69       GURL(), base::SysNSStringToUTF8([cookie name]),
70       base::SysNSStringToUTF8([cookie value]),
71       base::SysNSStringToUTF8([cookie domain]),
72       base::SysNSStringToUTF8([cookie path]), ceation_time,
73       base::Time::FromDoubleT([[cookie expiresDate] timeIntervalSince1970]),
74       base::Time(), [cookie isSecure], [cookie isHTTPOnly], false,
75       net::COOKIE_PRIORITY_DEFAULT);
78 // Converts net::CanonicalCookie to NSHTTPCookie.
79 NSHTTPCookie* SystemCookieFromCanonicalCookie(
80     const net::CanonicalCookie& cookie) {
81   NSString* cookie_domain = base::SysUTF8ToNSString(cookie.Domain());
82   NSString* cookie_name = base::SysUTF8ToNSString(cookie.Name());
83   NSString* cookie_path = base::SysUTF8ToNSString(cookie.Path());
84   NSString* cookie_value = base::SysUTF8ToNSString(cookie.Value());
85   if (!cookie_domain || !cookie_name || !cookie_path || !cookie_value) {
86     DLOG(ERROR) << "Cannot create system cookie: " << cookie.DebugString();
87     return nil;
88   }
89   NSMutableDictionary* properties =
90       [NSMutableDictionary dictionaryWithDictionary:@{
91         NSHTTPCookieDomain : cookie_domain,
92         NSHTTPCookieName : cookie_name,
93         NSHTTPCookiePath : cookie_path,
94         NSHTTPCookieValue : cookie_value,
95       }];
96   if (cookie.IsPersistent()) {
97     NSDate* expiry =
98         [NSDate dateWithTimeIntervalSince1970:cookie.ExpiryDate().ToDoubleT()];
99     [properties setObject:expiry forKey:NSHTTPCookieExpires];
100   }
101   if (cookie.IsSecure())
102     [properties setObject:@"Y" forKey:NSHTTPCookieSecure];
103   if (cookie.IsHttpOnly())
104     [properties setObject:@YES forKey:kNSHTTPCookieHttpOnly];
105   NSHTTPCookie* system_cookie = [NSHTTPCookie cookieWithProperties:properties];
106   DCHECK(system_cookie);
107   return system_cookie;
110 void CheckForCookieLoss(size_t cookie_count, CookieEvent event) {
111   NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
112   BOOL check_cookie_loss = [defaults boolForKey:kCheckCookieLossKey];
114   // Start reporting errors if the cookie count goes above kCookieThresholdHigh.
115   if (!check_cookie_loss && cookie_count >= kCookieThresholdHigh) {
116     [defaults setBool:YES forKey:kCheckCookieLossKey];
117     [defaults synchronize];
118     return;
119   }
121   if (!check_cookie_loss) {
122     // Error reporting is disabled.
123     ReportUMACookieLoss(NOT_ENOUGH_COOKIES, event);
124     return;
125   }
127   if (cookie_count > kCookieThresholdLow) {
128     // No cookie loss.
129     ReportUMACookieLoss(NO_LOSS, event);
130     return;
131   }
133 #if 0
134   // TODO(ios): [Merge 277884]: crbug.com/386074 ERROR_REPORT is no longer
135   // supported.
136   LOG(ERROR_REPORT) << "Possible cookie issue (crbug/370024)\nCookie count: "
137                     << cookie_count;
138 #endif
140   ReportUMACookieLoss(LOSS, event);
142   // Disable reporting until the cookie count rises above kCookieThresholdHigh
143   // again.
144   ResetCookieCountMetrics();
147 void ResetCookieCountMetrics() {
148   NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
149   [defaults setBool:NO forKey:kCheckCookieLossKey];
150   [defaults synchronize];
153 }  // namespace net