OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 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 "chrome/browser/renderer_host/transfer_navigation_resource_handler.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "chrome/browser/profiles/profile_io_data.h" |
| 9 #include "chrome/browser/extensions/extension_info_map.h" |
| 10 #include "content/browser/renderer_host/render_view_host.h" |
| 11 #include "content/browser/renderer_host/render_view_host_delegate.h" |
| 12 #include "content/browser/renderer_host/resource_dispatcher_host.h" |
| 13 #include "content/browser/renderer_host/resource_dispatcher_host_request_info.h" |
| 14 |
| 15 namespace { |
| 16 |
| 17 // This code is borrowed from ChromeContentRendererClient. We want to mimic |
| 18 // the logic used by the renderer. |
| 19 const Extension* GetNonBookmarkAppExtension( |
| 20 const ExtensionSet& extensions, const GURL& url) { |
| 21 // Exclude bookmark apps, which do not use the app process model. |
| 22 const Extension* extension = extensions.GetByURL(ExtensionURLInfo(url)); |
| 23 if (extension && extension->from_bookmark()) |
| 24 extension = NULL; |
| 25 return extension; |
| 26 } |
| 27 |
| 28 bool CrossesExtensionExtents( |
| 29 const ExtensionSet& extensions, |
| 30 const GURL& old_url, |
| 31 const GURL& new_url) { |
| 32 const Extension* new_url_extension = GetNonBookmarkAppExtension(extensions, |
| 33 new_url); |
| 34 const Extension* old_url_extension = GetNonBookmarkAppExtension(extensions, |
| 35 old_url); |
| 36 |
| 37 // TODO(creis): Temporary workaround for crbug.com/59285: Only return true if |
| 38 // we would enter an extension app's extent from a non-app, or if we leave an |
| 39 // extension with no web extent. We avoid swapping processes to exit a hosted |
| 40 // app for now, since we do not yet support postMessage calls from outside the |
| 41 // app back into it (e.g., as in Facebook OAuth 2.0). |
| 42 bool old_url_is_hosted_app = old_url_extension && |
| 43 !old_url_extension->web_extent().is_empty(); |
| 44 if (old_url_is_hosted_app) |
| 45 return false; |
| 46 |
| 47 return old_url_extension != new_url_extension; |
| 48 } |
| 49 |
| 50 void RequestTransferURLOnUIThread(int render_process_id, |
| 51 int render_view_id, |
| 52 GURL new_url, |
| 53 GURL referrer, |
| 54 WindowOpenDisposition window_open_disposition, |
| 55 int64 frame_id, |
| 56 const GlobalRequestID& request_id) { |
| 57 RenderViewHost* rvh = RenderViewHost::FromID(render_process_id, |
| 58 render_view_id); |
| 59 if (!rvh) |
| 60 return; |
| 61 |
| 62 RenderViewHostDelegate* delegate = rvh->delegate(); |
| 63 if (!delegate) |
| 64 return; |
| 65 |
| 66 delegate->RequestTransferURL(new_url, referrer, window_open_disposition, |
| 67 frame_id, request_id); |
| 68 } |
| 69 |
| 70 } // namespace |
| 71 |
| 72 TransferNavigationResourceHandler::TransferNavigationResourceHandler( |
| 73 ResourceHandler* handler, |
| 74 ResourceDispatcherHost* resource_dispatcher_host, |
| 75 net::URLRequest* request) |
| 76 : next_handler_(handler), |
| 77 rdh_(resource_dispatcher_host), |
| 78 request_(request) { |
| 79 } |
| 80 |
| 81 TransferNavigationResourceHandler::~TransferNavigationResourceHandler() { |
| 82 } |
| 83 |
| 84 bool TransferNavigationResourceHandler::OnUploadProgress(int request_id, |
| 85 uint64 position, |
| 86 uint64 size) { |
| 87 return next_handler_->OnUploadProgress(request_id, position, size); |
| 88 } |
| 89 |
| 90 bool TransferNavigationResourceHandler::OnRequestRedirected( |
| 91 int request_id, |
| 92 const GURL& new_url, |
| 93 content::ResourceResponse* response, |
| 94 bool* defer) { |
| 95 |
| 96 ResourceDispatcherHostRequestInfo* info = |
| 97 ResourceDispatcherHost::InfoForRequest(request_); |
| 98 |
| 99 // If a toplevel request is redirecting across extension extents, we want to |
| 100 // switch processes. We do this by deferring the redirect and resuming the |
| 101 // request once the navigation controller properly assigns the right process |
| 102 // to host the new URL. |
| 103 // TODO(mpcomplete): handle for cases other than extensions (e.g. WebUI). |
| 104 const content::ResourceContext& resource_context = *info->context(); |
| 105 ProfileIOData* io_data = |
| 106 reinterpret_cast<ProfileIOData*>(resource_context.GetUserData(NULL)); |
| 107 |
| 108 if (info->resource_type() == ResourceType::MAIN_FRAME && |
| 109 CrossesExtensionExtents(io_data->GetExtensionInfoMap()->extensions(), |
| 110 request_->url(), new_url)) { |
| 111 int render_process_id, render_view_id; |
| 112 if (ResourceDispatcherHost::RenderViewForRequest( |
| 113 request_, &render_process_id, &render_view_id)) { |
| 114 |
| 115 GlobalRequestID global_id(info->child_id(), info->request_id()); |
| 116 rdh_->MarkAsTransferredNavigation(global_id, request_); |
| 117 |
| 118 content::BrowserThread::PostTask( |
| 119 content::BrowserThread::UI, |
| 120 FROM_HERE, |
| 121 base::Bind(&RequestTransferURLOnUIThread, |
| 122 render_process_id, render_view_id, |
| 123 new_url, GURL(request_->referrer()), CURRENT_TAB, |
| 124 info->frame_id(), global_id)); |
| 125 |
| 126 *defer = true; |
| 127 return true; |
| 128 } |
| 129 } |
| 130 |
| 131 return next_handler_->OnRequestRedirected( |
| 132 request_id, new_url, response, defer); |
| 133 } |
| 134 |
| 135 bool TransferNavigationResourceHandler::OnResponseStarted( |
| 136 int request_id, content::ResourceResponse* response) { |
| 137 return next_handler_->OnResponseStarted(request_id, response); |
| 138 } |
| 139 |
| 140 bool TransferNavigationResourceHandler::OnWillStart(int request_id, |
| 141 const GURL& url, |
| 142 bool* defer) { |
| 143 return next_handler_->OnWillStart(request_id, url, defer); |
| 144 } |
| 145 |
| 146 bool TransferNavigationResourceHandler::OnWillRead(int request_id, |
| 147 net::IOBuffer** buf, |
| 148 int* buf_size, |
| 149 int min_size) { |
| 150 return next_handler_->OnWillRead(request_id, buf, buf_size, min_size); |
| 151 } |
| 152 |
| 153 bool TransferNavigationResourceHandler::OnReadCompleted(int request_id, |
| 154 int* bytes_read) { |
| 155 return next_handler_->OnReadCompleted(request_id, bytes_read); |
| 156 } |
| 157 |
| 158 bool TransferNavigationResourceHandler::OnResponseCompleted( |
| 159 int request_id, |
| 160 const net::URLRequestStatus& status, |
| 161 const std::string& security_info) { |
| 162 return next_handler_->OnResponseCompleted(request_id, status, security_info); |
| 163 } |
| 164 |
| 165 void TransferNavigationResourceHandler::OnRequestClosed() { |
| 166 next_handler_->OnRequestClosed(); |
| 167 } |
OLD | NEW |