14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file. 44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/prerender/prerender_resource_throttle.h" 64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/prerender/prerender_final_status.h" 8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/prerender/prerender_manager.h" 9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/prerender/prerender_util.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/render_frame_host.h" 124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/browser/resource_controller.h" 134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/browser/resource_request_info.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/web_contents.h" 154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/url_request/url_request.h" 164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdochusing content::ResourceType; 18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace prerender { 204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static const char kFollowOnlyWhenPrerenderShown[] = 234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) "follow-only-when-prerender-shown"; 244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PrerenderContents* g_prerender_contents_for_testing; 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PrerenderResourceThrottle::OverridePrerenderContentsForTesting( 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PrerenderContents* contents) { 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) g_prerender_contents_for_testing = contents; 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PrerenderResourceThrottle::PrerenderResourceThrottle(net::URLRequest* request) 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : request_(request) { 354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void PrerenderResourceThrottle::WillStartRequest(bool* defer) { 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const content::ResourceRequestInfo* info = 39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) content::ResourceRequestInfo::ForRequest(request_); 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *defer = true; 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::BrowserThread::PostTask( 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::BrowserThread::UI, 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&PrerenderResourceThrottle::WillStartRequestOnUI, 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AsWeakPtr(), request_->method(), info->GetResourceType(), 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) info->GetChildID(), info->GetRenderFrameID(), 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_->url())); 48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void PrerenderResourceThrottle::WillRedirectRequest(const GURL& new_url, 514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool* defer) { 524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const content::ResourceRequestInfo* info = 534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) content::ResourceRequestInfo::ForRequest(request_); 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *defer = true; 554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string header; 564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) request_->GetResponseHeaderByName(kFollowOnlyWhenPrerenderShown, &header); 574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::BrowserThread::PostTask( 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::BrowserThread::UI, 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&PrerenderResourceThrottle::WillRedirectRequestOnUI, 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AsWeakPtr(), header, info->GetResourceType(), info->IsAsync(), 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) info->GetChildID(), info->GetRenderFrameID(), new_url)); 644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char* PrerenderResourceThrottle::GetNameForLogging() const { 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return "PrerenderResourceThrottle"; 68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void PrerenderResourceThrottle::Resume() { 714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) controller()->Resume(); 724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void PrerenderResourceThrottle::Cancel() { 754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) controller()->Cancel(); 764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PrerenderResourceThrottle::WillStartRequestOnUI( 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::WeakPtr<PrerenderResourceThrottle>& throttle, 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& method, 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ResourceType resource_type, 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int render_process_id, 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int render_frame_id, 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const GURL& url) { 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool cancel = false; 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PrerenderContents* prerender_contents = 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PrerenderContentsFromRenderFrame(render_process_id, render_frame_id); 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (prerender_contents) { 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Abort any prerenders that spawn requests that use unsupported HTTP 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // methods or schemes. 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!PrerenderManager::IsValidHttpMethod(method)) { 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prerender_contents->Destroy(FINAL_STATUS_INVALID_HTTP_METHOD); 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cancel = true; 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else if (!PrerenderManager::DoesSubresourceURLHaveValidScheme(url)) { 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prerender_contents->Destroy(FINAL_STATUS_UNSUPPORTED_SCHEME); 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ReportUnsupportedPrerenderScheme(url); 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cancel = true; 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_ANDROID) 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else if (resource_type == content::RESOURCE_TYPE_FAVICON) { 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Delay icon fetching until the contents are getting swapped in 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // to conserve network usage in mobile devices. 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prerender_contents->AddResourceThrottle(throttle); 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::BrowserThread::PostTask( 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::BrowserThread::IO, 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(cancel ? &PrerenderResourceThrottle::Cancel : 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &PrerenderResourceThrottle::Resume, throttle)); 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PrerenderResourceThrottle::WillRedirectRequestOnUI( 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::WeakPtr<PrerenderResourceThrottle>& throttle, 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& follow_only_when_prerender_shown_header, 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ResourceType resource_type, 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool async, 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int render_process_id, 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int render_frame_id, 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const GURL& new_url) { 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool cancel = false; 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PrerenderContents* prerender_contents = 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PrerenderContentsFromRenderFrame(render_process_id, render_frame_id); 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (prerender_contents) { 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Abort any prerenders with requests which redirect to invalid schemes. 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!PrerenderManager::DoesURLHaveValidScheme(new_url)) { 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prerender_contents->Destroy(FINAL_STATUS_UNSUPPORTED_SCHEME); 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ReportUnsupportedPrerenderScheme(new_url); 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cancel = true; 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else if (follow_only_when_prerender_shown_header == "1" && 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) resource_type != content::RESOURCE_TYPE_MAIN_FRAME) { 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Only defer redirects with the Follow-Only-When-Prerender-Shown 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // header. Do not defer redirects on main frame loads. 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!async) { 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Cancel on deferred synchronous requests. Those will 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // indefinitely hang up a renderer process. 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prerender_contents->Destroy(FINAL_STATUS_BAD_DEFERRED_REDIRECT); 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cancel = true; 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Defer the redirect until the prerender is used or canceled. 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) prerender_contents->AddResourceThrottle(throttle); 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::BrowserThread::PostTask( 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::BrowserThread::IO, 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(cancel ? &PrerenderResourceThrottle::Cancel : 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &PrerenderResourceThrottle::Resume, throttle)); 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PrerenderContents* PrerenderResourceThrottle::PrerenderContentsFromRenderFrame( 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int render_process_id, int render_frame_id) { 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (g_prerender_contents_for_testing) 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return g_prerender_contents_for_testing; 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::RenderFrameHost* rfh = content::RenderFrameHost::FromID( 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) render_process_id, render_frame_id); 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::WebContents* web_contents = 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::WebContents::FromRenderFrameHost(rfh); 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return PrerenderContents::FromWebContents(web_contents); 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} // namespace prerender 168