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

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

Issue 2005273002: Move MimeTypeResourceHandler before ThrottlingResourceHandler (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed comments Created 4 years, 5 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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_type_resource_handler.h" 5 #include "content/browser/loader/mime_sniffing_resource_handler.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <memory> 9 #include <memory>
10 10
11 #include "base/files/file_path.h" 11 #include "base/files/file_path.h"
12 #include "base/location.h" 12 #include "base/location.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/macros.h" 14 #include "base/macros.h"
15 #include "base/single_thread_task_runner.h" 15 #include "base/single_thread_task_runner.h"
16 #include "base/threading/thread_task_runner_handle.h" 16 #include "base/threading/thread_task_runner_handle.h"
17 #include "content/browser/loader/intercepting_resource_handler.h"
17 #include "content/browser/loader/resource_dispatcher_host_impl.h" 18 #include "content/browser/loader/resource_dispatcher_host_impl.h"
18 #include "content/public/browser/resource_controller.h" 19 #include "content/public/browser/resource_controller.h"
19 #include "content/public/browser/resource_dispatcher_host_delegate.h" 20 #include "content/public/browser/resource_dispatcher_host_delegate.h"
20 #include "content/public/browser/resource_request_info.h" 21 #include "content/public/browser/resource_request_info.h"
21 #include "content/public/common/resource_response.h" 22 #include "content/public/common/resource_response.h"
22 #include "content/public/common/webplugininfo.h" 23 #include "content/public/common/webplugininfo.h"
23 #include "content/public/test/test_browser_thread_bundle.h" 24 #include "content/public/test/test_browser_thread_bundle.h"
24 #include "content/public/test/test_utils.h" 25 #include "content/public/test/test_utils.h"
25 #include "content/test/fake_plugin_service.h" 26 #include "content/test/fake_plugin_service.h"
26 #include "net/url_request/url_request_context.h" 27 #include "net/url_request/url_request_context.h"
27 #include "testing/gtest/include/gtest/gtest.h" 28 #include "testing/gtest/include/gtest/gtest.h"
28 #include "url/gurl.h" 29 #include "url/gurl.h"
29 30
30 namespace content { 31 namespace content {
31 32
32 namespace { 33 namespace {
33 34
34 class TestResourceHandler : public ResourceHandler { 35 class TestResourceHandler : public ResourceHandler {
35 public: 36 public:
36 TestResourceHandler() : ResourceHandler(nullptr) {} 37 TestResourceHandler(bool response_started,
38 bool defer_response_started,
39 bool will_read,
40 bool read_completed,
41 bool defer_read_completed)
42 : ResourceHandler(nullptr),
43 buffer_(new net::IOBuffer(2048)),
44 response_started_(response_started),
45 defer_response_started_(defer_response_started),
46 will_read_(will_read),
47 read_completed_(read_completed),
48 defer_read_completed_(defer_read_completed) {}
37 49
38 void SetController(ResourceController* controller) override {} 50 void SetController(ResourceController* controller) override {}
39 51
40 bool OnRequestRedirected(const net::RedirectInfo& redirect_info, 52 bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
41 ResourceResponse* response, 53 ResourceResponse* response,
42 bool* defer) override { 54 bool* defer) override {
43 NOTREACHED(); 55 NOTREACHED();
44 return false; 56 return false;
45 } 57 }
46 58
47 bool OnResponseStarted(ResourceResponse* response, bool* defer) override { 59 bool OnResponseStarted(ResourceResponse* response, bool* defer) override {
48 return false; 60 if (defer_response_started_)
61 *defer = true;
62 return response_started_;
49 } 63 }
50 64
51 bool OnWillStart(const GURL& url, bool* defer) override { 65 bool OnWillStart(const GURL& url, bool* defer) override { return false; }
52 return false;
53 }
54 66
55 bool OnBeforeNetworkStart(const GURL& url, bool* defer) override { 67 bool OnBeforeNetworkStart(const GURL& url, bool* defer) override {
56 NOTREACHED(); 68 NOTREACHED();
57 return false; 69 return false;
58 } 70 }
59 71
60 bool OnWillRead(scoped_refptr<net::IOBuffer>* buf, 72 bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
61 int* buf_size, 73 int* buf_size,
62 int min_size) override { 74 int min_size) override {
63 NOTREACHED(); 75 *buf = buffer_;
64 return false; 76 *buf_size = 2048;
77 return will_read_;
65 } 78 }
66 79
67 bool OnReadCompleted(int bytes_read, bool* defer) override { 80 bool OnReadCompleted(int bytes_read, bool* defer) override {
68 NOTREACHED(); 81 DCHECK_LT(bytes_read, 2048);
69 return false; 82 if (defer_read_completed_)
83 *defer = true;
84 return read_completed_;
70 } 85 }
71 86
72 void OnResponseCompleted(const net::URLRequestStatus& status, 87 void OnResponseCompleted(const net::URLRequestStatus& status,
73 const std::string& security_info, 88 const std::string& security_info,
74 bool* defer) override { 89 bool* defer) override {}
75 }
76 90
77 void OnDataDownloaded(int bytes_downloaded) override { 91 void OnDataDownloaded(int bytes_downloaded) override { NOTREACHED(); }
78 NOTREACHED(); 92
93 scoped_refptr<net::IOBuffer> buffer() { return buffer_; }
94
95 private:
96 scoped_refptr<net::IOBuffer> buffer_;
97 bool response_started_;
98 bool defer_response_started_;
99 bool will_read_;
100 bool read_completed_;
101 bool defer_read_completed_;
102 DISALLOW_COPY_AND_ASSIGN(TestResourceHandler);
103 };
104
105 class TestResourceDispatcherHostDelegate
106 : public ResourceDispatcherHostDelegate {
107 public:
108 TestResourceDispatcherHostDelegate(bool must_download)
109 : must_download_(must_download) {}
110
111 bool ShouldForceDownloadResource(const GURL& url,
112 const std::string& mime_type) override {
113 return must_download_;
79 } 114 }
80 115
81 private: 116 private:
82 DISALLOW_COPY_AND_ASSIGN(TestResourceHandler); 117 const bool must_download_;
83 }; 118 };
84 119
85 class TestResourceDispatcherHost : public ResourceDispatcherHostImpl { 120 class TestResourceDispatcherHost : public ResourceDispatcherHostImpl {
86 public: 121 public:
87 explicit TestResourceDispatcherHost(bool stream_has_handler) 122 TestResourceDispatcherHost(bool stream_has_handler)
88 : stream_has_handler_(stream_has_handler), 123 : stream_has_handler_(stream_has_handler),
89 intercepted_as_stream_(false), 124 intercepted_as_stream_(false),
90 intercepted_as_stream_count_(0) {} 125 intercepted_as_stream_count_(0),
126 last_resource_handler_(nullptr) {}
91 127
92 bool intercepted_as_stream() const { return intercepted_as_stream_; } 128 bool intercepted_as_stream() const { return intercepted_as_stream_; }
93 129
94 std::unique_ptr<ResourceHandler> CreateResourceHandlerForDownload( 130 std::unique_ptr<ResourceHandler> CreateResourceHandlerForDownload(
95 net::URLRequest* request, 131 net::URLRequest* request,
96 bool is_content_initiated, 132 bool is_content_initiated,
97 bool must_download) override { 133 bool must_download) override {
98 return std::unique_ptr<ResourceHandler>(new TestResourceHandler); 134 return CreateNewResourceHandler();
99 } 135 }
100 136
101 std::unique_ptr<ResourceHandler> MaybeInterceptAsStream( 137 std::unique_ptr<ResourceHandler> MaybeInterceptAsStream(
102 const base::FilePath& plugin_path, 138 const base::FilePath& plugin_path,
103 net::URLRequest* request, 139 net::URLRequest* request,
104 ResourceResponse* response, 140 ResourceResponse* response,
105 std::string* payload) override { 141 std::string* payload) override {
106 intercepted_as_stream_count_++; 142 intercepted_as_stream_count_++;
107 if (stream_has_handler_) { 143 if (stream_has_handler_) {
108 intercepted_as_stream_ = true; 144 intercepted_as_stream_ = true;
109 return std::unique_ptr<ResourceHandler>(new TestResourceHandler); 145 return CreateNewResourceHandler();
110 } else { 146 } else {
111 return std::unique_ptr<ResourceHandler>(); 147 return CreateNewResourceHandler();
112 } 148 }
113 } 149 }
114 150
115 int intercepted_as_stream_count() const { 151 int intercepted_as_stream_count() const {
116 return intercepted_as_stream_count_; 152 return intercepted_as_stream_count_;
117 } 153 }
118 154
155 TestResourceHandler* last_resource_handler() const {
156 return last_resource_handler_;
157 }
158
119 private: 159 private:
160 std::unique_ptr<ResourceHandler> CreateNewResourceHandler() {
161 std::unique_ptr<ResourceHandler> new_resource_handler;
162 new_resource_handler.reset(
163 new TestResourceHandler(false, false, true, true, false));
164 last_resource_handler_ =
165 static_cast<TestResourceHandler*>(new_resource_handler.get());
166 return new_resource_handler;
167 }
168
120 // Whether the URL request should be intercepted as a stream. 169 // Whether the URL request should be intercepted as a stream.
121 bool stream_has_handler_; 170 bool stream_has_handler_;
122 171
123 // Whether the URL request has been intercepted as a stream. 172 // Whether the URL request has been intercepted as a stream.
124 bool intercepted_as_stream_; 173 bool intercepted_as_stream_;
125 174
126 // Count of number of times MaybeInterceptAsStream function get called in a 175 // Count of number of times MaybeInterceptAsStream function get called in a
127 // test. 176 // test.
128 int intercepted_as_stream_count_; 177 int intercepted_as_stream_count_;
129 };
130 178
131 class TestResourceDispatcherHostDelegate 179 // The last TestResourceHandler created by this TestResourceDispatcherHost.
132 : public ResourceDispatcherHostDelegate { 180 TestResourceHandler* last_resource_handler_;
133 public:
134 TestResourceDispatcherHostDelegate(bool must_download)
135 : must_download_(must_download) {
136 }
137
138 bool ShouldForceDownloadResource(const GURL& url,
139 const std::string& mime_type) override {
140 return must_download_;
141 }
142
143 private:
144 const bool must_download_;
145 };
146
147 class TestResourceController : public ResourceController {
148 public:
149 void Cancel() override {}
150
151 void CancelAndIgnore() override {
152 NOTREACHED();
153 }
154
155 void CancelWithError(int error_code) override {
156 NOTREACHED();
157 }
158
159 void Resume() override {
160 NOTREACHED();
161 }
162 }; 181 };
163 182
164 class TestFakePluginService : public FakePluginService { 183 class TestFakePluginService : public FakePluginService {
165 public: 184 public:
166 // If |is_plugin_stale| is true, GetPluginInfo will indicate the plugins are 185 // If |is_plugin_stale| is true, GetPluginInfo will indicate the plugins are
167 // stale until GetPlugins is called. 186 // stale until GetPlugins is called.
168 TestFakePluginService(bool plugin_available, bool is_plugin_stale) 187 TestFakePluginService(bool plugin_available, bool is_plugin_stale)
169 : plugin_available_(plugin_available), 188 : plugin_available_(plugin_available),
170 is_plugin_stale_(is_plugin_stale) {} 189 is_plugin_stale_(is_plugin_stale) {}
171 190
(...skipping 23 matching lines...) Expand all
195 FROM_HERE, base::Bind(callback, plugins)); 214 FROM_HERE, base::Bind(callback, plugins));
196 } 215 }
197 216
198 private: 217 private:
199 const bool plugin_available_; 218 const bool plugin_available_;
200 bool is_plugin_stale_; 219 bool is_plugin_stale_;
201 220
202 DISALLOW_COPY_AND_ASSIGN(TestFakePluginService); 221 DISALLOW_COPY_AND_ASSIGN(TestFakePluginService);
203 }; 222 };
204 223
205 class MimeTypeResourceHandlerTest : public testing::Test { 224 class TestResourceController : public ResourceController {
206 public: 225 public:
207 MimeTypeResourceHandlerTest() 226 TestResourceController() : cancel_called_(0), resume_called_(0) {}
227 void Cancel() override { cancel_called_++; }
mmenke 2016/07/19 21:42:33 night: Blank line before Cancel()
clamy 2016/07/25 16:58:26 Done.
228
229 void CancelAndIgnore() override { NOTREACHED(); }
230
231 void CancelWithError(int error_code) override { NOTREACHED(); }
232
233 void Resume() override { resume_called_++; }
234
235 int cancel_called() const { return cancel_called_; }
236 int resume_called() const { return resume_called_; }
mmenke 2016/07/19 21:42:33 Maybe call these something like times_blah_called(
clamy 2016/07/25 16:58:26 Done.
237
238 private:
239 int cancel_called_;
240 int resume_called_;
241 };
242
243 } // namespace
244
245 class MimeSniffingResourceHandlerTest : public testing::Test {
246 public:
247 MimeSniffingResourceHandlerTest()
208 : stream_has_handler_(false), 248 : stream_has_handler_(false),
209 plugin_available_(false), 249 plugin_available_(false),
210 plugin_stale_(false) {} 250 plugin_stale_(false) {}
211 251
252 std::string TestAcceptHeaderSetting(ResourceType request_resource_type);
253 std::string TestAcceptHeaderSettingWithURLRequest(
254 ResourceType request_resource_type,
255 net::URLRequest* request);
256
212 void set_stream_has_handler(bool stream_has_handler) { 257 void set_stream_has_handler(bool stream_has_handler) {
213 stream_has_handler_ = stream_has_handler; 258 stream_has_handler_ = stream_has_handler;
214 } 259 }
215 260
216 void set_plugin_available(bool plugin_available) { 261 void set_plugin_available(bool plugin_available) {
217 plugin_available_ = plugin_available; 262 plugin_available_ = plugin_available;
218 } 263 }
219 264
220 void set_plugin_stale(bool plugin_stale) { plugin_stale_ = plugin_stale; } 265 void set_plugin_stale(bool plugin_stale) { plugin_stale_ = plugin_stale; }
221 266
222 bool TestStreamIsIntercepted(bool allow_download, 267 bool TestStreamIsIntercepted(bool allow_download,
223 bool must_download, 268 bool must_download,
224 ResourceType request_resource_type); 269 ResourceType request_resource_type);
270 // Tests the operation of the MimeSniffingHandler when it needs to buffer
271 // data.
272 void TestHandlerSniffing(bool response_started,
273 bool defer_response_started,
274 bool will_read,
275 bool read_completed,
276 bool defer_read_completed);
225 277
226 std::string TestAcceptHeaderSetting(ResourceType request_resource_type); 278 // Tests the operation of the MimeSniffingHandler when it doesn't buffer
227 std::string TestAcceptHeaderSettingWithURLRequest( 279 // data.
228 ResourceType request_resource_type, 280 void TestHandlerNoSniffing(bool response_started,
229 net::URLRequest* request); 281 bool defer_response_started,
282 bool will_read,
283 bool read_completed,
284 bool defer_read_completed);
230 285
231 private: 286 private:
232 // Whether the URL request should be intercepted as a stream. 287 // Whether the URL request should be intercepted as a stream.
233 bool stream_has_handler_; 288 bool stream_has_handler_;
234 bool plugin_available_; 289 bool plugin_available_;
235 bool plugin_stale_; 290 bool plugin_stale_;
236 291
237 TestBrowserThreadBundle thread_bundle_; 292 TestBrowserThreadBundle thread_bundle_;
238 }; 293 };
239 294
240 bool MimeTypeResourceHandlerTest::TestStreamIsIntercepted( 295 std::string MimeSniffingResourceHandlerTest::TestAcceptHeaderSetting(
296 ResourceType request_resource_type) {
297 net::URLRequestContext context;
298 std::unique_ptr<net::URLRequest> request(context.CreateRequest(
299 GURL("http://www.google.com"), net::DEFAULT_PRIORITY, nullptr));
300 return TestAcceptHeaderSettingWithURLRequest(request_resource_type,
301 request.get());
302 }
303
304 std::string
305 MimeSniffingResourceHandlerTest::TestAcceptHeaderSettingWithURLRequest(
306 ResourceType request_resource_type,
307 net::URLRequest* request) {
308 bool is_main_frame = request_resource_type == RESOURCE_TYPE_MAIN_FRAME;
309 ResourceRequestInfo::AllocateForTesting(request, request_resource_type,
310 nullptr, // context
311 0, // render_process_id
312 0, // render_view_id
313 0, // render_frame_id
314 is_main_frame, // is_main_frame
315 false, // parent_is_main_frame
316 false, // allow_download
317 true, // is_async
318 false); // is_using_lofi
319
320 std::unique_ptr<ResourceHandler> mime_sniffing_handler(
321 new MimeSniffingResourceHandler(
322 std::unique_ptr<ResourceHandler>(
323 new TestResourceHandler(false, false, false, false, false)),
324 nullptr, nullptr, nullptr, request));
325
326 bool defer = false;
327 mime_sniffing_handler->OnWillStart(request->url(), &defer);
328 content::RunAllPendingInMessageLoop();
329
330 std::string accept_header;
331 request->extra_request_headers().GetHeader("Accept", &accept_header);
332 return accept_header;
333 }
334
335 bool MimeSniffingResourceHandlerTest::TestStreamIsIntercepted(
241 bool allow_download, 336 bool allow_download,
242 bool must_download, 337 bool must_download,
243 ResourceType request_resource_type) { 338 ResourceType request_resource_type) {
244 net::URLRequestContext context; 339 net::URLRequestContext context;
245 std::unique_ptr<net::URLRequest> request(context.CreateRequest( 340 std::unique_ptr<net::URLRequest> request(context.CreateRequest(
246 GURL("http://www.google.com"), net::DEFAULT_PRIORITY, nullptr)); 341 GURL("http://www.google.com"), net::DEFAULT_PRIORITY, nullptr));
247 bool is_main_frame = request_resource_type == RESOURCE_TYPE_MAIN_FRAME; 342 bool is_main_frame = request_resource_type == RESOURCE_TYPE_MAIN_FRAME;
248 ResourceRequestInfo::AllocateForTesting( 343 ResourceRequestInfo::AllocateForTesting(request.get(), request_resource_type,
249 request.get(), 344 nullptr, // context
250 request_resource_type, 345 0, // render_process_id
251 nullptr, // context 346 0, // render_view_id
252 0, // render_process_id 347 0, // render_frame_id
253 0, // render_view_id 348 is_main_frame, // is_main_frame
254 0, // render_frame_id 349 false, // parent_is_main_frame
255 is_main_frame, // is_main_frame 350 allow_download, // allow_download
256 false, // parent_is_main_frame 351 true, // is_async
257 allow_download, // allow_download 352 false); // is_using_lofi
258 true, // is_async
259 false); // is_using_lofi
260 353
261 TestResourceDispatcherHost host(stream_has_handler_); 354 TestResourceDispatcherHost host(stream_has_handler_);
262 TestResourceDispatcherHostDelegate host_delegate(must_download); 355 TestResourceDispatcherHostDelegate host_delegate(must_download);
263 host.SetDelegate(&host_delegate); 356 host.SetDelegate(&host_delegate);
264 357
265 TestFakePluginService plugin_service(plugin_available_, plugin_stale_); 358 TestFakePluginService plugin_service(plugin_available_, plugin_stale_);
266 std::unique_ptr<ResourceHandler> mime_sniffing_handler( 359 std::unique_ptr<ResourceHandler> intercepting_handler(
mmenke 2016/07/19 21:42:33 This can just be a std::unique_ptr<InterceptingRes
clamy 2016/07/25 16:58:26 Done.
267 new MimeTypeResourceHandler( 360 new InterceptingResourceHandler(std::unique_ptr<ResourceHandler>(),
268 std::unique_ptr<ResourceHandler>(new TestResourceHandler()), &host, 361 nullptr));
269 &plugin_service, request.get())); 362 std::unique_ptr<ResourceHandler> mime_handler(new MimeSniffingResourceHandler(
363 std::unique_ptr<ResourceHandler>(
364 new TestResourceHandler(false, false, false, false, false)),
365 &host, &plugin_service,
366 static_cast<InterceptingResourceHandler*>(intercepting_handler.get()),
367 request.get()));
368
270 TestResourceController resource_controller; 369 TestResourceController resource_controller;
271 mime_sniffing_handler->SetController(&resource_controller); 370 mime_handler->SetController(&resource_controller);
272 371
273 scoped_refptr<ResourceResponse> response(new ResourceResponse); 372 scoped_refptr<ResourceResponse> response(new ResourceResponse);
274 // The MIME type isn't important but it shouldn't be empty. 373 // The MIME type isn't important but it shouldn't be empty.
275 response->head.mime_type = "application/pdf"; 374 response->head.mime_type = "application/pdf";
276 375
277 bool defer = false; 376 bool defer = false;
278 mime_sniffing_handler->OnResponseStarted(response.get(), &defer); 377 mime_handler->OnResponseStarted(response.get(), &defer);
279 378
280 content::RunAllPendingInMessageLoop(); 379 content::RunAllPendingInMessageLoop();
281 EXPECT_LT(host.intercepted_as_stream_count(), 2); 380 EXPECT_LT(host.intercepted_as_stream_count(), 2);
mmenke 2016/07/19 21:42:33 We don't check that we actually attach the alterna
clamy 2016/07/25 16:58:26 Done.
282 return host.intercepted_as_stream(); 381 return host.intercepted_as_stream();
283 } 382 }
284 383
285 std::string MimeTypeResourceHandlerTest::TestAcceptHeaderSetting( 384 void MimeSniffingResourceHandlerTest::TestHandlerSniffing(
286 ResourceType request_resource_type) { 385 bool response_started,
386 bool defer_response_started,
387 bool will_read,
388 bool read_completed,
389 bool defer_read_completed) {
287 net::URLRequestContext context; 390 net::URLRequestContext context;
288 std::unique_ptr<net::URLRequest> request(context.CreateRequest( 391 std::unique_ptr<net::URLRequest> request(context.CreateRequest(
289 GURL("http://www.google.com"), net::DEFAULT_PRIORITY, nullptr)); 392 GURL("http://www.google.com"), net::DEFAULT_PRIORITY, nullptr));
290 return TestAcceptHeaderSettingWithURLRequest( 393 ResourceRequestInfo::AllocateForTesting(request.get(),
291 request_resource_type, request.get()); 394 RESOURCE_TYPE_MAIN_FRAME,
292 } 395 nullptr, // context
293 396 0, // render_process_id
294 std::string MimeTypeResourceHandlerTest::TestAcceptHeaderSettingWithURLRequest( 397 0, // render_view_id
295 ResourceType request_resource_type, 398 0, // render_frame_id
296 net::URLRequest* request) { 399 true, // is_main_frame
297 bool is_main_frame = request_resource_type == RESOURCE_TYPE_MAIN_FRAME; 400 false, // parent_is_main_frame
298 ResourceRequestInfo::AllocateForTesting( 401 false, // allow_download
299 request, 402 true, // is_async
300 request_resource_type, 403 false); // is_using_lofi
301 nullptr, // context 404
302 0, // render_process_id 405 TestResourceDispatcherHost host(false);
303 0, // render_view_id
304 0, // render_frame_id
305 is_main_frame, // is_main_frame
306 false, // parent_is_main_frame
307 false, // allow_download
308 true, // is_async
309 false); // is_using_lofi
310
311 TestResourceDispatcherHost host(stream_has_handler_);
312 TestResourceDispatcherHostDelegate host_delegate(false); 406 TestResourceDispatcherHostDelegate host_delegate(false);
313 host.SetDelegate(&host_delegate); 407 host.SetDelegate(&host_delegate);
314 408
315 std::unique_ptr<ResourceHandler> mime_sniffing_handler( 409 TestFakePluginService plugin_service(plugin_available_, plugin_stale_);
316 new MimeTypeResourceHandler( 410 std::unique_ptr<ResourceHandler> intercepting_handler(
317 std::unique_ptr<ResourceHandler>(new TestResourceHandler()), &host, 411 new InterceptingResourceHandler(std::unique_ptr<ResourceHandler>(),
318 nullptr, request)); 412 nullptr));
319 413 std::unique_ptr<ResourceHandler> handler(new MimeSniffingResourceHandler(
414 std::unique_ptr<ResourceHandler>(new TestResourceHandler(
415 response_started, defer_response_started, will_read, read_completed,
416 defer_read_completed)),
417 &host, &plugin_service,
418 static_cast<InterceptingResourceHandler*>(intercepting_handler.get()),
419 request.get()));
420 MimeSniffingResourceHandler* mime_sniffing_handler =
421 static_cast<MimeSniffingResourceHandler*>(handler.get());
422
423 TestResourceController resource_controller;
424 mime_sniffing_handler->SetController(&resource_controller);
425
426 // The response should be sniffed.
427 scoped_refptr<ResourceResponse> response(new ResourceResponse);
428 response->head.mime_type.assign("text/plain");
429
430 CHECK_EQ(MimeSniffingResourceHandler::STATE_STARTING,
431 mime_sniffing_handler->state_);
432
433 // Simulate the response starting. We should start buffering, so the return
434 // value should always be true.
320 bool defer = false; 435 bool defer = false;
321 mime_sniffing_handler->OnWillStart(request->url(), &defer); 436 CHECK_EQ(true,
437 mime_sniffing_handler->OnResponseStarted(response.get(), &defer));
438 CHECK_EQ(0, resource_controller.cancel_called());
439 CHECK_EQ(0, resource_controller.resume_called());
440 CHECK_EQ(false, defer);
441 CHECK_EQ(MimeSniffingResourceHandler::STATE_BUFFERING,
442 mime_sniffing_handler->state_);
443
444 // Read some data to sniff the mime type. This will ask the next
445 // ResourceHandler for a buffer.
446 scoped_refptr<net::IOBuffer> read_buffer;
447 int buf_size = 0;
448 CHECK_EQ(will_read,
449 mime_sniffing_handler->OnWillRead(&read_buffer, &buf_size, -1));
450 CHECK_EQ(0, resource_controller.cancel_called());
451 CHECK_EQ(MimeSniffingResourceHandler::STATE_BUFFERING,
452 mime_sniffing_handler->state_);
453
454 if (!will_read)
455 return;
456
457 // Simulate an HTML page. The mime sniffer will identify the MimeType and
458 // proceed with replay.
459 char data[] = "!DOCTYPE html\n<head>\n<title>Foo</title>\n</head>";
460 memcpy(read_buffer->data(), data, sizeof(data));
461
462 defer = false;
463 bool return_value =
464 mime_sniffing_handler->OnReadCompleted(sizeof(data), &defer);
465
466 // If the next handler cancels the response start, we hsould be notified
467 // immediately.
468 if (!response_started) {
469 CHECK_EQ(response_started, return_value);
470 CHECK_EQ(0, resource_controller.cancel_called());
471 return;
472 }
473
474 // The replay can be deferred both at response started and read replay
475 // stages.
476 CHECK_EQ(defer, defer_response_started || defer_read_completed);
477 if (defer_response_started) {
478 CHECK_EQ(true, defer);
479 CHECK_EQ(true, return_value);
480 CHECK_EQ(MimeSniffingResourceHandler::STATE_REPLAYING_RESPONSE_RECEIVED,
481 mime_sniffing_handler->state_);
482 mime_sniffing_handler->Resume();
483 }
484
485 // The body that was sniffed should be transmitted to the next handler. This
486 // may cancel the request.
487 if (!read_completed) {
488 if (defer_response_started) {
489 CHECK_EQ(1, resource_controller.cancel_called());
490 } else {
491 CHECK_EQ(0, resource_controller.cancel_called());
492 CHECK_EQ(false, return_value);
493 }
494 return;
495 }
496
497 CHECK_EQ(MimeSniffingResourceHandler::STATE_STREAMING,
498 mime_sniffing_handler->state_);
499
500 // The request may be deferred by the next handler once the read is done.
501 if (defer_read_completed) {
502 CHECK_EQ(true, defer);
503 mime_sniffing_handler->Resume();
504 }
505
506 CHECK_EQ(MimeSniffingResourceHandler::STATE_STREAMING,
507 mime_sniffing_handler->state_);
508 CHECK_EQ(0, resource_controller.cancel_called());
509
510 // Even if the next handler defers the request twice, the
511 // MimeSniffingResourceHandler should only call Resume on its controller
512 // once.
513 if (defer_response_started || defer_read_completed)
514 CHECK_EQ(1, resource_controller.resume_called());
515 else
516 CHECK_EQ(0, resource_controller.resume_called());
517
322 content::RunAllPendingInMessageLoop(); 518 content::RunAllPendingInMessageLoop();
323
324 std::string accept_header;
325 request->extra_request_headers().GetHeader("Accept", &accept_header);
326 return accept_header;
327 } 519 }
328 520
521 void MimeSniffingResourceHandlerTest::TestHandlerNoSniffing(
522 bool response_started,
523 bool defer_response_started,
524 bool will_read,
525 bool read_completed,
526 bool defer_read_completed) {
527 net::URLRequestContext context;
528 std::unique_ptr<net::URLRequest> request(context.CreateRequest(
529 GURL("http://www.google.com"), net::DEFAULT_PRIORITY, nullptr));
530 ResourceRequestInfo::AllocateForTesting(request.get(),
531 RESOURCE_TYPE_MAIN_FRAME,
532 nullptr, // context
533 0, // render_process_id
534 0, // render_view_id
535 0, // render_frame_id
536 true, // is_main_frame
537 false, // parent_is_main_frame
538 false, // allow_download
539 true, // is_async
540 false); // is_using_lofi
541
542 TestResourceDispatcherHost host(false);
543 TestResourceDispatcherHostDelegate host_delegate(false);
544 host.SetDelegate(&host_delegate);
545
546 TestFakePluginService plugin_service(plugin_available_, plugin_stale_);
547 std::unique_ptr<ResourceHandler> intercepting_handler(
548 new InterceptingResourceHandler(std::unique_ptr<ResourceHandler>(),
549 nullptr));
550
551 std::unique_ptr<ResourceHandler> handler(new MimeSniffingResourceHandler(
552 std::unique_ptr<ResourceHandler>(new TestResourceHandler(
553 response_started, defer_response_started, will_read, read_completed,
554 defer_read_completed)),
555 &host, &plugin_service,
556 static_cast<InterceptingResourceHandler*>(intercepting_handler.get()),
557 request.get()));
558 MimeSniffingResourceHandler* mime_sniffing_handler =
559 static_cast<MimeSniffingResourceHandler*>(handler.get());
560
561 TestResourceController resource_controller;
562 mime_sniffing_handler->SetController(&resource_controller);
563 int expected_resume_calls = 0;
564
565 // The response should not be sniffed.
566 scoped_refptr<ResourceResponse> response(new ResourceResponse);
567 response->head.mime_type.assign("text/html");
568
569 CHECK_EQ(MimeSniffingResourceHandler::STATE_STARTING,
570 mime_sniffing_handler->state_);
571
572 // Simulate the response starting. There should be no need for buffering, so
573 // the return value should be that of the next handler.
574 bool defer = false;
575 CHECK_EQ(response_started,
576 mime_sniffing_handler->OnResponseStarted(response.get(), &defer));
577 CHECK_EQ(0, resource_controller.cancel_called());
578
579 if (!response_started)
580 return;
581
582 CHECK_EQ(defer_response_started, defer);
583 if (defer) {
584 CHECK_EQ(MimeSniffingResourceHandler::STATE_REPLAYING_RESPONSE_RECEIVED,
585 mime_sniffing_handler->state_);
586 expected_resume_calls++;
587 mime_sniffing_handler->Resume();
588 }
589
590 CHECK_EQ(expected_resume_calls, resource_controller.resume_called());
591 CHECK_EQ(MimeSniffingResourceHandler::STATE_STREAMING,
592 mime_sniffing_handler->state_);
593
594 // The MimeSniffingResourceHandler should be acting as a pass-through
595 // ResourceHandler.
596 scoped_refptr<net::IOBuffer> read_buffer;
597 int buf_size = 0;
598 CHECK_EQ(will_read,
599 mime_sniffing_handler->OnWillRead(&read_buffer, &buf_size, -1));
600 CHECK_EQ(0, resource_controller.cancel_called());
601 CHECK_EQ(MimeSniffingResourceHandler::STATE_STREAMING,
602 mime_sniffing_handler->state_);
603
604 if (!will_read)
605 return;
606
607 defer = false;
608 CHECK_EQ(read_completed,
609 mime_sniffing_handler->OnReadCompleted(2000, &defer));
610 CHECK_EQ(0, resource_controller.cancel_called());
611 CHECK_EQ(MimeSniffingResourceHandler::STATE_STREAMING,
612 mime_sniffing_handler->state_);
613
614 if (!read_completed)
615 return;
616
617 CHECK_EQ(defer_read_completed, defer);
618 if (defer) {
619 expected_resume_calls++;
620 mime_sniffing_handler->Resume();
621 }
622 CHECK_EQ(expected_resume_calls, resource_controller.resume_called());
623
624 content::RunAllPendingInMessageLoop();
625 }
626
329 // Test that the proper Accept: header is set based on the ResourceType 627 // Test that the proper Accept: header is set based on the ResourceType
330 TEST_F(MimeTypeResourceHandlerTest, AcceptHeaders) { 628 TEST_F(MimeSniffingResourceHandlerTest, AcceptHeaders) {
331 EXPECT_EQ( 629 EXPECT_EQ(
332 "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp," 630 "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,"
333 "*/*;q=0.8", 631 "*/*;q=0.8",
334 TestAcceptHeaderSetting(RESOURCE_TYPE_MAIN_FRAME)); 632 TestAcceptHeaderSetting(RESOURCE_TYPE_MAIN_FRAME));
335 EXPECT_EQ( 633 EXPECT_EQ(
336 "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp," 634 "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,"
337 "*/*;q=0.8", 635 "*/*;q=0.8",
338 TestAcceptHeaderSetting(RESOURCE_TYPE_SUB_FRAME)); 636 TestAcceptHeaderSetting(RESOURCE_TYPE_SUB_FRAME));
339 EXPECT_EQ("text/css,*/*;q=0.1", 637 EXPECT_EQ("text/css,*/*;q=0.1",
340 TestAcceptHeaderSetting(RESOURCE_TYPE_STYLESHEET)); 638 TestAcceptHeaderSetting(RESOURCE_TYPE_STYLESHEET));
341 EXPECT_EQ("*/*", 639 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_SCRIPT));
342 TestAcceptHeaderSetting(RESOURCE_TYPE_SCRIPT));
343 EXPECT_EQ("image/webp,image/*,*/*;q=0.8", 640 EXPECT_EQ("image/webp,image/*,*/*;q=0.8",
344 TestAcceptHeaderSetting(RESOURCE_TYPE_IMAGE)); 641 TestAcceptHeaderSetting(RESOURCE_TYPE_IMAGE));
345 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_FONT_RESOURCE)); 642 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_FONT_RESOURCE));
346 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_SUB_RESOURCE)); 643 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_SUB_RESOURCE));
347 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_OBJECT)); 644 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_OBJECT));
348 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_MEDIA)); 645 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_MEDIA));
349 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_WORKER)); 646 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_WORKER));
350 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_SHARED_WORKER)); 647 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_SHARED_WORKER));
351 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_PREFETCH)); 648 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_PREFETCH));
352 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_FAVICON)); 649 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_FAVICON));
353 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_XHR)); 650 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_XHR));
354 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_PING)); 651 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_PING));
355 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_SERVICE_WORKER)); 652 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_SERVICE_WORKER));
356 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_CSP_REPORT)); 653 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_CSP_REPORT));
357 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_PLUGIN_RESOURCE)); 654 EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_PLUGIN_RESOURCE));
358 655
359 // Ensure that if an Accept header is already set, it is not overwritten. 656 // Ensure that if an Accept header is already set, it is not overwritten.
360 net::URLRequestContext context; 657 net::URLRequestContext context;
361 std::unique_ptr<net::URLRequest> request(context.CreateRequest( 658 std::unique_ptr<net::URLRequest> request(context.CreateRequest(
362 GURL("http://www.google.com"), net::DEFAULT_PRIORITY, nullptr)); 659 GURL("http://www.google.com"), net::DEFAULT_PRIORITY, nullptr));
363 request->SetExtraRequestHeaderByName("Accept", "*", true); 660 request->SetExtraRequestHeaderByName("Accept", "*", true);
364 EXPECT_EQ("*", 661 EXPECT_EQ("*", TestAcceptHeaderSettingWithURLRequest(RESOURCE_TYPE_XHR,
365 TestAcceptHeaderSettingWithURLRequest(RESOURCE_TYPE_XHR, request.get())); 662 request.get()));
366 } 663 }
367 664
368 // Test that stream requests are correctly intercepted under the right 665 // Test that stream requests are correctly intercepted under the right
369 // circumstances. Test is not relevent when plugins are disabled. 666 // circumstances. Test is not relevent when plugins are disabled.
370 #if defined(ENABLE_PLUGINS) 667 #if defined(ENABLE_PLUGINS)
371 TEST_F(MimeTypeResourceHandlerTest, StreamHandling) { 668 TEST_F(MimeSniffingResourceHandlerTest, StreamHandling) {
372 bool allow_download; 669 bool allow_download;
373 bool must_download; 670 bool must_download;
374 ResourceType resource_type; 671 ResourceType resource_type;
375 672
376 // Ensure the stream is handled by MaybeInterceptAsStream in the 673 // Ensure the stream is handled by MaybeInterceptAsStream in the
377 // ResourceDispatcherHost. 674 // ResourceDispatcherHost.
378 set_stream_has_handler(true); 675 set_stream_has_handler(true);
379 set_plugin_available(true); 676 set_plugin_available(true);
380 677
381 // Main frame request with no download allowed. Stream shouldn't be 678 // Main frame request with no download allowed. Stream shouldn't be
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 722
426 // Test the cases where the stream isn't handled by MaybeInterceptAsStream 723 // Test the cases where the stream isn't handled by MaybeInterceptAsStream
427 // in the ResourceDispatcherHost. 724 // in the ResourceDispatcherHost.
428 set_stream_has_handler(false); 725 set_stream_has_handler(false);
429 allow_download = false; 726 allow_download = false;
430 must_download = false; 727 must_download = false;
431 resource_type = RESOURCE_TYPE_OBJECT; 728 resource_type = RESOURCE_TYPE_OBJECT;
432 EXPECT_FALSE( 729 EXPECT_FALSE(
433 TestStreamIsIntercepted(allow_download, must_download, resource_type)); 730 TestStreamIsIntercepted(allow_download, must_download, resource_type));
434 731
435 allow_download = true;
436 must_download = false;
437 resource_type = RESOURCE_TYPE_MAIN_FRAME;
438 EXPECT_FALSE(
439 TestStreamIsIntercepted(allow_download, must_download, resource_type));
440
441 // Test the cases where the stream handled by MaybeInterceptAsStream 732 // Test the cases where the stream handled by MaybeInterceptAsStream
442 // with plugin not available. This is the case when intercepting streams for 733 // with plugin not available. This is the case when intercepting streams for
443 // the streamsPrivate extensions API. 734 // the streamsPrivate extensions API.
444 set_stream_has_handler(true); 735 set_stream_has_handler(true);
445 set_plugin_available(false); 736 set_plugin_available(false);
446 allow_download = false; 737 allow_download = false;
447 must_download = false; 738 must_download = false;
448 resource_type = RESOURCE_TYPE_OBJECT; 739 resource_type = RESOURCE_TYPE_OBJECT;
449 EXPECT_TRUE( 740 EXPECT_TRUE(
450 TestStreamIsIntercepted(allow_download, must_download, resource_type)); 741 TestStreamIsIntercepted(allow_download, must_download, resource_type));
451 742
452 // Test the cases where the stream handled by MaybeInterceptAsStream 743 // Test the cases where the stream handled by MaybeInterceptAsStream
453 // with plugin not available. This is the case when intercepting streams for 744 // with plugin not available. This is the case when intercepting streams for
454 // the streamsPrivate extensions API with stale plugin. 745 // the streamsPrivate extensions API with stale plugin.
455 set_plugin_stale(true); 746 set_plugin_stale(true);
456 allow_download = false; 747 allow_download = false;
457 must_download = false; 748 must_download = false;
458 resource_type = RESOURCE_TYPE_OBJECT; 749 resource_type = RESOURCE_TYPE_OBJECT;
459 EXPECT_TRUE( 750 EXPECT_TRUE(
460 TestStreamIsIntercepted(allow_download, must_download, resource_type)); 751 TestStreamIsIntercepted(allow_download, must_download, resource_type));
461 } 752 }
462 #endif 753 #endif
463 754
464 } // namespace 755 // Test that the MimeSniffingHandler operates properly when it doesn't sniff
756 // resources.
757 TEST_F(MimeSniffingResourceHandlerTest, NoSniffing) {
758 // Test simple case.
759 TestHandlerNoSniffing(true, false, true, true, false);
760
761 // Test deferral in OnResponseStarted and/or in OnReadCompleted.
762 TestHandlerNoSniffing(true, true, true, true, false);
763 TestHandlerNoSniffing(true, false, true, true, true);
764 TestHandlerNoSniffing(true, true, true, true, true);
765
766 // Test cancel in OnResponseStarted, OnWillRead, OnReadCompleted.
767 TestHandlerNoSniffing(false, false, false, false, false);
768 TestHandlerNoSniffing(true, false, false, false, false);
769 TestHandlerNoSniffing(true, false, true, false, false);
770
771 // Test cancel after OnResponseStarted deferral.
772 TestHandlerNoSniffing(true, true, false, false, false);
773 TestHandlerNoSniffing(true, true, true, false, false);
774
775 content::RunAllPendingInMessageLoop();
776 }
777
778 // Test that the MimeSniffingHandler operates properly when it sniffs
779 // resources.
780 TEST_F(MimeSniffingResourceHandlerTest, Sniffing) {
781 // Test simple case.
782 TestHandlerSniffing(true, false, true, true, false);
783
784 // Test deferral in OnResponseStarted and/or in OnReadCompleted.
785 TestHandlerSniffing(true, true, true, true, false);
786 TestHandlerSniffing(true, false, true, true, true);
787 TestHandlerSniffing(true, true, true, true, true);
788
789 // Test cancel in OnResponseStarted, OnWillRead, OnReadCompleted.
790 TestHandlerSniffing(false, false, false, false, false);
791 TestHandlerSniffing(true, false, false, false, false);
792 TestHandlerSniffing(true, false, true, false, false);
793
794 // Test cancel after OnResponseStarted deferral.
795 TestHandlerSniffing(true, true, false, false, false);
796 TestHandlerSniffing(true, true, true, false, false);
797
798 content::RunAllPendingInMessageLoop();
799 }
800
801 // Tests that 304s do not trigger a change in handlers.
802 TEST_F(MimeSniffingResourceHandlerTest, 304Handling) {
803 net::URLRequestContext context;
804 std::unique_ptr<net::URLRequest> request(context.CreateRequest(
805 GURL("http://www.google.com"), net::DEFAULT_PRIORITY, nullptr));
806 ResourceRequestInfo::AllocateForTesting(request.get(),
807 RESOURCE_TYPE_MAIN_FRAME,
808 nullptr, // context
809 0, // render_process_id
810 0, // render_view_id
811 0, // render_frame_id
812 true, // is_main_frame
813 false, // parent_is_main_frame
814 true, // allow_download
815 true, // is_async
816 false); // is_using_lofi
817
818 TestResourceDispatcherHost host(false);
819 TestResourceDispatcherHostDelegate host_delegate(false);
820 host.SetDelegate(&host_delegate);
821
822 TestFakePluginService plugin_service(false, false);
823 std::unique_ptr<ResourceHandler> intercepting_handler(
824 new InterceptingResourceHandler(std::unique_ptr<ResourceHandler>(),
825 nullptr));
826 std::unique_ptr<ResourceHandler> mime_handler(new MimeSniffingResourceHandler(
827 std::unique_ptr<ResourceHandler>(
828 new TestResourceHandler(true, false, true, true, false)),
829 &host, &plugin_service,
830 static_cast<InterceptingResourceHandler*>(intercepting_handler.get()),
831 request.get()));
832
833 TestResourceController resource_controller;
834 mime_handler->SetController(&resource_controller);
835
836 // Simulate a 304 response.
837 scoped_refptr<ResourceResponse> response(new ResourceResponse);
838 // The MIME type isn't important but it shouldn't be empty.
839 response->head.mime_type = "application/pdf";
840 response->head.headers = new net::HttpResponseHeaders("HTTP/1.x 304 OK");
841
842 // The response is received. No new ResourceHandler should be created to
843 // handle the download.
844 bool defer = false;
845 mime_handler->OnResponseStarted(response.get(), &defer);
846 EXPECT_FALSE(defer);
847 TestResourceHandler* new_handler = host.last_resource_handler();
848 EXPECT_TRUE(!new_handler);
849
850 content::RunAllPendingInMessageLoop();
851 }
465 852
466 } // namespace content 853 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698