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 @@
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util.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_connection_status_flags.h"
#include "net/ssl/ssl_info.h"
......@@ -841,20 +840,6 @@ void WebURLLoaderImpl::Context::OnReceivedResponse(
WebURLResponse response;
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_) {
auto read_handle = std::make_unique<SharedMemoryDataConsumerHandle>(
base::BindOnce(&Context::CancelBodyStreaming, this),
......
......@@ -254,10 +254,6 @@ class WebURLResponse {
// Returns true if the URL list is not empty.
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 ServiceWorker. Null if the response isn't from the CacheStorage.
BLINK_PLATFORM_EXPORT void SetCacheStorageCacheName(const WebString&);
......
......@@ -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_loading_log.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/shared_buffer.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
......@@ -482,10 +483,14 @@ void ImageResource::ResponseReceived(
std::unique_ptr<WebDataConsumerHandle> handle) {
DCHECK(!handle);
DCHECK(!multipart_parser_);
// If there's no boundary, just handle the request normally.
if (response.IsMultipart() && !response.MultipartBoundary().IsEmpty()) {
multipart_parser_ = MakeGarbageCollected<MultipartImageResourceParser>(
response, response.MultipartBoundary(), this);
if (response.MimeType() == "multipart/x-mixed-replace") {
Vector<char> boundary = network_utils::ParseMultipartBoundary(
response.HttpHeaderField(http_names::kContentType));
// 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
......
......@@ -377,7 +377,8 @@ TEST(ImageResourceTest, MultipartImage) {
// flagged as multipart.
ResourceResponse multipart_response(NullURL());
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(
WrappedResourceResponse(multipart_response), nullptr);
EXPECT_FALSE(image_resource->ResourceBuffer());
......@@ -457,7 +458,8 @@ TEST(ImageResourceTest, BitmapMultipartImage) {
ResourceResponse multipart_response(NullURL());
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(
WrappedResourceResponse(multipart_response), nullptr);
EXPECT_FALSE(image_resource->GetContent()->HasImage());
......
......@@ -344,10 +344,6 @@ bool WebURLResponse::HasUrlListViaServiceWorker() const {
return resource_response_->UrlListViaServiceWorker().size() > 0;
}
void WebURLResponse::SetMultipartBoundary(const char* bytes, size_t size) {
resource_response_->SetMultipartBoundary(bytes, size);
}
void WebURLResponse::SetCacheStorageCacheName(
const WebString& cache_storage_cache_name) {
resource_response_->SetCacheStorageCacheName(cache_storage_cache_name);
......
......@@ -200,8 +200,6 @@ class PLATFORM_EXPORT ResourceResponse final {
void ClearHTTPHeaderField(const AtomicString& name);
const HTTPHeaderMap& HttpHeaderFields() const;
bool IsMultipart() const { return MimeType() == "multipart/x-mixed-replace"; }
bool IsAttachment() const;
AtomicString HttpContentType() const;
......@@ -330,12 +328,6 @@ class PLATFORM_EXPORT ResourceResponse final {
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 {
return cache_storage_cache_name_;
}
......@@ -530,9 +522,6 @@ class PLATFORM_EXPORT ResourceResponse final {
// Note: only valid for main resource responses.
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.
// This is empty if the response was created inside the ServiceWorker.
Vector<KURL> url_list_via_service_worker_;
......
......@@ -133,6 +133,21 @@ String GenerateAcceptLanguageHeader(const String& lang) {
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 blink
......@@ -46,6 +46,9 @@ PLATFORM_EXPORT bool IsLegacySymantecCertError(int);
PLATFORM_EXPORT String GenerateAcceptLanguageHeader(const String&);
PLATFORM_EXPORT Vector<char> ParseMultipartBoundary(
const AtomicString& content_type_header);
} // namespace network_utils
} // 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