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 |