| Index: ios/web/net/request_group_util.mm
|
| diff --git a/ios/web/net/request_group_util.mm b/ios/web/net/request_group_util.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..9a41cef393270b0125dfc8b13b91225b91b4d4fa
|
| --- /dev/null
|
| +++ b/ios/web/net/request_group_util.mm
|
| @@ -0,0 +1,113 @@
|
| +// 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/web/net/request_group_util.h"
|
| +
|
| +#include <Foundation/Foundation.h>
|
| +
|
| +#include "base/base64.h"
|
| +#include "base/logging.h"
|
| +#include "base/rand_util.h"
|
| +#include "base/strings/sys_string_conversions.h"
|
| +#import "net/base/mac/url_conversions.h"
|
| +#include "url/gurl.h"
|
| +
|
| +namespace {
|
| +// Minimum length for a request group ID. A shorter string is considered as an
|
| +// invalid ID.
|
| +const int kMinimumIDLength = 5;
|
| +}
|
| +
|
| +namespace web {
|
| +
|
| +// Generates a request-group ID used to correlate web requests with the embedder
|
| +// that triggered it. It is important that the return value should not be unique
|
| +// for different users. See crbug/355613 for context.
|
| +NSString* GenerateNewRequestGroupID() {
|
| + const unsigned int kGroupSize = 1000;
|
| + static unsigned long count = 0;
|
| + static unsigned int offset = base::RandInt(0, kGroupSize - 1);
|
| +
|
| + unsigned long current = count++;
|
| + if (current < kGroupSize)
|
| + current = (current + offset) % kGroupSize;
|
| +
|
| + // The returned string must have a minimum of kMinimumIDLength characters, and
|
| + // no spaces.
|
| + // TODO(blundell): Develop a long-term solution to this problem.
|
| + // crbug.com/329243
|
| + return [NSString stringWithFormat:@"%06lu", current];
|
| +}
|
| +
|
| +NSString* ExtractRequestGroupIDFromUserAgent(NSString* user_agent) {
|
| + if (![user_agent length])
|
| + return nil;
|
| +
|
| + // The request_group_id is wrapped by parenthesis in the last space-delimited
|
| + // fragment.
|
| + NSString* fragment =
|
| + [[user_agent componentsSeparatedByString:@" "] lastObject];
|
| + NSString* request_group_id =
|
| + [fragment hasPrefix:@"("] && [fragment hasSuffix:@")"]
|
| + ? [fragment substringWithRange:NSMakeRange(1, [fragment length] - 2)]
|
| + : nil;
|
| + // GTLService constructs user agents that end with "(gzip)". To avoid these
|
| + // getting treated as having the request_group_id "gzip", short-circuit out if
|
| + // the request_group_id is not long enough to be a valid request_group_id (all
|
| + // valid request_group_id are at least kMinimumIDLength characters long).
|
| + // TODO(blundell): Develop a long-term solution to this problem.
|
| + // crbug.com/329243
|
| + if ([request_group_id length] < kMinimumIDLength)
|
| + return nil;
|
| + return request_group_id;
|
| +}
|
| +
|
| +NSString* AddRequestGroupIDToUserAgent(NSString* base_user_agent,
|
| + NSString* request_group_id) {
|
| + // TODO(blundell): Develop a long-term solution to this problem.
|
| + // crbug.com/329243
|
| + DCHECK([request_group_id length] >= kMinimumIDLength);
|
| + return
|
| + [NSString stringWithFormat:@"%@ (%@)", base_user_agent, request_group_id];
|
| +}
|
| +
|
| +NSString* ExtractRequestGroupIDFromURL(NSURL* url) {
|
| + GURL gurl = net::GURLWithNSURL(url);
|
| + if (!gurl.has_username())
|
| + return nil;
|
| +
|
| + std::string request_group_id_as_string;
|
| + if (base::Base64Decode(gurl.username(), &request_group_id_as_string))
|
| + return base::SysUTF8ToNSString(request_group_id_as_string);
|
| +
|
| + return nil;
|
| +}
|
| +
|
| +NSURL* AddRequestGroupIDToURL(NSURL* base_url, NSString* request_group_id) {
|
| + GURL url = net::GURLWithNSURL(base_url);
|
| + std::string base64RequestGroupID;
|
| + base::Base64Encode(base::SysNSStringToUTF8(request_group_id),
|
| + &base64RequestGroupID);
|
| + GURL::Replacements replacements;
|
| + replacements.SetUsernameStr(base64RequestGroupID);
|
| + url = url.ReplaceComponents(replacements);
|
| + return net::NSURLWithGURL(url);
|
| +}
|
| +
|
| +NSString* ExtractRequestGroupIDFromRequest(NSURLRequest* request,
|
| + NSString* application_scheme) {
|
| + NSString* user_agent =
|
| + [[request allHTTPHeaderFields] objectForKey:@"User-Agent"];
|
| + NSString* request_group_id = ExtractRequestGroupIDFromUserAgent(user_agent);
|
| + if (request_group_id)
|
| + return request_group_id;
|
| + if (application_scheme &&
|
| + [[request.mainDocumentURL scheme]
|
| + caseInsensitiveCompare:application_scheme] == NSOrderedSame) {
|
| + return ExtractRequestGroupIDFromURL(request.mainDocumentURL);
|
| + }
|
| + return nil;
|
| +}
|
| +
|
| +} // namespace web
|
|
|