OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/loader/mime_sniffing_resource_handler.h" | 5 #include "content/browser/loader/mime_sniffing_resource_handler.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/location.h" | 11 #include "base/location.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/metrics/histogram_macros.h" | 13 #include "base/metrics/histogram_macros.h" |
14 #include "base/single_thread_task_runner.h" | 14 #include "base/single_thread_task_runner.h" |
15 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
16 #include "base/threading/thread_task_runner_handle.h" | 16 #include "base/threading/thread_task_runner_handle.h" |
17 #include "components/mime_util/mime_util.h" | 17 #include "components/mime_util/mime_util.h" |
18 #include "content/browser/download/download_resource_handler.h" | 18 #include "content/browser/download/download_resource_handler.h" |
19 #include "content/browser/download/download_stats.h" | 19 #include "content/browser/download/download_stats.h" |
20 #include "content/browser/loader/intercepting_resource_handler.h" | 20 #include "content/browser/loader/intercepting_resource_handler.h" |
21 #include "content/browser/loader/resource_controller.h" | |
21 #include "content/browser/loader/resource_dispatcher_host_impl.h" | 22 #include "content/browser/loader/resource_dispatcher_host_impl.h" |
22 #include "content/browser/loader/resource_request_info_impl.h" | 23 #include "content/browser/loader/resource_request_info_impl.h" |
23 #include "content/browser/loader/stream_resource_handler.h" | 24 #include "content/browser/loader/stream_resource_handler.h" |
24 #include "content/public/browser/content_browser_client.h" | 25 #include "content/public/browser/content_browser_client.h" |
25 #include "content/public/browser/download_item.h" | 26 #include "content/public/browser/download_item.h" |
26 #include "content/public/browser/download_save_info.h" | 27 #include "content/public/browser/download_save_info.h" |
27 #include "content/public/browser/download_url_parameters.h" | 28 #include "content/public/browser/download_url_parameters.h" |
28 #include "content/public/browser/plugin_service.h" | 29 #include "content/public/browser/plugin_service.h" |
29 #include "content/public/browser/resource_context.h" | 30 #include "content/public/browser/resource_context.h" |
30 #include "content/public/browser/resource_dispatcher_host_delegate.h" | 31 #include "content/public/browser/resource_dispatcher_host_delegate.h" |
(...skipping 27 matching lines...) Expand all Loading... | |
58 : net::WrappedIOBuffer(buf->data() + offset), buf_(buf) {} | 59 : net::WrappedIOBuffer(buf->data() + offset), buf_(buf) {} |
59 | 60 |
60 private: | 61 private: |
61 ~DependentIOBuffer() override {} | 62 ~DependentIOBuffer() override {} |
62 | 63 |
63 scoped_refptr<net::IOBuffer> buf_; | 64 scoped_refptr<net::IOBuffer> buf_; |
64 }; | 65 }; |
65 | 66 |
66 } // namespace | 67 } // namespace |
67 | 68 |
69 class MimeSniffingResourceHandler::Controller : public ResourceController { | |
Charlie Harrison
2017/01/25 20:22:59
This looks just like a couple of other controllers
mmenke
2017/01/25 22:07:59
I think there are only two classes like this? Res
Charlie Harrison
2017/01/26 00:25:50
Yeah, I probably just looked at this one 5 times a
| |
70 public: | |
71 explicit Controller(MimeSniffingResourceHandler* mime_handler) | |
72 : mime_handler_(mime_handler) {} | |
73 | |
74 void Resume() override { | |
75 DCHECK(!used_); | |
76 used_ = true; | |
77 mime_handler_->ResumeInternal(); | |
78 } | |
79 | |
80 void Cancel() override { | |
81 DCHECK(!used_); | |
82 used_ = true; | |
83 mime_handler_->Cancel(); | |
84 } | |
85 | |
86 void CancelAndIgnore() override { | |
87 DCHECK(!used_); | |
88 used_ = true; | |
89 mime_handler_->CancelAndIgnore(); | |
90 } | |
91 | |
92 void CancelWithError(int error_code) override { | |
93 DCHECK(!used_); | |
94 used_ = true; | |
95 mime_handler_->CancelWithError(error_code); | |
96 } | |
97 | |
98 private: | |
99 MimeSniffingResourceHandler* mime_handler_; | |
100 bool used_ = false; | |
101 | |
102 DISALLOW_COPY_AND_ASSIGN(Controller); | |
103 }; | |
104 | |
68 MimeSniffingResourceHandler::MimeSniffingResourceHandler( | 105 MimeSniffingResourceHandler::MimeSniffingResourceHandler( |
69 std::unique_ptr<ResourceHandler> next_handler, | 106 std::unique_ptr<ResourceHandler> next_handler, |
70 ResourceDispatcherHostImpl* host, | 107 ResourceDispatcherHostImpl* host, |
71 PluginService* plugin_service, | 108 PluginService* plugin_service, |
72 InterceptingResourceHandler* intercepting_handler, | 109 InterceptingResourceHandler* intercepting_handler, |
73 net::URLRequest* request, | 110 net::URLRequest* request, |
74 RequestContextType request_context_type) | 111 RequestContextType request_context_type) |
75 : LayeredResourceHandler(request, std::move(next_handler)), | 112 : LayeredResourceHandler(request, std::move(next_handler)), |
76 state_(STATE_STARTING), | 113 state_(STATE_STARTING), |
77 host_(host), | 114 host_(host), |
78 #if BUILDFLAG(ENABLE_PLUGINS) | 115 #if BUILDFLAG(ENABLE_PLUGINS) |
79 plugin_service_(plugin_service), | 116 plugin_service_(plugin_service), |
80 #endif | 117 #endif |
81 must_download_(false), | 118 must_download_(false), |
82 must_download_is_set_(false), | 119 must_download_is_set_(false), |
83 read_buffer_size_(0), | 120 read_buffer_size_(0), |
84 bytes_read_(0), | 121 bytes_read_(0), |
85 intercepting_handler_(intercepting_handler), | 122 intercepting_handler_(intercepting_handler), |
86 request_context_type_(request_context_type), | 123 request_context_type_(request_context_type), |
124 in_state_loop_(false), | |
125 advance_state_(false), | |
87 weak_ptr_factory_(this) { | 126 weak_ptr_factory_(this) { |
88 } | 127 } |
89 | 128 |
90 MimeSniffingResourceHandler::~MimeSniffingResourceHandler() {} | 129 MimeSniffingResourceHandler::~MimeSniffingResourceHandler() {} |
91 | 130 |
92 void MimeSniffingResourceHandler::SetController( | 131 void MimeSniffingResourceHandler::OnWillStart( |
93 ResourceController* controller) { | 132 const GURL& url, |
94 ResourceHandler::SetController(controller); | 133 std::unique_ptr<ResourceController> controller) { |
134 DCHECK(!has_controller()); | |
95 | 135 |
96 // Downstream handlers see the MimeSniffingResourceHandler as their | |
97 // ResourceController, which allows it to consume part or all of the resource | |
98 // response, and then later replay it to downstream handler. | |
99 DCHECK(next_handler_.get()); | |
100 next_handler_->SetController(this); | |
101 } | |
102 | |
103 bool MimeSniffingResourceHandler::OnWillStart(const GURL& url, bool* defer) { | |
104 const char* accept_value = nullptr; | 136 const char* accept_value = nullptr; |
105 switch (GetRequestInfo()->GetResourceType()) { | 137 switch (GetRequestInfo()->GetResourceType()) { |
106 case RESOURCE_TYPE_MAIN_FRAME: | 138 case RESOURCE_TYPE_MAIN_FRAME: |
107 case RESOURCE_TYPE_SUB_FRAME: | 139 case RESOURCE_TYPE_SUB_FRAME: |
108 accept_value = kFrameAcceptHeader; | 140 accept_value = kFrameAcceptHeader; |
109 break; | 141 break; |
110 case RESOURCE_TYPE_STYLESHEET: | 142 case RESOURCE_TYPE_STYLESHEET: |
111 accept_value = kStylesheetAcceptHeader; | 143 accept_value = kStylesheetAcceptHeader; |
112 break; | 144 break; |
113 case RESOURCE_TYPE_FAVICON: | 145 case RESOURCE_TYPE_FAVICON: |
(...skipping 16 matching lines...) Expand all Loading... | |
130 accept_value = kDefaultAcceptHeader; | 162 accept_value = kDefaultAcceptHeader; |
131 break; | 163 break; |
132 case RESOURCE_TYPE_LAST_TYPE: | 164 case RESOURCE_TYPE_LAST_TYPE: |
133 NOTREACHED(); | 165 NOTREACHED(); |
134 break; | 166 break; |
135 } | 167 } |
136 | 168 |
137 // The false parameter prevents overwriting an existing accept header value, | 169 // The false parameter prevents overwriting an existing accept header value, |
138 // which is needed because JS can manually set an accept header on an XHR. | 170 // which is needed because JS can manually set an accept header on an XHR. |
139 request()->SetExtraRequestHeaderByName(kAcceptHeader, accept_value, false); | 171 request()->SetExtraRequestHeaderByName(kAcceptHeader, accept_value, false); |
140 return next_handler_->OnWillStart(url, defer); | 172 next_handler_->OnWillStart(url, std::move(controller)); |
141 } | 173 } |
142 | 174 |
143 bool MimeSniffingResourceHandler::OnResponseStarted(ResourceResponse* response, | 175 void MimeSniffingResourceHandler::OnResponseStarted( |
144 bool* defer) { | 176 ResourceResponse* response, |
177 std::unique_ptr<ResourceController> controller) { | |
145 DCHECK_EQ(STATE_STARTING, state_); | 178 DCHECK_EQ(STATE_STARTING, state_); |
179 DCHECK(!has_controller()); | |
180 | |
146 response_ = response; | 181 response_ = response; |
147 | 182 |
148 state_ = STATE_BUFFERING; | 183 state_ = STATE_BUFFERING; |
149 // A 304 response should not contain a Content-Type header (RFC 7232 section | 184 // A 304 response should not contain a Content-Type header (RFC 7232 section |
150 // 4.1). The following code may incorrectly attempt to add a Content-Type to | 185 // 4.1). The following code may incorrectly attempt to add a Content-Type to |
151 // the response, and so must be skipped for 304 responses. | 186 // the response, and so must be skipped for 304 responses. |
152 if (!(response_->head.headers.get() && | 187 if (!(response_->head.headers.get() && |
153 response_->head.headers->response_code() == 304)) { | 188 response_->head.headers->response_code() == 304)) { |
154 if (ShouldSniffContent()) | 189 if (ShouldSniffContent()) { |
155 return true; | 190 controller->Resume(); |
191 return; | |
192 } | |
156 | 193 |
157 if (response_->head.mime_type.empty()) { | 194 if (response_->head.mime_type.empty()) { |
158 // Ugg. The server told us not to sniff the content but didn't give us a | 195 // Ugg. The server told us not to sniff the content but didn't give us a |
159 // mime type. What's a browser to do? Turns out, we're supposed to | 196 // mime type. What's a browser to do? Turns out, we're supposed to |
160 // treat the response as "text/plain". This is the most secure option. | 197 // treat the response as "text/plain". This is the most secure option. |
161 response_->head.mime_type.assign("text/plain"); | 198 response_->head.mime_type.assign("text/plain"); |
162 } | 199 } |
163 | 200 |
164 // Treat feed types as text/plain. | 201 // Treat feed types as text/plain. |
165 if (response_->head.mime_type == "application/rss+xml" || | 202 if (response_->head.mime_type == "application/rss+xml" || |
166 response_->head.mime_type == "application/atom+xml") { | 203 response_->head.mime_type == "application/atom+xml") { |
167 response_->head.mime_type.assign("text/plain"); | 204 response_->head.mime_type.assign("text/plain"); |
168 } | 205 } |
169 } | 206 } |
170 | 207 |
171 return ProcessState(defer); | 208 HoldController(std::move(controller)); |
209 AdvanceState(); | |
172 } | 210 } |
173 | 211 |
174 bool MimeSniffingResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, | 212 bool MimeSniffingResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, |
175 int* buf_size, | 213 int* buf_size, |
176 int min_size) { | 214 int min_size) { |
177 if (state_ == STATE_STREAMING) | 215 if (state_ == STATE_STREAMING) |
178 return next_handler_->OnWillRead(buf, buf_size, min_size); | 216 return next_handler_->OnWillRead(buf, buf_size, min_size); |
179 | 217 |
180 DCHECK_EQ(-1, min_size); | 218 DCHECK_EQ(-1, min_size); |
181 | 219 |
182 if (read_buffer_.get()) { | 220 if (read_buffer_.get()) { |
183 CHECK_LT(bytes_read_, read_buffer_size_); | 221 CHECK_LT(bytes_read_, read_buffer_size_); |
184 *buf = new DependentIOBuffer(read_buffer_.get(), bytes_read_); | 222 *buf = new DependentIOBuffer(read_buffer_.get(), bytes_read_); |
185 *buf_size = read_buffer_size_ - bytes_read_; | 223 *buf_size = read_buffer_size_ - bytes_read_; |
186 } else { | 224 } else { |
187 if (!next_handler_->OnWillRead(buf, buf_size, min_size)) | 225 if (!next_handler_->OnWillRead(buf, buf_size, min_size)) |
188 return false; | 226 return false; |
189 | 227 |
190 read_buffer_ = *buf; | 228 read_buffer_ = *buf; |
191 read_buffer_size_ = *buf_size; | 229 read_buffer_size_ = *buf_size; |
192 DCHECK_GE(read_buffer_size_, net::kMaxBytesToSniff * 2); | 230 DCHECK_GE(read_buffer_size_, net::kMaxBytesToSniff * 2); |
193 } | 231 } |
194 return true; | 232 return true; |
195 } | 233 } |
196 | 234 |
197 bool MimeSniffingResourceHandler::OnReadCompleted(int bytes_read, bool* defer) { | 235 void MimeSniffingResourceHandler::OnReadCompleted( |
198 if (state_ == STATE_STREAMING) | 236 int bytes_read, |
199 return next_handler_->OnReadCompleted(bytes_read, defer); | 237 std::unique_ptr<ResourceController> controller) { |
238 DCHECK(!has_controller()); | |
239 | |
240 if (state_ == STATE_STREAMING) { | |
241 next_handler_->OnReadCompleted(bytes_read, std::move(controller)); | |
242 return; | |
243 } | |
200 | 244 |
201 DCHECK_EQ(state_, STATE_BUFFERING); | 245 DCHECK_EQ(state_, STATE_BUFFERING); |
202 bytes_read_ += bytes_read; | 246 bytes_read_ += bytes_read; |
203 | 247 |
204 const std::string& type_hint = response_->head.mime_type; | 248 const std::string& type_hint = response_->head.mime_type; |
205 | 249 |
206 std::string new_type; | 250 std::string new_type; |
207 bool made_final_decision = | 251 bool made_final_decision = |
208 net::SniffMimeType(read_buffer_->data(), bytes_read_, request()->url(), | 252 net::SniffMimeType(read_buffer_->data(), bytes_read_, request()->url(), |
209 type_hint, &new_type); | 253 type_hint, &new_type); |
210 | 254 |
211 // SniffMimeType() returns false if there is not enough data to determine | 255 // SniffMimeType() returns false if there is not enough data to determine |
212 // the mime type. However, even if it returns false, it returns a new type | 256 // the mime type. However, even if it returns false, it returns a new type |
213 // that is probably better than the current one. | 257 // that is probably better than the current one. |
214 response_->head.mime_type.assign(new_type); | 258 response_->head.mime_type.assign(new_type); |
215 | 259 |
216 if (!made_final_decision && (bytes_read > 0)) | 260 if (!made_final_decision && (bytes_read > 0)) { |
217 return true; | 261 controller->Resume(); |
262 return; | |
263 } | |
218 | 264 |
219 return ProcessState(defer); | 265 HoldController(std::move(controller)); |
266 AdvanceState(); | |
220 } | 267 } |
221 | 268 |
222 void MimeSniffingResourceHandler::OnResponseCompleted( | 269 void MimeSniffingResourceHandler::OnResponseCompleted( |
223 const net::URLRequestStatus& status, | 270 const net::URLRequestStatus& status, |
224 bool* defer) { | 271 std::unique_ptr<ResourceController> resource_controller) { |
225 // Upon completion, act like a pass-through handler in case the downstream | 272 // Upon completion, act like a pass-through handler in case the downstream |
226 // handler defers OnResponseCompleted. | 273 // handler defers OnResponseCompleted. |
227 state_ = STATE_STREAMING; | 274 state_ = STATE_STREAMING; |
228 | 275 |
229 next_handler_->OnResponseCompleted(status, defer); | 276 next_handler_->OnResponseCompleted(status, std::move(resource_controller)); |
230 } | 277 } |
231 | 278 |
232 void MimeSniffingResourceHandler::Resume() { | 279 void MimeSniffingResourceHandler::ResumeInternal() { |
280 DCHECK_NE(state_, STATE_BUFFERING); | |
281 DCHECK(!advance_state_); | |
282 | |
233 // If no information is currently being transmitted to downstream handlers, | 283 // If no information is currently being transmitted to downstream handlers, |
234 // they should not attempt to resume the request. | 284 // they should not attempt to resume the request. |
235 if (state_ == STATE_BUFFERING) { | 285 if (state_ == STATE_BUFFERING) { |
236 NOTREACHED(); | 286 NOTREACHED(); |
Charlie Harrison
2017/01/25 20:22:59
Unnecessary NOTREACHED() with the DCHECK above. It
mmenke
2017/01/25 22:07:59
I left this as it is mostly because of the sheer s
Charlie Harrison
2017/01/26 00:25:50
Acknowledged.
| |
237 return; | 287 return; |
238 } | 288 } |
239 | 289 |
240 // If the BufferingHandler is acting as a pass-through handler, just ask the | 290 if (in_state_loop_) { |
241 // upwards ResourceController to resume the request. | 291 advance_state_ = true; |
242 if (state_ == STATE_STARTING || state_ == STATE_STREAMING) { | |
243 controller()->Resume(); | |
244 return; | 292 return; |
245 } | 293 } |
246 | 294 |
247 // Otherwise proceed with the replay of the response. If it is successful, | 295 // Otherwise proceed with the replay of the response. If it is successful, |
248 // it will resume the request. Posted as a task to avoid re-entrancy into | 296 // it will resume the request. Posted as a task to avoid re-entrancy into |
249 // the calling class. | 297 // the calling class. |
250 base::ThreadTaskRunnerHandle::Get()->PostTask( | 298 base::ThreadTaskRunnerHandle::Get()->PostTask( |
251 FROM_HERE, base::Bind(&MimeSniffingResourceHandler::AdvanceState, | 299 FROM_HERE, base::Bind(&MimeSniffingResourceHandler::AdvanceState, |
252 weak_ptr_factory_.GetWeakPtr())); | 300 weak_ptr_factory_.GetWeakPtr())); |
253 } | 301 } |
254 | 302 |
255 void MimeSniffingResourceHandler::Cancel() { | 303 void MimeSniffingResourceHandler::AdvanceState() { |
256 controller()->Cancel(); | 304 DCHECK(!in_state_loop_); |
257 } | 305 DCHECK(!advance_state_); |
258 | 306 |
259 void MimeSniffingResourceHandler::CancelAndIgnore() { | 307 in_state_loop_ = true; |
260 controller()->CancelAndIgnore(); | 308 advance_state_ = true; |
261 } | 309 while (advance_state_) { |
310 advance_state_ = false; | |
262 | 311 |
263 void MimeSniffingResourceHandler::CancelWithError(int error_code) { | |
264 controller()->CancelWithError(error_code); | |
265 } | |
266 | |
267 void MimeSniffingResourceHandler::AdvanceState() { | |
268 bool defer = false; | |
269 if (!ProcessState(&defer)) { | |
270 Cancel(); | |
271 } else if (!defer) { | |
272 DCHECK_EQ(STATE_STREAMING, state_); | |
273 controller()->Resume(); | |
274 } | |
275 } | |
276 | |
277 bool MimeSniffingResourceHandler::ProcessState(bool* defer) { | |
278 bool return_value = true; | |
279 while (!*defer && return_value && state_ != STATE_STREAMING) { | |
280 switch (state_) { | 312 switch (state_) { |
281 case STATE_BUFFERING: | 313 case STATE_BUFFERING: |
282 return_value = MaybeIntercept(defer); | 314 MaybeIntercept(); |
283 break; | 315 break; |
284 case STATE_INTERCEPTION_CHECK_DONE: | 316 case STATE_INTERCEPTION_CHECK_DONE: |
285 return_value = ReplayResponseReceived(defer); | 317 ReplayResponseReceived(); |
286 break; | 318 break; |
287 case STATE_REPLAYING_RESPONSE_RECEIVED: | 319 case STATE_REPLAYING_RESPONSE_RECEIVED: |
288 return_value = ReplayReadCompleted(defer); | 320 ReplayReadCompleted(); |
289 break; | 321 break; |
322 case STATE_STARTING: | |
323 case STATE_STREAMING: | |
324 in_state_loop_ = false; | |
325 Resume(); | |
326 return; | |
290 default: | 327 default: |
291 NOTREACHED(); | 328 NOTREACHED(); |
292 break; | 329 break; |
293 } | 330 } |
294 } | 331 } |
295 return return_value; | 332 |
333 DCHECK(in_state_loop_); | |
334 in_state_loop_ = false; | |
296 } | 335 } |
297 | 336 |
298 bool MimeSniffingResourceHandler::MaybeIntercept(bool* defer) { | 337 void MimeSniffingResourceHandler::MaybeIntercept() { |
299 DCHECK_EQ(STATE_BUFFERING, state_); | 338 DCHECK_EQ(STATE_BUFFERING, state_); |
300 // If a request that can be intercepted failed the check for interception | 339 // If a request that can be intercepted failed the check for interception |
301 // step, it should be canceled. | 340 // step, it should be canceled. |
302 if (!MaybeStartInterception(defer)) | 341 if (!MaybeStartInterception()) |
303 return false; | 342 return; |
304 | 343 |
305 if (!*defer) | 344 state_ = STATE_INTERCEPTION_CHECK_DONE; |
306 state_ = STATE_INTERCEPTION_CHECK_DONE; | 345 ResumeInternal(); |
307 | |
308 return true; | |
309 } | 346 } |
310 | 347 |
311 bool MimeSniffingResourceHandler::ReplayResponseReceived(bool* defer) { | 348 void MimeSniffingResourceHandler::ReplayResponseReceived() { |
312 DCHECK_EQ(STATE_INTERCEPTION_CHECK_DONE, state_); | 349 DCHECK_EQ(STATE_INTERCEPTION_CHECK_DONE, state_); |
313 state_ = STATE_REPLAYING_RESPONSE_RECEIVED; | 350 state_ = STATE_REPLAYING_RESPONSE_RECEIVED; |
314 return next_handler_->OnResponseStarted(response_.get(), defer); | 351 next_handler_->OnResponseStarted(response_.get(), |
352 base::MakeUnique<Controller>(this)); | |
315 } | 353 } |
316 | 354 |
317 bool MimeSniffingResourceHandler::ReplayReadCompleted(bool* defer) { | 355 void MimeSniffingResourceHandler::ReplayReadCompleted() { |
318 DCHECK_EQ(STATE_REPLAYING_RESPONSE_RECEIVED, state_); | 356 DCHECK_EQ(STATE_REPLAYING_RESPONSE_RECEIVED, state_); |
319 | 357 |
320 state_ = STATE_STREAMING; | 358 state_ = STATE_STREAMING; |
321 | 359 |
322 if (!read_buffer_.get()) | 360 if (!read_buffer_.get()) { |
323 return true; | 361 ResumeInternal(); |
362 return; | |
363 } | |
324 | 364 |
325 bool result = next_handler_->OnReadCompleted(bytes_read_, defer); | 365 int bytes_read = bytes_read_; |
326 | 366 |
327 read_buffer_ = nullptr; | 367 read_buffer_ = nullptr; |
328 read_buffer_size_ = 0; | 368 read_buffer_size_ = 0; |
329 bytes_read_ = 0; | 369 bytes_read_ = 0; |
330 | 370 |
331 return result; | 371 next_handler_->OnReadCompleted(bytes_read, |
372 base::MakeUnique<Controller>(this)); | |
332 } | 373 } |
333 | 374 |
334 bool MimeSniffingResourceHandler::ShouldSniffContent() { | 375 bool MimeSniffingResourceHandler::ShouldSniffContent() { |
335 if (request_context_type_ == REQUEST_CONTEXT_TYPE_FETCH) { | 376 if (request_context_type_ == REQUEST_CONTEXT_TYPE_FETCH) { |
336 // MIME sniffing should be disabled for a request initiated by fetch(). | 377 // MIME sniffing should be disabled for a request initiated by fetch(). |
337 return false; | 378 return false; |
338 } | 379 } |
339 | 380 |
340 const std::string& mime_type = response_->head.mime_type; | 381 const std::string& mime_type = response_->head.mime_type; |
341 | 382 |
(...skipping 10 matching lines...) Expand all Loading... | |
352 // We're going to look at the data before deciding what the content type | 393 // We're going to look at the data before deciding what the content type |
353 // is. That means we need to delay sending the ResponseStarted message | 394 // is. That means we need to delay sending the ResponseStarted message |
354 // over the IPC channel. | 395 // over the IPC channel. |
355 VLOG(1) << "To buffer: " << request()->url().spec(); | 396 VLOG(1) << "To buffer: " << request()->url().spec(); |
356 return true; | 397 return true; |
357 } | 398 } |
358 | 399 |
359 return false; | 400 return false; |
360 } | 401 } |
361 | 402 |
362 bool MimeSniffingResourceHandler::MaybeStartInterception(bool* defer) { | 403 bool MimeSniffingResourceHandler::MaybeStartInterception() { |
363 if (!CanBeIntercepted()) | 404 if (!CanBeIntercepted()) |
364 return true; | 405 return true; |
365 | 406 |
366 DCHECK(!response_->head.mime_type.empty()); | 407 DCHECK(!response_->head.mime_type.empty()); |
367 | 408 |
368 ResourceRequestInfoImpl* info = GetRequestInfo(); | 409 ResourceRequestInfoImpl* info = GetRequestInfo(); |
369 const std::string& mime_type = response_->head.mime_type; | 410 const std::string& mime_type = response_->head.mime_type; |
370 | 411 |
371 // Allow requests for object/embed tags to be intercepted as streams. | 412 // Allow requests for object/embed tags to be intercepted as streams. |
372 if (info->GetResourceType() == content::RESOURCE_TYPE_OBJECT) { | 413 if (info->GetResourceType() == content::RESOURCE_TYPE_OBJECT) { |
373 DCHECK(!info->allow_download()); | 414 DCHECK(!info->allow_download()); |
374 | 415 |
375 bool handled_by_plugin; | 416 bool handled_by_plugin; |
376 if (!CheckForPluginHandler(defer, &handled_by_plugin)) | 417 if (!CheckForPluginHandler(&handled_by_plugin)) |
377 return false; | 418 return false; |
378 if (handled_by_plugin || *defer) | 419 if (handled_by_plugin) |
379 return true; | 420 return true; |
380 } | 421 } |
381 | 422 |
382 if (!info->allow_download()) | 423 if (!info->allow_download()) |
383 return true; | 424 return true; |
384 | 425 |
385 // info->allow_download() == true implies | 426 // info->allow_download() == true implies |
386 // info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME or | 427 // info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME or |
387 // info->GetResourceType() == RESOURCE_TYPE_SUB_FRAME. | 428 // info->GetResourceType() == RESOURCE_TYPE_SUB_FRAME. |
388 DCHECK(info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME || | 429 DCHECK(info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME || |
389 info->GetResourceType() == RESOURCE_TYPE_SUB_FRAME); | 430 info->GetResourceType() == RESOURCE_TYPE_SUB_FRAME); |
390 | 431 |
391 bool must_download = MustDownload(); | 432 bool must_download = MustDownload(); |
392 if (!must_download) { | 433 if (!must_download) { |
393 if (mime_util::IsSupportedMimeType(mime_type)) | 434 if (mime_util::IsSupportedMimeType(mime_type)) |
394 return true; | 435 return true; |
395 | 436 |
396 bool handled_by_plugin; | 437 bool handled_by_plugin; |
397 if (!CheckForPluginHandler(defer, &handled_by_plugin)) | 438 if (!CheckForPluginHandler(&handled_by_plugin)) |
398 return false; | 439 return false; |
399 if (handled_by_plugin || *defer) | 440 if (handled_by_plugin) |
400 return true; | 441 return true; |
401 } | 442 } |
402 | 443 |
403 // This request is a download. | 444 // This request is a download. |
404 | 445 |
405 if (!CheckResponseIsNotProvisional()) | 446 if (!CheckResponseIsNotProvisional()) |
406 return false; | 447 return false; |
407 | 448 |
408 info->set_is_download(true); | 449 info->set_is_download(true); |
409 std::unique_ptr<ResourceHandler> handler( | 450 std::unique_ptr<ResourceHandler> handler( |
410 host_->CreateResourceHandlerForDownload(request(), | 451 host_->CreateResourceHandlerForDownload(request(), |
411 true, // is_content_initiated | 452 true, // is_content_initiated |
412 must_download, | 453 must_download, |
413 false /* is_new_request */)); | 454 false /* is_new_request */)); |
414 intercepting_handler_->UseNewHandler(std::move(handler), std::string()); | 455 intercepting_handler_->UseNewHandler(std::move(handler), std::string()); |
415 return true; | 456 return true; |
416 } | 457 } |
417 | 458 |
418 bool MimeSniffingResourceHandler::CheckForPluginHandler( | 459 bool MimeSniffingResourceHandler::CheckForPluginHandler( |
419 bool* defer, | |
420 bool* handled_by_plugin) { | 460 bool* handled_by_plugin) { |
421 *handled_by_plugin = false; | 461 *handled_by_plugin = false; |
422 #if BUILDFLAG(ENABLE_PLUGINS) | 462 #if BUILDFLAG(ENABLE_PLUGINS) |
423 ResourceRequestInfoImpl* info = GetRequestInfo(); | 463 ResourceRequestInfoImpl* info = GetRequestInfo(); |
424 bool allow_wildcard = false; | 464 bool allow_wildcard = false; |
425 bool stale; | 465 bool stale; |
426 WebPluginInfo plugin; | 466 WebPluginInfo plugin; |
427 bool has_plugin = plugin_service_->GetPluginInfo( | 467 bool has_plugin = plugin_service_->GetPluginInfo( |
428 info->GetChildID(), info->GetRenderFrameID(), info->GetContext(), | 468 info->GetChildID(), info->GetRenderFrameID(), info->GetContext(), |
429 request()->url(), url::Origin(), response_->head.mime_type, | 469 request()->url(), url::Origin(), response_->head.mime_type, |
430 allow_wildcard, &stale, &plugin, NULL); | 470 allow_wildcard, &stale, &plugin, NULL); |
431 | 471 |
432 if (stale) { | 472 if (stale) { |
433 // Refresh the plugins asynchronously. | 473 // Refresh the plugins asynchronously. |
434 plugin_service_->GetPlugins( | 474 plugin_service_->GetPlugins( |
435 base::Bind(&MimeSniffingResourceHandler::OnPluginsLoaded, | 475 base::Bind(&MimeSniffingResourceHandler::OnPluginsLoaded, |
436 weak_ptr_factory_.GetWeakPtr())); | 476 weak_ptr_factory_.GetWeakPtr())); |
437 request()->LogBlockedBy("MimeSniffingResourceHandler"); | 477 request()->LogBlockedBy("MimeSniffingResourceHandler"); |
438 *defer = true; | 478 // Will complete asynchronously. |
439 return true; | 479 return false; |
440 } | 480 } |
441 | 481 |
442 if (has_plugin && plugin.type != WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN) { | 482 if (has_plugin && plugin.type != WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN) { |
443 *handled_by_plugin = true; | 483 *handled_by_plugin = true; |
444 return true; | 484 return true; |
445 } | 485 } |
446 | 486 |
447 // Attempt to intercept the request as a stream. | 487 // Attempt to intercept the request as a stream. |
448 base::FilePath plugin_path; | 488 base::FilePath plugin_path; |
449 if (has_plugin) | 489 if (has_plugin) |
450 plugin_path = plugin.path; | 490 plugin_path = plugin.path; |
451 std::string payload; | 491 std::string payload; |
452 std::unique_ptr<ResourceHandler> handler(host_->MaybeInterceptAsStream( | 492 std::unique_ptr<ResourceHandler> handler(host_->MaybeInterceptAsStream( |
453 plugin_path, request(), response_.get(), &payload)); | 493 plugin_path, request(), response_.get(), &payload)); |
454 if (handler) { | 494 if (handler) { |
455 if (!CheckResponseIsNotProvisional()) | 495 if (!CheckResponseIsNotProvisional()) { |
496 Cancel(); | |
456 return false; | 497 return false; |
498 } | |
457 *handled_by_plugin = true; | 499 *handled_by_plugin = true; |
458 intercepting_handler_->UseNewHandler(std::move(handler), payload); | 500 intercepting_handler_->UseNewHandler(std::move(handler), payload); |
459 } | 501 } |
460 #endif | 502 #endif |
461 return true; | 503 return true; |
462 } | 504 } |
463 | 505 |
464 bool MimeSniffingResourceHandler::CanBeIntercepted() { | 506 bool MimeSniffingResourceHandler::CanBeIntercepted() { |
465 if (response_->head.headers.get() && | 507 if (response_->head.headers.get() && |
466 response_->head.headers->response_code() == 304) { | 508 response_->head.headers->response_code() == 304) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
510 | 552 |
511 void MimeSniffingResourceHandler::OnPluginsLoaded( | 553 void MimeSniffingResourceHandler::OnPluginsLoaded( |
512 const std::vector<WebPluginInfo>& plugins) { | 554 const std::vector<WebPluginInfo>& plugins) { |
513 // No longer blocking on the plugins being loaded. | 555 // No longer blocking on the plugins being loaded. |
514 request()->LogUnblocked(); | 556 request()->LogUnblocked(); |
515 if (state_ == STATE_BUFFERING) | 557 if (state_ == STATE_BUFFERING) |
516 AdvanceState(); | 558 AdvanceState(); |
517 } | 559 } |
518 | 560 |
519 } // namespace content | 561 } // namespace content |
OLD | NEW |