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

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

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

Powered by Google App Engine
This is Rietveld 408576698