1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
content / browser / data_url_loader_factory.cc [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/data_url_loader_factory.h"
#include <string_view>
#include "base/memory/ref_counted.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/data_pipe_producer.h"
#include "mojo/public/cpp/system/string_data_source.h"
#include "net/base/data_url.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
namespace content {
namespace {
struct WriteData {
mojo::Remote<network::mojom::URLLoaderClient> client;
std::string data;
std::unique_ptr<mojo::DataPipeProducer> producer;
};
void OnWrite(std::unique_ptr<WriteData> write_data, MojoResult result) {
if (result != MOJO_RESULT_OK) {
write_data->client->OnComplete(
network::URLLoaderCompletionStatus(net::ERR_FAILED));
return;
}
network::URLLoaderCompletionStatus status(net::OK);
status.encoded_data_length = write_data->data.size();
status.encoded_body_length = write_data->data.size();
status.decoded_body_length = write_data->data.size();
write_data->client->OnComplete(status);
}
} // namespace
DataURLLoaderFactory::DataURLLoaderFactory(
const GURL& url,
mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver)
: network::SelfDeletingURLLoaderFactory(std::move(factory_receiver)),
url_(url) {}
DataURLLoaderFactory::~DataURLLoaderFactory() = default;
void DataURLLoaderFactory::CreateLoaderAndStart(
mojo::PendingReceiver<network::mojom::URLLoader> loader,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& request,
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
const GURL* url = nullptr;
if (!url_.is_empty() && request.url.is_empty()) {
url = &url_;
} else {
url = &request.url;
}
std::string data;
scoped_refptr<net::HttpResponseHeaders> headers;
auto response = network::mojom::URLResponseHead::New();
net::Error result = net::DataURL::BuildResponse(
*url, request.method, &response->mime_type, &response->charset, &data,
&response->headers);
// Users of CreateAndBindForOneSpecificUrl should only submit one load
// request - we won't need the URL anymore.
url_ = GURL();
mojo::Remote<network::mojom::URLLoaderClient> client_remote(
std::move(client));
if (result != net::OK) {
client_remote->OnComplete(network::URLLoaderCompletionStatus(result));
return;
}
mojo::ScopedDataPipeProducerHandle producer;
mojo::ScopedDataPipeConsumerHandle consumer;
if (CreateDataPipe(nullptr, producer, consumer) != MOJO_RESULT_OK) {
client_remote->OnComplete(
network::URLLoaderCompletionStatus(net::ERR_INSUFFICIENT_RESOURCES));
return;
}
client_remote->OnReceiveResponse(std::move(response), std::move(consumer),
std::nullopt);
auto write_data = std::make_unique<WriteData>();
write_data->client = std::move(client_remote);
write_data->data = std::move(data);
write_data->producer =
std::make_unique<mojo::DataPipeProducer>(std::move(producer));
mojo::DataPipeProducer* producer_ptr = write_data->producer.get();
std::string_view string_piece(write_data->data);
producer_ptr->Write(
std::make_unique<mojo::StringDataSource>(
string_piece, mojo::StringDataSource::AsyncWritingMode::
STRING_STAYS_VALID_UNTIL_COMPLETION),
base::BindOnce(OnWrite, std::move(write_data)));
}
// static
mojo::PendingRemote<network::mojom::URLLoaderFactory>
DataURLLoaderFactory::Create() {
return CreateForOneSpecificUrl(GURL());
}
// static
mojo::PendingRemote<network::mojom::URLLoaderFactory>
DataURLLoaderFactory::CreateForOneSpecificUrl(const GURL& url) {
mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_remote;
// The DataURLLoaderFactory will delete itself when there are no more
// receivers - see the network::SelfDeletingURLLoaderFactory::OnDisconnect
// method.
new DataURLLoaderFactory(url,
pending_remote.InitWithNewPipeAndPassReceiver());
return pending_remote;
}
} // namespace content