Commit 68b0fa48 authored by Dmitry Gozman's avatar Dmitry Gozman Committed by Commit Bot

Loader: handle multipart/x-mixed-replace entirely in Blink

We currently parse content type header to extract boundary
in WebURLLoaderImpl, while we can do so lazily in ImageResource.
The rest of multipart image processing has been already moved
to Blink.

Bug: none
Change-Id: Ic00bb08f2cb0148ae3425135451a403ef755f964
Reviewed-on: https://chromium-review.googlesource.com/c/1394185Reviewed-by: default avatarHiroshige Hayashizaki <hiroshige@chromium.org>
Commit-Queue: Dmitry Gozman <dgozman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#619837}
parent cbc9ef93
...@@ -45,7 +45,6 @@ ...@@ -45,7 +45,6 @@
#include "net/cert/x509_certificate.h" #include "net/cert/x509_certificate.h"
#include "net/cert/x509_util.h" #include "net/cert/x509_util.h"
#include "net/http/http_response_headers.h" #include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "net/ssl/ssl_cipher_suite_names.h" #include "net/ssl/ssl_cipher_suite_names.h"
#include "net/ssl/ssl_connection_status_flags.h" #include "net/ssl/ssl_connection_status_flags.h"
#include "net/ssl/ssl_info.h" #include "net/ssl/ssl_info.h"
...@@ -841,20 +840,6 @@ void WebURLLoaderImpl::Context::OnReceivedResponse( ...@@ -841,20 +840,6 @@ void WebURLLoaderImpl::Context::OnReceivedResponse(
WebURLResponse response; WebURLResponse response;
PopulateURLResponse(url_, info, &response, report_raw_headers_, request_id_); PopulateURLResponse(url_, info, &response, report_raw_headers_, request_id_);
if (info.headers.get() && info.mime_type == "multipart/x-mixed-replace") {
std::string content_type;
info.headers->EnumerateHeader(nullptr, "content-type", &content_type);
std::string mime_type;
std::string charset;
bool had_charset = false;
std::string boundary;
net::HttpUtil::ParseContentType(content_type, &mime_type, &charset,
&had_charset, &boundary);
base::TrimString(boundary, " \"", &boundary);
response.SetMultipartBoundary(boundary.data(), boundary.size());
}
if (use_stream_on_response_) { if (use_stream_on_response_) {
auto read_handle = std::make_unique<SharedMemoryDataConsumerHandle>( auto read_handle = std::make_unique<SharedMemoryDataConsumerHandle>(
base::BindOnce(&Context::CancelBodyStreaming, this), base::BindOnce(&Context::CancelBodyStreaming, this),
......
...@@ -254,10 +254,6 @@ class WebURLResponse { ...@@ -254,10 +254,6 @@ class WebURLResponse {
// Returns true if the URL list is not empty. // Returns true if the URL list is not empty.
BLINK_PLATFORM_EXPORT bool HasUrlListViaServiceWorker() const; BLINK_PLATFORM_EXPORT bool HasUrlListViaServiceWorker() const;
// The boundary of the response. Set only when this is a multipart response.
BLINK_PLATFORM_EXPORT void SetMultipartBoundary(const char* bytes,
size_t /* size */);
// The cache name of the CacheStorage from where the response is served via // The cache name of the CacheStorage from where the response is served via
// the ServiceWorker. Null if the response isn't from the CacheStorage. // the ServiceWorker. Null if the response isn't from the CacheStorage.
BLINK_PLATFORM_EXPORT void SetCacheStorageCacheName(const WebString&); BLINK_PLATFORM_EXPORT void SetCacheStorageCacheName(const WebString&);
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loading_log.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_loading_log.h"
#include "third_party/blink/renderer/platform/network/http_parsers.h" #include "third_party/blink/renderer/platform/network/http_parsers.h"
#include "third_party/blink/renderer/platform/network/network_utils.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/shared_buffer.h" #include "third_party/blink/renderer/platform/shared_buffer.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h"
...@@ -482,10 +483,14 @@ void ImageResource::ResponseReceived( ...@@ -482,10 +483,14 @@ void ImageResource::ResponseReceived(
std::unique_ptr<WebDataConsumerHandle> handle) { std::unique_ptr<WebDataConsumerHandle> handle) {
DCHECK(!handle); DCHECK(!handle);
DCHECK(!multipart_parser_); DCHECK(!multipart_parser_);
// If there's no boundary, just handle the request normally. if (response.MimeType() == "multipart/x-mixed-replace") {
if (response.IsMultipart() && !response.MultipartBoundary().IsEmpty()) { Vector<char> boundary = network_utils::ParseMultipartBoundary(
multipart_parser_ = MakeGarbageCollected<MultipartImageResourceParser>( response.HttpHeaderField(http_names::kContentType));
response, response.MultipartBoundary(), this); // If there's no boundary, just handle the request normally.
if (!boundary.IsEmpty()) {
multipart_parser_ = MakeGarbageCollected<MultipartImageResourceParser>(
response, boundary, this);
}
} }
// Notify the base class that a response has been received. Note that after // Notify the base class that a response has been received. Note that after
......
...@@ -377,7 +377,8 @@ TEST(ImageResourceTest, MultipartImage) { ...@@ -377,7 +377,8 @@ TEST(ImageResourceTest, MultipartImage) {
// flagged as multipart. // flagged as multipart.
ResourceResponse multipart_response(NullURL()); ResourceResponse multipart_response(NullURL());
multipart_response.SetMimeType("multipart/x-mixed-replace"); multipart_response.SetMimeType("multipart/x-mixed-replace");
multipart_response.SetMultipartBoundary("boundary", strlen("boundary")); multipart_response.SetHTTPHeaderField(
http_names::kContentType, "multipart/x-mixed-replace; boundary=boundary");
image_resource->Loader()->DidReceiveResponse( image_resource->Loader()->DidReceiveResponse(
WrappedResourceResponse(multipart_response), nullptr); WrappedResourceResponse(multipart_response), nullptr);
EXPECT_FALSE(image_resource->ResourceBuffer()); EXPECT_FALSE(image_resource->ResourceBuffer());
...@@ -457,7 +458,8 @@ TEST(ImageResourceTest, BitmapMultipartImage) { ...@@ -457,7 +458,8 @@ TEST(ImageResourceTest, BitmapMultipartImage) {
ResourceResponse multipart_response(NullURL()); ResourceResponse multipart_response(NullURL());
multipart_response.SetMimeType("multipart/x-mixed-replace"); multipart_response.SetMimeType("multipart/x-mixed-replace");
multipart_response.SetMultipartBoundary("boundary", strlen("boundary")); multipart_response.SetHTTPHeaderField(
http_names::kContentType, "multipart/x-mixed-replace; boundary=boundary");
image_resource->Loader()->DidReceiveResponse( image_resource->Loader()->DidReceiveResponse(
WrappedResourceResponse(multipart_response), nullptr); WrappedResourceResponse(multipart_response), nullptr);
EXPECT_FALSE(image_resource->GetContent()->HasImage()); EXPECT_FALSE(image_resource->GetContent()->HasImage());
......
...@@ -344,10 +344,6 @@ bool WebURLResponse::HasUrlListViaServiceWorker() const { ...@@ -344,10 +344,6 @@ bool WebURLResponse::HasUrlListViaServiceWorker() const {
return resource_response_->UrlListViaServiceWorker().size() > 0; return resource_response_->UrlListViaServiceWorker().size() > 0;
} }
void WebURLResponse::SetMultipartBoundary(const char* bytes, size_t size) {
resource_response_->SetMultipartBoundary(bytes, size);
}
void WebURLResponse::SetCacheStorageCacheName( void WebURLResponse::SetCacheStorageCacheName(
const WebString& cache_storage_cache_name) { const WebString& cache_storage_cache_name) {
resource_response_->SetCacheStorageCacheName(cache_storage_cache_name); resource_response_->SetCacheStorageCacheName(cache_storage_cache_name);
......
...@@ -200,8 +200,6 @@ class PLATFORM_EXPORT ResourceResponse final { ...@@ -200,8 +200,6 @@ class PLATFORM_EXPORT ResourceResponse final {
void ClearHTTPHeaderField(const AtomicString& name); void ClearHTTPHeaderField(const AtomicString& name);
const HTTPHeaderMap& HttpHeaderFields() const; const HTTPHeaderMap& HttpHeaderFields() const;
bool IsMultipart() const { return MimeType() == "multipart/x-mixed-replace"; }
bool IsAttachment() const; bool IsAttachment() const;
AtomicString HttpContentType() const; AtomicString HttpContentType() const;
...@@ -330,12 +328,6 @@ class PLATFORM_EXPORT ResourceResponse final { ...@@ -330,12 +328,6 @@ class PLATFORM_EXPORT ResourceResponse final {
url_list_via_service_worker_ = url_list; url_list_via_service_worker_ = url_list;
} }
const Vector<char>& MultipartBoundary() const { return multipart_boundary_; }
void SetMultipartBoundary(const char* bytes, uint32_t size) {
multipart_boundary_.clear();
multipart_boundary_.Append(bytes, size);
}
const String& CacheStorageCacheName() const { const String& CacheStorageCacheName() const {
return cache_storage_cache_name_; return cache_storage_cache_name_;
} }
...@@ -530,9 +522,6 @@ class PLATFORM_EXPORT ResourceResponse final { ...@@ -530,9 +522,6 @@ class PLATFORM_EXPORT ResourceResponse final {
// Note: only valid for main resource responses. // Note: only valid for main resource responses.
KURL app_cache_manifest_url_; KURL app_cache_manifest_url_;
// The multipart boundary of this response.
Vector<char> multipart_boundary_;
// The URL list of the response which was fetched by the ServiceWorker. // The URL list of the response which was fetched by the ServiceWorker.
// This is empty if the response was created inside the ServiceWorker. // This is empty if the response was created inside the ServiceWorker.
Vector<KURL> url_list_via_service_worker_; Vector<KURL> url_list_via_service_worker_;
......
...@@ -133,6 +133,21 @@ String GenerateAcceptLanguageHeader(const String& lang) { ...@@ -133,6 +133,21 @@ String GenerateAcceptLanguageHeader(const String& lang) {
net::HttpUtil::GenerateAcceptLanguageHeader(string)); net::HttpUtil::GenerateAcceptLanguageHeader(string));
} }
Vector<char> ParseMultipartBoundary(const AtomicString& content_type_header) {
CString cstring(content_type_header.Utf8());
std::string string(cstring.data(), cstring.length());
std::string mime_type;
std::string charset;
bool had_charset = false;
std::string boundary;
net::HttpUtil::ParseContentType(string, &mime_type, &charset, &had_charset,
&boundary);
base::TrimString(boundary, " \"", &boundary);
Vector<char> result;
result.Append(boundary.data(), boundary.size());
return result;
}
} // namespace network_utils } // namespace network_utils
} // namespace blink } // namespace blink
...@@ -46,6 +46,9 @@ PLATFORM_EXPORT bool IsLegacySymantecCertError(int); ...@@ -46,6 +46,9 @@ PLATFORM_EXPORT bool IsLegacySymantecCertError(int);
PLATFORM_EXPORT String GenerateAcceptLanguageHeader(const String&); PLATFORM_EXPORT String GenerateAcceptLanguageHeader(const String&);
PLATFORM_EXPORT Vector<char> ParseMultipartBoundary(
const AtomicString& content_type_header);
} // namespace network_utils } // namespace network_utils
} // namespace blink } // namespace blink
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment