OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/buffered_resource_handler.h" | 5 #include "content/browser/loader/buffered_resource_handler.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
12 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
13 #include "content/browser/download/download_resource_handler.h" | 13 #include "content/browser/download/download_resource_handler.h" |
14 #include "content/browser/download/download_stats.h" | 14 #include "content/browser/download/download_stats.h" |
15 #include "content/browser/loader/certificate_resource_handler.h" | 15 #include "content/browser/loader/certificate_resource_handler.h" |
16 #include "content/browser/loader/resource_dispatcher_host_impl.h" | 16 #include "content/browser/loader/resource_dispatcher_host_impl.h" |
17 #include "content/browser/loader/resource_request_info_impl.h" | 17 #include "content/browser/loader/resource_request_info_impl.h" |
| 18 #include "content/browser/loader/stream_resource_handler.h" |
18 #include "content/browser/plugin_service_impl.h" | 19 #include "content/browser/plugin_service_impl.h" |
19 #include "content/public/browser/content_browser_client.h" | 20 #include "content/public/browser/content_browser_client.h" |
20 #include "content/public/browser/download_item.h" | 21 #include "content/public/browser/download_item.h" |
21 #include "content/public/browser/download_save_info.h" | 22 #include "content/public/browser/download_save_info.h" |
22 #include "content/public/browser/download_url_parameters.h" | 23 #include "content/public/browser/download_url_parameters.h" |
23 #include "content/public/browser/resource_context.h" | 24 #include "content/public/browser/resource_context.h" |
24 #include "content/public/browser/resource_dispatcher_host_delegate.h" | 25 #include "content/public/browser/resource_dispatcher_host_delegate.h" |
25 #include "content/public/common/resource_response.h" | 26 #include "content/public/common/resource_response.h" |
26 #include "content/public/common/webplugininfo.h" | 27 #include "content/public/common/webplugininfo.h" |
27 #include "net/base/io_buffer.h" | 28 #include "net/base/io_buffer.h" |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 DCHECK(!response_->head.mime_type.empty()); | 299 DCHECK(!response_->head.mime_type.empty()); |
299 | 300 |
300 ResourceRequestInfoImpl* info = GetRequestInfo(); | 301 ResourceRequestInfoImpl* info = GetRequestInfo(); |
301 const std::string& mime_type = response_->head.mime_type; | 302 const std::string& mime_type = response_->head.mime_type; |
302 | 303 |
303 if (net::IsSupportedCertificateMimeType(mime_type)) { | 304 if (net::IsSupportedCertificateMimeType(mime_type)) { |
304 // Install certificate file. | 305 // Install certificate file. |
305 info->set_is_download(true); | 306 info->set_is_download(true); |
306 scoped_ptr<ResourceHandler> handler( | 307 scoped_ptr<ResourceHandler> handler( |
307 new CertificateResourceHandler(request())); | 308 new CertificateResourceHandler(request())); |
308 return UseAlternateNextHandler(handler.Pass()); | 309 return UseAlternateNextHandler(handler.Pass(), std::string()); |
309 } | 310 } |
310 | 311 |
311 if (!info->allow_download()) | 312 if (!info->allow_download()) |
312 return true; | 313 return true; |
313 | 314 |
314 bool must_download = MustDownload(); | 315 bool must_download = MustDownload(); |
315 if (!must_download) { | 316 if (!must_download) { |
316 if (net::IsSupportedMimeType(mime_type)) | 317 if (net::IsSupportedMimeType(mime_type)) |
317 return true; | 318 return true; |
318 | 319 |
| 320 std::string payload; |
319 scoped_ptr<ResourceHandler> handler( | 321 scoped_ptr<ResourceHandler> handler( |
320 host_->MaybeInterceptAsStream(request(), response_.get())); | 322 host_->MaybeInterceptAsStream(request(), response_.get(), &payload)); |
321 if (handler) | 323 if (handler) { |
322 return UseAlternateNextHandler(handler.Pass()); | 324 return UseAlternateNextHandler(handler.Pass(), payload); |
| 325 } |
323 | 326 |
324 #if defined(ENABLE_PLUGINS) | 327 #if defined(ENABLE_PLUGINS) |
325 bool stale; | 328 bool stale; |
326 bool has_plugin = HasSupportingPlugin(&stale); | 329 bool has_plugin = HasSupportingPlugin(&stale); |
327 if (stale) { | 330 if (stale) { |
328 // Refresh the plugins asynchronously. | 331 // Refresh the plugins asynchronously. |
329 PluginServiceImpl::GetInstance()->GetPlugins( | 332 PluginServiceImpl::GetInstance()->GetPlugins( |
330 base::Bind(&BufferedResourceHandler::OnPluginsLoaded, | 333 base::Bind(&BufferedResourceHandler::OnPluginsLoaded, |
331 weak_ptr_factory_.GetWeakPtr())); | 334 weak_ptr_factory_.GetWeakPtr())); |
332 request()->LogBlockedBy("BufferedResourceHandler"); | 335 request()->LogBlockedBy("BufferedResourceHandler"); |
333 *defer = true; | 336 *defer = true; |
334 return true; | 337 return true; |
335 } | 338 } |
336 if (has_plugin) | 339 if (has_plugin) |
337 return true; | 340 return true; |
338 #endif | 341 #endif |
339 } | 342 } |
340 | 343 |
341 // Install download handler | 344 // Install download handler |
342 info->set_is_download(true); | 345 info->set_is_download(true); |
343 scoped_ptr<ResourceHandler> handler( | 346 scoped_ptr<ResourceHandler> handler( |
344 host_->CreateResourceHandlerForDownload( | 347 host_->CreateResourceHandlerForDownload( |
345 request(), | 348 request(), |
346 true, // is_content_initiated | 349 true, // is_content_initiated |
347 must_download, | 350 must_download, |
348 content::DownloadItem::kInvalidId, | 351 content::DownloadItem::kInvalidId, |
349 scoped_ptr<DownloadSaveInfo>(new DownloadSaveInfo()), | 352 scoped_ptr<DownloadSaveInfo>(new DownloadSaveInfo()), |
350 DownloadUrlParameters::OnStartedCallback())); | 353 DownloadUrlParameters::OnStartedCallback())); |
351 return UseAlternateNextHandler(handler.Pass()); | 354 return UseAlternateNextHandler(handler.Pass(), std::string()); |
352 } | 355 } |
353 | 356 |
354 bool BufferedResourceHandler::UseAlternateNextHandler( | 357 bool BufferedResourceHandler::UseAlternateNextHandler( |
355 scoped_ptr<ResourceHandler> new_handler) { | 358 scoped_ptr<ResourceHandler> new_handler, |
| 359 const std::string& payload_for_old_handler) { |
356 if (response_->head.headers.get() && // Can be NULL if FTP. | 360 if (response_->head.headers.get() && // Can be NULL if FTP. |
357 response_->head.headers->response_code() / 100 != 2) { | 361 response_->head.headers->response_code() / 100 != 2) { |
358 // The response code indicates that this is an error page, but we don't | 362 // The response code indicates that this is an error page, but we don't |
359 // know how to display the content. We follow Firefox here and show our | 363 // know how to display the content. We follow Firefox here and show our |
360 // own error page instead of triggering a download. | 364 // own error page instead of triggering a download. |
361 // TODO(abarth): We should abstract the response_code test, but this kind | 365 // TODO(abarth): We should abstract the response_code test, but this kind |
362 // of check is scattered throughout our codebase. | 366 // of check is scattered throughout our codebase. |
363 request()->CancelWithError(net::ERR_INVALID_RESPONSE); | 367 request()->CancelWithError(net::ERR_INVALID_RESPONSE); |
364 return false; | 368 return false; |
365 } | 369 } |
366 | 370 |
367 // Inform the original ResourceHandler that this will be handled entirely by | 371 // Inform the original ResourceHandler that this will be handled entirely by |
368 // the new ResourceHandler. | 372 // the new ResourceHandler. |
369 // TODO(darin): We should probably check the return values of these. | 373 // TODO(darin): We should probably check the return values of these. |
370 bool defer_ignored = false; | 374 bool defer_ignored = false; |
371 next_handler_->OnResponseStarted(response_.get(), &defer_ignored); | 375 next_handler_->OnResponseStarted(response_.get(), &defer_ignored); |
372 // Although deferring OnResponseStarted is legal, the only downstream handler | 376 // Although deferring OnResponseStarted is legal, the only downstream handler |
373 // which does so is CrossSiteResourceHandler. Cross-site transitions should | 377 // which does so is CrossSiteResourceHandler. Cross-site transitions should |
374 // not trigger when switching handlers. | 378 // not trigger when switching handlers. |
375 DCHECK(!defer_ignored); | 379 DCHECK(!defer_ignored); |
376 net::URLRequestStatus status(net::URLRequestStatus::CANCELED, | 380 if (payload_for_old_handler.empty()) { |
377 net::ERR_ABORTED); | 381 net::URLRequestStatus status(net::URLRequestStatus::CANCELED, |
378 next_handler_->OnResponseCompleted(status, std::string(), &defer_ignored); | 382 net::ERR_ABORTED); |
379 DCHECK(!defer_ignored); | 383 next_handler_->OnResponseCompleted(status, std::string(), &defer_ignored); |
| 384 DCHECK(!defer_ignored); |
| 385 } else { |
| 386 scoped_refptr<net::IOBuffer> buf; |
| 387 int size = 0; |
| 388 |
| 389 next_handler_->OnWillRead(&buf, &size, payload_for_old_handler.length()); |
| 390 CHECK_GE(size, static_cast<int>(payload_for_old_handler.length())); |
| 391 |
| 392 memcpy(buf->data(), payload_for_old_handler.c_str(), |
| 393 payload_for_old_handler.length()); |
| 394 |
| 395 next_handler_->OnReadCompleted(payload_for_old_handler.length(), |
| 396 &defer_ignored); |
| 397 DCHECK(!defer_ignored); |
| 398 |
| 399 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); |
| 400 next_handler_->OnResponseCompleted(status, std::string(), &defer_ignored); |
| 401 DCHECK(!defer_ignored); |
| 402 } |
380 | 403 |
381 // This is handled entirely within the new ResourceHandler, so just reset the | 404 // This is handled entirely within the new ResourceHandler, so just reset the |
382 // original ResourceHandler. | 405 // original ResourceHandler. |
383 next_handler_ = new_handler.Pass(); | 406 next_handler_ = new_handler.Pass(); |
384 next_handler_->SetController(this); | 407 next_handler_->SetController(this); |
385 | 408 |
386 return CopyReadBufferToNextHandler(); | 409 return CopyReadBufferToNextHandler(); |
387 } | 410 } |
388 | 411 |
389 bool BufferedResourceHandler::ReplayReadCompleted(bool* defer) { | 412 bool BufferedResourceHandler::ReplayReadCompleted(bool* defer) { |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 request()->LogUnblocked(); | 491 request()->LogUnblocked(); |
469 bool defer = false; | 492 bool defer = false; |
470 if (!ProcessResponse(&defer)) { | 493 if (!ProcessResponse(&defer)) { |
471 controller()->Cancel(); | 494 controller()->Cancel(); |
472 } else if (!defer) { | 495 } else if (!defer) { |
473 controller()->Resume(); | 496 controller()->Resume(); |
474 } | 497 } |
475 } | 498 } |
476 | 499 |
477 } // namespace content | 500 } // namespace content |
OLD | NEW |