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
3 // found in the LICENSE file.
5 #include "components/navigation_interception/intercept_navigation_resource_throttle.h"
7 #include "components/navigation_interception/navigation_params.h"
8 #include "content/public/browser/browser_thread.h"
9 #include "content/public/browser/child_process_security_policy.h"
10 #include "content/public/browser/render_frame_host.h"
11 #include "content/public/browser/render_process_host.h"
12 #include "content/public/browser/resource_context.h"
13 #include "content/public/browser/resource_controller.h"
14 #include "content/public/browser/resource_request_info.h"
15 #include "content/public/browser/web_contents.h"
16 #include "content/public/common/referrer.h"
17 #include "net/http/http_response_headers.h"
18 #include "net/url_request/url_request_context.h"
19 #include "net/url_request/url_request_job_factory.h"
20 #include "net/url_request/url_request.h"
21 #include "ui/base/page_transition_types.h"
23 using content::BrowserThread
;
24 using content::ChildProcessSecurityPolicy
;
25 using ui::PageTransition
;
26 using content::Referrer
;
27 using content::RenderProcessHost
;
28 using content::ResourceRequestInfo
;
30 namespace navigation_interception
{
34 void CheckIfShouldIgnoreNavigationOnUIThread(
35 int render_process_id
,
37 const NavigationParams
& navigation_params
,
38 InterceptNavigationResourceThrottle::CheckOnUIThreadCallback
39 should_ignore_callback
,
40 base::Callback
<void(bool)> callback
) {
41 bool should_ignore_navigation
= false;
42 RenderProcessHost
* rph
= RenderProcessHost::FromID(render_process_id
);
44 NavigationParams
validated_params(navigation_params
);
45 rph
->FilterURL(false, &validated_params
.url());
47 content::RenderFrameHost
* render_frame_host
=
48 content::RenderFrameHost::FromID(render_process_id
, render_frame_id
);
49 content::WebContents
* web_contents
=
50 content::WebContents::FromRenderFrameHost(render_frame_host
);
53 should_ignore_navigation
= should_ignore_callback
.Run(web_contents
,
58 BrowserThread::PostTask(
61 base::Bind(callback
, should_ignore_navigation
));
66 InterceptNavigationResourceThrottle::InterceptNavigationResourceThrottle(
67 net::URLRequest
* request
,
68 CheckOnUIThreadCallback should_ignore_callback
)
70 should_ignore_callback_(should_ignore_callback
),
71 weak_ptr_factory_(this) {
74 InterceptNavigationResourceThrottle::~InterceptNavigationResourceThrottle() {
75 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
78 void InterceptNavigationResourceThrottle::WillStartRequest(bool* defer
) {
80 CheckIfShouldIgnoreNavigation(request_
->url(), request_
->method(), false);
83 void InterceptNavigationResourceThrottle::WillRedirectRequest(
87 CheckIfShouldIgnoreNavigation(new_url
, GetMethodAfterRedirect(), true);
90 const char* InterceptNavigationResourceThrottle::GetNameForLogging() const {
91 return "InterceptNavigationResourceThrottle";
94 std::string
InterceptNavigationResourceThrottle::GetMethodAfterRedirect() {
95 net::HttpResponseHeaders
* headers
= request_
->response_headers();
97 return request_
->method();
98 // TODO(davidben): Plumb net::RedirectInfo through content::ResourceThrottle
99 // and unexpose net::URLRequest::ComputeMethodForRedirect.
100 return net::URLRequest::ComputeMethodForRedirect(
101 request_
->method(), headers
->response_code());
104 bool InterceptNavigationResourceThrottle::CheckIfShouldIgnoreNavigation(
106 const std::string
& method
,
108 const ResourceRequestInfo
* info
= ResourceRequestInfo::ForRequest(request_
);
112 int render_process_id
, render_frame_id
;
113 if (!info
->GetAssociatedRenderFrame(&render_process_id
, &render_frame_id
))
116 bool is_external_protocol
=
117 !info
->GetContext()->GetRequestContext()->job_factory()->IsHandledURL(
119 NavigationParams
navigation_params(
120 url
, Referrer(GURL(request_
->referrer()), info
->GetReferrerPolicy()),
121 info
->HasUserGesture(), method
== "POST", info
->GetPageTransition(),
122 is_redirect
, is_external_protocol
);
124 BrowserThread::PostTask(
128 &CheckIfShouldIgnoreNavigationOnUIThread
,
132 should_ignore_callback_
,
134 &InterceptNavigationResourceThrottle::OnResultObtained
,
135 weak_ptr_factory_
.GetWeakPtr())));
137 // Defer request while we wait for the UI thread to check if the navigation
138 // should be ignored.
142 void InterceptNavigationResourceThrottle::OnResultObtained(
143 bool should_ignore_navigation
) {
144 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
146 if (should_ignore_navigation
) {
147 controller()->CancelAndIgnore();
149 controller()->Resume();
153 } // namespace navigation_interception