Allow clients to clear certificate exceptions and close connections (issue #1793)
This commit is contained in:
parent
912e94bf61
commit
cd7e8a0558
|
@ -38,6 +38,7 @@
|
|||
#define CEF_INCLUDE_CAPI_CEF_REQUEST_CONTEXT_CAPI_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/capi/cef_callback_capi.h"
|
||||
#include "include/capi/cef_cookie_capi.h"
|
||||
#include "include/capi/cef_request_context_handler_capi.h"
|
||||
#include "include/capi/cef_values_capi.h"
|
||||
|
@ -199,6 +200,28 @@ typedef struct _cef_request_context_t {
|
|||
int (CEF_CALLBACK *set_preference)(struct _cef_request_context_t* self,
|
||||
const cef_string_t* name, struct _cef_value_t* value,
|
||||
cef_string_t* error);
|
||||
|
||||
///
|
||||
// Clears all certificate exceptions that were added as part of handling
|
||||
// cef_request_tHandler::on_certificate_error(). If you call this it is
|
||||
// recommended that you also call close_all_connections() or you risk not
|
||||
// being prompted again for server certificates if you reconnect quickly. If
|
||||
// |callback| is non-NULL it will be executed on the UI thread after
|
||||
// completion.
|
||||
///
|
||||
void (CEF_CALLBACK *clear_certificate_exceptions)(
|
||||
struct _cef_request_context_t* self,
|
||||
struct _cef_completion_callback_t* callback);
|
||||
|
||||
///
|
||||
// Clears all active and idle connections that Chromium currently has. This is
|
||||
// only recommended if you have released all other CEF objects but don't yet
|
||||
// want to call cef_shutdown(). If |callback| is non-NULL it will be executed
|
||||
// on the UI thread after completion.
|
||||
///
|
||||
void (CEF_CALLBACK *close_all_connections)(
|
||||
struct _cef_request_context_t* self,
|
||||
struct _cef_completion_callback_t* callback);
|
||||
} cef_request_context_t;
|
||||
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#define CEF_INCLUDE_CEF_REQUEST_CONTEXT_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/cef_callback.h"
|
||||
#include "include/cef_cookie.h"
|
||||
#include "include/cef_request_context_handler.h"
|
||||
#include "include/cef_values.h"
|
||||
|
@ -217,6 +218,28 @@ class CefRequestContext : public virtual CefBase {
|
|||
virtual bool SetPreference(const CefString& name,
|
||||
CefRefPtr<CefValue> value,
|
||||
CefString& error) =0;
|
||||
|
||||
///
|
||||
// Clears all certificate exceptions that were added as part of handling
|
||||
// CefRequestHandler::OnCertificateError(). If you call this it is
|
||||
// recommended that you also call CloseAllConnections() or you risk not
|
||||
// being prompted again for server certificates if you reconnect quickly.
|
||||
// If |callback| is non-NULL it will be executed on the UI thread after
|
||||
// completion.
|
||||
///
|
||||
/*--cef(optional_param=callback)--*/
|
||||
virtual void ClearCertificateExceptions(
|
||||
CefRefPtr<CefCompletionCallback> callback) =0;
|
||||
|
||||
///
|
||||
// Clears all active and idle connections that Chromium currently has.
|
||||
// This is only recommended if you have released all other CEF objects but
|
||||
// don't yet want to call CefShutdown(). If |callback| is non-NULL it will be
|
||||
// executed on the UI thread after completion.
|
||||
///
|
||||
/*--cef(optional_param=callback)--*/
|
||||
virtual void CloseAllConnections(
|
||||
CefRefPtr<CefCompletionCallback> callback) =0;
|
||||
};
|
||||
|
||||
#endif // CEF_INCLUDE_CEF_REQUEST_CONTEXT_H_
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
#include "base/prefs/pref_service.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "content/public/browser/plugin_service.h"
|
||||
#include "content/public/browser/ssl_host_state_delegate.h"
|
||||
#include "net/http/http_cache.h"
|
||||
#include "net/http/http_transaction_factory.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
|
@ -444,6 +447,22 @@ bool CefRequestContextImpl::SetPreference(const CefString& name,
|
|||
return true;
|
||||
}
|
||||
|
||||
void CefRequestContextImpl::ClearCertificateExceptions(
|
||||
CefRefPtr<CefCompletionCallback> callback) {
|
||||
GetBrowserContext(
|
||||
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
|
||||
base::Bind(&CefRequestContextImpl::ClearCertificateExceptionsInternal,
|
||||
this, callback));
|
||||
}
|
||||
|
||||
void CefRequestContextImpl::CloseAllConnections(
|
||||
CefRefPtr<CefCompletionCallback> callback) {
|
||||
GetRequestContextImpl(
|
||||
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
|
||||
base::Bind(&CefRequestContextImpl::CloseAllConnectionsInternal, this,
|
||||
callback));
|
||||
}
|
||||
|
||||
CefRequestContextImpl::CefRequestContextImpl(
|
||||
scoped_refptr<CefBrowserContext> browser_context)
|
||||
: browser_context_(browser_context),
|
||||
|
@ -548,3 +567,41 @@ void CefRequestContextImpl::PurgePluginListCacheInternal(
|
|||
content::PluginService::GetInstance()->PurgePluginListCache(
|
||||
browser_context.get(), false);
|
||||
}
|
||||
|
||||
void CefRequestContextImpl::ClearCertificateExceptionsInternal(
|
||||
CefRefPtr<CefCompletionCallback> callback,
|
||||
scoped_refptr<CefBrowserContext> browser_context) {
|
||||
CEF_REQUIRE_UIT();
|
||||
|
||||
content::SSLHostStateDelegate* ssl_delegate =
|
||||
browser_context->GetSSLHostStateDelegate();
|
||||
if (ssl_delegate)
|
||||
ssl_delegate->Clear();
|
||||
|
||||
if (callback) {
|
||||
CEF_POST_TASK(CEF_UIT,
|
||||
base::Bind(&CefCompletionCallback::OnComplete, callback.get()));
|
||||
}
|
||||
}
|
||||
|
||||
void CefRequestContextImpl::CloseAllConnectionsInternal(
|
||||
CefRefPtr<CefCompletionCallback> callback,
|
||||
scoped_refptr<CefURLRequestContextGetterImpl> request_context) {
|
||||
CEF_REQUIRE_IOT();
|
||||
|
||||
net::URLRequestContext* url_context = request_context->GetURLRequestContext();
|
||||
if (url_context) {
|
||||
net::HttpTransactionFactory* http_factory =
|
||||
url_context->http_transaction_factory();
|
||||
if (http_factory) {
|
||||
net::HttpCache* cache = http_factory->GetCache();
|
||||
if (cache)
|
||||
cache->CloseAllConnections();
|
||||
}
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
CEF_POST_TASK(CEF_UIT,
|
||||
base::Bind(&CefCompletionCallback::OnComplete, callback.get()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,6 +69,9 @@ class CefRequestContextImpl : public CefRequestContext {
|
|||
bool SetPreference(const CefString& name,
|
||||
CefRefPtr<CefValue> value,
|
||||
CefString& error) override;
|
||||
void ClearCertificateExceptions(
|
||||
CefRefPtr<CefCompletionCallback> callback) override;
|
||||
void CloseAllConnections(CefRefPtr<CefCompletionCallback> callback) override;
|
||||
|
||||
const CefRequestContextSettings& settings() const { return settings_; }
|
||||
|
||||
|
@ -103,6 +106,12 @@ class CefRequestContextImpl : public CefRequestContext {
|
|||
void PurgePluginListCacheInternal(
|
||||
bool reload_pages,
|
||||
scoped_refptr<CefBrowserContext> browser_context);
|
||||
void ClearCertificateExceptionsInternal(
|
||||
CefRefPtr<CefCompletionCallback> callback,
|
||||
scoped_refptr<CefBrowserContext> browser_context);
|
||||
void CloseAllConnectionsInternal(
|
||||
CefRefPtr<CefCompletionCallback> callback,
|
||||
scoped_refptr<CefURLRequestContextGetterImpl> request_context);
|
||||
|
||||
scoped_refptr<CefBrowserContext> browser_context_;
|
||||
CefRequestContextSettings settings_;
|
||||
|
|
|
@ -350,6 +350,34 @@ int CEF_CALLBACK request_context_set_preference(
|
|||
return _retval;
|
||||
}
|
||||
|
||||
void CEF_CALLBACK request_context_clear_certificate_exceptions(
|
||||
struct _cef_request_context_t* self, cef_completion_callback_t* callback) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return;
|
||||
// Unverified params: callback
|
||||
|
||||
// Execute
|
||||
CefRequestContextCppToC::Get(self)->ClearCertificateExceptions(
|
||||
CefCompletionCallbackCToCpp::Wrap(callback));
|
||||
}
|
||||
|
||||
void CEF_CALLBACK request_context_close_all_connections(
|
||||
struct _cef_request_context_t* self, cef_completion_callback_t* callback) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return;
|
||||
// Unverified params: callback
|
||||
|
||||
// Execute
|
||||
CefRequestContextCppToC::Get(self)->CloseAllConnections(
|
||||
CefCompletionCallbackCToCpp::Wrap(callback));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
@ -374,6 +402,9 @@ CefRequestContextCppToC::CefRequestContextCppToC() {
|
|||
GetStruct()->get_all_preferences = request_context_get_all_preferences;
|
||||
GetStruct()->can_set_preference = request_context_can_set_preference;
|
||||
GetStruct()->set_preference = request_context_set_preference;
|
||||
GetStruct()->clear_certificate_exceptions =
|
||||
request_context_clear_certificate_exceptions;
|
||||
GetStruct()->close_all_connections = request_context_close_all_connections;
|
||||
}
|
||||
|
||||
template<> CefRefPtr<CefRequestContext> CefCppToC<CefRequestContextCppToC,
|
||||
|
|
|
@ -325,6 +325,36 @@ bool CefRequestContextCToCpp::SetPreference(const CefString& name,
|
|||
return _retval?true:false;
|
||||
}
|
||||
|
||||
void CefRequestContextCToCpp::ClearCertificateExceptions(
|
||||
CefRefPtr<CefCompletionCallback> callback) {
|
||||
cef_request_context_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, clear_certificate_exceptions))
|
||||
return;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Unverified params: callback
|
||||
|
||||
// Execute
|
||||
_struct->clear_certificate_exceptions(_struct,
|
||||
CefCompletionCallbackCppToC::Wrap(callback));
|
||||
}
|
||||
|
||||
void CefRequestContextCToCpp::CloseAllConnections(
|
||||
CefRefPtr<CefCompletionCallback> callback) {
|
||||
cef_request_context_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, close_all_connections))
|
||||
return;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Unverified params: callback
|
||||
|
||||
// Execute
|
||||
_struct->close_all_connections(_struct,
|
||||
CefCompletionCallbackCppToC::Wrap(callback));
|
||||
}
|
||||
|
||||
|
||||
// CONSTRUCTOR - Do not edit by hand.
|
||||
|
||||
|
|
|
@ -52,6 +52,9 @@ class CefRequestContextCToCpp
|
|||
bool CanSetPreference(const CefString& name) OVERRIDE;
|
||||
bool SetPreference(const CefString& name, CefRefPtr<CefValue> value,
|
||||
CefString& error) OVERRIDE;
|
||||
void ClearCertificateExceptions(
|
||||
CefRefPtr<CefCompletionCallback> callback) OVERRIDE;
|
||||
void CloseAllConnections(CefRefPtr<CefCompletionCallback> callback) OVERRIDE;
|
||||
};
|
||||
|
||||
#endif // USING_CEF_SHARED
|
||||
|
|
|
@ -650,3 +650,135 @@ TEST(RequestContextTest, NoReferrerLinkDifferentOrigin) {
|
|||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class MethodTestHandler : public TestHandler {
|
||||
public:
|
||||
enum Method {
|
||||
METHOD_CLEAR_CERTIFICATE_EXCEPTIONS,
|
||||
METHOD_CLOSE_ALL_CONNECTIONS,
|
||||
};
|
||||
|
||||
class CompletionCallback : public CefCompletionCallback {
|
||||
public:
|
||||
explicit CompletionCallback(MethodTestHandler* test_handler)
|
||||
: test_handler_(test_handler) {
|
||||
}
|
||||
|
||||
~CompletionCallback() override {
|
||||
EXPECT_UI_THREAD();
|
||||
|
||||
// OnComplete should be executed.
|
||||
EXPECT_FALSE(test_handler_);
|
||||
}
|
||||
|
||||
void OnComplete() override {
|
||||
EXPECT_UI_THREAD();
|
||||
|
||||
// OnComplete should be executed only one time.
|
||||
EXPECT_TRUE(test_handler_);
|
||||
test_handler_->OnCompleteCallback();
|
||||
test_handler_ = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
MethodTestHandler* test_handler_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(CompletionCallback);
|
||||
};
|
||||
|
||||
MethodTestHandler(bool global_context,
|
||||
Method method)
|
||||
: global_context_(global_context),
|
||||
method_(method) {
|
||||
}
|
||||
|
||||
void RunTest() override {
|
||||
const char kUrl[] = "http://tests/method.html";
|
||||
|
||||
AddResource(kUrl, "<html><body>Method</body></html>", "text/html");
|
||||
|
||||
CefRefPtr<CefRequestContext> request_context;
|
||||
if (!global_context_) {
|
||||
CefRequestContextSettings settings;
|
||||
request_context = CefRequestContext::CreateContext(settings, nullptr);
|
||||
}
|
||||
|
||||
CreateBrowser(kUrl, request_context);
|
||||
|
||||
// Time out the test after a reasonable period of time.
|
||||
SetTestTimeout();
|
||||
}
|
||||
|
||||
void OnLoadEnd(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int httpStatusCode) override {
|
||||
CefRefPtr<CefRequestContext> context =
|
||||
browser->GetHost()->GetRequestContext();
|
||||
CefRefPtr<CefCompletionCallback> callback = new CompletionCallback(this);
|
||||
if (method_ == METHOD_CLEAR_CERTIFICATE_EXCEPTIONS)
|
||||
context->ClearCertificateExceptions(callback);
|
||||
else if (method_ == METHOD_CLOSE_ALL_CONNECTIONS)
|
||||
context->CloseAllConnections(callback);
|
||||
}
|
||||
|
||||
void OnCompleteCallback() {
|
||||
EXPECT_UI_THREAD();
|
||||
EXPECT_FALSE(got_completion_callback_);
|
||||
got_completion_callback_.yes();
|
||||
DestroyTest();
|
||||
}
|
||||
|
||||
private:
|
||||
void DestroyTest() override {
|
||||
EXPECT_TRUE(got_completion_callback_);
|
||||
TestHandler::DestroyTest();
|
||||
}
|
||||
|
||||
const bool global_context_;
|
||||
const Method method_;
|
||||
|
||||
TrackCallback got_completion_callback_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(MethodTestHandler);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// Test CefRequestContext::ClearCertificateExceptions with the global context.
|
||||
TEST(RequestContextTest, ClearCertificateExceptionsGlobal) {
|
||||
CefRefPtr<MethodTestHandler> handler =
|
||||
new MethodTestHandler(true,
|
||||
MethodTestHandler::METHOD_CLEAR_CERTIFICATE_EXCEPTIONS);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Test CefRequestContext::ClearCertificateExceptions with a custom context.
|
||||
TEST(RequestContextTest, ClearCertificateExceptionsCustom) {
|
||||
CefRefPtr<MethodTestHandler> handler =
|
||||
new MethodTestHandler(false,
|
||||
MethodTestHandler::METHOD_CLEAR_CERTIFICATE_EXCEPTIONS);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Test CefRequestContext::CloseAllConnections with the global context.
|
||||
TEST(RequestContextTest, CloseAllConnectionsGlobal) {
|
||||
CefRefPtr<MethodTestHandler> handler =
|
||||
new MethodTestHandler(true,
|
||||
MethodTestHandler::METHOD_CLOSE_ALL_CONNECTIONS);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Test CefRequestContext::CloseAllConnections with a custom context.
|
||||
TEST(RequestContextTest, CloseAllConnectionsCustom) {
|
||||
CefRefPtr<MethodTestHandler> handler =
|
||||
new MethodTestHandler(false,
|
||||
MethodTestHandler::METHOD_CLOSE_ALL_CONNECTIONS);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
Loading…
Reference in New Issue