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. | |
|
Alexei Svitkine (slow)
2014/01/09 16:39:29
Expand comment to mention that this is only done f
ksimbili
2014/01/09 18:54:50
Done.
| |
| 184 bool ViaHeaderContains(WebFrame* frame, const std::string& via_value) { | |
| 176 const char kViaHeaderName[] = "Via"; | 185 const char kViaHeaderName[] = "Via"; |
| 177 const char kDatReductionProxyViaValue[] = "1.1 Chrome Compression Proxy"; | |
| 178 | 186 |
| 179 DocumentState* document_state = | 187 DocumentState* document_state = |
| 180 DocumentState::FromDataSource(frame->dataSource()); | 188 DocumentState::FromDataSource(frame->dataSource()); |
| 181 if (!document_state->was_fetched_via_proxy()) | 189 if (!document_state->was_fetched_via_proxy()) |
| 182 return false; | 190 return false; |
| 183 | 191 |
| 184 std::string via_header(base::UTF16ToUTF8( | 192 std::vector<std::string> via_header_values; |
| 185 frame->dataSource()->response().httpHeaderField(kViaHeaderName))); | 193 base::SplitString(base::UTF16ToUTF8( |
|
nikhilmadan
2014/01/08 22:25:29
Add a comment explaining why we do this
ksimbili
2014/01/09 18:54:50
Done.
| |
| 186 return via_header.find(kDatReductionProxyViaValue) != std::string::npos; | 194 frame->dataSource()->response().httpHeaderField(kViaHeaderName)), |
| 187 #endif | 195 ',', &via_header_values); |
|
bengr
2014/01/09 17:32:46
This will work most of the time, but please follow
ksimbili
2014/01/09 18:54:50
Like I said, we don't have HttpResponseHeaders her
| |
| 196 for (unsigned int i = 0; i < via_header_values.size(); ++i) { | |
| 197 if (via_header_values[i].find(via_value) != std::string::npos) | |
|
Alexei Svitkine (slow)
2014/01/09 16:39:29
Will this find any part separate by commas that co
bengr
2014/01/09 17:32:46
Via values shouldn't have commas in them. Why not
ksimbili
2014/01/09 18:54:50
We don't have network stack HTTPResponseHeaders he
ksimbili
2014/01/09 18:54:50
we are not using find() directly to make sure that
Alexei Svitkine (slow)
2014/01/09 19:01:42
If |via_value| never contains a comma (which is th
ksimbili
2014/01/09 19:13:49
No. Sorry for the confusion.
There can be multipl
Alexei Svitkine (slow)
2014/01/09 19:34:38
Ok, thanks for explaining the format of that heade
ksimbili
2014/01/09 20:16:21
Sorry, corrected the code. I should have checked f
| |
| 198 return true; | |
| 199 } | |
| 188 return false; | 200 return false; |
| 189 } | 201 } |
| 190 | 202 |
| 191 // Returns true if the provided URL is a referrer string that came from | 203 // 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 | 204 // a Google Web Search results page. This is a little non-deterministic |
| 193 // because desktop and mobile websearch differ and sometimes just provide | 205 // 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 | 206 // 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 | 207 // 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. | 208 // 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 | 209 // The domain validation matches the code used by the prerenderer for similar |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 222 return kNoExperiment; | 234 return kNoExperiment; |
| 223 | 235 |
| 224 int experiment_id; | 236 int experiment_id; |
| 225 if (!base::StringToInt(value, &experiment_id)) | 237 if (!base::StringToInt(value, &experiment_id)) |
| 226 return kNoExperiment; | 238 return kNoExperiment; |
| 227 if (0 < experiment_id && experiment_id <= kMaxExperimentID) | 239 if (0 < experiment_id && experiment_id <= kMaxExperimentID) |
| 228 return experiment_id; | 240 return experiment_id; |
| 229 return kNoExperiment; | 241 return kNoExperiment; |
| 230 } | 242 } |
| 231 | 243 |
| 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. | 244 // Returns preview state by looking at url and referer url. |
| 264 void GetPreviewState(const GURL& url, | 245 void GetPreviewState(WebFrame* frame, |
| 265 const base::string16& referrer, | |
| 266 bool came_from_websearch, | 246 bool came_from_websearch, |
| 267 bool data_reduction_proxy_was_used, | 247 bool data_reduction_proxy_was_used, |
| 268 GwsPreviewState* preview_state, | 248 GwsPreviewState* preview_state, |
| 269 int* preview_experiment_id) { | 249 int* preview_experiment_id) { |
| 270 // Conditions for GWS preview are, | 250 // Conditions for GWS preview are, |
| 271 // 1. Data reduction proxy was used. | 251 // 1. Data reduction proxy was used. |
| 272 // 2. URL is loaded from web search. | 252 // 2. URL is loaded from web search. |
| 273 // If the URL contains "cerivrj_*' query parameter record under | 253 // Based on via header PREVIEW/PREVIEW_WAS_SHOWN/PREVIEW_NOT_USED is |
| 274 // "Preview". | 254 // determined. |
| 275 if (data_reduction_proxy_was_used) { | 255 if (data_reduction_proxy_was_used) { |
| 276 if (came_from_websearch) { | 256 if (came_from_websearch) { |
| 277 *preview_state = | 257 *preview_state = |
| 278 AppendPreviewQueryFromURL(url, NULL) ? PREVIEW : PREVIEW_NOT_USED; | 258 ViaHeaderContains(frame, "Google Promise Preview") ? PREVIEW : |
|
Alexei Svitkine (slow)
2014/01/09 16:39:29
Nit: Incorrect indent.
ksimbili
2014/01/09 18:54:50
Done.
| |
| 279 } else if (IsReferrerPreviewOfURL(url, referrer)) { | 259 PREVIEW_NOT_USED; |
| 260 } else if (ViaHeaderContains(frame, "Google Promise Original")) { | |
| 280 *preview_state = PREVIEW_WAS_SHOWN; | 261 *preview_state = PREVIEW_WAS_SHOWN; |
| 281 *preview_experiment_id = GetQueryStringBasedExperiment(GURL(referrer)); | 262 *preview_experiment_id = GetQueryStringBasedExperiment( |
| 263 GURL(frame->document().referrer())); | |
| 282 } | 264 } |
| 283 } | 265 } |
| 284 } | 266 } |
| 285 | 267 |
| 286 void DumpPerformanceTiming(const WebPerformance& performance, | 268 void DumpPerformanceTiming(const WebPerformance& performance, |
| 287 DocumentState* document_state, | 269 DocumentState* document_state, |
| 288 bool data_reduction_proxy_was_used, | 270 bool data_reduction_proxy_was_used, |
| 289 bool came_from_websearch, | 271 bool came_from_websearch, |
| 290 int websearch_chrome_joint_experiment_id, | 272 int websearch_chrome_joint_experiment_id, |
| 291 GwsPreviewState preview_state, | 273 GwsPreviewState preview_state, |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 553 IsFromGoogleSearchResult(frame->document().url(), | 535 IsFromGoogleSearchResult(frame->document().url(), |
| 554 GURL(frame->document().referrer())); | 536 GURL(frame->document().referrer())); |
| 555 int websearch_chrome_joint_experiment_id = kNoExperiment; | 537 int websearch_chrome_joint_experiment_id = kNoExperiment; |
| 556 if (came_from_websearch) { | 538 if (came_from_websearch) { |
| 557 websearch_chrome_joint_experiment_id = | 539 websearch_chrome_joint_experiment_id = |
| 558 GetQueryStringBasedExperiment(GURL(frame->document().referrer())); | 540 GetQueryStringBasedExperiment(GURL(frame->document().referrer())); |
| 559 } | 541 } |
| 560 | 542 |
| 561 GwsPreviewState preview_state = PREVIEW_NONE; | 543 GwsPreviewState preview_state = PREVIEW_NONE; |
| 562 int preview_experiment_id = websearch_chrome_joint_experiment_id; | 544 int preview_experiment_id = websearch_chrome_joint_experiment_id; |
| 563 GetPreviewState(frame->document().url(), frame->document().referrer(), | 545 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); | 546 &preview_state, &preview_experiment_id); |
| 566 | 547 |
| 567 // Times based on the Web Timing metrics. | 548 // Times based on the Web Timing metrics. |
| 568 // http://www.w3.org/TR/navigation-timing/ | 549 // http://www.w3.org/TR/navigation-timing/ |
| 569 // TODO(tonyg, jar): We are in the process of vetting these metrics against | 550 // 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 | 551 // the existing ones. Once we understand any differences, we will standardize |
| 571 // on a single set of metrics. | 552 // on a single set of metrics. |
| 572 DumpPerformanceTiming(frame->performance(), document_state, | 553 DumpPerformanceTiming(frame->performance(), document_state, |
| 573 data_reduction_proxy_was_used, | 554 data_reduction_proxy_was_used, |
| 574 came_from_websearch, | 555 came_from_websearch, |
| (...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1047 | 1028 |
| 1048 DCHECK(document_state); | 1029 DCHECK(document_state); |
| 1049 DCHECK(ds); | 1030 DCHECK(ds); |
| 1050 GURL url(ds->request().url()); | 1031 GURL url(ds->request().url()); |
| 1051 Time start = document_state->start_load_time(); | 1032 Time start = document_state->start_load_time(); |
| 1052 Time finish = document_state->finish_load_time(); | 1033 Time finish = document_state->finish_load_time(); |
| 1053 // TODO(mbelshe): should we log more stats? | 1034 // TODO(mbelshe): should we log more stats? |
| 1054 VLOG(1) << "PLT: " << (finish - start).InMilliseconds() << "ms " | 1035 VLOG(1) << "PLT: " << (finish - start).InMilliseconds() << "ms " |
| 1055 << url.spec(); | 1036 << url.spec(); |
| 1056 } | 1037 } |
| OLD | NEW |