• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2013 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 "include/base/cef_callback.h"
6 #include "include/cef_request_context.h"
7 #include "include/cef_request_context_handler.h"
8 #include "include/wrapper/cef_closure_task.h"
9 #include "include/wrapper/cef_scoped_temp_dir.h"
10 #include "tests/ceftests/test_handler.h"
11 #include "tests/ceftests/test_util.h"
12 #include "tests/gtest/include/gtest/gtest.h"
13 
TEST(RequestContextTest,BasicGetGlobal)14 TEST(RequestContextTest, BasicGetGlobal) {
15   CefRefPtr<CefRequestContext> context1 = CefRequestContext::GetGlobalContext();
16   EXPECT_TRUE(context1.get());
17   EXPECT_TRUE(context1->IsGlobal());
18   EXPECT_TRUE(context1->IsSame(context1));
19   EXPECT_TRUE(context1->IsSharingWith(context1));
20 
21   CefRefPtr<CefRequestContext> context2 = CefRequestContext::GetGlobalContext();
22   EXPECT_TRUE(context2.get());
23   EXPECT_TRUE(context2->IsGlobal());
24   EXPECT_TRUE(context2->IsSame(context2));
25   EXPECT_TRUE(context2->IsSharingWith(context2));
26 
27   EXPECT_TRUE(context1->IsSame(context2));
28   EXPECT_TRUE(context2->IsSame(context1));
29   EXPECT_TRUE(context1->IsSharingWith(context2));
30   EXPECT_TRUE(context2->IsSharingWith(context1));
31 }
32 
TEST(RequestContextTest,BasicCreate)33 TEST(RequestContextTest, BasicCreate) {
34   class Handler : public CefRequestContextHandler {
35    public:
36     Handler() {}
37 
38    private:
39     IMPLEMENT_REFCOUNTING(Handler);
40   };
41 
42   CefRefPtr<CefRequestContextHandler> handler = new Handler();
43 
44   CefRequestContextSettings settings;
45 
46   CefRefPtr<CefRequestContext> context1 =
47       CefRequestContext::CreateContext(settings, handler.get());
48   EXPECT_TRUE(context1.get());
49   EXPECT_FALSE(context1->IsGlobal());
50   EXPECT_TRUE(context1->IsSame(context1));
51   EXPECT_TRUE(context1->IsSharingWith(context1));
52   EXPECT_EQ(context1->GetHandler().get(), handler.get());
53 
54   CefRefPtr<CefRequestContext> context2 =
55       CefRequestContext::CreateContext(settings, handler.get());
56   EXPECT_TRUE(context2.get());
57   EXPECT_FALSE(context2->IsGlobal());
58   EXPECT_TRUE(context2->IsSame(context2));
59   EXPECT_TRUE(context2->IsSharingWith(context2));
60   EXPECT_EQ(context2->GetHandler().get(), handler.get());
61 
62   EXPECT_FALSE(context1->IsSame(context2));
63   EXPECT_FALSE(context1->IsSharingWith(context2));
64   EXPECT_FALSE(context2->IsSame(context1));
65   EXPECT_FALSE(context2->IsSharingWith(context1));
66 
67   CefRefPtr<CefRequestContext> context3 = CefRequestContext::GetGlobalContext();
68   EXPECT_TRUE(context3.get());
69   EXPECT_FALSE(context3->IsSame(context1));
70   EXPECT_FALSE(context3->IsSharingWith(context1));
71   EXPECT_FALSE(context3->IsSame(context2));
72   EXPECT_FALSE(context3->IsSharingWith(context2));
73   EXPECT_FALSE(context1->IsSame(context3));
74   EXPECT_FALSE(context1->IsSharingWith(context3));
75   EXPECT_FALSE(context2->IsSame(context3));
76   EXPECT_FALSE(context2->IsSharingWith(context3));
77 }
78 
TEST(RequestContextTest,BasicCreateNoHandler)79 TEST(RequestContextTest, BasicCreateNoHandler) {
80   CefRequestContextSettings settings;
81 
82   CefRefPtr<CefRequestContext> context1 =
83       CefRequestContext::CreateContext(settings, nullptr);
84   EXPECT_TRUE(context1.get());
85   EXPECT_FALSE(context1->IsGlobal());
86   EXPECT_TRUE(context1->IsSame(context1));
87   EXPECT_TRUE(context1->IsSharingWith(context1));
88   EXPECT_FALSE(context1->GetHandler().get());
89 
90   CefRefPtr<CefRequestContext> context2 =
91       CefRequestContext::CreateContext(settings, nullptr);
92   EXPECT_TRUE(context2.get());
93   EXPECT_FALSE(context2->IsGlobal());
94   EXPECT_TRUE(context2->IsSame(context2));
95   EXPECT_TRUE(context2->IsSharingWith(context2));
96   EXPECT_FALSE(context2->GetHandler().get());
97 
98   EXPECT_FALSE(context1->IsSame(context2));
99   EXPECT_FALSE(context1->IsSharingWith(context2));
100   EXPECT_FALSE(context2->IsSame(context1));
101   EXPECT_FALSE(context2->IsSharingWith(context1));
102 
103   CefRefPtr<CefRequestContext> context3 = CefRequestContext::GetGlobalContext();
104   EXPECT_TRUE(context3.get());
105   EXPECT_FALSE(context3->IsSame(context1));
106   EXPECT_FALSE(context3->IsSharingWith(context1));
107   EXPECT_FALSE(context3->IsSame(context2));
108   EXPECT_FALSE(context3->IsSharingWith(context2));
109   EXPECT_FALSE(context1->IsSame(context3));
110   EXPECT_FALSE(context1->IsSharingWith(context3));
111   EXPECT_FALSE(context2->IsSame(context3));
112   EXPECT_FALSE(context2->IsSharingWith(context3));
113 }
114 
TEST(RequestContextTest,BasicCreateSharedGlobal)115 TEST(RequestContextTest, BasicCreateSharedGlobal) {
116   CefRequestContextSettings settings;
117 
118   CefRefPtr<CefRequestContext> context1 = CefRequestContext::GetGlobalContext();
119   EXPECT_TRUE(context1.get());
120   EXPECT_TRUE(context1->IsGlobal());
121   EXPECT_TRUE(context1->IsSame(context1));
122   EXPECT_TRUE(context1->IsSharingWith(context1));
123 
124   // Returns the same global context.
125   CefRefPtr<CefRequestContext> context2 =
126       CefRequestContext::CreateContext(context1, nullptr);
127   EXPECT_TRUE(context2.get());
128   EXPECT_TRUE(context2->IsGlobal());
129   EXPECT_TRUE(context2->IsSame(context2));
130   EXPECT_TRUE(context2->IsSame(context1));
131   EXPECT_TRUE(context1->IsSame(context2));
132   EXPECT_TRUE(context2->IsSharingWith(context2));
133   EXPECT_TRUE(context2->IsSharingWith(context1));
134   EXPECT_TRUE(context1->IsSharingWith(context2));
135 }
136 
TEST(RequestContextTest,BasicCreateSharedOnDisk)137 TEST(RequestContextTest, BasicCreateSharedOnDisk) {
138   CefScopedTempDir tempdir;
139   EXPECT_TRUE(tempdir.CreateUniqueTempDirUnderPath(
140       CefTestSuite::GetInstance()->root_cache_path()));
141 
142   CefRequestContextSettings settings;
143   CefString(&settings.cache_path) = tempdir.GetPath();
144 
145   CefRefPtr<CefRequestContext> context1 =
146       CefRequestContext::CreateContext(settings, nullptr);
147   EXPECT_TRUE(context1.get());
148   EXPECT_FALSE(context1->IsGlobal());
149   EXPECT_TRUE(context1->IsSame(context1));
150   EXPECT_TRUE(context1->IsSharingWith(context1));
151 
152   CefRefPtr<CefRequestContext> context2 =
153       CefRequestContext::CreateContext(context1, nullptr);
154   EXPECT_TRUE(context2.get());
155   EXPECT_FALSE(context2->IsGlobal());
156   EXPECT_TRUE(context2->IsSame(context2));
157   EXPECT_FALSE(context2->IsSame(context1));
158   EXPECT_FALSE(context1->IsSame(context2));
159   EXPECT_TRUE(context2->IsSharingWith(context2));
160   EXPECT_TRUE(context2->IsSharingWith(context1));
161   EXPECT_TRUE(context1->IsSharingWith(context2));
162 
163   CefRefPtr<CefRequestContext> context3 =
164       CefRequestContext::CreateContext(context2, nullptr);
165   EXPECT_TRUE(context3.get());
166   EXPECT_FALSE(context3->IsGlobal());
167   EXPECT_TRUE(context3->IsSame(context3));
168   EXPECT_FALSE(context3->IsSame(context2));
169   EXPECT_FALSE(context3->IsSame(context1));
170   EXPECT_FALSE(context1->IsSame(context3));
171   EXPECT_FALSE(context2->IsSame(context3));
172   EXPECT_TRUE(context3->IsSharingWith(context3));
173   EXPECT_TRUE(context3->IsSharingWith(context2));
174   EXPECT_TRUE(context3->IsSharingWith(context1));
175   EXPECT_TRUE(context1->IsSharingWith(context3));
176   EXPECT_TRUE(context2->IsSharingWith(context3));
177 
178   CefRefPtr<CefRequestContext> context4 =
179       CefRequestContext::CreateContext(context1, nullptr);
180   EXPECT_TRUE(context4.get());
181   EXPECT_FALSE(context4->IsGlobal());
182   EXPECT_TRUE(context4->IsSame(context4));
183   EXPECT_FALSE(context4->IsSame(context3));
184   EXPECT_FALSE(context4->IsSame(context2));
185   EXPECT_FALSE(context4->IsSame(context1));
186   EXPECT_FALSE(context1->IsSame(context4));
187   EXPECT_FALSE(context2->IsSame(context4));
188   EXPECT_FALSE(context3->IsSame(context4));
189   EXPECT_TRUE(context4->IsSharingWith(context4));
190   EXPECT_TRUE(context4->IsSharingWith(context3));
191   EXPECT_TRUE(context4->IsSharingWith(context2));
192   EXPECT_TRUE(context4->IsSharingWith(context1));
193   EXPECT_TRUE(context1->IsSharingWith(context4));
194   EXPECT_TRUE(context2->IsSharingWith(context4));
195   EXPECT_TRUE(context3->IsSharingWith(context4));
196 }
197 
198 namespace {
199 
200 class PopupTestHandler : public TestHandler {
201  public:
202   enum Mode {
203     MODE_WINDOW_OPEN,
204     MODE_TARGETED_LINK,
205     MODE_NOREFERRER_LINK,
206   };
207 
PopupTestHandler(bool same_origin,Mode mode)208   PopupTestHandler(bool same_origin, Mode mode) : mode_(mode) {
209     url_ = "http://tests-simple-rch1.com/nav1.html";
210     if (same_origin)
211       popup_url_ = "http://tests-simple-rch1.com/pop1.html";
212     else
213       popup_url_ = "http://tests-simple-rch2.com/pop1.html";
214   }
215 
RunTest()216   void RunTest() override {
217     std::string link;
218     if (mode_ == MODE_TARGETED_LINK) {
219       link = "<a href=\"" + std::string(popup_url_) +
220              "\" target=\"mytarget\"\">CLICK ME</a>";
221     } else if (mode_ == MODE_NOREFERRER_LINK) {
222       link = "<a href=\"" + std::string(popup_url_) +
223              "\" rel=\"noreferrer\" target=\"_blank\"\">CLICK ME</a>";
224     }
225 
226     AddResource(url_,
227                 "<html>"
228                 "<head><script>document.cookie='name1=value1';"
229                 "function doPopup() { window.open('" +
230                     std::string(popup_url_) +
231                     "'); }"
232                     "</script></head>"
233                     "<body><h1>" +
234                     link +
235                     "</h1></body>"
236                     "</html>",
237                 "text/html");
238 
239     AddResource(popup_url_,
240                 "<html>"
241                 "<head><script>document.cookie='name2=value2';</script></head>"
242                 "<body>Nav1</body>"
243                 "</html>",
244                 "text/html");
245 
246     CefRequestContextSettings settings;
247 
248     context_ = CefRequestContext::CreateContext(settings, nullptr);
249     cookie_manager_ = context_->GetCookieManager(nullptr);
250 
251     // Create browser that loads the 1st URL.
252     CreateBrowser(url_, context_);
253 
254     // Time out the test after a reasonable period of time.
255     SetTestTimeout();
256   }
257 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int httpStatusCode)258   void OnLoadEnd(CefRefPtr<CefBrowser> browser,
259                  CefRefPtr<CefFrame> frame,
260                  int httpStatusCode) override {
261     CefRefPtr<CefRequestContext> context =
262         browser->GetHost()->GetRequestContext();
263     EXPECT_TRUE(context.get());
264     EXPECT_TRUE(context->IsSame(context_));
265     EXPECT_FALSE(context->IsGlobal());
266 
267     EXPECT_TRUE(frame->IsMain());
268 
269     const std::string& url = frame->GetURL();
270     if (url == url_) {
271       got_load_end1_.yes();
272       LaunchPopup(browser);
273     } else if (url == popup_url_) {
274       got_load_end2_.yes();
275       EXPECT_TRUE(browser->IsPopup());
276       // Close the popup window.
277       CloseBrowser(browser, true);
278     }
279   }
280 
OnBeforePopup(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const CefString & target_url,const CefString & target_frame_name,cef_window_open_disposition_t target_disposition,bool user_gesture,const CefPopupFeatures & popupFeatures,CefWindowInfo & windowInfo,CefRefPtr<CefClient> & client,CefBrowserSettings & settings,CefRefPtr<CefDictionaryValue> & extra_info,bool * no_javascript_access)281   bool OnBeforePopup(CefRefPtr<CefBrowser> browser,
282                      CefRefPtr<CefFrame> frame,
283                      const CefString& target_url,
284                      const CefString& target_frame_name,
285                      cef_window_open_disposition_t target_disposition,
286                      bool user_gesture,
287                      const CefPopupFeatures& popupFeatures,
288                      CefWindowInfo& windowInfo,
289                      CefRefPtr<CefClient>& client,
290                      CefBrowserSettings& settings,
291                      CefRefPtr<CefDictionaryValue>& extra_info,
292                      bool* no_javascript_access) override {
293     got_on_before_popup_.yes();
294 
295     const std::string& url = target_url;
296     EXPECT_STREQ(url.c_str(), popup_url_.c_str());
297 
298     EXPECT_EQ(WOD_NEW_FOREGROUND_TAB, target_disposition);
299 
300     if (mode_ == MODE_WINDOW_OPEN)
301       EXPECT_FALSE(user_gesture);
302     else
303       EXPECT_TRUE(user_gesture);
304 
305     return false;
306   }
307 
OnBeforeClose(CefRefPtr<CefBrowser> browser)308   void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
309     TestHandler::OnBeforeClose(browser);
310 
311     if (browser->IsPopup())
312       FinishTest();
313   }
314 
315  protected:
LaunchPopup(CefRefPtr<CefBrowser> browser)316   void LaunchPopup(CefRefPtr<CefBrowser> browser) {
317     if (mode_ == MODE_WINDOW_OPEN) {
318       browser->GetMainFrame()->ExecuteJavaScript("doPopup()", url_, 0);
319     } else if (mode_ == MODE_TARGETED_LINK || mode_ == MODE_NOREFERRER_LINK) {
320       CefMouseEvent mouse_event;
321       mouse_event.x = 20;
322       mouse_event.y = 20;
323       mouse_event.modifiers = 0;
324 
325       // Add some delay to avoid having events dropped or rate limited.
326       CefPostDelayedTask(
327           TID_UI,
328           base::BindOnce(&CefBrowserHost::SendMouseClickEvent,
329                          browser->GetHost(), mouse_event, MBT_LEFT, false, 1),
330           50);
331       CefPostDelayedTask(
332           TID_UI,
333           base::BindOnce(&CefBrowserHost::SendMouseClickEvent,
334                          browser->GetHost(), mouse_event, MBT_LEFT, true, 1),
335           100);
336     } else {
337       ADD_FAILURE();  // Not reached.
338     }
339   }
340 
FinishTest()341   void FinishTest() {
342     // Verify that the cookies were set correctly.
343     class TestVisitor : public CefCookieVisitor {
344      public:
345       explicit TestVisitor(PopupTestHandler* handler) : handler_(handler) {}
346       ~TestVisitor() override {
347         // Destroy the test.
348         CefPostTask(TID_UI,
349                     base::BindOnce(&PopupTestHandler::DestroyTest, handler_));
350       }
351 
352       bool Visit(const CefCookie& cookie,
353                  int count,
354                  int total,
355                  bool& deleteCookie) override {
356         const std::string& name = CefString(&cookie.name);
357         const std::string& value = CefString(&cookie.value);
358         if (name == "name1" && value == "value1") {
359           handler_->got_cookie1_.yes();
360           deleteCookie = true;
361         } else if (name == "name2" && value == "value2") {
362           handler_->got_cookie2_.yes();
363           deleteCookie = true;
364         }
365         return true;
366       }
367 
368      private:
369       PopupTestHandler* handler_;
370       IMPLEMENT_REFCOUNTING(TestVisitor);
371     };
372 
373     cookie_manager_->VisitAllCookies(new TestVisitor(this));
374   }
375 
DestroyTest()376   void DestroyTest() override {
377     // Verify test expectations.
378     EXPECT_TRUE(got_load_end1_);
379     EXPECT_TRUE(got_on_before_popup_);
380     EXPECT_TRUE(got_load_end2_);
381     EXPECT_TRUE(got_cookie1_);
382     EXPECT_TRUE(got_cookie2_);
383     context_ = nullptr;
384 
385     TestHandler::DestroyTest();
386   }
387 
388   std::string url_;
389   std::string popup_url_;
390   Mode mode_;
391 
392   CefRefPtr<CefRequestContext> context_;
393   CefRefPtr<CefCookieManager> cookie_manager_;
394 
395   TrackCallback got_load_end1_;
396   TrackCallback got_on_before_popup_;
397   TrackCallback got_load_end2_;
398   TrackCallback got_cookie1_;
399   TrackCallback got_cookie2_;
400 
401   IMPLEMENT_REFCOUNTING(PopupTestHandler);
402 };
403 
404 }  // namespace
405 
406 // Test that a popup created using window.open() will get the same request
407 // context as the parent browser.
TEST(RequestContextTest,PopupBasicWindowOpenSameOrigin)408 TEST(RequestContextTest, PopupBasicWindowOpenSameOrigin) {
409   CefRefPtr<PopupTestHandler> handler =
410       new PopupTestHandler(true, PopupTestHandler::MODE_WINDOW_OPEN);
411   handler->ExecuteTest();
412   ReleaseAndWaitForDestructor(handler);
413 }
414 
TEST(RequestContextTest,PopupBasicWindowOpenDifferentOrigin)415 TEST(RequestContextTest, PopupBasicWindowOpenDifferentOrigin) {
416   CefRefPtr<PopupTestHandler> handler =
417       new PopupTestHandler(false, PopupTestHandler::MODE_WINDOW_OPEN);
418   handler->ExecuteTest();
419   ReleaseAndWaitForDestructor(handler);
420 }
421 
422 // Test that a popup created using a targeted link will get the same request
423 // context as the parent browser.
TEST(RequestContextTest,PopupBasicTargetedLinkSameOrigin)424 TEST(RequestContextTest, PopupBasicTargetedLinkSameOrigin) {
425   CefRefPtr<PopupTestHandler> handler =
426       new PopupTestHandler(true, PopupTestHandler::MODE_TARGETED_LINK);
427   handler->ExecuteTest();
428   ReleaseAndWaitForDestructor(handler);
429 }
430 
TEST(RequestContextTest,PopupBasicTargetedLinkDifferentOrigin)431 TEST(RequestContextTest, PopupBasicTargetedLinkDifferentOrigin) {
432   CefRefPtr<PopupTestHandler> handler =
433       new PopupTestHandler(false, PopupTestHandler::MODE_TARGETED_LINK);
434   handler->ExecuteTest();
435   ReleaseAndWaitForDestructor(handler);
436 }
437 
438 // Test that a popup created using a noreferrer link will get the same
439 // request context as the parent browser. A new render process will
440 // be created for the popup browser.
TEST(RequestContextTest,PopupBasicNoReferrerLinkSameOrigin)441 TEST(RequestContextTest, PopupBasicNoReferrerLinkSameOrigin) {
442   CefRefPtr<PopupTestHandler> handler =
443       new PopupTestHandler(true, PopupTestHandler::MODE_NOREFERRER_LINK);
444   handler->ExecuteTest();
445   ReleaseAndWaitForDestructor(handler);
446 }
447 
TEST(RequestContextTest,PopupBasicNoReferrerLinkDifferentOrigin)448 TEST(RequestContextTest, PopupBasicNoReferrerLinkDifferentOrigin) {
449   CefRefPtr<PopupTestHandler> handler =
450       new PopupTestHandler(false, PopupTestHandler::MODE_NOREFERRER_LINK);
451   handler->ExecuteTest();
452   ReleaseAndWaitForDestructor(handler);
453 }
454 
455 namespace {
456 
457 const char kPopupNavPageUrl[] = "http://tests-popup.com/page.html";
458 const char kPopupNavPopupUrl[] = "http://tests-popup.com/popup.html";
459 const char kPopupNavPopupUrl2[] = "http://tests-popup2.com/popup.html";
460 const char kPopupNavPopupName[] = "my_popup";
461 
462 // Browser side.
463 class PopupNavTestHandler : public TestHandler {
464  public:
465   enum TestMode {
466     ALLOW_CLOSE_POPUP_FIRST,
467     ALLOW_CLOSE_POPUP_LAST,
468     DENY,
469     NAVIGATE_AFTER_CREATION,
470     DESTROY_PARENT_BEFORE_CREATION,
471     DESTROY_PARENT_BEFORE_CREATION_FORCE,
472     DESTROY_PARENT_DURING_CREATION,
473     DESTROY_PARENT_DURING_CREATION_FORCE,
474     DESTROY_PARENT_AFTER_CREATION,
475     DESTROY_PARENT_AFTER_CREATION_FORCE,
476   };
477 
PopupNavTestHandler(TestMode test_mode,TestRequestContextMode rc_mode,const std::string & rc_cache_path)478   PopupNavTestHandler(TestMode test_mode,
479                       TestRequestContextMode rc_mode,
480                       const std::string& rc_cache_path)
481       : mode_(test_mode), rc_mode_(rc_mode), rc_cache_path_(rc_cache_path) {}
482 
RunTest()483   void RunTest() override {
484     // Add the resources that we will navigate to/from.
485     std::string page = "<html><script>function doPopup() { window.open('" +
486                        std::string(kPopupNavPopupUrl) + "', '" +
487                        std::string(kPopupNavPopupName) +
488                        "'); }</script>Page</html>";
489     AddResource(kPopupNavPageUrl, page, "text/html");
490     AddResource(kPopupNavPopupUrl, "<html>Popup</html>", "text/html");
491     if (mode_ == NAVIGATE_AFTER_CREATION)
492       AddResource(kPopupNavPopupUrl2, "<html>Popup2</html>", "text/html");
493 
494     CefRefPtr<CefRequestContext> request_context =
495         CreateTestRequestContext(rc_mode_, rc_cache_path_);
496 
497     // Create the browser.
498     CreateBrowser(kPopupNavPageUrl, request_context);
499 
500     // Time out the test after a reasonable period of time.
501     SetTestTimeout();
502   }
503 
OnBeforePopup(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const CefString & target_url,const CefString & target_frame_name,cef_window_open_disposition_t target_disposition,bool user_gesture,const CefPopupFeatures & popupFeatures,CefWindowInfo & windowInfo,CefRefPtr<CefClient> & client,CefBrowserSettings & settings,CefRefPtr<CefDictionaryValue> & extra_info,bool * no_javascript_access)504   bool OnBeforePopup(CefRefPtr<CefBrowser> browser,
505                      CefRefPtr<CefFrame> frame,
506                      const CefString& target_url,
507                      const CefString& target_frame_name,
508                      cef_window_open_disposition_t target_disposition,
509                      bool user_gesture,
510                      const CefPopupFeatures& popupFeatures,
511                      CefWindowInfo& windowInfo,
512                      CefRefPtr<CefClient>& client,
513                      CefBrowserSettings& settings,
514                      CefRefPtr<CefDictionaryValue>& extra_info,
515                      bool* no_javascript_access) override {
516     EXPECT_FALSE(got_on_before_popup_);
517     got_on_before_popup_.yes();
518 
519     EXPECT_TRUE(CefCurrentlyOn(TID_UI));
520     EXPECT_EQ(GetBrowserId(), browser->GetIdentifier());
521     EXPECT_STREQ(kPopupNavPageUrl, frame->GetURL().ToString().c_str());
522     EXPECT_STREQ(kPopupNavPopupUrl, target_url.ToString().c_str());
523     EXPECT_STREQ(kPopupNavPopupName, target_frame_name.ToString().c_str());
524     EXPECT_EQ(WOD_NEW_FOREGROUND_TAB, target_disposition);
525     EXPECT_FALSE(user_gesture);
526     EXPECT_FALSE(*no_javascript_access);
527 
528     if (mode_ == DESTROY_PARENT_DURING_CREATION ||
529         mode_ == DESTROY_PARENT_DURING_CREATION_FORCE) {
530       // Destroy the main (parent) browser while popup creation is pending.
531       CloseBrowser(browser, mode_ == DESTROY_PARENT_DURING_CREATION_FORCE);
532     }
533 
534     return (mode_ == DENY);  // Return true to cancel the popup.
535   }
536 
OnAfterCreated(CefRefPtr<CefBrowser> browser)537   void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
538     TestHandler::OnAfterCreated(browser);
539 
540     if (browser->IsPopup() && (mode_ == DESTROY_PARENT_AFTER_CREATION ||
541                                mode_ == DESTROY_PARENT_AFTER_CREATION_FORCE)) {
542       // Destroy the main (parent) browser immediately after the popup is
543       // created.
544       CloseBrowser(GetBrowser(), mode_ == DESTROY_PARENT_AFTER_CREATION_FORCE);
545     }
546 
547     if (mode_ == NAVIGATE_AFTER_CREATION && browser->IsPopup()) {
548       // Navigate to the 2nd popup URL instead of the 1st popup URL.
549       browser->GetMainFrame()->LoadURL(kPopupNavPopupUrl2);
550     }
551   }
552 
OnLoadStart(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,TransitionType transition_type)553   void OnLoadStart(CefRefPtr<CefBrowser> browser,
554                    CefRefPtr<CefFrame> frame,
555                    TransitionType transition_type) override {
556     const std::string& url = frame->GetURL();
557     if (url == kPopupNavPageUrl) {
558       EXPECT_FALSE(got_load_start_);
559       got_load_start_.yes();
560     } else if (url == kPopupNavPopupUrl) {
561       EXPECT_FALSE(got_popup_load_start_);
562       got_popup_load_start_.yes();
563     } else if (url == kPopupNavPopupUrl2) {
564       EXPECT_FALSE(got_popup_load_start2_);
565       got_popup_load_start2_.yes();
566     }
567   }
568 
OnLoadError(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,ErrorCode errorCode,const CefString & errorText,const CefString & failedUrl)569   void OnLoadError(CefRefPtr<CefBrowser> browser,
570                    CefRefPtr<CefFrame> frame,
571                    ErrorCode errorCode,
572                    const CefString& errorText,
573                    const CefString& failedUrl) override {
574     if (failedUrl == kPopupNavPageUrl) {
575       EXPECT_FALSE(got_load_error_);
576       got_load_error_.yes();
577     } else if (failedUrl == kPopupNavPopupUrl) {
578       EXPECT_FALSE(got_popup_load_error_);
579       got_popup_load_error_.yes();
580     } else if (failedUrl == kPopupNavPopupUrl2) {
581       EXPECT_FALSE(got_popup_load_error2_);
582       got_popup_load_error2_.yes();
583     }
584   }
585 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int httpStatusCode)586   void OnLoadEnd(CefRefPtr<CefBrowser> browser,
587                  CefRefPtr<CefFrame> frame,
588                  int httpStatusCode) override {
589     const std::string& url = frame->GetURL();
590     if (url == kPopupNavPageUrl) {
591       EXPECT_FALSE(got_load_end_);
592       got_load_end_.yes();
593 
594       frame->ExecuteJavaScript("doPopup()", kPopupNavPageUrl, 0);
595 
596       if (mode_ == DESTROY_PARENT_BEFORE_CREATION ||
597           mode_ == DESTROY_PARENT_BEFORE_CREATION_FORCE) {
598         // Destroy the main (parent) browser immediately before the popup is
599         // created.
600         CloseBrowser(browser, mode_ == DESTROY_PARENT_BEFORE_CREATION_FORCE);
601       }
602 
603       if (mode_ == DENY) {
604         // Wait a bit to make sure the popup window isn't created.
605         CefPostDelayedTask(
606             TID_UI, base::BindOnce(&PopupNavTestHandler::DestroyTest, this),
607             200);
608       }
609     } else if (url == kPopupNavPopupUrl) {
610       EXPECT_FALSE(got_popup_load_end_);
611       got_popup_load_end_.yes();
612 
613       if (mode_ == ALLOW_CLOSE_POPUP_FIRST) {
614         // Close the popup browser first.
615         CloseBrowser(browser, false);
616       } else if (mode_ == ALLOW_CLOSE_POPUP_LAST) {
617         // Close the main browser first.
618         CloseBrowser(GetBrowser(), false);
619       } else if (mode_ != NAVIGATE_AFTER_CREATION) {
620         EXPECT_FALSE(true);  // Not reached.
621       }
622     } else if (url == kPopupNavPopupUrl2) {
623       EXPECT_FALSE(got_popup_load_end2_);
624       got_popup_load_end2_.yes();
625 
626       if (mode_ == NAVIGATE_AFTER_CREATION) {
627         // Close the popup browser first.
628         CloseBrowser(browser, false);
629       } else {
630         EXPECT_FALSE(true);  // Not reached.
631       }
632     } else {
633       EXPECT_FALSE(true);  // Not reached.
634     }
635   }
636 
OnBeforeClose(CefRefPtr<CefBrowser> browser)637   void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
638     TestHandler::OnBeforeClose(browser);
639 
640     bool destroy_test = false;
641     if (mode_ == ALLOW_CLOSE_POPUP_FIRST || mode_ == NAVIGATE_AFTER_CREATION) {
642       // Destroy the test after the popup browser closes.
643       if (browser->IsPopup())
644         destroy_test = true;
645     } else if (mode_ == ALLOW_CLOSE_POPUP_LAST ||
646                mode_ == DESTROY_PARENT_BEFORE_CREATION ||
647                mode_ == DESTROY_PARENT_BEFORE_CREATION_FORCE ||
648                mode_ == DESTROY_PARENT_DURING_CREATION ||
649                mode_ == DESTROY_PARENT_DURING_CREATION_FORCE ||
650                mode_ == DESTROY_PARENT_AFTER_CREATION ||
651                mode_ == DESTROY_PARENT_AFTER_CREATION_FORCE) {
652       // Destroy the test after the main browser closes.
653       if (!browser->IsPopup())
654         destroy_test = true;
655     }
656 
657     if (destroy_test) {
658       CefPostTask(TID_UI,
659                   base::BindOnce(&PopupNavTestHandler::DestroyTest, this));
660     }
661   }
662 
663  private:
DestroyTest()664   void DestroyTest() override {
665     EXPECT_TRUE(got_load_start_);
666     EXPECT_FALSE(got_load_error_);
667     EXPECT_TRUE(got_load_end_);
668 
669     // OnBeforePopup may come before or after browser destruction with the
670     // DESTROY_PARENT_BEFORE_CREATION* tests.
671     if (mode_ != DESTROY_PARENT_BEFORE_CREATION &&
672         mode_ != DESTROY_PARENT_BEFORE_CREATION_FORCE) {
673       EXPECT_TRUE(got_on_before_popup_);
674     }
675 
676     if (mode_ == ALLOW_CLOSE_POPUP_FIRST || mode_ == ALLOW_CLOSE_POPUP_LAST) {
677       EXPECT_TRUE(got_popup_load_start_);
678       EXPECT_FALSE(got_popup_load_error_);
679       EXPECT_TRUE(got_popup_load_end_);
680       EXPECT_FALSE(got_popup_load_start2_);
681       EXPECT_FALSE(got_popup_load_error2_);
682       EXPECT_FALSE(got_popup_load_end2_);
683     } else if (mode_ == DENY || mode_ == DESTROY_PARENT_BEFORE_CREATION ||
684                mode_ == DESTROY_PARENT_BEFORE_CREATION_FORCE ||
685                mode_ == DESTROY_PARENT_DURING_CREATION ||
686                mode_ == DESTROY_PARENT_DURING_CREATION_FORCE ||
687                mode_ == DESTROY_PARENT_AFTER_CREATION ||
688                mode_ == DESTROY_PARENT_AFTER_CREATION_FORCE) {
689       EXPECT_FALSE(got_popup_load_start_);
690       EXPECT_FALSE(got_popup_load_error_);
691       EXPECT_FALSE(got_popup_load_end_);
692       EXPECT_FALSE(got_popup_load_start2_);
693       EXPECT_FALSE(got_popup_load_error2_);
694       EXPECT_FALSE(got_popup_load_end2_);
695     } else if (mode_ == NAVIGATE_AFTER_CREATION) {
696       EXPECT_FALSE(got_popup_load_start_);
697 
698       // With browser-side navigation we will never actually begin the
699       // navigation to the 1st popup URL, so there will be no load error.
700       EXPECT_FALSE(got_popup_load_error_);
701 
702       EXPECT_FALSE(got_popup_load_end_);
703       EXPECT_TRUE(got_popup_load_start2_);
704       EXPECT_FALSE(got_popup_load_error2_);
705       EXPECT_TRUE(got_popup_load_end2_);
706     }
707 
708     // Will trigger destruction of all remaining browsers.
709     TestHandler::DestroyTest();
710   }
711 
712   const TestMode mode_;
713   const TestRequestContextMode rc_mode_;
714   const std::string rc_cache_path_;
715 
716   TrackCallback got_on_before_popup_;
717   TrackCallback got_load_start_;
718   TrackCallback got_load_error_;
719   TrackCallback got_load_end_;
720   TrackCallback got_popup_load_start_;
721   TrackCallback got_popup_load_error_;
722   TrackCallback got_popup_load_end_;
723   TrackCallback got_popup_load_start2_;
724   TrackCallback got_popup_load_error2_;
725   TrackCallback got_popup_load_end2_;
726 
727   IMPLEMENT_REFCOUNTING(PopupNavTestHandler);
728 };
729 
730 }  // namespace
731 #define POPUP_TEST_GROUP(test_name, test_mode)                     \
732   RC_TEST_GROUP_IN_MEMORY(RequestContextTest, PopupNav##test_name, \
733                           PopupNavTestHandler, test_mode)
734 
735 // Test allowing popups and closing the popup browser first.
736 POPUP_TEST_GROUP(AllowClosePopupFirst, ALLOW_CLOSE_POPUP_FIRST)
737 
738 // Test allowing popups and closing the main browser first to verify
739 // that internal objects are tracked correctly (see issue #2162).
740 POPUP_TEST_GROUP(AllowClosePopupLast, ALLOW_CLOSE_POPUP_LAST)
741 
742 // Test denying popups.
743 POPUP_TEST_GROUP(Deny, DENY)
744 
745 // Test navigation to a different origin after popup creation to
746 // verify that internal objects are tracked correctly (see issue
747 // #1392).
748 POPUP_TEST_GROUP(NavigateAfterCreation, NAVIGATE_AFTER_CREATION)
749 
750 // Test destroying the parent browser during or immediately after
751 // popup creation to verify that internal objects are tracked
752 // correctly (see issue #2041).
753 POPUP_TEST_GROUP(DestroyParentBeforeCreation, DESTROY_PARENT_BEFORE_CREATION)
754 POPUP_TEST_GROUP(DestroyParentBeforeCreationForce,
755                  DESTROY_PARENT_BEFORE_CREATION_FORCE)
756 POPUP_TEST_GROUP(DestroyParentDuringCreation, DESTROY_PARENT_DURING_CREATION)
757 POPUP_TEST_GROUP(DestroyParentDuringCreationForce,
758                  DESTROY_PARENT_DURING_CREATION_FORCE)
759 POPUP_TEST_GROUP(DestroyParentAfterCreation, DESTROY_PARENT_AFTER_CREATION)
760 POPUP_TEST_GROUP(DestroyParentAfterCreationForce,
761                  DESTROY_PARENT_AFTER_CREATION_FORCE)
762 
763 namespace {
764 
765 const char kResolveOrigin[] = "http://www.google.com";
766 
767 class MethodTestHandler : public TestHandler {
768  public:
769   enum Method {
770     METHOD_CLEAR_CERTIFICATE_EXCEPTIONS,
771     METHOD_CLOSE_ALL_CONNECTIONS,
772     METHOD_RESOLVE_HOST,
773   };
774 
775   class CompletionCallback : public CefCompletionCallback,
776                              public CefResolveCallback {
777    public:
CompletionCallback(MethodTestHandler * test_handler,CefRefPtr<CefBrowser> browser)778     CompletionCallback(MethodTestHandler* test_handler,
779                        CefRefPtr<CefBrowser> browser)
780         : test_handler_(test_handler), browser_(browser) {}
781 
~CompletionCallback()782     ~CompletionCallback() override {
783       // OnComplete should be executed.
784       EXPECT_FALSE(test_handler_);
785     }
786 
OnComplete()787     void OnComplete() override {
788       EXPECT_UI_THREAD();
789 
790       // OnComplete should be executed only one time.
791       EXPECT_TRUE(test_handler_);
792       test_handler_->OnCompleteCallback(browser_);
793       test_handler_ = nullptr;
794       browser_ = nullptr;
795     }
796 
OnResolveCompleted(cef_errorcode_t result,const std::vector<CefString> & resolved_ips)797     void OnResolveCompleted(
798         cef_errorcode_t result,
799         const std::vector<CefString>& resolved_ips) override {
800       EXPECT_EQ(ERR_NONE, result);
801       EXPECT_TRUE(!resolved_ips.empty());
802       OnComplete();
803     }
804 
805    private:
806     MethodTestHandler* test_handler_;
807     CefRefPtr<CefBrowser> browser_;
808 
809     IMPLEMENT_REFCOUNTING(CompletionCallback);
810   };
811 
MethodTestHandler(bool global_context,Method method)812   MethodTestHandler(bool global_context, Method method)
813       : global_context_(global_context), method_(method) {}
814 
RunTest()815   void RunTest() override {
816     const char kUrl[] = "http://tests/method.html";
817 
818     AddResource(kUrl, "<html><body>Method</body></html>", "text/html");
819 
820     CefRefPtr<CefRequestContext> request_context;
821     if (!global_context_) {
822       CefRequestContextSettings settings;
823       request_context = CefRequestContext::CreateContext(settings, nullptr);
824     }
825 
826     CreateBrowser(kUrl, request_context);
827 
828     // Time out the test after a reasonable period of time.
829     SetTestTimeout();
830   }
831 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int httpStatusCode)832   void OnLoadEnd(CefRefPtr<CefBrowser> browser,
833                  CefRefPtr<CefFrame> frame,
834                  int httpStatusCode) override {
835     CefRefPtr<CefRequestContext> context =
836         browser->GetHost()->GetRequestContext();
837     CefRefPtr<CompletionCallback> callback =
838         new CompletionCallback(this, browser);
839     if (method_ == METHOD_CLEAR_CERTIFICATE_EXCEPTIONS)
840       context->ClearCertificateExceptions(callback);
841     else if (method_ == METHOD_CLOSE_ALL_CONNECTIONS)
842       context->CloseAllConnections(callback);
843     else if (method_ == METHOD_RESOLVE_HOST)
844       context->ResolveHost(kResolveOrigin, callback);
845   }
846 
OnCompleteCallback(CefRefPtr<CefBrowser> browser)847   void OnCompleteCallback(CefRefPtr<CefBrowser> browser) {
848     EXPECT_UI_THREAD();
849     EXPECT_FALSE(got_completion_callback_);
850     got_completion_callback_.yes();
851 
852     DestroyTest();
853   }
854 
855  private:
DestroyTest()856   void DestroyTest() override {
857     EXPECT_TRUE(got_completion_callback_);
858     TestHandler::DestroyTest();
859   }
860 
861   const bool global_context_;
862   const Method method_;
863 
864   TrackCallback got_completion_callback_;
865 
866   IMPLEMENT_REFCOUNTING(MethodTestHandler);
867 };
868 
869 }  // namespace
870 
871 // Test CefRequestContext::ClearCertificateExceptions with the global
872 // context.
TEST(RequestContextTest,ClearCertificateExceptionsGlobal)873 TEST(RequestContextTest, ClearCertificateExceptionsGlobal) {
874   CefRefPtr<MethodTestHandler> handler = new MethodTestHandler(
875       true, MethodTestHandler::METHOD_CLEAR_CERTIFICATE_EXCEPTIONS);
876   handler->ExecuteTest();
877   ReleaseAndWaitForDestructor(handler);
878 }
879 
880 // Test CefRequestContext::ClearCertificateExceptions with a custom
881 // context.
TEST(RequestContextTest,ClearCertificateExceptionsCustom)882 TEST(RequestContextTest, ClearCertificateExceptionsCustom) {
883   CefRefPtr<MethodTestHandler> handler = new MethodTestHandler(
884       false, MethodTestHandler::METHOD_CLEAR_CERTIFICATE_EXCEPTIONS);
885   handler->ExecuteTest();
886   ReleaseAndWaitForDestructor(handler);
887 }
888 
889 // Test CefRequestContext::CloseAllConnections with the global
890 // context.
TEST(RequestContextTest,CloseAllConnectionsGlobal)891 TEST(RequestContextTest, CloseAllConnectionsGlobal) {
892   CefRefPtr<MethodTestHandler> handler = new MethodTestHandler(
893       true, MethodTestHandler::METHOD_CLOSE_ALL_CONNECTIONS);
894   handler->ExecuteTest();
895   ReleaseAndWaitForDestructor(handler);
896 }
897 
898 // Test CefRequestContext::CloseAllConnections with a custom context.
TEST(RequestContextTest,CloseAllConnectionsCustom)899 TEST(RequestContextTest, CloseAllConnectionsCustom) {
900   CefRefPtr<MethodTestHandler> handler = new MethodTestHandler(
901       false, MethodTestHandler::METHOD_CLOSE_ALL_CONNECTIONS);
902   handler->ExecuteTest();
903   ReleaseAndWaitForDestructor(handler);
904 }
905 
906 // Test CefRequestContext::ResolveHost with the global context.
TEST(RequestContextTest,ResolveHostGlobal)907 TEST(RequestContextTest, ResolveHostGlobal) {
908   CefRefPtr<MethodTestHandler> handler =
909       new MethodTestHandler(true, MethodTestHandler::METHOD_RESOLVE_HOST);
910   handler->ExecuteTest();
911   ReleaseAndWaitForDestructor(handler);
912 }
913 
914 // Test CefRequestContext::ResolveHost with a custom context.
TEST(RequestContextTest,ResolveHostCustom)915 TEST(RequestContextTest, ResolveHostCustom) {
916   CefRefPtr<MethodTestHandler> handler =
917       new MethodTestHandler(false, MethodTestHandler::METHOD_RESOLVE_HOST);
918   handler->ExecuteTest();
919   ReleaseAndWaitForDestructor(handler);
920 }
921