1 // Copyright (c) 2011 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 "chrome/browser/prerender/prerender_util.h" 6 7 #include "base/logging.h" 8 #include "base/metrics/sparse_histogram.h" 9 #include "base/strings/string_util.h" 10 #include "content/public/browser/resource_request_info.h" 11 #include "net/http/http_response_headers.h" 12 #include "net/url_request/url_request.h" 13 #include "url/url_canon.h" 14 #include "url/url_parse.h" 15 #include "url/url_util.h" 16 17 namespace prerender { 18 19 bool MaybeGetQueryStringBasedAliasURL( 20 const GURL& url, GURL* alias_url) { 21 DCHECK(alias_url); 22 url_parse::Parsed parsed; 23 url_parse::ParseStandardURL(url.spec().c_str(), url.spec().length(), 24 &parsed); 25 url_parse::Component query = parsed.query; 26 url_parse::Component key, value; 27 while (url_parse::ExtractQueryKeyValue(url.spec().c_str(), &query, &key, 28 &value)) { 29 if (key.len != 3 || strncmp(url.spec().c_str() + key.begin, "url", key.len)) 30 continue; 31 // We found a url= query string component. 32 if (value.len < 1) 33 continue; 34 url_canon::RawCanonOutputW<1024> decoded_url; 35 url_util::DecodeURLEscapeSequences(url.spec().c_str() + value.begin, 36 value.len, &decoded_url); 37 GURL new_url(string16(decoded_url.data(), decoded_url.length())); 38 if (!new_url.is_empty() && new_url.is_valid()) { 39 *alias_url = new_url; 40 return true; 41 } 42 return false; 43 } 44 return false; 45 } 46 47 uint8 GetQueryStringBasedExperiment(const GURL& url) { 48 url_parse::Parsed parsed; 49 url_parse::ParseStandardURL(url.spec().c_str(), url.spec().length(), 50 &parsed); 51 url_parse::Component query = parsed.query; 52 url_parse::Component key, value; 53 while (url_parse::ExtractQueryKeyValue(url.spec().c_str(), &query, &key, 54 &value)) { 55 if (key.len != 3 || strncmp(url.spec().c_str() + key.begin, "lpe", key.len)) 56 continue; 57 58 // We found a lpe= query string component. 59 if (value.len != 1) 60 continue; 61 uint8 exp = *(url.spec().c_str() + value.begin) - '0'; 62 if (exp < 1 || exp > 9) 63 continue; 64 return exp; 65 } 66 return kNoExperiment; 67 } 68 69 bool IsGoogleDomain(const GURL& url) { 70 return StartsWithASCII(url.host(), std::string("www.google."), true); 71 } 72 73 bool IsGoogleSearchResultURL(const GURL& url) { 74 if (!IsGoogleDomain(url)) 75 return false; 76 return (url.path().empty() || 77 StartsWithASCII(url.path(), std::string("/search"), true) || 78 (url.path() == "/") || 79 StartsWithASCII(url.path(), std::string("/webhp"), true)); 80 } 81 82 bool IsWebURL(const GURL& url) { 83 return url.SchemeIs("http") || url.SchemeIs("https"); 84 } 85 86 bool IsNoSwapInExperiment(uint8 experiment_id) { 87 // Currently, experiments 5 and 6 fall in this category. 88 return experiment_id == 5 || experiment_id == 6; 89 } 90 91 bool IsControlGroupExperiment(uint8 experiment_id) { 92 // Currently, experiments 7 and 8 fall in this category. 93 return experiment_id == 7 || experiment_id == 8; 94 } 95 96 void URLRequestResponseStarted(net::URLRequest* request) { 97 static const char* kModPagespeedHeader = "X-Mod-Pagespeed"; 98 static const char* kModPagespeedHistogram = "Prerender.ModPagespeedHeader"; 99 const content::ResourceRequestInfo* info = 100 content::ResourceRequestInfo::ForRequest(request); 101 // Gather histogram information about the X-Mod-Pagespeed header. 102 if (info->GetResourceType() == ResourceType::MAIN_FRAME && 103 IsWebURL(request->url())) { 104 UMA_HISTOGRAM_SPARSE_SLOWLY(kModPagespeedHistogram, 0); 105 if (request->response_headers() && 106 request->response_headers()->HasHeader(kModPagespeedHeader)) { 107 UMA_HISTOGRAM_SPARSE_SLOWLY(kModPagespeedHistogram, 1); 108 109 // Attempt to parse the version number, and encode it in buckets 110 // 2 through 99. 0 and 1 are used to store all pageviews and 111 // # pageviews with the MPS header (see above). 112 void* iter = NULL; 113 std::string mps_version; 114 if (request->response_headers()->EnumerateHeader( 115 &iter, kModPagespeedHeader, &mps_version) && 116 !mps_version.empty()) { 117 // Mod Pagespeed versions are of the form a.b.c.d-e 118 int a, b, c, d, e; 119 int num_parsed = sscanf(mps_version.c_str(), "%d.%d.%d.%d-%d", 120 &a, &b, &c, &d, &e); 121 if (num_parsed == 5) { 122 int output = 2; 123 if (c > 10) 124 output += 2 * (c - 10); 125 if (d > 1) 126 output++; 127 if (output < 2 || output >= 99) 128 output = 99; 129 UMA_HISTOGRAM_SPARSE_SLOWLY(kModPagespeedHistogram, output); 130 } 131 } 132 } 133 } 134 } 135 136 } // namespace prerender 137