Port PrerenderResourceThrottle to work with Network Service.
This throttle is used for Prerendering and NoStatePrefetch. A new URLLoaderThrottle,
PrerenderURLLoaderThrottle, is created as a replacement. It's used for subresources in the renderer
when both the network service is enabled and disabled. In the browser, PrerenderURLLoaderThrottle
is used if the network service is enabled. When network service is disabled,
PrerenderResourceThrottle is still used in the browser until URLLoader is used
(http://crbug.com/740130).
Two behavior change with NoStatePrefetch that were needed:
1) The subresource data is sent to the renderer. This is needed
so that the URLLoaderThrottle gets notifications. The data isn't delivered to Blink but is just
consumed, which maintains the previous intent of not storing increasing renderer memory by having
this data in Blink's caches.
2) The prefetch renderer is kept alive until all fetched subresources complete. Previously it was
kept alive only until the main resource is parsed. This is needed to ensure all the subresources
get put into the cache and the URLLoaderThrottle get their notifications for histogramming
purposes.
Bug: 769401
Change-Id: I6fe30e6c48d4791b30530e4e45bf8061d4b04db6
Cq-Include-Trybots: master.tryserver.chromium.linux:linux_mojo
Reviewed-on: https://chromium-review.googlesource.com/845114
Reviewed-by: Tom Sepez <[email protected]>
Reviewed-by: Nate Chapin <[email protected]>
Reviewed-by: Alexei Svitkine <[email protected]>
Reviewed-by: Matthew Cary <[email protected]>
Commit-Queue: John Abd-El-Malek <[email protected]>
Cr-Commit-Position: refs/heads/master@{#527760}
TBR=tsepez,japhet,asvitkine,mattcary
for reland after conflict with another cl
Change-Id: I6fe30e6c48d4791b30530e4e45bf8061d4b04db6
Reviewed-on: https://chromium-review.googlesource.com/855041
Commit-Queue: John Abd-El-Malek <[email protected]>
Reviewed-by: John Abd-El-Malek <[email protected]>
Cr-Commit-Position: refs/heads/master@{#527821}
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 7fdb479c..9db5f06 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -124,6 +124,7 @@
#include "chrome/common/logging_chrome.h"
#include "chrome/common/pepper_permission_util.h"
#include "chrome/common/pref_names.h"
+#include "chrome/common/prerender_url_loader_throttle.h"
#include "chrome/common/profiling/constants.mojom.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/renderer_configuration.mojom.h"
@@ -792,6 +793,16 @@
g_browser_process->system_request_context());
}
+chrome::mojom::PrerenderCanceler* GetPrerenderCanceller(
+ const base::Callback<content::WebContents*()>& wc_getter) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ auto* web_contents = wc_getter.Run();
+ if (!web_contents)
+ return nullptr;
+
+ return prerender::PrerenderContents::FromWebContents(web_contents);
+}
+
} // namespace
ChromeContentBrowserClient::ChromeContentBrowserClient()
@@ -3700,6 +3711,17 @@
if (safe_browsing_throttle)
result.push_back(std::move(safe_browsing_throttle));
+ ChromeNavigationUIData* chrome_navigation_ui_data =
+ static_cast<ChromeNavigationUIData*>(navigation_ui_data);
+ if (chrome_navigation_ui_data &&
+ chrome_navigation_ui_data->prerender_mode() != prerender::NO_PRERENDER) {
+ result.push_back(std::make_unique<prerender::PrerenderURLLoaderThrottle>(
+ chrome_navigation_ui_data->prerender_mode(),
+ chrome_navigation_ui_data->prerender_histogram_prefix(),
+ base::BindOnce(GetPrerenderCanceller, wc_getter),
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)));
+ }
+
return result;
}
diff --git a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc
index 3d6fbcf..65c3337a1 100644
--- a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc
+++ b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc
@@ -77,6 +77,7 @@
#include "content/public/browser/service_worker_context.h"
#include "content/public/browser/stream_info.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/previews_state.h"
#include "content/public/common/resource_response.h"
#include "extensions/features/features.h"
@@ -673,8 +674,14 @@
const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
if (info->IsPrerendering()) {
- throttles->push_back(
- base::MakeUnique<prerender::PrerenderResourceThrottle>(request));
+ // TODO(jam): remove this throttle once http://crbug.com/740130 is fixed and
+ // PrerendererURLLoaderThrottle can be used for frame requests in the
+ // network-service-disabled mode.
+ if (!base::FeatureList::IsEnabled(features::kNetworkService) &&
+ content::IsResourceTypeFrame(info->GetResourceType())) {
+ throttles->push_back(
+ base::MakeUnique<prerender::PrerenderResourceThrottle>(request));
+ }
}
std::unique_ptr<PredictorResourceThrottle> predictor_throttle =
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc
index 3aacaf5..d8b300125 100644
--- a/chrome/browser/prerender/prerender_browsertest.cc
+++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -116,6 +116,7 @@
#include "extensions/common/switches.h"
#include "extensions/test/result_catcher.h"
#include "media/base/media_switches.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
#include "net/base/escape.h"
#include "net/cert/x509_certificate.h"
#include "net/dns/mock_host_resolver.h"
@@ -2870,6 +2871,8 @@
net::test_server::GetFilePathWithReplacements(
"/prerender/prerender_with_image.html", replacement_text,
&replacement_path);
+ // Disable load event checks because they race with cancellation.
+ DisableLoadEventCheck();
PrerenderTestURL(replacement_path, FINAL_STATUS_UNSUPPORTED_SCHEME, 0);
}
@@ -2908,6 +2911,8 @@
// Checks that non-http/https main page redirects cancel the prerender.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
PrerenderCancelMainFrameRedirectUnsupportedScheme) {
+ // Disable load event checks because they race with cancellation.
+ DisableLoadEventCheck();
GURL url = embedded_test_server()->GetURL(
CreateServerRedirect("invalidscheme://www.google.com/test.html"));
PrerenderTestURL(url, FINAL_STATUS_UNSUPPORTED_SCHEME, 0);
@@ -3036,6 +3041,8 @@
// Checks that deferred redirects in a synchronous XHR abort the prerender.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDeferredSynchronousXHR) {
+ // Disable load event checks because they race with cancellation.
+ DisableLoadEventCheck();
PrerenderTestURL("/prerender/prerender_deferred_sync_xhr.html",
FINAL_STATUS_BAD_DEFERRED_REDIRECT, 0);
ui_test_utils::NavigateToURL(current_browser(), dest_url());
@@ -3227,28 +3234,25 @@
GURL main_page_url =
GetURLWithReplacement("/prerender/prerender_with_image.html",
"REPLACE_WITH_IMAGE_URL", kPrefetchJpeg);
-
- // Setup request interceptors for subresources.
- auto get_priority_lambda = [](net::RequestPriority* out_priority,
- net::URLRequest* request) {
- *out_priority = request->priority();
- };
- RequestCounter before_swap_counter;
net::RequestPriority before_swap_priority = net::THROTTLED;
- InterceptRequestAndCount(
- before_swap_url, &before_swap_counter,
- base::Bind(get_priority_lambda, base::Unretained(&before_swap_priority)));
- RequestCounter after_swap_counter;
net::RequestPriority after_swap_priority = net::THROTTLED;
- InterceptRequestAndCount(
- after_swap_url, &after_swap_counter,
- base::Bind(get_priority_lambda, base::Unretained(&after_swap_priority)));
+
+ content::URLLoaderInterceptor interceptor(
+ base::BindLambdaForTesting(
+ [&](content::URLLoaderInterceptor::RequestParams* params) {
+ if (params->url_request.url == before_swap_url)
+ before_swap_priority = params->url_request.priority;
+ else if (params->url_request.url == after_swap_url)
+ after_swap_priority = params->url_request.priority;
+ return false;
+ }),
+ false, true);
// Start the prerender.
PrerenderTestURL(main_page_url, FINAL_STATUS_USED, 1);
// Check priority before swap.
- before_swap_counter.WaitForCount(1);
+ WaitForRequestCount(before_swap_url, 1);
#if defined(OS_ANDROID)
EXPECT_GT(before_swap_priority, net::IDLE);
#else
@@ -3262,10 +3266,40 @@
GetActiveWebContents()->GetMainFrame()->ExecuteJavaScriptForTests(
base::ASCIIToUTF16(
"var img=new Image(); img.src='/prerender/image.png'"));
- after_swap_counter.WaitForCount(1);
+ WaitForRequestCount(after_swap_url, 1);
EXPECT_NE(net::IDLE, after_swap_priority);
}
+namespace {
+
+class HangingURLLoader : public content::mojom::URLLoader {
+ public:
+ explicit HangingURLLoader(content::mojom::URLLoaderClientPtr client)
+ : client_(std::move(client)) {}
+ ~HangingURLLoader() override {}
+ // mojom::URLLoader implementation:
+ void FollowRedirect() override {}
+ void ProceedWithResponse() override {}
+ void SetPriority(net::RequestPriority priority,
+ int32_t intra_priority_value) override {
+ if (set_priority_callback_)
+ std::move(set_priority_callback_).Run(priority);
+ }
+ void PauseReadingBodyFromNet() override {}
+ void ResumeReadingBodyFromNet() override {}
+
+ using SetPriorityCallback = base::OnceCallback<void(net::RequestPriority)>;
+ void set_set_priority_callback(SetPriorityCallback callback) {
+ set_priority_callback_ = std::move(callback);
+ }
+
+ private:
+ content::mojom::URLLoaderClientPtr client_;
+ SetPriorityCallback set_priority_callback_;
+};
+
+} // namespace
+
// Checks that a request started before the swap gets its original priority back
// after the swap.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, ResourcePriorityOverlappingSwap) {
@@ -3274,30 +3308,30 @@
GetURLWithReplacement("/prerender/prerender_with_image.html",
"REPLACE_WITH_IMAGE_URL", kPrefetchJpeg);
- // Setup request interceptors for subresources.
- net::URLRequest* url_request = nullptr;
net::RequestPriority priority = net::THROTTLED;
- base::RunLoop wait_loop;
- auto io_lambda = [](net::URLRequest** out_request,
- net::RequestPriority* out_priority, base::Closure closure,
- net::URLRequest* request) {
- if (out_request)
- *out_request = request;
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
- base::BindOnce(
- [](net::RequestPriority priority,
- net::RequestPriority* out_priority, base::Closure closure) {
- *out_priority = priority;
- closure.Run();
- },
- request->priority(), base::Unretained(out_priority), closure));
- };
+ base::RunLoop load_image_run_loop, set_priority_run_loop;
+ content::URLLoaderInterceptor interceptor(
+ base::BindLambdaForTesting(
+ [&](content::URLLoaderInterceptor::RequestParams* params) {
+ if (params->url_request.url == image_url) {
+ // Check priority before swap.
+ priority = params->url_request.priority;
+ load_image_run_loop.QuitClosure().Run();
- test_utils::CreateHangingFirstRequestInterceptor(
- image_url, base::FilePath(),
- base::Bind(io_lambda, base::Unretained(&url_request),
- base::Unretained(&priority), wait_loop.QuitClosure()));
+ auto loader =
+ std::make_unique<HangingURLLoader>(std::move(params->client));
+ loader->set_set_priority_callback(base::BindLambdaForTesting(
+ [&](net::RequestPriority request_priority) {
+ priority = request_priority;
+ set_priority_run_loop.QuitClosure().Run();
+ }));
+ mojo::MakeStrongBinding(std::move(loader),
+ std::move(params->request));
+ return true;
+ }
+ return false;
+ }),
+ false, true);
// The prerender will hang on the image resource, can't run the usual checks.
DisableLoadEventCheck();
@@ -3305,14 +3339,11 @@
// Start the prerender.
PrerenderTestURL(main_page_url, FINAL_STATUS_USED, 0);
-// Check priority before swap.
+ // Check priority before swap.
+ load_image_run_loop.Run();
#if defined(OS_ANDROID)
- if (priority <= net::IDLE)
- wait_loop.Run();
EXPECT_GT(priority, net::IDLE);
#else
- if (priority != net::IDLE)
- wait_loop.Run();
EXPECT_EQ(net::IDLE, priority);
#endif
@@ -3323,15 +3354,7 @@
ui::PAGE_TRANSITION_TYPED, false));
// Check priority after swap. The test may timeout in case of failure.
- priority = net::THROTTLED;
- do {
- base::RunLoop loop;
- content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
- base::BindOnce(io_lambda, nullptr, base::Unretained(&priority),
- loop.QuitClosure(), base::Unretained(url_request)));
- loop.Run();
- } while (priority <= net::IDLE);
+ set_priority_run_loop.Run();
EXPECT_GT(priority, net::IDLE);
}
diff --git a/chrome/browser/prerender/prerender_contents.cc b/chrome/browser/prerender/prerender_contents.cc
index c7c70cc..6c94f3f5 100644
--- a/chrome/browser/prerender/prerender_contents.cc
+++ b/chrome/browser/prerender/prerender_contents.cc
@@ -23,12 +23,14 @@
#include "chrome/browser/prerender/prerender_manager.h"
#include "chrome/browser/prerender/prerender_manager_factory.h"
#include "chrome/browser/prerender/prerender_resource_throttle.h"
+#include "chrome/browser/prerender/prerender_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/task_manager/web_contents_tags.h"
#include "chrome/browser/ui/tab_helpers.h"
#include "chrome/browser/ui/web_contents_sizer.h"
#include "chrome/common/prerender_messages.h"
#include "chrome/common/prerender_types.h"
+#include "chrome/common/prerender_util.h"
#include "components/history/core/browser/history_types.h"
#include "content/public/browser/browser_child_process_host.h"
#include "content/public/browser/browser_thread.h"
@@ -57,16 +59,6 @@
namespace {
-// Valid HTTP methods for both prefetch and prerendering.
-const char* const kValidHttpMethods[] = {
- "GET", "HEAD",
-};
-
-// Additional valid HTTP methods for prerendering.
-const char* const kValidHttpMethodsForPrerendering[] = {
- "OPTIONS", "POST", "TRACE",
-};
-
void ResumeThrottles(
std::vector<base::WeakPtr<PrerenderResourceThrottle>> throttles,
std::vector<base::WeakPtr<PrerenderResourceThrottle>> idle_resources) {
@@ -232,27 +224,6 @@
prerender_mode_ = mode;
}
-bool PrerenderContents::IsValidHttpMethod(const std::string& method) {
- DCHECK_NE(prerender_mode(), NO_PRERENDER);
- // |method| has been canonicalized to upper case at this point so we can just
- // compare them.
- DCHECK_EQ(method, base::ToUpperASCII(method));
- for (auto* valid_method : kValidHttpMethods) {
- if (method == valid_method)
- return true;
- }
-
- if (prerender_mode() == PREFETCH_ONLY)
- return false;
-
- for (auto* valid_method : kValidHttpMethodsForPrerendering) {
- if (method == valid_method)
- return true;
- }
-
- return false;
-}
-
// static
PrerenderContents::Factory* PrerenderContents::CreateFactory() {
return new PrerenderContentsFactoryImpl();
@@ -538,7 +509,8 @@
// occur. Note that this is always triggered before the first navigation, so
// there's no need to send the message just after the WebContents is created.
render_frame_host->Send(new PrerenderMsg_SetIsPrerendering(
- render_frame_host->GetRoutingID(), prerender_mode_));
+ render_frame_host->GetRoutingID(), prerender_mode_,
+ PrerenderHistograms::GetHistogramPrefix(origin_)));
}
void PrerenderContents::DidStopLoading() {
@@ -738,8 +710,8 @@
SetFinalStatus(FINAL_STATUS_USED);
if (prerender_contents_.get()) {
- prerender_contents_->SendToAllFrames(
- new PrerenderMsg_SetIsPrerendering(MSG_ROUTING_NONE, NO_PRERENDER));
+ prerender_contents_->SendToAllFrames(new PrerenderMsg_SetIsPrerendering(
+ MSG_ROUTING_NONE, NO_PRERENDER, std::string()));
}
NotifyPrerenderStop();
@@ -755,6 +727,19 @@
Destroy(FINAL_STATUS_WINDOW_PRINT);
}
+void PrerenderContents::CancelPrerenderForUnsupportedMethod() {
+ Destroy(FINAL_STATUS_INVALID_HTTP_METHOD);
+}
+
+void PrerenderContents::CancelPrerenderForUnsupportedScheme(const GURL& url) {
+ Destroy(FINAL_STATUS_UNSUPPORTED_SCHEME);
+ ReportUnsupportedPrerenderScheme(url);
+}
+
+void PrerenderContents::CancelPrerenderForSyncDeferredRedirect() {
+ Destroy(FINAL_STATUS_BAD_DEFERRED_REDIRECT);
+}
+
void PrerenderContents::OnPrerenderCancelerRequest(
chrome::mojom::PrerenderCancelerRequest request) {
if (!prerender_canceler_binding_.is_bound())
diff --git a/chrome/browser/prerender/prerender_contents.h b/chrome/browser/prerender/prerender_contents.h
index 305e97b..c2caba3 100644
--- a/chrome/browser/prerender/prerender_contents.h
+++ b/chrome/browser/prerender/prerender_contents.h
@@ -114,9 +114,6 @@
void SetPrerenderMode(PrerenderMode mode);
PrerenderMode prerender_mode() const { return prerender_mode_; }
- // Returns true iff the method given is valid for prerendering.
- bool IsValidHttpMethod(const std::string& method);
-
static Factory* CreateFactory();
// Returns a PrerenderContents from the given web_contents, if it's used for
@@ -309,6 +306,9 @@
// chrome::mojom::PrerenderCanceler:
void CancelPrerenderForPrinting() override;
+ void CancelPrerenderForUnsupportedMethod() override;
+ void CancelPrerenderForUnsupportedScheme(const GURL& url) override;
+ void CancelPrerenderForSyncDeferredRedirect() override;
void OnPrerenderCancelerRequest(
chrome::mojom::PrerenderCancelerRequest request);
diff --git a/chrome/browser/prerender/prerender_histograms.cc b/chrome/browser/prerender/prerender_histograms.cc
index ef37835..389dea9 100644
--- a/chrome/browser/prerender/prerender_histograms.cc
+++ b/chrome/browser/prerender/prerender_histograms.cc
@@ -13,6 +13,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/prerender/prerender_manager.h"
+#include "chrome/common/prerender_util.h"
#include "components/google/core/browser/google_util.h"
#include "net/http/http_cache.h"
@@ -20,55 +21,9 @@
namespace {
-// This enum is used to define the buckets for the
-// "Prerender.NoStatePrefetchResourceCount" histogram family.
-// Hence, existing enumerated constants should never be deleted or reordered,
-// and new constants should only be appended at the end of the enumeration.
-enum NoStatePrefetchResponseType {
- NO_STORE = 1 << 0,
- REDIRECT = 1 << 1,
- MAIN_RESOURCE = 1 << 2,
- NO_STATE_PREFETCH_RESPONSE_TYPE_COUNT = 1 << 3
-};
-
-int GetResourceType(bool is_main_resource, bool is_redirect, bool is_no_store) {
- return (is_no_store * NO_STORE) + (is_redirect * REDIRECT) +
- (is_main_resource * MAIN_RESOURCE);
-}
-
-std::string ComposeHistogramName(const std::string& prefix_type,
- const std::string& name) {
- if (prefix_type.empty())
- return std::string("Prerender.") + name;
- return std::string("Prerender.") + prefix_type + std::string("_") + name;
-}
-
std::string GetHistogramName(Origin origin, const std::string& name) {
- switch (origin) {
- case ORIGIN_OMNIBOX:
- return ComposeHistogramName("omnibox", name);
- case ORIGIN_NONE:
- return ComposeHistogramName("none", name);
- case ORIGIN_LINK_REL_PRERENDER_SAMEDOMAIN:
- return ComposeHistogramName("websame", name);
- case ORIGIN_LINK_REL_PRERENDER_CROSSDOMAIN:
- return ComposeHistogramName("webcross", name);
- case ORIGIN_EXTERNAL_REQUEST:
- return ComposeHistogramName("externalrequest", name);
- case ORIGIN_LINK_REL_NEXT:
- return ComposeHistogramName("webnext", name);
- case ORIGIN_GWS_PRERENDER:
- return ComposeHistogramName("gws", name);
- case ORIGIN_EXTERNAL_REQUEST_FORCED_PRERENDER:
- return ComposeHistogramName("externalrequestforced", name);
- default:
- NOTREACHED();
- break;
- }
-
- // Dummy return value to make the compiler happy.
- NOTREACHED();
- return ComposeHistogramName("none", name);
+ return ComposeHistogramName(PrerenderHistograms::GetHistogramPrefix(origin),
+ name);
}
const char* FirstContentfulPaintHiddenName(bool was_hidden) {
@@ -79,6 +34,33 @@
PrerenderHistograms::PrerenderHistograms() {}
+std::string PrerenderHistograms::GetHistogramPrefix(Origin origin) {
+ switch (origin) {
+ case ORIGIN_OMNIBOX:
+ return "omnibox";
+ case ORIGIN_NONE:
+ return "none";
+ case ORIGIN_LINK_REL_PRERENDER_SAMEDOMAIN:
+ return "websame";
+ case ORIGIN_LINK_REL_PRERENDER_CROSSDOMAIN:
+ return "webcross";
+ case ORIGIN_EXTERNAL_REQUEST:
+ return "externalrequest";
+ case ORIGIN_LINK_REL_NEXT:
+ return "webnext";
+ case ORIGIN_GWS_PRERENDER:
+ return "gws";
+ case ORIGIN_EXTERNAL_REQUEST_FORCED_PRERENDER:
+ return "externalrequestforced";
+ default:
+ NOTREACHED();
+ break;
+ }
+
+ // Dummy return value to make the compiler happy.
+ return "none";
+}
+
void PrerenderHistograms::RecordPerceivedFirstContentfulPaintStatus(
Origin origin,
bool successful,
@@ -123,34 +105,6 @@
kBucketCount);
}
-void PrerenderHistograms::RecordPrefetchResponseReceived(
- Origin origin,
- bool is_main_resource,
- bool is_redirect,
- bool is_no_store) const {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- int sample = GetResourceType(is_main_resource, is_redirect, is_no_store);
- std::string histogram_name =
- GetHistogramName(origin, "NoStatePrefetchResponseTypes");
- base::UmaHistogramExactLinear(histogram_name, sample,
- NO_STATE_PREFETCH_RESPONSE_TYPE_COUNT);
-}
-
-void PrerenderHistograms::RecordPrefetchRedirectCount(
- Origin origin,
- bool is_main_resource,
- int redirect_count) const {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- const int kMaxRedirectCount = 10;
- std::string histogram_base_name = base::StringPrintf(
- "NoStatePrefetch%sResourceRedirects", is_main_resource ? "Main" : "Sub");
- std::string histogram_name = GetHistogramName(origin, histogram_base_name);
- base::UmaHistogramExactLinear(histogram_name, redirect_count,
- kMaxRedirectCount);
-}
-
void PrerenderHistograms::RecordPrefetchFirstContentfulPaintTime(
Origin origin,
bool is_no_store,
diff --git a/chrome/browser/prerender/prerender_histograms.h b/chrome/browser/prerender/prerender_histograms.h
index c1b81a9..51dbcb3 100644
--- a/chrome/browser/prerender/prerender_histograms.h
+++ b/chrome/browser/prerender/prerender_histograms.h
@@ -45,6 +45,10 @@
// PrerenderManager.
PrerenderHistograms();
+ // Return the string to use as a prefix for histograms depending on the origin
+ // of the prerender.
+ static std::string GetHistogramPrefix(Origin origin);
+
// Record that a first contentful paint occured, and whether we were able to
// successfuly record the perceived FCP.
void RecordPerceivedFirstContentfulPaintStatus(Origin origin,
@@ -67,19 +71,6 @@
int64_t prerender_bytes,
int64_t profile_bytes) const;
- // Called when a NoStatePrefetch request has received a response (including
- // redirects). May be called several times per resource, in case of redirects.
- void RecordPrefetchResponseReceived(Origin origin,
- bool is_main_resource,
- bool is_redirect,
- bool is_no_store) const;
-
- // Called when a NoStatePrefetch resource has been loaded. This is called only
- // once per resource, when all redirects have been resolved.
- void RecordPrefetchRedirectCount(Origin origin,
- bool is_main_resource,
- int redirect_count) const;
-
// Records the time to first contentful paint with respect to a possible
// prefetch of the page. The time to first contentful paint with respect to
// the navigation start is recorded (even if the page was prererendered in
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc
index d3ed8fb..4c63209 100644
--- a/chrome/browser/prerender/prerender_manager.cc
+++ b/chrome/browser/prerender/prerender_manager.cc
@@ -477,21 +477,6 @@
PostCleanupTask();
}
-void PrerenderManager::RecordPrefetchResponseReceived(Origin origin,
- bool is_main_resource,
- bool is_redirect,
- bool is_no_store) {
- histograms_->RecordPrefetchResponseReceived(origin, is_main_resource,
- is_redirect, is_no_store);
-}
-
-void PrerenderManager::RecordPrefetchRedirectCount(Origin origin,
- bool is_main_resource,
- int redirect_count) {
- histograms_->RecordPrefetchRedirectCount(origin, is_main_resource,
- redirect_count);
-}
-
void PrerenderManager::RecordNoStateFirstContentfulPaint(const GURL& url,
bool is_no_store,
bool was_hidden,
@@ -696,18 +681,6 @@
return false;
}
-// static
-bool PrerenderManager::DoesURLHaveValidScheme(const GURL& url) {
- return (url.SchemeIsHTTPOrHTTPS() ||
- url.SchemeIs(extensions::kExtensionScheme) ||
- url.SchemeIs("data"));
-}
-
-// static
-bool PrerenderManager::DoesSubresourceURLHaveValidScheme(const GURL& url) {
- return DoesURLHaveValidScheme(url) || url == url::kAboutBlankURL;
-}
-
std::unique_ptr<base::DictionaryValue> PrerenderManager::CopyAsValue() const {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/chrome/browser/prerender/prerender_manager.h b/chrome/browser/prerender/prerender_manager.h
index 807b809..becd84f 100644
--- a/chrome/browser/prerender/prerender_manager.h
+++ b/chrome/browser/prerender/prerender_manager.h
@@ -166,19 +166,6 @@
virtual void MoveEntryToPendingDelete(PrerenderContents* entry,
FinalStatus final_status);
- // Called when a NoStatePrefetch request has received a response (including
- // redirects). May be called several times per resource, in case of redirects.
- void RecordPrefetchResponseReceived(Origin origin,
- bool is_main_resource,
- bool is_redirect,
- bool is_no_store);
-
- // Called when a NoStatePrefetch resource has been loaded. This is called only
- // once per resource, when all redirects have been resolved.
- void RecordPrefetchRedirectCount(Origin origin,
- bool is_main_resource,
- int redirect_count);
-
// Called to record the time to First Contentful Paint for all pages that were
// not prerendered.
//
@@ -256,13 +243,6 @@
// Checks whether |url| has been recently navigated to.
bool HasRecentlyBeenNavigatedTo(Origin origin, const GURL& url);
- // Returns true iff the scheme of the URL given is valid for prerendering.
- static bool DoesURLHaveValidScheme(const GURL& url);
-
- // Returns true iff the scheme of the subresource URL given is valid for
- // prerendering.
- static bool DoesSubresourceURLHaveValidScheme(const GURL& url);
-
// Returns a Value object containing the active pages being prerendered, and
// a history of pages which were prerendered.
std::unique_ptr<base::DictionaryValue> CopyAsValue() const;
diff --git a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
index a6b6259..4611805 100644
--- a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
+++ b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
@@ -14,6 +14,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task_scheduler/post_task.h"
+#include "base/test/bind_test_util.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/threading/platform_thread.h"
#include "chrome/browser/history/history_service_factory.h"
@@ -483,7 +484,6 @@
// Checks that the load flags are set correctly for all resources in a 301
// redirect chain.
IN_PROC_BROWSER_TEST_P(NoStatePrefetchBrowserTest, Prefetch301LoadFlags) {
- // TODO(jam): override frame URLLoaderFactory.
std::string redirect_path =
"/server-redirect/?" + net::EscapeQueryParamValue(kPrefetchPage, false);
GURL redirect_url = src_server()->GetURL(redirect_path);
@@ -709,22 +709,25 @@
// Checks that prefetch requests have net::IDLE priority.
IN_PROC_BROWSER_TEST_P(NoStatePrefetchBrowserTest, IssuesIdlePriorityRequests) {
- // TODO(jam): use URLLoaderFactory for subresource.
GURL script_url = src_server()->GetURL(kPrefetchScript);
- RequestCounter script_counter;
- prerender::test_utils::InterceptRequestAndCount(
- script_url, &script_counter, base::Bind([](net::URLRequest* request) {
+ content::URLLoaderInterceptor interceptor(
+ base::BindLambdaForTesting(
+ [=](content::URLLoaderInterceptor::RequestParams* params) {
#if defined(OS_ANDROID)
- // On Android requests from prerenders do not get downgraded priority.
- // See: https://crbug.com/652746.
- constexpr net::RequestPriority kExpectedPriority = net::HIGHEST;
+ // On Android requests from prerenders do not get downgraded
+ // priority. See: https://crbug.com/652746.
+ constexpr net::RequestPriority kExpectedPriority = net::HIGHEST;
#else
- constexpr net::RequestPriority kExpectedPriority = net::IDLE;
+ constexpr net::RequestPriority kExpectedPriority = net::IDLE;
#endif
- EXPECT_EQ(kExpectedPriority, request->priority());
- }));
+ if (params->url_request.url == script_url)
+ EXPECT_EQ(kExpectedPriority, params->url_request.priority);
+ return false;
+ }),
+ false, true);
+
PrefetchFromFile(kPrefetchPage, FINAL_STATUS_NOSTATE_PREFETCH_FINISHED);
- script_counter.WaitForCount(1);
+ WaitForRequestCount(script_url, 1);
}
// Checks that a registered ServiceWorker (SW) that is not currently running
diff --git a/chrome/browser/prerender/prerender_resource_throttle.cc b/chrome/browser/prerender/prerender_resource_throttle.cc
index e12cdcf9..1721167 100644
--- a/chrome/browser/prerender/prerender_resource_throttle.cc
+++ b/chrome/browser/prerender/prerender_resource_throttle.cc
@@ -11,6 +11,7 @@
#include "chrome/browser/prerender/prerender_final_status.h"
#include "chrome/browser/prerender/prerender_manager.h"
#include "chrome/browser/prerender/prerender_util.h"
+#include "chrome/common/prerender_util.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/browser/web_contents.h"
@@ -26,9 +27,6 @@
namespace prerender {
namespace {
-static const char kFollowOnlyWhenPrerenderShown[] =
- "follow-only-when-prerender-shown";
-
PrerenderContents* g_prerender_contents_for_testing;
// Returns true if the response has a "no-store" cache control header.
@@ -202,7 +200,7 @@
// Abort any prerenders that spawn requests that use unsupported HTTP
// methods or schemes.
- if (!prerender_contents->IsValidHttpMethod(method)) {
+ if (!IsValidHttpMethod(prerender_contents->prerender_mode(), method)) {
// If this is a full prerender, cancel the prerender in response to
// invalid requests. For prefetches, cancel invalid requests but keep the
// prefetch going, unless it's the main frame that's invalid.
@@ -211,7 +209,7 @@
prerender_contents->Destroy(FINAL_STATUS_INVALID_HTTP_METHOD);
}
cancel = true;
- } else if (!PrerenderManager::DoesSubresourceURLHaveValidScheme(url) &&
+ } else if (!DoesSubresourceURLHaveValidScheme(url) &&
resource_type != content::RESOURCE_TYPE_MAIN_FRAME) {
// Destroying the prerender for unsupported scheme only for non-main
// resource to allow chrome://crash to actually crash in the
@@ -260,12 +258,12 @@
PrerenderContents* prerender_contents =
PrerenderContentsFromGetter(web_contents_getter);
if (prerender_contents) {
- prerender_contents->prerender_manager()->RecordPrefetchResponseReceived(
- prerender_contents->origin(),
+ RecordPrefetchResponseReceived(
+ PrerenderHistograms::GetHistogramPrefix(prerender_contents->origin()),
content::IsResourceTypeFrame(resource_type), true /* is_redirect */,
is_no_store);
// Abort any prerenders with requests which redirect to invalid schemes.
- if (!PrerenderManager::DoesURLHaveValidScheme(new_url)) {
+ if (!DoesURLHaveValidScheme(new_url)) {
prerender_contents->Destroy(FINAL_STATUS_UNSUPPORTED_SCHEME);
ReportUnsupportedPrerenderScheme(new_url);
cancel = true;
@@ -307,11 +305,12 @@
if (prerender_throttle_info->mode() != PREFETCH_ONLY)
return;
- prerender_throttle_info->manager()->RecordPrefetchResponseReceived(
- prerender_throttle_info->origin(), is_main_resource,
- false /* is_redirect */, is_no_store);
- prerender_throttle_info->manager()->RecordPrefetchRedirectCount(
- prerender_throttle_info->origin(), is_main_resource, redirect_count);
+ auto histogram_prefix = PrerenderHistograms::GetHistogramPrefix(
+ prerender_throttle_info->origin());
+ RecordPrefetchResponseReceived(histogram_prefix, is_main_resource,
+ false /* is_redirect */, is_no_store);
+ RecordPrefetchRedirectCount(histogram_prefix, is_main_resource,
+ redirect_count);
}
// static
diff --git a/chrome/browser/prerender/prerender_unittest.cc b/chrome/browser/prerender/prerender_unittest.cc
index ceb726a..7c19ae6 100644
--- a/chrome/browser/prerender/prerender_unittest.cc
+++ b/chrome/browser/prerender/prerender_unittest.cc
@@ -32,6 +32,7 @@
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/prerender_types.h"
+#include "chrome/common/prerender_util.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "components/content_settings/core/common/pref_names.h"
@@ -1784,25 +1785,19 @@
}
TEST_F(PrerenderTest, PrerenderContentsIsValidHttpMethod) {
- DummyPrerenderContents* prerender_contents =
- prerender_manager()->CreateNextPrerenderContents(
- GURL("my://dummy.url"), FINAL_STATUS_MANAGER_SHUTDOWN);
+ EXPECT_TRUE(IsValidHttpMethod(FULL_PRERENDER, "GET"));
+ EXPECT_TRUE(IsValidHttpMethod(FULL_PRERENDER, "HEAD"));
+ EXPECT_TRUE(IsValidHttpMethod(FULL_PRERENDER, "OPTIONS"));
+ EXPECT_TRUE(IsValidHttpMethod(FULL_PRERENDER, "POST"));
+ EXPECT_TRUE(IsValidHttpMethod(FULL_PRERENDER, "TRACE"));
+ EXPECT_FALSE(IsValidHttpMethod(FULL_PRERENDER, "WHATEVER"));
- prerender_contents->SetPrerenderMode(FULL_PRERENDER);
- EXPECT_TRUE(prerender_contents->IsValidHttpMethod("GET"));
- EXPECT_TRUE(prerender_contents->IsValidHttpMethod("HEAD"));
- EXPECT_TRUE(prerender_contents->IsValidHttpMethod("OPTIONS"));
- EXPECT_TRUE(prerender_contents->IsValidHttpMethod("POST"));
- EXPECT_TRUE(prerender_contents->IsValidHttpMethod("TRACE"));
- EXPECT_FALSE(prerender_contents->IsValidHttpMethod("WHATEVER"));
-
- prerender_contents->SetPrerenderMode(PREFETCH_ONLY);
- EXPECT_TRUE(prerender_contents->IsValidHttpMethod("GET"));
- EXPECT_TRUE(prerender_contents->IsValidHttpMethod("HEAD"));
- EXPECT_FALSE(prerender_contents->IsValidHttpMethod("OPTIONS"));
- EXPECT_FALSE(prerender_contents->IsValidHttpMethod("POST"));
- EXPECT_FALSE(prerender_contents->IsValidHttpMethod("TRACE"));
- EXPECT_FALSE(prerender_contents->IsValidHttpMethod("WHATEVER"));
+ EXPECT_TRUE(IsValidHttpMethod(PREFETCH_ONLY, "GET"));
+ EXPECT_TRUE(IsValidHttpMethod(PREFETCH_ONLY, "HEAD"));
+ EXPECT_FALSE(IsValidHttpMethod(PREFETCH_ONLY, "OPTIONS"));
+ EXPECT_FALSE(IsValidHttpMethod(PREFETCH_ONLY, "POST"));
+ EXPECT_FALSE(IsValidHttpMethod(PREFETCH_ONLY, "TRACE"));
+ EXPECT_FALSE(IsValidHttpMethod(PREFETCH_ONLY, "WHATEVER"));
}
TEST_F(PrerenderTest, PrerenderContentsIncrementsByteCount) {
diff --git a/chrome/browser/renderer_host/chrome_navigation_ui_data.cc b/chrome/browser/renderer_host/chrome_navigation_ui_data.cc
index ae64d6f..c908555 100644
--- a/chrome/browser/renderer_host/chrome_navigation_ui_data.cc
+++ b/chrome/browser/renderer_host/chrome_navigation_ui_data.cc
@@ -5,6 +5,8 @@
#include "chrome/browser/renderer_host/chrome_navigation_ui_data.h"
#include "base/memory/ptr_util.h"
+#include "chrome/browser/prerender/prerender_contents.h"
+#include "chrome/browser/prerender/prerender_histograms.h"
#include "chrome/browser/sessions/session_tab_helper.h"
#include "content/public/browser/navigation_handle.h"
#include "extensions/features/features.h"
@@ -13,15 +15,25 @@
ChromeNavigationUIData::ChromeNavigationUIData(
content::NavigationHandle* navigation_handle) {
+ auto* web_contents = navigation_handle->GetWebContents();
#if BUILDFLAG(ENABLE_EXTENSIONS)
SessionTabHelper* session_tab_helper =
- SessionTabHelper::FromWebContents(navigation_handle->GetWebContents());
+ SessionTabHelper::FromWebContents(web_contents);
int tab_id = session_tab_helper ? session_tab_helper->session_id().id() : -1;
int window_id =
session_tab_helper ? session_tab_helper->window_id().id() : -1;
extension_data_ = base::MakeUnique<extensions::ExtensionNavigationUIData>(
navigation_handle, tab_id, window_id);
#endif
+
+ auto* prerender_contents =
+ prerender::PrerenderContents::FromWebContents(web_contents);
+ if (prerender_contents) {
+ prerender_mode_ = prerender_contents->prerender_mode();
+ prerender_histogram_prefix_ =
+ prerender::PrerenderHistograms::GetHistogramPrefix(
+ prerender_contents->origin());
+ }
}
ChromeNavigationUIData::~ChromeNavigationUIData() {}
@@ -41,6 +53,9 @@
copy->SetOfflinePageNavigationUIData(offline_page_data_->DeepCopy());
#endif
+ copy->prerender_mode_ = prerender_mode_;
+ copy->prerender_histogram_prefix_ = prerender_histogram_prefix_;
+
return std::move(copy);
}
diff --git a/chrome/browser/renderer_host/chrome_navigation_ui_data.h b/chrome/browser/renderer_host/chrome_navigation_ui_data.h
index eec348b7..de1cf32 100644
--- a/chrome/browser/renderer_host/chrome_navigation_ui_data.h
+++ b/chrome/browser/renderer_host/chrome_navigation_ui_data.h
@@ -8,6 +8,7 @@
#include <memory>
#include "base/macros.h"
+#include "chrome/common/prerender_types.h"
#include "components/offline_pages/core/request_header/offline_page_navigation_ui_data.h"
#include "components/offline_pages/features/features.h"
#include "content/public/browser/navigation_ui_data.h"
@@ -54,6 +55,11 @@
}
#endif
+ prerender::PrerenderMode prerender_mode() const { return prerender_mode_; }
+ const std::string& prerender_histogram_prefix() {
+ return prerender_histogram_prefix_;
+ }
+
private:
#if BUILDFLAG(ENABLE_EXTENSIONS)
// Manages the lifetime of optional ExtensionNavigationUIData information.
@@ -66,6 +72,9 @@
offline_page_data_;
#endif
+ prerender::PrerenderMode prerender_mode_ = prerender::NO_PRERENDER;
+ std::string prerender_histogram_prefix_;
+
DISALLOW_COPY_AND_ASSIGN(ChromeNavigationUIData);
};