| 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/web/net/request_group_util.h" |
| 6 |
| 7 #include <Foundation/Foundation.h> |
| 8 |
| 9 #include "base/base64.h" |
| 10 #include "base/logging.h" |
| 11 #include "base/rand_util.h" |
| 12 #include "base/strings/sys_string_conversions.h" |
| 13 #import "net/base/mac/url_conversions.h" |
| 14 #include "url/gurl.h" |
| 15 |
| 16 namespace { |
| 17 // Minimum length for a request group ID. A shorter string is considered as an |
| 18 // invalid ID. |
| 19 const int kMinimumIDLength = 5; |
| 20 } |
| 21 |
| 22 namespace web { |
| 23 |
| 24 // Generates a request-group ID used to correlate web requests with the embedder |
| 25 // that triggered it. It is important that the return value should not be unique |
| 26 // for different users. See crbug/355613 for context. |
| 27 NSString* GenerateNewRequestGroupID() { |
| 28 const unsigned int kGroupSize = 1000; |
| 29 static unsigned long count = 0; |
| 30 static unsigned int offset = base::RandInt(0, kGroupSize - 1); |
| 31 |
| 32 unsigned long current = count++; |
| 33 if (current < kGroupSize) |
| 34 current = (current + offset) % kGroupSize; |
| 35 |
| 36 // The returned string must have a minimum of kMinimumIDLength characters, and |
| 37 // no spaces. |
| 38 // TODO(blundell): Develop a long-term solution to this problem. |
| 39 // crbug.com/329243 |
| 40 return [NSString stringWithFormat:@"%06lu", current]; |
| 41 } |
| 42 |
| 43 NSString* ExtractRequestGroupIDFromUserAgent(NSString* user_agent) { |
| 44 if (![user_agent length]) |
| 45 return nil; |
| 46 |
| 47 // The request_group_id is wrapped by parenthesis in the last space-delimited |
| 48 // fragment. |
| 49 NSString* fragment = |
| 50 [[user_agent componentsSeparatedByString:@" "] lastObject]; |
| 51 NSString* request_group_id = |
| 52 [fragment hasPrefix:@"("] && [fragment hasSuffix:@")"] |
| 53 ? [fragment substringWithRange:NSMakeRange(1, [fragment length] - 2)] |
| 54 : nil; |
| 55 // GTLService constructs user agents that end with "(gzip)". To avoid these |
| 56 // getting treated as having the request_group_id "gzip", short-circuit out if |
| 57 // the request_group_id is not long enough to be a valid request_group_id (all |
| 58 // valid request_group_id are at least kMinimumIDLength characters long). |
| 59 // TODO(blundell): Develop a long-term solution to this problem. |
| 60 // crbug.com/329243 |
| 61 if ([request_group_id length] < kMinimumIDLength) |
| 62 return nil; |
| 63 return request_group_id; |
| 64 } |
| 65 |
| 66 NSString* AddRequestGroupIDToUserAgent(NSString* base_user_agent, |
| 67 NSString* request_group_id) { |
| 68 // TODO(blundell): Develop a long-term solution to this problem. |
| 69 // crbug.com/329243 |
| 70 DCHECK([request_group_id length] >= kMinimumIDLength); |
| 71 return |
| 72 [NSString stringWithFormat:@"%@ (%@)", base_user_agent, request_group_id]; |
| 73 } |
| 74 |
| 75 NSString* ExtractRequestGroupIDFromURL(NSURL* url) { |
| 76 GURL gurl = net::GURLWithNSURL(url); |
| 77 if (!gurl.has_username()) |
| 78 return nil; |
| 79 |
| 80 std::string request_group_id_as_string; |
| 81 if (base::Base64Decode(gurl.username(), &request_group_id_as_string)) |
| 82 return base::SysUTF8ToNSString(request_group_id_as_string); |
| 83 |
| 84 return nil; |
| 85 } |
| 86 |
| 87 NSURL* AddRequestGroupIDToURL(NSURL* base_url, NSString* request_group_id) { |
| 88 GURL url = net::GURLWithNSURL(base_url); |
| 89 std::string base64RequestGroupID; |
| 90 base::Base64Encode(base::SysNSStringToUTF8(request_group_id), |
| 91 &base64RequestGroupID); |
| 92 GURL::Replacements replacements; |
| 93 replacements.SetUsernameStr(base64RequestGroupID); |
| 94 url = url.ReplaceComponents(replacements); |
| 95 return net::NSURLWithGURL(url); |
| 96 } |
| 97 |
| 98 NSString* ExtractRequestGroupIDFromRequest(NSURLRequest* request, |
| 99 NSString* application_scheme) { |
| 100 NSString* user_agent = |
| 101 [[request allHTTPHeaderFields] objectForKey:@"User-Agent"]; |
| 102 NSString* request_group_id = ExtractRequestGroupIDFromUserAgent(user_agent); |
| 103 if (request_group_id) |
| 104 return request_group_id; |
| 105 if (application_scheme && |
| 106 [[request.mainDocumentURL scheme] |
| 107 caseInsensitiveCompare:application_scheme] == NSOrderedSame) { |
| 108 return ExtractRequestGroupIDFromURL(request.mainDocumentURL); |
| 109 } |
| 110 return nil; |
| 111 } |
| 112 |
| 113 } // namespace web |
| OLD | NEW |