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
3 // found in the LICENSE file.
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop.h"
10 #include "base/process.h"
11 #include "base/process_util.h"
12 #include "content/child/request_extra_data.h"
13 #include "content/child/resource_dispatcher.h"
14 #include "content/common/resource_messages.h"
15 #include "content/public/common/resource_response.h"
16 #include "net/base/net_errors.h"
17 #include "net/base/upload_data.h"
18 #include "net/http/http_response_headers.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "webkit/common/appcache/appcache_interfaces.h"
22 using webkit_glue::ResourceLoaderBridge
;
23 using webkit_glue::ResourceResponseInfo
;
27 static const char test_page_url
[] = "http://www.google.com/";
28 static const char test_page_headers
[] =
29 "HTTP/1.1 200 OK\nContent-Type:text/html\n\n";
30 static const char test_page_mime_type
[] = "text/html";
31 static const char test_page_charset
[] = "";
32 static const char test_page_contents
[] =
33 "<html><head><title>Google</title></head><body><h1>Google</h1></body></html>";
34 static const uint32 test_page_contents_len
= arraysize(test_page_contents
) - 1;
36 static const char kShmemSegmentName
[] = "DeferredResourceLoaderTest";
38 // Listens for request response data and stores it so that it can be compared
39 // to the reference data.
40 class TestRequestCallback
: public ResourceLoaderBridge::Peer
{
42 TestRequestCallback() : complete_(false) {
45 virtual void OnUploadProgress(uint64 position
, uint64 size
) OVERRIDE
{
48 virtual bool OnReceivedRedirect(
50 const ResourceResponseInfo
& info
,
51 bool* has_new_first_party_for_cookies
,
52 GURL
* new_first_party_for_cookies
) OVERRIDE
{
53 *has_new_first_party_for_cookies
= false;
57 virtual void OnReceivedResponse(const ResourceResponseInfo
& info
) OVERRIDE
{
60 virtual void OnDownloadedData(int len
) OVERRIDE
{
63 virtual void OnReceivedData(const char* data
,
65 int encoded_data_length
) OVERRIDE
{
66 EXPECT_FALSE(complete_
);
67 data_
.append(data
, data_length
);
68 total_encoded_data_length_
+= encoded_data_length
;
71 virtual void OnCompletedRequest(
73 bool was_ignored_by_handler
,
74 const std::string
& security_info
,
75 const base::TimeTicks
& completion_time
) OVERRIDE
{
76 EXPECT_FALSE(complete_
);
80 bool complete() const {
83 const std::string
& data() const {
86 int total_encoded_data_length() const {
87 return total_encoded_data_length_
;
93 int total_encoded_data_length_
;
97 // Sets up the message sender override for the unit test
98 class ResourceDispatcherTest
: public testing::Test
, public IPC::Sender
{
100 // Emulates IPC send operations (IPC::Sender) by adding
101 // pending messages to the queue.
102 virtual bool Send(IPC::Message
* msg
) OVERRIDE
{
103 message_queue_
.push_back(IPC::Message(*msg
));
108 // Emulates the browser process and processes the pending IPC messages,
109 // returning the hardcoded file contents.
110 void ProcessMessages() {
111 while (!message_queue_
.empty()) {
113 ResourceHostMsg_Request request
;
114 ASSERT_TRUE(ResourceHostMsg_RequestResource::Read(
115 &message_queue_
[0], &request_id
, &request
));
118 EXPECT_EQ(test_page_url
, request
.url
.spec());
120 // received response message
121 ResourceResponseHead response
;
122 std::string
raw_headers(test_page_headers
);
123 std::replace(raw_headers
.begin(), raw_headers
.end(), '\n', '\0');
124 response
.headers
= new net::HttpResponseHeaders(raw_headers
);
125 response
.mime_type
= test_page_mime_type
;
126 response
.charset
= test_page_charset
;
127 dispatcher_
->OnReceivedResponse(request_id
, response
);
129 // received data message with the test contents
130 base::SharedMemory shared_mem
;
131 EXPECT_TRUE(shared_mem
.CreateAndMapAnonymous(test_page_contents_len
));
132 char* put_data_here
= static_cast<char*>(shared_mem
.memory());
133 memcpy(put_data_here
, test_page_contents
, test_page_contents_len
);
134 base::SharedMemoryHandle dup_handle
;
135 EXPECT_TRUE(shared_mem
.GiveToProcess(
136 base::Process::Current().handle(), &dup_handle
));
137 dispatcher_
->OnSetDataBuffer(message_queue_
[0], request_id
, dup_handle
,
138 test_page_contents_len
, 0);
139 dispatcher_
->OnReceivedData(message_queue_
[0], request_id
, 0,
140 test_page_contents_len
,
141 test_page_contents_len
);
143 message_queue_
.erase(message_queue_
.begin());
145 // read the ack message.
146 Tuple1
<int> request_ack
;
147 ASSERT_TRUE(ResourceHostMsg_DataReceived_ACK::Read(
148 &message_queue_
[0], &request_ack
));
150 ASSERT_EQ(request_ack
.a
, request_id
);
152 message_queue_
.erase(message_queue_
.begin());
158 virtual void SetUp() OVERRIDE
{
159 dispatcher_
.reset(new ResourceDispatcher(this));
161 virtual void TearDown() OVERRIDE
{
165 ResourceLoaderBridge
* CreateBridge() {
166 webkit_glue::ResourceLoaderBridge::RequestInfo request_info
;
167 request_info
.method
= "GET";
168 request_info
.url
= GURL(test_page_url
);
169 request_info
.first_party_for_cookies
= GURL(test_page_url
);
170 request_info
.referrer
= GURL();
171 request_info
.headers
= std::string();
172 request_info
.load_flags
= 0;
173 request_info
.requestor_pid
= 0;
174 request_info
.request_type
= ResourceType::SUB_RESOURCE
;
175 request_info
.appcache_host_id
= appcache::kNoHostId
;
176 request_info
.routing_id
= 0;
177 RequestExtraData
extra_data(WebKit::WebReferrerPolicyDefault
,
179 true, 0, false, -1, true,
180 PAGE_TRANSITION_LINK
, -1, -1);
181 request_info
.extra_data
= &extra_data
;
183 return dispatcher_
->CreateBridge(request_info
);
186 std::vector
<IPC::Message
> message_queue_
;
187 static scoped_ptr
<ResourceDispatcher
> dispatcher_
;
191 scoped_ptr
<ResourceDispatcher
> ResourceDispatcherTest::dispatcher_
;
193 // Does a simple request and tests that the correct data is received.
194 TEST_F(ResourceDispatcherTest
, RoundTrip
) {
195 TestRequestCallback callback
;
196 ResourceLoaderBridge
* bridge
= CreateBridge();
198 bridge
->Start(&callback
);
202 // FIXME(brettw) when the request complete messages are actually handledo
203 // and dispatched, uncomment this.
204 //EXPECT_TRUE(callback.complete());
205 //EXPECT_STREQ(test_page_contents, callback.data().c_str());
206 //EXPECT_EQ(test_page_contents_len, callback.total_encoded_data_length());
211 // Tests that the request IDs are straight when there are multiple requests.
212 TEST_F(ResourceDispatcherTest
, MultipleRequests
) {
216 // Tests that the cancel method prevents other messages from being received
217 TEST_F(ResourceDispatcherTest
, Cancel
) {
221 TEST_F(ResourceDispatcherTest
, Cookies
) {
225 TEST_F(ResourceDispatcherTest
, SerializedPostData
) {
229 // This class provides functionality to validate whether the ResourceDispatcher
230 // object honors the deferred loading contract correctly, i.e. if deferred
231 // loading is enabled it should queue up any responses received. If deferred
232 // loading is enabled/disabled in the context of a dispatched message, other
233 // queued messages should not be dispatched until deferred load is turned off.
234 class DeferredResourceLoadingTest
: public ResourceDispatcherTest
,
235 public ResourceLoaderBridge::Peer
{
237 DeferredResourceLoadingTest()
238 : defer_loading_(false) {
241 virtual bool Send(IPC::Message
* msg
) OVERRIDE
{
246 void InitMessages() {
247 set_defer_loading(true);
249 ResourceResponseHead response_head
;
250 response_head
.error_code
= net::OK
;
252 dispatcher_
->OnMessageReceived(
253 ResourceMsg_ReceivedResponse(0, 0, response_head
));
255 // Duplicate the shared memory handle so both the test and the callee can
257 base::SharedMemoryHandle duplicated_handle
;
258 EXPECT_TRUE(shared_handle_
.ShareToProcess(base::GetCurrentProcessHandle(),
259 &duplicated_handle
));
261 dispatcher_
->OnMessageReceived(
262 ResourceMsg_SetDataBuffer(0, 0, duplicated_handle
, 100, 0));
263 dispatcher_
->OnMessageReceived(
264 ResourceMsg_DataReceived(0, 0, 0, 100, 100));
266 set_defer_loading(false);
269 // ResourceLoaderBridge::Peer methods.
270 virtual void OnUploadProgress(uint64 position
, uint64 size
) OVERRIDE
{
273 virtual bool OnReceivedRedirect(
275 const ResourceResponseInfo
& info
,
276 bool* has_new_first_party_for_cookies
,
277 GURL
* new_first_party_for_cookies
) OVERRIDE
{
278 *has_new_first_party_for_cookies
= false;
282 virtual void OnReceivedResponse(const ResourceResponseInfo
& info
) OVERRIDE
{
283 EXPECT_EQ(defer_loading_
, false);
284 set_defer_loading(true);
287 virtual void OnDownloadedData(int len
) OVERRIDE
{
290 virtual void OnReceivedData(const char* data
,
292 int encoded_data_length
) OVERRIDE
{
293 EXPECT_EQ(defer_loading_
, false);
294 set_defer_loading(false);
297 virtual void OnCompletedRequest(
299 bool was_ignored_by_handler
,
300 const std::string
& security_info
,
301 const base::TimeTicks
& completion_time
) OVERRIDE
{
305 virtual void SetUp() OVERRIDE
{
306 ResourceDispatcherTest::SetUp();
307 shared_handle_
.Delete(kShmemSegmentName
);
308 EXPECT_TRUE(shared_handle_
.CreateNamed(kShmemSegmentName
, false, 100));
311 virtual void TearDown() OVERRIDE
{
312 shared_handle_
.Close();
313 EXPECT_TRUE(shared_handle_
.Delete(kShmemSegmentName
));
314 ResourceDispatcherTest::TearDown();
318 void set_defer_loading(bool defer
) {
319 defer_loading_
= defer
;
320 dispatcher_
->SetDefersLoading(0, defer
);
323 bool defer_loading() const {
324 return defer_loading_
;
328 base::SharedMemory shared_handle_
;
331 TEST_F(DeferredResourceLoadingTest
, DeferredLoadTest
) {
332 base::MessageLoop
message_loop(base::MessageLoop::TYPE_IO
);
334 ResourceLoaderBridge
* bridge
= CreateBridge();
339 // Dispatch deferred messages.
340 message_loop
.RunUntilIdle();
344 class TimeConversionTest
: public ResourceDispatcherTest
,
345 public ResourceLoaderBridge::Peer
{
347 virtual bool Send(IPC::Message
* msg
) OVERRIDE
{
352 void PerformTest(const ResourceResponseHead
& response_head
) {
353 scoped_ptr
<ResourceLoaderBridge
> bridge(CreateBridge());
356 dispatcher_
->OnMessageReceived(
357 ResourceMsg_ReceivedResponse(0, 0, response_head
));
360 // ResourceLoaderBridge::Peer methods.
361 virtual void OnUploadProgress(uint64 position
, uint64 size
) OVERRIDE
{
364 virtual bool OnReceivedRedirect(
366 const ResourceResponseInfo
& info
,
367 bool* has_new_first_party_for_cookies
,
368 GURL
* new_first_party_for_cookies
) OVERRIDE
{
372 virtual void OnReceivedResponse(const ResourceResponseInfo
& info
) OVERRIDE
{
373 response_info_
= info
;
376 virtual void OnDownloadedData(int len
) OVERRIDE
{
379 virtual void OnReceivedData(const char* data
,
381 int encoded_data_length
) OVERRIDE
{
384 virtual void OnCompletedRequest(
386 bool was_ignored_by_handler
,
387 const std::string
& security_info
,
388 const base::TimeTicks
& completion_time
) OVERRIDE
{
391 const ResourceResponseInfo
& response_info() const { return response_info_
; }
394 ResourceResponseInfo response_info_
;
397 // TODO(simonjam): Enable this when 10829031 lands.
398 TEST_F(TimeConversionTest
, DISABLED_ProperlyInitialized
) {
399 ResourceResponseHead response_head
;
400 response_head
.error_code
= net::OK
;
401 response_head
.request_start
= base::TimeTicks::FromInternalValue(5);
402 response_head
.response_start
= base::TimeTicks::FromInternalValue(15);
403 response_head
.load_timing
.request_start_time
= base::Time::Now();
404 response_head
.load_timing
.request_start
=
405 base::TimeTicks::FromInternalValue(10);
406 response_head
.load_timing
.connect_timing
.connect_start
=
407 base::TimeTicks::FromInternalValue(13);
409 PerformTest(response_head
);
411 EXPECT_LT(base::TimeTicks(), response_info().load_timing
.request_start
);
412 EXPECT_EQ(base::TimeTicks(),
413 response_info().load_timing
.connect_timing
.dns_start
);
414 EXPECT_LE(response_head
.load_timing
.request_start
,
415 response_info().load_timing
.connect_timing
.connect_start
);
418 TEST_F(TimeConversionTest
, PartiallyInitialized
) {
419 ResourceResponseHead response_head
;
420 response_head
.error_code
= net::OK
;
421 response_head
.request_start
= base::TimeTicks::FromInternalValue(5);
422 response_head
.response_start
= base::TimeTicks::FromInternalValue(15);
424 PerformTest(response_head
);
426 EXPECT_EQ(base::TimeTicks(), response_info().load_timing
.request_start
);
427 EXPECT_EQ(base::TimeTicks(),
428 response_info().load_timing
.connect_timing
.dns_start
);
431 TEST_F(TimeConversionTest
, NotInitialized
) {
432 ResourceResponseHead response_head
;
433 response_head
.error_code
= net::OK
;
435 PerformTest(response_head
);
437 EXPECT_EQ(base::TimeTicks(), response_info().load_timing
.request_start
);
438 EXPECT_EQ(base::TimeTicks(),
439 response_info().load_timing
.connect_timing
.dns_start
);
442 } // namespace content