Avi Drissman | 4e1b7bc3 | 2022-09-15 14:03:50 | [diff] [blame] | 1 | // Copyright 2019 The Chromium Authors |
John Abd-El-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 2 | // 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 Hasan | a963a934 | 2024-04-03 10:15:14 | [diff] [blame] | 7 | #include <string_view> |
| 8 | |
Matt Menke | 5f66421b | 2019-10-24 22:02:04 | [diff] [blame] | 9 | #include "base/memory/ref_counted.h" |
Julie Jeongeun Kim | 6dd4c7b | 2019-11-18 05:56:30 | [diff] [blame] | 10 | #include "mojo/public/cpp/bindings/remote.h" |
Takashi Toyoshima | 7a4dcba18 | 2019-07-22 11:28:27 | [diff] [blame] | 11 | #include "mojo/public/cpp/system/data_pipe_producer.h" |
| 12 | #include "mojo/public/cpp/system/string_data_source.h" |
Matt Menke | 5f66421b | 2019-10-24 22:02:04 | [diff] [blame] | 13 | #include "net/base/data_url.h" |
| 14 | #include "net/base/net_errors.h" |
| 15 | #include "net/http/http_response_headers.h" |
Sigurd Schneider | e3d43c6b | 2021-07-27 13:35:01 | [diff] [blame] | 16 | #include "services/network/public/cpp/resource_request.h" |
John Abd-El-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 17 | #include "services/network/public/mojom/url_loader.mojom.h" |
Lucas Furukawa Gadani | b867478 | 2019-12-11 16:22:58 | [diff] [blame] | 18 | #include "services/network/public/mojom/url_response_head.mojom.h" |
John Abd-El-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 19 | |
| 20 | namespace content { |
| 21 | |
| 22 | namespace { |
| 23 | struct WriteData { |
Julie Jeongeun Kim | 6dd4c7b | 2019-11-18 05:56:30 | [diff] [blame] | 24 | mojo::Remote<network::mojom::URLLoaderClient> client; |
John Abd-El-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 25 | std::string data; |
Takashi Toyoshima | 7a4dcba18 | 2019-07-22 11:28:27 | [diff] [blame] | 26 | std::unique_ptr<mojo::DataPipeProducer> producer; |
John Abd-El-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 27 | }; |
| 28 | |
| 29 | void OnWrite(std::unique_ptr<WriteData> write_data, MojoResult result) { |
| 30 | if (result != MOJO_RESULT_OK) { |
John Abd-El-Malek | 075cd21 | 2020-08-31 22:37:23 | [diff] [blame] | 31 | write_data->client->OnComplete( |
| 32 | network::URLLoaderCompletionStatus(net::ERR_FAILED)); |
John Abd-El-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 33 | 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 Anforowicz | 9c5516b | 2020-09-10 01:34:13 | [diff] [blame] | 45 | DataURLLoaderFactory::DataURLLoaderFactory( |
| 46 | const GURL& url, |
| 47 | mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver) |
Lukasz Anforowicz | 25620d3 | 2021-01-27 22:03:44 | [diff] [blame] | 48 | : network::SelfDeletingURLLoaderFactory(std::move(factory_receiver)), |
| 49 | url_(url) {} |
John Abd-El-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 50 | |
Lukasz Anforowicz | 9c5516b | 2020-09-10 01:34:13 | [diff] [blame] | 51 | DataURLLoaderFactory::~DataURLLoaderFactory() = default; |
John Abd-El-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 52 | |
| 53 | void DataURLLoaderFactory::CreateLoaderAndStart( |
Julie Jeongeun Kim | e003de5 | 2019-10-29 05:14:27 | [diff] [blame] | 54 | mojo::PendingReceiver<network::mojom::URLLoader> loader, |
John Abd-El-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 55 | int32_t request_id, |
| 56 | uint32_t options, |
| 57 | const network::ResourceRequest& request, |
Julie Jeongeun Kim | 6dd4c7b | 2019-11-18 05:56:30 | [diff] [blame] | 58 | mojo::PendingRemote<network::mojom::URLLoaderClient> client, |
John Abd-El-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 59 | const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) { |
John Abd-El-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 60 | 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 Menke | 5f66421b | 2019-10-24 22:02:04 | [diff] [blame] | 67 | std::string data; |
| 68 | scoped_refptr<net::HttpResponseHeaders> headers; |
Lucas Furukawa Gadani | b867478 | 2019-12-11 16:22:58 | [diff] [blame] | 69 | 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 Anforowicz | 9c5516b | 2020-09-10 01:34:13 | [diff] [blame] | 73 | |
| 74 | // Users of CreateAndBindForOneSpecificUrl should only submit one load |
| 75 | // request - we won't need the URL anymore. |
| 76 | url_ = GURL(); |
John Abd-El-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 77 | |
Julie Jeongeun Kim | 6dd4c7b | 2019-11-18 05:56:30 | [diff] [blame] | 78 | mojo::Remote<network::mojom::URLLoaderClient> client_remote( |
| 79 | std::move(client)); |
John Abd-El-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 80 | if (result != net::OK) { |
Julie Jeongeun Kim | 6dd4c7b | 2019-11-18 05:56:30 | [diff] [blame] | 81 | client_remote->OnComplete(network::URLLoaderCompletionStatus(result)); |
John Abd-El-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 82 | return; |
| 83 | } |
| 84 | |
John Abd-El-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 85 | mojo::ScopedDataPipeProducerHandle producer; |
| 86 | mojo::ScopedDataPipeConsumerHandle consumer; |
Robert Sesek | 3bce5dd | 2021-02-19 19:27:58 | [diff] [blame] | 87 | if (CreateDataPipe(nullptr, producer, consumer) != MOJO_RESULT_OK) { |
Julie Jeongeun Kim | 6dd4c7b | 2019-11-18 05:56:30 | [diff] [blame] | 88 | client_remote->OnComplete( |
John Abd-El-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 89 | network::URLLoaderCompletionStatus(net::ERR_INSUFFICIENT_RESOURCES)); |
| 90 | return; |
| 91 | } |
| 92 | |
Leszek Swirski | 154cddb | 2022-08-29 17:57:19 | [diff] [blame] | 93 | client_remote->OnReceiveResponse(std::move(response), std::move(consumer), |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 94 | std::nullopt); |
John Abd-El-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 95 | |
| 96 | auto write_data = std::make_unique<WriteData>(); |
Julie Jeongeun Kim | 6dd4c7b | 2019-11-18 05:56:30 | [diff] [blame] | 97 | write_data->client = std::move(client_remote); |
John Abd-El-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 98 | write_data->data = std::move(data); |
| 99 | write_data->producer = |
Takashi Toyoshima | 7a4dcba18 | 2019-07-22 11:28:27 | [diff] [blame] | 100 | std::make_unique<mojo::DataPipeProducer>(std::move(producer)); |
John Abd-El-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 101 | |
Maksim Ivanov | c5edae4 | 2020-08-31 16:44:47 | [diff] [blame] | 102 | mojo::DataPipeProducer* producer_ptr = write_data->producer.get(); |
Md Hasibul Hasan | a963a934 | 2024-04-03 10:15:14 | [diff] [blame] | 103 | std::string_view string_piece(write_data->data); |
John Abd-El-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 104 | |
Maksim Ivanov | c5edae4 | 2020-08-31 16:44:47 | [diff] [blame] | 105 | producer_ptr->Write( |
Takashi Toyoshima | 7a4dcba18 | 2019-07-22 11:28:27 | [diff] [blame] | 106 | 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-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 110 | } |
| 111 | |
Lukasz Anforowicz | 9c5516b | 2020-09-10 01:34:13 | [diff] [blame] | 112 | // static |
| 113 | mojo::PendingRemote<network::mojom::URLLoaderFactory> |
| 114 | DataURLLoaderFactory::Create() { |
| 115 | return CreateForOneSpecificUrl(GURL()); |
| 116 | } |
| 117 | |
| 118 | // static |
| 119 | mojo::PendingRemote<network::mojom::URLLoaderFactory> |
| 120 | DataURLLoaderFactory::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 Anforowicz | 25620d3 | 2021-01-27 22:03:44 | [diff] [blame] | 124 | // receivers - see the network::SelfDeletingURLLoaderFactory::OnDisconnect |
| 125 | // method. |
Lukasz Anforowicz | 9c5516b | 2020-09-10 01:34:13 | [diff] [blame] | 126 | new DataURLLoaderFactory(url, |
| 127 | pending_remote.InitWithNewPipeAndPassReceiver()); |
| 128 | |
| 129 | return pending_remote; |
John Abd-El-Malek | f504747 | 2019-04-22 18:07:36 | [diff] [blame] | 130 | } |
| 131 | |
| 132 | } // namespace content |