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.
5 #include "chrome/browser/prerender/prerender_util.h"
7 #include "base/logging.h"
8 #include "base/metrics/histogram.h"
9 #include "base/metrics/sparse_histogram.h"
10 #include "base/strings/string_util.h"
11 #include "content/public/browser/resource_request_info.h"
12 #include "content/public/common/resource_type.h"
13 #include "net/http/http_response_headers.h"
14 #include "net/url_request/url_request.h"
15 #include "url/url_canon.h"
16 #include "url/url_parse.h"
17 #include "url/url_util.h"
19 using content::ResourceType
;
25 enum PrerenderSchemeCancelReason
{
26 PRERENDER_SCHEME_CANCEL_REASON_EXTERNAL_PROTOCOL
,
27 PRERENDER_SCHEME_CANCEL_REASON_DATA
,
28 PRERENDER_SCHEME_CANCEL_REASON_BLOB
,
29 PRERENDER_SCHEME_CANCEL_REASON_FILE
,
30 PRERENDER_SCHEME_CANCEL_REASON_FILESYSTEM
,
31 PRERENDER_SCHEME_CANCEL_REASON_WEBSOCKET
,
32 PRERENDER_SCHEME_CANCEL_REASON_FTP
,
33 PRERENDER_SCHEME_CANCEL_REASON_CHROME
,
34 PRERENDER_SCHEME_CANCEL_REASON_CHROME_EXTENSION
,
35 PRERENDER_SCHEME_CANCEL_REASON_ABOUT
,
36 PRERENDER_SCHEME_CANCEL_REASON_UNKNOWN
,
37 PRERENDER_SCHEME_CANCEL_REASON_MAX
,
40 void ReportPrerenderSchemeCancelReason(PrerenderSchemeCancelReason reason
) {
41 UMA_HISTOGRAM_ENUMERATION(
42 "Prerender.SchemeCancelReason", reason
,
43 PRERENDER_SCHEME_CANCEL_REASON_MAX
);
48 const char kChromeNavigateExtraDataKey
[] = "chrome_navigate";
50 bool MaybeGetQueryStringBasedAliasURL(
51 const GURL
& url
, GURL
* alias_url
) {
54 url::ParseStandardURL(url
.spec().c_str(), url
.spec().length(), &parsed
);
55 url::Component query
= parsed
.query
;
56 url::Component key
, value
;
57 while (url::ExtractQueryKeyValue(url
.spec().c_str(), &query
, &key
, &value
)) {
58 if (key
.len
!= 3 || strncmp(url
.spec().c_str() + key
.begin
, "url", key
.len
))
60 // We found a url= query string component.
63 url::RawCanonOutputW
<1024> decoded_url
;
64 url::DecodeURLEscapeSequences(url
.spec().c_str() + value
.begin
, value
.len
,
66 GURL
new_url(base::string16(decoded_url
.data(), decoded_url
.length()));
67 if (!new_url
.is_empty() && new_url
.is_valid()) {
76 uint8
GetQueryStringBasedExperiment(const GURL
& url
) {
78 url::ParseStandardURL(url
.spec().c_str(), url
.spec().length(), &parsed
);
79 url::Component query
= parsed
.query
;
80 url::Component key
, value
;
81 while (url::ExtractQueryKeyValue(url
.spec().c_str(), &query
, &key
, &value
)) {
82 if (key
.len
!= 3 || strncmp(url
.spec().c_str() + key
.begin
, "lpe", key
.len
))
85 // We found a lpe= query string component.
88 uint8 exp
= *(url
.spec().c_str() + value
.begin
) - '0';
89 if (exp
< 1 || exp
> 9)
96 bool IsGoogleDomain(const GURL
& url
) {
97 return StartsWithASCII(url
.host(), std::string("www.google."), true);
100 bool IsGoogleSearchResultURL(const GURL
& url
) {
101 if (!IsGoogleDomain(url
))
103 return (url
.path().empty() ||
104 StartsWithASCII(url
.path(), std::string("/search"), true) ||
105 (url
.path() == "/") ||
106 StartsWithASCII(url
.path(), std::string("/webhp"), true));
109 bool IsNoSwapInExperiment(uint8 experiment_id
) {
110 // Currently, experiments 5 and 6 fall in this category.
111 return experiment_id
== 5 || experiment_id
== 6;
114 bool IsControlGroupExperiment(uint8 experiment_id
) {
115 // Currently, experiments 7 and 8 fall in this category.
116 return experiment_id
== 7 || experiment_id
== 8;
119 void ReportPrerenderExternalURL() {
120 ReportPrerenderSchemeCancelReason(
121 PRERENDER_SCHEME_CANCEL_REASON_EXTERNAL_PROTOCOL
);
124 void ReportUnsupportedPrerenderScheme(const GURL
& url
) {
125 if (url
.SchemeIs("data")) {
126 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_DATA
);
127 } else if (url
.SchemeIs("blob")) {
128 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_BLOB
);
129 } else if (url
.SchemeIsFile()) {
130 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_FILE
);
131 } else if (url
.SchemeIsFileSystem()) {
132 ReportPrerenderSchemeCancelReason(
133 PRERENDER_SCHEME_CANCEL_REASON_FILESYSTEM
);
134 } else if (url
.SchemeIs("ws") || url
.SchemeIs("wss")) {
135 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_WEBSOCKET
);
136 } else if (url
.SchemeIs("ftp")) {
137 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_FTP
);
138 } else if (url
.SchemeIs("chrome")) {
139 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_CHROME
);
140 } else if (url
.SchemeIs("chrome-extension")) {
141 ReportPrerenderSchemeCancelReason(
142 PRERENDER_SCHEME_CANCEL_REASON_CHROME_EXTENSION
);
143 } else if (url
.SchemeIs("about")) {
144 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_ABOUT
);
146 ReportPrerenderSchemeCancelReason(PRERENDER_SCHEME_CANCEL_REASON_UNKNOWN
);
150 } // namespace prerender