| 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 |