Merge pull request #3487 from atom/certificate-api
Rework of the certificate API
This commit is contained in:
commit
45e3d4ea6b
15 changed files with 256 additions and 225 deletions
|
@ -17,6 +17,7 @@
|
|||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/net_converter.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "base/command_line.h"
|
||||
|
@ -27,6 +28,7 @@
|
|||
#include "chrome/common/chrome_paths.h"
|
||||
#include "content/public/browser/client_certificate_delegate.h"
|
||||
#include "content/public/browser/gpu_data_manager.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/common/content_switches.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
|
@ -154,11 +156,14 @@ void PassLoginInformation(scoped_refptr<LoginHandler> login_handler,
|
|||
} // namespace
|
||||
|
||||
App::App() {
|
||||
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->set_delegate(this);
|
||||
Browser::Get()->AddObserver(this);
|
||||
content::GpuDataManager::GetInstance()->AddObserver(this);
|
||||
}
|
||||
|
||||
App::~App() {
|
||||
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->set_delegate(
|
||||
nullptr);
|
||||
Browser::Get()->RemoveObserver(this);
|
||||
content::GpuDataManager::GetInstance()->RemoveObserver(this);
|
||||
}
|
||||
|
@ -212,15 +217,59 @@ void App::OnFinishLaunching() {
|
|||
Emit("ready");
|
||||
}
|
||||
|
||||
void App::OnSelectCertificate(
|
||||
void App::OnLogin(LoginHandler* login_handler) {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
bool prevent_default = Emit(
|
||||
"login",
|
||||
WebContents::CreateFrom(isolate(), login_handler->GetWebContents()),
|
||||
login_handler->request(),
|
||||
login_handler->auth_info(),
|
||||
base::Bind(&PassLoginInformation, make_scoped_refptr(login_handler)));
|
||||
|
||||
// Default behavior is to always cancel the auth.
|
||||
if (!prevent_default)
|
||||
login_handler->CancelAuth();
|
||||
}
|
||||
|
||||
void App::AllowCertificateError(
|
||||
int pid,
|
||||
int fid,
|
||||
int cert_error,
|
||||
const net::SSLInfo& ssl_info,
|
||||
const GURL& request_url,
|
||||
content::ResourceType resource_type,
|
||||
bool overridable,
|
||||
bool strict_enforcement,
|
||||
bool expired_previous_decision,
|
||||
const base::Callback<void(bool)>& callback,
|
||||
content::CertificateRequestResultType* request) {
|
||||
auto rfh = content::RenderFrameHost::FromID(pid, fid);
|
||||
auto web_contents = content::WebContents::FromRenderFrameHost(rfh);
|
||||
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
bool prevent_default = Emit("certificate-error",
|
||||
WebContents::CreateFrom(isolate(), web_contents),
|
||||
request_url,
|
||||
net::ErrorToString(cert_error),
|
||||
ssl_info.cert,
|
||||
callback);
|
||||
|
||||
// Deny the certificate by default.
|
||||
if (!prevent_default)
|
||||
*request = content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY;
|
||||
}
|
||||
|
||||
void App::SelectClientCertificate(
|
||||
content::WebContents* web_contents,
|
||||
net::SSLCertRequestInfo* cert_request_info,
|
||||
scoped_ptr<content::ClientCertificateDelegate> delegate) {
|
||||
std::shared_ptr<content::ClientCertificateDelegate>
|
||||
shared_delegate(delegate.release());
|
||||
bool prevent_default =
|
||||
Emit("select-certificate",
|
||||
api::WebContents::CreateFrom(isolate(), web_contents),
|
||||
Emit("select-client-certificate",
|
||||
WebContents::CreateFrom(isolate(), web_contents),
|
||||
cert_request_info->host_and_port.ToString(),
|
||||
cert_request_info->client_certs,
|
||||
base::Bind(&OnClientCertificateSelected,
|
||||
|
@ -233,31 +282,6 @@ void App::OnSelectCertificate(
|
|||
cert_request_info->client_certs[0].get());
|
||||
}
|
||||
|
||||
void App::OnLogin(LoginHandler* login_handler) {
|
||||
// Convert the args explicitly since they will be passed for twice.
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
auto web_contents =
|
||||
WebContents::CreateFrom(isolate(), login_handler->GetWebContents());
|
||||
auto request = mate::ConvertToV8(isolate(), login_handler->request());
|
||||
auto auth_info = mate::ConvertToV8(isolate(), login_handler->auth_info());
|
||||
auto callback = mate::ConvertToV8(
|
||||
isolate(),
|
||||
base::Bind(&PassLoginInformation, make_scoped_refptr(login_handler)));
|
||||
|
||||
bool prevent_default =
|
||||
Emit("login", web_contents, request, auth_info, callback);
|
||||
|
||||
// Also pass it to WebContents.
|
||||
if (!prevent_default)
|
||||
prevent_default =
|
||||
web_contents->Emit("login", request, auth_info, callback);
|
||||
|
||||
// Default behavior is to always cancel the auth.
|
||||
if (!prevent_default)
|
||||
login_handler->CancelAuth();
|
||||
}
|
||||
|
||||
void App::OnGpuProcessCrashed(base::TerminationStatus exit_code) {
|
||||
Emit("gpu-process-crashed");
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <string>
|
||||
|
||||
#include "atom/browser/api/event_emitter.h"
|
||||
#include "atom/browser/atom_browser_client.h"
|
||||
#include "atom/browser/browser_observer.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "chrome/browser/process_singleton.h"
|
||||
|
@ -26,7 +27,8 @@ namespace atom {
|
|||
|
||||
namespace api {
|
||||
|
||||
class App : public mate::EventEmitter,
|
||||
class App : public AtomBrowserClient::Delegate,
|
||||
public mate::EventEmitter,
|
||||
public BrowserObserver,
|
||||
public content::GpuDataManagerObserver {
|
||||
public:
|
||||
|
@ -46,11 +48,25 @@ class App : public mate::EventEmitter,
|
|||
void OnActivate(bool has_visible_windows) override;
|
||||
void OnWillFinishLaunching() override;
|
||||
void OnFinishLaunching() override;
|
||||
void OnSelectCertificate(
|
||||
void OnLogin(LoginHandler* login_handler) override;
|
||||
|
||||
// content::ContentBrowserClient:
|
||||
void AllowCertificateError(
|
||||
int render_process_id,
|
||||
int render_frame_id,
|
||||
int cert_error,
|
||||
const net::SSLInfo& ssl_info,
|
||||
const GURL& request_url,
|
||||
content::ResourceType resource_type,
|
||||
bool overridable,
|
||||
bool strict_enforcement,
|
||||
bool expired_previous_decision,
|
||||
const base::Callback<void(bool)>& callback,
|
||||
content::CertificateRequestResultType* request) override;
|
||||
void SelectClientCertificate(
|
||||
content::WebContents* web_contents,
|
||||
net::SSLCertRequestInfo* cert_request_info,
|
||||
scoped_ptr<content::ClientCertificateDelegate> delegate) override;
|
||||
void OnLogin(LoginHandler* login_handler) override;
|
||||
|
||||
// content::GpuDataManagerObserver:
|
||||
void OnGpuProcessCrashed(base::TerminationStatus exit_code) override;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "atom/browser/api/save_page_handler.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/browser/net/atom_cert_verifier.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
|
@ -238,18 +239,11 @@ void SetProxyInIO(net::URLRequestContextGetter* getter,
|
|||
RunCallbackInUI(callback);
|
||||
}
|
||||
|
||||
void PassVerificationResult(
|
||||
scoped_refptr<AtomCertVerifier::CertVerifyRequest> request,
|
||||
bool success) {
|
||||
request->ContinueWithResult(success ? net::OK : net::ERR_FAILED);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Session::Session(AtomBrowserContext* browser_context)
|
||||
: browser_context_(browser_context) {
|
||||
AttachAsUserData(browser_context);
|
||||
browser_context->cert_verifier()->SetDelegate(this);
|
||||
|
||||
// Observe DownloadManger to get download notifications.
|
||||
content::BrowserContext::GetDownloadManager(browser_context)->
|
||||
|
@ -262,19 +256,6 @@ Session::~Session() {
|
|||
Destroy();
|
||||
}
|
||||
|
||||
void Session::RequestCertVerification(
|
||||
const scoped_refptr<AtomCertVerifier::CertVerifyRequest>& request) {
|
||||
bool prevent_default = Emit(
|
||||
"untrusted-certificate",
|
||||
request->args().hostname,
|
||||
request->args().cert,
|
||||
base::Bind(&PassVerificationResult, request));
|
||||
|
||||
if (!prevent_default)
|
||||
// Tell the request to use the result of default verifier.
|
||||
request->ContinueWithResult(net::ERR_IO_PENDING);
|
||||
}
|
||||
|
||||
void Session::OnDownloadCreated(content::DownloadManager* manager,
|
||||
content::DownloadItem* item) {
|
||||
auto web_contents = item->GetWebContents();
|
||||
|
@ -295,7 +276,6 @@ bool Session::IsDestroyed() const {
|
|||
}
|
||||
|
||||
void Session::Destroy() {
|
||||
browser_context_->cert_verifier()->SetDelegate(nullptr);
|
||||
browser_context_ = nullptr;
|
||||
}
|
||||
|
||||
|
@ -377,6 +357,17 @@ void Session::DisableNetworkEmulation() {
|
|||
base::Passed(&conditions)));
|
||||
}
|
||||
|
||||
void Session::SetCertVerifyProc(v8::Local<v8::Value> val,
|
||||
mate::Arguments* args) {
|
||||
AtomCertVerifier::VerifyProc proc;
|
||||
if (!(val->IsNull() || mate::ConvertFromV8(args->isolate(), val, &proc))) {
|
||||
args->ThrowError("Must pass null or function");
|
||||
return;
|
||||
}
|
||||
|
||||
browser_context_->cert_verifier()->SetVerifyProc(proc);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Session::Cookies(v8::Isolate* isolate) {
|
||||
if (cookies_.IsEmpty()) {
|
||||
auto handle = atom::api::Cookies::Create(isolate, browser_context());
|
||||
|
@ -395,6 +386,7 @@ mate::ObjectTemplateBuilder Session::GetObjectTemplateBuilder(
|
|||
.SetMethod("setDownloadPath", &Session::SetDownloadPath)
|
||||
.SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation)
|
||||
.SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation)
|
||||
.SetMethod("setCertificateVerifyProc", &Session::SetCertVerifyProc)
|
||||
.SetProperty("cookies", &Session::Cookies);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include <string>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/net/atom_cert_verifier.h"
|
||||
#include "content/public/browser/download_manager.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "net/base/completion_callback.h"
|
||||
|
@ -35,7 +34,6 @@ class AtomBrowserContext;
|
|||
namespace api {
|
||||
|
||||
class Session: public mate::TrackableObject<Session>,
|
||||
public AtomCertVerifier::Delegate,
|
||||
public content::DownloadManager::Observer {
|
||||
public:
|
||||
using ResolveProxyCallback = base::Callback<void(std::string)>;
|
||||
|
@ -54,10 +52,6 @@ class Session: public mate::TrackableObject<Session>,
|
|||
explicit Session(AtomBrowserContext* browser_context);
|
||||
~Session();
|
||||
|
||||
// AtomCertVerifier::Delegate:
|
||||
void RequestCertVerification(
|
||||
const scoped_refptr<AtomCertVerifier::CertVerifyRequest>&) override;
|
||||
|
||||
// content::DownloadManager::Observer:
|
||||
void OnDownloadCreated(content::DownloadManager* manager,
|
||||
content::DownloadItem* item) override;
|
||||
|
@ -78,6 +72,7 @@ class Session: public mate::TrackableObject<Session>,
|
|||
void SetDownloadPath(const base::FilePath& path);
|
||||
void EnableNetworkEmulation(const mate::Dictionary& options);
|
||||
void DisableNetworkEmulation();
|
||||
void SetCertVerifyProc(v8::Local<v8::Value> proc, mate::Arguments* args);
|
||||
v8::Local<v8::Value> Cookies(v8::Isolate* isolate);
|
||||
|
||||
// Cached object for cookies API.
|
||||
|
|
|
@ -38,6 +38,12 @@ app.getAppPath = ->
|
|||
# Helpers.
|
||||
app.resolveProxy = (url, callback) -> @defaultSession.resolveProxy url, callback
|
||||
|
||||
# Routes the events to webContents.
|
||||
for name in ['login', 'certificate-error', 'select-client-certificate']
|
||||
do (name) ->
|
||||
app.on name, (event, webContents, args...) ->
|
||||
webContents.emit name, event, args...
|
||||
|
||||
# Deprecated.
|
||||
{deprecate} = electron
|
||||
app.getHomeDir = deprecate 'app.getHomeDir', 'app.getPath', ->
|
||||
|
@ -52,6 +58,7 @@ deprecate.event app, 'finish-launching', 'ready', ->
|
|||
@emit 'finish-launching'
|
||||
deprecate.event app, 'activate-with-no-open-windows', 'activate', (event, hasVisibleWindows) ->
|
||||
@emit 'activate-with-no-open-windows' if not hasVisibleWindows
|
||||
deprecate.event app, 'select-certificate', 'select-client-certificate'
|
||||
|
||||
# Wrappers for native classes.
|
||||
wrapSession = (session) ->
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include "atom/browser/atom_quota_permission_context.h"
|
||||
#include "atom/browser/atom_resource_dispatcher_host_delegate.h"
|
||||
#include "atom/browser/atom_speech_recognition_manager_delegate.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/web_contents_preferences.h"
|
||||
#include "atom/browser/window_list.h"
|
||||
|
@ -88,7 +87,7 @@ void AtomBrowserClient::SetCustomSchemes(
|
|||
g_custom_schemes = JoinString(schemes, ',');
|
||||
}
|
||||
|
||||
AtomBrowserClient::AtomBrowserClient() {
|
||||
AtomBrowserClient::AtomBrowserClient() : delegate_(nullptr) {
|
||||
}
|
||||
|
||||
AtomBrowserClient::~AtomBrowserClient() {
|
||||
|
@ -208,6 +207,26 @@ content::QuotaPermissionContext*
|
|||
return new AtomQuotaPermissionContext;
|
||||
}
|
||||
|
||||
void AtomBrowserClient::AllowCertificateError(
|
||||
int render_process_id,
|
||||
int render_frame_id,
|
||||
int cert_error,
|
||||
const net::SSLInfo& ssl_info,
|
||||
const GURL& request_url,
|
||||
content::ResourceType resource_type,
|
||||
bool overridable,
|
||||
bool strict_enforcement,
|
||||
bool expired_previous_decision,
|
||||
const base::Callback<void(bool)>& callback,
|
||||
content::CertificateRequestResultType* request) {
|
||||
if (delegate_) {
|
||||
delegate_->AllowCertificateError(
|
||||
render_process_id, render_frame_id, cert_error, ssl_info, request_url,
|
||||
resource_type, overridable, strict_enforcement,
|
||||
expired_previous_decision, callback, request);
|
||||
}
|
||||
}
|
||||
|
||||
void AtomBrowserClient::SelectClientCertificate(
|
||||
content::WebContents* web_contents,
|
||||
net::SSLCertRequestInfo* cert_request_info,
|
||||
|
@ -222,10 +241,10 @@ void AtomBrowserClient::SelectClientCertificate(
|
|||
return;
|
||||
}
|
||||
|
||||
if (!cert_request_info->client_certs.empty())
|
||||
Browser::Get()->ClientCertificateSelector(web_contents,
|
||||
cert_request_info,
|
||||
delegate.Pass());
|
||||
if (!cert_request_info->client_certs.empty() && delegate_) {
|
||||
delegate_->SelectClientCertificate(
|
||||
web_contents, cert_request_info, delegate.Pass());
|
||||
}
|
||||
}
|
||||
|
||||
void AtomBrowserClient::ResourceDispatcherHostCreated() {
|
||||
|
|
|
@ -31,6 +31,9 @@ class AtomBrowserClient : public brightray::BrowserClient,
|
|||
AtomBrowserClient();
|
||||
virtual ~AtomBrowserClient();
|
||||
|
||||
using Delegate = content::ContentBrowserClient;
|
||||
void set_delegate(Delegate* delegate) { delegate_ = delegate; }
|
||||
|
||||
// Don't force renderer process to restart for once.
|
||||
static void SuppressRendererProcessRestartForOnce();
|
||||
// Custom schemes to be registered to standard.
|
||||
|
@ -54,6 +57,18 @@ class AtomBrowserClient : public brightray::BrowserClient,
|
|||
int child_process_id) override;
|
||||
void DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) override;
|
||||
content::QuotaPermissionContext* CreateQuotaPermissionContext() override;
|
||||
void AllowCertificateError(
|
||||
int render_process_id,
|
||||
int render_frame_id,
|
||||
int cert_error,
|
||||
const net::SSLInfo& ssl_info,
|
||||
const GURL& request_url,
|
||||
content::ResourceType resource_type,
|
||||
bool overridable,
|
||||
bool strict_enforcement,
|
||||
bool expired_previous_decision,
|
||||
const base::Callback<void(bool)>& callback,
|
||||
content::CertificateRequestResultType* request) override;
|
||||
void SelectClientCertificate(
|
||||
content::WebContents* web_contents,
|
||||
net::SSLCertRequestInfo* cert_request_info,
|
||||
|
@ -74,6 +89,8 @@ class AtomBrowserClient : public brightray::BrowserClient,
|
|||
scoped_ptr<AtomResourceDispatcherHostDelegate>
|
||||
resource_dispatcher_host_delegate_;
|
||||
|
||||
Delegate* delegate_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomBrowserClient);
|
||||
};
|
||||
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/window_list.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "content/public/browser/client_certificate_delegate.h"
|
||||
#include "net/ssl/ssl_cert_request_info.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
|
@ -141,17 +139,6 @@ void Browser::DidFinishLaunching() {
|
|||
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnFinishLaunching());
|
||||
}
|
||||
|
||||
void Browser::ClientCertificateSelector(
|
||||
content::WebContents* web_contents,
|
||||
net::SSLCertRequestInfo* cert_request_info,
|
||||
scoped_ptr<content::ClientCertificateDelegate> delegate) {
|
||||
FOR_EACH_OBSERVER(BrowserObserver,
|
||||
observers_,
|
||||
OnSelectCertificate(web_contents,
|
||||
cert_request_info,
|
||||
delegate.Pass()));
|
||||
}
|
||||
|
||||
void Browser::RequestLogin(LoginHandler* login_handler) {
|
||||
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnLogin(login_handler));
|
||||
}
|
||||
|
|
|
@ -126,12 +126,6 @@ class Browser : public WindowListObserver {
|
|||
void WillFinishLaunching();
|
||||
void DidFinishLaunching();
|
||||
|
||||
// Called when client certificate is required.
|
||||
void ClientCertificateSelector(
|
||||
content::WebContents* web_contents,
|
||||
net::SSLCertRequestInfo* cert_request_info,
|
||||
scoped_ptr<content::ClientCertificateDelegate> delegate);
|
||||
|
||||
// Request basic auth login.
|
||||
void RequestLogin(LoginHandler* login_handler);
|
||||
|
||||
|
|
|
@ -7,17 +7,6 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "content/public/browser/client_certificate_delegate.h"
|
||||
|
||||
namespace content {
|
||||
class WebContents;
|
||||
}
|
||||
|
||||
namespace net {
|
||||
class SSLCertRequestInfo;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class LoginHandler;
|
||||
|
@ -53,12 +42,6 @@ class BrowserObserver {
|
|||
virtual void OnWillFinishLaunching() {}
|
||||
virtual void OnFinishLaunching() {}
|
||||
|
||||
// The browser requires client certificate.
|
||||
virtual void OnSelectCertificate(
|
||||
content::WebContents* web_contents,
|
||||
net::SSLCertRequestInfo* cert_request_info,
|
||||
scoped_ptr<content::ClientCertificateDelegate> delegate) {}
|
||||
|
||||
// The browser requests HTTP login.
|
||||
virtual void OnLogin(LoginHandler* login_handler) {}
|
||||
|
||||
|
|
|
@ -15,30 +15,31 @@ using content::BrowserThread;
|
|||
|
||||
namespace atom {
|
||||
|
||||
AtomCertVerifier::CertVerifyRequest::~CertVerifyRequest() {
|
||||
}
|
||||
namespace {
|
||||
|
||||
void AtomCertVerifier::CertVerifyRequest::ContinueWithResult(int result) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
|
||||
if (handled_)
|
||||
return;
|
||||
|
||||
handled_ = true;
|
||||
void OnResult(
|
||||
net::CertVerifyResult* verify_result,
|
||||
const net::CompletionCallback& callback,
|
||||
bool result) {
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(args_.callback,
|
||||
result == net::ERR_IO_PENDING ? result_ : result));
|
||||
base::Bind(callback, result ? net::OK : net::ERR_FAILED));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
AtomCertVerifier::AtomCertVerifier()
|
||||
: delegate_(nullptr) {
|
||||
default_cert_verifier_.reset(net::CertVerifier::CreateDefault());
|
||||
: default_cert_verifier_(net::CertVerifier::CreateDefault()) {
|
||||
}
|
||||
|
||||
AtomCertVerifier::~AtomCertVerifier() {
|
||||
}
|
||||
|
||||
void AtomCertVerifier::SetVerifyProc(const VerifyProc& proc) {
|
||||
base::AutoLock auto_lock(lock_);
|
||||
verify_proc_ = proc;
|
||||
}
|
||||
|
||||
int AtomCertVerifier::Verify(
|
||||
net::X509Certificate* cert,
|
||||
const std::string& hostname,
|
||||
|
@ -51,45 +52,26 @@ int AtomCertVerifier::Verify(
|
|||
const net::BoundNetLog& net_log) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
|
||||
if (callback.is_null() || !verify_result || hostname.empty() || !delegate_)
|
||||
return net::ERR_INVALID_ARGUMENT;
|
||||
|
||||
VerifyArgs args = { cert, hostname, callback };
|
||||
int result = default_cert_verifier_->Verify(
|
||||
cert, hostname, ocsp_response, flags, crl_set, verify_result,
|
||||
base::Bind(&AtomCertVerifier::OnDefaultVerificationResult,
|
||||
base::Unretained(this), args),
|
||||
out_req, net_log);
|
||||
if (result != net::OK && result != net::ERR_IO_PENDING) {
|
||||
// The default verifier fails immediately.
|
||||
VerifyCertificateFromDelegate(args, result);
|
||||
return net::ERR_IO_PENDING;
|
||||
VerifyProc proc;
|
||||
{
|
||||
base::AutoLock auto_lock(lock_);
|
||||
proc = verify_proc_;
|
||||
}
|
||||
|
||||
return result;
|
||||
if (proc.is_null())
|
||||
return default_cert_verifier_->Verify(
|
||||
cert, hostname, ocsp_response, flags, crl_set, verify_result, callback,
|
||||
out_req, net_log);
|
||||
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(proc, hostname, make_scoped_refptr(cert),
|
||||
base::Bind(OnResult, verify_result, callback)));
|
||||
return net::ERR_IO_PENDING;
|
||||
}
|
||||
|
||||
bool AtomCertVerifier::SupportsOCSPStapling() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void AtomCertVerifier::VerifyCertificateFromDelegate(
|
||||
const VerifyArgs& args, int result) {
|
||||
CertVerifyRequest* request = new CertVerifyRequest(this, result, args);
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&Delegate::RequestCertVerification,
|
||||
base::Unretained(delegate_),
|
||||
make_scoped_refptr(request)));
|
||||
}
|
||||
|
||||
void AtomCertVerifier::OnDefaultVerificationResult(
|
||||
const VerifyArgs& args, int result) {
|
||||
if (result == net::OK) {
|
||||
args.callback.Run(result);
|
||||
return;
|
||||
}
|
||||
|
||||
VerifyCertificateFromDelegate(args, result);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
|
|
@ -8,61 +8,22 @@
|
|||
#include <string>
|
||||
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/synchronization/lock.h"
|
||||
#include "net/cert/cert_verifier.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomCertVerifier : public net::CertVerifier {
|
||||
public:
|
||||
struct VerifyArgs {
|
||||
scoped_refptr<net::X509Certificate> cert;
|
||||
const std::string& hostname;
|
||||
net::CompletionCallback callback;
|
||||
};
|
||||
|
||||
class CertVerifyRequest
|
||||
: public base::RefCountedThreadSafe<CertVerifyRequest> {
|
||||
public:
|
||||
CertVerifyRequest(AtomCertVerifier* cert_verifier,
|
||||
int result,
|
||||
const VerifyArgs& args)
|
||||
: cert_verifier_(cert_verifier),
|
||||
result_(result),
|
||||
args_(args),
|
||||
handled_(false) {
|
||||
}
|
||||
|
||||
void ContinueWithResult(int result);
|
||||
|
||||
const VerifyArgs& args() const { return args_; }
|
||||
|
||||
private:
|
||||
friend class base::RefCountedThreadSafe<CertVerifyRequest>;
|
||||
~CertVerifyRequest();
|
||||
|
||||
AtomCertVerifier* cert_verifier_;
|
||||
int result_;
|
||||
VerifyArgs args_;
|
||||
bool handled_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CertVerifyRequest);
|
||||
};
|
||||
|
||||
class Delegate {
|
||||
public:
|
||||
virtual ~Delegate() {}
|
||||
|
||||
// Called on UI thread.
|
||||
virtual void RequestCertVerification(
|
||||
const scoped_refptr<CertVerifyRequest>& request) {}
|
||||
};
|
||||
|
||||
AtomCertVerifier();
|
||||
virtual ~AtomCertVerifier();
|
||||
|
||||
void SetDelegate(Delegate* delegate) {
|
||||
delegate_ = delegate;
|
||||
}
|
||||
using VerifyProc =
|
||||
base::Callback<void(const std::string& hostname,
|
||||
scoped_refptr<net::X509Certificate>,
|
||||
const base::Callback<void(bool)>&)>;
|
||||
|
||||
void SetVerifyProc(const VerifyProc& proc);
|
||||
|
||||
protected:
|
||||
// net::CertVerifier:
|
||||
|
@ -78,12 +39,8 @@ class AtomCertVerifier : public net::CertVerifier {
|
|||
bool SupportsOCSPStapling() override;
|
||||
|
||||
private:
|
||||
friend class CertVerifyRequest;
|
||||
|
||||
void VerifyCertificateFromDelegate(const VerifyArgs& args, int result);
|
||||
void OnDefaultVerificationResult(const VerifyArgs& args, int result);
|
||||
|
||||
Delegate* delegate_;
|
||||
base::Lock lock_;
|
||||
VerifyProc verify_proc_;
|
||||
scoped_ptr<net::CertVerifier> default_cert_verifier_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomCertVerifier);
|
||||
|
|
|
@ -131,7 +131,36 @@ Returns:
|
|||
|
||||
Emitted when a new [browserWindow](browser-window.md) is created.
|
||||
|
||||
### Event: 'select-certificate'
|
||||
### Event: 'certificate-error'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
* `url` URL
|
||||
* `error` String - The error code
|
||||
* `certificate` Object
|
||||
* `data` Buffer - PEM encoded data
|
||||
* `issuerName` String
|
||||
* `callback` Function
|
||||
|
||||
Emitted when failed to verify the `certificate` for `url`, to trust the
|
||||
certificate you should prevent the default behavior with
|
||||
`event.preventDefault()` and call `callback(true)`.
|
||||
|
||||
```javascript
|
||||
session.on('certificate-error', function(event, webContents, url, error, certificate, callback) {
|
||||
if (url == "https://github.com") {
|
||||
// Verification logic.
|
||||
event.preventDefault();
|
||||
callback(true);
|
||||
} else {
|
||||
callback(false);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Event: 'select-client-certificate'
|
||||
|
||||
Returns:
|
||||
|
||||
|
@ -151,7 +180,7 @@ and `callback` needs to be called with an entry filtered from the list. Using
|
|||
certificate from the store.
|
||||
|
||||
```javascript
|
||||
app.on('select-certificate', function(event, host, url, list, callback) {
|
||||
app.on('select-client-certificate', function(event, webContents, url, list, callback) {
|
||||
event.preventDefault();
|
||||
callback(list[0]);
|
||||
})
|
||||
|
|
|
@ -34,31 +34,6 @@ session.on('will-download', function(event, item, webContents) {
|
|||
});
|
||||
```
|
||||
|
||||
### Event: 'untrusted-certificate'
|
||||
|
||||
* `event` Event
|
||||
* `hostname` String
|
||||
* `certificate` Object
|
||||
* `data` Buffer - PEM encoded data
|
||||
* `issuerName` String
|
||||
* `callback` Function
|
||||
|
||||
Emitted when failed to verify the `certificate` for `hostname`, to trust the
|
||||
certificate you should prevent the default behavior with
|
||||
`event.preventDefault()` and call `callback(true)`.
|
||||
|
||||
```js
|
||||
session.on('verify-certificate', function(event, hostname, certificate, callback) {
|
||||
if (hostname == "github.com") {
|
||||
// Verification logic.
|
||||
event.preventDefault();
|
||||
callback(true);
|
||||
} else {
|
||||
callback(false);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Methods
|
||||
|
||||
The `session` object has the following methods:
|
||||
|
@ -245,3 +220,24 @@ window.webContents.session.enableNetworkEmulation({offline: true});
|
|||
|
||||
Disables any network emulation already active for the `session`. Resets to
|
||||
the original network configuration.
|
||||
|
||||
### `session.setCertificateVerifyProc(proc)`
|
||||
|
||||
* `proc` Function
|
||||
|
||||
Sets the certificate verify proc for `session`, the `proc` will be called with
|
||||
`proc(hostname, certificate, callback)` whenever a server certificate
|
||||
verification is requested. Calling `callback(true)` accepts the certificate,
|
||||
calling `callback(false)` rejects it.
|
||||
|
||||
Calling `setCertificateVerifyProc(null)` will revert back to default certificate
|
||||
verify proc.
|
||||
|
||||
```javascript
|
||||
myWindow.webContents.session.setCertificateVerifyProc(function(hostname, cert, callback) {
|
||||
if (hostname == 'github.com')
|
||||
callback(true);
|
||||
else
|
||||
callback(false);
|
||||
});
|
||||
```
|
||||
|
|
|
@ -167,6 +167,39 @@ Emitted when DevTools is closed.
|
|||
|
||||
Emitted when DevTools is focused / opened.
|
||||
|
||||
### Event: 'certificate-error'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `url` URL
|
||||
* `error` String - The error code
|
||||
* `certificate` Object
|
||||
* `data` Buffer - PEM encoded data
|
||||
* `issuerName` String
|
||||
* `callback` Function
|
||||
|
||||
Emitted when failed to verify the `certificate` for `url`.
|
||||
|
||||
The usage is the same with [the `certificate-error` event of
|
||||
`app`](app.md#event-certificate-error).
|
||||
|
||||
### Event: 'select-client-certificate'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `url` URL
|
||||
* `certificateList` [Objects]
|
||||
* `data` Buffer - PEM encoded data
|
||||
* `issuerName` String - Issuer's Common Name
|
||||
* `callback` Function
|
||||
|
||||
Emitted when a client certificate is requested.
|
||||
|
||||
The usage is the same with [the `select-client-certificate` event of
|
||||
`app`](app.md#event-select-client-certificate).
|
||||
|
||||
### Event: 'login'
|
||||
|
||||
Returns:
|
||||
|
|
Loading…
Reference in a new issue