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
3 // found in the LICENSE file.
5 #include "content/browser/loader/buffered_resource_handler.h"
7 #include "base/logging.h"
8 #include "base/macros.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "content/browser/loader/resource_dispatcher_host_impl.h"
11 #include "content/public/browser/resource_controller.h"
12 #include "content/public/browser/resource_dispatcher_host_delegate.h"
13 #include "content/public/browser/resource_request_info.h"
14 #include "content/public/common/resource_response.h"
15 #include "content/public/test/test_browser_thread_bundle.h"
16 #include "content/public/test/test_utils.h"
17 #include "net/url_request/url_request_context.h"
18 #include "testing/gtest/include/gtest/gtest.h"
25 class TestResourceHandler
: public ResourceHandler
{
27 TestResourceHandler() : ResourceHandler(nullptr) {}
29 void SetController(ResourceController
* controller
) override
{}
31 bool OnUploadProgress(uint64 position
, uint64 size
) override
{
36 bool OnRequestRedirected(const net::RedirectInfo
& redirect_info
,
37 ResourceResponse
* response
,
38 bool* defer
) override
{
43 bool OnResponseStarted(ResourceResponse
* response
, bool* defer
) override
{
47 bool OnWillStart(const GURL
& url
, bool* defer
) override
{
52 bool OnBeforeNetworkStart(const GURL
& url
, bool* defer
) override
{
57 bool OnWillRead(scoped_refptr
<net::IOBuffer
>* buf
,
59 int min_size
) override
{
64 bool OnReadCompleted(int bytes_read
, bool* defer
) override
{
69 void OnResponseCompleted(const net::URLRequestStatus
& status
,
70 const std::string
& security_info
,
71 bool* defer
) override
{
74 void OnDataDownloaded(int bytes_downloaded
) override
{
79 DISALLOW_COPY_AND_ASSIGN(TestResourceHandler
);
82 class TestResourceDispatcherHost
: public ResourceDispatcherHostImpl
{
84 explicit TestResourceDispatcherHost(bool stream_has_handler
)
85 : stream_has_handler_(stream_has_handler
),
86 intercepted_as_stream_(false) {}
88 bool intercepted_as_stream() const { return intercepted_as_stream_
; }
90 scoped_ptr
<ResourceHandler
> CreateResourceHandlerForDownload(
91 net::URLRequest
* request
,
92 bool is_content_initiated
,
95 scoped_ptr
<DownloadSaveInfo
> save_info
,
96 const DownloadUrlParameters::OnStartedCallback
& started_cb
) override
{
97 return scoped_ptr
<ResourceHandler
>(new TestResourceHandler
).Pass();
100 scoped_ptr
<ResourceHandler
> MaybeInterceptAsStream(
101 net::URLRequest
* request
,
102 ResourceResponse
* response
,
103 std::string
* payload
) override
{
104 if (stream_has_handler_
) {
105 intercepted_as_stream_
= true;
106 return scoped_ptr
<ResourceHandler
>(new TestResourceHandler
).Pass();
108 return scoped_ptr
<ResourceHandler
>();
113 // Whether the URL request should be intercepted as a stream.
114 bool stream_has_handler_
;
116 // Whether the URL request has been intercepted as a stream.
117 bool intercepted_as_stream_
;
120 class TestResourceDispatcherHostDelegate
121 : public ResourceDispatcherHostDelegate
{
123 TestResourceDispatcherHostDelegate(bool must_download
)
124 : must_download_(must_download
) {
127 bool ShouldForceDownloadResource(const GURL
& url
,
128 const std::string
& mime_type
) override
{
129 return must_download_
;
133 const bool must_download_
;
136 class TestResourceController
: public ResourceController
{
138 void Cancel() override
{}
140 void CancelAndIgnore() override
{
144 void CancelWithError(int error_code
) override
{
148 void Resume() override
{
153 class BufferedResourceHandlerTest
: public testing::Test
{
155 BufferedResourceHandlerTest() : stream_has_handler_(false) {}
157 void set_stream_has_handler(bool stream_has_handler
) {
158 stream_has_handler_
= stream_has_handler
;
161 bool TestStreamIsIntercepted(bool allow_download
,
163 ResourceType request_resource_type
);
166 // Whether the URL request should be intercepted as a stream.
167 bool stream_has_handler_
;
169 TestBrowserThreadBundle thread_bundle_
;
172 bool BufferedResourceHandlerTest::TestStreamIsIntercepted(
175 ResourceType request_resource_type
) {
176 net::URLRequestContext context
;
177 scoped_ptr
<net::URLRequest
> request(context
.CreateRequest(
178 GURL("http://www.google.com"), net::DEFAULT_PRIORITY
, nullptr, nullptr));
179 bool is_main_frame
= request_resource_type
== RESOURCE_TYPE_MAIN_FRAME
;
180 ResourceRequestInfo::AllocateForTesting(
182 request_resource_type
,
184 0, // render_process_id
186 0, // render_frame_id
187 is_main_frame
, // is_main_frame
188 false, // parent_is_main_frame
189 allow_download
, // allow_download
192 TestResourceDispatcherHost
host(stream_has_handler_
);
193 TestResourceDispatcherHostDelegate
host_delegate(must_download
);
194 host
.SetDelegate(&host_delegate
);
196 scoped_ptr
<ResourceHandler
> buffered_handler(
197 new BufferedResourceHandler(
198 scoped_ptr
<ResourceHandler
>(new TestResourceHandler()).Pass(),
199 &host
, request
.get()));
200 TestResourceController resource_controller
;
201 buffered_handler
->SetController(&resource_controller
);
203 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
204 // The MIME type isn't important but it shouldn't be empty.
205 response
->head
.mime_type
= "application/pdf";
208 buffered_handler
->OnResponseStarted(response
.get(), &defer
);
210 content::RunAllPendingInMessageLoop();
212 return host
.intercepted_as_stream();
215 // TODO(raymes): Currently fails on Mac due to dependency on plugin
217 #if defined(OS_MACOSX)
218 #define MAYBE_StreamHandling DISABLED_StreamHandling
220 #define MAYBE_StreamHandling StreamHandling
222 // Test that stream requests are correctly intercepted under the right
224 TEST_F(BufferedResourceHandlerTest
, MAYBE_StreamHandling
) {
227 ResourceType resource_type
;
229 // Ensure the stream is handled by MaybeInterceptAsStream in the
230 // ResourceDispatcherHost.
231 set_stream_has_handler(true);
233 // Main frame request with no download allowed. Stream shouldn't be
235 allow_download
= false;
236 must_download
= false;
237 resource_type
= RESOURCE_TYPE_MAIN_FRAME
;
239 TestStreamIsIntercepted(allow_download
, must_download
, resource_type
));
241 // Main frame request with download allowed. Stream should be intercepted.
242 allow_download
= true;
243 must_download
= false;
244 resource_type
= RESOURCE_TYPE_MAIN_FRAME
;
246 TestStreamIsIntercepted(allow_download
, must_download
, resource_type
));
248 // Main frame request with download forced. Stream shouldn't be intercepted.
249 allow_download
= true;
250 must_download
= true;
251 resource_type
= RESOURCE_TYPE_MAIN_FRAME
;
253 TestStreamIsIntercepted(allow_download
, must_download
, resource_type
));
255 // Sub-resource request with download not allowed. Stream shouldn't be
257 allow_download
= false;
258 must_download
= false;
259 resource_type
= RESOURCE_TYPE_SUB_RESOURCE
;
261 TestStreamIsIntercepted(allow_download
, must_download
, resource_type
));
263 // Object request with download not allowed. Stream should be intercepted.
264 allow_download
= false;
265 must_download
= false;
266 resource_type
= RESOURCE_TYPE_OBJECT
;
268 TestStreamIsIntercepted(allow_download
, must_download
, resource_type
));
270 // Test the cases where the stream isn't handled by MaybeInterceptAsStream
271 // in the ResourceDispatcherHost.
272 set_stream_has_handler(false);
274 allow_download
= false;
275 must_download
= false;
276 resource_type
= RESOURCE_TYPE_OBJECT
;
278 TestStreamIsIntercepted(allow_download
, must_download
, resource_type
));
280 allow_download
= true;
281 must_download
= false;
282 resource_type
= RESOURCE_TYPE_MAIN_FRAME
;
284 TestStreamIsIntercepted(allow_download
, must_download
, resource_type
));
289 } // namespace content