OLD | NEW |
| (Empty) |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
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/child/throttling_url_loader.h" | |
6 | |
7 namespace content { | |
8 | |
9 // static | |
10 std::unique_ptr<ThrottlingURLLoader> ThrottlingURLLoader::CreateLoaderAndStart( | |
11 mojom::URLLoaderFactory* factory, | |
12 std::vector<std::unique_ptr<URLLoaderThrottle>> throttles, | |
13 int32_t routing_id, | |
14 int32_t request_id, | |
15 uint32_t options, | |
16 std::unique_ptr<ResourceRequest> url_request, | |
17 mojom::URLLoaderClient* client) { | |
18 std::unique_ptr<ThrottlingURLLoader> loader( | |
19 new ThrottlingURLLoader(std::move(throttles), client)); | |
20 loader->Start(factory, routing_id, request_id, options, | |
21 std::move(url_request)); | |
22 return loader; | |
23 } | |
24 | |
25 ThrottlingURLLoader::~ThrottlingURLLoader() {} | |
26 | |
27 void ThrottlingURLLoader::FollowRedirect() { | |
28 if (url_loader_) | |
29 url_loader_->FollowRedirect(); | |
30 } | |
31 | |
32 void ThrottlingURLLoader::SetPriority(net::RequestPriority priority, | |
33 int32_t intra_priority_value) { | |
34 if (!url_loader_ && !cancelled_by_throttle_) { | |
35 DCHECK_EQ(DEFERRED_START, deferred_stage_); | |
36 set_priority_cached_ = true; | |
37 priority_ = priority; | |
38 intra_priority_value_ = intra_priority_value; | |
39 return; | |
40 } | |
41 | |
42 url_loader_->SetPriority(priority, intra_priority_value); | |
43 } | |
44 | |
45 ThrottlingURLLoader::ThrottlingURLLoader( | |
46 std::vector<std::unique_ptr<URLLoaderThrottle>> throttles, | |
47 mojom::URLLoaderClient* client) | |
48 : forwarding_client_(client), client_binding_(this) { | |
49 if (throttles.size() > 0) { | |
50 // TODO(yzshen): Implement a URLLoaderThrottle subclass which handles a list | |
51 // of URLLoaderThrottles. | |
52 CHECK_EQ(1u, throttles.size()); | |
53 throttle_ = std::move(throttles[0]); | |
54 throttle_->set_delegate(this); | |
55 } | |
56 } | |
57 | |
58 void ThrottlingURLLoader::Start(mojom::URLLoaderFactory* factory, | |
59 int32_t routing_id, | |
60 int32_t request_id, | |
61 uint32_t options, | |
62 std::unique_ptr<ResourceRequest> url_request) { | |
63 DCHECK_EQ(DEFERRED_NONE, deferred_stage_); | |
64 DCHECK(!cancelled_by_throttle_); | |
65 | |
66 if (throttle_) { | |
67 bool deferred = false; | |
68 throttle_->WillStartRequest(url_request->url, url_request->load_flags, | |
69 url_request->resource_type, &deferred); | |
70 if (cancelled_by_throttle_) | |
71 return; | |
72 | |
73 if (deferred) { | |
74 deferred_stage_ = DEFERRED_START; | |
75 url_loader_factory_ = factory; | |
76 routing_id_ = routing_id; | |
77 request_id_ = request_id; | |
78 options_ = options; | |
79 url_request_ = std::move(url_request); | |
80 return; | |
81 } | |
82 } | |
83 | |
84 factory->CreateLoaderAndStart(mojo::MakeRequest(&url_loader_), routing_id, | |
85 request_id, options, *url_request, | |
86 client_binding_.CreateInterfacePtrAndBind()); | |
87 } | |
88 | |
89 void ThrottlingURLLoader::OnReceiveResponse( | |
90 const ResourceResponseHead& response_head, | |
91 const base::Optional<net::SSLInfo>& ssl_info, | |
92 mojom::DownloadedTempFilePtr downloaded_file) { | |
93 DCHECK_EQ(DEFERRED_NONE, deferred_stage_); | |
94 DCHECK(!cancelled_by_throttle_); | |
95 | |
96 if (throttle_) { | |
97 bool deferred = false; | |
98 throttle_->WillProcessResponse(&deferred); | |
99 if (cancelled_by_throttle_) | |
100 return; | |
101 | |
102 if (deferred) { | |
103 deferred_stage_ = DEFERRED_RESPONSE; | |
104 response_head_ = response_head; | |
105 ssl_info_ = ssl_info; | |
106 downloaded_file_ = std::move(downloaded_file); | |
107 client_binding_.PauseIncomingMethodCallProcessing(); | |
108 return; | |
109 } | |
110 } | |
111 | |
112 forwarding_client_->OnReceiveResponse(response_head, ssl_info, | |
113 std::move(downloaded_file)); | |
114 } | |
115 | |
116 void ThrottlingURLLoader::OnReceiveRedirect( | |
117 const net::RedirectInfo& redirect_info, | |
118 const ResourceResponseHead& response_head) { | |
119 DCHECK_EQ(DEFERRED_NONE, deferred_stage_); | |
120 DCHECK(!cancelled_by_throttle_); | |
121 | |
122 if (throttle_) { | |
123 bool deferred = false; | |
124 throttle_->WillRedirectRequest(redirect_info, &deferred); | |
125 if (cancelled_by_throttle_) | |
126 return; | |
127 | |
128 if (deferred) { | |
129 deferred_stage_ = DEFERRED_REDIRECT; | |
130 redirect_info_ = redirect_info; | |
131 response_head_ = response_head; | |
132 client_binding_.PauseIncomingMethodCallProcessing(); | |
133 return; | |
134 } | |
135 } | |
136 | |
137 forwarding_client_->OnReceiveRedirect(redirect_info, response_head); | |
138 } | |
139 | |
140 void ThrottlingURLLoader::OnDataDownloaded(int64_t data_len, | |
141 int64_t encoded_data_len) { | |
142 DCHECK_EQ(DEFERRED_NONE, deferred_stage_); | |
143 DCHECK(!cancelled_by_throttle_); | |
144 | |
145 forwarding_client_->OnDataDownloaded(data_len, encoded_data_len); | |
146 } | |
147 | |
148 void ThrottlingURLLoader::OnUploadProgress( | |
149 int64_t current_position, | |
150 int64_t total_size, | |
151 OnUploadProgressCallback ack_callback) { | |
152 DCHECK_EQ(DEFERRED_NONE, deferred_stage_); | |
153 DCHECK(!cancelled_by_throttle_); | |
154 | |
155 forwarding_client_->OnUploadProgress(current_position, total_size, | |
156 std::move(ack_callback)); | |
157 } | |
158 | |
159 void ThrottlingURLLoader::OnReceiveCachedMetadata( | |
160 const std::vector<uint8_t>& data) { | |
161 DCHECK_EQ(DEFERRED_NONE, deferred_stage_); | |
162 DCHECK(!cancelled_by_throttle_); | |
163 | |
164 forwarding_client_->OnReceiveCachedMetadata(data); | |
165 } | |
166 | |
167 void ThrottlingURLLoader::OnTransferSizeUpdated(int32_t transfer_size_diff) { | |
168 DCHECK_EQ(DEFERRED_NONE, deferred_stage_); | |
169 DCHECK(!cancelled_by_throttle_); | |
170 | |
171 forwarding_client_->OnTransferSizeUpdated(transfer_size_diff); | |
172 } | |
173 | |
174 void ThrottlingURLLoader::OnStartLoadingResponseBody( | |
175 mojo::ScopedDataPipeConsumerHandle body) { | |
176 DCHECK_EQ(DEFERRED_NONE, deferred_stage_); | |
177 DCHECK(!cancelled_by_throttle_); | |
178 | |
179 forwarding_client_->OnStartLoadingResponseBody(std::move(body)); | |
180 } | |
181 | |
182 void ThrottlingURLLoader::OnComplete( | |
183 const ResourceRequestCompletionStatus& status) { | |
184 DCHECK_EQ(DEFERRED_NONE, deferred_stage_); | |
185 DCHECK(!cancelled_by_throttle_); | |
186 | |
187 forwarding_client_->OnComplete(status); | |
188 } | |
189 | |
190 void ThrottlingURLLoader::CancelWithError(int error_code) { | |
191 // TODO(yzshen): Support a mode that cancellation also deletes the disk cache | |
192 // entry. | |
193 if (cancelled_by_throttle_) | |
194 return; | |
195 | |
196 cancelled_by_throttle_ = true; | |
197 | |
198 ResourceRequestCompletionStatus request_complete_data; | |
199 request_complete_data.error_code = error_code; | |
200 request_complete_data.completion_time = base::TimeTicks::Now(); | |
201 | |
202 deferred_stage_ = DEFERRED_NONE; | |
203 client_binding_.Close(); | |
204 url_loader_.reset(); | |
205 | |
206 forwarding_client_->OnComplete(request_complete_data); | |
207 } | |
208 | |
209 void ThrottlingURLLoader::Resume() { | |
210 if (cancelled_by_throttle_ || deferred_stage_ == DEFERRED_NONE) | |
211 return; | |
212 | |
213 switch (deferred_stage_) { | |
214 case DEFERRED_START: { | |
215 url_loader_factory_->CreateLoaderAndStart( | |
216 mojo::MakeRequest(&url_loader_), routing_id_, request_id_, options_, | |
217 *url_request_, client_binding_.CreateInterfacePtrAndBind()); | |
218 | |
219 if (set_priority_cached_) { | |
220 set_priority_cached_ = false; | |
221 url_loader_->SetPriority(priority_, intra_priority_value_); | |
222 } | |
223 break; | |
224 } | |
225 case DEFERRED_REDIRECT: { | |
226 client_binding_.ResumeIncomingMethodCallProcessing(); | |
227 forwarding_client_->OnReceiveRedirect(redirect_info_, response_head_); | |
228 break; | |
229 } | |
230 case DEFERRED_RESPONSE: { | |
231 client_binding_.ResumeIncomingMethodCallProcessing(); | |
232 forwarding_client_->OnReceiveResponse(response_head_, ssl_info_, | |
233 std::move(downloaded_file_)); | |
234 break; | |
235 } | |
236 default: | |
237 NOTREACHED(); | |
238 break; | |
239 } | |
240 deferred_stage_ = DEFERRED_NONE; | |
241 } | |
242 | |
243 } // namespace content | |
OLD | NEW |