- Factor platform-specific code out of CefBrowserHostImpl (issue #1749).

- Introduce native/ and osr/ folders for native (non-platform-agnostic) and
    osr (windowless) code respectively.
  - Introduce CefBrowserPlatformDelegate for abstracting platform-specific
    implementations of browser host functionality.
  - Move dialog and menu code to separate manager and platform-specific runner
    implementations exposed via CefBrowserPlatformDelegate.
  - Standardize focus-handling behavior between windowed and windowless
    implementations. CefFocusHandler::OnSetFocus() will now also be called for
    osr focus changes.
- Support multiple simultaneous popups (issue #1289).
This commit is contained in:
Marshall Greenblatt
2015-11-17 13:20:13 -05:00
parent 4b5f052e13
commit 6cccc3b8a7
93 changed files with 6870 additions and 4569 deletions

View File

@@ -2152,6 +2152,275 @@ TEST(NavigationTest, PopupNavigateAfterCreation) {
}
namespace {
const char kSimultPopupMainUrl[] = "http://www.tests-sp.com/main.html";
const char kSimultPopupPopupUrl[] = "http://www.tests-sp.com/popup";
const size_t kSimultPopupCount = 5U;
// Test multiple popups simultaniously.
class PopupSimultaneousTestHandler : public TestHandler {
public:
explicit PopupSimultaneousTestHandler(bool same_url)
: same_url_(same_url),
before_popup_ct_(0U),
after_created_ct_(0U),
before_close_ct_(0U) {}
void RunTest() override {
std::string main_html = "<html><script>\n";
for (size_t i = 0; i < kSimultPopupCount; ++i) {
if (same_url_) {
popup_url_[i] = std::string(kSimultPopupPopupUrl) + ".html";
} else {
std::stringstream ss;
ss << kSimultPopupPopupUrl << i << ".html";
popup_url_[i] = ss.str();
}
main_html += "window.open('" + popup_url_[i] + "');\n";
AddResource(popup_url_[i], "<html>Popup " + popup_url_[i] + "</html>",
"text/html");
}
main_html += "</script></html>";
AddResource(kSimultPopupMainUrl, main_html, "text/html");
// Create the browser.
CreateBrowser(kSimultPopupMainUrl);
// 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 {
const std::string& url = target_url;
EXPECT_LT(before_popup_ct_, kSimultPopupCount);
EXPECT_STREQ(popup_url_[before_popup_ct_].c_str(), url.c_str()) <<
before_popup_ct_;
before_popup_ct_++;
return false;
}
void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
TestHandler::OnAfterCreated(browser);
if (browser->IsPopup()) {
EXPECT_LT(after_created_ct_, kSimultPopupCount);
browser_id_[after_created_ct_] = browser->GetIdentifier();
after_created_ct_++;
}
}
void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
bool isLoading,
bool canGoBack,
bool canGoForward) override {
if (isLoading)
return;
if (browser->IsPopup()) {
const std::string& url = browser->GetMainFrame()->GetURL();
for (size_t i = 0; i < kSimultPopupCount; ++i) {
if (browser->GetIdentifier() == browser_id_[i]) {
EXPECT_STREQ(popup_url_[i].c_str(), url.c_str()) << i;
got_loading_state_change_[i].yes();
browser->GetHost()->CloseBrowser(true);
return;
}
}
EXPECT_FALSE(true); // Not reached.
}
}
void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
TestHandler::OnBeforeClose(browser);
if (browser->IsPopup()) {
const std::string& url = browser->GetMainFrame()->GetURL();
for (size_t i = 0; i < kSimultPopupCount; ++i) {
if (browser->GetIdentifier() == browser_id_[i]) {
EXPECT_STREQ(popup_url_[i].c_str(), url.c_str()) << i;
got_before_close_[i].yes();
if (++before_close_ct_ == kSimultPopupCount)
DestroyTest();
return;
}
}
EXPECT_FALSE(true); // Not reached.
}
}
private:
void DestroyTest() override {
EXPECT_EQ(kSimultPopupCount, before_popup_ct_);
EXPECT_EQ(kSimultPopupCount, after_created_ct_);
EXPECT_EQ(kSimultPopupCount, before_close_ct_);
for (size_t i = 0; i < kSimultPopupCount; ++i) {
EXPECT_GT(browser_id_[i], 0) << i;
EXPECT_TRUE(got_loading_state_change_[i]) << i;
EXPECT_TRUE(got_before_close_[i]) << i;
}
TestHandler::DestroyTest();
}
const bool same_url_;
std::string popup_url_[kSimultPopupCount];
size_t before_popup_ct_;
int browser_id_[kSimultPopupCount];
size_t after_created_ct_;
TrackCallback got_loading_state_change_[kSimultPopupCount];
TrackCallback got_before_close_[kSimultPopupCount];
size_t before_close_ct_;
IMPLEMENT_REFCOUNTING(PopupSimultaneousTestHandler);
};
} // namespace
// Test simultaneous popups with different URLs.
TEST(NavigationTest, PopupSimultaneousDifferentUrl) {
CefRefPtr<PopupSimultaneousTestHandler> handler =
new PopupSimultaneousTestHandler(false);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
// Test simultaneous popups with the same URL.
TEST(NavigationTest, PopupSimultaneousSameUrl) {
CefRefPtr<PopupSimultaneousTestHandler> handler =
new PopupSimultaneousTestHandler(true);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
namespace {
const char kPopupJSOpenMainUrl[] = "http://www.tests-pjso.com/main.html";
const char kPopupJSOpenPopupUrl[] = "http://www.tests-pjso.com/popup.html";
// Test a popup where the URL is a JavaScript URI that opens another popup.
// See comments on CefBrowserInfoManager::FilterPendingPopupURL.
class PopupJSWindowOpenTestHandler : public TestHandler {
public:
PopupJSWindowOpenTestHandler()
: before_popup_ct_(0U),
after_created_ct_(0U),
load_end_ct_(0U),
before_close_ct_(0U) {}
void RunTest() override {
AddResource(kPopupJSOpenMainUrl, "<html>Main</html>", "text/html");
AddResource(kPopupJSOpenPopupUrl, "<html>Popup</html>", "text/html");
// Create the browser.
CreateBrowser(kPopupJSOpenMainUrl);
// 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 {
before_popup_ct_++;
return false;
}
void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
TestHandler::OnAfterCreated(browser);
if (browser->IsPopup())
after_created_ct_++;
}
void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
bool isLoading,
bool canGoBack,
bool canGoForward) override {
if (isLoading)
return;
if (browser->IsPopup()) {
const std::string& url = browser->GetMainFrame()->GetURL();
if (load_end_ct_ == 0)
EXPECT_TRUE(url.empty());
else
EXPECT_STREQ(kPopupJSOpenPopupUrl, url.c_str());
load_end_ct_++;
browser->GetHost()->CloseBrowser(true);
} else if (browser->GetMainFrame()->GetURL() == kPopupJSOpenMainUrl) {
// Load the problematic JS URI.
// This will result in 2 popups being created:
// - An empty popup
// - A popup that loads kPopupJSOpenPopupUrl
browser->GetMainFrame()->LoadURL(
"javascript:window.open(\"javascript:window.open('" +
std::string(kPopupJSOpenPopupUrl) + "')\")");
}
}
void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
TestHandler::OnBeforeClose(browser);
before_close_ct_++;
if (before_close_ct_ == 2U)
DestroyTest();
}
private:
void DestroyTest() override {
EXPECT_EQ(2U, before_popup_ct_);
EXPECT_EQ(2U, after_created_ct_);
EXPECT_EQ(2U, load_end_ct_);
EXPECT_EQ(2U, before_close_ct_);
TestHandler::DestroyTest();
}
size_t before_popup_ct_;
size_t after_created_ct_;
size_t load_end_ct_;
size_t before_close_ct_;
IMPLEMENT_REFCOUNTING(PopupJSWindowOpenTestHandler);
};
} // namespace
// Test a popup where the URL is a JavaScript URI that opens another popup.
TEST(NavigationTest, PopupJSWindowOpen) {
CefRefPtr<PopupJSWindowOpenTestHandler> handler =
new PopupJSWindowOpenTestHandler();
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
namespace {
const char kBrowseNavPageUrl[] = "http://tests-browsenav/nav.html";