OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include <string> | |
6 #include <vector> | |
7 | |
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/common/request_extra_data.h" | |
13 #include "content/common/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" | |
21 | |
22 using webkit_glue::ResourceLoaderBridge; | |
23 using webkit_glue::ResourceResponseInfo; | |
24 | |
25 namespace content { | |
26 | |
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; | |
35 | |
36 static const char kShmemSegmentName[] = "DeferredResourceLoaderTest"; | |
37 | |
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 { | |
41 public: | |
42 TestRequestCallback() : complete_(false) { | |
43 } | |
44 | |
45 virtual void OnUploadProgress(uint64 position, uint64 size) OVERRIDE { | |
46 } | |
47 | |
48 virtual bool OnReceivedRedirect( | |
49 const GURL& new_url, | |
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; | |
54 return true; | |
55 } | |
56 | |
57 virtual void OnReceivedResponse(const ResourceResponseInfo& info) OVERRIDE { | |
58 } | |
59 | |
60 virtual void OnDownloadedData(int len) OVERRIDE { | |
61 } | |
62 | |
63 virtual void OnReceivedData(const char* data, | |
64 int data_length, | |
65 int encoded_data_length) OVERRIDE { | |
66 EXPECT_FALSE(complete_); | |
67 data_.append(data, data_length); | |
68 total_encoded_data_length_ += encoded_data_length; | |
69 } | |
70 | |
71 virtual void OnCompletedRequest( | |
72 int error_code, | |
73 bool was_ignored_by_handler, | |
74 const std::string& security_info, | |
75 const base::TimeTicks& completion_time) OVERRIDE { | |
76 EXPECT_FALSE(complete_); | |
77 complete_ = true; | |
78 } | |
79 | |
80 bool complete() const { | |
81 return complete_; | |
82 } | |
83 const std::string& data() const { | |
84 return data_; | |
85 } | |
86 int total_encoded_data_length() const { | |
87 return total_encoded_data_length_; | |
88 } | |
89 | |
90 private: | |
91 bool complete_; | |
92 std::string data_; | |
93 int total_encoded_data_length_; | |
94 }; | |
95 | |
96 | |
97 // Sets up the message sender override for the unit test | |
98 class ResourceDispatcherTest : public testing::Test, public IPC::Sender { | |
99 public: | |
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)); | |
104 delete msg; | |
105 return true; | |
106 } | |
107 | |
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()) { | |
112 int request_id; | |
113 ResourceHostMsg_Request request; | |
114 ASSERT_TRUE(ResourceHostMsg_RequestResource::Read( | |
115 &message_queue_[0], &request_id, &request)); | |
116 | |
117 // check values | |
118 EXPECT_EQ(test_page_url, request.url.spec()); | |
119 | |
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); | |
128 | |
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); | |
142 | |
143 message_queue_.erase(message_queue_.begin()); | |
144 | |
145 // read the ack message. | |
146 Tuple1<int> request_ack; | |
147 ASSERT_TRUE(ResourceHostMsg_DataReceived_ACK::Read( | |
148 &message_queue_[0], &request_ack)); | |
149 | |
150 ASSERT_EQ(request_ack.a, request_id); | |
151 | |
152 message_queue_.erase(message_queue_.begin()); | |
153 } | |
154 } | |
155 | |
156 protected: | |
157 // testing::Test | |
158 virtual void SetUp() OVERRIDE { | |
159 dispatcher_.reset(new ResourceDispatcher(this)); | |
160 } | |
161 virtual void TearDown() OVERRIDE { | |
162 dispatcher_.reset(); | |
163 } | |
164 | |
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, | |
178 WebKit::WebString(), | |
179 true, 0, false, -1, true, | |
180 PAGE_TRANSITION_LINK, -1, -1); | |
181 request_info.extra_data = &extra_data; | |
182 | |
183 return dispatcher_->CreateBridge(request_info); | |
184 } | |
185 | |
186 std::vector<IPC::Message> message_queue_; | |
187 static scoped_ptr<ResourceDispatcher> dispatcher_; | |
188 }; | |
189 | |
190 /*static*/ | |
191 scoped_ptr<ResourceDispatcher> ResourceDispatcherTest::dispatcher_; | |
192 | |
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(); | |
197 | |
198 bridge->Start(&callback); | |
199 | |
200 ProcessMessages(); | |
201 | |
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()); | |
207 | |
208 delete bridge; | |
209 } | |
210 | |
211 // Tests that the request IDs are straight when there are multiple requests. | |
212 TEST_F(ResourceDispatcherTest, MultipleRequests) { | |
213 // FIXME | |
214 } | |
215 | |
216 // Tests that the cancel method prevents other messages from being received | |
217 TEST_F(ResourceDispatcherTest, Cancel) { | |
218 // FIXME | |
219 } | |
220 | |
221 TEST_F(ResourceDispatcherTest, Cookies) { | |
222 // FIXME | |
223 } | |
224 | |
225 TEST_F(ResourceDispatcherTest, SerializedPostData) { | |
226 // FIXME | |
227 } | |
228 | |
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 { | |
236 public: | |
237 DeferredResourceLoadingTest() | |
238 : defer_loading_(false) { | |
239 } | |
240 | |
241 virtual bool Send(IPC::Message* msg) OVERRIDE { | |
242 delete msg; | |
243 return true; | |
244 } | |
245 | |
246 void InitMessages() { | |
247 set_defer_loading(true); | |
248 | |
249 ResourceResponseHead response_head; | |
250 response_head.error_code = net::OK; | |
251 | |
252 dispatcher_->OnMessageReceived( | |
253 ResourceMsg_ReceivedResponse(0, 0, response_head)); | |
254 | |
255 // Duplicate the shared memory handle so both the test and the callee can | |
256 // close their copy. | |
257 base::SharedMemoryHandle duplicated_handle; | |
258 EXPECT_TRUE(shared_handle_.ShareToProcess(base::GetCurrentProcessHandle(), | |
259 &duplicated_handle)); | |
260 | |
261 dispatcher_->OnMessageReceived( | |
262 ResourceMsg_SetDataBuffer(0, 0, duplicated_handle, 100, 0)); | |
263 dispatcher_->OnMessageReceived( | |
264 ResourceMsg_DataReceived(0, 0, 0, 100, 100)); | |
265 | |
266 set_defer_loading(false); | |
267 } | |
268 | |
269 // ResourceLoaderBridge::Peer methods. | |
270 virtual void OnUploadProgress(uint64 position, uint64 size) OVERRIDE { | |
271 } | |
272 | |
273 virtual bool OnReceivedRedirect( | |
274 const GURL& new_url, | |
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; | |
279 return true; | |
280 } | |
281 | |
282 virtual void OnReceivedResponse(const ResourceResponseInfo& info) OVERRIDE { | |
283 EXPECT_EQ(defer_loading_, false); | |
284 set_defer_loading(true); | |
285 } | |
286 | |
287 virtual void OnDownloadedData(int len) OVERRIDE { | |
288 } | |
289 | |
290 virtual void OnReceivedData(const char* data, | |
291 int data_length, | |
292 int encoded_data_length) OVERRIDE { | |
293 EXPECT_EQ(defer_loading_, false); | |
294 set_defer_loading(false); | |
295 } | |
296 | |
297 virtual void OnCompletedRequest( | |
298 int error_code, | |
299 bool was_ignored_by_handler, | |
300 const std::string& security_info, | |
301 const base::TimeTicks& completion_time) OVERRIDE { | |
302 } | |
303 | |
304 protected: | |
305 virtual void SetUp() OVERRIDE { | |
306 ResourceDispatcherTest::SetUp(); | |
307 shared_handle_.Delete(kShmemSegmentName); | |
308 EXPECT_TRUE(shared_handle_.CreateNamed(kShmemSegmentName, false, 100)); | |
309 } | |
310 | |
311 virtual void TearDown() OVERRIDE { | |
312 shared_handle_.Close(); | |
313 EXPECT_TRUE(shared_handle_.Delete(kShmemSegmentName)); | |
314 ResourceDispatcherTest::TearDown(); | |
315 } | |
316 | |
317 private: | |
318 void set_defer_loading(bool defer) { | |
319 defer_loading_ = defer; | |
320 dispatcher_->SetDefersLoading(0, defer); | |
321 } | |
322 | |
323 bool defer_loading() const { | |
324 return defer_loading_; | |
325 } | |
326 | |
327 bool defer_loading_; | |
328 base::SharedMemory shared_handle_; | |
329 }; | |
330 | |
331 TEST_F(DeferredResourceLoadingTest, DeferredLoadTest) { | |
332 base::MessageLoop message_loop(base::MessageLoop::TYPE_IO); | |
333 | |
334 ResourceLoaderBridge* bridge = CreateBridge(); | |
335 | |
336 bridge->Start(this); | |
337 InitMessages(); | |
338 | |
339 // Dispatch deferred messages. | |
340 message_loop.RunUntilIdle(); | |
341 delete bridge; | |
342 } | |
343 | |
344 class TimeConversionTest : public ResourceDispatcherTest, | |
345 public ResourceLoaderBridge::Peer { | |
346 public: | |
347 virtual bool Send(IPC::Message* msg) OVERRIDE { | |
348 delete msg; | |
349 return true; | |
350 } | |
351 | |
352 void PerformTest(const ResourceResponseHead& response_head) { | |
353 scoped_ptr<ResourceLoaderBridge> bridge(CreateBridge()); | |
354 bridge->Start(this); | |
355 | |
356 dispatcher_->OnMessageReceived( | |
357 ResourceMsg_ReceivedResponse(0, 0, response_head)); | |
358 } | |
359 | |
360 // ResourceLoaderBridge::Peer methods. | |
361 virtual void OnUploadProgress(uint64 position, uint64 size) OVERRIDE { | |
362 } | |
363 | |
364 virtual bool OnReceivedRedirect( | |
365 const GURL& new_url, | |
366 const ResourceResponseInfo& info, | |
367 bool* has_new_first_party_for_cookies, | |
368 GURL* new_first_party_for_cookies) OVERRIDE { | |
369 return true; | |
370 } | |
371 | |
372 virtual void OnReceivedResponse(const ResourceResponseInfo& info) OVERRIDE { | |
373 response_info_ = info; | |
374 } | |
375 | |
376 virtual void OnDownloadedData(int len) OVERRIDE { | |
377 } | |
378 | |
379 virtual void OnReceivedData(const char* data, | |
380 int data_length, | |
381 int encoded_data_length) OVERRIDE { | |
382 } | |
383 | |
384 virtual void OnCompletedRequest( | |
385 int error_code, | |
386 bool was_ignored_by_handler, | |
387 const std::string& security_info, | |
388 const base::TimeTicks& completion_time) OVERRIDE { | |
389 } | |
390 | |
391 const ResourceResponseInfo& response_info() const { return response_info_; } | |
392 | |
393 private: | |
394 ResourceResponseInfo response_info_; | |
395 }; | |
396 | |
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); | |
408 | |
409 PerformTest(response_head); | |
410 | |
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); | |
416 } | |
417 | |
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); | |
423 | |
424 PerformTest(response_head); | |
425 | |
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); | |
429 } | |
430 | |
431 TEST_F(TimeConversionTest, NotInitialized) { | |
432 ResourceResponseHead response_head; | |
433 response_head.error_code = net::OK; | |
434 | |
435 PerformTest(response_head); | |
436 | |
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); | |
440 } | |
441 | |
442 } // namespace content | |
OLD | NEW |