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