forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mime_sniffing_url_loader.h
152 lines (126 loc) · 6.33 KB
/
mime_sniffing_url_loader.h
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Copyright 2018 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 CONTENT_COMMON_MIME_SNIFFING_URL_LOADER_H_
#define CONTENT_COMMON_MIME_SNIFFING_URL_LOADER_H_
#include <tuple>
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_piece.h"
#include "content/common/content_export.h"
#include "content/common/possibly_associated_interface_ptr.h"
#include "content/public/common/url_loader_throttle.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/public/cpp/system/simple_watcher.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
namespace content {
class MimeSniffingThrottle;
// Reads the response body and determines its mime type. This url loader buffers
// the response body until the mime type is decided. MimeSniffingURLLoader
// is expected to be created just after receiving OnReceiveResponse(), so this
// handles only OnStartLoadingResponseBody() and OnComplete() as a
// network::mojom::URLLoaderClient.
//
// This loader has five states:
// kWaitForBody: The initial state until the body is received (=
// OnStartLoadingResponseBody() is called) or the response is
// finished (= OnComplete() is called). When body is provided, the
// state is changed to kSniffing. Otherwise the state goes to
// kCompleted.
// kSniffing: Receives the body from the source loader and estimate the mime
// type. The received body is kept in this loader until the mime type
// is decided. When the mime type is decided or all body has been
// received, this loader will dispatch queued messages like
// OnStartLoadingResponseBody() to the destination
// loader client, and then the state is changed to kSending.
// kSending: Receives the body and sends it to the destination loader client.
// The state changes to kCompleted after all data is sent.
// kCompleted: All data has been sent to the destination loader.
// kAborted: Unexpected behavior happens. Watchers, pipes and the binding from
// the source loader to |this| are stopped. All incoming messages from
// the destination (through network::mojom::URLLoader) are ignored in
// this state.
class CONTENT_EXPORT MimeSniffingURLLoader
: public network::mojom::URLLoaderClient,
public network::mojom::URLLoader {
public:
~MimeSniffingURLLoader() override;
// Start waiting for the body.
void Start(
network::mojom::URLLoaderPtr source_url_loader,
network::mojom::URLLoaderClientRequest source_url_loader_client_request);
// network::mojom::URLLoaderPtr controls the lifetime of the loader.
static std::tuple<network::mojom::URLLoaderPtr,
network::mojom::URLLoaderClientRequest,
MimeSniffingURLLoader*>
CreateLoader(base::WeakPtr<MimeSniffingThrottle> throttle,
const GURL& response_url,
const network::ResourceResponseHead& response_head,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
private:
MimeSniffingURLLoader(
base::WeakPtr<MimeSniffingThrottle> throttle,
const GURL& response_url,
const network::ResourceResponseHead& response_head,
network::mojom::URLLoaderClientPtr destination_url_loader_client,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
// network::mojom::URLLoaderClient implementation (called from the source of
// the response):
void OnReceiveResponse(
const network::ResourceResponseHead& response_head) override;
void OnReceiveRedirect(
const net::RedirectInfo& redirect_info,
const network::ResourceResponseHead& response_head) override;
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback ack_callback) override;
void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override;
void OnComplete(const network::URLLoaderCompletionStatus& status) override;
// network::mojom::URLLoader implementation (called from the destination of
// the response):
void FollowRedirect(const std::vector<std::string>& removed_headers,
const net::HttpRequestHeaders& modified_headers,
const base::Optional<GURL>& new_url) override;
void ProceedWithResponse() override;
void SetPriority(net::RequestPriority priority,
int32_t intra_priority_value) override;
void PauseReadingBodyFromNet() override;
void ResumeReadingBodyFromNet() override;
void OnBodyReadable(MojoResult);
void OnBodyWritable(MojoResult);
void CompleteSniffing();
void CompleteSending();
void SendReceivedBodyToClient();
void ForwardBodyToClient();
void Abort();
static const char kDefaultMimeType[];
base::WeakPtr<MimeSniffingThrottle> throttle_;
mojo::Binding<network::mojom::URLLoaderClient> source_url_client_binding_;
network::mojom::URLLoaderPtr source_url_loader_;
network::mojom::URLLoaderClientPtr destination_url_loader_client_;
GURL response_url_;
// Capture the response head to defer to send it to the destination until the
// mime type is decided.
network::ResourceResponseHead response_head_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
enum class State { kWaitForBody, kSniffing, kSending, kCompleted, kAborted };
State state_ = State::kWaitForBody;
// Set if OnComplete() is called during sniffing.
base::Optional<network::URLLoaderCompletionStatus> complete_status_;
std::vector<char> buffered_body_;
size_t bytes_remaining_in_buffer_;
mojo::ScopedDataPipeConsumerHandle body_consumer_handle_;
mojo::ScopedDataPipeProducerHandle body_producer_handle_;
mojo::SimpleWatcher body_consumer_watcher_;
mojo::SimpleWatcher body_producer_watcher_;
DISALLOW_COPY_AND_ASSIGN(MimeSniffingURLLoader);
};
} // namespace content
#endif // CONTENT_COMMON_MIME_SNIFFING_URL_LOADER_H_