Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/renderer/page_load_histograms.h" | 5 #include "chrome/renderer/page_load_histograms.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/metrics/field_trial.h" | 11 #include "base/metrics/field_trial.h" |
| 12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 13 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
| 14 #include "base/strings/string_split.h" | |
| 14 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
| 15 #include "base/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
| 16 #include "base/strings/utf_string_conversions.h" | 17 #include "base/strings/utf_string_conversions.h" |
| 17 #include "base/time/time.h" | 18 #include "base/time/time.h" |
| 18 #include "chrome/common/chrome_switches.h" | 19 #include "chrome/common/chrome_switches.h" |
| 19 #include "chrome/renderer/chrome_content_renderer_client.h" | 20 #include "chrome/renderer/chrome_content_renderer_client.h" |
| 20 #include "content/public/common/content_constants.h" | 21 #include "content/public/common/content_constants.h" |
| 21 #include "content/public/renderer/document_state.h" | 22 #include "content/public/renderer/document_state.h" |
| 22 #include "content/public/renderer/render_thread.h" | 23 #include "content/public/renderer/render_thread.h" |
| 23 #include "content/public/renderer/render_view.h" | 24 #include "content/public/renderer/render_view.h" |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 166 return static_cast<URLPattern::SchemeMasks>(0); | 167 return static_cast<URLPattern::SchemeMasks>(0); |
| 167 } | 168 } |
| 168 | 169 |
| 169 // Returns true if the data reduction proxy was used. Note, this function will | 170 // Returns true if the data reduction proxy was used. Note, this function will |
| 170 // produce a false positive if a page is fetched using SPDY and using a proxy, | 171 // produce a false positive if a page is fetched using SPDY and using a proxy, |
| 171 // and |kDatReductionProxyViaValue| is added to the Via header. | 172 // and |kDatReductionProxyViaValue| is added to the Via header. |
| 172 // TODO(bengr): Plumb the hostname of the proxy from |HttpNetworkTransaction| | 173 // TODO(bengr): Plumb the hostname of the proxy from |HttpNetworkTransaction| |
| 173 // and check if it matches |SPDY_PROXY_AUTH_ORIGIN|. | 174 // and check if it matches |SPDY_PROXY_AUTH_ORIGIN|. |
| 174 bool DataReductionProxyWasUsed(WebFrame* frame) { | 175 bool DataReductionProxyWasUsed(WebFrame* frame) { |
| 175 #if defined(SPDY_PROXY_AUTH_ORIGIN) | 176 #if defined(SPDY_PROXY_AUTH_ORIGIN) |
| 177 const char kDatReductionProxyViaValue[] = "1.1 Chrome Compression Proxy"; | |
| 178 return ViaHeaderContains(frame, kDatReductionProxyViaValue); | |
| 179 #endif | |
| 180 return false; | |
| 181 } | |
| 182 | |
| 183 // Helper function to check for string in 'via' header. This is used only for | |
| 184 // requests fetched via the proxy. | |
| 185 bool ViaHeaderContains(WebFrame* frame, const std::string& via_value) { | |
| 176 const char kViaHeaderName[] = "Via"; | 186 const char kViaHeaderName[] = "Via"; |
| 177 const char kDatReductionProxyViaValue[] = "1.1 Chrome Compression Proxy"; | |
| 178 | 187 |
| 179 DocumentState* document_state = | 188 DocumentState* document_state = |
| 180 DocumentState::FromDataSource(frame->dataSource()); | 189 DocumentState::FromDataSource(frame->dataSource()); |
| 181 if (!document_state->was_fetched_via_proxy()) | 190 if (!document_state->was_fetched_via_proxy()) |
| 182 return false; | 191 return false; |
| 183 | 192 |
| 184 std::string via_header(base::UTF16ToUTF8( | 193 std::vector<std::string> via_header_values; |
| 185 frame->dataSource()->response().httpHeaderField(kViaHeaderName))); | 194 // Multiple via headers have already been coalesced and hence each value |
| 186 return via_header.find(kDatReductionProxyViaValue) != std::string::npos; | 195 // seperated by ',' correspond to a proxy. Value added by proxy is not |
|
bengr
2014/01/09 19:39:45
seperated by ',' correspond --> that is separated
ksimbili
2014/01/09 20:16:21
Done.
| |
| 187 #endif | 196 // expected to contain any ','. |
| 197 base::SplitString(base::UTF16ToUTF8( | |
| 198 frame->dataSource()->response().httpHeaderField(kViaHeaderName)), | |
| 199 ',', &via_header_values); | |
| 200 for (unsigned int i = 0; i < via_header_values.size(); ++i) { | |
| 201 if (via_header_values[i].find(via_value) != std::string::npos) | |
|
bengr
2014/01/09 19:39:45
I think you should test for equality here.
I.e.,
ksimbili
2014/01/09 20:16:21
Done.
| |
| 202 return true; | |
| 203 } | |
| 188 return false; | 204 return false; |
| 189 } | 205 } |
| 190 | 206 |
| 191 // Returns true if the provided URL is a referrer string that came from | 207 // Returns true if the provided URL is a referrer string that came from |
| 192 // a Google Web Search results page. This is a little non-deterministic | 208 // a Google Web Search results page. This is a little non-deterministic |
| 193 // because desktop and mobile websearch differ and sometimes just provide | 209 // because desktop and mobile websearch differ and sometimes just provide |
| 194 // http://www.google.com/ as the referrer. In the case of /url we can be sure | 210 // http://www.google.com/ as the referrer. In the case of /url we can be sure |
| 195 // that it came from websearch but we will be generous and allow for cases | 211 // that it came from websearch but we will be generous and allow for cases |
| 196 // where a non-Google URL was provided a bare Google URL as a referrer. | 212 // where a non-Google URL was provided a bare Google URL as a referrer. |
| 197 // The domain validation matches the code used by the prerenderer for similar | 213 // The domain validation matches the code used by the prerenderer for similar |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 222 return kNoExperiment; | 238 return kNoExperiment; |
| 223 | 239 |
| 224 int experiment_id; | 240 int experiment_id; |
| 225 if (!base::StringToInt(value, &experiment_id)) | 241 if (!base::StringToInt(value, &experiment_id)) |
| 226 return kNoExperiment; | 242 return kNoExperiment; |
| 227 if (0 < experiment_id && experiment_id <= kMaxExperimentID) | 243 if (0 < experiment_id && experiment_id <= kMaxExperimentID) |
| 228 return experiment_id; | 244 return experiment_id; |
| 229 return kNoExperiment; | 245 return kNoExperiment; |
| 230 } | 246 } |
| 231 | 247 |
| 232 // Appends "cerivrj_*" and "gcjeid" query parameters from preview_url to url. | |
| 233 // Returns true if "cerivrj_*" query is found. | |
| 234 // This will be used only for search results URLs. | |
| 235 bool AppendPreviewQueryFromURL(const GURL& preview_url, GURL* url) { | |
| 236 bool preview_query_found = false; | |
| 237 for (net::QueryIterator it(preview_url); !it.IsAtEnd(); it.Advance()) { | |
| 238 const std::string param_name = it.GetKey(); | |
| 239 bool is_preview = StartsWithASCII(param_name, "cerivrj_", true); | |
| 240 if (url && (is_preview || param_name == "gcjeid")) | |
| 241 net::AppendQueryParameter(*url, param_name, it.GetValue()); | |
| 242 preview_query_found = preview_query_found || is_preview; | |
| 243 } | |
| 244 return preview_query_found; | |
| 245 } | |
| 246 | |
| 247 // Returns true if the provided referrer URL is the preview URL of the current | |
| 248 // URL. Preview URL differs from original only with "cerivrj_*", "gcjeid" query | |
| 249 // parameters. | |
| 250 bool IsReferrerPreviewOfURL(const GURL& url, | |
| 251 const base::string16& referrer_str) { | |
| 252 GURL referrer(referrer_str); | |
| 253 if (referrer.is_valid()) { | |
| 254 GURL generated_preview_url(url); | |
| 255 // Now try to copy "cerivrj_*" and "gcjeid" paramters to url and check if | |
| 256 // they exactly match. | |
| 257 if (AppendPreviewQueryFromURL(referrer, &generated_preview_url)) | |
| 258 return generated_preview_url == referrer; | |
| 259 } | |
| 260 return false; | |
| 261 } | |
| 262 | |
| 263 // Returns preview state by looking at url and referer url. | 248 // Returns preview state by looking at url and referer url. |
| 264 void GetPreviewState(const GURL& url, | 249 void GetPreviewState(WebFrame* frame, |
| 265 const base::string16& referrer, | |
| 266 bool came_from_websearch, | 250 bool came_from_websearch, |
| 267 bool data_reduction_proxy_was_used, | 251 bool data_reduction_proxy_was_used, |
| 268 GwsPreviewState* preview_state, | 252 GwsPreviewState* preview_state, |
| 269 int* preview_experiment_id) { | 253 int* preview_experiment_id) { |
| 270 // Conditions for GWS preview are, | 254 // Conditions for GWS preview are, |
| 271 // 1. Data reduction proxy was used. | 255 // 1. Data reduction proxy was used. |
| 272 // 2. URL is loaded from web search. | 256 // 2. URL is loaded from web search. |
| 273 // If the URL contains "cerivrj_*' query parameter record under | 257 // Based on via header PREVIEW/PREVIEW_WAS_SHOWN/PREVIEW_NOT_USED is |
| 274 // "Preview". | 258 // determined. |
| 275 if (data_reduction_proxy_was_used) { | 259 if (data_reduction_proxy_was_used) { |
| 276 if (came_from_websearch) { | 260 if (came_from_websearch) { |
| 277 *preview_state = | 261 *preview_state = |
| 278 AppendPreviewQueryFromURL(url, NULL) ? PREVIEW : PREVIEW_NOT_USED; | 262 ViaHeaderContains(frame, "1.1 Google Promise Preview") ? PREVIEW : |
| 279 } else if (IsReferrerPreviewOfURL(url, referrer)) { | 263 PREVIEW_NOT_USED; |
| 264 } else if (ViaHeaderContains(frame, "1.1 Google Promise Original")) { | |
| 280 *preview_state = PREVIEW_WAS_SHOWN; | 265 *preview_state = PREVIEW_WAS_SHOWN; |
| 281 *preview_experiment_id = GetQueryStringBasedExperiment(GURL(referrer)); | 266 *preview_experiment_id = GetQueryStringBasedExperiment( |
| 267 GURL(frame->document().referrer())); | |
| 282 } | 268 } |
| 283 } | 269 } |
| 284 } | 270 } |
| 285 | 271 |
| 286 void DumpPerformanceTiming(const WebPerformance& performance, | 272 void DumpPerformanceTiming(const WebPerformance& performance, |
| 287 DocumentState* document_state, | 273 DocumentState* document_state, |
| 288 bool data_reduction_proxy_was_used, | 274 bool data_reduction_proxy_was_used, |
| 289 bool came_from_websearch, | 275 bool came_from_websearch, |
| 290 int websearch_chrome_joint_experiment_id, | 276 int websearch_chrome_joint_experiment_id, |
| 291 GwsPreviewState preview_state, | 277 GwsPreviewState preview_state, |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 553 IsFromGoogleSearchResult(frame->document().url(), | 539 IsFromGoogleSearchResult(frame->document().url(), |
| 554 GURL(frame->document().referrer())); | 540 GURL(frame->document().referrer())); |
| 555 int websearch_chrome_joint_experiment_id = kNoExperiment; | 541 int websearch_chrome_joint_experiment_id = kNoExperiment; |
| 556 if (came_from_websearch) { | 542 if (came_from_websearch) { |
| 557 websearch_chrome_joint_experiment_id = | 543 websearch_chrome_joint_experiment_id = |
| 558 GetQueryStringBasedExperiment(GURL(frame->document().referrer())); | 544 GetQueryStringBasedExperiment(GURL(frame->document().referrer())); |
| 559 } | 545 } |
| 560 | 546 |
| 561 GwsPreviewState preview_state = PREVIEW_NONE; | 547 GwsPreviewState preview_state = PREVIEW_NONE; |
| 562 int preview_experiment_id = websearch_chrome_joint_experiment_id; | 548 int preview_experiment_id = websearch_chrome_joint_experiment_id; |
| 563 GetPreviewState(frame->document().url(), frame->document().referrer(), | 549 GetPreviewState(frame, came_from_websearch, data_reduction_proxy_was_used, |
| 564 came_from_websearch, data_reduction_proxy_was_used, | |
| 565 &preview_state, &preview_experiment_id); | 550 &preview_state, &preview_experiment_id); |
| 566 | 551 |
| 567 // Times based on the Web Timing metrics. | 552 // Times based on the Web Timing metrics. |
| 568 // http://www.w3.org/TR/navigation-timing/ | 553 // http://www.w3.org/TR/navigation-timing/ |
| 569 // TODO(tonyg, jar): We are in the process of vetting these metrics against | 554 // TODO(tonyg, jar): We are in the process of vetting these metrics against |
| 570 // the existing ones. Once we understand any differences, we will standardize | 555 // the existing ones. Once we understand any differences, we will standardize |
| 571 // on a single set of metrics. | 556 // on a single set of metrics. |
| 572 DumpPerformanceTiming(frame->performance(), document_state, | 557 DumpPerformanceTiming(frame->performance(), document_state, |
| 573 data_reduction_proxy_was_used, | 558 data_reduction_proxy_was_used, |
| 574 came_from_websearch, | 559 came_from_websearch, |
| (...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1047 | 1032 |
| 1048 DCHECK(document_state); | 1033 DCHECK(document_state); |
| 1049 DCHECK(ds); | 1034 DCHECK(ds); |
| 1050 GURL url(ds->request().url()); | 1035 GURL url(ds->request().url()); |
| 1051 Time start = document_state->start_load_time(); | 1036 Time start = document_state->start_load_time(); |
| 1052 Time finish = document_state->finish_load_time(); | 1037 Time finish = document_state->finish_load_time(); |
| 1053 // TODO(mbelshe): should we log more stats? | 1038 // TODO(mbelshe): should we log more stats? |
| 1054 VLOG(1) << "PLT: " << (finish - start).InMilliseconds() << "ms " | 1039 VLOG(1) << "PLT: " << (finish - start).InMilliseconds() << "ms " |
| 1055 << url.spec(); | 1040 << url.spec(); |
| 1056 } | 1041 } |
| OLD | NEW |