Popups must share the parent context to avoid crashes on parent browser destruction (issue #2162)

This commit is contained in:
Marshall Greenblatt
2017-05-04 17:53:27 -04:00
parent 5a5b538af7
commit 3f970689a0
17 changed files with 448 additions and 390 deletions

View File

@@ -2237,229 +2237,6 @@ TEST(NavigationTest, CrossOriginCtrlLeftClickCancel) {
}
namespace {
const char kPopupNavPageUrl[] = "http://tests-popup.com/page.html";
const char kPopupNavPopupUrl[] = "http://tests-popup.com/popup.html";
const char kPopupNavPopupUrl2[] = "http://tests-popup2.com/popup.html";
const char kPopupNavPopupName[] = "my_popup";
// Browser side.
class PopupNavTestHandler : public TestHandler {
public:
enum Mode {
ALLOW,
DENY,
NAVIGATE_AFTER_CREATION,
};
PopupNavTestHandler(Mode mode)
: mode_(mode) {}
void RunTest() override {
// Add the resources that we will navigate to/from.
std::string page = "<html><script>function doPopup() { window.open('" +
std::string(kPopupNavPopupUrl) + "', '" +
std::string(kPopupNavPopupName) +
"'); }</script>Page</html>";
AddResource(kPopupNavPageUrl, page, "text/html");
AddResource(kPopupNavPopupUrl, "<html>Popup</html>", "text/html");
if (mode_ == NAVIGATE_AFTER_CREATION)
AddResource(kPopupNavPopupUrl2, "<html>Popup2</html>", "text/html");
// Create the browser.
CreateBrowser(kPopupNavPageUrl);
// Time out the test after a reasonable period of time.
SetTestTimeout();
}
bool 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,
bool* no_javascript_access) override {
EXPECT_FALSE(got_on_before_popup_);
got_on_before_popup_.yes();
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
EXPECT_EQ(GetBrowserId(), browser->GetIdentifier());
EXPECT_STREQ(kPopupNavPageUrl, frame->GetURL().ToString().c_str());
EXPECT_STREQ(kPopupNavPopupUrl, target_url.ToString().c_str());
EXPECT_STREQ(kPopupNavPopupName, target_frame_name.ToString().c_str());
EXPECT_EQ(WOD_NEW_FOREGROUND_TAB, target_disposition);
EXPECT_FALSE(user_gesture);
EXPECT_FALSE(*no_javascript_access);
return (mode_ == DENY); // Return true to cancel the popup.
}
void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
TestHandler::OnAfterCreated(browser);
if (mode_ == NAVIGATE_AFTER_CREATION && browser->IsPopup()) {
// Navigate to the 2nd popup URL instead of the 1st popup URL.
browser->GetMainFrame()->LoadURL(kPopupNavPopupUrl2);
}
}
void OnLoadStart(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
TransitionType transition_type) override {
const std::string& url = frame->GetURL();
if (url == kPopupNavPageUrl) {
EXPECT_FALSE(got_load_start_);
got_load_start_.yes();
} else if (url == kPopupNavPopupUrl) {
EXPECT_FALSE(got_popup_load_start_);
got_popup_load_start_.yes();
} else if (url == kPopupNavPopupUrl2) {
EXPECT_FALSE(got_popup_load_start2_);
got_popup_load_start2_.yes();
}
}
void OnLoadError(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) override {
if (failedUrl == kPopupNavPageUrl) {
EXPECT_FALSE(got_load_error_);
got_load_error_.yes();
} else if (failedUrl == kPopupNavPopupUrl) {
EXPECT_FALSE(got_popup_load_error_);
got_popup_load_error_.yes();
} else if (failedUrl == kPopupNavPopupUrl2) {
EXPECT_FALSE(got_popup_load_error2_);
got_popup_load_error2_.yes();
}
}
void OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int httpStatusCode) override {
const std::string& url = frame->GetURL();
if (url == kPopupNavPageUrl) {
EXPECT_FALSE(got_load_end_);
got_load_end_.yes();
frame->ExecuteJavaScript("doPopup()", kPopupNavPageUrl, 0);
if (mode_ == DENY) {
// Wait a bit to make sure the popup window isn't created.
CefPostDelayedTask(TID_UI,
base::Bind(&PopupNavTestHandler::DestroyTest, this), 200);
}
} else if (url == kPopupNavPopupUrl) {
EXPECT_FALSE(got_popup_load_end_);
got_popup_load_end_.yes();
if (mode_ != NAVIGATE_AFTER_CREATION) {
if (mode_ != DENY) {
CloseBrowser(browser, false);
DestroyTest();
} else {
EXPECT_FALSE(true); // Not reached.
}
}
} else if (url == kPopupNavPopupUrl2) {
EXPECT_FALSE(got_popup_load_end2_);
got_popup_load_end2_.yes();
if (mode_ == NAVIGATE_AFTER_CREATION) {
CloseBrowser(browser, false);
DestroyTest();
} else {
EXPECT_FALSE(true); // Not reached.
}
} else {
EXPECT_FALSE(true); // Not reached.
}
}
private:
void DestroyTest() override {
EXPECT_TRUE(got_load_start_);
EXPECT_FALSE(got_load_error_);
EXPECT_TRUE(got_load_end_);
EXPECT_TRUE(got_on_before_popup_);
if (mode_ == ALLOW) {
EXPECT_TRUE(got_popup_load_start_);
EXPECT_FALSE(got_popup_load_error_);
EXPECT_TRUE(got_popup_load_end_);
EXPECT_FALSE(got_popup_load_start2_);
EXPECT_FALSE(got_popup_load_error2_);
EXPECT_FALSE(got_popup_load_end2_);
} else if (mode_ == DENY) {
EXPECT_FALSE(got_popup_load_start_);
EXPECT_FALSE(got_popup_load_error_);
EXPECT_FALSE(got_popup_load_end_);
EXPECT_FALSE(got_popup_load_start2_);
EXPECT_FALSE(got_popup_load_error2_);
EXPECT_FALSE(got_popup_load_end2_);
} else if (mode_ == NAVIGATE_AFTER_CREATION) {
EXPECT_FALSE(got_popup_load_start_);
EXPECT_TRUE(got_popup_load_error_);
EXPECT_FALSE(got_popup_load_end_);
EXPECT_TRUE(got_popup_load_start2_);
EXPECT_FALSE(got_popup_load_error2_);
EXPECT_TRUE(got_popup_load_end2_);
}
TestHandler::DestroyTest();
}
const Mode mode_;
TrackCallback got_on_before_popup_;
TrackCallback got_load_start_;
TrackCallback got_load_error_;
TrackCallback got_load_end_;
TrackCallback got_popup_load_start_;
TrackCallback got_popup_load_error_;
TrackCallback got_popup_load_end_;
TrackCallback got_popup_load_start2_;
TrackCallback got_popup_load_error2_;
TrackCallback got_popup_load_end2_;
IMPLEMENT_REFCOUNTING(PopupNavTestHandler);
};
} // namespace
// Test allowing popups.
TEST(NavigationTest, PopupAllow) {
CefRefPtr<PopupNavTestHandler> handler =
new PopupNavTestHandler(PopupNavTestHandler::ALLOW);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
// Test denying popups.
TEST(NavigationTest, PopupDeny) {
CefRefPtr<PopupNavTestHandler> handler =
new PopupNavTestHandler(PopupNavTestHandler::DENY);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
// Test navigation to a different origin after popup creation to verify that
// internal objects are tracked correctly (see issue #1392).
TEST(NavigationTest, PopupNavigateAfterCreation) {
CefRefPtr<PopupNavTestHandler> handler =
new PopupNavTestHandler(PopupNavTestHandler::NAVIGATE_AFTER_CREATION);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
namespace {
const char kSimultPopupMainUrl[] = "http://www.tests-sp.com/main.html";