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

Side by Side Diff: content/browser/loader/intercepting_resource_handler.cc

Issue 2005273002: Move MimeTypeResourceHandler before ThrottlingResourceHandler (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed issue in ResourceDispatcherHostTests Created 4 years, 6 months 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/loader/mime_type_resource_handler.h" 5 #include "content/browser/loader/intercepting_resource_handler.h"
6 6
7 #include <utility> 7 #include <utility>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/location.h" 11 #include "base/location.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/metrics/histogram_macros.h" 13 #include "base/metrics/histogram_macros.h"
14 #include "base/single_thread_task_runner.h" 14 #include "base/single_thread_task_runner.h"
15 #include "base/strings/string_util.h" 15 #include "base/strings/string_util.h"
16 #include "base/threading/thread_task_runner_handle.h" 16 #include "base/threading/thread_task_runner_handle.h"
17 #include "components/mime_util/mime_util.h" 17 #include "components/mime_util/mime_util.h"
18 #include "content/browser/download/download_resource_handler.h" 18 #include "content/browser/download/download_resource_handler.h"
19 #include "content/browser/download/download_stats.h" 19 #include "content/browser/download/download_stats.h"
20 #include "content/browser/loader/resource_dispatcher_host_impl.h" 20 #include "content/browser/loader/resource_dispatcher_host_impl.h"
21 #include "content/browser/loader/resource_request_info_impl.h" 21 #include "content/browser/loader/resource_request_info_impl.h"
22 #include "content/browser/loader/stream_resource_handler.h" 22 #include "content/browser/loader/stream_resource_handler.h"
23 #include "content/public/browser/content_browser_client.h" 23 #include "content/public/browser/content_browser_client.h"
24 #include "content/public/browser/download_item.h" 24 #include "content/public/browser/download_item.h"
25 #include "content/public/browser/download_save_info.h" 25 #include "content/public/browser/download_save_info.h"
26 #include "content/public/browser/download_url_parameters.h" 26 #include "content/public/browser/download_url_parameters.h"
27 #include "content/public/browser/plugin_service.h" 27 #include "content/public/browser/plugin_service.h"
28 #include "content/public/browser/resource_context.h" 28 #include "content/public/browser/resource_context.h"
29 #include "content/public/browser/resource_dispatcher_host_delegate.h" 29 #include "content/public/browser/resource_dispatcher_host_delegate.h"
30 #include "content/public/common/resource_response.h" 30 #include "content/public/common/resource_response.h"
31 #include "content/public/common/webplugininfo.h" 31 #include "content/public/common/webplugininfo.h"
32 #include "net/base/io_buffer.h" 32 #include "net/base/io_buffer.h"
33 #include "net/base/mime_sniffer.h"
34 #include "net/base/mime_util.h" 33 #include "net/base/mime_util.h"
35 #include "net/base/net_errors.h"
36 #include "net/http/http_content_disposition.h" 34 #include "net/http/http_content_disposition.h"
37 #include "net/http/http_response_headers.h" 35 #include "net/http/http_response_headers.h"
38 #include "net/url_request/url_request.h"
39 36
40 namespace content { 37 namespace content {
41 38
42 namespace { 39 InterceptingResourceHandler::InterceptingResourceHandler(
43
44 const char kAcceptHeader[] = "Accept";
45 const char kFrameAcceptHeader[] =
46 "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,"
47 "*/*;q=0.8";
48 const char kStylesheetAcceptHeader[] = "text/css,*/*;q=0.1";
49 const char kImageAcceptHeader[] = "image/webp,image/*,*/*;q=0.8";
50 const char kDefaultAcceptHeader[] = "*/*";
51
52 // Used to write into an existing IOBuffer at a given offset.
53 class DependentIOBuffer : public net::WrappedIOBuffer {
54 public:
55 DependentIOBuffer(net::IOBuffer* buf, int offset)
56 : net::WrappedIOBuffer(buf->data() + offset),
57 buf_(buf) {
58 }
59
60 private:
61 ~DependentIOBuffer() override {}
62
63 scoped_refptr<net::IOBuffer> buf_;
64 };
65
66 } // namespace
67
68 MimeTypeResourceHandler::MimeTypeResourceHandler(
69 std::unique_ptr<ResourceHandler> next_handler, 40 std::unique_ptr<ResourceHandler> next_handler,
70 ResourceDispatcherHostImpl* host, 41 ResourceDispatcherHostImpl* host,
71 PluginService* plugin_service, 42 PluginService* plugin_service,
72 net::URLRequest* request) 43 net::URLRequest* request)
73 : LayeredResourceHandler(request, std::move(next_handler)), 44 : LayeredResourceHandler(request, std::move(next_handler)),
74 state_(STATE_STARTING), 45 state_(State::STARTING),
75 host_(host), 46 host_(host),
76 #if defined(ENABLE_PLUGINS) 47 #if defined(ENABLE_PLUGINS)
77 plugin_service_(plugin_service), 48 plugin_service_(plugin_service),
78 #endif 49 #endif
79 read_buffer_size_(0), 50 switched_handler_(false),
80 bytes_read_(0),
81 must_download_(false), 51 must_download_(false),
82 must_download_is_set_(false), 52 must_download_is_set_(false),
53 bytes_read_(0),
83 weak_ptr_factory_(this) { 54 weak_ptr_factory_(this) {
84 } 55 }
85 56
86 MimeTypeResourceHandler::~MimeTypeResourceHandler() { 57 InterceptingResourceHandler::~InterceptingResourceHandler() {}
58
59 bool InterceptingResourceHandler::OnResponseStarted(ResourceResponse* response,
60 bool* defer) {
61 if (response->head.headers.get() &&
62 response->head.headers->response_code() == 304) {
asanka 2016/06/22 20:26:53 For HTTP(-like) responses, this class does the fol
mmenke 2016/06/22 20:31:18 If this is an <a download> link, but we get a 4xx
asanka 2016/06/23 02:26:17 <a download>s are explicit downloads and don't use
clamy 2016/06/28 16:20:41 I've moved the interception choice case to the Mim
clamy 2016/06/29 13:35:57 It appears that one of teh unit tests is (Forbidde
63 state_ = State::DONE;
64 return next_handler_->OnResponseStarted(response, defer);
65 }
66
67 response_ = response;
68
69 return MakeHandlerChoice(defer);
87 } 70 }
88 71
89 void MimeTypeResourceHandler::SetController(ResourceController* controller) { 72 bool InterceptingResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
90 ResourceHandler::SetController(controller); 73 int* buf_size,
91 74 int min_size) {
92 // Downstream handlers see us as their ResourceController, which allows us to 75 if (state_ == State::DONE)
93 // consume part or all of the resource response, and then later replay it to
94 // downstream handler.
95 DCHECK(next_handler_.get());
96 next_handler_->SetController(this);
97 }
98
99 bool MimeTypeResourceHandler::OnResponseStarted(ResourceResponse* response,
100 bool* defer) {
101 response_ = response;
102
103 // A 304 response should not contain a Content-Type header (RFC 7232 section
104 // 4.1). The following code may incorrectly attempt to add a Content-Type to
105 // the response, and so must be skipped for 304 responses.
106 if (!(response_->head.headers.get() &&
107 response_->head.headers->response_code() == 304)) {
108 if (ShouldSniffContent()) {
109 state_ = STATE_BUFFERING;
110 return true;
111 }
112
113 if (response_->head.mime_type.empty()) {
114 // Ugg. The server told us not to sniff the content but didn't give us
115 // a mime type. What's a browser to do? Turns out, we're supposed to
116 // treat the response as "text/plain". This is the most secure option.
117 response_->head.mime_type.assign("text/plain");
118 }
119
120 // Treat feed types as text/plain.
121 if (response_->head.mime_type == "application/rss+xml" ||
122 response_->head.mime_type == "application/atom+xml") {
123 response_->head.mime_type.assign("text/plain");
124 }
125 }
126
127 state_ = STATE_PROCESSING;
128 return ProcessResponse(defer);
129 }
130
131 bool MimeTypeResourceHandler::OnWillStart(const GURL& url, bool* defer) {
132 const char* accept_value = nullptr;
133 switch (GetRequestInfo()->GetResourceType()) {
134 case RESOURCE_TYPE_MAIN_FRAME:
135 case RESOURCE_TYPE_SUB_FRAME:
136 accept_value = kFrameAcceptHeader;
137 break;
138 case RESOURCE_TYPE_STYLESHEET:
139 accept_value = kStylesheetAcceptHeader;
140 break;
141 case RESOURCE_TYPE_IMAGE:
142 accept_value = kImageAcceptHeader;
143 break;
144 case RESOURCE_TYPE_SCRIPT:
145 case RESOURCE_TYPE_FONT_RESOURCE:
146 case RESOURCE_TYPE_SUB_RESOURCE:
147 case RESOURCE_TYPE_OBJECT:
148 case RESOURCE_TYPE_MEDIA:
149 case RESOURCE_TYPE_WORKER:
150 case RESOURCE_TYPE_SHARED_WORKER:
151 case RESOURCE_TYPE_PREFETCH:
152 case RESOURCE_TYPE_FAVICON:
153 case RESOURCE_TYPE_XHR:
154 case RESOURCE_TYPE_PING:
155 case RESOURCE_TYPE_SERVICE_WORKER:
156 case RESOURCE_TYPE_CSP_REPORT:
157 case RESOURCE_TYPE_PLUGIN_RESOURCE:
158 accept_value = kDefaultAcceptHeader;
159 break;
160 case RESOURCE_TYPE_LAST_TYPE:
161 NOTREACHED();
162 break;
163 }
164
165 // The false parameter prevents overwriting an existing accept header value,
166 // which is needed because JS can manually set an accept header on an XHR.
167 request()->SetExtraRequestHeaderByName(kAcceptHeader, accept_value, false);
168 return next_handler_->OnWillStart(url, defer);
169 }
170
171 bool MimeTypeResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
172 int* buf_size,
173 int min_size) {
174 if (state_ == STATE_STREAMING)
175 return next_handler_->OnWillRead(buf, buf_size, min_size); 76 return next_handler_->OnWillRead(buf, buf_size, min_size);
176 77
78 DCHECK_EQ(State::STARTING, state_);
177 DCHECK_EQ(-1, min_size); 79 DCHECK_EQ(-1, min_size);
178 80
179 if (read_buffer_.get()) { 81 if (!next_handler_->OnWillRead(buf, buf_size, min_size))
180 CHECK_LT(bytes_read_, read_buffer_size_); 82 return false;
181 *buf = new DependentIOBuffer(read_buffer_.get(), bytes_read_);
182 *buf_size = read_buffer_size_ - bytes_read_;
183 } else {
184 if (!next_handler_->OnWillRead(buf, buf_size, min_size))
185 return false;
186 83
187 read_buffer_ = *buf; 84 read_buffer_ = *buf;
188 read_buffer_size_ = *buf_size;
189 DCHECK_GE(read_buffer_size_, net::kMaxBytesToSniff * 2);
190 }
191 return true; 85 return true;
192 } 86 }
193 87
194 bool MimeTypeResourceHandler::OnReadCompleted(int bytes_read, bool* defer) { 88 bool InterceptingResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
195 if (state_ == STATE_STREAMING) 89 if (state_ == State::DONE)
196 return next_handler_->OnReadCompleted(bytes_read, defer); 90 return next_handler_->OnReadCompleted(bytes_read, defer);
197 91
198 DCHECK_EQ(state_, STATE_BUFFERING); 92 DCHECK_EQ(State::WAITING_FOR_BUFFER_COPY, state_);
199 bytes_read_ += bytes_read; 93 bytes_read_ += bytes_read;
94 if (!CopyReadBufferToNextHandler())
95 return false;
200 96
201 if (!DetermineMimeType() && (bytes_read > 0)) 97 return next_handler_->OnReadCompleted(bytes_read, defer);
202 return true; // Needs more data, so keep buffering.
203
204 state_ = STATE_PROCESSING;
205 return ProcessResponse(defer);
206 } 98 }
207 99
208 void MimeTypeResourceHandler::OnResponseCompleted( 100 bool InterceptingResourceHandler::MakeHandlerChoice(bool* defer) {
209 const net::URLRequestStatus& status, 101 if (!SelectNextHandler(defer))
210 const std::string& security_info, 102 return false;
211 bool* defer) {
212 // Upon completion, act like a pass-through handler in case the downstream
213 // handler defers OnResponseCompleted.
214 state_ = STATE_STREAMING;
215 103
216 next_handler_->OnResponseCompleted(status, security_info, defer); 104 if (*defer)
217 } 105 return true;
218
219 void MimeTypeResourceHandler::Resume() {
220 switch (state_) {
221 case STATE_BUFFERING:
222 case STATE_PROCESSING:
223 NOTREACHED();
224 break;
225 case STATE_REPLAYING:
226 base::ThreadTaskRunnerHandle::Get()->PostTask(
227 FROM_HERE,
228 base::Bind(&MimeTypeResourceHandler::CallReplayReadCompleted,
229 weak_ptr_factory_.GetWeakPtr()));
230 break;
231 case STATE_STARTING:
232 case STATE_STREAMING:
233 controller()->Resume();
234 break;
235 }
236 }
237
238 void MimeTypeResourceHandler::Cancel() {
239 controller()->Cancel();
240 }
241
242 void MimeTypeResourceHandler::CancelAndIgnore() {
243 controller()->CancelAndIgnore();
244 }
245
246 void MimeTypeResourceHandler::CancelWithError(int error_code) {
247 controller()->CancelWithError(error_code);
248 }
249
250 bool MimeTypeResourceHandler::ProcessResponse(bool* defer) {
251 DCHECK_EQ(STATE_PROCESSING, state_);
252
253 // TODO(darin): Stop special-casing 304 responses.
254 if (!(response_->head.headers.get() &&
255 response_->head.headers->response_code() == 304)) {
256 if (!SelectNextHandler(defer))
257 return false;
258 if (*defer)
259 return true;
260 }
261
262 state_ = STATE_REPLAYING;
263 106
264 if (!next_handler_->OnResponseStarted(response_.get(), defer)) 107 if (!next_handler_->OnResponseStarted(response_.get(), defer))
265 return false; 108 return false;
266 109
267 if (!read_buffer_.get()) { 110 state_ = read_buffer_ && switched_handler_ ? State::WAITING_FOR_BUFFER_COPY
268 state_ = STATE_STREAMING; 111 : State::DONE;
269 return true;
270 }
271
272 if (!*defer)
273 return ReplayReadCompleted(defer);
274
275 return true; 112 return true;
276 } 113 }
277 114
278 bool MimeTypeResourceHandler::ShouldSniffContent() { 115 bool InterceptingResourceHandler::SelectPluginHandler(bool* defer,
279 const std::string& mime_type = response_->head.mime_type; 116 bool* handled_by_plugin) {
280
281 std::string content_type_options;
282 request()->GetResponseHeaderByName("x-content-type-options",
283 &content_type_options);
284
285 bool sniffing_blocked =
286 base::LowerCaseEqualsASCII(content_type_options, "nosniff");
287 bool we_would_like_to_sniff =
288 net::ShouldSniffMimeType(request()->url(), mime_type);
289
290 if (!sniffing_blocked && we_would_like_to_sniff) {
291 // We're going to look at the data before deciding what the content type
292 // is. That means we need to delay sending the ResponseStarted message
293 // over the IPC channel.
294 VLOG(1) << "To buffer: " << request()->url().spec();
295 return true;
296 }
297
298 return false;
299 }
300
301 bool MimeTypeResourceHandler::DetermineMimeType() {
302 DCHECK_EQ(STATE_BUFFERING, state_);
303
304 const std::string& type_hint = response_->head.mime_type;
305
306 std::string new_type;
307 bool made_final_decision =
308 net::SniffMimeType(read_buffer_->data(), bytes_read_, request()->url(),
309 type_hint, &new_type);
310
311 // SniffMimeType() returns false if there is not enough data to determine
312 // the mime type. However, even if it returns false, it returns a new type
313 // that is probably better than the current one.
314 response_->head.mime_type.assign(new_type);
315
316 return made_final_decision;
317 }
318
319 bool MimeTypeResourceHandler::SelectPluginHandler(bool* defer,
320 bool* handled_by_plugin) {
321 *handled_by_plugin = false; 117 *handled_by_plugin = false;
322 #if defined(ENABLE_PLUGINS) 118 #if defined(ENABLE_PLUGINS)
323 ResourceRequestInfoImpl* info = GetRequestInfo(); 119 ResourceRequestInfoImpl* info = GetRequestInfo();
324 bool allow_wildcard = false; 120 bool allow_wildcard = false;
325 bool stale; 121 bool stale;
326 WebPluginInfo plugin; 122 WebPluginInfo plugin;
327 bool has_plugin = plugin_service_->GetPluginInfo( 123 bool has_plugin = plugin_service_->GetPluginInfo(
328 info->GetChildID(), info->GetRenderFrameID(), info->GetContext(), 124 info->GetChildID(), info->GetRenderFrameID(), info->GetContext(),
329 request()->url(), GURL(), response_->head.mime_type, allow_wildcard, 125 request()->url(), GURL(), response_->head.mime_type, allow_wildcard,
330 &stale, &plugin, NULL); 126 &stale, &plugin, NULL);
331 127
332 if (stale) { 128 if (stale) {
129 state_ = State::WAITING_FOR_PLUGINS;
130
333 // Refresh the plugins asynchronously. 131 // Refresh the plugins asynchronously.
334 plugin_service_->GetPlugins( 132 plugin_service_->GetPlugins(
335 base::Bind(&MimeTypeResourceHandler::OnPluginsLoaded, 133 base::Bind(&InterceptingResourceHandler::OnPluginsLoaded,
336 weak_ptr_factory_.GetWeakPtr())); 134 weak_ptr_factory_.GetWeakPtr()));
337 request()->LogBlockedBy("MimeTypeResourceHandler"); 135 request()->LogBlockedBy("InterceptingResourceHandler");
338 *defer = true; 136 *defer = true;
339 return true; 137 return true;
340 } 138 }
341 139
342 if (has_plugin && plugin.type != WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN) { 140 if (has_plugin && plugin.type != WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN) {
343 *handled_by_plugin = true; 141 *handled_by_plugin = true;
344 return true; 142 return true;
345 } 143 }
346 144
347 // Attempt to intercept the request as a stream. 145 // Attempt to intercept the request as a stream.
348 base::FilePath plugin_path; 146 base::FilePath plugin_path;
349 if (has_plugin) 147 if (has_plugin)
350 plugin_path = plugin.path; 148 plugin_path = plugin.path;
351 std::string payload; 149 std::string payload;
352 std::unique_ptr<ResourceHandler> handler(host_->MaybeInterceptAsStream( 150 std::unique_ptr<ResourceHandler> handler(host_->MaybeInterceptAsStream(
353 plugin_path, request(), response_.get(), &payload)); 151 plugin_path, request(), response_.get(), &payload));
354 if (handler) { 152 if (handler) {
355 *handled_by_plugin = true; 153 *handled_by_plugin = true;
356 return UseAlternateNextHandler(std::move(handler), payload); 154 return UseAlternateNextHandler(std::move(handler), payload);
357 } 155 }
358 #endif 156 #endif
359 return true; 157 return true;
360 } 158 }
361 159
362 bool MimeTypeResourceHandler::SelectNextHandler(bool* defer) { 160 bool InterceptingResourceHandler::SelectNextHandler(bool* defer) {
363 DCHECK(!response_->head.mime_type.empty()); 161 DCHECK(!response_->head.mime_type.empty());
364 162
365 ResourceRequestInfoImpl* info = GetRequestInfo(); 163 ResourceRequestInfoImpl* info = GetRequestInfo();
366 const std::string& mime_type = response_->head.mime_type; 164 const std::string& mime_type = response_->head.mime_type;
367 165
368 // https://crbug.com/568184 - Temporary hack to track servers that aren't 166 // https://crbug.com/568184 - Temporary hack to track servers that aren't
369 // setting Content-Disposition when sending x-x509-user-cert and expecting 167 // setting Content-Disposition when sending x-x509-user-cert and expecting
370 // the browser to automatically install certificates; this is being 168 // the browser to automatically install certificates; this is being
371 // deprecated and will be removed upon full <keygen> removal. 169 // deprecated and will be removed upon full <keygen> removal.
372 if (mime_type == "application/x-x509-user-cert") { 170 if (mime_type == "application/x-x509-user-cert") {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 207
410 // Install download handler 208 // Install download handler
411 info->set_is_download(true); 209 info->set_is_download(true);
412 std::unique_ptr<ResourceHandler> handler( 210 std::unique_ptr<ResourceHandler> handler(
413 host_->CreateResourceHandlerForDownload(request(), 211 host_->CreateResourceHandlerForDownload(request(),
414 true, // is_content_initiated 212 true, // is_content_initiated
415 must_download)); 213 must_download));
416 return UseAlternateNextHandler(std::move(handler), std::string()); 214 return UseAlternateNextHandler(std::move(handler), std::string());
417 } 215 }
418 216
419 bool MimeTypeResourceHandler::UseAlternateNextHandler( 217 bool InterceptingResourceHandler::UseAlternateNextHandler(
420 std::unique_ptr<ResourceHandler> new_handler, 218 std::unique_ptr<ResourceHandler> new_handler,
421 const std::string& payload_for_old_handler) { 219 const std::string& payload_for_old_handler) {
422 if (response_->head.headers.get() && // Can be NULL if FTP. 220 if (response_->head.headers.get() && // Can be NULL if FTP.
423 response_->head.headers->response_code() / 100 != 2) { 221 response_->head.headers->response_code() / 100 != 2) {
424 // The response code indicates that this is an error page, but we don't 222 // The response code indicates that this is an error page, but we don't
425 // know how to display the content. We follow Firefox here and show our 223 // know how to display the content. We follow Firefox here and show our
426 // own error page instead of triggering a download. 224 // own error page instead of triggering a download.
427 // TODO(abarth): We should abstract the response_code test, but this kind 225 // TODO(abarth): We should abstract the response_code test, but this kind
428 // of check is scattered throughout our codebase. 226 // of check is scattered throughout our codebase.
429 request()->CancelWithError(net::ERR_INVALID_RESPONSE); 227 request()->CancelWithError(net::ERR_INVALID_RESPONSE);
(...skipping 10 matching lines...) Expand all
440 // not trigger when switching handlers. 238 // not trigger when switching handlers.
441 DCHECK(!defer_ignored); 239 DCHECK(!defer_ignored);
442 if (payload_for_old_handler.empty()) { 240 if (payload_for_old_handler.empty()) {
443 net::URLRequestStatus status(net::URLRequestStatus::CANCELED, 241 net::URLRequestStatus status(net::URLRequestStatus::CANCELED,
444 net::ERR_ABORTED); 242 net::ERR_ABORTED);
445 next_handler_->OnResponseCompleted(status, std::string(), &defer_ignored); 243 next_handler_->OnResponseCompleted(status, std::string(), &defer_ignored);
446 DCHECK(!defer_ignored); 244 DCHECK(!defer_ignored);
447 } else { 245 } else {
448 scoped_refptr<net::IOBuffer> buf; 246 scoped_refptr<net::IOBuffer> buf;
449 int size = 0; 247 int size = 0;
450
451 next_handler_->OnWillRead(&buf, &size, -1); 248 next_handler_->OnWillRead(&buf, &size, -1);
asanka 2016/06/22 20:26:53 Is this correct? It seems that the old handler cou
clamy 2016/06/28 16:20:41 I'm now doing a OnReadCompleted of size 0 so that
452 CHECK_GE(size, static_cast<int>(payload_for_old_handler.length())); 249 CHECK_GE(size, static_cast<int>(payload_for_old_handler.length()));
453
454 memcpy(buf->data(), payload_for_old_handler.c_str(), 250 memcpy(buf->data(), payload_for_old_handler.c_str(),
455 payload_for_old_handler.length()); 251 payload_for_old_handler.length());
456
457 next_handler_->OnReadCompleted(payload_for_old_handler.length(), 252 next_handler_->OnReadCompleted(payload_for_old_handler.length(),
458 &defer_ignored); 253 &defer_ignored);
459 DCHECK(!defer_ignored); 254 DCHECK(!defer_ignored);
460 255
461 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); 256 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
462 next_handler_->OnResponseCompleted(status, std::string(), &defer_ignored); 257 next_handler_->OnResponseCompleted(status, std::string(), &defer_ignored);
463 DCHECK(!defer_ignored); 258 DCHECK(!defer_ignored);
464 } 259 }
465 260
466 // This is handled entirely within the new ResourceHandler, so just reset the 261 // This is handled entirely within the new ResourceHandler, so just reset the
467 // original ResourceHandler. 262 // original ResourceHandler.
468 next_handler_ = std::move(new_handler); 263 next_handler_ = std::move(new_handler);
469 next_handler_->SetController(this); 264 next_handler_->SetController(controller());
470 265
471 return CopyReadBufferToNextHandler(); 266 switched_handler_ = true;
267
268 return true;
472 } 269 }
473 270
474 bool MimeTypeResourceHandler::ReplayReadCompleted(bool* defer) { 271 bool InterceptingResourceHandler::MustDownload() {
475 DCHECK(read_buffer_.get());
476
477 bool result = next_handler_->OnReadCompleted(bytes_read_, defer);
478
479 read_buffer_ = NULL;
480 read_buffer_size_ = 0;
481 bytes_read_ = 0;
482
483 state_ = STATE_STREAMING;
484
485 return result;
486 }
487
488 void MimeTypeResourceHandler::CallReplayReadCompleted() {
489 bool defer = false;
490 if (!ReplayReadCompleted(&defer)) {
491 controller()->Cancel();
492 } else if (!defer) {
493 state_ = STATE_STREAMING;
494 controller()->Resume();
495 }
496 }
497
498 bool MimeTypeResourceHandler::MustDownload() {
499 if (must_download_is_set_) 272 if (must_download_is_set_)
500 return must_download_; 273 return must_download_;
501 274
502 must_download_is_set_ = true; 275 must_download_is_set_ = true;
503 276
504 std::string disposition; 277 std::string disposition;
505 request()->GetResponseHeaderByName("content-disposition", &disposition); 278 request()->GetResponseHeaderByName("content-disposition", &disposition);
506 if (!disposition.empty() && 279 if (!disposition.empty() &&
507 net::HttpContentDisposition(disposition, std::string()).is_attachment()) { 280 net::HttpContentDisposition(disposition, std::string()).is_attachment()) {
508 must_download_ = true; 281 must_download_ = true;
509 } else if (host_->delegate() && 282 } else if (host_->delegate() &&
510 host_->delegate()->ShouldForceDownloadResource( 283 host_->delegate()->ShouldForceDownloadResource(
511 request()->url(), response_->head.mime_type)) { 284 request()->url(), response_->head.mime_type)) {
512 must_download_ = true; 285 must_download_ = true;
513 } else { 286 } else {
514 must_download_ = false; 287 must_download_ = false;
515 } 288 }
516 289
517 return must_download_; 290 return must_download_;
518 } 291 }
519 292
520 bool MimeTypeResourceHandler::CopyReadBufferToNextHandler() { 293 void InterceptingResourceHandler::OnPluginsLoaded(
521 if (!read_buffer_.get()) 294 const std::vector<WebPluginInfo>& plugins) {
522 return true; 295 request()->LogUnblocked();
296 bool defer = false;
297 if (!MakeHandlerChoice(&defer)) {
298 controller()->Cancel();
299 } else if (!defer) {
300 controller()->Resume();
301 }
302 }
523 303
304 bool InterceptingResourceHandler::CopyReadBufferToNextHandler() {
305 DCHECK(read_buffer_.get());
524 scoped_refptr<net::IOBuffer> buf; 306 scoped_refptr<net::IOBuffer> buf;
525 int buf_len = 0; 307 int buf_len = 0;
526 if (!next_handler_->OnWillRead(&buf, &buf_len, bytes_read_)) 308 if (!next_handler_->OnWillRead(&buf, &buf_len, bytes_read_))
527 return false; 309 return false;
528 310
529 CHECK((buf_len >= bytes_read_) && (bytes_read_ >= 0)); 311 CHECK((buf_len >= bytes_read_) && (bytes_read_ >= 0));
530 memcpy(buf->data(), read_buffer_->data(), bytes_read_); 312 memcpy(buf->data(), read_buffer_->data(), bytes_read_);
313 state_ = State::DONE;
531 return true; 314 return true;
532 } 315 }
533 316
534 void MimeTypeResourceHandler::OnPluginsLoaded(
535 const std::vector<WebPluginInfo>& plugins) {
536 request()->LogUnblocked();
537 bool defer = false;
538 if (!ProcessResponse(&defer)) {
539 controller()->Cancel();
540 } else if (!defer) {
541 controller()->Resume();
542 }
543 }
544
545 } // namespace content 317 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698