blob: b789df518f638dec95eef371fce2a1038c21a714 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2019 The Chromium Authors
John Abd-El-Malekf5047472019-04-22 18:07:362// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/data_url_loader_factory.h"
6
Md Hasibul Hasana963a9342024-04-03 10:15:147#include <string_view>
8
Matt Menke5f66421b2019-10-24 22:02:049#include "base/memory/ref_counted.h"
Julie Jeongeun Kim6dd4c7b2019-11-18 05:56:3010#include "mojo/public/cpp/bindings/remote.h"
Takashi Toyoshima7a4dcba182019-07-22 11:28:2711#include "mojo/public/cpp/system/data_pipe_producer.h"
12#include "mojo/public/cpp/system/string_data_source.h"
Matt Menke5f66421b2019-10-24 22:02:0413#include "net/base/data_url.h"
14#include "net/base/net_errors.h"
15#include "net/http/http_response_headers.h"
Sigurd Schneidere3d43c6b2021-07-27 13:35:0116#include "services/network/public/cpp/resource_request.h"
John Abd-El-Malekf5047472019-04-22 18:07:3617#include "services/network/public/mojom/url_loader.mojom.h"
Lucas Furukawa Gadanib8674782019-12-11 16:22:5818#include "services/network/public/mojom/url_response_head.mojom.h"
John Abd-El-Malekf5047472019-04-22 18:07:3619
20namespace content {
21
22namespace {
23struct WriteData {
Julie Jeongeun Kim6dd4c7b2019-11-18 05:56:3024 mojo::Remote<network::mojom::URLLoaderClient> client;
John Abd-El-Malekf5047472019-04-22 18:07:3625 std::string data;
Takashi Toyoshima7a4dcba182019-07-22 11:28:2726 std::unique_ptr<mojo::DataPipeProducer> producer;
John Abd-El-Malekf5047472019-04-22 18:07:3627};
28
29void OnWrite(std::unique_ptr<WriteData> write_data, MojoResult result) {
30 if (result != MOJO_RESULT_OK) {
John Abd-El-Malek075cd212020-08-31 22:37:2331 write_data->client->OnComplete(
32 network::URLLoaderCompletionStatus(net::ERR_FAILED));
John Abd-El-Malekf5047472019-04-22 18:07:3633 return;
34 }
35
36 network::URLLoaderCompletionStatus status(net::OK);
37 status.encoded_data_length = write_data->data.size();
38 status.encoded_body_length = write_data->data.size();
39 status.decoded_body_length = write_data->data.size();
40 write_data->client->OnComplete(status);
41}
42
43} // namespace
44
Lukasz Anforowicz9c5516b2020-09-10 01:34:1345DataURLLoaderFactory::DataURLLoaderFactory(
46 const GURL& url,
47 mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver)
Lukasz Anforowicz25620d32021-01-27 22:03:4448 : network::SelfDeletingURLLoaderFactory(std::move(factory_receiver)),
49 url_(url) {}
John Abd-El-Malekf5047472019-04-22 18:07:3650
Lukasz Anforowicz9c5516b2020-09-10 01:34:1351DataURLLoaderFactory::~DataURLLoaderFactory() = default;
John Abd-El-Malekf5047472019-04-22 18:07:3652
53void DataURLLoaderFactory::CreateLoaderAndStart(
Julie Jeongeun Kime003de52019-10-29 05:14:2754 mojo::PendingReceiver<network::mojom::URLLoader> loader,
John Abd-El-Malekf5047472019-04-22 18:07:3655 int32_t request_id,
56 uint32_t options,
57 const network::ResourceRequest& request,
Julie Jeongeun Kim6dd4c7b2019-11-18 05:56:3058 mojo::PendingRemote<network::mojom::URLLoaderClient> client,
John Abd-El-Malekf5047472019-04-22 18:07:3659 const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
John Abd-El-Malekf5047472019-04-22 18:07:3660 const GURL* url = nullptr;
61 if (!url_.is_empty() && request.url.is_empty()) {
62 url = &url_;
63 } else {
64 url = &request.url;
65 }
66
Matt Menke5f66421b2019-10-24 22:02:0467 std::string data;
68 scoped_refptr<net::HttpResponseHeaders> headers;
Lucas Furukawa Gadanib8674782019-12-11 16:22:5869 auto response = network::mojom::URLResponseHead::New();
70 net::Error result = net::DataURL::BuildResponse(
71 *url, request.method, &response->mime_type, &response->charset, &data,
72 &response->headers);
Lukasz Anforowicz9c5516b2020-09-10 01:34:1373
74 // Users of CreateAndBindForOneSpecificUrl should only submit one load
75 // request - we won't need the URL anymore.
76 url_ = GURL();
John Abd-El-Malekf5047472019-04-22 18:07:3677
Julie Jeongeun Kim6dd4c7b2019-11-18 05:56:3078 mojo::Remote<network::mojom::URLLoaderClient> client_remote(
79 std::move(client));
John Abd-El-Malekf5047472019-04-22 18:07:3680 if (result != net::OK) {
Julie Jeongeun Kim6dd4c7b2019-11-18 05:56:3081 client_remote->OnComplete(network::URLLoaderCompletionStatus(result));
John Abd-El-Malekf5047472019-04-22 18:07:3682 return;
83 }
84
John Abd-El-Malekf5047472019-04-22 18:07:3685 mojo::ScopedDataPipeProducerHandle producer;
86 mojo::ScopedDataPipeConsumerHandle consumer;
Robert Sesek3bce5dd2021-02-19 19:27:5887 if (CreateDataPipe(nullptr, producer, consumer) != MOJO_RESULT_OK) {
Julie Jeongeun Kim6dd4c7b2019-11-18 05:56:3088 client_remote->OnComplete(
John Abd-El-Malekf5047472019-04-22 18:07:3689 network::URLLoaderCompletionStatus(net::ERR_INSUFFICIENT_RESOURCES));
90 return;
91 }
92
Leszek Swirski154cddb2022-08-29 17:57:1993 client_remote->OnReceiveResponse(std::move(response), std::move(consumer),
Arthur Sonzognic686e8f2024-01-11 08:36:3794 std::nullopt);
John Abd-El-Malekf5047472019-04-22 18:07:3695
96 auto write_data = std::make_unique<WriteData>();
Julie Jeongeun Kim6dd4c7b2019-11-18 05:56:3097 write_data->client = std::move(client_remote);
John Abd-El-Malekf5047472019-04-22 18:07:3698 write_data->data = std::move(data);
99 write_data->producer =
Takashi Toyoshima7a4dcba182019-07-22 11:28:27100 std::make_unique<mojo::DataPipeProducer>(std::move(producer));
John Abd-El-Malekf5047472019-04-22 18:07:36101
Maksim Ivanovc5edae42020-08-31 16:44:47102 mojo::DataPipeProducer* producer_ptr = write_data->producer.get();
Md Hasibul Hasana963a9342024-04-03 10:15:14103 std::string_view string_piece(write_data->data);
John Abd-El-Malekf5047472019-04-22 18:07:36104
Maksim Ivanovc5edae42020-08-31 16:44:47105 producer_ptr->Write(
Takashi Toyoshima7a4dcba182019-07-22 11:28:27106 std::make_unique<mojo::StringDataSource>(
107 string_piece, mojo::StringDataSource::AsyncWritingMode::
108 STRING_STAYS_VALID_UNTIL_COMPLETION),
109 base::BindOnce(OnWrite, std::move(write_data)));
John Abd-El-Malekf5047472019-04-22 18:07:36110}
111
Lukasz Anforowicz9c5516b2020-09-10 01:34:13112// static
113mojo::PendingRemote<network::mojom::URLLoaderFactory>
114DataURLLoaderFactory::Create() {
115 return CreateForOneSpecificUrl(GURL());
116}
117
118// static
119mojo::PendingRemote<network::mojom::URLLoaderFactory>
120DataURLLoaderFactory::CreateForOneSpecificUrl(const GURL& url) {
121 mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_remote;
122
123 // The DataURLLoaderFactory will delete itself when there are no more
Lukasz Anforowicz25620d32021-01-27 22:03:44124 // receivers - see the network::SelfDeletingURLLoaderFactory::OnDisconnect
125 // method.
Lukasz Anforowicz9c5516b2020-09-10 01:34:13126 new DataURLLoaderFactory(url,
127 pending_remote.InitWithNewPipeAndPassReceiver());
128
129 return pending_remote;
John Abd-El-Malekf5047472019-04-22 18:07:36130}
131
132} // namespace content