From 86234371d6c9d429ea878e5379f756a0395c461f Mon Sep 17 00:00:00 2001 From: aee <117306596+aee-google@users.noreply.github.com> Date: Mon, 29 Apr 2024 15:00:32 -0700 Subject: [PATCH] Add back support for data URL's. (#3108) b/335235285 (cherry picked from commit 1f2f1912fec3888398db7f52d340b7719ba36449) --- cobalt/network/BUILD.gn | 8 + .../network/custom/data_protocol_handler.cc | 36 ++++ cobalt/network/custom/data_protocol_handler.h | 48 ++++++ .../network/custom/url_range_request_job.cc | 44 +++++ cobalt/network/custom/url_range_request_job.h | 55 ++++++ cobalt/network/custom/url_request_data_job.cc | 73 ++++++++ cobalt/network/custom/url_request_data_job.h | 58 +++++++ .../network/custom/url_request_simple_job.cc | 156 ++++++++++++++++++ .../network/custom/url_request_simple_job.h | 89 ++++++++++ cobalt/network/url_request_context.cc | 4 +- 10 files changed, 568 insertions(+), 3 deletions(-) create mode 100644 cobalt/network/custom/data_protocol_handler.cc create mode 100644 cobalt/network/custom/data_protocol_handler.h create mode 100644 cobalt/network/custom/url_range_request_job.cc create mode 100644 cobalt/network/custom/url_range_request_job.h create mode 100644 cobalt/network/custom/url_request_data_job.cc create mode 100644 cobalt/network/custom/url_request_data_job.h create mode 100644 cobalt/network/custom/url_request_simple_job.cc create mode 100644 cobalt/network/custom/url_request_simple_job.h diff --git a/cobalt/network/BUILD.gn b/cobalt/network/BUILD.gn index 4e6f0b6f0a18..78b1145854c5 100644 --- a/cobalt/network/BUILD.gn +++ b/cobalt/network/BUILD.gn @@ -28,6 +28,8 @@ static_library("network") { sources = [ "cookie_jar_impl.cc", "cookie_jar_impl.h", + "custom/data_protocol_handler.cc", + "custom/data_protocol_handler.h", "custom/url_fetcher.cc", "custom/url_fetcher.h", "custom/url_fetcher_core.cc", @@ -39,6 +41,12 @@ static_library("network") { "custom/url_fetcher_impl.h", "custom/url_fetcher_response_writer.cc", "custom/url_fetcher_response_writer.h", + "custom/url_range_request_job.cc", + "custom/url_range_request_job.h", + "custom/url_request_data_job.cc", + "custom/url_request_data_job.h", + "custom/url_request_simple_job.cc", + "custom/url_request_simple_job.h", "custom/url_request_status.cc", "custom/url_request_status.h", "disk_cache/cobalt_backend_factory.cc", diff --git a/cobalt/network/custom/data_protocol_handler.cc b/cobalt/network/custom/data_protocol_handler.cc new file mode 100644 index 000000000000..cc30c68a0379 --- /dev/null +++ b/cobalt/network/custom/data_protocol_handler.cc @@ -0,0 +1,36 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cobalt/network/custom/data_protocol_handler.h" + +#include "cobalt/network/custom/url_request_data_job.h" + +namespace net { + +DataProtocolHandler::DataProtocolHandler() = default; + +std::unique_ptr DataProtocolHandler::CreateJob( + URLRequest* request) const { + return std::make_unique(request); +} + +bool DataProtocolHandler::IsSafeRedirectTarget(const GURL& location) const { + return false; +} + +} // namespace net diff --git a/cobalt/network/custom/data_protocol_handler.h b/cobalt/network/custom/data_protocol_handler.h new file mode 100644 index 000000000000..65df49b0884f --- /dev/null +++ b/cobalt/network/custom/data_protocol_handler.h @@ -0,0 +1,48 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COBALT_NETWORK_CUSTOM_DATA_PROTOCOL_HANDLER_H_ +#define COBALT_NETWORK_CUSTOM_DATA_PROTOCOL_HANDLER_H_ + +#include + +#include "base/compiler_specific.h" +#include "base/macros.h" +#include "net/base/net_export.h" +#include "net/url_request/url_request_job_factory.h" + +namespace net { + +class URLRequestJob; + +// Implements a ProtocolHandler for Data jobs. +class NET_EXPORT DataProtocolHandler + : public URLRequestJobFactory::ProtocolHandler { + public: + DataProtocolHandler(); + DataProtocolHandler(const DataProtocolHandler&) = delete; + DataProtocolHandler& operator=(const DataProtocolHandler&) = delete; + + std::unique_ptr CreateJob(URLRequest* request) const override; + + bool IsSafeRedirectTarget(const GURL& location) const override; +}; + +} // namespace net + +#endif // COBALT_NETWORK_CUSTOM_DATA_PROTOCOL_HANDLER_H_ diff --git a/cobalt/network/custom/url_range_request_job.cc b/cobalt/network/custom/url_range_request_job.cc new file mode 100644 index 000000000000..71e568e54e2c --- /dev/null +++ b/cobalt/network/custom/url_range_request_job.cc @@ -0,0 +1,44 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cobalt/network/custom/url_range_request_job.h" + +#include + +#include "net/base/net_errors.h" +#include "net/http/http_request_headers.h" +#include "net/http/http_util.h" + +namespace net { + +URLRangeRequestJob::URLRangeRequestJob(URLRequest* request) + : URLRequestJob(request), range_parse_result_(OK) {} + +URLRangeRequestJob::~URLRangeRequestJob() = default; + +void URLRangeRequestJob::SetExtraRequestHeaders( + const HttpRequestHeaders& headers) { + std::string range_header; + if (headers.GetHeader(HttpRequestHeaders::kRange, &range_header)) { + if (!HttpUtil::ParseRangeHeader(range_header, &ranges_)) { + range_parse_result_ = ERR_REQUEST_RANGE_NOT_SATISFIABLE; + } + } +} + +} // namespace net diff --git a/cobalt/network/custom/url_range_request_job.h b/cobalt/network/custom/url_range_request_job.h new file mode 100644 index 000000000000..13663d0623bf --- /dev/null +++ b/cobalt/network/custom/url_range_request_job.h @@ -0,0 +1,55 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COBALT_NETWORK_CUSTOM_URL_RANGE_REQUEST_JOB_H_ +#define COBALT_NETWORK_CUSTOM_URL_RANGE_REQUEST_JOB_H_ + +#include + +#include "net/base/net_export.h" +#include "net/http/http_byte_range.h" +#include "net/url_request/url_request_job.h" + +namespace net { + +class HttpRequestHeaders; + +// URLRequestJob with support for parsing range requests. +// It is up to subclasses to handle the response +// and deal with an errors parsing the range request header. +// This must be done after Start() has been called. +class NET_EXPORT URLRangeRequestJob : public URLRequestJob { + public: + explicit URLRangeRequestJob(URLRequest* request); + + void SetExtraRequestHeaders(const HttpRequestHeaders& headers) override; + + const std::vector& ranges() const { return ranges_; } + int range_parse_result() const { return range_parse_result_; } + + protected: + ~URLRangeRequestJob() override; + + private: + std::vector ranges_; + int range_parse_result_; +}; + +} // namespace net + +#endif // COBALT_NETWORK_CUSTOM_URL_RANGE_REQUEST_JOB_H_ diff --git a/cobalt/network/custom/url_request_data_job.cc b/cobalt/network/custom/url_request_data_job.cc new file mode 100644 index 000000000000..53292e3ba260 --- /dev/null +++ b/cobalt/network/custom/url_request_data_job.cc @@ -0,0 +1,73 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Simple implementation of a data: protocol handler. + +#include "cobalt/network/custom/url_request_data_job.h" + +#include "net/base/data_url.h" +#include "net/base/net_errors.h" +#include "net/http/http_response_headers.h" +#include "url/gurl.h" + +namespace net { + +int URLRequestDataJob::BuildResponse(const GURL& url, std::string* mime_type, + std::string* charset, std::string* data, + HttpResponseHeaders* headers) { + if (!DataURL::Parse(url, mime_type, charset, data)) return ERR_INVALID_URL; + + // |mime_type| set by DataURL::Parse() is guaranteed to be in + // token "/" token + // form. |charset| can be an empty string. + + DCHECK(!mime_type->empty()); + + if (headers) { + headers->ReplaceStatusLine("HTTP/1.1 200 OK"); + // "charset" in the Content-Type header is specified explicitly to follow + // the "token" ABNF in the HTTP spec. When DataURL::Parse() call is + // successful, it's guaranteed that the string in |charset| follows the + // "token" ABNF. + std::string content_type_header = *mime_type; + if (!charset->empty()) content_type_header.append(";charset=" + *charset); + headers->AddHeader("Content-Type", content_type_header); + } + + return OK; +} + +URLRequestDataJob::URLRequestDataJob(URLRequest* request) + : URLRequestSimpleJob(request) {} + +int URLRequestDataJob::GetData(std::string* mime_type, std::string* charset, + std::string* data, + CompletionOnceCallback callback) const { + // Check if data URL is valid. If not, don't bother to try to extract data. + // Otherwise, parse the data from the data URL. + const GURL& url = request_->url(); + if (!url.is_valid()) return ERR_INVALID_URL; + + // TODO(tyoshino): Get the headers and export via + // URLRequestJob::GetResponseInfo(). + return BuildResponse(url, mime_type, charset, data, NULL); +} + +URLRequestDataJob::~URLRequestDataJob() = default; + +} // namespace net diff --git a/cobalt/network/custom/url_request_data_job.h b/cobalt/network/custom/url_request_data_job.h new file mode 100644 index 000000000000..fa882799cf47 --- /dev/null +++ b/cobalt/network/custom/url_request_data_job.h @@ -0,0 +1,58 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COBALT_NETWORK_CUSTOM_URL_REQUEST_DATA_JOB_H_ +#define COBALT_NETWORK_CUSTOM_URL_REQUEST_DATA_JOB_H_ + +#include + +#include "base/macros.h" +#include "cobalt/network/custom/url_request_simple_job.h" +#include "net/base/completion_once_callback.h" +#include "net/base/net_export.h" +#include "net/url_request/url_request.h" + +class GURL; + +namespace net { + +class HttpResponseHeaders; +class URLRequest; + +class NET_EXPORT URLRequestDataJob : public URLRequestSimpleJob { + public: + // Extracts info from a data scheme URL. Returns OK if successful. Returns + // ERR_INVALID_URL otherwise. + static int BuildResponse(const GURL& url, std::string* mime_type, + std::string* charset, std::string* data, + HttpResponseHeaders* headers); + + explicit URLRequestDataJob(URLRequest* request); + ~URLRequestDataJob() override; + URLRequestDataJob(const URLRequestDataJob&) = delete; + URLRequestDataJob& operator=(const URLRequestDataJob&) = delete; + + + // URLRequestSimpleJob + int GetData(std::string* mime_type, std::string* charset, std::string* data, + CompletionOnceCallback callback) const override; +}; + +} // namespace net + +#endif // COBALT_NETWORK_CUSTOM_URL_REQUEST_DATA_JOB_H_ diff --git a/cobalt/network/custom/url_request_simple_job.cc b/cobalt/network/custom/url_request_simple_job.cc new file mode 100644 index 000000000000..e8839ca3e67c --- /dev/null +++ b/cobalt/network/custom/url_request_simple_job.cc @@ -0,0 +1,156 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cobalt/network/custom/url_request_simple_job.h" + +#include +#include +#include + +#include "base/bind.h" +#include "base/compiler_specific.h" +#include "base/location.h" +#include "base/memory/ref_counted_memory.h" +#include "base/single_thread_task_runner.h" +#include "base/task/task_traits.h" +#include "base/task/thread_pool.h" +#include "base/threading/thread_task_runner_handle.h" +#include "cobalt/network/custom/url_request_status.h" +#include "net/base/io_buffer.h" +#include "net/base/net_errors.h" +#include "net/http/http_request_headers.h" +#include "net/http/http_util.h" +#include "starboard/memory.h" + +namespace net { + +namespace { + +void CopyData(const scoped_refptr& buf, int buf_size, + const scoped_refptr& data, + int64_t data_offset) { + memcpy(buf->data(), data->front() + data_offset, buf_size); +} + +} // namespace + +URLRequestSimpleJob::URLRequestSimpleJob(URLRequest* request) + : URLRangeRequestJob(request), next_data_offset_(0), weak_factory_(this) {} + +void URLRequestSimpleJob::Start() { + // Start reading asynchronously so that all error reporting and data + // callbacks happen as they would for network requests. + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, + base::Bind(&URLRequestSimpleJob::StartAsync, weak_factory_.GetWeakPtr())); +} + +void URLRequestSimpleJob::Kill() { + weak_factory_.InvalidateWeakPtrs(); + URLRangeRequestJob::Kill(); +} + +bool URLRequestSimpleJob::GetMimeType(std::string* mime_type) const { + *mime_type = mime_type_; + return true; +} + +bool URLRequestSimpleJob::GetCharset(std::string* charset) { + *charset = charset_; + return true; +} + +URLRequestSimpleJob::~URLRequestSimpleJob() = default; + +int URLRequestSimpleJob::ReadRawData(IOBuffer* buf, int buf_size) { + buf_size = std::min(static_cast(buf_size), + byte_range_.last_byte_position() - next_data_offset_ + 1); + if (buf_size == 0) return 0; + + // Do memory copy asynchronously on a thread that is not the network thread. + // See crbug.com/422489. + base::ThreadPool::PostTaskAndReply( + FROM_HERE, {base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, + base::BindOnce(&CopyData, base::WrapRefCounted(buf), buf_size, data_, + next_data_offset_), + base::BindOnce(&URLRequestSimpleJob::ReadRawDataComplete, + weak_factory_.GetWeakPtr(), buf_size)); + next_data_offset_ += buf_size; + return ERR_IO_PENDING; +} + +int URLRequestSimpleJob::GetData(std::string* mime_type, std::string* charset, + std::string* data, + CompletionOnceCallback callback) const { + NOTREACHED(); + return ERR_UNEXPECTED; +} + +int URLRequestSimpleJob::GetRefCountedData( + std::string* mime_type, std::string* charset, + scoped_refptr* data, + CompletionOnceCallback callback) const { + scoped_refptr str_data(new base::RefCountedString()); + int result = + GetData(mime_type, charset, &str_data->data(), std::move(callback)); + *data = str_data; + return result; +} + +void URLRequestSimpleJob::StartAsync() { + if (!request_) return; + + if (ranges().size() > 1) { + NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, + ERR_REQUEST_RANGE_NOT_SATISFIABLE) + .ToNetError()); + return; + } + + if (!ranges().empty() && range_parse_result() == OK) + byte_range_ = ranges().front(); + + const int result = + GetRefCountedData(&mime_type_, &charset_, &data_, + base::Bind(&URLRequestSimpleJob::OnGetDataCompleted, + weak_factory_.GetWeakPtr())); + + if (result != ERR_IO_PENDING) OnGetDataCompleted(result); +} + +void URLRequestSimpleJob::OnGetDataCompleted(int result) { + if (result == OK) { + // Notify that the headers are complete + if (!byte_range_.ComputeBounds(data_->size())) { + NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, + ERR_REQUEST_RANGE_NOT_SATISFIABLE) + .ToNetError()); + return; + } + + next_data_offset_ = byte_range_.first_byte_position(); + set_expected_content_size(byte_range_.last_byte_position() - + next_data_offset_ + 1); + NotifyHeadersComplete(); + } else { + NotifyStartError( + URLRequestStatus(URLRequestStatus::FAILED, result).ToNetError()); + } +} + +} // namespace net diff --git a/cobalt/network/custom/url_request_simple_job.h b/cobalt/network/custom/url_request_simple_job.h new file mode 100644 index 000000000000..85d9da11f714 --- /dev/null +++ b/cobalt/network/custom/url_request_simple_job.h @@ -0,0 +1,89 @@ +// Copyright 2024 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COBALT_NETWORK_CUSTOM_URL_REQUEST_SIMPLE_JOB_H_ +#define COBALT_NETWORK_CUSTOM_URL_REQUEST_SIMPLE_JOB_H_ + +#include + +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/strings/string_piece.h" +#include "cobalt/network/custom/url_range_request_job.h" +#include "net/base/net_export.h" +#include "starboard/types.h" + +namespace base { +class RefCountedMemory; +} + +namespace net { + +using CompletionOnceCallback = base::OnceCallback; + +class URLRequest; + +class NET_EXPORT URLRequestSimpleJob : public URLRangeRequestJob { + public: + explicit URLRequestSimpleJob(URLRequest* request); + + void Start() override; + void Kill() override; + int ReadRawData(IOBuffer* buf, int buf_size) override; + bool GetMimeType(std::string* mime_type) const override; + bool GetCharset(std::string* charset) override; + + protected: + ~URLRequestSimpleJob() override; + + // Subclasses must override either GetData or GetRefCountedData to define the + // way response data is determined. + // The return value should be: + // - OK if data is obtained; + // - ERR_IO_PENDING if async processing is needed to finish obtaining data. + // This is the only case when |callback| should be called after + // completion of the operation. In other situations |callback| should + // never be called; + // - any other ERR_* code to indicate an error. This code will be used + // as the error code in the URLRequestStatus when the URLRequest + // is finished. + virtual int GetData(std::string* mime_type, std::string* charset, + std::string* data, CompletionOnceCallback callback) const; + + // Similar to GetData(), except |*data| can share ownership of the bytes + // instead of copying them into a std::string. + virtual int GetRefCountedData(std::string* mime_type, std::string* charset, + scoped_refptr* data, + CompletionOnceCallback callback) const; + + void StartAsync(); + + private: + void OnGetDataCompleted(int result); + + HttpByteRange byte_range_; + std::string mime_type_; + std::string charset_; + scoped_refptr data_; + int64_t next_data_offset_; + base::WeakPtrFactory weak_factory_; +}; + +} // namespace net + +#endif // COBALT_NETWORK_CUSTOM_URL_REQUEST_SIMPLE_JOB_H_ diff --git a/cobalt/network/url_request_context.cc b/cobalt/network/url_request_context.cc index e7ce33720d71..ed047d13e58c 100644 --- a/cobalt/network/url_request_context.cc +++ b/cobalt/network/url_request_context.cc @@ -26,6 +26,7 @@ #include "base/command_line.h" #include "cobalt/base/polymorphic_downcast.h" #include "cobalt/configuration/configuration.h" +#include "cobalt/network/custom/data_protocol_handler.h" #include "cobalt/network/disk_cache/cobalt_backend_factory.h" #include "cobalt/network/disk_cache/cobalt_backend_impl.h" #include "cobalt/network/disk_cache/resource_type.h" @@ -302,11 +303,8 @@ URLRequestContext::URLRequestContext( base::Unretained(this))); } -#ifndef COBALT_PENDING_CLEAN_UP - // TODO: Determine if this is needed. url_request_context_builder->SetProtocolHandler( url::kDataScheme, std::make_unique()); -#endif url_request_context_ = url_request_context_builder->Build(); }