mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-02 12:17:15 +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*
|
||||
CefBrowserContextProxy::GetDownloadManagerDelegate() {
|
||||
DCHECK(!download_manager_delegate_.get());
|
||||
|
||||
content::DownloadManager* manager = BrowserContext::GetDownloadManager(this);
|
||||
download_manager_delegate_.reset(new CefDownloadManagerDelegate(manager));
|
||||
if (!download_manager_delegate_) {
|
||||
content::DownloadManager* manager =
|
||||
BrowserContext::GetDownloadManager(this);
|
||||
download_manager_delegate_.reset(new CefDownloadManagerDelegate(manager));
|
||||
}
|
||||
return download_manager_delegate_.get();
|
||||
}
|
||||
|
||||
|
@ -315,13 +315,28 @@ void CefDownloadManagerDelegate::OnDownloadDestroyed(DownloadItem* item) {
|
||||
|
||||
void CefDownloadManagerDelegate::OnDownloadCreated(DownloadManager* manager,
|
||||
DownloadItem* item) {
|
||||
item->AddObserver(this);
|
||||
|
||||
CefBrowserHostImpl* browser = nullptr;
|
||||
content::WebContents* contents = item->GetWebContents();
|
||||
if (contents)
|
||||
if (contents) {
|
||||
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));
|
||||
|
||||
@ -399,7 +414,11 @@ CefBrowserHostImpl* CefDownloadManagerDelegate::GetBrowser(DownloadItem* item) {
|
||||
if (it != item_browser_map_.end())
|
||||
return it->second;
|
||||
|
||||
// An entry should always exist for a DownloadItem.
|
||||
NOTREACHED();
|
||||
// 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 OnDownloadCreated.
|
||||
DCHECK(!item->GetWebContents());
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -6,13 +6,14 @@
|
||||
#include "include/wrapper/cef_closure_task.h"
|
||||
#include "include/wrapper/cef_scoped_temp_dir.h"
|
||||
#include "tests/ceftests/test_handler.h"
|
||||
#include "tests/ceftests/test_util.h"
|
||||
#include "tests/gtest/include/gtest/gtest.h"
|
||||
#include "tests/shared/browser/file_util.h"
|
||||
|
||||
namespace {
|
||||
|
||||
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 kTestNavUrl[] = "http://test-download-nav.com/nav.html";
|
||||
const char kTestFileName[] = "download_test.txt";
|
||||
@ -35,10 +36,7 @@ class DownloadSchemeHandler : public CefResourceHandler {
|
||||
bool ProcessRequest(CefRefPtr<CefRequest> request,
|
||||
CefRefPtr<CefCallback> callback) override {
|
||||
std::string url = request->GetURL();
|
||||
if (url == kTestEntryUrl) {
|
||||
content_ = "<html><body>Download Test</body></html>";
|
||||
mime_type_ = "text/html";
|
||||
} else if (url == kTestDownloadUrl) {
|
||||
if (url == kTestDownloadUrl) {
|
||||
got_download_request_->yes();
|
||||
content_ = kTestContent;
|
||||
mime_type_ = kTestMimeType;
|
||||
@ -136,27 +134,48 @@ class DownloadSchemeHandlerFactory : public CefSchemeHandlerFactory {
|
||||
class DownloadTestHandler : public TestHandler {
|
||||
public:
|
||||
enum TestMode {
|
||||
NORMAL,
|
||||
PROGAMMATIC,
|
||||
NAVIGATED,
|
||||
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 {
|
||||
DelayCallback delay_callback;
|
||||
if (test_mode_ == NAVIGATED || test_mode_ == PENDING)
|
||||
delay_callback = base::Bind(&DownloadTestHandler::OnDelayCallback, this);
|
||||
|
||||
CefRegisterSchemeHandlerFactory(
|
||||
"http", kTestDomain,
|
||||
CefRefPtr<CefSchemeHandlerFactory> scheme_factory =
|
||||
new DownloadSchemeHandlerFactory(delay_callback,
|
||||
&got_download_request_));
|
||||
&got_download_request_);
|
||||
|
||||
// Create a new temporary directory.
|
||||
EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
|
||||
test_path_ =
|
||||
client::file_util::JoinPath(temp_dir_.GetPath(), kTestFileName);
|
||||
CefRefPtr<CefRequestContext> request_context =
|
||||
CreateTestRequestContext(rc_mode_, rc_cache_path_);
|
||||
if (request_context) {
|
||||
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) {
|
||||
// Add the resource that we'll navigate to.
|
||||
@ -164,8 +183,26 @@ class DownloadTestHandler : public TestHandler {
|
||||
"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
|
||||
CreateBrowser(kTestEntryUrl);
|
||||
CreateBrowser(kTestStartUrl, request_context);
|
||||
|
||||
// Time out the test after a reasonable period of time.
|
||||
SetTestTimeout();
|
||||
@ -175,12 +212,27 @@ class DownloadTestHandler : public TestHandler {
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int httpStatusCode) override {
|
||||
const std::string& url = frame->GetURL().ToString();
|
||||
if (url == kTestEntryUrl) {
|
||||
// Begin the download.
|
||||
browser->GetHost()->StartDownload(kTestDownloadUrl);
|
||||
} else if (url == kTestNavUrl) {
|
||||
if (url == kTestNavUrl) {
|
||||
got_nav_load_.yes();
|
||||
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() {
|
||||
DCHECK_EQ(test_mode_, NAVIGATED);
|
||||
EXPECT_EQ(test_mode_, NAVIGATED);
|
||||
if (got_delay_callback_ && got_nav_load_) {
|
||||
delay_callback_->Continue();
|
||||
delay_callback_ = nullptr;
|
||||
@ -213,7 +265,7 @@ class DownloadTestHandler : public TestHandler {
|
||||
}
|
||||
|
||||
void ContinuePendingIfReady() {
|
||||
DCHECK_EQ(test_mode_, PENDING);
|
||||
EXPECT_EQ(test_mode_, PENDING);
|
||||
if (got_delay_callback_ && got_on_before_download_ &&
|
||||
got_on_download_updated_) {
|
||||
// Destroy the test without waiting for the download to complete.
|
||||
@ -338,18 +390,30 @@ class DownloadTestHandler : public TestHandler {
|
||||
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_);
|
||||
EXPECT_TRUE(got_on_before_download_);
|
||||
EXPECT_TRUE(got_on_download_updated_);
|
||||
if (test_mode_ == CLICKED_REJECTED) {
|
||||
EXPECT_FALSE(got_download_request_);
|
||||
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)
|
||||
EXPECT_TRUE(got_nav_load_);
|
||||
else
|
||||
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_full_path_);
|
||||
} else {
|
||||
@ -361,7 +425,21 @@ class DownloadTestHandler : public TestHandler {
|
||||
}
|
||||
|
||||
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 TestRequestContextMode rc_mode_;
|
||||
const std::string rc_cache_path_;
|
||||
|
||||
CefRefPtr<CefRequestContext> request_context_;
|
||||
|
||||
// Used with NAVIGATED test mode.
|
||||
CefRefPtr<CefCallback> delay_callback_;
|
||||
@ -383,26 +461,21 @@ class DownloadTestHandler : public TestHandler {
|
||||
|
||||
} // namespace
|
||||
|
||||
// Test a basic download.
|
||||
TEST(DownloadTest, Download) {
|
||||
CefRefPtr<DownloadTestHandler> handler =
|
||||
new DownloadTestHandler(DownloadTestHandler::NORMAL);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
#define DOWNLOAD_TEST_GROUP(test_name, test_mode) \
|
||||
RC_TEST_GROUP_ALL(DownloadTest, test_name, DownloadTestHandler, test_mode)
|
||||
|
||||
// Test a programmatic download.
|
||||
DOWNLOAD_TEST_GROUP(Programmatic, PROGAMMATIC);
|
||||
|
||||
// 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(DownloadTest, DownloadNavigated) {
|
||||
CefRefPtr<DownloadTestHandler> handler =
|
||||
new DownloadTestHandler(DownloadTestHandler::NAVIGATED);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
DOWNLOAD_TEST_GROUP(Navigated, NAVIGATED);
|
||||
|
||||
// Test where the download is still pending when the browser is destroyed.
|
||||
TEST(DownloadTest, DownloadPending) {
|
||||
CefRefPtr<DownloadTestHandler> handler =
|
||||
new DownloadTestHandler(DownloadTestHandler::PENDING);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
DOWNLOAD_TEST_GROUP(Pending, PENDING);
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "include/wrapper/cef_closure_task.h"
|
||||
#include "include/wrapper/cef_scoped_temp_dir.h"
|
||||
#include "tests/ceftests/test_handler.h"
|
||||
#include "tests/ceftests/test_util.h"
|
||||
#include "tests/gtest/include/gtest/gtest.h"
|
||||
|
||||
TEST(RequestContextTest, GetGlobalContext) {
|
||||
@ -608,7 +609,7 @@ const char kPopupNavPopupName[] = "my_popup";
|
||||
// Browser side.
|
||||
class PopupNavTestHandler : public TestHandler {
|
||||
public:
|
||||
enum Mode {
|
||||
enum TestMode {
|
||||
ALLOW_CLOSE_POPUP_FIRST,
|
||||
ALLOW_CLOSE_POPUP_LAST,
|
||||
DENY,
|
||||
@ -620,14 +621,11 @@ class PopupNavTestHandler : public TestHandler {
|
||||
DESTROY_PARENT_AFTER_CREATION,
|
||||
DESTROY_PARENT_AFTER_CREATION_FORCE,
|
||||
};
|
||||
enum RCMode {
|
||||
RC_MODE_NONE,
|
||||
RC_MODE_IMPL,
|
||||
RC_MODE_PROXY,
|
||||
};
|
||||
|
||||
PopupNavTestHandler(Mode mode, RCMode rc_mode)
|
||||
: mode_(mode), rc_mode_(rc_mode) {}
|
||||
PopupNavTestHandler(TestMode test_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 {
|
||||
// Add the resources that we will navigate to/from.
|
||||
@ -640,23 +638,8 @@ class PopupNavTestHandler : public TestHandler {
|
||||
if (mode_ == NAVIGATE_AFTER_CREATION)
|
||||
AddResource(kPopupNavPopupUrl2, "<html>Popup2</html>", "text/html");
|
||||
|
||||
CefRefPtr<CefRequestContext> request_context;
|
||||
CefRefPtr<CefRequestContextHandler> rc_handler;
|
||||
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);
|
||||
}
|
||||
CefRefPtr<CefRequestContext> request_context =
|
||||
CreateTestRequestContext(rc_mode_, rc_cache_path_);
|
||||
|
||||
// Create the browser.
|
||||
CreateBrowser(kPopupNavPageUrl, request_context);
|
||||
@ -872,8 +855,9 @@ class PopupNavTestHandler : public TestHandler {
|
||||
TestHandler::DestroyTest();
|
||||
}
|
||||
|
||||
const Mode mode_;
|
||||
const RCMode rc_mode_;
|
||||
const TestMode mode_;
|
||||
const TestRequestContextMode rc_mode_;
|
||||
const std::string rc_cache_path_;
|
||||
|
||||
TrackCallback got_on_before_popup_;
|
||||
TrackCallback got_load_start_;
|
||||
@ -890,36 +874,28 @@ class PopupNavTestHandler : public TestHandler {
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#define POPUP_TEST(name, test_mode, rc_mode) \
|
||||
TEST(RequestContextTest, Popup##name) { \
|
||||
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);
|
||||
#define POPUP_TEST_GROUP(test_name, test_mode) \
|
||||
RC_TEST_GROUP_IN_MEMORY(RequestContextTest, Popup##test_name, \
|
||||
PopupNavTestHandler, test_mode)
|
||||
|
||||
// Test allowing popups and closing the popup browser first.
|
||||
POPUP_TEST_GROUP(AllowClosePopupFirst, ALLOW_CLOSE_POPUP_FIRST);
|
||||
|
||||
// Test allowing popups and closing the main browser first to verify that
|
||||
// internal objects are tracked correctly (see issue #2162).
|
||||
// Test allowing popups and closing the main browser first to verify
|
||||
// that internal objects are tracked correctly (see issue #2162).
|
||||
POPUP_TEST_GROUP(AllowClosePopupLast, ALLOW_CLOSE_POPUP_LAST);
|
||||
|
||||
// Test denying popups.
|
||||
POPUP_TEST_GROUP(Deny, DENY);
|
||||
|
||||
// Test navigation to a different origin after popup creation to verify that
|
||||
// internal objects are tracked correctly (see issue #1392).
|
||||
// Test navigation to a different origin after popup creation to
|
||||
// verify that internal objects are tracked correctly (see issue
|
||||
// #1392).
|
||||
POPUP_TEST_GROUP(NavigateAfterCreation, NAVIGATE_AFTER_CREATION);
|
||||
|
||||
// Test destroying the parent browser during or immediately after popup creation
|
||||
// to verify that internal objects are tracked correctly (see issue #2041).
|
||||
// Test destroying the parent browser during or immediately after
|
||||
// popup creation to verify that internal objects are tracked
|
||||
// correctly (see issue #2041).
|
||||
POPUP_TEST_GROUP(DestroyParentBeforeCreation, DESTROY_PARENT_BEFORE_CREATION);
|
||||
POPUP_TEST_GROUP(DestroyParentBeforeCreationForce,
|
||||
DESTROY_PARENT_BEFORE_CREATION_FORCE);
|
||||
@ -1058,7 +1034,8 @@ class MethodTestHandler : public TestHandler {
|
||||
|
||||
} // namespace
|
||||
|
||||
// Test CefRequestContext::ClearCertificateExceptions with the global context.
|
||||
// Test CefRequestContext::ClearCertificateExceptions with the global
|
||||
// context.
|
||||
TEST(RequestContextTest, ClearCertificateExceptionsGlobal) {
|
||||
CefRefPtr<MethodTestHandler> handler = new MethodTestHandler(
|
||||
true, MethodTestHandler::METHOD_CLEAR_CERTIFICATE_EXCEPTIONS);
|
||||
@ -1066,7 +1043,8 @@ TEST(RequestContextTest, ClearCertificateExceptionsGlobal) {
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Test CefRequestContext::ClearCertificateExceptions with a custom context.
|
||||
// Test CefRequestContext::ClearCertificateExceptions with a custom
|
||||
// context.
|
||||
TEST(RequestContextTest, ClearCertificateExceptionsCustom) {
|
||||
CefRefPtr<MethodTestHandler> handler = new MethodTestHandler(
|
||||
false, MethodTestHandler::METHOD_CLEAR_CERTIFICATE_EXCEPTIONS);
|
||||
@ -1074,7 +1052,8 @@ TEST(RequestContextTest, ClearCertificateExceptionsCustom) {
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Test CefRequestContext::CloseAllConnections with the global context.
|
||||
// Test CefRequestContext::CloseAllConnections with the global
|
||||
// context.
|
||||
TEST(RequestContextTest, CloseAllConnectionsGlobal) {
|
||||
CefRefPtr<MethodTestHandler> handler = new MethodTestHandler(
|
||||
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)
|
||||
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_request.h"
|
||||
#include "include/cef_request_context.h"
|
||||
#include "include/cef_response.h"
|
||||
#include "include/cef_values.h"
|
||||
#include "tests/ceftests/test_suite.h"
|
||||
|
||||
// Test that CefRequest::HeaderMap objects are equal
|
||||
// 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,
|
||||
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_
|
||||
|
Loading…
x
Reference in New Issue
Block a user