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/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");
}

View file

@ -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;

View file

@ -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);
}

View file

@ -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.

View file

@ -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) ->

View file

@ -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() {

View file

@ -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);
};

View file

@ -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));
}

View file

@ -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);

View file

@ -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) {}

View file

@ -106,13 +106,25 @@ unwrapArgs = (sender, args) ->
# Call a function and send reply asynchronously if it's a an asynchronous
# style function and the caller didn't pass a callback.
callFunction = (event, func, caller, args) ->
if v8Util.getHiddenValue(func, 'asynchronous') and typeof args[args.length - 1] isnt 'function'
args.push (ret) ->
funcMarkedAsync = v8Util.getHiddenValue(func, 'asynchronous')
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
func.apply caller, args
else
ret = func.apply caller, args
event.returnValue = valueToMeta event.sender, ret, true
catch e
# Catch functions thrown further down in function invocation and wrap
# them with the function name so it's easier to trace things like
# `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.
process.on 'ATOM_BROWSER_RELEASE_RENDER_VIEW', (id) ->

View file

@ -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

View file

@ -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);

View file

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

View file

@ -2,7 +2,7 @@
## 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.
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});
// cargar el index.html de nuestra aplicación.
mainWindow.loadUrl('file://' + __dirname + '/index.html');
mainWindow.loadURL('file://' + __dirname + '/index.html');
// Desplegar devtools.
mainWindow.openDevTools();

View file

@ -74,7 +74,7 @@ app.on('ready', function() {
mainWindow = new BrowserWindow({width: 800, height: 600});
// and load the index.html of the app.
mainWindow.loadUrl('file://' + __dirname + '/index.html');
mainWindow.loadURL('file://' + __dirname + '/index.html');
// Open the devtools.
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.
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
mínimo, controlado por JavaScript.
### 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
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.
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
renderizador da página web deve se comunicar com o processo principal para requisitar
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`
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();
// 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.
var mainWindow = null;
@ -106,7 +106,7 @@ app.on('ready', function() {
mainWindow = new BrowserWindow({width: 800, height: 600});
// e carrega o index.html do app.
mainWindow.loadUrl('file://' + __dirname + '/index.html');
mainWindow.loadURL('file://' + __dirname + '/index.html');
// Abre os DevTools.
mainWindow.openDevTools();
@ -187,6 +187,6 @@ $ ./Electron.app/Contents/MacOS/Electron your-app/
### 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
empacotado.

View file

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

View file

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

View file

@ -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]);
})

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.
### 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)
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.
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
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
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);
});
```

View file

@ -175,7 +175,8 @@ Sets the title displayed aside of the tray icon in the status bar.
* `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_

View file

@ -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: