Merge remote-tracking branch 'refs/remotes/atom/master'

This commit is contained in:
Plusb Preco 2015-11-18 23:33:38 +09:00
commit 6058c7e14d
25 changed files with 317 additions and 271 deletions

View file

@ -17,6 +17,7 @@
#include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/net_converter.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/file_path_converter.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "atom/common/node_includes.h" #include "atom/common/node_includes.h"
#include "atom/common/options_switches.h" #include "atom/common/options_switches.h"
#include "base/command_line.h" #include "base/command_line.h"
@ -27,6 +28,7 @@
#include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_paths.h"
#include "content/public/browser/client_certificate_delegate.h" #include "content/public/browser/client_certificate_delegate.h"
#include "content/public/browser/gpu_data_manager.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 "content/public/common/content_switches.h"
#include "native_mate/dictionary.h" #include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h" #include "native_mate/object_template_builder.h"
@ -154,11 +156,14 @@ void PassLoginInformation(scoped_refptr<LoginHandler> login_handler,
} // namespace } // namespace
App::App() { App::App() {
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->set_delegate(this);
Browser::Get()->AddObserver(this); Browser::Get()->AddObserver(this);
content::GpuDataManager::GetInstance()->AddObserver(this); content::GpuDataManager::GetInstance()->AddObserver(this);
} }
App::~App() { App::~App() {
static_cast<AtomBrowserClient*>(AtomBrowserClient::Get())->set_delegate(
nullptr);
Browser::Get()->RemoveObserver(this); Browser::Get()->RemoveObserver(this);
content::GpuDataManager::GetInstance()->RemoveObserver(this); content::GpuDataManager::GetInstance()->RemoveObserver(this);
} }
@ -212,15 +217,59 @@ void App::OnFinishLaunching() {
Emit("ready"); 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, content::WebContents* web_contents,
net::SSLCertRequestInfo* cert_request_info, net::SSLCertRequestInfo* cert_request_info,
scoped_ptr<content::ClientCertificateDelegate> delegate) { scoped_ptr<content::ClientCertificateDelegate> delegate) {
std::shared_ptr<content::ClientCertificateDelegate> std::shared_ptr<content::ClientCertificateDelegate>
shared_delegate(delegate.release()); shared_delegate(delegate.release());
bool prevent_default = bool prevent_default =
Emit("select-certificate", Emit("select-client-certificate",
api::WebContents::CreateFrom(isolate(), web_contents), WebContents::CreateFrom(isolate(), web_contents),
cert_request_info->host_and_port.ToString(), cert_request_info->host_and_port.ToString(),
cert_request_info->client_certs, cert_request_info->client_certs,
base::Bind(&OnClientCertificateSelected, base::Bind(&OnClientCertificateSelected,
@ -233,31 +282,6 @@ void App::OnSelectCertificate(
cert_request_info->client_certs[0].get()); 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) { void App::OnGpuProcessCrashed(base::TerminationStatus exit_code) {
Emit("gpu-process-crashed"); Emit("gpu-process-crashed");
} }

View file

@ -8,6 +8,7 @@
#include <string> #include <string>
#include "atom/browser/api/event_emitter.h" #include "atom/browser/api/event_emitter.h"
#include "atom/browser/atom_browser_client.h"
#include "atom/browser/browser_observer.h" #include "atom/browser/browser_observer.h"
#include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/callback.h"
#include "chrome/browser/process_singleton.h" #include "chrome/browser/process_singleton.h"
@ -26,7 +27,8 @@ namespace atom {
namespace api { namespace api {
class App : public mate::EventEmitter, class App : public AtomBrowserClient::Delegate,
public mate::EventEmitter,
public BrowserObserver, public BrowserObserver,
public content::GpuDataManagerObserver { public content::GpuDataManagerObserver {
public: public:
@ -46,11 +48,25 @@ class App : public mate::EventEmitter,
void OnActivate(bool has_visible_windows) override; void OnActivate(bool has_visible_windows) override;
void OnWillFinishLaunching() override; void OnWillFinishLaunching() override;
void OnFinishLaunching() 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, content::WebContents* web_contents,
net::SSLCertRequestInfo* cert_request_info, net::SSLCertRequestInfo* cert_request_info,
scoped_ptr<content::ClientCertificateDelegate> delegate) override; scoped_ptr<content::ClientCertificateDelegate> delegate) override;
void OnLogin(LoginHandler* login_handler) override;
// content::GpuDataManagerObserver: // content::GpuDataManagerObserver:
void OnGpuProcessCrashed(base::TerminationStatus exit_code) override; void OnGpuProcessCrashed(base::TerminationStatus exit_code) override;

View file

@ -13,6 +13,7 @@
#include "atom/browser/api/save_page_handler.h" #include "atom/browser/api/save_page_handler.h"
#include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_browser_main_parts.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/callback.h"
#include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/gurl_converter.h"
#include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/native_mate_converters/file_path_converter.h"
@ -238,18 +239,11 @@ void SetProxyInIO(net::URLRequestContextGetter* getter,
RunCallbackInUI(callback); RunCallbackInUI(callback);
} }
void PassVerificationResult(
scoped_refptr<AtomCertVerifier::CertVerifyRequest> request,
bool success) {
request->ContinueWithResult(success ? net::OK : net::ERR_FAILED);
}
} // namespace } // namespace
Session::Session(AtomBrowserContext* browser_context) Session::Session(AtomBrowserContext* browser_context)
: browser_context_(browser_context) { : browser_context_(browser_context) {
AttachAsUserData(browser_context); AttachAsUserData(browser_context);
browser_context->cert_verifier()->SetDelegate(this);
// Observe DownloadManger to get download notifications. // Observe DownloadManger to get download notifications.
content::BrowserContext::GetDownloadManager(browser_context)-> content::BrowserContext::GetDownloadManager(browser_context)->
@ -262,19 +256,6 @@ Session::~Session() {
Destroy(); 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, void Session::OnDownloadCreated(content::DownloadManager* manager,
content::DownloadItem* item) { content::DownloadItem* item) {
auto web_contents = item->GetWebContents(); auto web_contents = item->GetWebContents();
@ -295,7 +276,6 @@ bool Session::IsDestroyed() const {
} }
void Session::Destroy() { void Session::Destroy() {
browser_context_->cert_verifier()->SetDelegate(nullptr);
browser_context_ = nullptr; browser_context_ = nullptr;
} }
@ -377,6 +357,17 @@ void Session::DisableNetworkEmulation() {
base::Passed(&conditions))); 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) { v8::Local<v8::Value> Session::Cookies(v8::Isolate* isolate) {
if (cookies_.IsEmpty()) { if (cookies_.IsEmpty()) {
auto handle = atom::api::Cookies::Create(isolate, browser_context()); auto handle = atom::api::Cookies::Create(isolate, browser_context());
@ -395,6 +386,7 @@ mate::ObjectTemplateBuilder Session::GetObjectTemplateBuilder(
.SetMethod("setDownloadPath", &Session::SetDownloadPath) .SetMethod("setDownloadPath", &Session::SetDownloadPath)
.SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation) .SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation)
.SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation) .SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation)
.SetMethod("setCertificateVerifyProc", &Session::SetCertVerifyProc)
.SetProperty("cookies", &Session::Cookies); .SetProperty("cookies", &Session::Cookies);
} }

View file

@ -8,7 +8,6 @@
#include <string> #include <string>
#include "atom/browser/api/trackable_object.h" #include "atom/browser/api/trackable_object.h"
#include "atom/browser/net/atom_cert_verifier.h"
#include "content/public/browser/download_manager.h" #include "content/public/browser/download_manager.h"
#include "native_mate/handle.h" #include "native_mate/handle.h"
#include "net/base/completion_callback.h" #include "net/base/completion_callback.h"
@ -35,7 +34,6 @@ class AtomBrowserContext;
namespace api { namespace api {
class Session: public mate::TrackableObject<Session>, class Session: public mate::TrackableObject<Session>,
public AtomCertVerifier::Delegate,
public content::DownloadManager::Observer { public content::DownloadManager::Observer {
public: public:
using ResolveProxyCallback = base::Callback<void(std::string)>; using ResolveProxyCallback = base::Callback<void(std::string)>;
@ -54,10 +52,6 @@ class Session: public mate::TrackableObject<Session>,
explicit Session(AtomBrowserContext* browser_context); explicit Session(AtomBrowserContext* browser_context);
~Session(); ~Session();
// AtomCertVerifier::Delegate:
void RequestCertVerification(
const scoped_refptr<AtomCertVerifier::CertVerifyRequest>&) override;
// content::DownloadManager::Observer: // content::DownloadManager::Observer:
void OnDownloadCreated(content::DownloadManager* manager, void OnDownloadCreated(content::DownloadManager* manager,
content::DownloadItem* item) override; content::DownloadItem* item) override;
@ -78,6 +72,7 @@ class Session: public mate::TrackableObject<Session>,
void SetDownloadPath(const base::FilePath& path); void SetDownloadPath(const base::FilePath& path);
void EnableNetworkEmulation(const mate::Dictionary& options); void EnableNetworkEmulation(const mate::Dictionary& options);
void DisableNetworkEmulation(); void DisableNetworkEmulation();
void SetCertVerifyProc(v8::Local<v8::Value> proc, mate::Arguments* args);
v8::Local<v8::Value> Cookies(v8::Isolate* isolate); v8::Local<v8::Value> Cookies(v8::Isolate* isolate);
// Cached object for cookies API. // Cached object for cookies API.

View file

@ -38,6 +38,12 @@ app.getAppPath = ->
# Helpers. # Helpers.
app.resolveProxy = (url, callback) -> @defaultSession.resolveProxy url, callback 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. # Deprecated.
{deprecate} = electron {deprecate} = electron
app.getHomeDir = deprecate 'app.getHomeDir', 'app.getPath', -> app.getHomeDir = deprecate 'app.getHomeDir', 'app.getPath', ->
@ -52,6 +58,7 @@ deprecate.event app, 'finish-launching', 'ready', ->
@emit 'finish-launching' @emit 'finish-launching'
deprecate.event app, 'activate-with-no-open-windows', 'activate', (event, hasVisibleWindows) -> deprecate.event app, 'activate-with-no-open-windows', 'activate', (event, hasVisibleWindows) ->
@emit 'activate-with-no-open-windows' if not hasVisibleWindows @emit 'activate-with-no-open-windows' if not hasVisibleWindows
deprecate.event app, 'select-certificate', 'select-client-certificate'
# Wrappers for native classes. # Wrappers for native classes.
wrapSession = (session) -> wrapSession = (session) ->

View file

@ -14,7 +14,6 @@
#include "atom/browser/atom_quota_permission_context.h" #include "atom/browser/atom_quota_permission_context.h"
#include "atom/browser/atom_resource_dispatcher_host_delegate.h" #include "atom/browser/atom_resource_dispatcher_host_delegate.h"
#include "atom/browser/atom_speech_recognition_manager_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/native_window.h"
#include "atom/browser/web_contents_preferences.h" #include "atom/browser/web_contents_preferences.h"
#include "atom/browser/window_list.h" #include "atom/browser/window_list.h"
@ -88,7 +87,7 @@ void AtomBrowserClient::SetCustomSchemes(
g_custom_schemes = JoinString(schemes, ','); g_custom_schemes = JoinString(schemes, ',');
} }
AtomBrowserClient::AtomBrowserClient() { AtomBrowserClient::AtomBrowserClient() : delegate_(nullptr) {
} }
AtomBrowserClient::~AtomBrowserClient() { AtomBrowserClient::~AtomBrowserClient() {
@ -208,6 +207,26 @@ content::QuotaPermissionContext*
return new AtomQuotaPermissionContext; 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( void AtomBrowserClient::SelectClientCertificate(
content::WebContents* web_contents, content::WebContents* web_contents,
net::SSLCertRequestInfo* cert_request_info, net::SSLCertRequestInfo* cert_request_info,
@ -222,10 +241,10 @@ void AtomBrowserClient::SelectClientCertificate(
return; return;
} }
if (!cert_request_info->client_certs.empty()) if (!cert_request_info->client_certs.empty() && delegate_) {
Browser::Get()->ClientCertificateSelector(web_contents, delegate_->SelectClientCertificate(
cert_request_info, web_contents, cert_request_info, delegate.Pass());
delegate.Pass()); }
} }
void AtomBrowserClient::ResourceDispatcherHostCreated() { void AtomBrowserClient::ResourceDispatcherHostCreated() {

View file

@ -31,6 +31,9 @@ class AtomBrowserClient : public brightray::BrowserClient,
AtomBrowserClient(); AtomBrowserClient();
virtual ~AtomBrowserClient(); virtual ~AtomBrowserClient();
using Delegate = content::ContentBrowserClient;
void set_delegate(Delegate* delegate) { delegate_ = delegate; }
// Don't force renderer process to restart for once. // Don't force renderer process to restart for once.
static void SuppressRendererProcessRestartForOnce(); static void SuppressRendererProcessRestartForOnce();
// Custom schemes to be registered to standard. // Custom schemes to be registered to standard.
@ -54,6 +57,18 @@ class AtomBrowserClient : public brightray::BrowserClient,
int child_process_id) override; int child_process_id) override;
void DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) override; void DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) override;
content::QuotaPermissionContext* CreateQuotaPermissionContext() 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( void SelectClientCertificate(
content::WebContents* web_contents, content::WebContents* web_contents,
net::SSLCertRequestInfo* cert_request_info, net::SSLCertRequestInfo* cert_request_info,
@ -74,6 +89,8 @@ class AtomBrowserClient : public brightray::BrowserClient,
scoped_ptr<AtomResourceDispatcherHostDelegate> scoped_ptr<AtomResourceDispatcherHostDelegate>
resource_dispatcher_host_delegate_; resource_dispatcher_host_delegate_;
Delegate* delegate_;
DISALLOW_COPY_AND_ASSIGN(AtomBrowserClient); DISALLOW_COPY_AND_ASSIGN(AtomBrowserClient);
}; };

View file

@ -10,8 +10,6 @@
#include "atom/browser/native_window.h" #include "atom/browser/native_window.h"
#include "atom/browser/window_list.h" #include "atom/browser/window_list.h"
#include "base/message_loop/message_loop.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 { namespace atom {
@ -141,17 +139,6 @@ void Browser::DidFinishLaunching() {
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnFinishLaunching()); 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) { void Browser::RequestLogin(LoginHandler* login_handler) {
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnLogin(login_handler)); FOR_EACH_OBSERVER(BrowserObserver, observers_, OnLogin(login_handler));
} }

View file

@ -126,12 +126,6 @@ class Browser : public WindowListObserver {
void WillFinishLaunching(); void WillFinishLaunching();
void DidFinishLaunching(); 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. // Request basic auth login.
void RequestLogin(LoginHandler* login_handler); void RequestLogin(LoginHandler* login_handler);

View file

@ -7,17 +7,6 @@
#include <string> #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 { namespace atom {
class LoginHandler; class LoginHandler;
@ -53,12 +42,6 @@ class BrowserObserver {
virtual void OnWillFinishLaunching() {} virtual void OnWillFinishLaunching() {}
virtual void OnFinishLaunching() {} 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. // The browser requests HTTP login.
virtual void OnLogin(LoginHandler* login_handler) {} virtual void OnLogin(LoginHandler* login_handler) {}

View file

@ -106,13 +106,25 @@ unwrapArgs = (sender, args) ->
# Call a function and send reply asynchronously if it's a an asynchronous # Call a function and send reply asynchronously if it's a an asynchronous
# style function and the caller didn't pass a callback. # style function and the caller didn't pass a callback.
callFunction = (event, func, caller, args) -> callFunction = (event, func, caller, args) ->
if v8Util.getHiddenValue(func, 'asynchronous') and typeof args[args.length - 1] isnt 'function' funcMarkedAsync = v8Util.getHiddenValue(func, 'asynchronous')
args.push (ret) -> funcPassedCallback = args[args.length - 1] is 'function'
try
if funcMarkedAsync and not funcPassedCallback
args.push (ret) ->
event.returnValue = valueToMeta event.sender, ret, true
func.apply caller, args
else
ret = func.apply caller, args
event.returnValue = valueToMeta event.sender, ret, true event.returnValue = valueToMeta event.sender, ret, true
func.apply caller, args catch e
else # Catch functions thrown further down in function invocation and wrap
ret = func.apply caller, args # them with the function name so it's easier to trace things like
event.returnValue = valueToMeta event.sender, ret, true # `Error processing argument -1.`
funcName = func.name ? "anonymous"
throw new Error("Could not call remote function `#{funcName}`.
Check that the function signature is correct.
Underlying error: #{e.message}")
# Send by BrowserWindow when its render view is deleted. # Send by BrowserWindow when its render view is deleted.
process.on 'ATOM_BROWSER_RELEASE_RENDER_VIEW', (id) -> process.on 'ATOM_BROWSER_RELEASE_RENDER_VIEW', (id) ->

View file

@ -15,30 +15,31 @@ using content::BrowserThread;
namespace atom { namespace atom {
AtomCertVerifier::CertVerifyRequest::~CertVerifyRequest() { namespace {
}
void AtomCertVerifier::CertVerifyRequest::ContinueWithResult(int result) { void OnResult(
DCHECK_CURRENTLY_ON(BrowserThread::UI); net::CertVerifyResult* verify_result,
const net::CompletionCallback& callback,
if (handled_) bool result) {
return;
handled_ = true;
BrowserThread::PostTask( BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE, BrowserThread::IO, FROM_HERE,
base::Bind(args_.callback, base::Bind(callback, result ? net::OK : net::ERR_FAILED));
result == net::ERR_IO_PENDING ? result_ : result));
} }
} // namespace
AtomCertVerifier::AtomCertVerifier() AtomCertVerifier::AtomCertVerifier()
: delegate_(nullptr) { : default_cert_verifier_(net::CertVerifier::CreateDefault()) {
default_cert_verifier_.reset(net::CertVerifier::CreateDefault());
} }
AtomCertVerifier::~AtomCertVerifier() { AtomCertVerifier::~AtomCertVerifier() {
} }
void AtomCertVerifier::SetVerifyProc(const VerifyProc& proc) {
base::AutoLock auto_lock(lock_);
verify_proc_ = proc;
}
int AtomCertVerifier::Verify( int AtomCertVerifier::Verify(
net::X509Certificate* cert, net::X509Certificate* cert,
const std::string& hostname, const std::string& hostname,
@ -51,45 +52,26 @@ int AtomCertVerifier::Verify(
const net::BoundNetLog& net_log) { const net::BoundNetLog& net_log) {
DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (callback.is_null() || !verify_result || hostname.empty() || !delegate_) VerifyProc proc;
return net::ERR_INVALID_ARGUMENT; {
base::AutoLock auto_lock(lock_);
VerifyArgs args = { cert, hostname, callback }; proc = verify_proc_;
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;
} }
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() { bool AtomCertVerifier::SupportsOCSPStapling() {
return true; 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 } // namespace atom

View file

@ -8,61 +8,22 @@
#include <string> #include <string>
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
#include "net/cert/cert_verifier.h" #include "net/cert/cert_verifier.h"
namespace atom { namespace atom {
class AtomCertVerifier : public net::CertVerifier { class AtomCertVerifier : public net::CertVerifier {
public: 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(); AtomCertVerifier();
virtual ~AtomCertVerifier(); virtual ~AtomCertVerifier();
void SetDelegate(Delegate* delegate) { using VerifyProc =
delegate_ = delegate; base::Callback<void(const std::string& hostname,
} scoped_refptr<net::X509Certificate>,
const base::Callback<void(bool)>&)>;
void SetVerifyProc(const VerifyProc& proc);
protected: protected:
// net::CertVerifier: // net::CertVerifier:
@ -78,12 +39,8 @@ class AtomCertVerifier : public net::CertVerifier {
bool SupportsOCSPStapling() override; bool SupportsOCSPStapling() override;
private: private:
friend class CertVerifyRequest; base::Lock lock_;
VerifyProc verify_proc_;
void VerifyCertificateFromDelegate(const VerifyArgs& args, int result);
void OnDefaultVerificationResult(const VerifyArgs& args, int result);
Delegate* delegate_;
scoped_ptr<net::CertVerifier> default_cert_verifier_; scoped_ptr<net::CertVerifier> default_cert_verifier_;
DISALLOW_COPY_AND_ASSIGN(AtomCertVerifier); DISALLOW_COPY_AND_ASSIGN(AtomCertVerifier);

View file

@ -40,15 +40,9 @@ const CGFloat kVerticalTitleMargin = 2;
trayIcon_ = icon; trayIcon_ = icon;
isHighlightEnable_ = YES; isHighlightEnable_ = YES;
// Get the initial size. if ((self = [super initWithFrame: CGRectZero])) {
NSStatusBar* statusBar = [NSStatusBar systemStatusBar];
NSRect frame = NSMakeRect(0, 0, [self fullWidth], [statusBar thickness]);
if ((self = [super initWithFrame:frame])) {
// Setup the image view. // Setup the image view.
NSRect iconFrame = frame; image_view_.reset([[NSImageView alloc] initWithFrame: CGRectZero]);
iconFrame.size.width = [self iconWidth];
image_view_.reset([[NSImageView alloc] initWithFrame:iconFrame]);
[image_view_ setImageScaling:NSImageScaleNone]; [image_view_ setImageScaling:NSImageScaleNone];
[image_view_ setImageAlignment:NSImageAlignCenter]; [image_view_ setImageAlignment:NSImageAlignCenter];
[self addSubview:image_view_]; [self addSubview:image_view_];
@ -56,17 +50,27 @@ const CGFloat kVerticalTitleMargin = 2;
// Unregister image_view_ as a dragged destination, allows its parent view // Unregister image_view_ as a dragged destination, allows its parent view
// (StatusItemView) handle dragging events. // (StatusItemView) handle dragging events.
[image_view_ unregisterDraggedTypes]; [image_view_ unregisterDraggedTypes];
NSArray* types = [NSArray arrayWithObjects:NSFilenamesPboardType, nil]; [self registerForDraggedTypes: @[NSFilenamesPboardType]];
[self registerForDraggedTypes:types];
// Create the status item. // Create the status item.
statusItem_.reset([[[NSStatusBar systemStatusBar] NSStatusItem * item = [[NSStatusBar systemStatusBar]
statusItemWithLength:NSWidth(frame)] retain]); statusItemWithLength:NSVariableStatusItemLength];
statusItem_.reset([item retain]);
[statusItem_ setView:self]; [statusItem_ setView:self];
// Finalize setup by sizing our views
[self updateDimensions];
} }
return self; return self;
} }
- (void)updateDimensions {
NSStatusBar * bar = [NSStatusBar systemStatusBar];
[image_view_ setFrame: NSMakeRect(0, 0, [self iconWidth], [bar thickness])];
[self setFrame: NSMakeRect(0, 0, [self fullWidth], [bar thickness])];
[self setNeedsDisplay:YES];
}
- (void)removeItem { - (void)removeItem {
[[NSStatusBar systemStatusBar] removeStatusItem:statusItem_]; [[NSStatusBar systemStatusBar] removeStatusItem:statusItem_];
statusItem_.reset(); statusItem_.reset();
@ -81,9 +85,7 @@ const CGFloat kVerticalTitleMargin = 2;
// Draw background. // Draw background.
BOOL highlight = [self shouldHighlight]; BOOL highlight = [self shouldHighlight];
CGFloat thickness = [[statusItem_ statusBar] thickness]; CGFloat thickness = [[statusItem_ statusBar] thickness];
NSRect statusItemBounds = NSMakeRect(0, 0, [statusItem_ length], thickness); [statusItem_ drawStatusBarBackgroundInRect:self.bounds withHighlight:highlight];
[statusItem_ drawStatusBarBackgroundInRect:statusItemBounds
withHighlight:highlight];
// Make use of NSImageView to draw the image, which can correctly draw // Make use of NSImageView to draw the image, which can correctly draw
// template image under dark menu bar. // template image under dark menu bar.
@ -157,10 +159,10 @@ const CGFloat kVerticalTitleMargin = 2;
NSColor* foregroundColor = highlight ? NSColor* foregroundColor = highlight ?
[NSColor whiteColor] : [NSColor whiteColor] :
[NSColor colorWithRed:0.265625 green:0.25390625 blue:0.234375 alpha:1.0]; [NSColor colorWithRed:0.265625 green:0.25390625 blue:0.234375 alpha:1.0];
return [NSDictionary dictionaryWithObjectsAndKeys: return @{
font, NSFontAttributeName, NSFontAttributeName: font,
foregroundColor, NSForegroundColorAttributeName, NSForegroundColorAttributeName: foregroundColor
nil]; };
} }
- (NSDictionary*)titleAttributes { - (NSDictionary*)titleAttributes {
@ -169,7 +171,7 @@ const CGFloat kVerticalTitleMargin = 2;
- (void)setImage:(NSImage*)image { - (void)setImage:(NSImage*)image {
image_.reset([image copy]); image_.reset([image copy]);
[self setNeedsDisplay:YES]; [self updateDimensions];
} }
- (void)setAlternateImage:(NSImage*)image { - (void)setAlternateImage:(NSImage*)image {
@ -181,12 +183,12 @@ const CGFloat kVerticalTitleMargin = 2;
} }
- (void)setTitle:(NSString*)title { - (void)setTitle:(NSString*)title {
if (title.length > 0) if (title.length > 0) {
title_.reset([title copy]); title_.reset([title copy]);
else } else {
title_.reset(); title_.reset();
[statusItem_ setLength:[self fullWidth]]; }
[self setNeedsDisplay:YES]; [self updateDimensions];
} }
- (void)setMenuController:(AtomMenuController*)menu { - (void)setMenuController:(AtomMenuController*)menu {

View file

@ -2,7 +2,7 @@
## Introducción ## Introducción
Electron permite la creación de aplicaciones de escritorio utilizando JavaScript puro, a través de un runtime con APIs nativas. Puedes verlo como una variante de io.js, enfocado en aplicaciones de escritorio, en vez de servidores web. Electron permite la creación de aplicaciones de escritorio utilizando JavaScript puro, a través de un runtime con APIs nativas. Puedes verlo como una variante de io.js, enfocado en aplicaciones de escritorio, en vez de servidores web.
Esto no significa que Electron sea un binding de librerías GUI para JavaScript. Esto no significa que Electron sea un binding de librerías GUI para JavaScript.
Electron utiliza páginas web como su GUI, por lo cual puedes verlo como un navegador Chromium mínimo, Electron utiliza páginas web como su GUI, por lo cual puedes verlo como un navegador Chromium mínimo,
@ -94,7 +94,7 @@ app.on('ready', function() {
mainWindow = new BrowserWindow({width: 800, height: 600}); mainWindow = new BrowserWindow({width: 800, height: 600});
// cargar el index.html de nuestra aplicación. // cargar el index.html de nuestra aplicación.
mainWindow.loadUrl('file://' + __dirname + '/index.html'); mainWindow.loadURL('file://' + __dirname + '/index.html');
// Desplegar devtools. // Desplegar devtools.
mainWindow.openDevTools(); mainWindow.openDevTools();

View file

@ -74,7 +74,7 @@ app.on('ready', function() {
mainWindow = new BrowserWindow({width: 800, height: 600}); mainWindow = new BrowserWindow({width: 800, height: 600});
// and load the index.html of the app. // and load the index.html of the app.
mainWindow.loadUrl('file://' + __dirname + '/index.html'); mainWindow.loadURL('file://' + __dirname + '/index.html');
// Open the devtools. // Open the devtools.
mainWindow.openDevTools(); mainWindow.openDevTools();

View file

@ -5,13 +5,13 @@ um runtime com APIs ricas e nativas. Você pode ver isso como uma variação do
runtime do io.js que é focado em aplicações desktop em vez de web servers. runtime do io.js que é focado em aplicações desktop em vez de web servers.
Isso não significa que o Electron é uma ligação em JavaScript para blibliotécas Isso não significa que o Electron é uma ligação em JavaScript para blibliotécas
de interface gráfica (GUI). Em vez disso, Electron usa páginas web como de interface gráfica (GUI). Em vez disso, Electron usa páginas web como
interface gráfica, então você pode ver isso também como um navegador Chromium interface gráfica, então você pode ver isso também como um navegador Chromium
mínimo, controlado por JavaScript. mínimo, controlado por JavaScript.
### Processo Principal ### Processo Principal
No Electron, o processo que executa o script principal (main) do `package.json` No Electron, o processo que executa o script principal (main) do `package.json`
é chamado __processo principal__. O script que roda no processo principal pode é chamado __processo principal__. O script que roda no processo principal pode
mostrar uma GUI criando páginas web. mostrar uma GUI criando páginas web.
@ -38,7 +38,7 @@ correspondentes. Cada processo renderizador é isolado e toma conta de sua
respectiva página web. respectiva página web.
Nas páginas web, chamar APIs nativas relacionadas à GUI não é permitido porque Nas páginas web, chamar APIs nativas relacionadas à GUI não é permitido porque
gerênciar recursos de GUI em páginas web é muito perigoso e torna fácil o vazamento de gerênciar recursos de GUI em páginas web é muito perigoso e torna fácil o vazamento de
recursos. Se você quer realizar operações com GUI em páginas web, o processo recursos. Se você quer realizar operações com GUI em páginas web, o processo
renderizador da página web deve se comunicar com o processo principal para requisitar renderizador da página web deve se comunicar com o processo principal para requisitar
que o processo principal realize estas operações. que o processo principal realize estas operações.
@ -71,7 +71,7 @@ com isso:
} }
``` ```
__Nota__: Se o campo `main` não estiver presente no `package.jso`, o Electron irá __Nota__: Se o campo `main` não estiver presente no `package.jso`, o Electron irá
tentar carregar um `index.js` tentar carregar um `index.js`
O `main.js` deve criar as janelas e os manipuladores de eventos do sistema, um típico O `main.js` deve criar as janelas e os manipuladores de eventos do sistema, um típico
@ -85,7 +85,7 @@ var BrowserWindow = require('browser-window'); // Módulo para criar uma janela
require('crash-reporter').start(); require('crash-reporter').start();
// Mantenha uma referência global para o objeto window, se você não o fizer, // Mantenha uma referência global para o objeto window, se você não o fizer,
// a janela será fechada automaticamente quando o objeto JavaScript for // a janela será fechada automaticamente quando o objeto JavaScript for
// coletado pelo garbage collector. // coletado pelo garbage collector.
var mainWindow = null; var mainWindow = null;
@ -106,7 +106,7 @@ app.on('ready', function() {
mainWindow = new BrowserWindow({width: 800, height: 600}); mainWindow = new BrowserWindow({width: 800, height: 600});
// e carrega o index.html do app. // e carrega o index.html do app.
mainWindow.loadUrl('file://' + __dirname + '/index.html'); mainWindow.loadURL('file://' + __dirname + '/index.html');
// Abre os DevTools. // Abre os DevTools.
mainWindow.openDevTools(); mainWindow.openDevTools();
@ -187,6 +187,6 @@ $ ./Electron.app/Contents/MacOS/Electron your-app/
### Executar como uma distribuição ### Executar como uma distribuição
Depois de terminar seu app, você pode criar uma distribuição seguindo o guia Depois de terminar seu app, você pode criar uma distribuição seguindo o guia
[Application Distribution](./application-distribution.md) e então executar o app [Application Distribution](./application-distribution.md) e então executar o app
empacotado. empacotado.

View file

@ -68,7 +68,7 @@ app.on('ready', function() {
mainWindow = new BrowserWindow({width: 800, height: 600}); mainWindow = new BrowserWindow({width: 800, height: 600});
// 加载应用的 index.html // 加载应用的 index.html
mainWindow.loadUrl('file://' + __dirname + '/index.html'); mainWindow.loadURL('file://' + __dirname + '/index.html');
// 打开开发工具 // 打开开发工具
mainWindow.openDevTools(); mainWindow.openDevTools();

View file

@ -85,7 +85,7 @@ app.on('ready', function() {
  mainWindow = new BrowserWindow({width: 800, height: 600});   mainWindow = new BrowserWindow({width: 800, height: 600});
  // 載入應用程式的 index.html   // 載入應用程式的 index.html
  mainWindow.loadUrl('file://' + __dirname + '/index.html');   mainWindow.loadURL('file://' + __dirname + '/index.html');
  // 打開開發者工具   // 打開開發者工具
  mainWindow.webContents.openDevTools();   mainWindow.webContents.openDevTools();
@ -174,4 +174,4 @@ $ git clone https://github.com/atom/electron-quick-start
$ cd electron-quick-start $ cd electron-quick-start
# Install dependencies and run the app # Install dependencies and run the app
$ npm install && npm start $ npm install && npm start
``` ```

View file

@ -131,7 +131,36 @@ Returns:
Emitted when a new [browserWindow](browser-window.md) is created. 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: Returns:
@ -151,7 +180,7 @@ and `callback` needs to be called with an entry filtered from the list. Using
certificate from the store. certificate from the store.
```javascript ```javascript
app.on('select-certificate', function(event, host, url, list, callback) { app.on('select-client-certificate', function(event, webContents, url, list, callback) {
event.preventDefault(); event.preventDefault();
callback(list[0]); callback(list[0]);
}) })

View file

@ -232,7 +232,7 @@ Emitted when the window enters full screen state triggered by html api.
Emitted when the window leaves full screen state triggered by html api. Emitted when the window leaves full screen state triggered by html api.
### Event: 'app-command': ### Event: 'app-command' _Windows_
Emitted when an [App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx) Emitted when an [App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx)
is invoked. These are typically related to keyboard media keys or browser is invoked. These are typically related to keyboard media keys or browser

View file

@ -103,7 +103,7 @@ Registers a protocol of `scheme` that will send a `String` as a response. The
Registers a protocol of `scheme` that will send an HTTP request as a response. Registers a protocol of `scheme` that will send an HTTP request as a response.
The `callback` should be called with an object that has the `url`, `method`, The `callback` should be called with an object that has the `url`, `method`,
`referer`, and `session` properties. `referrer`, and `session` properties.
By default the HTTP request will reuse the current session. If you want the By default the HTTP request will reuse the current session. If you want the
request to have a different session you should set `session` to `null`. request to have a different session you should set `session` to `null`.

View file

@ -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 ## Methods
The `session` object has the following 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 Disables any network emulation already active for the `session`. Resets to
the original network configuration. 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);
});
```

View file

@ -175,7 +175,8 @@ Sets the title displayed aside of the tray icon in the status bar.
* `highlight` Boolean * `highlight` Boolean
Sets whether the tray icon is highlighted when it is clicked. Sets whether the tray icon's background becomes highlighted (in blue)
when the tray icon is clicked. Defaults to true.
### `Tray.displayBalloon(options)` _Windows_ ### `Tray.displayBalloon(options)` _Windows_

View file

@ -167,6 +167,39 @@ Emitted when DevTools is closed.
Emitted when DevTools is focused / opened. 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' ### Event: 'login'
Returns: Returns: