| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/prerender/prerender_util.h" | 5 #include "chrome/browser/prerender/prerender_util.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
| 9 #include "base/metrics/sparse_histogram.h" | 9 #include "base/metrics/sparse_histogram.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| 11 #include "content/public/browser/resource_request_info.h" | 11 #include "content/public/browser/resource_request_info.h" |
| 12 #include "content/public/common/resource_type.h" | 12 #include "content/public/common/resource_type.h" |
| 13 #include "net/http/http_response_headers.h" | 13 #include "net/http/http_response_headers.h" |
| 14 #include "net/url_request/url_request.h" | 14 #include "net/url_request/url_request.h" |
| 15 #include "url/url_canon.h" | 15 #include "url/url_canon.h" |
| 16 #include "url/url_parse.h" | 16 #include "url/url_parse.h" |
| 17 #include "url/url_util.h" | 17 #include "url/url_util.h" |
| 18 | 18 |
| 19 using content::ResourceType; | 19 using content::ResourceType; |
| 20 | 20 |
| 21 namespace prerender { | 21 namespace prerender { |
| 22 | 22 |
| 23 namespace { | 23 namespace { |
| 24 | 24 |
| 25 const char kModPagespeedHeader[] = "X-Mod-Pagespeed"; | |
| 26 const char kPageSpeedHeader[] = "X-Page-Speed"; | |
| 27 const char kPagespeedServerHistogram[] = | |
| 28 "Prerender.PagespeedHeader.ServerCounts"; | |
| 29 const char kPagespeedVersionHistogram[] = | |
| 30 "Prerender.PagespeedHeader.VersionCounts"; | |
| 31 | |
| 32 enum PagespeedHeaderServerType { | |
| 33 PAGESPEED_TOTAL_RESPONSES = 0, | |
| 34 PAGESPEED_MOD_PAGESPEED_SERVER = 1, | |
| 35 PAGESPEED_NGX_PAGESPEED_SERVER = 2, | |
| 36 PAGESPEED_PAGESPEED_SERVICE_SERVER = 3, | |
| 37 PAGESPEED_UNKNOWN_SERVER = 4, | |
| 38 PAGESPEED_SERVER_MAXIMUM = 5 | |
| 39 }; | |
| 40 | |
| 41 // Private function to parse the PageSpeed version number and encode it in | |
| 42 // buckets 2 through 99: if it is in the format a.b.c.d-e the bucket will be | |
| 43 // 2 + 2 * (max(c, 10) - 10) + (d > 1 ? 1 : 0); if it is not in this format | |
| 44 // we return zero. | |
| 45 int GetXModPagespeedBucketFromVersion(const std::string& version) { | |
| 46 int a, b, c, d, e; | |
| 47 int num_parsed = sscanf(version.c_str(), "%d.%d.%d.%d-%d", | |
| 48 &a, &b, &c, &d, &e); | |
| 49 int output = 0; | |
| 50 if (num_parsed == 5) { | |
| 51 output = 2; | |
| 52 if (c > 10) | |
| 53 output += 2 * (c - 10); | |
| 54 if (d > 1) | |
| 55 output++; | |
| 56 if (output < 2 || output > 99) | |
| 57 output = 0; | |
| 58 } | |
| 59 return output; | |
| 60 } | |
| 61 | |
| 62 // Private function to parse the X-Page-Speed header value and determine | |
| 63 // whether it is in the PageSpeed Service format, namely m_n_dc were m_n is | |
| 64 // a version number and dc is an encoded 2-character value. | |
| 65 bool IsPageSpeedServiceVersionNumber(const std::string& version) { | |
| 66 int a, b; | |
| 67 char c, d, e; // e is to detect EOL as we check that it /isn't/ converted. | |
| 68 int num_parsed = sscanf(version.c_str(), "%d_%d_%c%c%c", &a, &b, &c, &d, &e); | |
| 69 return (num_parsed == 4); | |
| 70 } | |
| 71 | |
| 72 enum PrerenderSchemeCancelReason { | 25 enum PrerenderSchemeCancelReason { |
| 73 PRERENDER_SCHEME_CANCEL_REASON_EXTERNAL_PROTOCOL, | 26 PRERENDER_SCHEME_CANCEL_REASON_EXTERNAL_PROTOCOL, |
| 74 PRERENDER_SCHEME_CANCEL_REASON_DATA, | 27 PRERENDER_SCHEME_CANCEL_REASON_DATA, |
| 75 PRERENDER_SCHEME_CANCEL_REASON_BLOB, | 28 PRERENDER_SCHEME_CANCEL_REASON_BLOB, |
| 76 PRERENDER_SCHEME_CANCEL_REASON_FILE, | 29 PRERENDER_SCHEME_CANCEL_REASON_FILE, |
| 77 PRERENDER_SCHEME_CANCEL_REASON_FILESYSTEM, | 30 PRERENDER_SCHEME_CANCEL_REASON_FILESYSTEM, |
| 78 PRERENDER_SCHEME_CANCEL_REASON_WEBSOCKET, | 31 PRERENDER_SCHEME_CANCEL_REASON_WEBSOCKET, |
| 79 PRERENDER_SCHEME_CANCEL_REASON_FTP, | 32 PRERENDER_SCHEME_CANCEL_REASON_FTP, |
| 80 PRERENDER_SCHEME_CANCEL_REASON_CHROME, | 33 PRERENDER_SCHEME_CANCEL_REASON_CHROME, |
| 81 PRERENDER_SCHEME_CANCEL_REASON_CHROME_EXTENSION, | 34 PRERENDER_SCHEME_CANCEL_REASON_CHROME_EXTENSION, |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 bool IsNoSwapInExperiment(uint8 experiment_id) { | 109 bool IsNoSwapInExperiment(uint8 experiment_id) { |
| 157 // Currently, experiments 5 and 6 fall in this category. | 110 // Currently, experiments 5 and 6 fall in this category. |
| 158 return experiment_id == 5 || experiment_id == 6; | 111 return experiment_id == 5 || experiment_id == 6; |
| 159 } | 112 } |
| 160 | 113 |
| 161 bool IsControlGroupExperiment(uint8 experiment_id) { | 114 bool IsControlGroupExperiment(uint8 experiment_id) { |
| 162 // Currently, experiments 7 and 8 fall in this category. | 115 // Currently, experiments 7 and 8 fall in this category. |
| 163 return experiment_id == 7 || experiment_id == 8; | 116 return experiment_id == 7 || experiment_id == 8; |
| 164 } | 117 } |
| 165 | 118 |
| 166 void GatherPagespeedData(const ResourceType resource_type, | |
| 167 const GURL& request_url, | |
| 168 const net::HttpResponseHeaders* response_headers) { | |
| 169 if (resource_type != content::RESOURCE_TYPE_MAIN_FRAME || | |
| 170 !request_url.SchemeIsHTTPOrHTTPS()) | |
| 171 return; | |
| 172 | |
| 173 // bucket 0 counts every response seen. | |
| 174 UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram, | |
| 175 PAGESPEED_TOTAL_RESPONSES, | |
| 176 PAGESPEED_SERVER_MAXIMUM); | |
| 177 if (!response_headers) | |
| 178 return; | |
| 179 | |
| 180 void* iter = NULL; | |
| 181 std::string name; | |
| 182 std::string value; | |
| 183 while (response_headers->EnumerateHeaderLines(&iter, &name, &value)) { | |
| 184 if (name == kModPagespeedHeader) { | |
| 185 // Bucket 1 counts occurences of the X-Mod-Pagespeed header. | |
| 186 UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram, | |
| 187 PAGESPEED_MOD_PAGESPEED_SERVER, | |
| 188 PAGESPEED_SERVER_MAXIMUM); | |
| 189 if (!value.empty()) { | |
| 190 // If the header value is in the X-Mod-Pagespeed version number format | |
| 191 // then increment the appropriate bucket, otherwise increment bucket 1, | |
| 192 // which is the catch-all "unknown version number" bucket. | |
| 193 int bucket = GetXModPagespeedBucketFromVersion(value); | |
| 194 if (bucket > 0) { | |
| 195 UMA_HISTOGRAM_SPARSE_SLOWLY(kPagespeedVersionHistogram, bucket); | |
| 196 } else { | |
| 197 UMA_HISTOGRAM_SPARSE_SLOWLY(kPagespeedVersionHistogram, 1); | |
| 198 } | |
| 199 } | |
| 200 break; | |
| 201 } else if (name == kPageSpeedHeader) { | |
| 202 // X-Page-Speed header versions are either in the X-Mod-Pagespeed format, | |
| 203 // indicating an nginx installation, or they're in the PageSpeed Service | |
| 204 // format, indicating a PSS installation, or in some other format, | |
| 205 // indicating an unknown installation [possibly IISpeed]. | |
| 206 if (!value.empty()) { | |
| 207 int bucket = GetXModPagespeedBucketFromVersion(value); | |
| 208 if (bucket > 0) { | |
| 209 // Bucket 2 counts occurences of the X-Page-Speed header with a | |
| 210 // value in the X-Mod-Pagespeed version number format. We also | |
| 211 // count these responses in the version histogram. | |
| 212 UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram, | |
| 213 PAGESPEED_NGX_PAGESPEED_SERVER, | |
| 214 PAGESPEED_SERVER_MAXIMUM); | |
| 215 UMA_HISTOGRAM_SPARSE_SLOWLY(kPagespeedVersionHistogram, bucket); | |
| 216 } else if (IsPageSpeedServiceVersionNumber(value)) { | |
| 217 // Bucket 3 counts occurences of the X-Page-Speed header with a | |
| 218 // value in the PageSpeed Service version number format. | |
| 219 UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram, | |
| 220 PAGESPEED_PAGESPEED_SERVICE_SERVER, | |
| 221 PAGESPEED_SERVER_MAXIMUM); | |
| 222 } else { | |
| 223 // Bucket 4 counts occurences of all other values. | |
| 224 UMA_HISTOGRAM_ENUMERATION(kPagespeedServerHistogram, | |
| 225 PAGESPEED_UNKNOWN_SERVER, | |
| 226 PAGESPEED_SERVER_MAXIMUM); | |
| 227 } | |
| 228 } | |
| 229 break; | |
| 230 } | |
| 231 } | |
| 232 } | |
| 233 | |
| 234 void URLRequestResponseStarted(net::URLRequest* request) { | |
| 235 const content::ResourceRequestInfo* info = | |
| 236 content::ResourceRequestInfo::ForRequest(request); | |
| 237 GatherPagespeedData(info->GetResourceType(), | |
| 238 request->url(), | |
| 239 request->response_headers()); | |
| 240 } | |
| 241 | |
| 242 void ReportPrerenderExternalURL() { | 119 void ReportPrerenderExternalURL() { |
| 243 ReportPrerenderSchemeCancelReason( | 120 ReportPrerenderSchemeCancelReason( |
| 244 PRERENDER_SCHEME_CANCEL_REASON_EXTERNAL_PROTOCOL); | 121 PRERENDER_SCHEME_CANCEL_REASON_EXTERNAL_PROTOCOL); |
| 245 } | 122 } |
| 246 | 123 |
| 247 void ReportUnsupportedPrerenderScheme(const GURL& url) { | 124 void ReportUnsupportedPrerenderScheme(const GURL& url) { |
| 248 if (url.SchemeIs("data")) { | 125 if (url.SchemeIs("data")) { |
| 249 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_DATA); | 126 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_DATA); |
| 250 } else if (url.SchemeIs("blob")) { | 127 } else if (url.SchemeIs("blob")) { |
| 251 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_BLOB); | 128 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_BLOB); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 264 ReportPrerenderSchemeCancelReason( | 141 ReportPrerenderSchemeCancelReason( |
| 265 PRERENDER_SCHEME_CANCEL_REASON_CHROME_EXTENSION); | 142 PRERENDER_SCHEME_CANCEL_REASON_CHROME_EXTENSION); |
| 266 } else if (url.SchemeIs("about")) { | 143 } else if (url.SchemeIs("about")) { |
| 267 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_ABOUT); | 144 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_ABOUT); |
| 268 } else { | 145 } else { |
| 269 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_UNKNOWN); | 146 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_UNKNOWN); |
| 270 } | 147 } |
| 271 } | 148 } |
| 272 | 149 |
| 273 } // namespace prerender | 150 } // namespace prerender |
| OLD | NEW |