Fix breakages in https://codereview.chromium.org/1155713003/
[chromium-blink-merge.git] / ios / web / net / request_group_util.mm
blob9a41cef393270b0125dfc8b13b91225b91b4d4fa
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/web/net/request_group_util.h"
7 #include <Foundation/Foundation.h>
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"
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;
22 namespace web {
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);
32   unsigned long current = count++;
33   if (current < kGroupSize)
34     current = (current + offset) % kGroupSize;
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];
43 NSString* ExtractRequestGroupIDFromUserAgent(NSString* user_agent) {
44   if (![user_agent length])
45     return nil;
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;
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];
75 NSString* ExtractRequestGroupIDFromURL(NSURL* url) {
76   GURL gurl = net::GURLWithNSURL(url);
77   if (!gurl.has_username())
78     return nil;
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);
84   return nil;
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);
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;
113 }  // namespace web