1 // Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4
5 #include <map>
6
7 #include "include/base/cef_callback.h"
8 #include "include/cef_request.h"
9 #include "include/wrapper/cef_closure_task.h"
10 #include "tests/ceftests/test_handler.h"
11 #include "tests/ceftests/test_util.h"
12 #include "tests/gtest/include/gtest/gtest.h"
13 #include "tests/shared/renderer/client_app_renderer.h"
14
15 using client::ClientAppRenderer;
16
17 // Verify Set/Get methods for CefRequest, CefPostData and CefPostDataElement.
TEST(RequestTest,SetGet)18 TEST(RequestTest, SetGet) {
19 // CefRequest CreateRequest
20 CefRefPtr<CefRequest> request(CefRequest::Create());
21 EXPECT_TRUE(request.get() != nullptr);
22 EXPECT_EQ(0U, request->GetIdentifier());
23
24 CefString url = "http://tests.com/run.html";
25 CefString method = "POST";
26 CefRequest::HeaderMap setHeaders, getHeaders;
27 setHeaders.insert(std::make_pair("HeaderA", "ValueA"));
28 setHeaders.insert(std::make_pair("HeaderB", "ValueB"));
29
30 // CefPostData CreatePostData
31 CefRefPtr<CefPostData> postData(CefPostData::Create());
32 EXPECT_TRUE(postData.get() != nullptr);
33
34 // CefPostDataElement CreatePostDataElement
35 CefRefPtr<CefPostDataElement> element1(CefPostDataElement::Create());
36 EXPECT_TRUE(element1.get() != nullptr);
37 CefRefPtr<CefPostDataElement> element2(CefPostDataElement::Create());
38 EXPECT_TRUE(element2.get() != nullptr);
39
40 // CefPostDataElement SetToFile
41 CefString file = "c:\\path\\to\\file.ext";
42 element1->SetToFile(file);
43 EXPECT_EQ(PDE_TYPE_FILE, element1->GetType());
44 EXPECT_EQ(file, element1->GetFile());
45
46 // CefPostDataElement SetToBytes
47 char bytes[] = "Test Bytes";
48 element2->SetToBytes(sizeof(bytes), bytes);
49 EXPECT_EQ(PDE_TYPE_BYTES, element2->GetType());
50 EXPECT_EQ(sizeof(bytes), element2->GetBytesCount());
51 char bytesOut[sizeof(bytes)];
52 element2->GetBytes(sizeof(bytes), bytesOut);
53 EXPECT_TRUE(!memcmp(bytes, bytesOut, sizeof(bytes)));
54
55 // CefPostData AddElement
56 postData->AddElement(element1);
57 postData->AddElement(element2);
58 EXPECT_EQ((size_t)2, postData->GetElementCount());
59
60 // CefPostData RemoveElement
61 postData->RemoveElement(element1);
62 EXPECT_EQ((size_t)1, postData->GetElementCount());
63
64 // CefPostData RemoveElements
65 postData->RemoveElements();
66 EXPECT_EQ((size_t)0, postData->GetElementCount());
67
68 postData->AddElement(element1);
69 postData->AddElement(element2);
70 EXPECT_EQ((size_t)2, postData->GetElementCount());
71 CefPostData::ElementVector elements;
72 postData->GetElements(elements);
73 CefPostData::ElementVector::const_iterator it = elements.begin();
74 for (size_t i = 0; it != elements.end(); ++it, ++i) {
75 if (i == 0)
76 TestPostDataElementEqual(element1, (*it).get());
77 else if (i == 1)
78 TestPostDataElementEqual(element2, (*it).get());
79 }
80
81 // CefRequest SetURL
82 request->SetURL(url);
83 EXPECT_EQ(url, request->GetURL());
84
85 // CefRequest SetMethod
86 request->SetMethod(method);
87 EXPECT_EQ(method, request->GetMethod());
88
89 // CefRequest SetReferrer
90 CefString referrer = "http://tests.com/referrer.html";
91 CefRequest::ReferrerPolicy policy = REFERRER_POLICY_ORIGIN;
92 request->SetReferrer(referrer, policy);
93 EXPECT_STREQ("http://tests.com/",
94 request->GetReferrerURL().ToString().c_str());
95 EXPECT_EQ(policy, request->GetReferrerPolicy());
96
97 // CefRequest SetHeaderMap
98 request->SetHeaderMap(setHeaders);
99 request->GetHeaderMap(getHeaders);
100 TestMapEqual(setHeaders, getHeaders, false);
101 getHeaders.clear();
102
103 // CefRequest SetPostData
104 request->SetPostData(postData);
105 TestPostDataEqual(postData, request->GetPostData());
106
107 EXPECT_EQ(0U, request->GetIdentifier());
108
109 request = CefRequest::Create();
110 EXPECT_TRUE(request.get() != nullptr);
111 EXPECT_EQ(0U, request->GetIdentifier());
112
113 // CefRequest Set
114 request->Set(url, method, postData, setHeaders);
115 EXPECT_EQ(0U, request->GetIdentifier());
116 EXPECT_EQ(url, request->GetURL());
117 EXPECT_EQ(method, request->GetMethod());
118 request->GetHeaderMap(getHeaders);
119 TestMapEqual(setHeaders, getHeaders, false);
120 getHeaders.clear();
121 TestPostDataEqual(postData, request->GetPostData());
122 }
123
TEST(RequestTest,SetGetHeaderByName)124 TEST(RequestTest, SetGetHeaderByName) {
125 CefRefPtr<CefRequest> request(CefRequest::Create());
126 EXPECT_TRUE(request.get() != nullptr);
127
128 CefRequest::HeaderMap headers, expectedHeaders;
129
130 request->SetHeaderByName("HeaderA", "ValueA", false);
131 request->SetHeaderByName("HeaderB", "ValueB", false);
132
133 expectedHeaders.insert(std::make_pair("HeaderA", "ValueA"));
134 expectedHeaders.insert(std::make_pair("HeaderB", "ValueB"));
135
136 // Case insensitive retrieval.
137 EXPECT_STREQ("ValueA",
138 request->GetHeaderByName("headera").ToString().c_str());
139 EXPECT_STREQ("ValueB",
140 request->GetHeaderByName("headerb").ToString().c_str());
141 EXPECT_STREQ("", request->GetHeaderByName("noexist").ToString().c_str());
142
143 request->GetHeaderMap(headers);
144 TestMapEqual(expectedHeaders, headers, false);
145
146 // Replace an existing value.
147 request->SetHeaderByName("HeaderA", "ValueANew", true);
148
149 expectedHeaders.clear();
150 expectedHeaders.insert(std::make_pair("HeaderA", "ValueANew"));
151 expectedHeaders.insert(std::make_pair("HeaderB", "ValueB"));
152
153 // Case insensitive retrieval.
154 EXPECT_STREQ("ValueANew",
155 request->GetHeaderByName("headerA").ToString().c_str());
156
157 request->GetHeaderMap(headers);
158 TestMapEqual(expectedHeaders, headers, false);
159
160 // Header with multiple values.
161 expectedHeaders.clear();
162 expectedHeaders.insert(std::make_pair("HeaderA", "ValueA1"));
163 expectedHeaders.insert(std::make_pair("HeaderA", "ValueA2"));
164 expectedHeaders.insert(std::make_pair("HeaderB", "ValueB"));
165 request->SetHeaderMap(expectedHeaders);
166
167 // When there are multiple values only the first is returned.
168 EXPECT_STREQ("ValueA1",
169 request->GetHeaderByName("headera").ToString().c_str());
170
171 // Don't overwrite the value.
172 request->SetHeaderByName("HeaderA", "ValueANew", false);
173
174 request->GetHeaderMap(headers);
175 TestMapEqual(expectedHeaders, headers, false);
176
177 // Overwrite the value (remove the duplicates).
178 request->SetHeaderByName("HeaderA", "ValueANew", true);
179
180 expectedHeaders.clear();
181 expectedHeaders.insert(std::make_pair("HeaderA", "ValueANew"));
182 expectedHeaders.insert(std::make_pair("HeaderB", "ValueB"));
183
184 request->GetHeaderMap(headers);
185 TestMapEqual(expectedHeaders, headers, false);
186 }
187
188 namespace {
189
190 const char kTestUrl[] = "http://tests.com/run.html";
191
CreateRequest(CefRefPtr<CefRequest> & request)192 void CreateRequest(CefRefPtr<CefRequest>& request) {
193 request = CefRequest::Create();
194 EXPECT_TRUE(request.get() != nullptr);
195
196 request->SetURL(kTestUrl);
197 request->SetMethod("POST");
198
199 request->SetReferrer("http://tests.com/main.html", REFERRER_POLICY_DEFAULT);
200
201 CefRequest::HeaderMap headers;
202 headers.insert(std::make_pair("HeaderA", "ValueA"));
203 headers.insert(std::make_pair("HeaderB", "ValueB"));
204 request->SetHeaderMap(headers);
205
206 CefRefPtr<CefPostData> postData(CefPostData::Create());
207 EXPECT_TRUE(postData.get() != nullptr);
208
209 CefRefPtr<CefPostDataElement> element1(CefPostDataElement::Create());
210 EXPECT_TRUE(element1.get() != nullptr);
211 char bytes[] = "Test Bytes";
212 element1->SetToBytes(sizeof(bytes), bytes);
213 postData->AddElement(element1);
214
215 request->SetPostData(postData);
216 }
217
218 class RequestSendRecvTestHandler : public TestHandler {
219 public:
RequestSendRecvTestHandler()220 RequestSendRecvTestHandler() : response_length_(0), request_id_(0U) {}
221
RunTest()222 void RunTest() override {
223 // Create the test request.
224 CreateRequest(request_);
225
226 const std::string& resource = "<html><body>SendRecv Test</body></html>";
227 response_length_ = static_cast<int64>(resource.size());
228 AddResource(kTestUrl, resource, "text/html");
229
230 // Create the browser.
231 CreateBrowser("about:blank");
232
233 // Time out the test after a reasonable period of time.
234 SetTestTimeout();
235 }
236
OnAfterCreated(CefRefPtr<CefBrowser> browser)237 void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
238 TestHandler::OnAfterCreated(browser);
239
240 // Load the test request.
241 browser->GetMainFrame()->LoadRequest(request_);
242 }
243
OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request,CefRefPtr<CefCallback> callback)244 cef_return_value_t OnBeforeResourceLoad(
245 CefRefPtr<CefBrowser> browser,
246 CefRefPtr<CefFrame> frame,
247 CefRefPtr<CefRequest> request,
248 CefRefPtr<CefCallback> callback) override {
249 EXPECT_IO_THREAD();
250
251 request_id_ = request->GetIdentifier();
252 DCHECK_GT(request_id_, 0U);
253
254 TestRequest(request);
255 EXPECT_FALSE(request->IsReadOnly());
256
257 got_before_resource_load_.yes();
258
259 return RV_CONTINUE;
260 }
261
GetResourceHandler(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request)262 CefRefPtr<CefResourceHandler> GetResourceHandler(
263 CefRefPtr<CefBrowser> browser,
264 CefRefPtr<CefFrame> frame,
265 CefRefPtr<CefRequest> request) override {
266 EXPECT_IO_THREAD();
267
268 TestRequest(request);
269 EXPECT_TRUE(request->IsReadOnly());
270
271 got_resource_handler_.yes();
272
273 return TestHandler::GetResourceHandler(browser, frame, request);
274 }
275
OnResourceResponse(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request,CefRefPtr<CefResponse> response)276 bool OnResourceResponse(CefRefPtr<CefBrowser> browser,
277 CefRefPtr<CefFrame> frame,
278 CefRefPtr<CefRequest> request,
279 CefRefPtr<CefResponse> response) override {
280 EXPECT_IO_THREAD();
281
282 TestRequest(request);
283 EXPECT_FALSE(request->IsReadOnly());
284 TestResponse(response);
285 EXPECT_TRUE(response->IsReadOnly());
286
287 got_resource_response_.yes();
288
289 return false;
290 }
291
GetResourceResponseFilter(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request,CefRefPtr<CefResponse> response)292 CefRefPtr<CefResponseFilter> GetResourceResponseFilter(
293 CefRefPtr<CefBrowser> browser,
294 CefRefPtr<CefFrame> frame,
295 CefRefPtr<CefRequest> request,
296 CefRefPtr<CefResponse> response) override {
297 EXPECT_IO_THREAD();
298
299 TestRequest(request);
300 EXPECT_TRUE(request->IsReadOnly());
301 TestResponse(response);
302 EXPECT_TRUE(response->IsReadOnly());
303
304 got_resource_response_filter_.yes();
305 return nullptr;
306 }
307
OnResourceLoadComplete(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request,CefRefPtr<CefResponse> response,URLRequestStatus status,int64 received_content_length)308 void OnResourceLoadComplete(CefRefPtr<CefBrowser> browser,
309 CefRefPtr<CefFrame> frame,
310 CefRefPtr<CefRequest> request,
311 CefRefPtr<CefResponse> response,
312 URLRequestStatus status,
313 int64 received_content_length) override {
314 EXPECT_IO_THREAD();
315
316 if (IsChromeRuntimeEnabled() && request->GetResourceType() == RT_FAVICON) {
317 // Ignore favicon requests.
318 return;
319 }
320
321 TestRequest(request);
322 EXPECT_TRUE(request->IsReadOnly());
323 TestResponse(response);
324 EXPECT_TRUE(response->IsReadOnly());
325 EXPECT_EQ(UR_SUCCESS, status);
326 EXPECT_EQ(response_length_, received_content_length);
327
328 got_resource_load_complete_.yes();
329
330 DestroyTest();
331 }
332
333 private:
TestRequest(CefRefPtr<CefRequest> request)334 void TestRequest(CefRefPtr<CefRequest> request) {
335 TestRequestEqual(request_, request, true);
336 EXPECT_EQ(request_id_, request->GetIdentifier());
337 EXPECT_EQ(RT_MAIN_FRAME, request->GetResourceType());
338 EXPECT_EQ(TT_FORM_SUBMIT, request->GetTransitionType());
339 }
340
TestResponse(CefRefPtr<CefResponse> response)341 void TestResponse(CefRefPtr<CefResponse> response) {
342 EXPECT_EQ(200, response->GetStatus());
343 EXPECT_STREQ("OK", response->GetStatusText().ToString().c_str());
344 EXPECT_STREQ("text/html", response->GetMimeType().ToString().c_str());
345 }
346
DestroyTest()347 void DestroyTest() override {
348 EXPECT_TRUE(got_before_resource_load_);
349 EXPECT_TRUE(got_resource_handler_);
350 EXPECT_TRUE(got_resource_response_);
351 EXPECT_TRUE(got_resource_response_filter_);
352 EXPECT_TRUE(got_resource_load_complete_);
353
354 TestHandler::DestroyTest();
355 }
356
357 CefRefPtr<CefRequest> request_;
358 int64 response_length_;
359 uint64 request_id_;
360
361 TrackCallback got_before_resource_load_;
362 TrackCallback got_resource_handler_;
363 TrackCallback got_resource_response_;
364 TrackCallback got_resource_response_filter_;
365 TrackCallback got_resource_load_complete_;
366
367 IMPLEMENT_REFCOUNTING(RequestSendRecvTestHandler);
368 };
369
370 } // namespace
371
372 // Verify send and recieve
TEST(RequestTest,SendRecv)373 TEST(RequestTest, SendRecv) {
374 CefRefPtr<RequestSendRecvTestHandler> handler =
375 new RequestSendRecvTestHandler();
376 handler->ExecuteTest();
377 ReleaseAndWaitForDestructor(handler);
378 }
379
380 namespace {
381
382 const char kTypeTestOrigin[] = "http://tests-requesttt.com/";
383 const cef_transition_type_t kTransitionExplicitLoad =
384 static_cast<cef_transition_type_t>(TT_EXPLICIT | TT_DIRECT_LOAD_FLAG);
385
386 static struct TypeExpected {
387 const char* file;
388 bool navigation; // True if this expectation represents a navigation.
389 cef_transition_type_t transition_type;
390 cef_resource_type_t resource_type;
391 int expected_count;
392 } g_type_expected[] = {
393 // Initial main frame load due to browser creation.
394 {"main.html", true, kTransitionExplicitLoad, RT_MAIN_FRAME, 1},
395
396 // Sub frame load.
397 {"sub.html", true, TT_AUTO_SUBFRAME, RT_SUB_FRAME, 1},
398
399 // Stylesheet load.
400 {"style.css", false, TT_LINK, RT_STYLESHEET, 1},
401
402 // Script load.
403 {"script.js", false, TT_LINK, RT_SCRIPT, 1},
404
405 // Image load.
406 {"image.png", false, TT_LINK, RT_IMAGE, 1},
407
408 // Font load.
409 {"font.ttf", false, TT_LINK, RT_FONT_RESOURCE, 1},
410
411 // XHR load.
412 {"xhr.html", false, TT_LINK, RT_XHR, 1},
413 };
414
415 class TypeExpectations {
416 public:
TypeExpectations(bool navigation)417 explicit TypeExpectations(bool navigation) : navigation_(navigation) {
418 // Build the map of relevant requests.
419 for (int i = 0;
420 i < static_cast<int>(sizeof(g_type_expected) / sizeof(TypeExpected));
421 ++i) {
422 if (navigation_ && g_type_expected[i].navigation != navigation_)
423 continue;
424
425 request_count_.insert(std::make_pair(i, 0));
426 }
427 }
428
429 // Notify that a request has been received. Returns true if the request is
430 // something we care about.
GotRequest(CefRefPtr<CefRequest> request)431 bool GotRequest(CefRefPtr<CefRequest> request) {
432 const std::string& url = request->GetURL();
433 if (url.find(kTypeTestOrigin) != 0)
434 return false;
435
436 const std::string& file = url.substr(sizeof(kTypeTestOrigin) - 1);
437 cef_transition_type_t transition_type = request->GetTransitionType();
438 cef_resource_type_t resource_type = request->GetResourceType();
439
440 const int index = GetExpectedIndex(file, transition_type, resource_type);
441 EXPECT_GE(index, 0) << "File: " << file.c_str()
442 << "; Navigation: " << navigation_
443 << "; Transition Type: " << transition_type
444 << "; Resource Type: " << resource_type;
445
446 RequestCount::iterator it = request_count_.find(index);
447 EXPECT_TRUE(it != request_count_.end());
448
449 const int actual_count = ++it->second;
450 const int expected_count = g_type_expected[index].expected_count;
451 EXPECT_LE(actual_count, expected_count)
452 << "File: " << file.c_str() << "; Navigation: " << navigation_
453 << "; Transition Type: " << transition_type
454 << "; Resource Type: " << resource_type;
455
456 return true;
457 }
458
459 // Test if all expectations have been met.
IsDone(bool assert)460 bool IsDone(bool assert) {
461 for (int i = 0;
462 i < static_cast<int>(sizeof(g_type_expected) / sizeof(TypeExpected));
463 ++i) {
464 if (navigation_ && g_type_expected[i].navigation != navigation_)
465 continue;
466
467 RequestCount::const_iterator it = request_count_.find(i);
468 EXPECT_TRUE(it != request_count_.end());
469 if (it->second != g_type_expected[i].expected_count) {
470 if (assert) {
471 EXPECT_EQ(g_type_expected[i].expected_count, it->second)
472 << "File: " << g_type_expected[i].file
473 << "; Navigation: " << navigation_
474 << "; Transition Type: " << g_type_expected[i].transition_type
475 << "; Resource Type: " << g_type_expected[i].resource_type;
476 }
477 return false;
478 }
479 }
480 return true;
481 }
482
483 private:
484 // Returns the index for the specified navigation.
GetExpectedIndex(const std::string & file,cef_transition_type_t transition_type,cef_resource_type_t resource_type)485 int GetExpectedIndex(const std::string& file,
486 cef_transition_type_t transition_type,
487 cef_resource_type_t resource_type) {
488 for (int i = 0;
489 i < static_cast<int>(sizeof(g_type_expected) / sizeof(TypeExpected));
490 ++i) {
491 if (g_type_expected[i].file == file &&
492 (!navigation_ || g_type_expected[i].navigation == navigation_) &&
493 g_type_expected[i].transition_type == transition_type &&
494 g_type_expected[i].resource_type == resource_type) {
495 return i;
496 }
497 }
498 return -1;
499 }
500
501 bool navigation_;
502
503 // Map of TypeExpected index to actual request count.
504 typedef std::map<int, int> RequestCount;
505 RequestCount request_count_;
506 };
507
508 // Browser side.
509 class TypeTestHandler : public TestHandler {
510 public:
TypeTestHandler()511 TypeTestHandler()
512 : browse_expectations_(true),
513 load_expectations_(false),
514 get_expectations_(false),
515 completed_browser_side_(false),
516 destroyed_(false) {}
517
RunTest()518 void RunTest() override {
519 AddResource(std::string(kTypeTestOrigin) + "main.html",
520 "<html>"
521 "<head>"
522 "<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">"
523 "<script type=\"text/javascript\" src=\"script.js\"></script>"
524 "</head>"
525 "<body><p>Main</p>"
526 "<script>xhr = new XMLHttpRequest();"
527 "xhr.open('GET', 'xhr.html', false);"
528 "xhr.send();</script>"
529 "<iframe src=\"sub.html\"></iframe>"
530 "<img src=\"image.png\">"
531 "</body></html>",
532 "text/html");
533 AddResource(std::string(kTypeTestOrigin) + "sub.html", "<html>Sub</html>",
534 "text/html");
535 AddResource(std::string(kTypeTestOrigin) + "style.css",
536 "@font-face {"
537 " font-family: custom_font;"
538 " src: url('font.ttf');"
539 "}"
540 "p {"
541 " font-family: custom_font;"
542 "}",
543 "text/css");
544 AddResource(std::string(kTypeTestOrigin) + "script.js", "<!-- -->",
545 "text/javascript");
546 AddResource(std::string(kTypeTestOrigin) + "image.png", "<!-- -->",
547 "image/png");
548 AddResource(std::string(kTypeTestOrigin) + "font.ttf", "<!-- -->",
549 "font/ttf");
550 AddResource(std::string(kTypeTestOrigin) + "xhr.html", "<html>XHR</html>",
551 "text/html");
552 AddResource(std::string(kTypeTestOrigin) + "fetch.html",
553 "<html>Fetch</html>", "text/html");
554
555 CreateBrowser(std::string(kTypeTestOrigin) + "main.html");
556
557 // Time out the test after a reasonable period of time.
558 SetTestTimeout();
559 }
560
OnBeforeBrowse(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request,bool user_gesture,bool is_redirect)561 bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
562 CefRefPtr<CefFrame> frame,
563 CefRefPtr<CefRequest> request,
564 bool user_gesture,
565 bool is_redirect) override {
566 browse_expectations_.GotRequest(request);
567
568 return false;
569 }
570
OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request,CefRefPtr<CefCallback> callback)571 cef_return_value_t OnBeforeResourceLoad(
572 CefRefPtr<CefBrowser> browser,
573 CefRefPtr<CefFrame> frame,
574 CefRefPtr<CefRequest> request,
575 CefRefPtr<CefCallback> callback) override {
576 load_expectations_.GotRequest(request);
577
578 return RV_CONTINUE;
579 }
580
GetResourceHandler(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request)581 CefRefPtr<CefResourceHandler> GetResourceHandler(
582 CefRefPtr<CefBrowser> browser,
583 CefRefPtr<CefFrame> frame,
584 CefRefPtr<CefRequest> request) override {
585 if (get_expectations_.GotRequest(request) &&
586 get_expectations_.IsDone(false)) {
587 completed_browser_side_ = true;
588 // Destroy the test on the UI thread.
589 CefPostTask(TID_UI, base::BindOnce(&TypeTestHandler::DestroyTest, this));
590 }
591
592 return TestHandler::GetResourceHandler(browser, frame, request);
593 }
594
595 private:
DestroyTest()596 void DestroyTest() override {
597 if (destroyed_)
598 return;
599 destroyed_ = true;
600
601 // Verify test expectations.
602 EXPECT_TRUE(completed_browser_side_);
603 EXPECT_TRUE(browse_expectations_.IsDone(true));
604 EXPECT_TRUE(load_expectations_.IsDone(true));
605 EXPECT_TRUE(get_expectations_.IsDone(true));
606
607 TestHandler::DestroyTest();
608 }
609
610 TypeExpectations browse_expectations_;
611 TypeExpectations load_expectations_;
612 TypeExpectations get_expectations_;
613
614 bool completed_browser_side_;
615 bool destroyed_;
616
617 IMPLEMENT_REFCOUNTING(TypeTestHandler);
618 };
619
620 } // namespace
621
622 // Verify the order of navigation-related callbacks.
TEST(RequestTest,ResourceAndTransitionType)623 TEST(RequestTest, ResourceAndTransitionType) {
624 CefRefPtr<TypeTestHandler> handler = new TypeTestHandler();
625 handler->ExecuteTest();
626 ReleaseAndWaitForDestructor(handler);
627 }
628