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/message_loop.h"
10 #include "base/process/process.h"
11 #include "base/process/process_handle.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/http/http_response_headers.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "webkit/common/appcache/appcache_interfaces.h"
21 using webkit_glue::ResourceLoaderBridge;
22 using webkit_glue::ResourceResponseInfo;
26 static const char test_page_url[] = "http://www.google.com/";
27 static const char test_page_headers[] =
28 "HTTP/1.1 200 OK\nContent-Type:text/html\n\n";
29 static const char test_page_mime_type[] = "text/html";
30 static const char test_page_charset[] = "";
31 static const char test_page_contents[] =
32 "<html><head><title>Google</title></head><body><h1>Google</h1></body></html>";
33 static const uint32 test_page_contents_len = arraysize(test_page_contents) - 1;
35 static const char kShmemSegmentName[] = "DeferredResourceLoaderTest";
37 // Listens for request response data and stores it so that it can be compared
38 // to the reference data.
39 class TestRequestCallback : public ResourceLoaderBridge::Peer {
41 TestRequestCallback() : complete_(false) {
44 virtual void OnUploadProgress(uint64 position, uint64 size) OVERRIDE {
47 virtual bool OnReceivedRedirect(
49 const ResourceResponseInfo& info,
50 bool* has_new_first_party_for_cookies,
51 GURL* new_first_party_for_cookies) OVERRIDE {
52 *has_new_first_party_for_cookies = false;
56 virtual void OnReceivedResponse(const ResourceResponseInfo& info) OVERRIDE {
59 virtual void OnDownloadedData(int len, int encoded_data_length) OVERRIDE {
62 virtual void OnReceivedData(const char* data,
64 int encoded_data_length) OVERRIDE {
65 EXPECT_FALSE(complete_);
66 data_.append(data, data_length);
67 total_encoded_data_length_ += encoded_data_length;
70 virtual void OnCompletedRequest(
72 bool was_ignored_by_handler,
73 bool stale_copy_in_cache,
74 const std::string& security_info,
75 const base::TimeTicks& completion_time,
76 int64 total_transfer_size) OVERRIDE {
77 EXPECT_FALSE(complete_);
81 bool complete() const {
84 const std::string& data() const {
87 int total_encoded_data_length() const {
88 return total_encoded_data_length_;
94 int total_encoded_data_length_;
98 // Sets up the message sender override for the unit test
99 class ResourceDispatcherTest : public testing::Test, public IPC::Sender {
101 // Emulates IPC send operations (IPC::Sender) by adding
102 // pending messages to the queue.
103 virtual bool Send(IPC::Message* msg) OVERRIDE {
104 message_queue_.push_back(IPC::Message(*msg));
109 // Emulates the browser process and processes the pending IPC messages,
110 // returning the hardcoded file contents.
111 void ProcessMessages() {
112 while (!message_queue_.empty()) {
114 ResourceHostMsg_Request request;
115 ASSERT_TRUE(ResourceHostMsg_RequestResource::Read(
116 &message_queue_[0], &request_id, &request));
119 EXPECT_EQ(test_page_url, request.url.spec());
121 // received response message
122 ResourceResponseHead response;
123 std::string raw_headers(test_page_headers);
124 std::replace(raw_headers.begin(), raw_headers.end(), '\n', '\0');
125 response.headers = new net::HttpResponseHeaders(raw_headers);
126 response.mime_type = test_page_mime_type;
127 response.charset = test_page_charset;
128 dispatcher_->OnReceivedResponse(request_id, response);
130 // received data message with the test contents
131 base::SharedMemory shared_mem;
132 EXPECT_TRUE(shared_mem.CreateAndMapAnonymous(test_page_contents_len));
133 char* put_data_here = static_cast<char*>(shared_mem.memory());
134 memcpy(put_data_here, test_page_contents, test_page_contents_len);
135 base::SharedMemoryHandle dup_handle;
136 EXPECT_TRUE(shared_mem.GiveToProcess(
137 base::Process::Current().handle(), &dup_handle));
138 dispatcher_->OnSetDataBuffer(request_id, dup_handle,
139 test_page_contents_len, 0);
140 dispatcher_->OnReceivedData(request_id, 0, 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(blink::WebPageVisibilityStateVisible,
179 false, MSG_ROUTING_NONE, true, 0, GURL(),
181 PAGE_TRANSITION_LINK, false, -1, -1);
182 request_info.extra_data = &extra_data;
184 return dispatcher_->CreateBridge(request_info);
187 std::vector<IPC::Message> message_queue_;
188 static scoped_ptr<ResourceDispatcher> dispatcher_;
192 scoped_ptr<ResourceDispatcher> ResourceDispatcherTest::dispatcher_;
194 // Does a simple request and tests that the correct data is received.
195 TEST_F(ResourceDispatcherTest, RoundTrip) {
196 TestRequestCallback callback;
197 ResourceLoaderBridge* bridge = CreateBridge();
199 bridge->Start(&callback);
203 // FIXME(brettw) when the request complete messages are actually handledo
204 // and dispatched, uncomment this.
205 //EXPECT_TRUE(callback.complete());
206 //EXPECT_STREQ(test_page_contents, callback.data().c_str());
207 //EXPECT_EQ(test_page_contents_len, callback.total_encoded_data_length());
212 // Tests that the request IDs are straight when there are multiple requests.
213 TEST_F(ResourceDispatcherTest, MultipleRequests) {
217 // Tests that the cancel method prevents other messages from being received
218 TEST_F(ResourceDispatcherTest, Cancel) {
222 TEST_F(ResourceDispatcherTest, Cookies) {
226 TEST_F(ResourceDispatcherTest, SerializedPostData) {
230 // This class provides functionality to validate whether the ResourceDispatcher
231 // object honors the deferred loading contract correctly, i.e. if deferred
232 // loading is enabled it should queue up any responses received. If deferred
233 // loading is enabled/disabled in the context of a dispatched message, other
234 // queued messages should not be dispatched until deferred load is turned off.
235 class DeferredResourceLoadingTest : public ResourceDispatcherTest,
236 public ResourceLoaderBridge::Peer {
238 DeferredResourceLoadingTest()
239 : defer_loading_(false) {
242 virtual bool Send(IPC::Message* msg) OVERRIDE {
247 void InitMessages() {
248 set_defer_loading(true);
250 ResourceResponseHead response_head;
251 response_head.error_code = net::OK;
253 dispatcher_->OnMessageReceived(
254 ResourceMsg_ReceivedResponse(0, response_head));
256 // Duplicate the shared memory handle so both the test and the callee can
258 base::SharedMemoryHandle duplicated_handle;
259 EXPECT_TRUE(shared_handle_.ShareToProcess(base::GetCurrentProcessHandle(),
260 &duplicated_handle));
262 dispatcher_->OnMessageReceived(
263 ResourceMsg_SetDataBuffer(0, duplicated_handle, 100, 0));
264 dispatcher_->OnMessageReceived(ResourceMsg_DataReceived(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, int encoded_data_length) 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 bool stale_copy_in_cache,
301 const std::string& security_info,
302 const base::TimeTicks& completion_time,
303 int64 total_transfer_size) OVERRIDE {
307 virtual void SetUp() OVERRIDE {
308 ResourceDispatcherTest::SetUp();
309 shared_handle_.Delete(kShmemSegmentName);
310 EXPECT_TRUE(shared_handle_.CreateNamed(kShmemSegmentName, false, 100));
313 virtual void TearDown() OVERRIDE {
314 shared_handle_.Close();
315 EXPECT_TRUE(shared_handle_.Delete(kShmemSegmentName));
316 ResourceDispatcherTest::TearDown();
320 void set_defer_loading(bool defer) {
321 defer_loading_ = defer;
322 dispatcher_->SetDefersLoading(0, defer);
325 bool defer_loading() const {
326 return defer_loading_;
330 base::SharedMemory shared_handle_;
333 TEST_F(DeferredResourceLoadingTest, DeferredLoadTest) {
334 base::MessageLoopForIO message_loop;
336 ResourceLoaderBridge* bridge = CreateBridge();
341 // Dispatch deferred messages.
342 message_loop.RunUntilIdle();
346 class TimeConversionTest : public ResourceDispatcherTest,
347 public ResourceLoaderBridge::Peer {
349 virtual bool Send(IPC::Message* msg) OVERRIDE {
354 void PerformTest(const ResourceResponseHead& response_head) {
355 scoped_ptr<ResourceLoaderBridge> bridge(CreateBridge());
358 dispatcher_->OnMessageReceived(
359 ResourceMsg_ReceivedResponse(0, response_head));
362 // ResourceLoaderBridge::Peer methods.
363 virtual void OnUploadProgress(uint64 position, uint64 size) OVERRIDE {
366 virtual bool OnReceivedRedirect(
368 const ResourceResponseInfo& info,
369 bool* has_new_first_party_for_cookies,
370 GURL* new_first_party_for_cookies) OVERRIDE {
374 virtual void OnReceivedResponse(const ResourceResponseInfo& info) OVERRIDE {
375 response_info_ = info;
378 virtual void OnDownloadedData(int len, int encoded_data_length) OVERRIDE {
381 virtual void OnReceivedData(const char* data,
383 int encoded_data_length) OVERRIDE {
386 virtual void OnCompletedRequest(
388 bool was_ignored_by_handler,
389 bool stale_copy_in_cache,
390 const std::string& security_info,
391 const base::TimeTicks& completion_time,
392 int64 total_transfer_size) OVERRIDE {
395 const ResourceResponseInfo& response_info() const { return response_info_; }
398 ResourceResponseInfo response_info_;
401 // TODO(simonjam): Enable this when 10829031 lands.
402 TEST_F(TimeConversionTest, DISABLED_ProperlyInitialized) {
403 ResourceResponseHead response_head;
404 response_head.error_code = net::OK;
405 response_head.request_start = base::TimeTicks::FromInternalValue(5);
406 response_head.response_start = base::TimeTicks::FromInternalValue(15);
407 response_head.load_timing.request_start_time = base::Time::Now();
408 response_head.load_timing.request_start =
409 base::TimeTicks::FromInternalValue(10);
410 response_head.load_timing.connect_timing.connect_start =
411 base::TimeTicks::FromInternalValue(13);
413 PerformTest(response_head);
415 EXPECT_LT(base::TimeTicks(), response_info().load_timing.request_start);
416 EXPECT_EQ(base::TimeTicks(),
417 response_info().load_timing.connect_timing.dns_start);
418 EXPECT_LE(response_head.load_timing.request_start,
419 response_info().load_timing.connect_timing.connect_start);
422 TEST_F(TimeConversionTest, PartiallyInitialized) {
423 ResourceResponseHead response_head;
424 response_head.error_code = net::OK;
425 response_head.request_start = base::TimeTicks::FromInternalValue(5);
426 response_head.response_start = base::TimeTicks::FromInternalValue(15);
428 PerformTest(response_head);
430 EXPECT_EQ(base::TimeTicks(), response_info().load_timing.request_start);
431 EXPECT_EQ(base::TimeTicks(),
432 response_info().load_timing.connect_timing.dns_start);
435 TEST_F(TimeConversionTest, NotInitialized) {
436 ResourceResponseHead response_head;
437 response_head.error_code = net::OK;
439 PerformTest(response_head);
441 EXPECT_EQ(base::TimeTicks(), response_info().load_timing.request_start);
442 EXPECT_EQ(base::TimeTicks(),
443 response_info().load_timing.connect_timing.dns_start);
446 } // namespace content