Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / browser / prerender / prerender_resource_throttle.cc
blobd80cfb3b22465606b2fdf52b7d6a133bd2a7b691
1 // Copyright 2013 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_resource_throttle.h"
7 #include "chrome/browser/prerender/prerender_final_status.h"
8 #include "chrome/browser/prerender/prerender_manager.h"
9 #include "chrome/browser/prerender/prerender_util.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "content/public/browser/render_frame_host.h"
12 #include "content/public/browser/resource_controller.h"
13 #include "content/public/browser/resource_request_info.h"
14 #include "content/public/browser/web_contents.h"
15 #include "net/url_request/redirect_info.h"
16 #include "net/url_request/url_request.h"
18 using content::ResourceType;
20 namespace prerender {
22 namespace {
23 static const char kFollowOnlyWhenPrerenderShown[] =
24 "follow-only-when-prerender-shown";
26 PrerenderContents* g_prerender_contents_for_testing;
29 void PrerenderResourceThrottle::OverridePrerenderContentsForTesting(
30 PrerenderContents* contents) {
31 g_prerender_contents_for_testing = contents;
34 PrerenderResourceThrottle::PrerenderResourceThrottle(net::URLRequest* request)
35 : request_(request) {
38 void PrerenderResourceThrottle::WillStartRequest(bool* defer) {
39 const content::ResourceRequestInfo* info =
40 content::ResourceRequestInfo::ForRequest(request_);
41 *defer = true;
42 content::BrowserThread::PostTask(
43 content::BrowserThread::UI,
44 FROM_HERE,
45 base::Bind(&PrerenderResourceThrottle::WillStartRequestOnUI,
46 AsWeakPtr(), request_->method(), info->GetResourceType(),
47 info->GetChildID(), info->GetRenderFrameID(),
48 request_->url()));
51 void PrerenderResourceThrottle::WillRedirectRequest(
52 const net::RedirectInfo& redirect_info,
53 bool* defer) {
54 const content::ResourceRequestInfo* info =
55 content::ResourceRequestInfo::ForRequest(request_);
56 *defer = true;
57 std::string header;
58 request_->GetResponseHeaderByName(kFollowOnlyWhenPrerenderShown, &header);
60 content::BrowserThread::PostTask(
61 content::BrowserThread::UI,
62 FROM_HERE,
63 base::Bind(&PrerenderResourceThrottle::WillRedirectRequestOnUI,
64 AsWeakPtr(), header, info->GetResourceType(), info->IsAsync(),
65 info->GetChildID(), info->GetRenderFrameID(),
66 redirect_info.new_url));
69 const char* PrerenderResourceThrottle::GetNameForLogging() const {
70 return "PrerenderResourceThrottle";
73 void PrerenderResourceThrottle::Resume() {
74 controller()->Resume();
77 void PrerenderResourceThrottle::Cancel() {
78 controller()->Cancel();
81 void PrerenderResourceThrottle::WillStartRequestOnUI(
82 const base::WeakPtr<PrerenderResourceThrottle>& throttle,
83 const std::string& method,
84 ResourceType resource_type,
85 int render_process_id,
86 int render_frame_id,
87 const GURL& url) {
88 bool cancel = false;
89 PrerenderContents* prerender_contents =
90 PrerenderContentsFromRenderFrame(render_process_id, render_frame_id);
91 if (prerender_contents) {
92 // Abort any prerenders that spawn requests that use unsupported HTTP
93 // methods or schemes.
94 if (!PrerenderManager::IsValidHttpMethod(method)) {
95 prerender_contents->Destroy(FINAL_STATUS_INVALID_HTTP_METHOD);
96 cancel = true;
97 } else if (!PrerenderManager::DoesSubresourceURLHaveValidScheme(url)) {
98 prerender_contents->Destroy(FINAL_STATUS_UNSUPPORTED_SCHEME);
99 ReportUnsupportedPrerenderScheme(url);
100 cancel = true;
101 #if defined(OS_ANDROID)
102 } else if (resource_type == content::RESOURCE_TYPE_FAVICON) {
103 // Delay icon fetching until the contents are getting swapped in
104 // to conserve network usage in mobile devices.
105 prerender_contents->AddResourceThrottle(throttle);
106 return;
107 #endif
111 content::BrowserThread::PostTask(
112 content::BrowserThread::IO,
113 FROM_HERE,
114 base::Bind(cancel ? &PrerenderResourceThrottle::Cancel :
115 &PrerenderResourceThrottle::Resume, throttle));
118 void PrerenderResourceThrottle::WillRedirectRequestOnUI(
119 const base::WeakPtr<PrerenderResourceThrottle>& throttle,
120 const std::string& follow_only_when_prerender_shown_header,
121 ResourceType resource_type,
122 bool async,
123 int render_process_id,
124 int render_frame_id,
125 const GURL& new_url) {
126 bool cancel = false;
127 PrerenderContents* prerender_contents =
128 PrerenderContentsFromRenderFrame(render_process_id, render_frame_id);
129 if (prerender_contents) {
130 // Abort any prerenders with requests which redirect to invalid schemes.
131 if (!PrerenderManager::DoesURLHaveValidScheme(new_url)) {
132 prerender_contents->Destroy(FINAL_STATUS_UNSUPPORTED_SCHEME);
133 ReportUnsupportedPrerenderScheme(new_url);
134 cancel = true;
135 } else if (follow_only_when_prerender_shown_header == "1" &&
136 resource_type != content::RESOURCE_TYPE_MAIN_FRAME) {
137 // Only defer redirects with the Follow-Only-When-Prerender-Shown
138 // header. Do not defer redirects on main frame loads.
139 if (!async) {
140 // Cancel on deferred synchronous requests. Those will
141 // indefinitely hang up a renderer process.
142 prerender_contents->Destroy(FINAL_STATUS_BAD_DEFERRED_REDIRECT);
143 cancel = true;
144 } else {
145 // Defer the redirect until the prerender is used or canceled.
146 prerender_contents->AddResourceThrottle(throttle);
147 return;
152 content::BrowserThread::PostTask(
153 content::BrowserThread::IO,
154 FROM_HERE,
155 base::Bind(cancel ? &PrerenderResourceThrottle::Cancel :
156 &PrerenderResourceThrottle::Resume, throttle));
159 PrerenderContents* PrerenderResourceThrottle::PrerenderContentsFromRenderFrame(
160 int render_process_id, int render_frame_id) {
161 if (g_prerender_contents_for_testing)
162 return g_prerender_contents_for_testing;
163 content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(
164 render_process_id, render_frame_id);
165 content::WebContents* web_contents =
166 content::WebContents::FromRenderFrameHost(rfh);
167 return PrerenderContents::FromWebContents(web_contents);
170 } // namespace prerender