OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <vector> | 5 #include <vector> |
6 | 6 |
7 #include "base/message_loop.h" | 7 #include "base/message_loop.h" |
8 #include "chrome/browser/renderer_security_policy.h" | 8 #include "chrome/browser/renderer_security_policy.h" |
9 #include "chrome/browser/renderer_host/resource_dispatcher_host.h" | 9 #include "chrome/browser/renderer_host/resource_dispatcher_host.h" |
10 #include "chrome/common/render_messages.h" | 10 #include "chrome/common/render_messages.h" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 // We may want to move this to a shared space if it is useful for something else | 44 // We may want to move this to a shared space if it is useful for something else |
45 class ResourceIPCAccumulator { | 45 class ResourceIPCAccumulator { |
46 public: | 46 public: |
47 void AddMessage(const IPC::Message& msg) { | 47 void AddMessage(const IPC::Message& msg) { |
48 messages_.push_back(msg); | 48 messages_.push_back(msg); |
49 } | 49 } |
50 | 50 |
51 // This groups the messages by their request ID. The groups will be in order | 51 // This groups the messages by their request ID. The groups will be in order |
52 // that the first message for each request ID was received, and the messages | 52 // that the first message for each request ID was received, and the messages |
53 // within the groups will be in the order that they appeared. | 53 // within the groups will be in the order that they appeared. |
| 54 // Note that this clears messages_. |
54 typedef std::vector< std::vector<IPC::Message> > ClassifiedMessages; | 55 typedef std::vector< std::vector<IPC::Message> > ClassifiedMessages; |
55 void GetClassifiedMessages(ClassifiedMessages* msgs); | 56 void GetClassifiedMessages(ClassifiedMessages* msgs); |
56 | 57 |
57 std::vector<IPC::Message> messages_; | 58 std::vector<IPC::Message> messages_; |
58 }; | 59 }; |
59 | 60 |
60 // This is very inefficient as a result of repeatedly extracting the ID, use | 61 // This is very inefficient as a result of repeatedly extracting the ID, use |
61 // only for tests! | 62 // only for tests! |
62 void ResourceIPCAccumulator::GetClassifiedMessages(ClassifiedMessages* msgs) { | 63 void ResourceIPCAccumulator::GetClassifiedMessages(ClassifiedMessages* msgs) { |
63 while (!messages_.empty()) { | 64 while (!messages_.empty()) { |
64 std::vector<IPC::Message> cur_requests; | 65 std::vector<IPC::Message> cur_requests; |
65 cur_requests.push_back(messages_[0]); | 66 cur_requests.push_back(messages_[0]); |
66 int cur_id = RequestIDForMessage(messages_[0]); | 67 int cur_id = RequestIDForMessage(messages_[0]); |
67 | 68 |
68 // find all other messages with this ID | 69 // find all other messages with this ID |
69 for (int i = 1; i < static_cast<int>(messages_.size()); i++) { | 70 for (int i = 1; i < static_cast<int>(messages_.size()); i++) { |
70 int id = RequestIDForMessage(messages_[i]); | 71 int id = RequestIDForMessage(messages_[i]); |
71 if (id == cur_id) { | 72 if (id == cur_id) { |
72 cur_requests.push_back(messages_[i]); | 73 cur_requests.push_back(messages_[i]); |
73 messages_.erase(messages_.begin() + i); | 74 messages_.erase(messages_.begin() + i); |
74 i --; | 75 i--; |
75 } | 76 } |
76 } | 77 } |
77 messages_.erase(messages_.begin()); | 78 messages_.erase(messages_.begin()); |
78 msgs->push_back(cur_requests); | 79 msgs->push_back(cur_requests); |
79 } | 80 } |
80 } | 81 } |
81 | 82 |
82 class ResourceDispatcherHostTest : public testing::Test, | 83 class ResourceDispatcherHostTest : public testing::Test, |
83 public ResourceDispatcherHost::Receiver { | 84 public ResourceDispatcherHost::Receiver { |
84 public: | 85 public: |
(...skipping 14 matching lines...) Expand all Loading... |
99 EnsureTestSchemeIsAllowed(); | 100 EnsureTestSchemeIsAllowed(); |
100 } | 101 } |
101 virtual void TearDown() { | 102 virtual void TearDown() { |
102 URLRequest::RegisterProtocolFactory("test", NULL); | 103 URLRequest::RegisterProtocolFactory("test", NULL); |
103 RendererSecurityPolicy::GetInstance()->Remove(0); | 104 RendererSecurityPolicy::GetInstance()->Remove(0); |
104 | 105 |
105 // Flush the message loop to make Purify happy. | 106 // Flush the message loop to make Purify happy. |
106 message_loop_.RunAllPending(); | 107 message_loop_.RunAllPending(); |
107 } | 108 } |
108 | 109 |
109 void MakeTestRequest(int request_id, const GURL& url); | 110 void MakeTestRequest(int render_process_id, |
| 111 int render_view_id, |
| 112 int request_id, |
| 113 const GURL& url); |
110 void MakeCancelRequest(int request_id); | 114 void MakeCancelRequest(int request_id); |
111 | 115 |
112 void EnsureTestSchemeIsAllowed() { | 116 void EnsureTestSchemeIsAllowed() { |
113 static bool have_white_listed_test_scheme = false; | 117 static bool have_white_listed_test_scheme = false; |
114 | 118 |
115 if (!have_white_listed_test_scheme) { | 119 if (!have_white_listed_test_scheme) { |
116 RendererSecurityPolicy::GetInstance()->RegisterWebSafeScheme("test"); | 120 RendererSecurityPolicy::GetInstance()->RegisterWebSafeScheme("test"); |
117 have_white_listed_test_scheme = true; | 121 have_white_listed_test_scheme = true; |
118 } | 122 } |
119 } | 123 } |
120 | 124 |
121 MessageLoopForIO message_loop_; | 125 MessageLoopForIO message_loop_; |
122 ResourceDispatcherHost host_; | 126 ResourceDispatcherHost host_; |
123 ResourceIPCAccumulator accum_; | 127 ResourceIPCAccumulator accum_; |
124 }; | 128 }; |
125 | 129 |
126 // Spin up the message loop to kick off the request. | 130 // Spin up the message loop to kick off the request. |
127 static void KickOffRequest() { | 131 static void KickOffRequest() { |
128 MessageLoop::current()->RunAllPending(); | 132 MessageLoop::current()->RunAllPending(); |
129 } | 133 } |
130 | 134 |
131 void ResourceDispatcherHostTest::MakeTestRequest(int request_id, | 135 void ResourceDispatcherHostTest::MakeTestRequest(int render_process_id, |
| 136 int render_view_id, |
| 137 int request_id, |
132 const GURL& url) { | 138 const GURL& url) { |
133 ViewHostMsg_Resource_Request request = CreateResourceRequest("GET", url); | 139 ViewHostMsg_Resource_Request request = CreateResourceRequest("GET", url); |
134 | 140 |
135 host_.BeginRequest(this, GetCurrentProcess(), 0, MSG_ROUTING_NONE, | 141 host_.BeginRequest(this, GetCurrentProcess(), render_process_id, |
136 request_id, request, NULL, NULL); | 142 render_view_id, request_id, request, NULL, NULL); |
137 KickOffRequest(); | 143 KickOffRequest(); |
138 } | 144 } |
139 | 145 |
140 void ResourceDispatcherHostTest::MakeCancelRequest(int request_id) { | 146 void ResourceDispatcherHostTest::MakeCancelRequest(int request_id) { |
141 host_.CancelRequest(0, request_id, false); | 147 host_.CancelRequest(0, request_id, false); |
142 } | 148 } |
143 | 149 |
144 void CheckSuccessfulRequest(const std::vector<IPC::Message>& messages, | 150 void CheckSuccessfulRequest(const std::vector<IPC::Message>& messages, |
145 const std::string& reference_data) { | 151 const std::string& reference_data) { |
146 // A successful request will have received 4 messages: | 152 // A successful request will have received 4 messages: |
(...skipping 29 matching lines...) Expand all Loading... |
176 | 182 |
177 // followed by a 0-byte read | 183 // followed by a 0-byte read |
178 //ASSERT_EQ(ViewMsg_Resource_DataReceived::ID, messages[2].type()); | 184 //ASSERT_EQ(ViewMsg_Resource_DataReceived::ID, messages[2].type()); |
179 | 185 |
180 // the last message should be all data received | 186 // the last message should be all data received |
181 ASSERT_EQ(ViewMsg_Resource_RequestComplete::ID, messages[2].type()); | 187 ASSERT_EQ(ViewMsg_Resource_RequestComplete::ID, messages[2].type()); |
182 } | 188 } |
183 | 189 |
184 // Tests whether many messages get dispatched properly. | 190 // Tests whether many messages get dispatched properly. |
185 TEST_F(ResourceDispatcherHostTest, TestMany) { | 191 TEST_F(ResourceDispatcherHostTest, TestMany) { |
186 MakeTestRequest(1, URLRequestTestJob::test_url_1()); | 192 MakeTestRequest(0, 0, 1, URLRequestTestJob::test_url_1()); |
187 MakeTestRequest(2, URLRequestTestJob::test_url_2()); | 193 MakeTestRequest(0, 0, 2, URLRequestTestJob::test_url_2()); |
188 MakeTestRequest(3, URLRequestTestJob::test_url_3()); | 194 MakeTestRequest(0, 0, 3, URLRequestTestJob::test_url_3()); |
189 | 195 |
190 // flush all the pending requests | 196 // flush all the pending requests |
191 while (URLRequestTestJob::ProcessOnePendingMessage()); | 197 while (URLRequestTestJob::ProcessOnePendingMessage()); |
192 | 198 |
193 // sorts out all the messages we saw by request | 199 // sorts out all the messages we saw by request |
194 ResourceIPCAccumulator::ClassifiedMessages msgs; | 200 ResourceIPCAccumulator::ClassifiedMessages msgs; |
195 accum_.GetClassifiedMessages(&msgs); | 201 accum_.GetClassifiedMessages(&msgs); |
196 | 202 |
197 // there are three requests, so we should have gotten them classified as such | 203 // there are three requests, so we should have gotten them classified as such |
198 ASSERT_EQ(3, msgs.size()); | 204 ASSERT_EQ(3, msgs.size()); |
199 | 205 |
200 CheckSuccessfulRequest(msgs[0], URLRequestTestJob::test_data_1()); | 206 CheckSuccessfulRequest(msgs[0], URLRequestTestJob::test_data_1()); |
201 CheckSuccessfulRequest(msgs[1], URLRequestTestJob::test_data_2()); | 207 CheckSuccessfulRequest(msgs[1], URLRequestTestJob::test_data_2()); |
202 CheckSuccessfulRequest(msgs[2], URLRequestTestJob::test_data_3()); | 208 CheckSuccessfulRequest(msgs[2], URLRequestTestJob::test_data_3()); |
203 } | 209 } |
204 | 210 |
205 // Tests whether messages get canceled properly. We issue three requests, | 211 // Tests whether messages get canceled properly. We issue three requests, |
206 // cancel one of them, and make sure that each sent the proper notifications. | 212 // cancel one of them, and make sure that each sent the proper notifications. |
207 TEST_F(ResourceDispatcherHostTest, Cancel) { | 213 TEST_F(ResourceDispatcherHostTest, Cancel) { |
208 ResourceDispatcherHost host(NULL); | 214 ResourceDispatcherHost host(NULL); |
209 | 215 |
210 MakeTestRequest(1, URLRequestTestJob::test_url_1()); | 216 MakeTestRequest(0, 0, 1, URLRequestTestJob::test_url_1()); |
211 MakeTestRequest(2, URLRequestTestJob::test_url_2()); | 217 MakeTestRequest(0, 0, 2, URLRequestTestJob::test_url_2()); |
212 MakeTestRequest(3, URLRequestTestJob::test_url_3()); | 218 MakeTestRequest(0, 0, 3, URLRequestTestJob::test_url_3()); |
213 MakeCancelRequest(2); | 219 MakeCancelRequest(2); |
214 | 220 |
215 // flush all the pending requests | 221 // flush all the pending requests |
216 while (URLRequestTestJob::ProcessOnePendingMessage()); | 222 while (URLRequestTestJob::ProcessOnePendingMessage()); |
217 | 223 |
218 ResourceIPCAccumulator::ClassifiedMessages msgs; | 224 ResourceIPCAccumulator::ClassifiedMessages msgs; |
219 accum_.GetClassifiedMessages(&msgs); | 225 accum_.GetClassifiedMessages(&msgs); |
220 | 226 |
221 // there are three requests, so we should have gotten them classified as such | 227 // there are three requests, so we should have gotten them classified as such |
222 ASSERT_EQ(3, msgs.size()); | 228 ASSERT_EQ(3, msgs.size()); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 | 276 |
271 // request 1 goes to the test delegate | 277 // request 1 goes to the test delegate |
272 ViewHostMsg_Resource_Request request = | 278 ViewHostMsg_Resource_Request request = |
273 CreateResourceRequest("GET", URLRequestTestJob::test_url_1()); | 279 CreateResourceRequest("GET", URLRequestTestJob::test_url_1()); |
274 | 280 |
275 host_.BeginRequest(&test_receiver, GetCurrentProcess(), 0, MSG_ROUTING_NONE, | 281 host_.BeginRequest(&test_receiver, GetCurrentProcess(), 0, MSG_ROUTING_NONE, |
276 1, request, NULL, NULL); | 282 1, request, NULL, NULL); |
277 KickOffRequest(); | 283 KickOffRequest(); |
278 | 284 |
279 // request 2 goes to us | 285 // request 2 goes to us |
280 MakeTestRequest(2, URLRequestTestJob::test_url_2()); | 286 MakeTestRequest(0, 0, 2, URLRequestTestJob::test_url_2()); |
281 | 287 |
282 // request 3 goes to the test delegate | 288 // request 3 goes to the test delegate |
283 request.url = URLRequestTestJob::test_url_3(); | 289 request.url = URLRequestTestJob::test_url_3(); |
284 host_.BeginRequest(&test_receiver, GetCurrentProcess(), 0, MSG_ROUTING_NONE, | 290 host_.BeginRequest(&test_receiver, GetCurrentProcess(), 0, MSG_ROUTING_NONE, |
285 3, request, NULL, NULL); | 291 3, request, NULL, NULL); |
286 KickOffRequest(); | 292 KickOffRequest(); |
287 | 293 |
288 // TODO: mbelshe | 294 // TODO: mbelshe |
289 // Now that the async IO path is in place, the IO always completes on the | 295 // Now that the async IO path is in place, the IO always completes on the |
290 // initial call; so the requests have already completed. This basically | 296 // initial call; so the requests have already completed. This basically |
(...skipping 16 matching lines...) Expand all Loading... |
307 // the test delegate should not have gotten any messages after being canceled | 313 // the test delegate should not have gotten any messages after being canceled |
308 ASSERT_EQ(0, test_receiver.received_after_canceled_); | 314 ASSERT_EQ(0, test_receiver.received_after_canceled_); |
309 | 315 |
310 // we should have gotten exactly one result | 316 // we should have gotten exactly one result |
311 ResourceIPCAccumulator::ClassifiedMessages msgs; | 317 ResourceIPCAccumulator::ClassifiedMessages msgs; |
312 accum_.GetClassifiedMessages(&msgs); | 318 accum_.GetClassifiedMessages(&msgs); |
313 ASSERT_EQ(1, msgs.size()); | 319 ASSERT_EQ(1, msgs.size()); |
314 CheckSuccessfulRequest(msgs[0], URLRequestTestJob::test_data_2()); | 320 CheckSuccessfulRequest(msgs[0], URLRequestTestJob::test_data_2()); |
315 } | 321 } |
316 | 322 |
| 323 // Tests blocking and resuming requests. |
| 324 TEST_F(ResourceDispatcherHostTest, TestBlockingResumingRequests) { |
| 325 host_.BlockRequestsForRenderView(0, 1); |
| 326 host_.BlockRequestsForRenderView(0, 2); |
| 327 host_.BlockRequestsForRenderView(0, 3); |
| 328 |
| 329 MakeTestRequest(0, 0, 1, URLRequestTestJob::test_url_1()); |
| 330 MakeTestRequest(0, 1, 2, URLRequestTestJob::test_url_2()); |
| 331 MakeTestRequest(0, 0, 3, URLRequestTestJob::test_url_3()); |
| 332 MakeTestRequest(0, 1, 4, URLRequestTestJob::test_url_1()); |
| 333 MakeTestRequest(0, 2, 5, URLRequestTestJob::test_url_2()); |
| 334 MakeTestRequest(0, 3, 6, URLRequestTestJob::test_url_3()); |
| 335 |
| 336 // Flush all the pending requests |
| 337 while (URLRequestTestJob::ProcessOnePendingMessage()); |
| 338 |
| 339 // Sort out all the messages we saw by request |
| 340 ResourceIPCAccumulator::ClassifiedMessages msgs; |
| 341 accum_.GetClassifiedMessages(&msgs); |
| 342 |
| 343 // All requests but the 2 for the RVH 0 should have been blocked. |
| 344 ASSERT_EQ(2, msgs.size()); |
| 345 |
| 346 CheckSuccessfulRequest(msgs[0], URLRequestTestJob::test_data_1()); |
| 347 CheckSuccessfulRequest(msgs[1], URLRequestTestJob::test_data_3()); |
| 348 |
| 349 // Resume requests for RVH 1 and flush pending requests. |
| 350 host_.ResumeBlockedRequestsForRenderView(0, 1); |
| 351 KickOffRequest(); |
| 352 while (URLRequestTestJob::ProcessOnePendingMessage()); |
| 353 |
| 354 msgs.clear(); |
| 355 accum_.GetClassifiedMessages(&msgs); |
| 356 ASSERT_EQ(2, msgs.size()); |
| 357 CheckSuccessfulRequest(msgs[0], URLRequestTestJob::test_data_2()); |
| 358 CheckSuccessfulRequest(msgs[1], URLRequestTestJob::test_data_1()); |
| 359 |
| 360 // Test that new requests are not blocked for RVH 1. |
| 361 MakeTestRequest(0, 1, 7, URLRequestTestJob::test_url_1()); |
| 362 while (URLRequestTestJob::ProcessOnePendingMessage()); |
| 363 msgs.clear(); |
| 364 accum_.GetClassifiedMessages(&msgs); |
| 365 ASSERT_EQ(1, msgs.size()); |
| 366 CheckSuccessfulRequest(msgs[0], URLRequestTestJob::test_data_1()); |
| 367 |
| 368 // Now resumes requests for all RVH (2 and 3). |
| 369 host_.ResumeBlockedRequestsForRenderView(0, 2); |
| 370 host_.ResumeBlockedRequestsForRenderView(0, 3); |
| 371 KickOffRequest(); |
| 372 while (URLRequestTestJob::ProcessOnePendingMessage()); |
| 373 |
| 374 msgs.clear(); |
| 375 accum_.GetClassifiedMessages(&msgs); |
| 376 ASSERT_EQ(2, msgs.size()); |
| 377 CheckSuccessfulRequest(msgs[0], URLRequestTestJob::test_data_2()); |
| 378 CheckSuccessfulRequest(msgs[1], URLRequestTestJob::test_data_3()); |
| 379 } |
| 380 |
| 381 // Tests blocking and canceling requests. |
| 382 TEST_F(ResourceDispatcherHostTest, TestBlockingCancelingRequests) { |
| 383 host_.BlockRequestsForRenderView(0, 1); |
| 384 |
| 385 MakeTestRequest(0, 0, 1, URLRequestTestJob::test_url_1()); |
| 386 MakeTestRequest(0, 1, 2, URLRequestTestJob::test_url_2()); |
| 387 MakeTestRequest(0, 0, 3, URLRequestTestJob::test_url_3()); |
| 388 MakeTestRequest(0, 1, 4, URLRequestTestJob::test_url_1()); |
| 389 |
| 390 // Flush all the pending requests. |
| 391 while (URLRequestTestJob::ProcessOnePendingMessage()); |
| 392 |
| 393 // Sort out all the messages we saw by request. |
| 394 ResourceIPCAccumulator::ClassifiedMessages msgs; |
| 395 accum_.GetClassifiedMessages(&msgs); |
| 396 |
| 397 // The 2 requests for the RVH 0 should have been processed. |
| 398 ASSERT_EQ(2, msgs.size()); |
| 399 |
| 400 CheckSuccessfulRequest(msgs[0], URLRequestTestJob::test_data_1()); |
| 401 CheckSuccessfulRequest(msgs[1], URLRequestTestJob::test_data_3()); |
| 402 |
| 403 // Cancel requests for RVH 1. |
| 404 host_.CancelBlockedRequestsForRenderView(0, 1); |
| 405 KickOffRequest(); |
| 406 while (URLRequestTestJob::ProcessOnePendingMessage()); |
| 407 msgs.clear(); |
| 408 accum_.GetClassifiedMessages(&msgs); |
| 409 ASSERT_EQ(0, msgs.size()); |
| 410 } |
| 411 |
| 412 // Tests that blocked requests are canceled if their associated process dies. |
| 413 TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsProcessDies) { |
| 414 host_.BlockRequestsForRenderView(1, 0); |
| 415 |
| 416 MakeTestRequest(0, 0, 1, URLRequestTestJob::test_url_1()); |
| 417 MakeTestRequest(1, 0, 2, URLRequestTestJob::test_url_2()); |
| 418 MakeTestRequest(0, 0, 3, URLRequestTestJob::test_url_3()); |
| 419 MakeTestRequest(1, 0, 4, URLRequestTestJob::test_url_1()); |
| 420 |
| 421 // Simulate process death. |
| 422 host_.CancelRequestsForProcess(1); |
| 423 |
| 424 // Flush all the pending requests. |
| 425 while (URLRequestTestJob::ProcessOnePendingMessage()); |
| 426 |
| 427 // Sort out all the messages we saw by request. |
| 428 ResourceIPCAccumulator::ClassifiedMessages msgs; |
| 429 accum_.GetClassifiedMessages(&msgs); |
| 430 |
| 431 // The 2 requests for the RVH 0 should have been processed. |
| 432 ASSERT_EQ(2, msgs.size()); |
| 433 |
| 434 CheckSuccessfulRequest(msgs[0], URLRequestTestJob::test_data_1()); |
| 435 CheckSuccessfulRequest(msgs[1], URLRequestTestJob::test_data_3()); |
| 436 |
| 437 EXPECT_TRUE(host_.blocked_requests_map_.empty()); |
| 438 } |
| 439 |
| 440 // Tests that blocked requests don't leak when the ResourceDispatcherHost goes |
| 441 // away. Note that we rely on Purify for finding the leaks if any. |
| 442 // If this test turns the Purify bot red, check the ResourceDispatcherHost |
| 443 // destructor to make sure the blocked requests are deleted. |
| 444 TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsDontLeak) { |
| 445 host_.BlockRequestsForRenderView(0, 1); |
| 446 host_.BlockRequestsForRenderView(0, 2); |
| 447 host_.BlockRequestsForRenderView(1, 1); |
| 448 |
| 449 MakeTestRequest(0, 0, 1, URLRequestTestJob::test_url_1()); |
| 450 MakeTestRequest(0, 1, 2, URLRequestTestJob::test_url_2()); |
| 451 MakeTestRequest(0, 0, 3, URLRequestTestJob::test_url_3()); |
| 452 MakeTestRequest(1, 1, 4, URLRequestTestJob::test_url_1()); |
| 453 MakeTestRequest(0, 2, 5, URLRequestTestJob::test_url_2()); |
| 454 MakeTestRequest(0, 2, 6, URLRequestTestJob::test_url_3()); |
| 455 |
| 456 // Flush all the pending requests. |
| 457 while (URLRequestTestJob::ProcessOnePendingMessage()); |
| 458 } |
OLD | NEW |