OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #include "ios/net/cookies/system_cookie_util.h" |
| 6 |
| 7 #import <Foundation/Foundation.h> |
| 8 |
| 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" |
| 15 |
| 16 namespace net { |
| 17 |
| 18 namespace { |
| 19 |
| 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 |
| 26 }; |
| 27 |
| 28 // Undocumented property of NSHTTPCookie. |
| 29 NSString* const kNSHTTPCookieHttpOnly = @"HttpOnly"; |
| 30 |
| 31 // Key in NSUserDefaults telling wether a low cookie count must be reported as |
| 32 // an error. |
| 33 NSString* const kCheckCookieLossKey = @"CookieUtilIOSCheckCookieLoss"; |
| 34 |
| 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; |
| 43 |
| 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 } |
| 60 } |
| 61 |
| 62 } // namespace |
| 63 |
| 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); |
| 76 } |
| 77 |
| 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; |
| 108 } |
| 109 |
| 110 void CheckForCookieLoss(size_t cookie_count, CookieEvent event) { |
| 111 NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; |
| 112 BOOL check_cookie_loss = [defaults boolForKey:kCheckCookieLossKey]; |
| 113 |
| 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 } |
| 120 |
| 121 if (!check_cookie_loss) { |
| 122 // Error reporting is disabled. |
| 123 ReportUMACookieLoss(NOT_ENOUGH_COOKIES, event); |
| 124 return; |
| 125 } |
| 126 |
| 127 if (cookie_count > kCookieThresholdLow) { |
| 128 // No cookie loss. |
| 129 ReportUMACookieLoss(NO_LOSS, event); |
| 130 return; |
| 131 } |
| 132 |
| 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 |
| 139 |
| 140 ReportUMACookieLoss(LOSS, event); |
| 141 |
| 142 // Disable reporting until the cookie count rises above kCookieThresholdHigh |
| 143 // again. |
| 144 ResetCookieCountMetrics(); |
| 145 } |
| 146 |
| 147 void ResetCookieCountMetrics() { |
| 148 NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; |
| 149 [defaults setBool:NO forKey:kCheckCookieLossKey]; |
| 150 [defaults synchronize]; |
| 151 } |
| 152 |
| 153 } // namespace net |
OLD | NEW |