• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "components/navigation_interception/intercept_navigation_resource_throttle.h"
6 
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_process_host.h"
11 #include "content/public/browser/render_view_host.h"
12 #include "content/public/browser/resource_controller.h"
13 #include "content/public/browser/resource_request_info.h"
14 #include "content/public/common/page_transition_types.h"
15 #include "content/public/common/referrer.h"
16 #include "net/http/http_response_headers.h"
17 #include "net/url_request/url_request.h"
18 
19 using content::BrowserThread;
20 using content::ChildProcessSecurityPolicy;
21 using content::PageTransition;
22 using content::Referrer;
23 using content::RenderViewHost;
24 using content::ResourceRequestInfo;
25 
26 namespace navigation_interception {
27 
28 namespace {
29 
CheckIfShouldIgnoreNavigationOnUIThread(int render_process_id,int render_view_id,const NavigationParams & navigation_params,InterceptNavigationResourceThrottle::CheckOnUIThreadCallback should_ignore_callback,base::Callback<void (bool)> callback)30 void CheckIfShouldIgnoreNavigationOnUIThread(
31     int render_process_id,
32     int render_view_id,
33     const NavigationParams& navigation_params,
34     InterceptNavigationResourceThrottle::CheckOnUIThreadCallback
35     should_ignore_callback,
36     base::Callback<void(bool)> callback) {
37 
38   bool should_ignore_navigation = false;
39   RenderViewHost* rvh =
40       RenderViewHost::FromID(render_process_id, render_view_id);
41 
42   if (rvh) {
43     NavigationParams validated_params(navigation_params);
44     RenderViewHost::FilterURL(
45         rvh->GetProcess(), false, &validated_params.url());
46 
47     should_ignore_navigation = should_ignore_callback.Run(rvh,
48                                                           validated_params);
49   }
50 
51   BrowserThread::PostTask(
52       BrowserThread::IO,
53       FROM_HERE,
54       base::Bind(callback, should_ignore_navigation));
55 }
56 
57 } // namespace
58 
InterceptNavigationResourceThrottle(net::URLRequest * request,CheckOnUIThreadCallback should_ignore_callback)59 InterceptNavigationResourceThrottle::InterceptNavigationResourceThrottle(
60     net::URLRequest* request,
61     CheckOnUIThreadCallback should_ignore_callback)
62     : request_(request),
63       should_ignore_callback_(should_ignore_callback),
64       weak_ptr_factory_(this) {
65 }
66 
~InterceptNavigationResourceThrottle()67 InterceptNavigationResourceThrottle::~InterceptNavigationResourceThrottle() {
68   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
69 }
70 
WillStartRequest(bool * defer)71 void InterceptNavigationResourceThrottle::WillStartRequest(bool* defer) {
72   *defer =
73       CheckIfShouldIgnoreNavigation(request_->url(), request_->method(), false);
74 }
75 
WillRedirectRequest(const GURL & new_url,bool * defer)76 void InterceptNavigationResourceThrottle::WillRedirectRequest(
77     const GURL& new_url,
78     bool* defer) {
79   *defer =
80       CheckIfShouldIgnoreNavigation(new_url, GetMethodAfterRedirect(), true);
81 }
82 
GetNameForLogging() const83 const char* InterceptNavigationResourceThrottle::GetNameForLogging() const {
84   return "InterceptNavigationResourceThrottle";
85 }
86 
GetMethodAfterRedirect()87 std::string InterceptNavigationResourceThrottle::GetMethodAfterRedirect() {
88   net::HttpResponseHeaders* headers = request_->response_headers();
89   if (!headers)
90     return request_->method();
91   return net::URLRequest::ComputeMethodForRedirect(
92              request_->method(), headers->response_code());
93 }
94 
CheckIfShouldIgnoreNavigation(const GURL & url,const std::string & method,bool is_redirect)95 bool InterceptNavigationResourceThrottle::CheckIfShouldIgnoreNavigation(
96     const GURL& url,
97     const std::string& method,
98     bool is_redirect) {
99   const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
100   if (!info)
101     return false;
102 
103   int render_process_id, render_view_id;
104   if (!info->GetAssociatedRenderView(&render_process_id, &render_view_id))
105     return false;
106 
107   NavigationParams navigation_params(url,
108                                      Referrer(GURL(request_->referrer()),
109                                               info->GetReferrerPolicy()),
110                                      info->HasUserGesture(),
111                                      method == "POST",
112                                      info->GetPageTransition(),
113                                      is_redirect);
114 
115   BrowserThread::PostTask(
116       BrowserThread::UI,
117       FROM_HERE,
118       base::Bind(
119           &CheckIfShouldIgnoreNavigationOnUIThread,
120           render_process_id,
121           render_view_id,
122           navigation_params,
123           should_ignore_callback_,
124           base::Bind(
125               &InterceptNavigationResourceThrottle::OnResultObtained,
126               weak_ptr_factory_.GetWeakPtr())));
127 
128   // Defer request while we wait for the UI thread to check if the navigation
129   // should be ignored.
130   return true;
131 }
132 
OnResultObtained(bool should_ignore_navigation)133 void InterceptNavigationResourceThrottle::OnResultObtained(
134     bool should_ignore_navigation) {
135   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
136 
137   if (should_ignore_navigation) {
138     controller()->CancelAndIgnore();
139   } else {
140     controller()->Resume();
141   }
142 }
143 
144 }  // namespace navigation_interception
145