Home | History | Annotate | Download | only in loader
      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 "content/browser/loader/transfer_navigation_resource_throttle.h"
      6 
      7 #include "base/bind.h"
      8 #include "content/browser/loader/resource_dispatcher_host_impl.h"
      9 #include "content/browser/renderer_host/render_view_host_delegate.h"
     10 #include "content/public/browser/browser_thread.h"
     11 #include "content/public/browser/content_browser_client.h"
     12 #include "content/public/browser/global_request_id.h"
     13 #include "content/public/browser/render_view_host.h"
     14 #include "content/public/browser/resource_request_info.h"
     15 #include "content/public/common/referrer.h"
     16 #include "net/url_request/url_request.h"
     17 
     18 namespace content {
     19 
     20 namespace {
     21 
     22 void RequestTransferURLOnUIThread(int render_process_id,
     23                                   int render_view_id,
     24                                   const GURL& new_url,
     25                                   const Referrer& referrer,
     26                                   WindowOpenDisposition window_open_disposition,
     27                                   int64 frame_id,
     28                                   const GlobalRequestID& global_request_id) {
     29   RenderViewHost* rvh =
     30       RenderViewHost::FromID(render_process_id, render_view_id);
     31   if (!rvh)
     32     return;
     33 
     34   RenderViewHostDelegate* delegate = rvh->GetDelegate();
     35   if (!delegate)
     36     return;
     37 
     38   // We don't know whether the original request had |user_action| set to true.
     39   // However, since we force the navigation to be in the current tab, it doesn't
     40   // matter.
     41   delegate->RequestTransferURL(
     42       new_url, referrer, window_open_disposition,
     43       frame_id, global_request_id, false, true);
     44 }
     45 
     46 }  // namespace
     47 
     48 TransferNavigationResourceThrottle::TransferNavigationResourceThrottle(
     49     net::URLRequest* request)
     50     : request_(request) {
     51 }
     52 
     53 TransferNavigationResourceThrottle::~TransferNavigationResourceThrottle() {
     54 }
     55 
     56 void TransferNavigationResourceThrottle::WillRedirectRequest(
     57     const GURL& new_url,
     58     bool* defer) {
     59   const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
     60 
     61   // If a toplevel request is redirecting across extension extents, we want to
     62   // switch processes. We do this by deferring the redirect and resuming the
     63   // request once the navigation controller properly assigns the right process
     64   // to host the new URL.
     65   // TODO(mpcomplete): handle for cases other than extensions (e.g. WebUI).
     66   ResourceContext* resource_context = info->GetContext();
     67   if (GetContentClient()->browser()->ShouldSwapProcessesForRedirect(
     68           resource_context, request_->url(), new_url)) {
     69     int render_process_id, render_view_id;
     70     if (info->GetAssociatedRenderView(&render_process_id, &render_view_id)) {
     71       GlobalRequestID global_id(info->GetChildID(), info->GetRequestID());
     72 
     73       ResourceDispatcherHostImpl::Get()->MarkAsTransferredNavigation(global_id,
     74                                                                      new_url);
     75 
     76       BrowserThread::PostTask(
     77           BrowserThread::UI,
     78           FROM_HERE,
     79           base::Bind(&RequestTransferURLOnUIThread,
     80               render_process_id,
     81               render_view_id,
     82               new_url,
     83               Referrer(GURL(request_->referrer()), info->GetReferrerPolicy()),
     84               CURRENT_TAB,
     85               info->GetFrameID(),
     86               global_id));
     87 
     88       *defer = true;
     89     }
     90   }
     91 }
     92 
     93 }  // namespace content
     94