Home | History | Annotate | Download | only in navigation_interception
      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 
     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 
     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 
     67 InterceptNavigationResourceThrottle::~InterceptNavigationResourceThrottle() {
     68   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     69 }
     70 
     71 void InterceptNavigationResourceThrottle::WillStartRequest(bool* defer) {
     72   *defer =
     73       CheckIfShouldIgnoreNavigation(request_->url(), request_->method(), false);
     74 }
     75 
     76 void InterceptNavigationResourceThrottle::WillRedirectRequest(
     77     const GURL& new_url,
     78     bool* defer) {
     79   *defer =
     80       CheckIfShouldIgnoreNavigation(new_url, GetMethodAfterRedirect(), true);
     81 }
     82 
     83 std::string InterceptNavigationResourceThrottle::GetMethodAfterRedirect() {
     84   net::HttpResponseHeaders* headers = request_->response_headers();
     85   if (!headers)
     86     return request_->method();
     87   return net::URLRequest::ComputeMethodForRedirect(
     88              request_->method(), headers->response_code());
     89 }
     90 
     91 bool InterceptNavigationResourceThrottle::CheckIfShouldIgnoreNavigation(
     92     const GURL& url,
     93     const std::string& method,
     94     bool is_redirect) {
     95   const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
     96   if (!info)
     97     return false;
     98 
     99   int render_process_id, render_view_id;
    100   if (!info->GetAssociatedRenderView(&render_process_id, &render_view_id))
    101     return false;
    102 
    103   NavigationParams navigation_params(url,
    104                                      Referrer(GURL(request_->referrer()),
    105                                               info->GetReferrerPolicy()),
    106                                      info->HasUserGesture(),
    107                                      method == "POST",
    108                                      info->GetPageTransition(),
    109                                      is_redirect);
    110 
    111   BrowserThread::PostTask(
    112       BrowserThread::UI,
    113       FROM_HERE,
    114       base::Bind(
    115           &CheckIfShouldIgnoreNavigationOnUIThread,
    116           render_process_id,
    117           render_view_id,
    118           navigation_params,
    119           should_ignore_callback_,
    120           base::Bind(
    121               &InterceptNavigationResourceThrottle::OnResultObtained,
    122               weak_ptr_factory_.GetWeakPtr())));
    123 
    124   // Defer request while we wait for the UI thread to check if the navigation
    125   // should be ignored.
    126   return true;
    127 }
    128 
    129 void InterceptNavigationResourceThrottle::OnResultObtained(
    130     bool should_ignore_navigation) {
    131   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    132 
    133   if (should_ignore_navigation) {
    134     controller()->CancelAndIgnore();
    135   } else {
    136     controller()->Resume();
    137   }
    138 }
    139 
    140 }  // namespace navigation_interception
    141