mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-02 20:26:59 +01:00
Fix crash when ALT+Clicking invalid protocol link (issue #2306)
This commit is contained in:
parent
f052e282dd
commit
54a015f785
@ -126,10 +126,11 @@ bool CefBrowserContextProxy::IsOffTheRecord() const {
|
|||||||
|
|
||||||
content::DownloadManagerDelegate*
|
content::DownloadManagerDelegate*
|
||||||
CefBrowserContextProxy::GetDownloadManagerDelegate() {
|
CefBrowserContextProxy::GetDownloadManagerDelegate() {
|
||||||
DCHECK(!download_manager_delegate_.get());
|
if (!download_manager_delegate_) {
|
||||||
|
content::DownloadManager* manager =
|
||||||
content::DownloadManager* manager = BrowserContext::GetDownloadManager(this);
|
BrowserContext::GetDownloadManager(this);
|
||||||
download_manager_delegate_.reset(new CefDownloadManagerDelegate(manager));
|
download_manager_delegate_.reset(new CefDownloadManagerDelegate(manager));
|
||||||
|
}
|
||||||
return download_manager_delegate_.get();
|
return download_manager_delegate_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,13 +315,28 @@ void CefDownloadManagerDelegate::OnDownloadDestroyed(DownloadItem* item) {
|
|||||||
|
|
||||||
void CefDownloadManagerDelegate::OnDownloadCreated(DownloadManager* manager,
|
void CefDownloadManagerDelegate::OnDownloadCreated(DownloadManager* manager,
|
||||||
DownloadItem* item) {
|
DownloadItem* item) {
|
||||||
item->AddObserver(this);
|
|
||||||
|
|
||||||
CefBrowserHostImpl* browser = nullptr;
|
CefBrowserHostImpl* browser = nullptr;
|
||||||
content::WebContents* contents = item->GetWebContents();
|
content::WebContents* contents = item->GetWebContents();
|
||||||
if (contents)
|
if (contents) {
|
||||||
browser = CefBrowserHostImpl::GetBrowserForContents(contents).get();
|
browser = CefBrowserHostImpl::GetBrowserForContents(contents).get();
|
||||||
DCHECK(browser);
|
DCHECK(browser);
|
||||||
|
}
|
||||||
|
if (!browser) {
|
||||||
|
// If the download is rejected (e.g. ALT+click on an invalid protocol link)
|
||||||
|
// then an "interrupted" download will be started via DownloadManagerImpl::
|
||||||
|
// StartDownloadWithId (originating from CreateInterruptedDownload) with no
|
||||||
|
// associated WebContents and consequently no associated CEF browser. In
|
||||||
|
// that case DetermineDownloadTarget will be called before this method.
|
||||||
|
// TODO(cef): Figure out how to expose this via a client callback.
|
||||||
|
const std::vector<GURL>& url_chain = item->GetUrlChain();
|
||||||
|
if (!url_chain.empty()) {
|
||||||
|
LOG(INFO) << "Rejected download of " << url_chain.back().spec();
|
||||||
|
}
|
||||||
|
item->Cancel(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
item->AddObserver(this);
|
||||||
|
|
||||||
item_browser_map_.insert(std::make_pair(item, browser));
|
item_browser_map_.insert(std::make_pair(item, browser));
|
||||||
|
|
||||||
@ -399,7 +414,11 @@ CefBrowserHostImpl* CefDownloadManagerDelegate::GetBrowser(DownloadItem* item) {
|
|||||||
if (it != item_browser_map_.end())
|
if (it != item_browser_map_.end())
|
||||||
return it->second;
|
return it->second;
|
||||||
|
|
||||||
// An entry should always exist for a DownloadItem.
|
// If the download is rejected (e.g. ALT+click on an invalid protocol link)
|
||||||
NOTREACHED();
|
// then an "interrupted" download will be started via DownloadManagerImpl::
|
||||||
|
// StartDownloadWithId (originating from CreateInterruptedDownload) with no
|
||||||
|
// associated WebContents and consequently no associated CEF browser. In that
|
||||||
|
// case DetermineDownloadTarget will be called before OnDownloadCreated.
|
||||||
|
DCHECK(!item->GetWebContents());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,14 @@
|
|||||||
#include "include/wrapper/cef_closure_task.h"
|
#include "include/wrapper/cef_closure_task.h"
|
||||||
#include "include/wrapper/cef_scoped_temp_dir.h"
|
#include "include/wrapper/cef_scoped_temp_dir.h"
|
||||||
#include "tests/ceftests/test_handler.h"
|
#include "tests/ceftests/test_handler.h"
|
||||||
|
#include "tests/ceftests/test_util.h"
|
||||||
#include "tests/gtest/include/gtest/gtest.h"
|
#include "tests/gtest/include/gtest/gtest.h"
|
||||||
#include "tests/shared/browser/file_util.h"
|
#include "tests/shared/browser/file_util.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const char kTestDomain[] = "test-download.com";
|
const char kTestDomain[] = "test-download.com";
|
||||||
const char kTestEntryUrl[] = "http://test-download.com/test.html";
|
const char kTestStartUrl[] = "http://test-download.com/test.html";
|
||||||
const char kTestDownloadUrl[] = "http://test-download.com/download.txt";
|
const char kTestDownloadUrl[] = "http://test-download.com/download.txt";
|
||||||
const char kTestNavUrl[] = "http://test-download-nav.com/nav.html";
|
const char kTestNavUrl[] = "http://test-download-nav.com/nav.html";
|
||||||
const char kTestFileName[] = "download_test.txt";
|
const char kTestFileName[] = "download_test.txt";
|
||||||
@ -35,10 +36,7 @@ class DownloadSchemeHandler : public CefResourceHandler {
|
|||||||
bool ProcessRequest(CefRefPtr<CefRequest> request,
|
bool ProcessRequest(CefRefPtr<CefRequest> request,
|
||||||
CefRefPtr<CefCallback> callback) override {
|
CefRefPtr<CefCallback> callback) override {
|
||||||
std::string url = request->GetURL();
|
std::string url = request->GetURL();
|
||||||
if (url == kTestEntryUrl) {
|
if (url == kTestDownloadUrl) {
|
||||||
content_ = "<html><body>Download Test</body></html>";
|
|
||||||
mime_type_ = "text/html";
|
|
||||||
} else if (url == kTestDownloadUrl) {
|
|
||||||
got_download_request_->yes();
|
got_download_request_->yes();
|
||||||
content_ = kTestContent;
|
content_ = kTestContent;
|
||||||
mime_type_ = kTestMimeType;
|
mime_type_ = kTestMimeType;
|
||||||
@ -136,27 +134,48 @@ class DownloadSchemeHandlerFactory : public CefSchemeHandlerFactory {
|
|||||||
class DownloadTestHandler : public TestHandler {
|
class DownloadTestHandler : public TestHandler {
|
||||||
public:
|
public:
|
||||||
enum TestMode {
|
enum TestMode {
|
||||||
NORMAL,
|
PROGAMMATIC,
|
||||||
NAVIGATED,
|
NAVIGATED,
|
||||||
PENDING,
|
PENDING,
|
||||||
|
CLICKED,
|
||||||
|
CLICKED_REJECTED,
|
||||||
};
|
};
|
||||||
|
|
||||||
DownloadTestHandler(TestMode test_mode) : test_mode_(test_mode) {}
|
DownloadTestHandler(TestMode test_mode,
|
||||||
|
TestRequestContextMode rc_mode,
|
||||||
|
const std::string& rc_cache_path)
|
||||||
|
: test_mode_(test_mode),
|
||||||
|
rc_mode_(rc_mode),
|
||||||
|
rc_cache_path_(rc_cache_path) {}
|
||||||
|
|
||||||
|
bool is_clicked() const {
|
||||||
|
return test_mode_ == CLICKED || test_mode_ == CLICKED_REJECTED;
|
||||||
|
}
|
||||||
|
|
||||||
void RunTest() override {
|
void RunTest() override {
|
||||||
DelayCallback delay_callback;
|
DelayCallback delay_callback;
|
||||||
if (test_mode_ == NAVIGATED || test_mode_ == PENDING)
|
if (test_mode_ == NAVIGATED || test_mode_ == PENDING)
|
||||||
delay_callback = base::Bind(&DownloadTestHandler::OnDelayCallback, this);
|
delay_callback = base::Bind(&DownloadTestHandler::OnDelayCallback, this);
|
||||||
|
|
||||||
CefRegisterSchemeHandlerFactory(
|
CefRefPtr<CefSchemeHandlerFactory> scheme_factory =
|
||||||
"http", kTestDomain,
|
|
||||||
new DownloadSchemeHandlerFactory(delay_callback,
|
new DownloadSchemeHandlerFactory(delay_callback,
|
||||||
&got_download_request_));
|
&got_download_request_);
|
||||||
|
|
||||||
// Create a new temporary directory.
|
CefRefPtr<CefRequestContext> request_context =
|
||||||
EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
|
CreateTestRequestContext(rc_mode_, rc_cache_path_);
|
||||||
test_path_ =
|
if (request_context) {
|
||||||
client::file_util::JoinPath(temp_dir_.GetPath(), kTestFileName);
|
request_context->RegisterSchemeHandlerFactory("http", kTestDomain,
|
||||||
|
scheme_factory);
|
||||||
|
} else {
|
||||||
|
CefRegisterSchemeHandlerFactory("http", kTestDomain, scheme_factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test_mode_ != CLICKED_REJECTED) {
|
||||||
|
// Create a new temporary directory.
|
||||||
|
EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
|
||||||
|
test_path_ =
|
||||||
|
client::file_util::JoinPath(temp_dir_.GetPath(), kTestFileName);
|
||||||
|
}
|
||||||
|
|
||||||
if (test_mode_ == NAVIGATED) {
|
if (test_mode_ == NAVIGATED) {
|
||||||
// Add the resource that we'll navigate to.
|
// Add the resource that we'll navigate to.
|
||||||
@ -164,8 +183,26 @@ class DownloadTestHandler : public TestHandler {
|
|||||||
"text/html");
|
"text/html");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_clicked()) {
|
||||||
|
std::string url;
|
||||||
|
if (test_mode_ == CLICKED) {
|
||||||
|
url = kTestDownloadUrl;
|
||||||
|
} else if (test_mode_ == CLICKED_REJECTED) {
|
||||||
|
url = "invalid:foo@example.com";
|
||||||
|
} else {
|
||||||
|
EXPECT_TRUE(false); // Not reached.
|
||||||
|
}
|
||||||
|
AddResource(
|
||||||
|
kTestStartUrl,
|
||||||
|
"<html><body><a href=\"" + url + "\">CLICK ME</a></body></html>",
|
||||||
|
"text/html");
|
||||||
|
} else {
|
||||||
|
AddResource(kTestStartUrl, "<html><body>Download Test</body></html>",
|
||||||
|
"text/html");
|
||||||
|
}
|
||||||
|
|
||||||
// Create the browser
|
// Create the browser
|
||||||
CreateBrowser(kTestEntryUrl);
|
CreateBrowser(kTestStartUrl, request_context);
|
||||||
|
|
||||||
// Time out the test after a reasonable period of time.
|
// Time out the test after a reasonable period of time.
|
||||||
SetTestTimeout();
|
SetTestTimeout();
|
||||||
@ -175,12 +212,27 @@ class DownloadTestHandler : public TestHandler {
|
|||||||
CefRefPtr<CefFrame> frame,
|
CefRefPtr<CefFrame> frame,
|
||||||
int httpStatusCode) override {
|
int httpStatusCode) override {
|
||||||
const std::string& url = frame->GetURL().ToString();
|
const std::string& url = frame->GetURL().ToString();
|
||||||
if (url == kTestEntryUrl) {
|
if (url == kTestNavUrl) {
|
||||||
// Begin the download.
|
|
||||||
browser->GetHost()->StartDownload(kTestDownloadUrl);
|
|
||||||
} else if (url == kTestNavUrl) {
|
|
||||||
got_nav_load_.yes();
|
got_nav_load_.yes();
|
||||||
ContinueNavigatedIfReady();
|
ContinueNavigatedIfReady();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_clicked()) {
|
||||||
|
// Begin the download by clicking a link.
|
||||||
|
// ALT key will trigger download of custom protocol links.
|
||||||
|
SendClick(browser,
|
||||||
|
test_mode_ == CLICKED_REJECTED ? EVENTFLAG_ALT_DOWN : 0);
|
||||||
|
|
||||||
|
if (test_mode_ == CLICKED_REJECTED) {
|
||||||
|
// Destroy the test after a bit because there will be no further
|
||||||
|
// callbacks.
|
||||||
|
CefPostDelayedTask(
|
||||||
|
TID_UI, base::Bind(&DownloadTestHandler::DestroyTest, this), 200);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Begin the download progammatically.
|
||||||
|
browser->GetHost()->StartDownload(kTestDownloadUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,7 +257,7 @@ class DownloadTestHandler : public TestHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ContinueNavigatedIfReady() {
|
void ContinueNavigatedIfReady() {
|
||||||
DCHECK_EQ(test_mode_, NAVIGATED);
|
EXPECT_EQ(test_mode_, NAVIGATED);
|
||||||
if (got_delay_callback_ && got_nav_load_) {
|
if (got_delay_callback_ && got_nav_load_) {
|
||||||
delay_callback_->Continue();
|
delay_callback_->Continue();
|
||||||
delay_callback_ = nullptr;
|
delay_callback_ = nullptr;
|
||||||
@ -213,7 +265,7 @@ class DownloadTestHandler : public TestHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ContinuePendingIfReady() {
|
void ContinuePendingIfReady() {
|
||||||
DCHECK_EQ(test_mode_, PENDING);
|
EXPECT_EQ(test_mode_, PENDING);
|
||||||
if (got_delay_callback_ && got_on_before_download_ &&
|
if (got_delay_callback_ && got_on_before_download_ &&
|
||||||
got_on_download_updated_) {
|
got_on_download_updated_) {
|
||||||
// Destroy the test without waiting for the download to complete.
|
// Destroy the test without waiting for the download to complete.
|
||||||
@ -338,18 +390,30 @@ class DownloadTestHandler : public TestHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CefRegisterSchemeHandlerFactory("http", kTestDomain, NULL);
|
if (request_context_) {
|
||||||
|
request_context_->RegisterSchemeHandlerFactory("http", kTestDomain,
|
||||||
|
nullptr);
|
||||||
|
request_context_ = nullptr;
|
||||||
|
} else {
|
||||||
|
CefRegisterSchemeHandlerFactory("http", kTestDomain, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
EXPECT_TRUE(got_download_request_);
|
if (test_mode_ == CLICKED_REJECTED) {
|
||||||
EXPECT_TRUE(got_on_before_download_);
|
EXPECT_FALSE(got_download_request_);
|
||||||
EXPECT_TRUE(got_on_download_updated_);
|
EXPECT_FALSE(got_on_before_download_);
|
||||||
|
EXPECT_FALSE(got_on_download_updated_);
|
||||||
|
} else {
|
||||||
|
EXPECT_TRUE(got_download_request_);
|
||||||
|
EXPECT_TRUE(got_on_before_download_);
|
||||||
|
EXPECT_TRUE(got_on_download_updated_);
|
||||||
|
}
|
||||||
|
|
||||||
if (test_mode_ == NAVIGATED)
|
if (test_mode_ == NAVIGATED)
|
||||||
EXPECT_TRUE(got_nav_load_);
|
EXPECT_TRUE(got_nav_load_);
|
||||||
else
|
else
|
||||||
EXPECT_FALSE(got_nav_load_);
|
EXPECT_FALSE(got_nav_load_);
|
||||||
|
|
||||||
if (test_mode_ == PENDING) {
|
if (test_mode_ == PENDING || test_mode_ == CLICKED_REJECTED) {
|
||||||
EXPECT_FALSE(got_download_complete_);
|
EXPECT_FALSE(got_download_complete_);
|
||||||
EXPECT_FALSE(got_full_path_);
|
EXPECT_FALSE(got_full_path_);
|
||||||
} else {
|
} else {
|
||||||
@ -361,7 +425,21 @@ class DownloadTestHandler : public TestHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void SendClick(CefRefPtr<CefBrowser> browser, uint32_t modifiers) {
|
||||||
|
EXPECT_TRUE(is_clicked());
|
||||||
|
CefMouseEvent mouse_event;
|
||||||
|
mouse_event.x = 20;
|
||||||
|
mouse_event.y = 20;
|
||||||
|
mouse_event.modifiers = modifiers;
|
||||||
|
browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1);
|
||||||
|
browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT, true, 1);
|
||||||
|
}
|
||||||
|
|
||||||
const TestMode test_mode_;
|
const TestMode test_mode_;
|
||||||
|
const TestRequestContextMode rc_mode_;
|
||||||
|
const std::string rc_cache_path_;
|
||||||
|
|
||||||
|
CefRefPtr<CefRequestContext> request_context_;
|
||||||
|
|
||||||
// Used with NAVIGATED test mode.
|
// Used with NAVIGATED test mode.
|
||||||
CefRefPtr<CefCallback> delay_callback_;
|
CefRefPtr<CefCallback> delay_callback_;
|
||||||
@ -383,26 +461,21 @@ class DownloadTestHandler : public TestHandler {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// Test a basic download.
|
#define DOWNLOAD_TEST_GROUP(test_name, test_mode) \
|
||||||
TEST(DownloadTest, Download) {
|
RC_TEST_GROUP_ALL(DownloadTest, test_name, DownloadTestHandler, test_mode)
|
||||||
CefRefPtr<DownloadTestHandler> handler =
|
|
||||||
new DownloadTestHandler(DownloadTestHandler::NORMAL);
|
// Test a programmatic download.
|
||||||
handler->ExecuteTest();
|
DOWNLOAD_TEST_GROUP(Programmatic, PROGAMMATIC);
|
||||||
ReleaseAndWaitForDestructor(handler);
|
|
||||||
}
|
// Test a clicked download.
|
||||||
|
DOWNLOAD_TEST_GROUP(Clicked, CLICKED);
|
||||||
|
|
||||||
|
// Test a clicked download where the protocol is invalid and therefore rejected.
|
||||||
|
// There will be no resulting CefDownloadHandler callbacks.
|
||||||
|
DOWNLOAD_TEST_GROUP(ClickedRejected, CLICKED_REJECTED);
|
||||||
|
|
||||||
// Test where the download completes after cross-origin navigation.
|
// Test where the download completes after cross-origin navigation.
|
||||||
TEST(DownloadTest, DownloadNavigated) {
|
DOWNLOAD_TEST_GROUP(Navigated, NAVIGATED);
|
||||||
CefRefPtr<DownloadTestHandler> handler =
|
|
||||||
new DownloadTestHandler(DownloadTestHandler::NAVIGATED);
|
|
||||||
handler->ExecuteTest();
|
|
||||||
ReleaseAndWaitForDestructor(handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test where the download is still pending when the browser is destroyed.
|
// Test where the download is still pending when the browser is destroyed.
|
||||||
TEST(DownloadTest, DownloadPending) {
|
DOWNLOAD_TEST_GROUP(Pending, PENDING);
|
||||||
CefRefPtr<DownloadTestHandler> handler =
|
|
||||||
new DownloadTestHandler(DownloadTestHandler::PENDING);
|
|
||||||
handler->ExecuteTest();
|
|
||||||
ReleaseAndWaitForDestructor(handler);
|
|
||||||
}
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "include/wrapper/cef_closure_task.h"
|
#include "include/wrapper/cef_closure_task.h"
|
||||||
#include "include/wrapper/cef_scoped_temp_dir.h"
|
#include "include/wrapper/cef_scoped_temp_dir.h"
|
||||||
#include "tests/ceftests/test_handler.h"
|
#include "tests/ceftests/test_handler.h"
|
||||||
|
#include "tests/ceftests/test_util.h"
|
||||||
#include "tests/gtest/include/gtest/gtest.h"
|
#include "tests/gtest/include/gtest/gtest.h"
|
||||||
|
|
||||||
TEST(RequestContextTest, GetGlobalContext) {
|
TEST(RequestContextTest, GetGlobalContext) {
|
||||||
@ -608,7 +609,7 @@ const char kPopupNavPopupName[] = "my_popup";
|
|||||||
// Browser side.
|
// Browser side.
|
||||||
class PopupNavTestHandler : public TestHandler {
|
class PopupNavTestHandler : public TestHandler {
|
||||||
public:
|
public:
|
||||||
enum Mode {
|
enum TestMode {
|
||||||
ALLOW_CLOSE_POPUP_FIRST,
|
ALLOW_CLOSE_POPUP_FIRST,
|
||||||
ALLOW_CLOSE_POPUP_LAST,
|
ALLOW_CLOSE_POPUP_LAST,
|
||||||
DENY,
|
DENY,
|
||||||
@ -620,14 +621,11 @@ class PopupNavTestHandler : public TestHandler {
|
|||||||
DESTROY_PARENT_AFTER_CREATION,
|
DESTROY_PARENT_AFTER_CREATION,
|
||||||
DESTROY_PARENT_AFTER_CREATION_FORCE,
|
DESTROY_PARENT_AFTER_CREATION_FORCE,
|
||||||
};
|
};
|
||||||
enum RCMode {
|
|
||||||
RC_MODE_NONE,
|
|
||||||
RC_MODE_IMPL,
|
|
||||||
RC_MODE_PROXY,
|
|
||||||
};
|
|
||||||
|
|
||||||
PopupNavTestHandler(Mode mode, RCMode rc_mode)
|
PopupNavTestHandler(TestMode test_mode,
|
||||||
: mode_(mode), rc_mode_(rc_mode) {}
|
TestRequestContextMode rc_mode,
|
||||||
|
const std::string& rc_cache_path)
|
||||||
|
: mode_(test_mode), rc_mode_(rc_mode), rc_cache_path_(rc_cache_path) {}
|
||||||
|
|
||||||
void RunTest() override {
|
void RunTest() override {
|
||||||
// Add the resources that we will navigate to/from.
|
// Add the resources that we will navigate to/from.
|
||||||
@ -640,23 +638,8 @@ class PopupNavTestHandler : public TestHandler {
|
|||||||
if (mode_ == NAVIGATE_AFTER_CREATION)
|
if (mode_ == NAVIGATE_AFTER_CREATION)
|
||||||
AddResource(kPopupNavPopupUrl2, "<html>Popup2</html>", "text/html");
|
AddResource(kPopupNavPopupUrl2, "<html>Popup2</html>", "text/html");
|
||||||
|
|
||||||
CefRefPtr<CefRequestContext> request_context;
|
CefRefPtr<CefRequestContext> request_context =
|
||||||
CefRefPtr<CefRequestContextHandler> rc_handler;
|
CreateTestRequestContext(rc_mode_, rc_cache_path_);
|
||||||
if (rc_mode_ == RC_MODE_PROXY) {
|
|
||||||
class Handler : public CefRequestContextHandler {
|
|
||||||
public:
|
|
||||||
Handler() {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
IMPLEMENT_REFCOUNTING(Handler);
|
|
||||||
};
|
|
||||||
rc_handler = new Handler();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc_mode_ != RC_MODE_NONE) {
|
|
||||||
CefRequestContextSettings settings;
|
|
||||||
request_context = CefRequestContext::CreateContext(settings, rc_handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the browser.
|
// Create the browser.
|
||||||
CreateBrowser(kPopupNavPageUrl, request_context);
|
CreateBrowser(kPopupNavPageUrl, request_context);
|
||||||
@ -872,8 +855,9 @@ class PopupNavTestHandler : public TestHandler {
|
|||||||
TestHandler::DestroyTest();
|
TestHandler::DestroyTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Mode mode_;
|
const TestMode mode_;
|
||||||
const RCMode rc_mode_;
|
const TestRequestContextMode rc_mode_;
|
||||||
|
const std::string rc_cache_path_;
|
||||||
|
|
||||||
TrackCallback got_on_before_popup_;
|
TrackCallback got_on_before_popup_;
|
||||||
TrackCallback got_load_start_;
|
TrackCallback got_load_start_;
|
||||||
@ -890,36 +874,28 @@ class PopupNavTestHandler : public TestHandler {
|
|||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
#define POPUP_TEST_GROUP(test_name, test_mode) \
|
||||||
#define POPUP_TEST(name, test_mode, rc_mode) \
|
RC_TEST_GROUP_IN_MEMORY(RequestContextTest, Popup##test_name, \
|
||||||
TEST(RequestContextTest, Popup##name) { \
|
PopupNavTestHandler, test_mode)
|
||||||
CefRefPtr<PopupNavTestHandler> handler = new PopupNavTestHandler( \
|
|
||||||
PopupNavTestHandler::test_mode, PopupNavTestHandler::rc_mode); \
|
|
||||||
handler->ExecuteTest(); \
|
|
||||||
ReleaseAndWaitForDestructor(handler); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define POPUP_TEST_GROUP(name, test_mode) \
|
|
||||||
POPUP_TEST(name##RCNone, test_mode, RC_MODE_NONE); \
|
|
||||||
POPUP_TEST(name##RCImpl, test_mode, RC_MODE_IMPL); \
|
|
||||||
POPUP_TEST(name##RCProxy, test_mode, RC_MODE_PROXY);
|
|
||||||
|
|
||||||
// Test allowing popups and closing the popup browser first.
|
// Test allowing popups and closing the popup browser first.
|
||||||
POPUP_TEST_GROUP(AllowClosePopupFirst, ALLOW_CLOSE_POPUP_FIRST);
|
POPUP_TEST_GROUP(AllowClosePopupFirst, ALLOW_CLOSE_POPUP_FIRST);
|
||||||
|
|
||||||
// Test allowing popups and closing the main browser first to verify that
|
// Test allowing popups and closing the main browser first to verify
|
||||||
// internal objects are tracked correctly (see issue #2162).
|
// that internal objects are tracked correctly (see issue #2162).
|
||||||
POPUP_TEST_GROUP(AllowClosePopupLast, ALLOW_CLOSE_POPUP_LAST);
|
POPUP_TEST_GROUP(AllowClosePopupLast, ALLOW_CLOSE_POPUP_LAST);
|
||||||
|
|
||||||
// Test denying popups.
|
// Test denying popups.
|
||||||
POPUP_TEST_GROUP(Deny, DENY);
|
POPUP_TEST_GROUP(Deny, DENY);
|
||||||
|
|
||||||
// Test navigation to a different origin after popup creation to verify that
|
// Test navigation to a different origin after popup creation to
|
||||||
// internal objects are tracked correctly (see issue #1392).
|
// verify that internal objects are tracked correctly (see issue
|
||||||
|
// #1392).
|
||||||
POPUP_TEST_GROUP(NavigateAfterCreation, NAVIGATE_AFTER_CREATION);
|
POPUP_TEST_GROUP(NavigateAfterCreation, NAVIGATE_AFTER_CREATION);
|
||||||
|
|
||||||
// Test destroying the parent browser during or immediately after popup creation
|
// Test destroying the parent browser during or immediately after
|
||||||
// to verify that internal objects are tracked correctly (see issue #2041).
|
// popup creation to verify that internal objects are tracked
|
||||||
|
// correctly (see issue #2041).
|
||||||
POPUP_TEST_GROUP(DestroyParentBeforeCreation, DESTROY_PARENT_BEFORE_CREATION);
|
POPUP_TEST_GROUP(DestroyParentBeforeCreation, DESTROY_PARENT_BEFORE_CREATION);
|
||||||
POPUP_TEST_GROUP(DestroyParentBeforeCreationForce,
|
POPUP_TEST_GROUP(DestroyParentBeforeCreationForce,
|
||||||
DESTROY_PARENT_BEFORE_CREATION_FORCE);
|
DESTROY_PARENT_BEFORE_CREATION_FORCE);
|
||||||
@ -1058,7 +1034,8 @@ class MethodTestHandler : public TestHandler {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// Test CefRequestContext::ClearCertificateExceptions with the global context.
|
// Test CefRequestContext::ClearCertificateExceptions with the global
|
||||||
|
// context.
|
||||||
TEST(RequestContextTest, ClearCertificateExceptionsGlobal) {
|
TEST(RequestContextTest, ClearCertificateExceptionsGlobal) {
|
||||||
CefRefPtr<MethodTestHandler> handler = new MethodTestHandler(
|
CefRefPtr<MethodTestHandler> handler = new MethodTestHandler(
|
||||||
true, MethodTestHandler::METHOD_CLEAR_CERTIFICATE_EXCEPTIONS);
|
true, MethodTestHandler::METHOD_CLEAR_CERTIFICATE_EXCEPTIONS);
|
||||||
@ -1066,7 +1043,8 @@ TEST(RequestContextTest, ClearCertificateExceptionsGlobal) {
|
|||||||
ReleaseAndWaitForDestructor(handler);
|
ReleaseAndWaitForDestructor(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test CefRequestContext::ClearCertificateExceptions with a custom context.
|
// Test CefRequestContext::ClearCertificateExceptions with a custom
|
||||||
|
// context.
|
||||||
TEST(RequestContextTest, ClearCertificateExceptionsCustom) {
|
TEST(RequestContextTest, ClearCertificateExceptionsCustom) {
|
||||||
CefRefPtr<MethodTestHandler> handler = new MethodTestHandler(
|
CefRefPtr<MethodTestHandler> handler = new MethodTestHandler(
|
||||||
false, MethodTestHandler::METHOD_CLEAR_CERTIFICATE_EXCEPTIONS);
|
false, MethodTestHandler::METHOD_CLEAR_CERTIFICATE_EXCEPTIONS);
|
||||||
@ -1074,7 +1052,8 @@ TEST(RequestContextTest, ClearCertificateExceptionsCustom) {
|
|||||||
ReleaseAndWaitForDestructor(handler);
|
ReleaseAndWaitForDestructor(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test CefRequestContext::CloseAllConnections with the global context.
|
// Test CefRequestContext::CloseAllConnections with the global
|
||||||
|
// context.
|
||||||
TEST(RequestContextTest, CloseAllConnectionsGlobal) {
|
TEST(RequestContextTest, CloseAllConnectionsGlobal) {
|
||||||
CefRefPtr<MethodTestHandler> handler = new MethodTestHandler(
|
CefRefPtr<MethodTestHandler> handler = new MethodTestHandler(
|
||||||
true, MethodTestHandler::METHOD_CLOSE_ALL_CONNECTIONS);
|
true, MethodTestHandler::METHOD_CLOSE_ALL_CONNECTIONS);
|
||||||
|
@ -261,3 +261,39 @@ void TestStringVectorEqual(const std::vector<CefString>& val1,
|
|||||||
for (size_t i = 0; i < val1.size(); ++i)
|
for (size_t i = 0; i < val1.size(); ++i)
|
||||||
EXPECT_STREQ(val1[i].ToString().c_str(), val2[i].ToString().c_str());
|
EXPECT_STREQ(val1[i].ToString().c_str(), val2[i].ToString().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CefRefPtr<CefRequestContext> CreateTestRequestContext(
|
||||||
|
TestRequestContextMode mode,
|
||||||
|
const std::string& cache_path) {
|
||||||
|
EXPECT_TRUE(cache_path.empty() || mode == TEST_RC_MODE_CUSTOM ||
|
||||||
|
mode == TEST_RC_MODE_CUSTOM_WITH_HANDLER);
|
||||||
|
|
||||||
|
if (mode == TEST_RC_MODE_NONE)
|
||||||
|
return nullptr;
|
||||||
|
if (mode == TEST_RC_MODE_GLOBAL)
|
||||||
|
return CefRequestContext::GetGlobalContext();
|
||||||
|
|
||||||
|
CefRefPtr<CefRequestContextHandler> rc_handler;
|
||||||
|
if (mode == TEST_RC_MODE_GLOBAL_WITH_HANDLER ||
|
||||||
|
mode == TEST_RC_MODE_CUSTOM_WITH_HANDLER) {
|
||||||
|
class Handler : public CefRequestContextHandler {
|
||||||
|
public:
|
||||||
|
Handler() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
IMPLEMENT_REFCOUNTING(Handler);
|
||||||
|
};
|
||||||
|
rc_handler = new Handler();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == TEST_RC_MODE_CUSTOM || mode == TEST_RC_MODE_CUSTOM_WITH_HANDLER) {
|
||||||
|
CefRequestContextSettings settings;
|
||||||
|
if (!cache_path.empty())
|
||||||
|
CefString(&settings.cache_path) = cache_path;
|
||||||
|
return CefRequestContext::CreateContext(settings, rc_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_EQ(mode, TEST_RC_MODE_GLOBAL_WITH_HANDLER);
|
||||||
|
return CefRequestContext::CreateContext(CefRequestContext::GetGlobalContext(),
|
||||||
|
rc_handler);
|
||||||
|
}
|
||||||
|
@ -8,8 +8,10 @@
|
|||||||
|
|
||||||
#include "include/cef_process_message.h"
|
#include "include/cef_process_message.h"
|
||||||
#include "include/cef_request.h"
|
#include "include/cef_request.h"
|
||||||
|
#include "include/cef_request_context.h"
|
||||||
#include "include/cef_response.h"
|
#include "include/cef_response.h"
|
||||||
#include "include/cef_values.h"
|
#include "include/cef_values.h"
|
||||||
|
#include "tests/ceftests/test_suite.h"
|
||||||
|
|
||||||
// Test that CefRequest::HeaderMap objects are equal
|
// Test that CefRequest::HeaderMap objects are equal
|
||||||
// If |allowExtras| is true then additional header fields will be allowed in
|
// If |allowExtras| is true then additional header fields will be allowed in
|
||||||
@ -62,4 +64,116 @@ void TestProcessMessageEqual(CefRefPtr<CefProcessMessage> val1,
|
|||||||
void TestStringVectorEqual(const std::vector<CefString>& val1,
|
void TestStringVectorEqual(const std::vector<CefString>& val1,
|
||||||
const std::vector<CefString>& val2);
|
const std::vector<CefString>& val2);
|
||||||
|
|
||||||
|
enum TestRequestContextMode {
|
||||||
|
TEST_RC_MODE_NONE,
|
||||||
|
TEST_RC_MODE_GLOBAL,
|
||||||
|
TEST_RC_MODE_GLOBAL_WITH_HANDLER,
|
||||||
|
TEST_RC_MODE_CUSTOM,
|
||||||
|
TEST_RC_MODE_CUSTOM_WITH_HANDLER,
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool IsTestRequestContextModeCustom(TestRequestContextMode mode) {
|
||||||
|
return mode == TEST_RC_MODE_CUSTOM ||
|
||||||
|
mode == TEST_RC_MODE_CUSTOM_WITH_HANDLER;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a RequestContext object matching the specified |mode|.
|
||||||
|
// |cache_path| may be specified for CUSTOM modes.
|
||||||
|
// Use the RC_TEST_GROUP_BASE macro to test all valid combinations.
|
||||||
|
CefRefPtr<CefRequestContext> CreateTestRequestContext(
|
||||||
|
TestRequestContextMode mode,
|
||||||
|
const std::string& cache_path);
|
||||||
|
|
||||||
|
// Helper macro for testing a single RequestContextMode value.
|
||||||
|
// See RC_TEST_GROUP_ALL documentation for example usage.
|
||||||
|
#define RC_TEST_BASE(test_case_name, test_name, test_class, test_mode, \
|
||||||
|
rc_mode, with_cache_path) \
|
||||||
|
TEST(test_case_name, test_name) { \
|
||||||
|
CefScopedTempDir scoped_temp_dir; \
|
||||||
|
std::string cache_path; \
|
||||||
|
if (with_cache_path) { \
|
||||||
|
EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDir()); \
|
||||||
|
cache_path = scoped_temp_dir.GetPath(); \
|
||||||
|
} \
|
||||||
|
CefRefPtr<test_class> handler = \
|
||||||
|
new test_class(test_class::test_mode, rc_mode, cache_path); \
|
||||||
|
handler->ExecuteTest(); \
|
||||||
|
ReleaseAndWaitForDestructor(handler); \
|
||||||
|
if (!scoped_temp_dir.IsEmpty()) { \
|
||||||
|
CefTestSuite::GetInstance()->RegisterTempDirectory( \
|
||||||
|
scoped_temp_dir.Take()); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequestContextModes that operate in memory.
|
||||||
|
#define RC_TEST_GROUP_IN_MEMORY(test_case_name, test_name, test_class, \
|
||||||
|
test_mode) \
|
||||||
|
RC_TEST_BASE(test_case_name, test_name##RCNone, test_class, test_mode, \
|
||||||
|
TEST_RC_MODE_NONE, false); \
|
||||||
|
RC_TEST_BASE(test_case_name, test_name##RCGlobal, test_class, test_mode, \
|
||||||
|
TEST_RC_MODE_GLOBAL, false); \
|
||||||
|
RC_TEST_BASE(test_case_name, test_name##RCGlobalWithHandler, test_class, \
|
||||||
|
test_mode, TEST_RC_MODE_GLOBAL_WITH_HANDLER, false); \
|
||||||
|
RC_TEST_BASE(test_case_name, test_name##RCCustomInMemory, test_class, \
|
||||||
|
test_mode, TEST_RC_MODE_CUSTOM, false); \
|
||||||
|
RC_TEST_BASE(test_case_name, test_name##RCCustomInMemoryWithHandler, \
|
||||||
|
test_class, test_mode, TEST_RC_MODE_CUSTOM_WITH_HANDLER, \
|
||||||
|
false);
|
||||||
|
|
||||||
|
// RequestContextModes that operate on disk.
|
||||||
|
#define RC_TEST_GROUP_ON_DISK(test_case_name, test_name, test_class, \
|
||||||
|
test_mode) \
|
||||||
|
RC_TEST_BASE(test_case_name, test_name##RCCustomOnDisk, test_class, \
|
||||||
|
test_mode, TEST_RC_MODE_CUSTOM, true); \
|
||||||
|
RC_TEST_BASE(test_case_name, test_name##RCCustomOnDiskWithHandler, \
|
||||||
|
test_class, test_mode, TEST_RC_MODE_CUSTOM_WITH_HANDLER, true);
|
||||||
|
|
||||||
|
// Helper macro for testing all valid combinations of RequestContextMode values.
|
||||||
|
// For example:
|
||||||
|
//
|
||||||
|
// // Test handler implementation.
|
||||||
|
// class MyTestHandler : public TestHandler {
|
||||||
|
// public:
|
||||||
|
// // Test modes supported by MyTestHandler.
|
||||||
|
// enum TestMode {
|
||||||
|
// FIRST,
|
||||||
|
// SECOND,
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// // Constructor always accepts three arguments.
|
||||||
|
// MyTestHandler(TestMode test_mode,
|
||||||
|
// TestRequestContextMode rc_mode,
|
||||||
|
// const std::string& rc_cache_path)
|
||||||
|
// : test_mode_(test_mode), rc_mode_(rc_mode),
|
||||||
|
// rc_cache_path_(rc_cache_path) {}
|
||||||
|
//
|
||||||
|
// void RunTest() override {
|
||||||
|
// // Create a RequestContext with the specified attributes.
|
||||||
|
// CefRefPtr<CefRequestContext> request_context =
|
||||||
|
// CreateTestRequestContext(rc_mode_, rc_cache_path_);
|
||||||
|
//
|
||||||
|
// // Do something with |test_mode_| and |request_context|...
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private:
|
||||||
|
// const TestMode test_mode_;
|
||||||
|
// const TestRequestContextMode rc_mode_;
|
||||||
|
// const std::string rc_cache_path_;
|
||||||
|
//
|
||||||
|
// IMPLEMENT_REFCOUNTING(MyTestHandler);
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// // Helper macro for defining tests using MyTestHandler.
|
||||||
|
// #define MY_TEST_GROUP(test_name, test_mode) \
|
||||||
|
// RC_TEST_GROUP_ALL(MyTest, test_name, MyTestHandler, test_mode)
|
||||||
|
//
|
||||||
|
// // Implementation for MyTest.First* tests.
|
||||||
|
// MY_TEST_GROUP(First, FIRST);
|
||||||
|
// // Implementation for MyTest.Second* tests.
|
||||||
|
// MY_TEST_GROUP(Second, SECOND);
|
||||||
|
//
|
||||||
|
#define RC_TEST_GROUP_ALL(test_case_name, test_name, test_class, test_mode) \
|
||||||
|
RC_TEST_GROUP_IN_MEMORY(test_case_name, test_name, test_class, test_mode) \
|
||||||
|
RC_TEST_GROUP_ON_DISK(test_case_name, test_name, test_class, test_mode)
|
||||||
|
|
||||||
#endif // CEF_TESTS_UNITTESTS_TEST_UTIL_H_
|
#endif // CEF_TESTS_UNITTESTS_TEST_UTIL_H_
|
||||||
|
Loading…
x
Reference in New Issue
Block a user