Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(232)

Side by Side Diff: content/browser/renderer_host/cross_site_resource_handler.cc

Issue 11414299: Add content/browser/loader/ for resource loading related classes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 <string>
6
7 #include "content/browser/renderer_host/cross_site_resource_handler.h"
8
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "content/browser/renderer_host/render_view_host_delegate.h"
12 #include "content/browser/renderer_host/render_view_host_impl.h"
13 #include "content/browser/renderer_host/resource_request_info_impl.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "content/public/browser/resource_controller.h"
16 #include "content/public/common/resource_response.h"
17 #include "net/http/http_response_headers.h"
18
19 namespace content {
20
21 namespace {
22
23 void OnCrossSiteResponseHelper(int render_process_id,
24 int render_view_id,
25 int request_id) {
26 RenderViewHostImpl* rvh = RenderViewHostImpl::FromID(render_process_id,
27 render_view_id);
28 if (rvh && rvh->GetDelegate()->GetRendererManagementDelegate()) {
29 rvh->GetDelegate()->GetRendererManagementDelegate()->OnCrossSiteResponse(
30 render_process_id, request_id);
31 }
32 }
33
34 } // namespace
35
36 CrossSiteResourceHandler::CrossSiteResourceHandler(
37 scoped_ptr<ResourceHandler> next_handler,
38 int render_process_host_id,
39 int render_view_id,
40 net::URLRequest* request)
41 : LayeredResourceHandler(next_handler.Pass()),
42 render_process_host_id_(render_process_host_id),
43 render_view_id_(render_view_id),
44 request_(request),
45 has_started_response_(false),
46 in_cross_site_transition_(false),
47 request_id_(-1),
48 completed_during_transition_(false),
49 did_defer_(false),
50 completed_status_(),
51 response_(NULL) {
52 }
53
54 CrossSiteResourceHandler::~CrossSiteResourceHandler() {
55 // Cleanup back-pointer stored on the request info.
56 ResourceRequestInfoImpl::ForRequest(request_)->set_cross_site_handler(NULL);
57 }
58
59 bool CrossSiteResourceHandler::OnRequestRedirected(
60 int request_id,
61 const GURL& new_url,
62 ResourceResponse* response,
63 bool* defer) {
64 // We should not have started the transition before being redirected.
65 DCHECK(!in_cross_site_transition_);
66 return next_handler_->OnRequestRedirected(
67 request_id, new_url, response, defer);
68 }
69
70 bool CrossSiteResourceHandler::OnResponseStarted(
71 int request_id,
72 ResourceResponse* response,
73 bool* defer) {
74 // At this point, we know that the response is safe to send back to the
75 // renderer: it is not a download, and it has passed the SSL and safe
76 // browsing checks.
77 // We should not have already started the transition before now.
78 DCHECK(!in_cross_site_transition_);
79 has_started_response_ = true;
80
81 ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request_);
82
83 // If this is a download, just pass the response through without doing a
84 // cross-site check. The renderer will see it is a download and abort the
85 // request.
86 //
87 // Similarly, HTTP 204 (No Content) responses leave us showing the previous
88 // page. We should allow the navigation to finish without running the unload
89 // handler or swapping in the pending RenderViewHost.
90 //
91 // In both cases, the pending RenderViewHost will stick around until the next
92 // cross-site navigation, since we are unable to tell when to destroy it.
93 // See RenderViewHostManager::RendererAbortedProvisionalLoad.
94 if (info->is_download() ||
95 (response->head.headers &&
96 response->head.headers->response_code() == 204)) {
97 return next_handler_->OnResponseStarted(request_id, response, defer);
98 }
99
100 // Tell the renderer to run the onunload event handler.
101 StartCrossSiteTransition(request_id, response);
102
103 // Defer loading until after the onunload event handler has run.
104 did_defer_ = *defer = true;
105 return true;
106 }
107
108 bool CrossSiteResourceHandler::OnReadCompleted(int request_id,
109 int bytes_read,
110 bool* defer) {
111 CHECK(!in_cross_site_transition_);
112 return next_handler_->OnReadCompleted(request_id, bytes_read, defer);
113 }
114
115 bool CrossSiteResourceHandler::OnResponseCompleted(
116 int request_id,
117 const net::URLRequestStatus& status,
118 const std::string& security_info) {
119 if (!in_cross_site_transition_) {
120 if (has_started_response_ ||
121 status.status() != net::URLRequestStatus::FAILED) {
122 // We've already completed the transition or we're canceling the request,
123 // so just pass it through.
124 return next_handler_->OnResponseCompleted(request_id, status,
125 security_info);
126 }
127
128 // An error occured, we should wait now for the cross-site transition,
129 // so that the error message (e.g., 404) can be displayed to the user.
130 // Also continue with the logic below to remember that we completed
131 // during the cross-site transition.
132 StartCrossSiteTransition(request_id, NULL);
133 }
134
135 // We have to buffer the call until after the transition completes.
136 completed_during_transition_ = true;
137 completed_status_ = status;
138 completed_security_info_ = security_info;
139
140 // Return false to tell RDH not to notify the world or clean up the
141 // pending request. We will do so in ResumeResponse.
142 did_defer_ = true;
143 return false;
144 }
145
146 // We can now send the response to the new renderer, which will cause
147 // WebContentsImpl to swap in the new renderer and destroy the old one.
148 void CrossSiteResourceHandler::ResumeResponse() {
149 DCHECK(request_id_ != -1);
150 DCHECK(in_cross_site_transition_);
151 in_cross_site_transition_ = false;
152
153 if (has_started_response_) {
154 // Send OnResponseStarted to the new renderer.
155 DCHECK(response_);
156 bool defer = false;
157 if (!next_handler_->OnResponseStarted(request_id_, response_, &defer)) {
158 controller()->Cancel();
159 } else if (!defer) {
160 // Unpause the request to resume reading. Any further reads will be
161 // directed toward the new renderer.
162 ResumeIfDeferred();
163 }
164 }
165
166 // Remove ourselves from the ExtraRequestInfo.
167 ResourceRequestInfoImpl* info =
168 ResourceRequestInfoImpl::ForRequest(request_);
169 info->set_cross_site_handler(NULL);
170
171 // If the response completed during the transition, notify the next
172 // event handler.
173 if (completed_during_transition_) {
174 if (next_handler_->OnResponseCompleted(request_id_, completed_status_,
175 completed_security_info_)) {
176 ResumeIfDeferred();
177 }
178 }
179 }
180
181 // Prepare to render the cross-site response in a new RenderViewHost, by
182 // telling the old RenderViewHost to run its onunload handler.
183 void CrossSiteResourceHandler::StartCrossSiteTransition(
184 int request_id,
185 ResourceResponse* response) {
186 in_cross_site_transition_ = true;
187 request_id_ = request_id;
188 response_ = response;
189
190 // Store this handler on the ExtraRequestInfo, so that RDH can call our
191 // ResumeResponse method when the close ACK is received.
192 ResourceRequestInfoImpl* info =
193 ResourceRequestInfoImpl::ForRequest(request_);
194 info->set_cross_site_handler(this);
195
196 // Tell the contents responsible for this request that a cross-site response
197 // is starting, so that it can tell its old renderer to run its onunload
198 // handler now. We will wait to hear the corresponding ClosePage_ACK.
199 BrowserThread::PostTask(
200 BrowserThread::UI,
201 FROM_HERE,
202 base::Bind(
203 &OnCrossSiteResponseHelper,
204 render_process_host_id_,
205 render_view_id_,
206 request_id));
207
208 // TODO(creis): If the above call should fail, then we need to notify the IO
209 // thread to proceed anyway, using ResourceDispatcherHost::OnClosePageACK.
210 }
211
212 void CrossSiteResourceHandler::ResumeIfDeferred() {
213 if (did_defer_) {
214 did_defer_ = false;
215 controller()->Resume();
216 }
217 }
218
219 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/renderer_host/cross_site_resource_handler.h ('k') | content/browser/renderer_host/doomed_resource_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698