• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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