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 "content/test/fake_plugin_service.h"
18 #include "net/url_request/url_request_context.h"
19 #include "testing/gtest/include/gtest/gtest.h"
26 class TestResourceHandler
: public ResourceHandler
{
28 TestResourceHandler() : ResourceHandler(nullptr) {}
30 void SetController(ResourceController
* controller
) override
{}
32 bool OnUploadProgress(uint64 position
, uint64 size
) override
{
37 bool OnRequestRedirected(const net::RedirectInfo
& redirect_info
,
38 ResourceResponse
* response
,
39 bool* defer
) override
{
44 bool OnResponseStarted(ResourceResponse
* response
, bool* defer
) override
{
48 bool OnWillStart(const GURL
& url
, bool* defer
) override
{
53 bool OnBeforeNetworkStart(const GURL
& url
, bool* defer
) override
{
58 bool OnWillRead(scoped_refptr
<net::IOBuffer
>* buf
,
60 int min_size
) override
{
65 bool OnReadCompleted(int bytes_read
, bool* defer
) override
{
70 void OnResponseCompleted(const net::URLRequestStatus
& status
,
71 const std::string
& security_info
,
72 bool* defer
) override
{
75 void OnDataDownloaded(int bytes_downloaded
) override
{
80 DISALLOW_COPY_AND_ASSIGN(TestResourceHandler
);
83 class TestResourceDispatcherHost
: public ResourceDispatcherHostImpl
{
85 explicit TestResourceDispatcherHost(bool stream_has_handler
)
86 : stream_has_handler_(stream_has_handler
),
87 intercepted_as_stream_(false) {}
89 bool intercepted_as_stream() const { return intercepted_as_stream_
; }
91 scoped_ptr
<ResourceHandler
> CreateResourceHandlerForDownload(
92 net::URLRequest
* request
,
93 bool is_content_initiated
,
96 scoped_ptr
<DownloadSaveInfo
> save_info
,
97 const DownloadUrlParameters::OnStartedCallback
& started_cb
) override
{
98 return scoped_ptr
<ResourceHandler
>(new TestResourceHandler
).Pass();
101 scoped_ptr
<ResourceHandler
> MaybeInterceptAsStream(
102 net::URLRequest
* request
,
103 ResourceResponse
* response
,
104 std::string
* payload
) override
{
105 if (stream_has_handler_
) {
106 intercepted_as_stream_
= true;
107 return scoped_ptr
<ResourceHandler
>(new TestResourceHandler
).Pass();
109 return scoped_ptr
<ResourceHandler
>();
114 // Whether the URL request should be intercepted as a stream.
115 bool stream_has_handler_
;
117 // Whether the URL request has been intercepted as a stream.
118 bool intercepted_as_stream_
;
121 class TestResourceDispatcherHostDelegate
122 : public ResourceDispatcherHostDelegate
{
124 TestResourceDispatcherHostDelegate(bool must_download
)
125 : must_download_(must_download
) {
128 bool ShouldForceDownloadResource(const GURL
& url
,
129 const std::string
& mime_type
) override
{
130 return must_download_
;
134 const bool must_download_
;
137 class TestResourceController
: public ResourceController
{
139 void Cancel() override
{}
141 void CancelAndIgnore() override
{
145 void CancelWithError(int error_code
) override
{
149 void Resume() override
{
154 class BufferedResourceHandlerTest
: public testing::Test
{
156 BufferedResourceHandlerTest() : stream_has_handler_(false) {}
158 void set_stream_has_handler(bool stream_has_handler
) {
159 stream_has_handler_
= stream_has_handler
;
162 bool TestStreamIsIntercepted(bool allow_download
,
164 ResourceType request_resource_type
);
167 // Whether the URL request should be intercepted as a stream.
168 bool stream_has_handler_
;
170 TestBrowserThreadBundle thread_bundle_
;
173 bool BufferedResourceHandlerTest::TestStreamIsIntercepted(
176 ResourceType request_resource_type
) {
177 net::URLRequestContext context
;
178 scoped_ptr
<net::URLRequest
> request(context
.CreateRequest(
179 GURL("http://www.google.com"), net::DEFAULT_PRIORITY
, nullptr, nullptr));
180 bool is_main_frame
= request_resource_type
== RESOURCE_TYPE_MAIN_FRAME
;
181 ResourceRequestInfo::AllocateForTesting(
183 request_resource_type
,
185 0, // render_process_id
187 0, // render_frame_id
188 is_main_frame
, // is_main_frame
189 false, // parent_is_main_frame
190 allow_download
, // allow_download
193 TestResourceDispatcherHost
host(stream_has_handler_
);
194 TestResourceDispatcherHostDelegate
host_delegate(must_download
);
195 host
.SetDelegate(&host_delegate
);
197 FakePluginService plugin_service
;
198 scoped_ptr
<ResourceHandler
> buffered_handler(
199 new BufferedResourceHandler(
200 scoped_ptr
<ResourceHandler
>(new TestResourceHandler()).Pass(),
204 TestResourceController resource_controller
;
205 buffered_handler
->SetController(&resource_controller
);
207 scoped_refptr
<ResourceResponse
> response(new ResourceResponse
);
208 // The MIME type isn't important but it shouldn't be empty.
209 response
->head
.mime_type
= "application/pdf";
212 buffered_handler
->OnResponseStarted(response
.get(), &defer
);
214 content::RunAllPendingInMessageLoop();
216 return host
.intercepted_as_stream();
219 // Test that stream requests are correctly intercepted under the right
221 TEST_F(BufferedResourceHandlerTest
, StreamHandling
) {
224 ResourceType resource_type
;
226 // Ensure the stream is handled by MaybeInterceptAsStream in the
227 // ResourceDispatcherHost.
228 set_stream_has_handler(true);
230 // Main frame request with no download allowed. Stream shouldn't be
232 allow_download
= false;
233 must_download
= false;
234 resource_type
= RESOURCE_TYPE_MAIN_FRAME
;
236 TestStreamIsIntercepted(allow_download
, must_download
, resource_type
));
238 // Main frame request with download allowed. Stream should be intercepted.
239 allow_download
= true;
240 must_download
= false;
241 resource_type
= RESOURCE_TYPE_MAIN_FRAME
;
243 TestStreamIsIntercepted(allow_download
, must_download
, resource_type
));
245 // Main frame request with download forced. Stream shouldn't be intercepted.
246 allow_download
= true;
247 must_download
= true;
248 resource_type
= RESOURCE_TYPE_MAIN_FRAME
;
250 TestStreamIsIntercepted(allow_download
, must_download
, resource_type
));
252 // Sub-resource request with download not allowed. Stream shouldn't be
254 allow_download
= false;
255 must_download
= false;
256 resource_type
= RESOURCE_TYPE_SUB_RESOURCE
;
258 TestStreamIsIntercepted(allow_download
, must_download
, resource_type
));
260 // Object request with download not allowed. Stream should be intercepted.
261 allow_download
= false;
262 must_download
= false;
263 resource_type
= RESOURCE_TYPE_OBJECT
;
265 TestStreamIsIntercepted(allow_download
, must_download
, resource_type
));
267 // Test the cases where the stream isn't handled by MaybeInterceptAsStream
268 // in the ResourceDispatcherHost.
269 set_stream_has_handler(false);
271 allow_download
= false;
272 must_download
= false;
273 resource_type
= RESOURCE_TYPE_OBJECT
;
275 TestStreamIsIntercepted(allow_download
, must_download
, resource_type
));
277 allow_download
= true;
278 must_download
= false;
279 resource_type
= RESOURCE_TYPE_MAIN_FRAME
;
281 TestStreamIsIntercepted(allow_download
, must_download
, resource_type
));
286 } // namespace content