Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(374)

Side by Side Diff: content/browser/loader/mime_sniffing_resource_handler.cc

Issue 2526983002: Refactor ResourceHandler API. (Closed)
Patch Set: Fix stuff Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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_dispatcher_host_impl.h" 21 #include "content/browser/loader/resource_dispatcher_host_impl.h"
22 #include "content/browser/loader/resource_request_info_impl.h" 22 #include "content/browser/loader/resource_request_info_impl.h"
23 #include "content/browser/loader/stream_resource_handler.h" 23 #include "content/browser/loader/stream_resource_handler.h"
24 #include "content/public/browser/content_browser_client.h" 24 #include "content/public/browser/content_browser_client.h"
25 #include "content/public/browser/download_item.h" 25 #include "content/public/browser/download_item.h"
26 #include "content/public/browser/download_save_info.h" 26 #include "content/public/browser/download_save_info.h"
27 #include "content/public/browser/download_url_parameters.h" 27 #include "content/public/browser/download_url_parameters.h"
28 #include "content/public/browser/plugin_service.h" 28 #include "content/public/browser/plugin_service.h"
29 #include "content/public/browser/resource_context.h" 29 #include "content/public/browser/resource_context.h"
30 #include "content/public/browser/resource_controller.h"
30 #include "content/public/browser/resource_dispatcher_host_delegate.h" 31 #include "content/public/browser/resource_dispatcher_host_delegate.h"
31 #include "content/public/common/resource_response.h" 32 #include "content/public/common/resource_response.h"
32 #include "content/public/common/webplugininfo.h" 33 #include "content/public/common/webplugininfo.h"
33 #include "net/base/io_buffer.h" 34 #include "net/base/io_buffer.h"
34 #include "net/base/mime_sniffer.h" 35 #include "net/base/mime_sniffer.h"
35 #include "net/base/mime_util.h" 36 #include "net/base/mime_util.h"
36 #include "net/http/http_content_disposition.h" 37 #include "net/http/http_content_disposition.h"
37 #include "net/http/http_response_headers.h" 38 #include "net/http/http_response_headers.h"
38 #include "net/url_request/url_request.h" 39 #include "net/url_request/url_request.h"
39 #include "ppapi/features/features.h" 40 #include "ppapi/features/features.h"
(...skipping 18 matching lines...) Expand all
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 {
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),
87 weak_ptr_factory_(this) { 124 weak_ptr_factory_(this) {
88 } 125 }
89 126
90 MimeSniffingResourceHandler::~MimeSniffingResourceHandler() {} 127 MimeSniffingResourceHandler::~MimeSniffingResourceHandler() {}
91 128
92 void MimeSniffingResourceHandler::SetController( 129 void MimeSniffingResourceHandler::OnWillStart(
93 ResourceController* controller) { 130 const GURL& url,
94 ResourceHandler::SetController(controller); 131 std::unique_ptr<ResourceController> controller) {
132 DCHECK(!has_controller());
95 133
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; 134 const char* accept_value = nullptr;
105 switch (GetRequestInfo()->GetResourceType()) { 135 switch (GetRequestInfo()->GetResourceType()) {
106 case RESOURCE_TYPE_MAIN_FRAME: 136 case RESOURCE_TYPE_MAIN_FRAME:
107 case RESOURCE_TYPE_SUB_FRAME: 137 case RESOURCE_TYPE_SUB_FRAME:
108 accept_value = kFrameAcceptHeader; 138 accept_value = kFrameAcceptHeader;
109 break; 139 break;
110 case RESOURCE_TYPE_STYLESHEET: 140 case RESOURCE_TYPE_STYLESHEET:
111 accept_value = kStylesheetAcceptHeader; 141 accept_value = kStylesheetAcceptHeader;
112 break; 142 break;
113 case RESOURCE_TYPE_FAVICON: 143 case RESOURCE_TYPE_FAVICON:
(...skipping 16 matching lines...) Expand all
130 accept_value = kDefaultAcceptHeader; 160 accept_value = kDefaultAcceptHeader;
131 break; 161 break;
132 case RESOURCE_TYPE_LAST_TYPE: 162 case RESOURCE_TYPE_LAST_TYPE:
133 NOTREACHED(); 163 NOTREACHED();
134 break; 164 break;
135 } 165 }
136 166
137 // The false parameter prevents overwriting an existing accept header value, 167 // 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. 168 // which is needed because JS can manually set an accept header on an XHR.
139 request()->SetExtraRequestHeaderByName(kAcceptHeader, accept_value, false); 169 request()->SetExtraRequestHeaderByName(kAcceptHeader, accept_value, false);
140 return next_handler_->OnWillStart(url, defer); 170 next_handler_->OnWillStart(url, std::move(controller));
141 } 171 }
142 172
143 bool MimeSniffingResourceHandler::OnResponseStarted(ResourceResponse* response, 173 void MimeSniffingResourceHandler::OnResponseStarted(
144 bool* defer) { 174 ResourceResponse* response,
175 std::unique_ptr<ResourceController> controller) {
145 DCHECK_EQ(STATE_STARTING, state_); 176 DCHECK_EQ(STATE_STARTING, state_);
177 DCHECK(!has_controller());
178
146 response_ = response; 179 response_ = response;
147 180
148 state_ = STATE_BUFFERING; 181 state_ = STATE_BUFFERING;
149 // A 304 response should not contain a Content-Type header (RFC 7232 section 182 // 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 183 // 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. 184 // the response, and so must be skipped for 304 responses.
152 if (!(response_->head.headers.get() && 185 if (!(response_->head.headers.get() &&
153 response_->head.headers->response_code() == 304)) { 186 response_->head.headers->response_code() == 304)) {
154 if (ShouldSniffContent()) 187 if (ShouldSniffContent()) {
155 return true; 188 controller->Resume();
189 return;
190 }
156 191
157 if (response_->head.mime_type.empty()) { 192 if (response_->head.mime_type.empty()) {
158 // Ugg. The server told us not to sniff the content but didn't give us a 193 // 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 194 // 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. 195 // treat the response as "text/plain". This is the most secure option.
161 response_->head.mime_type.assign("text/plain"); 196 response_->head.mime_type.assign("text/plain");
162 } 197 }
163 198
164 // Treat feed types as text/plain. 199 // Treat feed types as text/plain.
165 if (response_->head.mime_type == "application/rss+xml" || 200 if (response_->head.mime_type == "application/rss+xml" ||
166 response_->head.mime_type == "application/atom+xml") { 201 response_->head.mime_type == "application/atom+xml") {
167 response_->head.mime_type.assign("text/plain"); 202 response_->head.mime_type.assign("text/plain");
168 } 203 }
169 } 204 }
170 205
171 return ProcessState(defer); 206 set_controller(std::move(controller));
207 AdvanceState();
172 } 208 }
173 209
174 bool MimeSniffingResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, 210 bool MimeSniffingResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
175 int* buf_size, 211 int* buf_size,
176 int min_size) { 212 int min_size) {
177 if (state_ == STATE_STREAMING) 213 if (state_ == STATE_STREAMING)
178 return next_handler_->OnWillRead(buf, buf_size, min_size); 214 return next_handler_->OnWillRead(buf, buf_size, min_size);
179 215
180 DCHECK_EQ(-1, min_size); 216 DCHECK_EQ(-1, min_size);
181 217
182 if (read_buffer_.get()) { 218 if (read_buffer_.get()) {
183 CHECK_LT(bytes_read_, read_buffer_size_); 219 CHECK_LT(bytes_read_, read_buffer_size_);
184 *buf = new DependentIOBuffer(read_buffer_.get(), bytes_read_); 220 *buf = new DependentIOBuffer(read_buffer_.get(), bytes_read_);
185 *buf_size = read_buffer_size_ - bytes_read_; 221 *buf_size = read_buffer_size_ - bytes_read_;
186 } else { 222 } else {
187 if (!next_handler_->OnWillRead(buf, buf_size, min_size)) 223 if (!next_handler_->OnWillRead(buf, buf_size, min_size))
188 return false; 224 return false;
189 225
190 read_buffer_ = *buf; 226 read_buffer_ = *buf;
191 read_buffer_size_ = *buf_size; 227 read_buffer_size_ = *buf_size;
192 DCHECK_GE(read_buffer_size_, net::kMaxBytesToSniff * 2); 228 DCHECK_GE(read_buffer_size_, net::kMaxBytesToSniff * 2);
193 } 229 }
194 return true; 230 return true;
195 } 231 }
196 232
197 bool MimeSniffingResourceHandler::OnReadCompleted(int bytes_read, bool* defer) { 233 void MimeSniffingResourceHandler::OnReadCompleted(
198 if (state_ == STATE_STREAMING) 234 int bytes_read,
199 return next_handler_->OnReadCompleted(bytes_read, defer); 235 std::unique_ptr<ResourceController> controller) {
236 DCHECK(!has_controller());
237
238 if (state_ == STATE_STREAMING) {
239 next_handler_->OnReadCompleted(bytes_read, std::move(controller));
240 return;
241 }
200 242
201 DCHECK_EQ(state_, STATE_BUFFERING); 243 DCHECK_EQ(state_, STATE_BUFFERING);
202 bytes_read_ += bytes_read; 244 bytes_read_ += bytes_read;
203 245
204 const std::string& type_hint = response_->head.mime_type; 246 const std::string& type_hint = response_->head.mime_type;
205 247
206 std::string new_type; 248 std::string new_type;
207 bool made_final_decision = 249 bool made_final_decision =
208 net::SniffMimeType(read_buffer_->data(), bytes_read_, request()->url(), 250 net::SniffMimeType(read_buffer_->data(), bytes_read_, request()->url(),
209 type_hint, &new_type); 251 type_hint, &new_type);
210 252
211 // SniffMimeType() returns false if there is not enough data to determine 253 // 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 254 // the mime type. However, even if it returns false, it returns a new type
213 // that is probably better than the current one. 255 // that is probably better than the current one.
214 response_->head.mime_type.assign(new_type); 256 response_->head.mime_type.assign(new_type);
215 257
216 if (!made_final_decision && (bytes_read > 0)) 258 if (!made_final_decision && (bytes_read > 0)) {
217 return true; 259 controller->Resume();
260 return;
261 }
218 262
219 return ProcessState(defer); 263 set_controller(std::move(controller));
264 AdvanceState();
220 } 265 }
221 266
222 void MimeSniffingResourceHandler::OnResponseCompleted( 267 void MimeSniffingResourceHandler::OnResponseCompleted(
223 const net::URLRequestStatus& status, 268 const net::URLRequestStatus& status,
224 bool* defer) { 269 std::unique_ptr<ResourceController> resource_controller) {
225 // Upon completion, act like a pass-through handler in case the downstream 270 // Upon completion, act like a pass-through handler in case the downstream
226 // handler defers OnResponseCompleted. 271 // handler defers OnResponseCompleted.
227 state_ = STATE_STREAMING; 272 state_ = STATE_STREAMING;
228 273
229 next_handler_->OnResponseCompleted(status, defer); 274 next_handler_->OnResponseCompleted(status, std::move(resource_controller));
230 } 275 }
231 276
232 void MimeSniffingResourceHandler::Resume() { 277 void MimeSniffingResourceHandler::ResumeInternal() {
233 // If no information is currently being transmitted to downstream handlers, 278 // If no information is currently being transmitted to downstream handlers,
234 // they should not attempt to resume the request. 279 // they should not attempt to resume the request.
235 if (state_ == STATE_BUFFERING) { 280 if (state_ == STATE_BUFFERING) {
236 NOTREACHED(); 281 NOTREACHED();
237 return; 282 return;
238 } 283 }
239 284
240 // If the BufferingHandler is acting as a pass-through handler, just ask the 285 // If the BufferingHandler is acting as a pass-through handler, just ask the
241 // upwards ResourceController to resume the request. 286 // upwards ResourceController to resume the request.
242 if (state_ == STATE_STARTING || state_ == STATE_STREAMING) { 287 if (state_ == STATE_STARTING || state_ == STATE_STREAMING) {
243 controller()->Resume(); 288 Resume();
244 return; 289 return;
245 } 290 }
246 291
247 // Otherwise proceed with the replay of the response. If it is successful, 292 // Otherwise proceed with the replay of the response. If it is successful,
248 // it will resume the request. 293 // it will resume the request.
249 AdvanceState(); 294 AdvanceState();
250 } 295 }
251 296
252 void MimeSniffingResourceHandler::Cancel() {
253 controller()->Cancel();
254 }
255
256 void MimeSniffingResourceHandler::CancelAndIgnore() {
257 controller()->CancelAndIgnore();
258 }
259
260 void MimeSniffingResourceHandler::CancelWithError(int error_code) {
261 controller()->CancelWithError(error_code);
262 }
263
264 void MimeSniffingResourceHandler::AdvanceState() { 297 void MimeSniffingResourceHandler::AdvanceState() {
265 bool defer = false; 298 switch (state_) {
266 if (!ProcessState(&defer)) { 299 case STATE_BUFFERING:
267 Cancel(); 300 MaybeIntercept();
268 } else if (!defer) { 301 break;
269 DCHECK_EQ(STATE_STREAMING, state_); 302 case STATE_INTERCEPTION_CHECK_DONE:
270 controller()->Resume(); 303 ReplayResponseReceived();
304 break;
305 case STATE_REPLAYING_RESPONSE_RECEIVED:
306 ReplayReadCompleted();
307 break;
308 default:
309 NOTREACHED();
310 break;
271 } 311 }
272 } 312 }
273 313
274 bool MimeSniffingResourceHandler::ProcessState(bool* defer) { 314 void MimeSniffingResourceHandler::MaybeIntercept() {
275 bool return_value = true;
276 while (!*defer && return_value && state_ != STATE_STREAMING) {
277 switch (state_) {
278 case STATE_BUFFERING:
279 return_value = MaybeIntercept(defer);
280 break;
281 case STATE_INTERCEPTION_CHECK_DONE:
282 return_value = ReplayResponseReceived(defer);
283 break;
284 case STATE_REPLAYING_RESPONSE_RECEIVED:
285 return_value = ReplayReadCompleted(defer);
286 break;
287 default:
288 NOTREACHED();
289 break;
290 }
291 }
292 return return_value;
293 }
294
295 bool MimeSniffingResourceHandler::MaybeIntercept(bool* defer) {
296 DCHECK_EQ(STATE_BUFFERING, state_); 315 DCHECK_EQ(STATE_BUFFERING, state_);
297 // If a request that can be intercepted failed the check for interception 316 // If a request that can be intercepted failed the check for interception
298 // step, it should be canceled. 317 // step, it should be canceled.
299 if (!MaybeStartInterception(defer)) 318 if (!MaybeStartInterception())
300 return false; 319 return;
301 320
302 if (!*defer) 321 state_ = STATE_INTERCEPTION_CHECK_DONE;
303 state_ = STATE_INTERCEPTION_CHECK_DONE; 322 ResumeInternal();
304
305 return true;
306 } 323 }
307 324
308 bool MimeSniffingResourceHandler::ReplayResponseReceived(bool* defer) { 325 void MimeSniffingResourceHandler::ReplayResponseReceived() {
309 DCHECK_EQ(STATE_INTERCEPTION_CHECK_DONE, state_); 326 DCHECK_EQ(STATE_INTERCEPTION_CHECK_DONE, state_);
310 state_ = STATE_REPLAYING_RESPONSE_RECEIVED; 327 state_ = STATE_REPLAYING_RESPONSE_RECEIVED;
311 return next_handler_->OnResponseStarted(response_.get(), defer); 328 next_handler_->OnResponseStarted(response_.get(),
329 base::MakeUnique<Controller>(this));
312 } 330 }
313 331
314 bool MimeSniffingResourceHandler::ReplayReadCompleted(bool* defer) { 332 void MimeSniffingResourceHandler::ReplayReadCompleted() {
315 DCHECK_EQ(STATE_REPLAYING_RESPONSE_RECEIVED, state_); 333 DCHECK_EQ(STATE_REPLAYING_RESPONSE_RECEIVED, state_);
316 334
317 state_ = STATE_STREAMING; 335 state_ = STATE_STREAMING;
318 336
319 if (!read_buffer_.get()) 337 if (!read_buffer_.get()) {
320 return true; 338 ResumeInternal();
339 return;
340 }
321 341
322 bool result = next_handler_->OnReadCompleted(bytes_read_, defer); 342 int bytes_read = bytes_read_;
323 343
324 read_buffer_ = nullptr; 344 read_buffer_ = nullptr;
325 read_buffer_size_ = 0; 345 read_buffer_size_ = 0;
326 bytes_read_ = 0; 346 bytes_read_ = 0;
327 347
328 return result; 348 next_handler_->OnReadCompleted(bytes_read,
349 base::MakeUnique<Controller>(this));
329 } 350 }
330 351
331 bool MimeSniffingResourceHandler::ShouldSniffContent() { 352 bool MimeSniffingResourceHandler::ShouldSniffContent() {
332 if (request_context_type_ == REQUEST_CONTEXT_TYPE_FETCH) { 353 if (request_context_type_ == REQUEST_CONTEXT_TYPE_FETCH) {
333 // MIME sniffing should be disabled for a request initiated by fetch(). 354 // MIME sniffing should be disabled for a request initiated by fetch().
334 return false; 355 return false;
335 } 356 }
336 357
337 const std::string& mime_type = response_->head.mime_type; 358 const std::string& mime_type = response_->head.mime_type;
338 359
(...skipping 10 matching lines...) Expand all
349 // We're going to look at the data before deciding what the content type 370 // We're going to look at the data before deciding what the content type
350 // is. That means we need to delay sending the ResponseStarted message 371 // is. That means we need to delay sending the ResponseStarted message
351 // over the IPC channel. 372 // over the IPC channel.
352 VLOG(1) << "To buffer: " << request()->url().spec(); 373 VLOG(1) << "To buffer: " << request()->url().spec();
353 return true; 374 return true;
354 } 375 }
355 376
356 return false; 377 return false;
357 } 378 }
358 379
359 bool MimeSniffingResourceHandler::MaybeStartInterception(bool* defer) { 380 bool MimeSniffingResourceHandler::MaybeStartInterception() {
360 if (!CanBeIntercepted()) 381 if (!CanBeIntercepted())
361 return true; 382 return true;
362 383
363 DCHECK(!response_->head.mime_type.empty()); 384 DCHECK(!response_->head.mime_type.empty());
364 385
365 ResourceRequestInfoImpl* info = GetRequestInfo(); 386 ResourceRequestInfoImpl* info = GetRequestInfo();
366 const std::string& mime_type = response_->head.mime_type; 387 const std::string& mime_type = response_->head.mime_type;
367 388
368 // https://crbug.com/568184 - Temporary hack to track servers that aren't 389 // https://crbug.com/568184 - Temporary hack to track servers that aren't
369 // setting Content-Disposition when sending x-x509-user-cert and expecting 390 // setting Content-Disposition when sending x-x509-user-cert and expecting
370 // the browser to automatically install certificates; this is being 391 // the browser to automatically install certificates; this is being
371 // deprecated and will be removed upon full <keygen> removal. 392 // deprecated and will be removed upon full <keygen> removal.
372 if (mime_type == "application/x-x509-user-cert" && response_->head.headers) { 393 if (mime_type == "application/x-x509-user-cert" && response_->head.headers) {
373 UMA_HISTOGRAM_BOOLEAN( 394 UMA_HISTOGRAM_BOOLEAN(
374 "UserCert.ContentDisposition", 395 "UserCert.ContentDisposition",
375 response_->head.headers->HasHeader("Content-Disposition")); 396 response_->head.headers->HasHeader("Content-Disposition"));
376 } 397 }
377 398
378 // Allow requests for object/embed tags to be intercepted as streams. 399 // Allow requests for object/embed tags to be intercepted as streams.
379 if (info->GetResourceType() == content::RESOURCE_TYPE_OBJECT) { 400 if (info->GetResourceType() == content::RESOURCE_TYPE_OBJECT) {
380 DCHECK(!info->allow_download()); 401 DCHECK(!info->allow_download());
381 402
382 bool handled_by_plugin; 403 bool handled_by_plugin;
383 if (!CheckForPluginHandler(defer, &handled_by_plugin)) 404 if (!CheckForPluginHandler(&handled_by_plugin))
384 return false; 405 return false;
385 if (handled_by_plugin || *defer) 406 if (handled_by_plugin)
386 return true; 407 return true;
387 } 408 }
388 409
389 if (!info->allow_download()) 410 if (!info->allow_download())
390 return true; 411 return true;
391 412
392 // info->allow_download() == true implies 413 // info->allow_download() == true implies
393 // info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME or 414 // info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME or
394 // info->GetResourceType() == RESOURCE_TYPE_SUB_FRAME. 415 // info->GetResourceType() == RESOURCE_TYPE_SUB_FRAME.
395 DCHECK(info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME || 416 DCHECK(info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME ||
396 info->GetResourceType() == RESOURCE_TYPE_SUB_FRAME); 417 info->GetResourceType() == RESOURCE_TYPE_SUB_FRAME);
397 418
398 bool must_download = MustDownload(); 419 bool must_download = MustDownload();
399 if (!must_download) { 420 if (!must_download) {
400 if (mime_util::IsSupportedMimeType(mime_type)) 421 if (mime_util::IsSupportedMimeType(mime_type))
401 return true; 422 return true;
402 423
403 bool handled_by_plugin; 424 bool handled_by_plugin;
404 if (!CheckForPluginHandler(defer, &handled_by_plugin)) 425 if (!CheckForPluginHandler(&handled_by_plugin))
405 return false; 426 return false;
406 if (handled_by_plugin || *defer) 427 if (handled_by_plugin)
407 return true; 428 return true;
408 } 429 }
409 430
410 // This request is a download. 431 // This request is a download.
411 432
412 if (!CheckResponseIsNotProvisional()) 433 if (!CheckResponseIsNotProvisional())
413 return false; 434 return false;
414 435
415 info->set_is_download(true); 436 info->set_is_download(true);
416 std::unique_ptr<ResourceHandler> handler( 437 std::unique_ptr<ResourceHandler> handler(
417 host_->CreateResourceHandlerForDownload(request(), 438 host_->CreateResourceHandlerForDownload(request(),
418 true, // is_content_initiated 439 true, // is_content_initiated
419 must_download, 440 must_download,
420 false /* is_new_request */)); 441 false /* is_new_request */));
421 intercepting_handler_->UseNewHandler(std::move(handler), std::string()); 442 intercepting_handler_->UseNewHandler(std::move(handler), std::string());
422 return true; 443 return true;
423 } 444 }
424 445
425 bool MimeSniffingResourceHandler::CheckForPluginHandler( 446 bool MimeSniffingResourceHandler::CheckForPluginHandler(
426 bool* defer,
427 bool* handled_by_plugin) { 447 bool* handled_by_plugin) {
428 *handled_by_plugin = false; 448 *handled_by_plugin = false;
429 #if BUILDFLAG(ENABLE_PLUGINS) 449 #if BUILDFLAG(ENABLE_PLUGINS)
430 ResourceRequestInfoImpl* info = GetRequestInfo(); 450 ResourceRequestInfoImpl* info = GetRequestInfo();
431 bool allow_wildcard = false; 451 bool allow_wildcard = false;
432 bool stale; 452 bool stale;
433 WebPluginInfo plugin; 453 WebPluginInfo plugin;
434 bool has_plugin = plugin_service_->GetPluginInfo( 454 bool has_plugin = plugin_service_->GetPluginInfo(
435 info->GetChildID(), info->GetRenderFrameID(), info->GetContext(), 455 info->GetChildID(), info->GetRenderFrameID(), info->GetContext(),
436 request()->url(), url::Origin(), response_->head.mime_type, 456 request()->url(), url::Origin(), response_->head.mime_type,
437 allow_wildcard, &stale, &plugin, NULL); 457 allow_wildcard, &stale, &plugin, NULL);
438 458
439 if (stale) { 459 if (stale) {
440 // Refresh the plugins asynchronously. 460 // Refresh the plugins asynchronously.
441 plugin_service_->GetPlugins( 461 plugin_service_->GetPlugins(
442 base::Bind(&MimeSniffingResourceHandler::OnPluginsLoaded, 462 base::Bind(&MimeSniffingResourceHandler::OnPluginsLoaded,
443 weak_ptr_factory_.GetWeakPtr())); 463 weak_ptr_factory_.GetWeakPtr()));
444 request()->LogBlockedBy("MimeSniffingResourceHandler"); 464 request()->LogBlockedBy("MimeSniffingResourceHandler");
445 *defer = true; 465 // Will complete asynchronously.
446 return true; 466 return false;
447 } 467 }
448 468
449 if (has_plugin && plugin.type != WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN) { 469 if (has_plugin && plugin.type != WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN) {
450 *handled_by_plugin = true; 470 *handled_by_plugin = true;
451 return true; 471 return true;
452 } 472 }
453 473
454 // Attempt to intercept the request as a stream. 474 // Attempt to intercept the request as a stream.
455 base::FilePath plugin_path; 475 base::FilePath plugin_path;
456 if (has_plugin) 476 if (has_plugin)
457 plugin_path = plugin.path; 477 plugin_path = plugin.path;
458 std::string payload; 478 std::string payload;
459 std::unique_ptr<ResourceHandler> handler(host_->MaybeInterceptAsStream( 479 std::unique_ptr<ResourceHandler> handler(host_->MaybeInterceptAsStream(
460 plugin_path, request(), response_.get(), &payload)); 480 plugin_path, request(), response_.get(), &payload));
461 if (handler) { 481 if (handler) {
462 if (!CheckResponseIsNotProvisional()) 482 if (!CheckResponseIsNotProvisional()) {
483 Cancel();
463 return false; 484 return false;
485 }
464 *handled_by_plugin = true; 486 *handled_by_plugin = true;
465 intercepting_handler_->UseNewHandler(std::move(handler), payload); 487 intercepting_handler_->UseNewHandler(std::move(handler), payload);
466 } 488 }
467 #endif 489 #endif
468 return true; 490 return true;
469 } 491 }
470 492
471 bool MimeSniffingResourceHandler::CanBeIntercepted() { 493 bool MimeSniffingResourceHandler::CanBeIntercepted() {
472 if (response_->head.headers.get() && 494 if (response_->head.headers.get() &&
473 response_->head.headers->response_code() == 304) { 495 response_->head.headers->response_code() == 304) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 539
518 void MimeSniffingResourceHandler::OnPluginsLoaded( 540 void MimeSniffingResourceHandler::OnPluginsLoaded(
519 const std::vector<WebPluginInfo>& plugins) { 541 const std::vector<WebPluginInfo>& plugins) {
520 // No longer blocking on the plugins being loaded. 542 // No longer blocking on the plugins being loaded.
521 request()->LogUnblocked(); 543 request()->LogUnblocked();
522 if (state_ == STATE_BUFFERING) 544 if (state_ == STATE_BUFFERING)
523 AdvanceState(); 545 AdvanceState();
524 } 546 }
525 547
526 } // namespace content 548 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698