Merge master

This commit is contained in:
Jessica Lord 2015-09-02 10:19:08 -07:00
commit bd20104e5a
89 changed files with 1741 additions and 1059 deletions

View file

@ -6,7 +6,7 @@
### [Electron](https://github.com/atom/electron/) 한국어 참조문서
:zap: *이전까지 Atom Shell로 알려져 있었습니다* :zap:
:zap: *프레임워크 이름이 Atom Shell에서 Electron으로 바뀌었습니다* :zap:
Electron 프레임워크는 JavaScript, HTML 그리고 CSS를 사용하여 Cross-Platform 데스크톱 어플리케이션을 개발할 수 있도록 해주는 프레임워크입니다. 이 프레임워크는 [io.js](http://iojs.org) 와
[Chromium](http://www.chromium.org)을 기반으로 만들어 졌으며 [Atom Editor](https://github.com/atom/atom)에 사용되고 있습니다.
@ -36,7 +36,7 @@ npm install electron-prebuilt --save-dev
[Docs](https://github.com/atom/electron/tree/master/docs/README.md)에 개발 가이드와 API 레퍼런스가 있습니다.
Electron을 빌드 하는 방법과 프로젝트에 기여하는 방법도 문서에 포함되어 있으니 참고하시기 바랍니다.
## 참조 문서(번역)
## 참조 문서 (번역)
- [한국어](https://github.com/atom/electron/tree/master/docs-translations/ko)
- [일본어](https://github.com/atom/electron/tree/master/docs-translations/jp)

View file

@ -48,6 +48,7 @@ contains documents describing how to build and contribute to Electron.
- [Korean](https://github.com/atom/electron/tree/master/docs-translations/ko)
- [Japanese](https://github.com/atom/electron/tree/master/docs-translations/jp)
- [Spanish](https://github.com/atom/electron/tree/master/docs-translations/es)
- [Simplified Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-CN)
## Community

View file

@ -4,7 +4,7 @@
'product_name%': 'Electron',
'company_name%': 'GitHub, Inc',
'company_abbr%': 'github',
'version%': '0.31.0',
'version%': '0.31.2',
},
'includes': [
'filenames.gypi',

View file

@ -107,6 +107,10 @@ void Menu::SetSublabel(int index, const base::string16& sublabel) {
model_->SetSublabel(index, sublabel);
}
void Menu::SetRole(int index, const base::string16& role) {
model_->SetRole(index, role);
}
void Menu::Clear() {
model_->Clear();
}
@ -154,6 +158,7 @@ void Menu::BuildPrototype(v8::Isolate* isolate,
.SetMethod("insertSubMenu", &Menu::InsertSubMenuAt)
.SetMethod("setIcon", &Menu::SetIcon)
.SetMethod("setSublabel", &Menu::SetSublabel)
.SetMethod("setRole", &Menu::SetRole)
.SetMethod("clear", &Menu::Clear)
.SetMethod("getIndexOfCommandId", &Menu::GetIndexOfCommandId)
.SetMethod("getItemCount", &Menu::GetItemCount)

View file

@ -73,6 +73,7 @@ class Menu : public mate::Wrappable,
Menu* menu);
void SetIcon(int index, const gfx::Image& image);
void SetSublabel(int index, const base::string16& sublabel);
void SetRole(int index, const base::string16& role);
void Clear();
int GetIndexOfCommandId(int command_id);
int GetItemCount() const;

View file

@ -9,6 +9,7 @@
#include "atom/browser/api/atom_api_cookies.h"
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/api/atom_api_web_contents.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"
@ -101,6 +102,19 @@ struct Converter<ClearStorageDataOptions> {
}
};
template<>
struct Converter<content::DownloadItem*> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
content::DownloadItem* val) {
mate::Dictionary dict(isolate, v8::Object::New(isolate));
dict.Set("url", val->GetURL());
dict.Set("filename", val->GetSuggestedFilename());
dict.Set("mimeType", val->GetMimeType());
dict.Set("hasUserGesture", val->HasUserGesture());
return dict.GetHandle();
}
};
} // namespace mate
namespace atom {
@ -109,6 +123,10 @@ namespace api {
namespace {
// The wrapSession funtion which is implemented in JavaScript
using WrapSessionCallback = base::Callback<void(v8::Local<v8::Value>)>;
WrapSessionCallback g_wrap_session;
class ResolveProxyHelper {
public:
ResolveProxyHelper(AtomBrowserContext* browser_context,
@ -215,9 +233,28 @@ void SetProxyInIO(net::URLRequestContextGetter* getter,
Session::Session(AtomBrowserContext* browser_context)
: browser_context_(browser_context) {
AttachAsUserData(browser_context);
// Observe DownloadManger to get download notifications.
auto download_manager =
content::BrowserContext::GetDownloadManager(browser_context);
download_manager->AddObserver(this);
}
Session::~Session() {
auto download_manager =
content::BrowserContext::GetDownloadManager(browser_context_);
download_manager->RemoveObserver(this);
}
void Session::OnDownloadCreated(content::DownloadManager* manager,
content::DownloadItem* item) {
auto web_contents = item->GetWebContents();
bool prevent_default = Emit("will-download", item,
api::WebContents::CreateFrom(isolate(),
web_contents));
if (prevent_default) {
item->Cancel(true);
item->Remove();
}
}
void Session::ResolveProxy(const GURL& url, ResolveProxyCallback callback) {
@ -288,9 +325,33 @@ mate::Handle<Session> Session::CreateFrom(
if (existing)
return mate::CreateHandle(isolate, static_cast<Session*>(existing));
return mate::CreateHandle(isolate, new Session(browser_context));
auto handle = mate::CreateHandle(isolate, new Session(browser_context));
g_wrap_session.Run(handle.ToV8());
return handle;
}
void SetWrapSession(const WrapSessionCallback& callback) {
g_wrap_session = callback;
}
void ClearWrapSession() {
g_wrap_session.Reset();
}
} // namespace api
} // namespace atom
namespace {
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.SetMethod("_setWrapSession", &atom::api::SetWrapSession);
dict.SetMethod("_clearWrapSession", &atom::api::ClearWrapSession);
}
} // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_session, Initialize)

View file

@ -8,6 +8,7 @@
#include <string>
#include "atom/browser/api/trackable_object.h"
#include "content/public/browser/download_manager.h"
#include "native_mate/handle.h"
#include "net/base/completion_callback.h"
@ -27,7 +28,8 @@ class AtomBrowserContext;
namespace api {
class Session: public mate::TrackableObject<Session> {
class Session: public mate::TrackableObject<Session>,
public content::DownloadManager::Observer {
public:
using ResolveProxyCallback = base::Callback<void(std::string)>;
@ -41,6 +43,10 @@ class Session: public mate::TrackableObject<Session> {
explicit Session(AtomBrowserContext* browser_context);
~Session();
// content::DownloadManager::Observer:
void OnDownloadCreated(content::DownloadManager* manager,
content::DownloadItem* item) override;
// mate::Wrappable implementations:
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;

View file

@ -10,8 +10,8 @@
#include "atom/browser/api/trackable_object.h"
#include "atom/browser/common_web_contents_delegate.h"
#include "content/public/common/favicon_url.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/favicon_url.h"
#include "native_mate/handle.h"
#include "ui/gfx/image/image.h"

View file

@ -1,10 +1,15 @@
EventEmitter = require('events').EventEmitter
bindings = process.atomBinding 'app'
sessionBindings = process.atomBinding 'session'
app = bindings.app
app.__proto__ = EventEmitter.prototype
wrapSession = (session) ->
# session is an Event Emitter.
session.__proto__ = EventEmitter.prototype
app.setApplicationMenu = (menu) ->
require('menu').setApplicationMenu menu
@ -41,5 +46,9 @@ app.getDataPath = -> @getPath 'userData'
app.setDataPath = (path) -> @setPath 'userData', path
app.resolveProxy = -> @defaultSession.resolveProxy.apply @defaultSession, arguments
# Session wrapper.
sessionBindings._setWrapSession wrapSession
process.once 'exit', sessionBindings._clearWrapSession
# Only one App object pemitted.
module.exports = app

View file

@ -62,6 +62,12 @@ BrowserWindow::loadUrl = -> @webContents.loadUrl.apply @webContents, arguments
BrowserWindow::send = -> @webContents.send.apply @webContents, arguments
# Be compatible with old API.
BrowserWindow::undo = -> @webContents.undo()
BrowserWindow::redo = -> @webContents.redo()
BrowserWindow::cut = -> @webContents.cut()
BrowserWindow::copy = -> @webContents.copy()
BrowserWindow::paste = -> @webContents.paste()
BrowserWindow::selectAll = -> @webContents.selectAll()
BrowserWindow::restart = -> @webContents.reload()
BrowserWindow::getUrl = -> @webContents.getUrl()
BrowserWindow::reload = -> @webContents.reload.apply @webContents, arguments

View file

@ -3,18 +3,30 @@ v8Util = process.atomBinding 'v8_util'
nextCommandId = 0
# Maps role to methods of webContents
rolesMap =
undo: 'undo'
redo: 'redo'
cut: 'cut'
copy: 'copy'
paste: 'paste'
selectall: 'selectAll'
minimize: 'minimize'
close: 'close'
class MenuItem
@types = ['normal', 'separator', 'submenu', 'checkbox', 'radio']
constructor: (options) ->
Menu = require 'menu'
{click, @selector, @type, @label, @sublabel, @accelerator, @icon, @enabled, @visible, @checked, @submenu} = options
{click, @selector, @type, @role, @label, @sublabel, @accelerator, @icon, @enabled, @visible, @checked, @submenu} = options
@type = 'submenu' if not @type? and @submenu?
throw new Error('Invalid submenu') if @type is 'submenu' and @submenu?.constructor isnt Menu
@overrideReadOnlyProperty 'type', 'normal'
@overrideReadOnlyProperty 'role'
@overrideReadOnlyProperty 'accelerator'
@overrideReadOnlyProperty 'icon'
@overrideReadOnlyProperty 'submenu'
@ -27,12 +39,14 @@ class MenuItem
throw new Error("Unknown menu type #{@type}") if MenuItem.types.indexOf(@type) is -1
@commandId = ++nextCommandId
@click = =>
@click = (focusedWindow) =>
# Manually flip the checked flags when clicked.
@checked = !@checked if @type in ['checkbox', 'radio']
if typeof click is 'function'
click this, BrowserWindow.getFocusedWindow()
if @role and rolesMap[@role] and process.platform isnt 'darwin'
focusedWindow?[rolesMap[@role]]()
else if typeof click is 'function'
click this, focusedWindow
else if typeof @selector is 'string'
Menu.sendActionToFirstResponder @selector

View file

@ -67,7 +67,8 @@ Menu::_init = ->
isCommandIdVisible: (commandId) => @commandsMap[commandId]?.visible
getAcceleratorForCommandId: (commandId) => @commandsMap[commandId]?.accelerator
getIconForCommandId: (commandId) => @commandsMap[commandId]?.icon
executeCommand: (commandId) => @commandsMap[commandId]?.click()
executeCommand: (commandId) =>
@commandsMap[commandId]?.click BrowserWindow.getFocusedWindow()
menuWillShow: =>
# Make sure radio groups have at least one menu item seleted.
for id, group of @groupsMap
@ -115,6 +116,7 @@ Menu::insert = (pos, item) ->
@setSublabel pos, item.sublabel if item.sublabel?
@setIcon pos, item.icon if item.icon?
@setRole pos, item.role if item.role?
# Make menu accessable to items.
item.overrideReadOnlyProperty 'menu', this

View file

@ -36,238 +36,176 @@ app.once('ready', function() {
if (Menu.getApplicationMenu())
return;
var template;
var template = [
{
label: 'Edit',
submenu: [
{
label: 'Undo',
accelerator: 'CmdOrCtrl+Z',
role: 'undo'
},
{
label: 'Redo',
accelerator: 'Shift+CmdOrCtrl+Z',
role: 'redo'
},
{
type: 'separator'
},
{
label: 'Cut',
accelerator: 'CmdOrCtrl+X',
role: 'cut'
},
{
label: 'Copy',
accelerator: 'CmdOrCtrl+C',
role: 'copy'
},
{
label: 'Paste',
accelerator: 'CmdOrCtrl+V',
role: 'paste'
},
{
label: 'Select All',
accelerator: 'CmdOrCtrl+A',
role: 'selectall'
},
]
},
{
label: 'View',
submenu: [
{
label: 'Reload',
accelerator: 'CmdOrCtrl+R',
click: function(item, focusedWindow) {
if (focusedWindow)
focusedWindow.reload();
}
},
{
label: 'Toggle Full Screen',
accelerator: (function() {
if (process.platform == 'darwin')
return 'Ctrl+Command+F';
else
return 'F11';
})(),
click: function(item, focusedWindow) {
if (focusedWindow)
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
}
},
{
label: 'Toggle Developer Tools',
accelerator: (function() {
if (process.platform == 'darwin')
return 'Alt+Command+I';
else
return 'Ctrl+Shift+I';
})(),
click: function(item, focusedWindow) {
if (focusedWindow)
focusedWindow.toggleDevTools();
}
},
]
},
{
label: 'Window',
role: 'window',
submenu: [
{
label: 'Minimize',
accelerator: 'CmdOrCtrl+M',
role: 'minimize'
},
{
label: 'Close',
accelerator: 'CmdOrCtrl+W',
role: 'close'
},
]
},
{
label: 'Help',
role: 'help',
submenu: [
{
label: 'Learn More',
click: function() { require('shell').openExternal('http://electron.atom.io') }
},
{
label: 'Documentation',
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
},
{
label: 'Community Discussions',
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
},
{
label: 'Search Issues',
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
}
]
},
];
if (process.platform == 'darwin') {
template = [
template.unshift({
label: 'Electron',
submenu: [
{
label: 'About Electron',
role: 'about'
},
{
type: 'separator'
},
{
label: 'Services',
role: 'services',
submenu: []
},
{
type: 'separator'
},
{
label: 'Hide Electron',
accelerator: 'Command+H',
role: 'hide'
},
{
label: 'Hide Others',
accelerator: 'Command+Shift+H',
role: 'hideothers:'
},
{
label: 'Show All',
role: 'unhide:'
},
{
type: 'separator'
},
{
label: 'Quit',
accelerator: 'Command+Q',
click: function() { app.quit(); }
},
]
});
template[3].submenu.push(
{
label: 'Electron',
submenu: [
{
label: 'About Electron',
selector: 'orderFrontStandardAboutPanel:'
},
{
type: 'separator'
},
{
label: 'Services',
submenu: []
},
{
type: 'separator'
},
{
label: 'Hide Electron',
accelerator: 'Command+H',
selector: 'hide:'
},
{
label: 'Hide Others',
accelerator: 'Command+Shift+H',
selector: 'hideOtherApplications:'
},
{
label: 'Show All',
selector: 'unhideAllApplications:'
},
{
type: 'separator'
},
{
label: 'Quit',
accelerator: 'Command+Q',
click: function() { app.quit(); }
},
]
type: 'separator'
},
{
label: 'Edit',
submenu: [
{
label: 'Undo',
accelerator: 'Command+Z',
selector: 'undo:'
},
{
label: 'Redo',
accelerator: 'Shift+Command+Z',
selector: 'redo:'
},
{
type: 'separator'
},
{
label: 'Cut',
accelerator: 'Command+X',
selector: 'cut:'
},
{
label: 'Copy',
accelerator: 'Command+C',
selector: 'copy:'
},
{
label: 'Paste',
accelerator: 'Command+V',
selector: 'paste:'
},
{
label: 'Select All',
accelerator: 'Command+A',
selector: 'selectAll:'
},
]
},
{
label: 'View',
submenu: [
{
label: 'Reload',
accelerator: 'Command+R',
click: function() {
var focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow)
focusedWindow.reload();
}
},
{
label: 'Toggle Full Screen',
accelerator: 'Ctrl+Command+F',
click: function() {
var focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow)
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
}
},
{
label: 'Toggle Developer Tools',
accelerator: 'Alt+Command+I',
click: function() {
var focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow)
focusedWindow.toggleDevTools();
}
},
]
},
{
label: 'Window',
submenu: [
{
label: 'Minimize',
accelerator: 'Command+M',
selector: 'performMiniaturize:'
},
{
label: 'Close',
accelerator: 'Command+W',
selector: 'performClose:'
},
{
type: 'separator'
},
{
label: 'Bring All to Front',
selector: 'arrangeInFront:'
},
]
},
{
label: 'Help',
submenu: [
{
label: 'Learn More',
click: function() { require('shell').openExternal('http://electron.atom.io') }
},
{
label: 'Documentation',
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
},
{
label: 'Community Discussions',
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
},
{
label: 'Search Issues',
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
}
]
label: 'Bring All to Front',
role: 'front'
}
];
} else {
template = [
{
label: '&File',
submenu: [
{
label: '&Open',
accelerator: 'Ctrl+O',
},
{
label: '&Close',
accelerator: 'Ctrl+W',
click: function() {
var focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow)
focusedWindow.close();
}
},
]
},
{
label: '&View',
submenu: [
{
label: '&Reload',
accelerator: 'Ctrl+R',
click: function() {
var focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow)
focusedWindow.reload();
}
},
{
label: 'Toggle &Full Screen',
accelerator: 'F11',
click: function() {
var focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow)
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
}
},
{
label: 'Toggle &Developer Tools',
accelerator: 'Shift+Ctrl+I',
click: function() {
var focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow)
focusedWindow.toggleDevTools();
}
},
]
},
{
label: 'Help',
submenu: [
{
label: 'Learn More',
click: function() { require('shell').openExternal('http://electron.atom.io') }
},
{
label: 'Documentation',
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
},
{
label: 'Community Discussions',
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
},
{
label: 'Search Issues',
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
}
]
}
];
);
}
var menu = Menu.buildFromTemplate(template);

View file

@ -57,13 +57,19 @@ ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', (event, guestId, me
if guestContents?.getUrl().indexOf(targetOrigin) is 0 or targetOrigin is '*'
guestContents.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', message, targetOrigin
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', (event, message, targetOrigin) ->
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', (event, guestId, message, targetOrigin, sourceOrigin) ->
embedder = v8Util.getHiddenValue event.sender, 'embedder'
if embedder?.getUrl().indexOf(targetOrigin) is 0 or targetOrigin is '*'
embedder.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', message, targetOrigin
embedder.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', guestId, message, sourceOrigin
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', (event, guestId, method, args...) ->
BrowserWindow.fromId(guestId)?.webContents?[method] args...
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_IS_GUEST_WINDOW', (event) ->
event.returnValue = v8Util.getHiddenValue(event.sender, 'embedder') isnt undefined
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_GET_GUEST_ID', (event) ->
embedder = v8Util.getHiddenValue event.sender, 'embedder'
if embedder?
guest = BrowserWindow.fromWebContents event.sender
if guest?
event.returnValue = guest.id
return
event.returnValue = null

View file

@ -17,7 +17,7 @@
<key>CFBundleIconFile</key>
<string>atom.icns</string>
<key>CFBundleVersion</key>
<string>0.31.0</string>
<string>0.31.2</string>
<key>LSMinimumSystemVersion</key>
<string>10.8.0</string>
<key>NSMainNibFile</key>

View file

@ -56,8 +56,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,31,0,0
PRODUCTVERSION 0,31,0,0
FILEVERSION 0,31,2,0
PRODUCTVERSION 0,31,2,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -74,12 +74,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "GitHub, Inc."
VALUE "FileDescription", "Electron"
VALUE "FileVersion", "0.31.0"
VALUE "FileVersion", "0.31.2"
VALUE "InternalName", "electron.exe"
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
VALUE "OriginalFilename", "electron.exe"
VALUE "ProductName", "Electron"
VALUE "ProductVersion", "0.31.0"
VALUE "ProductVersion", "0.31.2"
VALUE "SquirrelAwareVersion", "1"
END
END

View file

@ -4,6 +4,8 @@
#include "atom/browser/ui/atom_menu_model.h"
#include "base/stl_util.h"
namespace atom {
AtomMenuModel::AtomMenuModel(Delegate* delegate)
@ -14,6 +16,17 @@ AtomMenuModel::AtomMenuModel(Delegate* delegate)
AtomMenuModel::~AtomMenuModel() {
}
void AtomMenuModel::SetRole(int index, const base::string16& role) {
roles_[index] = role;
}
base::string16 AtomMenuModel::GetRoleAt(int index) {
if (ContainsKey(roles_, index))
return roles_[index];
else
return base::string16();
}
void AtomMenuModel::MenuClosed() {
ui::SimpleMenuModel::MenuClosed();
FOR_EACH_OBSERVER(Observer, observers_, MenuClosed());

View file

@ -5,6 +5,8 @@
#ifndef ATOM_BROWSER_UI_ATOM_MENU_MODEL_H_
#define ATOM_BROWSER_UI_ATOM_MENU_MODEL_H_
#include <map>
#include "base/observer_list.h"
#include "ui/base/models/simple_menu_model.h"
@ -31,12 +33,16 @@ class AtomMenuModel : public ui::SimpleMenuModel {
void AddObserver(Observer* obs) { observers_.AddObserver(obs); }
void RemoveObserver(Observer* obs) { observers_.RemoveObserver(obs); }
void SetRole(int index, const base::string16& role);
base::string16 GetRoleAt(int index);
// ui::SimpleMenuModel:
void MenuClosed() override;
private:
Delegate* delegate_; // weak ref.
std::map<int, base::string16> roles_;
ObserverList<Observer> observers_;
DISALLOW_COPY_AND_ASSIGN(AtomMenuModel);

View file

@ -59,17 +59,4 @@ class MenuModel;
@end
// Exposed only for unit testing, do not call directly.
@interface AtomMenuController (PrivateExposedForTesting)
- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item;
@end
// Protected methods that subclassers can override.
@interface AtomMenuController (Protected)
- (void)addItemToMenu:(NSMenu*)menu
atIndex:(NSInteger)index
fromModel:(ui::MenuModel*)model;
- (NSMenu*)menuFromModel:(ui::MenuModel*)model;
@end
#endif // ATOM_BROWSER_UI_COCOA_ATOM_MENU_CONTROLLER_H_

View file

@ -8,16 +8,36 @@
#include "atom/browser/ui/atom_menu_model.h"
#include "base/logging.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/base/accelerators/platform_accelerator_cocoa.h"
#include "ui/base/l10n/l10n_util_mac.h"
#include "ui/events/cocoa/cocoa_event_utils.h"
#include "ui/gfx/image/image.h"
@interface AtomMenuController (Private)
- (void)addSeparatorToMenu:(NSMenu*)menu
atIndex:(int)index;
@end
namespace {
struct Role {
SEL selector;
const char* role;
};
Role kRolesMap[] = {
{ @selector(orderFrontStandardAboutPanel:), "about" },
{ @selector(hide:), "hide" },
{ @selector(hideOtherApplications:), "hideothers" },
{ @selector(unhideAllApplications:), "unhide" },
{ @selector(arrangeInFront:), "front" },
{ @selector(undo:), "undo" },
{ @selector(redo:), "redo" },
{ @selector(cut:), "cut" },
{ @selector(copy:), "copy" },
{ @selector(paste:), "paste" },
{ @selector(selectAll:), "selectall" },
{ @selector(performMiniaturize:), "minimize" },
{ @selector(performClose:), "close" },
};
} // namespace
@implementation AtomMenuController
@ -101,7 +121,9 @@
// associated with the entry in the model identified by |modelIndex|.
- (void)addItemToMenu:(NSMenu*)menu
atIndex:(NSInteger)index
fromModel:(ui::MenuModel*)model {
fromModel:(ui::MenuModel*)ui_model {
atom::AtomMenuModel* model = static_cast<atom::AtomMenuModel*>(ui_model);
base::string16 label16 = model->GetLabelAt(index);
NSString* label = l10n_util::FixUpWindowsStyleLabel(label16);
base::scoped_nsobject<NSMenuItem> item(
@ -124,13 +146,13 @@
[submenu setTitle:[item title]];
[item setSubmenu:submenu];
// Hack to set window and help menu.
if ([[item title] isEqualToString:@"Window"] && [submenu numberOfItems] > 0)
// Set submenu's role.
base::string16 role = model->GetRoleAt(index);
if (role == base::ASCIIToUTF16("window"))
[NSApp setWindowsMenu:submenu];
else if ([[item title] isEqualToString:@"Help"])
else if (role == base::ASCIIToUTF16("help"))
[NSApp setHelpMenu:submenu];
if ([[item title] isEqualToString:@"Services"] &&
[submenu numberOfItems] == 0)
if (role == base::ASCIIToUTF16("services"))
[NSApp setServicesMenu:submenu];
} else {
// The MenuModel works on indexes so we can't just set the command id as the
@ -139,7 +161,6 @@
// model. Setting the target to |self| allows this class to participate
// in validation of the menu items.
[item setTag:index];
[item setTarget:self];
NSValue* modelObject = [NSValue valueWithPointer:model];
[item setRepresentedObject:modelObject]; // Retains |modelObject|.
ui::Accelerator accelerator;
@ -153,6 +174,19 @@
platformAccelerator->modifier_mask()];
}
}
// Set menu item's role.
base::string16 role = model->GetRoleAt(index);
if (role.empty()) {
[item setTarget:self];
} else {
for (const Role& pair : kRolesMap) {
if (role == base::ASCIIToUTF16(pair.role)) {
[item setAction:pair.selector];
break;
}
}
}
}
[menu insertItem:item atIndex:index];
}

View file

@ -11,6 +11,7 @@
#include "atom/common/chrome_version.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "base/logging.h"
#include "base/process/process_metrics.h"
#include "native_mate/dictionary.h"
#include "atom/common/node_includes.h"
@ -61,6 +62,9 @@ void AtomBindings::BindTo(v8::Isolate* isolate,
dict.SetMethod("crash", &Crash);
dict.SetMethod("hang", &Hang);
dict.SetMethod("log", &Log);
#if defined(OS_POSIX)
dict.SetMethod("setFdLimit", &base::SetFdLimit);
#endif
dict.SetMethod("activateUvLoop",
base::Bind(&AtomBindings::ActivateUVLoop, base::Unretained(this)));

View file

@ -7,7 +7,7 @@
#define ATOM_MAJOR_VERSION 0
#define ATOM_MINOR_VERSION 31
#define ATOM_PATCH_VERSION 0
#define ATOM_PATCH_VERSION 2
#define ATOM_VERSION_IS_RELEASE 1

View file

@ -40,6 +40,7 @@ REFERENCE_MODULE(atom_browser_power_monitor);
REFERENCE_MODULE(atom_browser_power_save_blocker);
REFERENCE_MODULE(atom_browser_protocol);
REFERENCE_MODULE(atom_browser_global_shortcut);
REFERENCE_MODULE(atom_browser_session);
REFERENCE_MODULE(atom_browser_tray);
REFERENCE_MODULE(atom_browser_web_contents);
REFERENCE_MODULE(atom_browser_web_view_manager);

View file

@ -52,10 +52,6 @@ bool IsSwitchEnabled(base::CommandLine* command_line,
return true;
}
bool IsGuestFrame(blink::WebFrame* frame) {
return frame->uniqueName().utf8() == "ATOM_SHELL_GUEST_WEB_VIEW";
}
// global.Uint8Array;
v8::Local<v8::Function> GetUint8ArrayConstructor(
v8::Isolate* isolate, v8::Local<v8::Context> context) {
@ -113,8 +109,7 @@ class AtomRenderFrameObserver : public content::RenderFrameObserver {
AtomRendererClient::AtomRendererClient()
: node_bindings_(NodeBindings::Create(false)),
atom_bindings_(new AtomBindings),
main_frame_(nullptr) {
atom_bindings_(new AtomBindings) {
}
AtomRendererClient::~AtomRendererClient() {
@ -189,14 +184,9 @@ bool AtomRendererClient::OverrideCreatePlugin(
void AtomRendererClient::DidCreateScriptContext(
blink::WebFrame* frame,
v8::Handle<v8::Context> context) {
// Only attach node bindings in main frame or guest frame.
if (!IsGuestFrame(frame)) {
if (main_frame_)
return;
// The first web frame is the main frame.
main_frame_ = frame;
}
// Only insert node integration for the main frame.
if (frame->parent())
return;
// Give the node loop a run to make sure everything is ready.
node_bindings_->RunMessageLoop();
@ -221,10 +211,6 @@ bool AtomRendererClient::ShouldFork(blink::WebFrame* frame,
bool is_initial_navigation,
bool is_server_redirect,
bool* send_referrer) {
// Never fork renderer process for guests.
if (IsGuestFrame(frame))
return false;
// Handle all the navigations and reloads in browser.
// FIXME We only support GET here because http method will be ignored when
// the OpenURLFromTab is triggered, which means form posting would not work,

View file

@ -64,9 +64,6 @@ class AtomRendererClient : public content::ContentRendererClient,
scoped_ptr<NodeBindings> node_bindings_;
scoped_ptr<AtomBindings> atom_bindings_;
// The main frame.
blink::WebFrame* main_frame_;
DISALLOW_COPY_AND_ASSIGN(AtomRendererClient);
};

View file

@ -29,8 +29,6 @@ for arg in process.argv
if arg.indexOf('--guest-instance-id=') == 0
# This is a guest web view.
process.guestInstanceId = parseInt arg.substr(arg.indexOf('=') + 1)
# Set the frame name to make AtomRendererClient recognize this guest.
require('web-frame').setName 'ATOM_SHELL_GUEST_WEB_VIEW'
else if arg.indexOf('--node-integration=') == 0
nodeIntegration = arg.substr arg.indexOf('=') + 1
else if arg.indexOf('--preload=') == 0

View file

@ -94,14 +94,22 @@ window.confirm = (message, title='') ->
window.prompt = ->
throw new Error('prompt() is and will not be supported.')
# Simple implementation of postMessage.
if ipc.sendSync 'ATOM_SHELL_GUEST_WINDOW_MANAGER_IS_GUEST_WINDOW'
# Implement window.postMessage if current window is a guest window.
guestId = ipc.sendSync 'ATOM_SHELL_GUEST_WINDOW_MANAGER_GET_GUEST_ID'
if guestId?
window.opener =
postMessage: (message, targetOrigin='*') ->
ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', message, targetOrigin
ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', guestId, message, targetOrigin, location.origin
ipc.on 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', (message, targetOrigin) ->
window.postMessage message, targetOrigin
ipc.on 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', (guestId, message, sourceOrigin) ->
# Manually dispatch event instead of using postMessage because we also need to
# set event.source.
event = document.createEvent 'Event'
event.initEvent 'message', false, false
event.data = message
event.origin = sourceOrigin
event.source = new BrowserWindowProxy(guestId)
window.dispatchEvent event
# Forward history operations to browser.
sendHistoryOperation = (args...) ->

View file

@ -220,64 +220,6 @@ PrintedDocument* PrintJob::document() const {
return document_.get();
}
void PrintJob::UpdatePrintedDocument(PrintedDocument* new_document) {
if (document_.get() == new_document)
return;
document_ = new_document;
if (document_.get()) {
settings_ = document_->settings();
}
if (worker_) {
DCHECK(!is_job_pending_);
// Sync the document with the worker.
worker_->PostTask(FROM_HERE,
base::Bind(&HoldRefCallback,
make_scoped_refptr(this),
base::Bind(&PrintJobWorker::OnDocumentChanged,
base::Unretained(worker_.get()),
document_)));
}
}
void PrintJob::OnNotifyPrintJobEvent(const JobEventDetails& event_details) {
switch (event_details.type()) {
case JobEventDetails::FAILED: {
settings_.Clear();
// No need to cancel since the worker already canceled itself.
Stop();
break;
}
case JobEventDetails::USER_INIT_DONE:
case JobEventDetails::DEFAULT_INIT_DONE:
case JobEventDetails::USER_INIT_CANCELED: {
DCHECK_EQ(event_details.document(), document_.get());
break;
}
case JobEventDetails::NEW_DOC:
case JobEventDetails::NEW_PAGE:
case JobEventDetails::JOB_DONE:
case JobEventDetails::ALL_PAGES_REQUESTED: {
// Don't care.
break;
}
case JobEventDetails::DOC_DONE: {
// This will call Stop() and broadcast a JOB_DONE message.
base::MessageLoop::current()->PostTask(
FROM_HERE, base::Bind(&PrintJob::OnDocumentDone, this));
break;
}
case JobEventDetails::PAGE_DONE:
break;
default: {
NOTREACHED();
break;
}
}
}
#if defined(OS_WIN)
class PrintJob::PdfToEmfState {
@ -375,6 +317,68 @@ void PrintJob::OnPdfToEmfPageConverted(int page_number,
#endif // OS_WIN
void PrintJob::UpdatePrintedDocument(PrintedDocument* new_document) {
if (document_.get() == new_document)
return;
document_ = new_document;
if (document_.get()) {
settings_ = document_->settings();
}
if (worker_) {
DCHECK(!is_job_pending_);
// Sync the document with the worker.
worker_->PostTask(FROM_HERE,
base::Bind(&HoldRefCallback,
make_scoped_refptr(this),
base::Bind(&PrintJobWorker::OnDocumentChanged,
base::Unretained(worker_.get()),
document_)));
}
}
void PrintJob::OnNotifyPrintJobEvent(const JobEventDetails& event_details) {
switch (event_details.type()) {
case JobEventDetails::FAILED: {
settings_.Clear();
// No need to cancel since the worker already canceled itself.
Stop();
break;
}
case JobEventDetails::USER_INIT_DONE:
case JobEventDetails::DEFAULT_INIT_DONE:
case JobEventDetails::USER_INIT_CANCELED: {
DCHECK_EQ(event_details.document(), document_.get());
break;
}
case JobEventDetails::NEW_DOC:
case JobEventDetails::NEW_PAGE:
case JobEventDetails::JOB_DONE:
case JobEventDetails::ALL_PAGES_REQUESTED: {
// Don't care.
break;
}
case JobEventDetails::DOC_DONE: {
// This will call Stop() and broadcast a JOB_DONE message.
base::MessageLoop::current()->PostTask(
FROM_HERE, base::Bind(&PrintJob::OnDocumentDone, this));
break;
}
case JobEventDetails::PAGE_DONE:
#if defined(OS_WIN)
ptd_to_emf_state_->OnPageProcessed(
base::Bind(&PrintJob::OnPdfToEmfPageConverted, this));
#endif // OS_WIN
break;
default: {
NOTREACHED();
break;
}
}
}
void PrintJob::OnDocumentDone() {
// Be sure to live long enough. The instance could be destroyed by the
// JOB_DONE broadcast.

View file

@ -20,11 +20,11 @@
* [프로세스 객체](api/process.md)
* [크롬 Command-Line 스위치 지원](api/chrome-command-line-switches.md)
커스텀 DOM Element:
커스텀 DOM elements:
* [`File` 객체](api/file-object.md)
* [`<webview>` 태그](api/web-view-tag.md)
* [`window.open` 함수](api/window-open.md)
* [`window.open` 메서드](api/window-open.md)
메인 프로세스를 위한 모듈들:
@ -40,6 +40,8 @@
* [power-monitor](api/power-monitor.md)
* [power-save-blocker](api/power-save-blocker.md)
* [protocol](api/protocol.md)
* [session](api/session.md)
* [webContents](api/web-contents.md)
* [tray](api/tray.md)
랜더러 프로세스를 위한 모듈들 (웹 페이지):
@ -60,7 +62,7 @@
* [코딩 스타일](development/coding-style.md)
* [소스 코드 디렉터리 구조](development/source-code-directory-structure.md)
* [NW.js와 기술적으로 다른점 (이전 node-webkit)](development/atom-shell-vs-node-webkit.md)
* [NW.js(node-webkit)와 기술적으로 다른점](development/atom-shell-vs-node-webkit.md)
* [빌드 시스템 개요](development/build-system-overview.md)
* [빌드 설명서 (Mac)](development/build-instructions-osx.md)
* [빌드 설명서 (Windows)](development/build-instructions-windows.md)

View file

@ -17,7 +17,7 @@ Squirrel은 어플리케이션이 **안전하고 투명한 업데이트**를 제
Squirrel은 사용자에게 어플리케이션의 업데이트를 알릴 필요 없이 서버가 지시하는 버전을 받아온 후 자동으로 업데이트합니다.
이 기능을 사용하면 Squirrel을 통해 클라이언트의 어플리케이션을 지능적으로 업데이트 할 수 있습니다.
요청시 커스텀 헤더 또는 요청 본문에 인증 정보를 포함시킬 수 있습니다.
또한 요청시 커스텀 헤더 또는 요청 본문에 인증 정보를 포함시킬 수 있습니다.
서버에선 이러한 요청을 분류 처리하여 적당한 업데이트를 제공할 수 있습니다.
Squirrel JSON 업데이트 요청시 처리는 반드시 어떤 업데이트가 필요한지 요청의 기준에 맞춰 동적으로 생성되어야 합니다.
@ -76,6 +76,12 @@ Squirrel은 "url"로 `Accept: application/zip` 헤더와 함께 업데이트 zip
`pub_date`은 ISO 8601 표준에 따라 포맷된 날짜입니다.
## 업데이트 서버 구현
[Nuts](https://github.com/GitbookIO/nuts)는 위에서 설명한 업데이트 서버의 오픈 소스 구현입니다.
이 구현은 Github 릴리즈와 완벽하게 통합되어 있습니다. Nuts는 `Squirrel.Mac``Squirrel.Windows`를 지원하고 다운로드와 업데이트를 관리합니다.
이 구현을 사용하면 cross-platform 지원을 신경 쓸 필요가 없습니다.
## Events
`autoUpdater` 객체는 다음과 같은 이벤트를 발생시킵니다:

View file

@ -1,6 +1,6 @@
# clipboard
`clipboard` 복사/붙여넣기 작업을 수행하는 방법을 제공합니다. 다음 예제는 클립보드에 문자열을 씁니다:
`clipboard` 모듈은 복사/붙여넣기 작업을 수행하는 방법을 제공합니다. 다음 예제는 클립보드에 문자열을 씁니다:
```javascript
var clipboard = require('clipboard');
@ -15,59 +15,65 @@ clipboard.writeText('Example String', 'selection');
console.log(clipboard.readText('selection'));
```
## clipboard.readText([type])
## Methods
* `type` String
`clipboard` 모듈은 다음과 같은 메서드를 가지고 있습니다:
**참고:** Experimental 마크가 붙은 API는 실험적인 기능이며 차후 최신 버전에서 제거될 수 있습니다.
### `clipboard.readText([type])`
* `type` String (optional)
클립보드 컨텐츠를 `plain text`로 반환합니다.
## clipboard.writeText(text[, type])
### `clipboard.writeText(text[, type])`
* `text` String
* `type` String
* `type` String (optional)
클립보드에 `plain text`로 문자열을 씁니다.
## clipboard.readHtml([type])
### `clipboard.readHtml([type])`
* `type` String
* `type` String (optional)
클립보드 컨텐츠를 `markup`으로 반환합니다.
## clipboard.writeHtml(markup[, type])
### `clipboard.writeHtml(markup[, type])`
* `markup` String
* `type` String
* `type` String (optional)
클립보드에 `markup`으로 씁니다.
## clipboard.readImage([type])
### `clipboard.readImage([type])`
* `type` String
* `type` String (optional)
클립보드로부터 [NativeImage](native-image.md)로 이미지를 읽어들입니다.
## clipboard.writeImage(image[, type])
### `clipboard.writeImage(image[, type])`
* `image` [NativeImage](native-image.md)
* `type` String
* `type` String (optional)
클립보드에 `image`를 씁니다.
## clipboard.clear([type])
### `clipboard.clear([type])`
* `type` String
* `type` String (optional)
클립보드에 저장된 모든 컨텐츠를 삭제합니다.
## clipboard.availableFormats([type])
### clipboard.availableFormats([type])
클립보드의 `type`에 해당하는 지원하는 `format`을 문자열로 반환합니다.
## clipboard.has(data[, type])
### `clipboard.has(data[, type])`
* `data` String
* `type` String
* `type` String (optional)
클립보드가 지정한 `data`의 형식을 지원하는지 확인합니다.
@ -76,24 +82,20 @@ var clipboard = require('clipboard');
console.log(clipboard.has('<p>selection</p>'));
```
**알림:** 이 API는 실험적인 기능이며 차후 최신버전에서 제외될 수 있습니다.
## clipboard.read(data[, type])
### `clipboard.read(data[, type])` _Experimental_
* `data` String
* `type` String
* `type` String (optional)
클립보드로부터 `data`를 읽어들입니다.
**알림:** 이 API는 실험적인 기능이며 차후 최신버전에서 제외될 수 있습니다.
## clipboard.write(data[, type])
### `clipboard.write(data[, type])` _Experimental_
* `data` Object
* `text` String
* `html` String
* `image` [NativeImage](native-image.md)
* `type` String
* `type` String (optional)
```javascript
var clipboard = require('clipboard');

View file

@ -1,30 +1,35 @@
# content-tracing
# contentTracing
`content-trace` 모듈은 Chromium 컨텐츠 모듈단에서 생성된 데이터를 수집하고 추적하는데 사용됩니다.
`content-tracing` 모듈은 Chromium 컨텐츠 모듈단에서 생성된 데이터를 수집하고 추적하는데 사용됩니다.
이 모듈은 웹 인터페이스를 포함하고 있지 않으며 크롬 브라우저에서 `chrome://tracing/` 페이지를 열어 생성된 파일을 로드하면 결과를 볼 수 있습니다.
```javascript
var tracing = require('content-tracing');
tracing.startRecording('*', tracing.DEFAULT_OPTIONS, function() {
var contentTracing = require('content-tracing');
contentTracing.startRecording('*', contentTracing.DEFAULT_OPTIONS, function() {
console.log('Tracing started');
setTimeout(function() {
tracing.stopRecording('', function(path) {
contentTracing.stopRecording('', function(path) {
console.log('Tracing data recorded to ' + path);
});
}, 5000);
});
```
``
## tracing.getCategories(callback)
## Methods
`content-tracing` 모듈은 다음과 같은 메서드를 가지고 있습니다:
### `contentTracing.getCategories(callback)`
* `callback` Function
카테고리 그룹 세트를 가져옵니다. 카테고리 그룹은 도달된 코드 경로를 변경할 수 있습니다.
모든 child 프로세스가 `getCategories` 요청을 받으면 `callback` 호출되며 인자에 카테고리 그룹의 배열이 전달됩니다.
모든 child 프로세스가 `getCategories` 요청을 승인하면 `callback`이 한 번 호출되며 인자에 카테고리 그룹의 배열이 전달됩니다.
## tracing.startRecording(categoryFilter, traceOptions, callback)
### `contentTracing.startRecording(categoryFilter, traceOptions, callback)`
* `categoryFilter` String
* `traceOptions` String
@ -33,7 +38,7 @@ tracing.startRecording('*', tracing.DEFAULT_OPTIONS, function() {
모든 프로세스에서 레코딩을 시작합니다.
레코딩은 지역적으로 즉시 실행됩니다. 그리고 비동기로 child 프로세스는 곧 EnableRecording 요청을 받게 됩니다.
모든 child 프로세스가 `startRecording` 요청을 받으면 `callback` 호출됩니다.
모든 child 프로세스가 `startRecording` 요청을 승인하면 `callback`이 한 번 호출됩니다.
`categoryFilter`는 어떤 카테고리 그룹이 트레이싱 되어야 하는지 필터링할 수 있습니다.
필터는 `-` 접두사를 통해 특정 카테고리 그룹을 제외할 수 있습니다.
@ -63,7 +68,7 @@ tracing.startRecording('*', tracing.DEFAULT_OPTIONS, function() {
`record-until-full`이 기본 모드, `enable-sampling``enable-systrace`옵션은 포함되지 않음
## tracing.stopRecording(resultFilePath, callback)
## `contentTracing.stopRecording(resultFilePath, callback)`
* `resultFilePath` String
* `callback` Function
@ -75,12 +80,12 @@ Child 프로세스는 일반적으로 추적 데이터와 희귀한 플러시
우리는 추적에 의한 런타임 오버헤드를 피하고자 합니다.
그래서 추적이 끝나면 모든 child 프로세스에 보류된 추적 데이터를 플러시 할 것인지 물어봅니다.
모든 child 프로세스가 `stopRecording` 요청을 받으면 `callback`에 추적 데이터를 포함한 파일을 전달됩니다.
모든 child 프로세스가 `stopRecording` 요청을 승인하면 `callback`에 추적 데이터 파일을 포함하여 한 번 호출됩니다.
추적 데이터는 `resultFilePath` 해당 경로가 비어있는 경우에 한 해 해당 경로에 작성되거나 임시 파일에 작성됩니다.
실제 파일 경로는 null이 아닌 이상 `callback`을 통해 전달됩니다.
## tracing.startMonitoring(categoryFilter, traceOptions, callback)
### `contentTracing.startMonitoring(categoryFilter, traceOptions, callback)`
* `categoryFilter` String
* `traceOptions` String
@ -90,17 +95,17 @@ Child 프로세스는 일반적으로 추적 데이터와 희귀한 플러시
모니터링은 지역적으로 즉시 시작됩니다. 그리고 이내 자식 프로세스들이 `startMonitoring` 비동기 요청을 받습니다.
모든 자식 프로세스가 `startMonitoring` 요청을 받으면 `callback` 호출됩니다.
모든 자식 프로세스가 `startMonitoring` 요청을 승인하면 `callback`이 한 번 호출됩니다.
## tracing.stopMonitoring(callback);
### `contentTracing.stopMonitoring(callback)`
* `callback` Function
모든 프로세스에서 모니터링을 중단합니다.
모든 자식 프로세스가 `stopMonitoring` 요청을 받으면 `callback` 호출됩니다.
모든 자식 프로세스가 `stopMonitoring` 요청을 승인하면 `callback`이 한 번 호출됩니다.
## tracing.captureMonitoringSnapshot(resultFilePath, callback)
### `contentTracing.captureMonitoringSnapshot(resultFilePath, callback)`
* `resultFilePath` String
* `callback` Function
@ -112,15 +117,15 @@ Child 프로세스는 일반적으로 추적 데이터와 희귀한 플러시
그리고 우리는 추적시 발생하는 불필요한 런타임 오버헤드를 피하고자 합니다.
그래서 추적이 끝나면 반드시 비동기로 자식 프로세스들의 보류된 추적 데이터를 플러시 할 것인지 물어봅니다.
모든 자식 프로세스가 `captureMonitoringSnapshot` 요청을 받으면 추적 데이터 파일을 포함하는 `callback`이 호출됩니다.
모든 자식 프로세스가 `captureMonitoringSnapshot` 요청을 승인하면 추적 데이터 파일을 포함하는 `callback` 한 번 호출됩니다.
## tracing.getTraceBufferUsage(callback)
### `contentTracing.getTraceBufferUsage(callback)`
* `callback` Function
추적 버퍼 % 전체 상태의 프로세스간 최대치를 가져옵니다. TraceBufferUsage 값이 결정되면 `callback`이 호출됩니다.
추적 버퍼 % 전체 상태의 프로세스간 최대치를 가져옵니다. TraceBufferUsage 값이 결정되면 `callback` 한 번 호출됩니다.
## tracing.setWatchEvent(categoryName, eventName, callback)
### `contentTracing.setWatchEvent(categoryName, eventName, callback)`
* `categoryName` String
* `eventName` String
@ -128,6 +133,6 @@ Child 프로세스는 일반적으로 추적 데이터와 희귀한 플러시
`callback`은 지정된 이벤트가 어떤 작업을 발생시킬 때마다 호출됩니다.
## tracing.cancelWatchEvent()
### `contentTracing.cancelWatchEvent()`
Watch 이벤트를 중단합니다. 만약 추적이 활성화되어 있다면 이 함수는 watch 이벤트 콜백과 race가 일어날 것입니다.
Watch 이벤트를 중단합니다. 만약 추적이 활성화되어 있다면 이 메서드는 watch 이벤트 콜백과 race가 일어날 것입니다.

View file

@ -1,9 +1,12 @@
# crash-reporter
# crashReporter
다음 예제는 윈격 서버에 어플리케이션 오류 정보를 자동으로 보고하는 예제입니다:
`crash-reporter` 모듈은 어플리케이션의 크래시 정보를 자동으로 원격 서버에 업로드하는데 사용합니다.
다음 예제는 윈격 서버에 어플리케이션 크래시 정보를 자동으로 보고하는 예제입니다:
```javascript
crashReporter = require('crash-reporter');
var crashReporter = require('crash-reporter');
crashReporter.start({
productName: 'YourName',
companyName: 'YourCompany',
@ -12,38 +15,42 @@ crashReporter.start({
});
```
## crashReporter.start(options)
## Methods
* `options` Object
* `productName` String, 기본값: Electron
* `companyName` String, 기본값: GitHub, Inc
* `submitUrl` String, 기본값: http://54.249.141.255:1127/post
* Crash Reporter는 POST 방식으로 해당 URL에 전송됩니다.
* `autoSubmit` Boolean, 기본값: true
* true로 지정할 경우 유저의 승인 없이 자동으로 오류를 보고합니다.
* `ignoreSystemCrashHandler` Boolean, 기본값: false
* `extra` Object
* 오류보고 시 같이 보낼 추가 정보를 지정하는 객체입니다.
* 문자열로 된 속성만 정상적으로 보내집니다.
* 중첩 객체는 지원되지 않습니다. (Nested objects are not supported)
`crash-reporter` 모듈은 다음과 같은 메서드를 가지고 있습니다:
### `crashReporter.start(options)`
* `options` Object, properties:
* `productName` String, 기본값: Electron
* `companyName` String, 기본값: GitHub, Inc
* `submitUrl` String, 기본값: http://54.249.141.255:1127/post
* 크래시 리포트는 POST 방식으로 이 URL로 전송됩니다.
* `autoSubmit` Boolean, 기본값: true
* true로 지정할 경우 유저의 승인 없이 자동으로 오류를 보고합니다.
* `ignoreSystemCrashHandler` Boolean, 기본값: false
* `extra` Object
* 크래시 리포트 시 같이 보낼 추가 정보를 지정하는 객체입니다.
* 문자열로 된 속성만 정상적으로 보내집니다.
* 중첩 객체는 지원되지 않습니다. (Nested objects are not supported)
다른 crashReporter API들을 사용하기 전에 이 함수를 먼저 호출해야 합니다.
다른 crashReporter API를 사용하기 전에 이 메서드를 먼저 호출해야 합니다.
**알림:** OS X에선 Windows와 Linux의 `breakpad`와 달리 새로운 `crashpad` 클라이언트를 사용합니다.
**참고:** OS X에선 Windows와 Linux의 `breakpad`와 달리 새로운 `crashpad` 클라이언트를 사용합니다.
오류 수집 기능을 활성화 시키려면 오류를 수집하고 싶은 메인 프로세스나 랜더러 프로세스에서
`crashReporter.start` 함수를 호출하여 `crashpad`를 초기화 해야합니다.
`crashReporter.start` 메서드를 호출하여 `crashpad`를 초기화 해야합니다.
## crashReporter.getLastCrashReport()
### `crashReporter.getLastCrashReport()`
마지막 오류보고의 날짜와 ID를 반환합니다.
이전 오류보고가 없거나 Crash Reporter가 시작되지 않았을 경우 `null`이 반환됩니다.
마지막 크래시 리포트의 날짜와 ID를 반환합니다.
이전 크래시 리포트가 없거나 Crash Reporter가 시작되지 않았을 경우 `null`이 반환됩니다.
## crashReporter.getUploadedReports()
### `crashReporter.getUploadedReports()`
모든 업로드된 오류보고를 반환합니다. 각 보고는 날짜와 업로드 ID를 포함하고 있습니다.
모든 업로드된 크래시 리포트를 반환합니다. 각 보고는 날짜와 업로드 ID를 포함하고 있습니다.
# crash-reporter 오류보고 형식
## crash-reporter 업로드 형식
Crash Reporter는 다음과 같은 데이터를 `submitUrl``POST` 방식으로 전송합니다:
@ -56,5 +63,5 @@ Crash Reporter는 다음과 같은 데이터를 `submitUrl`에 `POST` 방식으
* `_productName` String - Crash Reporter의 `options` 객체에서 정의한 제품명.
* `prod` String - 기본 제품의 이름. 이 경우 Electron으로 표시됩니다.
* `_companyName` String - Crash Reporter의 `options` 객체에서 정의한 회사명.
* `upload_file_minidump` File - 오류보고 파일
* `upload_file_minidump` File - 크래시 리포트 파일
* Crash Reporter의 `options` 객체에서 정의한 `extra` 객체의 속성들.

View file

@ -1,34 +1,39 @@
# dialog
`dialog` 모듈은 네이티브 시스템의 대화 상자를 조작할 때 사용할 수 있는 API입니다.
웹 어플리케이션에서 일반 네이티브 어플리케이션과 같은 사용자 경험을 제공할 수 있습니다.
`dialog` 모듈은 파일 열기, 알림과 같은 네이티브 시스템의 대화 상자를 조작할 때 사용할 수 있는 모듈입니다.
이 모듈을 사용하면 웹 어플리케이션에서 일반 네이티브 어플리케이션과 비슷한 사용자 경험을 제공할 수 있습니다.
다음 예제는 파일과 디렉터리를 다중으로 선택하는 대화 상자를 표시하는 예제입니다:
```javascript
var win = ...; // 대화 상자를 사용할 객체
var win = ...; // 대화 상자를 사용할 BrowserWindow 객체
var dialog = require('dialog');
console.log(dialog.showOpenDialog({ properties: [ 'openFile', 'openDirectory', 'multiSelections' ]}));
```
**OS X 주의**: 대화 상자를 시트처럼 보여지게 하려면 `browserWindow` 인자에 `BrowserWindow` 객체의 참조를 제공하면 됩니다.
**OS X 알림**: 대화 상자를 시트처럼 보여지게 하려면 `browserWindow` 인자에 `BrowserWindow` 객체의 참조를 제공하면 됩니다.
## dialog.showOpenDialog([browserWindow], [options], [callback])
## Methods
* `browserWindow` BrowserWindow
* `options` Object
`dialog` 모듈은 다음과 같은 메서드를 가지고 있습니다:
### `dialog.showOpenDialog([browserWindow][, options][, callback])`
* `browserWindow` BrowserWindow (optional)
* `options` Object (optional)
* `title` String
* `defaultPath` String
* `filters` Array
* `properties` Array - 대화 상자가 사용할 기능(모드)이 담긴 배열입니다.
다음을 포함할 수 있습니다: `openFile`, `openDirectory`, `multiSelections`, `createDirectory`
* `callback` Function
* `callback` Function (optional)
사용할 대화 상자의 기능이 담긴 배열입니다. 다음을 포함할 수 있습니다: `openFile`, `openDirectory`, `multiSelections`, `createDirectory`
작업에 성공하면 유저가 선택한 파일의 경로를 포함한 배열을 반환합니다. 그 외의 경우`undefined`를 반환합니다.
작업에 성공하면 콜백으로 유저가 선택한 파일의 경로를 포함한 배열을 반환합니다. 그 외엔 `undefined`를 반환합니다.
`filters`를 지정하면 유저가 선택 가능한 파일 형식을 지정할 수 있습니다. 예제는 다음과 같습니다:
`filters`를 지정하면 유저가 선택 가능한 파일 형식을 지정할 수 있습니다.
유저가 선택할 수 있는 타입에 제한을 두려면 다음과 같이 할 수 있습니다:
```javascript
{
@ -42,32 +47,30 @@ console.log(dialog.showOpenDialog({ properties: [ 'openFile', 'openDirectory', '
```
`extensions` 배열은 반드시 와일드카드와 마침표를 제외한 파일 확장자를 포함시켜야 합니다.
예를 들어 `'png'`는 가능하지만 `'.png'``'*.png'`는 안됩니다.
(예를 들어 `'png'`는 가능하지만 `'.png'``'*.png'`는 안됩니다)
모든 파일을 보여주려면 `'*'`와 같은 와일드카드를 사용하면 됩니다. (다른 와일드카드는 지원하지 않습니다)
`callback`이 전달되면 메소드가 비동기로 작동되며 결과는 `callback(filenames)`을 통해 전달됩니다.
Windows와 Linux에선 파일 선택 모드, 디렉터리 선택 모드를 동시에 사용할 수 없습니다.
그래서 이 두 플랫폼에선 `properties``['openFile', 'openDirectory']`로 설정하면 디렉터리 선택 대화 상자가 표시됩니다.
**참고:** Windows와 Linux에선 파일 선택 모드, 디렉터리 선택 모드를 동시에 사용할 수 없습니다.
이러한 이유로 `properties``['openFile', 'openDirectory']`로 설정하면 디렉터리 선택 대화 상자가 표시됩니다.
## dialog.showSaveDialog([browserWindow], [options], [callback])
### `dialog.showSaveDialog([browserWindow][, options][, callback])`
* `browserWindow` BrowserWindow
* `options` Object
* `browserWindow` BrowserWindow (optional)
* `options` Object (optional)
* `title` String
* `defaultPath` String
* `filters` Array
* `callback` Function
* `callback` Function (optional)
작업에 성공하면
작업에 성공하면 유저가 선택한 파일의 경로를 포함한 배열을 반환합니다. 그 외의 경우엔 `undefined`를 반환합니다.
작업에 성공하면 콜백으로 유저가 선택한 파일의 경로를 포함한 배열을 반환합니다. 그 외엔 `undefined`를 반환합니다.
`filters`를 지정하면 유저가 저장 가능한 파일 형식을 지정할 수 있습니다. 사용 방법은 `dialog.showOpenDialog``filters` 속성과 같습니다.
`callback`이 전달되면 메소드가 비동기로 작동되며 결과는 `callback(filename)`을 통해 전달됩니다.
## dialog.showMessageBox([browserWindow], options, [callback])
### `dialog.showMessageBox([browserWindow][, options][, callback])`
* `browserWindow` BrowserWindow
* `options` Object
@ -78,26 +81,26 @@ Windows와 Linux에선 파일 선택 모드, 디렉터리 선택 모드를 동
* `message` String - 대화 상자의 본문 내용입니다.
* `detail` String - 메시지의 추가 정보입니다.
* `icon` [NativeImage](native-image.md)
* `cancelId` Integer - 유저가 대화 상자의 버튼을 클릭하지 않고 대화 상자를 취소했을 때 반환되는 버튼의 index입니다.
기본적으로 버튼 리스트가 "cancel" 또는 "no" 라벨을 가지고 있을 때 해당 버튼의 index를 반환합니다. 따로 두 라벨이 지정되지 않은 경우 0을 반환합니다.
* `cancelId` Integer - 유저가 대화 상자의 버튼을 클릭하지 않고 대화 상자를 취소했을 때 반환되는 버튼의 인덱스입니다.
기본적으로 버튼 리스트가 "cancel" 또는 "no" 라벨을 가지고 있을 때 해당 버튼의 인덱스를 반환합니다. 따로 두 라벨이 지정되지 않은 경우 0을 반환합니다.
OS X와 Windows에선 `cancelId` 지정 여부에 상관없이 "Cancel" 버튼이 언제나 `cancelId`로 지정됩니다.
* `noLink` Boolean - Windows Electron은 "Cancel"이나 "Yes"와 같은 흔히 사용되는 버튼을 찾으려고 시도하고
대화 상자 내에서 해당 버튼을 커맨드 링크처럼 만듭니다. 이 기능으로 앱을 좀 더 Modern Windows 앱처럼 만들 수 있습니다.
이 기능을 원하지 않으면 `noLink`를 true로 지정하면 됩니다.
* `callback` Function
대화 상자를 표시합니다. `browserWindow`를 지정하면 대화 상자가 완전히 닫힐 때까지 창을 사용할 수 없습니다.
완료시 유저가 선택한 버튼의 index를 반환합니다.
대화 상자를 표시합니다. `browserWindow`를 지정하면 대화 상자가 완전히 닫힐 때까지 지정한 창을 사용할 수 없습니다.
완료 시 유저가 선택한 버튼의 인덱스를 반환합니다.
역주: 부정을 표현하는 "아니오", "취소"와 같은 한글 단어는 지원되지 않습니다.
만약 OS X 또는 Windows에서 "확인", "취소"와 같은 순서로 버튼을 지정하게 될 때 Alt + f4로 해당 대화 상자를 끄게 되면 "확인"을 누른로 판단되어 버립니다.
만약 OS X 또는 Windows에서 "확인", "취소"와 같은 순서로 버튼을 지정하게 될 때 Alt + f4로 해당 대화 상자를 끄게 되면 "확인"을 누른 것으로 판단되어 버립니다.
이를 해결하려면 "Cancel"을 대신 사용하거나 BrowserWindow API를 사용하여 대화 상자를 직접 구현해야합니다.
`callback`이 전달되면 메소드가 비동기로 작동되며 결과는 `callback(response)`을 통해 전달됩니다.
## dialog.showErrorBox(title, content)
### `dialog.showErrorBox(title, content)`
에러 메시지를 보여주는 모달 대화 상자를 표시합니다.
에러 메시지를 보여주는 대화 상자를 표시합니다.
이 API는 `app` 모듈의 `ready` 이벤트가 발생하기 전에 사용할 수 있습니다.
이 메소드는 보통 어플리케이션이 시작되기 전에 특정한 에러를 표시하기 위해 사용됩니다.

View file

@ -1,9 +1,10 @@
# `File` 객체
DOM의 File 인터페이스는 네이티브 파일을 추상화 합니다. 유저가 직접적으로 HTML5 File API를 사용하여 작업할 때 파일의 경로를
알 수 있도록 Electron은 파일시스템의 실제 파일 경로를 담은 `path` 속성을 File 인터페이스에 추가하였습니다.
DOM의 File 인터페이스는 네이티브 파일을 추상화 합니다.
유저가 직접 HTML5 File API를 이용하여 작업할 때 선택된 파일의 경로를 알 수 있도록
Electron은 파일의 실제 경로를 담은 `path` 속성을 File 인터페이스에 추가하였습니다.
다음 예제는 drag n drop한 파일의 실제 경로를 가져옵니다:
다음 예제는 앱으로 드래그 앤 드롭한 파일의 실제 경로를 가져옵니다:
```html
<div id="holder">

View file

@ -1,10 +1,12 @@
# Frameless 윈도우
# Frameless Window
Frameless 윈도우는 테두리가 없는 윈도우 창을 말합니다.
Frameless Window는 [테두리](https://developer.mozilla.org/en-US/docs/Glossary/Chrome)가 없는 창입니다.
이 기능은 윈도우 창의 일부분인 툴바와 같이 웹 페이지의 일부분이 아닌 부분을 보이지 않도록 합니다.
[`BrowserWindow`](browser-window.md) 클래스의 옵션에서 설정할 수 있습니다.
## Frameless 윈도우 만들기
## Frameless Window 만들기
Frameless 윈도우를 만드려면 [BrowserWindow](browser-window.md) 객체의 `options`에서 `frame` 옵션을 `false`로 지정하기만 하면됩니다:
Frameless Window를 만드려면 [BrowserWindow](browser-window.md) 객체의 `options`에서 `frame` 옵션을 `false`로 지정하면 됩니다:
```javascript
var BrowserWindow = require('browser-window');
@ -13,7 +15,7 @@ var win = new BrowserWindow({ width: 800, height: 600, frame: false });
## 투명한 창 만들기
Frameless 윈도우의 창의 배경을 투명하게 만들고 싶다면 `transparent` 옵션을 `true`로 바꿔주기만 하면됩니다:
Frameless Window의 창의 배경을 투명하게 만들고 싶다면 `transparent` 옵션을 `true`로 바꿔주기만 하면됩니다:
```javascript
var win = new BrowserWindow({ transparent: true, frame: false });
@ -21,22 +23,20 @@ var win = new BrowserWindow({ transparent: true, frame: false });
### API의 한계
* 투명한 영역을 통과하여 클릭할 수 없습니다. 우리는 이 문제를 해결하기 위해 API를 제공할 예정이지만 현재로써는
* 투명한 영역을 통과하여 클릭할 수 없습니다. 우리는 이 문제를 해결하기 위해 API를 제공할 예정이었지만 현재로써는
[upstream 버그](https://code.google.com/p/chromium/issues/detail?id=387234)로 인해 중단된 상태입니다.
* 투명한 창은 크기를 조절할 수 없습니다. `resizable` 속성을 `true`로 할 경우 몇몇 플랫폼에선 윈도우 크래시가 일어납니다.
* `blur` 필터는 웹 페이지에서만 적용됩니다. 윈도우 아래 컨텐츠에는 블러 효과를 적용할 방법이 없습니다.
* Windows에선 DWM(데스크톱 창 관리자)가 비활성화되어 있을 경우 작동하지 않습니다.
* Linux를 사용할 경우 [alpha channel doesn't work on some NVidia drivers](https://code.google.com/p/chromium/issues/detail?id=369209)
upstream 버그가 있으므로 CLI 옵션에 `--enable-transparent-visuals --disable-gpu`을 추가해야 합니다.
* 투명한 창은 크기를 조절할 수 없습니다. `resizable` 속성을 `true`로 할 경우 몇몇 플랫폼에선 크래시가 일어납니다.
* `blur` 필터는 웹 페이지에서만 적용됩니다. 윈도우 아래 컨텐츠에는 블러 효과를 적용할 방법이 없습니다. (예시: 유저의 시스템에 열린 다른 어플리케이션)
* Windows에선 DWM(데스크톱 창 관리자)가 비활성화되어 있을 경우 투명한 창이 작동하지 않습니다.
* Linux를 사용할 경우 [alpha channel doesn't work on some NVidia drivers](https://code.google.com/p/chromium/issues/detail?id=369209)
upstream 버그가 있는 관계로 투명한 창 기능을 사용하려면 CLI 옵션에 `--enable-transparent-visuals --disable-gpu`을 추가해야 합니다.
이 옵션은 GPU의 사용을 중단하고 윈도우를 생성하는데 ARGB를 사용할 수 있도록 해줍니다.
* OS X(Mac)에선 네이티브 윈도우의 그림자가 투명한 창에선 보이지 않습니다.
* OS X(Mac)에선 네이티브 창에서 보여지는 그림자가 투명한 창에선 보이지 않습니다.
## 드래그 가능 위치 지정
기본적으로 Frameless 윈도우는 드래그 할 수 없습니다.
어플리케이션의 CSS에서 특정 범위를 `-webkit-app-region: drag`로 지정하면 OS의 기본 타이틀바 처럼 드래그 되도록 할 수 있습니다.
기본적으로 Frameless Window는 드래그 할 수 없습니다.
어플리케이션의 CSS에서 특정 범위를 `-webkit-app-region: drag`로 지정하면 OS의 기본 타이틀 바 처럼 드래그 되도록 할 수 있습니다.
그리고 `-webkit-app-region: no-drag`를 지정해서 드래그 불가능 영역을 만들 수도 있습니다. 현재 사각형 형태의 범위만 지원합니다.
창 전체를 드래그 가능하게 만드려면 `-webkit-app-region: drag``body`의 스타일에 지정하면 됩니다:
@ -54,13 +54,13 @@ button {
}
```
또한 커스텀 타이틀바를 만들어 사용할 때 타이틀바 내부의 버튼도 드래그 불가능 영역으로 지정해야 합니다.
따로 커스텀 타이틀 바를 만들어 사용할 때는 타이틀 바 내부의 모든 버튼을 드래그 불가능 영역으로 지정해야 합니다.
## 텍스트 선택
한가지, Frameless 윈도우에서 텍스트가 선택되는 드래그 동작은 혼란을 야기할 수 있습니다.
예를 들어 타이틀바를 드래그 할 때 타이틀바의 텍스트를 실수로 선택할 수 있습니다.
이를 방지하기 위해 다음과 같이 드래그 영역의 텍스트 선택 동작을 비활성화해야 할 필요가 있습니다:
Frameless Window에서 텍스트가 선택되는 드래그 동작은 혼란을 야기할 수 있습니다.
예를 들어 타이틀 바를 드래그 할 때 타이틀 바의 텍스트를 실수로 선택할 수 있습니다.
이를 방지하기 위해 다음과 같이 드래그 영역의 텍스트 선택 기능을 비활성화해야 할 필요가 있습니다:
```css
.titlebar {
@ -71,5 +71,5 @@ button {
## 컨텍스트 메뉴
몇몇 플랫폼에선 드래그 가능 영역이 non-client 프레임으로 처리됩니다. 그래서 이 영역에서 오른쪽 클릭 할 경우 시스템 메뉴가 팝업 됩니다.
그래서 컨텍스트 메뉴 지정이 모든 플랫폼에서 정상적으로 작동하게 하려면 커스텀 컨텍스트 메뉴를 드래그 영역 내에 만들어선 안됩니다.
몇몇 플랫폼에선 드래그 가능 영역이 non-client 프레임으로 처리됩니다. 이러한 플랫폼에선 드래그 가능 영역에서 오른쪽 클릭 할 경우 시스템 메뉴가 팝업 됩니다.
이러한 이유로 컨텍스트 메뉴 지정 시 모든 플랫폼에서 정상적으로 작동하게 하려면 커스텀 컨텍스트 메뉴를 드래그 영역 내에 만들어선 안됩니다.

View file

@ -1,8 +1,9 @@
# global-shortcut
`global-shortcut` 모듈은 운영체제의 전역 키보드 단축키를 설정 등록/해제 하는 방법을 제공합니다.
`global-shortcut` 모듈은 운영체제의 전역 키보드 단축키를 등록/해제 하는 방법을 제공합니다.
이 모듈을 사용하여 사용자가 다양한 단축키 작업을 할 수 있도록 단축키를 정의 할 수 있습니다.
참고로 설정된 단축키는 어플리케이션이 백그라운드로 작동(창이 포커스 되지 않음) 할 때도 여전히 계속 작동합니다.
**참고:** 등록된 단축키는 어플리케이션이 백그라운드로 작동(창이 포커스 되지 않음) 할 때도 계속해서 작동합니다.
이 모듈은 `app` 모듈의 `ready` 이벤트 이전에 사용할 수 없습니다.
```javascript
@ -30,25 +31,29 @@ app.on('will-quit', function() {
});
```
## globalShortcut.register(accelerator, callback)
## Methods
`global-shortcut` 모듈은 다음과 같은 메서드를 가지고 있습니다:
### `globalShortcut.register(accelerator, callback)`
* `accelerator` [Accelerator](accelerator.md)
* `callback` Function
`accelerator`로 표현된 전역 단축키를 등록합니다. 유저로부터 등록된 단축키가 눌렸을 경우 `callback` 함수가 호출됩니다.
## globalShortcut.isRegistered(accelerator)
### `globalShortcut.isRegistered(accelerator)`
* `accelerator` [Accelerator](accelerator.md)
지정된 `accelerator` 단축키가 등록되었는지 여부를 확인합니다. 반환값은 boolean(true, false) 입니다.
## globalShortcut.unregister(accelerator)
### `globalShortcut.unregister(accelerator)`
* `accelerator` [Accelerator](accelerator.md)
`키코드`에 해당하는 전역 단축키를 등록 해제합니다.
`accelerator`에 해당하는 전역 단축키를 등록 해제합니다.
## globalShortcut.unregisterAll()
### `globalShortcut.unregisterAll()`
모든 전역 단축키 등록을 해제합니다.

View file

@ -1,17 +1,21 @@
# ipc (main process)
랜더러 프로세스(웹 페이지)로 부터 동기 또는 비동기로 메시지를 받아 처리합니다.
`ipc` (main process) 모듈은 메인 프로세스에서 사용할 때 랜더러 프로세스(웹 페이지)에서 전달된 동기 또는 비동기 메시지를 보내고 받는 방법을 제공합니다.
랜더러 프로세스에서 메시지를 전달하면 이 모듈을 통해 메시지를 받을 수 있습니다.
랜더러로부터 발신된 메시지들은 모두 이 모듈에서 `channel` 이라는 특정 이벤트 이름을 통해 수신할 수 있습니다.
동기 메시지는 `event.returnValue`를 이용하여 반환값(답장)을 설정할 수 있습니다. 비동기 메시지라면 `event.sender.send(...)`를 사용하면 됩니다.
## 메시지 전송
또한 메인 프로세스에서 랜더러 프로세스로 메시지를 보내는 것도 가능합니다.
자세한 내용은 [WebContents.send](browser-window.md#webcontentssendchannel-args)를 참고 하세요.
물론 메인 프로세스에서 랜더러 프로세스로 메시지를 보내는 것도 가능합니다.
자세한 내용은 [WebContents.send](browser-window.md#webcontentssendchannel-args)를 참고하세요.
보내진 메시지들을 처리하는 예제입니다:
- 메시지를 전송할 때 이벤트 이름은 `channel`이 됩니다.
- 메시지에 동기로 응답할 땐 반드시 `event.returnValue`를 설정해야 합니다.
- 메시지를 비동기로 응답할 땐 `event.sender.send(...)` 메서드를 사용할 수 있습니다.
랜더러 프로세스와 메인 프로세스간에 메시지를 전달하고 받는 예제입니다:
```javascript
// 메인 프로세스에서 처리.
// 메인 프로세스
var ipc = require('ipc');
ipc.on('asynchronous-message', function(event, arg) {
console.log(arg); // prints "ping"
@ -25,7 +29,7 @@ ipc.on('synchronous-message', function(event, arg) {
```
```javascript
// 랜더러 프로세스에서의 처리 (web page).
// 랜더러 프로세스 (web page)
var ipc = require('ipc');
console.log(ipc.sendSync('synchronous-message', 'ping')); // prints "pong"
@ -35,12 +39,33 @@ ipc.on('asynchronous-reply', function(arg) {
ipc.send('asynchronous-message', 'ping');
```
## Class: Event
## 메시지 리스닝
### Event.returnValue
`ipc` 모듈은 다음과 같은 이벤트 메서드를 가지고 있습니다:
동기 메시지를 설정합니다.
### `ipc.on(channel, callback)`
### Event.sender
* `channel` String - 이벤트 이름
* `callback` Function
메시지를 보내온 sender `WebContents` 객체입니다.
이벤트가 발생하면 `callback``event` 객체와 `arg` 메시지가 포함되어 호출됩니다.
## IPC Events
`callback`에서 전달된 `event` 객체는 다음과 같은 메서드와 속성을 가지고 있습니다:
### `Event.returnValue`
이 메시지를 지정하면 동기 메시지를 전달합니다.
### `Event.sender`
메시지를 보낸 `WebContents` 객체를 반환합니다.
### `Event.sender.send(channel[, arg1][, arg2][, ...])`
* `channel` String - The event name.
* `arg` (optional)
랜더러 프로세스로 비동기 메시지를 전달합니다.
옵션으로 `arg`에 한 개 또는 여러 개의 메시지를 포함할 수 있습니다. 모든 타입을 사용할 수 있습니다.

View file

@ -1,25 +1,45 @@
# ipc (renderer)
`ipc` 모듈은 메인 프로세스로 메시지를 동기 또는 비동기로 보내고 받을 수 있는 몇 가지 방법을 제공합니다.
만약 랜더러 프로세스에서 메인 프로세스의 모듈을 직접적으로 사용하고 싶다면 [remote](remote.md) 모듈을 사용하는 것을 고려해보는 것이 좋습니다.
`ipc` (renderer) 모듈은 메인 프로세스로 동기 또는 비동기 메시지를 보내고 받는 방법을 제공합니다.
물론 메인 프로세스로부터 받은 메시지에 응답할 수도 있습니다.
[ipc (main process)](ipc-main-process.md)에서 예제를 볼 수 있습니다.
**참고:** 만약 랜더러 프로세스에서 메인 프로세스의 모듈을 직접적 사용하고 싶다면 [remote](remote.md) 모듈을 사용하는 것을 고려해보는 것이 좋습니다.
## ipc.send(channel[, args...])
[ipc (main process)](ipc-main-process.md)에서 예제를 확인 할 수 있습니다.
지정한 `channel`을 통해 `args..`를 비동기로 메시지를 보냅니다. 메인 프로세스는 `ipc` 모듈의 `channel` 이벤트를 통해 메시지를 받을 수 있습니다.
## Methods
## ipc.sendSync(channel[, args...])
`ipc` 모듈은 다음과 같은 메서드를 가지고 있습니다:
지정한 `channel`을 통해 `args..`를 동기로 메시지를 보냅니다. 그리고 메인 프로세스에서 보낸 결과를 반환합니다.
메인 프로세스는 `ipc` 모듈의 `channel` 이벤트를 통해 메시지를 받을 수 있습니다. 그리고 `event.returnValue`를 통해 반환값을 설정할 수 있습니다.
**참고:** 이 메소드들을 사용하여 `message`를 보낼 땐 반드시 메인 프로세스의
[`ipc (main process)`](ipc-main-process.md) 모듈에서도 이벤트 리스너를 등록해 두어야 합니다.
역자 주: `channel`은 이벤트 이름입니다.
### `ipc.send(channel[, arg1][, arg2][, ...])`
**알림:** 보통 개발자들은 해당 API를 사용하려 하지 않습니다. 동기 ipc 작업은 랜더러 프로세스의 모든 작업을 중단시킵니다.
* `channel` String - 이벤트 이름
* `arg` (optional)
## ipc.sendToHost(channel[, args...])
`channel`을 통해 메인 프로세스에 비동기 메시지를 보냅니다.
옵션으로 `arg`에 한 개 또는 여러 개의 메시지를 포함할 수 있습니다. 모든 타입을 사용할 수 있습니다.
메인 프로세스는 `ipc`를 통해 `channel` 이벤트를 리스닝 할 수 있습니다.
`ipc.send`와 비슷하지만 메시지를 메인 프로세스 대신 호스트 페이지로 보냅니다.
### `ipc.sendSync(channel[, arg1][, arg2][, ...])`
이 메소드는 보통 `<webview>`와 호스트 페이지 간의 통신에 사용됩니다.
* `channel` String - 이벤트 이름
* `arg` (optional)
`channel`을 통해 메인 프로세스에 동기 메시지를 보냅니다.
옵션으로 `arg`에 한 개 또는 여러 개의 메시지를 포함할 수 있습니다. 모든 타입을 사용할 수 있습니다.
메인 프로세스는 `ipc`를 통해 `channel` 이벤트를 리스닝 할 수 있습니다.
메인 프로세스에선 `ipc` 모듈의 `channel` 이벤트를 통해 받은 `event.returnValue`로 회신 할 수 있습니다.
**참고:** 동기 메시징은 모든 랜더러 프로세스의 작업을 일시 중단시킵니다. 이 메서드를 사용하는 것을 권장하지 않습니다.
### `ipc.sendToHost(channel[, arg1][, arg2][, ...])`
* `channel` String - 이벤트 이름
* `arg` (optional)
`ipc.send`와 비슷하지만 이벤트를 메인 프로세스 대신 호스트 페이지내의 `<webview>`로 보냅니다.
옵션으로 `arg`에 한 개 또는 여러 개의 메시지를 포함할 수 있습니다. 모든 타입을 사용할 수 있습니다.

View file

@ -5,7 +5,7 @@
### new MenuItem(options)
* `options` Object
* `click` Function - 메뉴 아이템이 클릭될 때 호출되는 콜백함수
* `click` Function - 메뉴 아이템이 클릭될 때 호출되는 콜백 함수
* `selector` String - First Responder가 클릭될 때 호출 되는 선택자 (OS X 전용)
* `type` String - `MenuItem`의 타입 `normal`, `separator`, `submenu`, `checkbox` 또는 `radio` 사용가능
* `label` String

View file

@ -181,9 +181,9 @@ Menu.setApplicationMenu(menu);
* `action` String
`action`을 어플리케이션의 first responder에 전달합니다.
함수는 Cocoa 메뉴 동작을 에뮬레이트 하는데 사용되며 보통 `MenuItem``selector` 속성에 사용됩니다.
메서드는 Cocoa 메뉴 동작을 에뮬레이트 하는데 사용되며 보통 `MenuItem``selector` 속성에 사용됩니다.
**알림:** 이 함수는 OS X에서만 사용할 수 있습니다.
**참고:** 이 메서드는 OS X에서만 사용할 수 있습니다.
### Class Method: Menu.buildFromTemplate(template)

View file

@ -23,7 +23,7 @@ powerSaveBlocker.stop(id);
Power save blocker를 시작하고 시스템이 저전력 모드(슬립)로 진입하는 것을 막습니다. 정수로 된 식별 ID를 반환합니다.
**알림:**
**참고:**
`prevent-display-sleep` 모드는 `prevent-app-suspension` 보다 우선순위가 높습니다.
가장 높은 우선순위의 모드만 작동합니다. 다시 말해 `prevent-display-sleep` 모드는 언제나 `prevent-app-suspension` 모드의 효과를 덮어씌웁니다.

View file

@ -10,3 +10,9 @@ Electron의 `process` 객체는 기존의 node와는 달리 약간의 차이점
## process.hang
현재 프로세스의 주 스레드를 중단시킵니다.
## process.setFdLimit(maxDescriptors) _OS X_ _Linux_
* `maxDescriptors` Integer
`maxDescriptors`에 file descriptor 소프트 리미트를 설정하거나 OS 하드 리미트를 설정합니다. 값은 현재 프로세스에 대해 낮은 값이어야 합니다.

View file

@ -20,7 +20,7 @@ app.on('ready', function() {
});
```
**알림:** 이 모듈은 `ready` 이벤트가 호출된 이후에만 사용할 수 있습니다.
**참고:** 이 모듈은 `ready` 이벤트가 호출된 이후에만 사용할 수 있습니다.
## protocol.registerStandardSchemes(schemes)

View file

@ -16,12 +16,12 @@ var win = new BrowserWindow({ width: 800, height: 600 });
win.loadUrl('https://github.com');
```
알림: 반대로 하려면(메인 프로세스에서 랜더러 프로세스에 접근) [webContents.executeJavascript](browser-window.md#webcontents-executejavascript-code) API를 사용하면 됩니다.
**참고:** 반대로 하려면(메인 프로세스에서 랜더러 프로세스에 접근) [webContents.executeJavascript](browser-window.md#webcontents-executejavascript-code) API를 사용하면 됩니다.
## Remote 객체
`remote` 모듈로부터 반환된 각 객체(함수 포함)는 메인 프로세스의 객체를 추상화 한 객체입니다. (우리는 그것을 remote 객체 또는 remote 함수라고 부릅니다)
Remote 모듈의 함수를 호출하거나, 객체에 접근하거나, 생성자로 객체를 생성하는 등의 작업은 실질적으로 동기형 inter-process 메시지를 보냅니다.
`remote` 모듈로부터 반환된 각 객체(메서드 포함)는 메인 프로세스의 객체를 추상화 한 객체입니다. (우리는 그것을 remote 객체 또는 remote 함수라고 부릅니다)
Remote 모듈의 메서드를 호출하거나, 객체에 접근하거나, 생성자로 객체를 생성하는 등의 작업은 실질적으로 동기형 inter-process 메시지를 보냅니다.
위의 예제에서 사용한 두 `BrowserWindow``win`은 remote 객체입니다. 그리고 `new BrowserWindow`이 생성하는 `BrowserWindow` 객체는 랜더러 프로세스에서 생성되지 않습니다.
대신에 이 `BrowserWindow` 객체는 메인 프로세스에서 생성되며 랜더러 프로세스에 `win` 객체와 같이 이에 대응하는 remote 객체를 반환합니다.
@ -38,16 +38,45 @@ Remote 객체가 GC 되려면 대응하는 메인 프로세스 내부 객체의
## 메인 프로세스로 콜백 넘기기
몇몇 메인 프로세스의 API는 콜백 함수를 사용합니다. 그리고 보통 remote 함수를 호출할 때 콜백 함수를 넘길 것입니다.
`remote` 모듈은 이를 지원합니다. 하지만 반드시 주의해서 사용해야 합니다.
메인 프로세스의 코드는 `remote` 모듈을 통해 랜더러 프로세스가 전달하는 콜백 함수를 받을 수 있습니다.
하지만 이 작업은 반드시 주의를 기울여 사용해야 합니다.
첫째, 데드락을 피하기 위해 메인 프로세스로 전달된 콜백들은 비동기로 호출됩니다.
그래서 전달된 콜백들이 언제나 값을 반환할 것이라고 기대하면 안 됩니다.
이러한 이유로 메인 프로세스로 전달된 콜백들의 반환 값을 내부 함수에서 언제나 정상적으로 받을 것이라고 예측해선 안됩니다.
둘째, 콜백들은 메인 프로세스로 전송되고 호출된 후에도 자동으로 참조가 릴리즈 되지 않습니다.
참조는 메인 프로세스에서 GC가 일어나기 전까지 계속 남아있게 됩니다.
예를 들어 메인 프로세스에서 `Array.map` 같은 메서드를 사용할 때 랜더러 프로세스에서 전달된 함수를 사용해선 안됩니다:
다음 코드를 보면 느낌이 팟 하고 올 것입니다. 이 예제는 remote 객체에 `close` 이벤트 콜백을 설치합니다:
```javascript
// mapNumbers.js 메인 프로세스
exports.withRendererCallback = function(mapper) {
return [1,2,3].map(mapper);
}
exports.withLocalCallback = function() {
return exports.mapNumbers(function(x) {
return x + 1;
});
}
// 랜더러 프로세스
var mapNumbers = require("remote").require("mapNumbers");
var withRendererCb = mapNumbers.withRendererCallback(function(x) {
return x + 1;
})
var withLocalCb = mapNumbers.withLocalCallback()
console.log(withRendererCb, withLocalCb) // [true, true, true], [2, 3, 4]
```
보다시피 랜더러 콜백의 동기 반환 값은 예상되지 않은 처리입니다.
그리고 메인 프로세스에서 처리한 함수의 반환 값과 일치하지 않습니다.
둘째, 콜백들은 메인 프로세스로 전달, 호출된 이후에도 자동으로 함수의 참조가 릴리즈 되지 않습니다.
함수 참조는 메인 프로세스에서 GC가 일어나기 전까지 계속 프로세스에 남아있게 됩니다.
다음 코드를 보면 느낌이 올 것입니다. 이 예제는 remote 객체에 `close` 이벤트 콜백을 설치합니다:
```javascript
var remote = require('remote');
@ -56,11 +85,14 @@ remote.getCurrentWindow().on('close', function() {
});
```
문제는 이 이벤트는 명시적으로 제거하지 않는 이상 계속해서 메인 프로세스에 남아있게 된다는 것입니다.
그래서 매 창을 새로고침 할 때마다 콜백이 새롭게 설치되며 이전 콜백은 떨궈져 누수가 됩니다.
설상가상으로 이전에 설치한 콜백의 콘텍스트가 릴리즈 되고 나서 `close` 이벤트가 발생하면 예외가 발생하고 메인 프로세스가 작동 중지됩니다.
하지만 이 코드 처럼 이벤트를 명시적으로 제거하지 않는 이상 콜백 함수의 참조가 계속해서 메인 프로세스에 남아있게 됩니다.
만약 명시적으로 콜백을 제거하지 않으면 매 번 창을 새로고침 할 때마다 콜백을 새로 설치합니다.
게다가 이전 콜백이 제거되지 않고 계속해서 쌓이면서 메모리 누수가 발생합니다.
일반적으로 정확히 무엇을 할 것인지 잘 알고 있지 않는 이상 웬만하면 메인 프로세스로 콜백 함수를 넘기는 건 자제하는 게 좋습니다.
설상가상으로 이전에 설치된 콜백의 콘텍스트가 릴리즈 되고 난 후(예: 페이지 새로고침) `close` 이벤트가 발생하면 예외가 발생하고 메인 프로세스가 작동 중지됩니다.
이러한 문제를 피하려면 랜더러 프로세스에서 메인 프로세스로 넘긴 함수의 참조를 사용 후 확실하게 제거해야 합니다.
작업 후 이벤트 콜백을 포함하여 책임 있게 함수의 참조를 제거하거나 메인 프로세스에서 랜더러 프로세스가 종료될 때 내부적으로 함수 참조를 제거하도록 설계해야 합니다.
## remote.require(module)

View file

@ -169,7 +169,7 @@ __주의:__ 이 기능은 OS X에서만 작동합니다.
트레이에 알림풍선을 생성합니다.
__알림:__ 이 기능은 Windows에서만 작동합니다.
__주의:__ 이 기능은 Windows에서만 작동합니다.
### Tray.popContextMenu([position])

View file

@ -1,8 +1,8 @@
# web-frame
`web-frame` 모듈은 현재 웹 페이지의 랜더링 상태를 설정 할 수 있도록 해줍니다.
`web-frame` 모듈은 현재 웹 페이지의 랜더링 상태를 설정 할 수 있도록 관련 유틸리티를 제공하는 모듈입니다.
다음 예제는 현재 페이지를 200% 줌 합니다.
다음 예제는 현재 페이지를 200% 줌 합니다:
```javascript
var webFrame = require('web-frame');
@ -30,6 +30,13 @@ webFrame.setZoomFactor(2);
현재 줌 레벨을 반환합니다.
## webFrame.setZoomLevelLimits(minimumLevel, maximumLevel)
* `minimumLevel` Number
* `maximumLevel` Number
줌 레벨의 최대, 최소치를 지정합니다.
## webFrame.setSpellCheckProvider(language, autoCorrectWord, provider)
* `language` String

View file

@ -1,9 +1,9 @@
# `window.open` 함수
# `window.open` 메서드
`window.open` 함수가 호출되면 새 창에서 새로운 페이지를 불러옵니다.
이 창은 `url`로 부터 만들어진 `BrowserWindow`의 새 인스턴스이며 본 객체 대신 페이지의 컨트롤이 제한된 프록시 객체를 반환합니다.
`window.open` 메서드가 호출되면 새 창을 생성하고 `url` 페이지를 불러옵니다.
이 창은 지정한 `url`을 로드하여 만들어진 `BrowserWindow`의 새 인스턴스이며 본래 창 객체 대신 페이지의 컨트롤이 제한된 프록시 객체를 반환합니다.
프록시 객체는 기존의 웹 페이지와 호환될 수 있도록 일부 제한된 표준 기능만 가지고 있습니다.
프록시 객체는 브라우저의 웹 페이지 창과 호환될 수 있도록 일부 제한된 표준 기능만 가지고 있습니다.
창의 모든 컨트롤을 가지려면 `BrowserWindow`를 직접 생성하여 작업해야 합니다.
## window.open(url, [frameName[, features]])
@ -19,7 +19,7 @@
* `message` String
* `targetOrigin` String
부모 윈도우에 메시지를 보냅니다. 특정한 origin을 지정할 수도 있으며 `*`를 지정하면 따로 origin 설정을 사용하지 않습니다.
부모 윈도우에 메시지를 보냅니다. origin을 특정할 수 있으며 `*`를 지정하면 따로 origin 설정을 사용하지 않습니다.
## Class: BrowserWindowProxy
@ -52,6 +52,6 @@ Forcefully closes the child window without calling its unload event.
* `message` String
* `targetOrigin` String
자식 윈도우에 메시지를 보냅니다. 특정한 origin을 지정할 수도 있으며 `*`를 지정하면 따로 origin 설정을 사용하지 않습니다.
자식 윈도우에 메시지를 보냅니다. origin을 특정할 수 있으며 `*`를 지정하면 따로 origin 설정을 사용하지 않습니다.
참고로 자식 윈도우의 `window.opener` 객체에는 다른 속성 없이 이 함수 하나만 구현되어 있습니다.
참고로 자식 윈도우의 `window.opener` 객체에는 다른 속성 없이 이 메서드 한 개만 구현되어 있습니다.

View file

@ -1,6 +1,6 @@
# NW.js와 기술적으로 다른점 (이전 node-webkit)
__알림: Electron은 이전까지 Atom Shell로 불려졌습니다.__
__주의: Electron은 Atom Shell의 새로운 이름입니다.__
NW.js 처럼 Electron은 JavaScript와 HTML 그리고 Node 통합환경을 제공함으로써 웹 페이지에서 저수준 시스템에 접근할 수 있는 웹 기반 데스크탑 어플리케이션을 작성할 수 있도록 합니다.

View file

@ -4,7 +4,7 @@
* Python 2.7.x. 몇몇 CentOS와 같은 배포판들은 아직도 Python 2.6.x 버전을 사용합니다. 그래서 `python -V`를 통해 버전을 확인해 줄 필요가 있습니다.
* Node.js v0.12.x. Node를 설치하는 방법은 여러가지가 있습니다. 그중 하나는 [Node.js](http://nodejs.org) 사이트에서 소스코드를 받아 빌드하는 방법입니다.
이렇게 하면 Node를 일반 유저로 홈 디렉터리에 설치할 수 있습니다. 또는 [NodeSource](https://nodesource.com/blog/nodejs-v012-iojs-and-the-nodesource-linux-repositories) 에서 받아올 수 있습니다.
이렇게 하면 Node를 일반 유저로 홈 디렉터리에 설치할 수 있습니다. 또는 [NodeSource](https://nodesource.com/blog/nodejs-v012-iojs-and-the-nodesource-linux-repositories)에서 소스 파일을 받아올 수 있습니다.
자세한 내용은 [Node.js 설치 방법](https://github.com/joyent/node/wiki/Installation) 을 참고하세요.
* Clang 3.4 또는 최신 버전
* GTK+ 와 libnotify의 개발용 헤더
@ -78,7 +78,7 @@ $ ./script/create-dist.py
이 스크립트는 매우 작은 배포판을 `dist` 디렉터리에 생성합니다.
create-dist.py 스크립트를 실행한 이후 1.3GB를 초과하는 공간을 차지하는 out/R 폴더의 실행파일 바이너리는 삭제해도 됩니다.
`Debug` 타겟만 빌드 할 수 있습니다:
또는 `Debug` 타겟만 빌드 할 수 있습니다:
```bash
$ ./script/build.py -c D

View file

@ -34,7 +34,7 @@ $ ./script/bootstrap.py -v
$ ./script/build.py
```
`Debug` 타겟만 빌드 할 수 있습니다:
또는 `Debug` 타겟만 빌드 할 수 있습니다:
```bash
$ ./script/build.py -c D

View file

@ -9,7 +9,7 @@
* [git](http://git-scm.com)
현재 Windows를 설치하지 않았다면 [modern.ie](https://www.modern.ie/en-us/virtualization-tools#downloads)에서
사용기한이 정해져있는 무료 가상머신 버전의 Windows를 받아 Electron을 빌드할 수도 있습니다.
사용 기한이 정해져있는 무료 가상머신 버전의 Windows를 받아 Electron을 빌드하는 방법도 있습니다.
Electron은 전적으로 command-line 스크립트를 사용하여 빌드합니다. 그렇기에 Electron을 개발하는데 아무런 에디터나 사용할 수 있습니다.
하지만 이 말은 Visual Studio를 개발을 위해 사용할 수 없다는 말이 됩니다. 나중에 Visual Studio를 이용한 빌드 방법도 제공할 예정입니다.
@ -40,7 +40,7 @@ python script\bootstrap.py -v
python script\build.py
```
`Debug` 타겟만 빌드 할 수 있습니다:
또는 `Debug` 타겟만 빌드 할 수 있습니다:
```powershell
python script\build.py -c D
@ -72,6 +72,15 @@ python script\cpplint.py
python script\test.py
```
테스트 실행시 `runas`와 같은 네이티브 모듈을 포함하는데 이 모듈은 디버그 빌드에서 같이 사용할 수 없습니다.
하지만 여전히 릴리즈 빌드에선 사용할 수 있습니다.
릴리즈 빌드로 테스트를 실행하려면 다음 커맨드를 사용하면 됩니다:
```powershell
python script\test.py -R
```
## 문제 해결
### Command xxxx not found

View file

@ -1,6 +1,6 @@
# 디버거에서 디버그 심볼 서버 설정
디버그 심볼은 디버깅 세션을 더 좋게 개선해 줍니다. 디버그 심볼은 실행 파일과 동적 링크 라이브러리에서 함수에 대한 정보를 담고 있으며 명료한 함수 호출 스텍 정보를 제공합니다.
디버그 심볼은 디버깅 세션을 더 좋게 개선해 줍니다. 디버그 심볼은 실행 파일과 동적 링크 라이브러리에서 메서드에 대한 정보를 담고 있으며 명료한 함수 호출 스텍 정보를 제공합니다.
심볼 서버는 유저가 크기가 큰 디버깅용 파일을 필수적으로 다운로드 받지 않고도 디버거가 알맞은 심볼, 바이너리 그리고 소스를 자동적으로 로드할 수 있도록 해줍니다.
서버 사용법은 [Microsoft의 심볼 서버](http://support.microsoft.com/kb/311503)와 비슷합니다. 이 문서를 참조하세요.

View file

@ -1,61 +1,55 @@
# Electron Documentation Styleguide
# Electron 문서 스타일 가이드
Find the appropriate section for your task: [reading Electron documentation](#)
or [writing Electron documentation](#).
[Electron 문서 읽기](#) 와 [Electron 문서 작성하기](#) 중 적당히 필요한 부분을 찾아 참고하세요:
## Writing Electron Documentation
## Electron 문서 작성하기
These are the ways that we construct the Electron documentation.
Electron 문서를 작성하는 규칙은 다음과 같습니다.
- Maximum one `h1` title per page.
- Use `bash` instead of `cmd` in code blocks (because of syntax highlighter).
- Doc `h1` titles should match object name (i.e. `browser-window` ¡æ
`BrowserWindow`).
- Hyphen separated filenames, however, are fine.
- No headers following headers, add at least a one-sentence description.
- Methods headers are wrapped in `code` ticks.
- Event headers are wrapped in single 'quotation' marks.
- No nesting lists more than 2 levels (unfortunately because of markdown
renderer).
- Add section titles: Events, Class Methods and Instance Methods.
- Use 'will' over 'would' when describing outcomes.
- Events and methods are `h3` headers.
- Optional arguments written as `function (required[, optional])`.
- Optional arguments are denoted when called out in list.
- Line length is 80-column wrapped.
- Platform specific methods are noted in italics following method header.
- `h1` 제목은 페이지당 한 개만 사용할 수 있습니다.
- 코드 블럭에서 터미널 언어 선택시 `cmd` 대신 `bash`를 사용합니다. (syntax highlighter를 사용하기 위해서)
- 문서의 `h1` 제목은 반드시 현재 객체 이름과 같게 해야 합니다. (예시: `browser-window``BrowserWindow`)
- 하이픈(-)으로 구분되었던 어떻게 되었던 간에 예시와 같이 작성합니다.
- 헤더 밑에 헤더를 바로 사용하지 않습니다. 한 줄이라도 좋으니 헤더와 헤더 사이에 설명 추가합니다.
- 메서드 헤더는 `code` 틱으로 표시합니다.
- 이벤트 헤더는 한 '따옴표'로 표시합니다.
- 리스트를 2 단계 이상 중첩하지 않습니다. (안타깝게도 markdown 랜더러가 지원하지 않습니다)
- 섹션에 대한 제목을 추가합니다: Events, Class 메서드 그리고 인스턴스 메서드등.
- 어떤 '것'의 사용 결과를 설명할 때 '될 것입니다' 형식을 사용하여 설명합니다.
- 이벤트와 메서드에는 `h3` 헤더를 사용합니다.
- 선택적 인수는 `function (required[, optional])` 형식으로 작성합니다.
- 선택적 인수는 목록에서 호출되면 표시합니다.
- 문장의 길이는 한 줄당 80 칸을 유지합니다.
- 플랫폼 특정 메서드 헤더는 이탈릭체로 표시합니다.
- ```### `method(foo, bar)` _OS X_```
## Reading Electron Documentation
## Electron 문서 읽기
Here are some tips for understanding Electron documentation syntax.
Electron 문서 구조를 이해하는 데 참고할 수 있는 유용한 도움말입니다.
### Methods
An example of [method](https://developer.mozilla.org/en-US/docs/Glossary/Method)
documentation:
[Method](https://developer.mozilla.org/en-US/docs/Glossary/Method) 문서의 예제입니다:
---
`methodName(required[, optional]))`
* `require` String, **required**
* `require` String, **필수**
* `optional` Integer
---
The method name is followed by the arguments it takes. Optional arguments are
notated by brackets surrounding the optional argument as well as the comma
required if this optional argument follows another argument.
메서드 이름은 인수가 무엇을 받는지에 따라 결정됩니다. 선택적 인수는 브라켓([, ])으로 묶어
이 인수가 다른 인수뒤에서 선택적으로 사용될 수 있다는 것을 표시합니다.
Below the method is more detailed information on each of the arguments. The type
of argument is notated by either the common types: [`String`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String), [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number), [`Object`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object), [`Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)
or a custom type like Electron's [`webContent`](api/web-content.md).
메서드의 밑에선 각 인수에 대해 자세한 설명을 합니다. 인수의 타입은 일반적인 타입 중 하나를 받거나:
[`String`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String), [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number), [`Object`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object), [`Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)
Electron의 [`webContent`](api/web-content.md)같은 커스텀 타입을 받습니다.
### Events
An example of [event](https://developer.mozilla.org/en-US/docs/Web/API/Event)
documentation:
[Event](https://developer.mozilla.org/en-US/docs/Web/API/Event) 문서의 예제입니다:
---
@ -67,12 +61,11 @@ Returns:
---
The event is a string that is used after a `.on` listener method. If it returns
a value it and its type is noted below. If you were to listen and respond to
this event it might look something like this:
이벤트는 `.on` 리스너 메서드로 사용할 수 있습니다. 만약 이벤트에서 값을 반환한다면 문서에서 표시된 대로
일정한 타입의 값을 반환합니다. 이벤트를 처리하거나 응답하려 한다면 다음과 같이 사용할 수 있습니다:
```javascript
Alarm.on('wake-up', function(time) {
console.log(time)
})
```
```

View file

@ -118,7 +118,7 @@ originalFs.readFileSync('/path/to/example.asar');
몇몇 API는 시스템의 실제 파일의 경로를 기반으로 작동하므로 이 API들을 사용할 땐 Electron은
이 API가 원할하게 작동할 수 있도록 하기 위해 임시경로에 해당 파일들의 압축을 해제합니다. 이 작업은 약간의 오버헤드를 불러 일으킬 수 있습니다.
해당하는 API 함수는 다음과 같습니다:
해당하는 API 메서드는 다음과 같습니다:
* `child_process.execFile`
* `fs.open`
@ -134,7 +134,7 @@ originalFs.readFileSync('/path/to/example.asar');
## `asar` 아카이브에 미리 압축 해제된 파일 추가하기
전술한 바와 같이 몇몇 Node API는 호출 시 해당 파일을 임시폴더에 압축을 해제합니다.
따로 성능문제가 발생할 수 있습니다. 그리고 백신 소프트웨어의 잘못된 오진을 일으킬 수도 있습니다.
이 방법은 성능문제가 발생할 수 있습니다. 그리고 설계상 백신 소프트웨어에서 잘못 진단하여 바이러스로 판단 할 수도 있습니다.
이 문제를 해결하려면 `--unpack` 옵션을 활용하여 파일을 압축이 풀려진 상태로 유지해야 합니다.
다음의 예제는 node 네이티브 모듈의 공유 라이브러리를 unpack 상태로 유지합니다:

View file

@ -26,13 +26,13 @@ $ node-inspector
### 2. Electron용 디버그 모드 활성화
다음과 같이 debung 플래그로 Electron을 실행할 수 있습니다:
다음과 같이 debung 플래그로 Electron을 실행할 수 있습니다:
```bash
$ electron --debug=5858 your/app
```
또는 스크립트 첫번째 라인에서 일시정지:
또는 스크립트 첫번째 라인에서 일시 정지할 수 있습니다:
```bash
$ electron --debug-brk=5858 your/app

View file

@ -35,10 +35,10 @@ _online-status.html_
</html>
```
필요한 경우 이 이벤트를 메인 프로세스로 보낼 수도 있습니다.
메인 프로세스는 `navigator` 오브젝트를 가지고 있지 않기 때문에 이 이벤트를 직접 사용할 수 없습니다.
이는 다음 예제와 같이 electron의 inter-process communication(ipc)유틸리티를 사용하여
이벤트를 메인 프로세스로 전달하는 것으로 해결할 수 있습니다.
물론 필요하다면 이 이벤트를 메인 프로세스로 보낼 수도 있습니다.
하지만 메인 프로세스는 `navigator` 객체를 가지고 있지 않기 때문에 이 이벤트를 직접 사용할 수 없습니다.
대신 다음 예제와 같이 Electron의 inter-process communication(ipc) 유틸리티를 사용하면 이벤트를 메인 프로세스로 전달할 수 있습니다.
_main.js_

View file

@ -10,23 +10,24 @@ Electron은 자바스크립트와 함께 제공된 풍부한 네이티브 API를
### 메인 프로세스
Electron은 실행될 때 __메인 프로세스__ 로 불리는 `package.json``main` 스크립트를 호출합니다.
Electron은 실행될 때 __메인 프로세스__로 불리는 `package.json``main` 스크립트를 호출합니다.
이 스크립트는 메인 프로세스에서 작동합니다. GUI 컴포넌트를 조작하거나 웹 페이지 창을 생성할 수 있습니다.
### 랜더러 프로세스
Electron이 웹페이지를 보여줄 때 Chromium의 multi-processes 구조도 같이 사용됩니다.
Electron 프로세스 내에서 작동하는 웹 페이지 __랜더러 프로세스__ 라고 불립니다.
Electron 프로세스 내에서 작동하는 웹 페이지 __랜더러 프로세스__ 라고 불립니다.
보통 일반 브라우저의 웹 페이지들은 샌드박스가 적용된 환경에서 작동하며 네이티브 리소스에는 접근할 수 없도록 되어 있습니다.
하지만 Electron은 웹 페이지 내에서 io.js(node.js) API를 사용하여 low-level 수준으로 운영체제와 상호작용할 수 있습니다.
### 메인 프로세스와 랜더러 프로세스의 차이점
메인 프로세스는 `BrowserWindow` Class를 이용하여 창을 만들 수 있습니다. `BrowserWindow` 인스턴스는
따로 분리된 프로세스에서 랜더링 되며 `BrowserWindow` 인스턴스가 소멸할 때 해당하는 랜더러 프로세스도 같이 소멸합니다.
메인 프로세스는 `BrowserWindow` Class를 사용하여 새로운 창을 만들 수 있습니다.
`BrowserWindow` 인스턴스는 따로 분리된 프로세스에서 랜더링 되며 이 프로세스를 랜더러 프로세스라고 합니다.
`BrowserWindow` 인스턴스가 소멸할 때 그 창의 랜더러 프로세스도 같이 소멸합니다.
메인 프로세스는 모든 웹 페이지와 그에 해당하는 랜더러 프로세스를 관리하며
메인 프로세스는 모든 웹 페이지와 랜더러 프로세스를 관리하며
랜더러 프로세스는 각각의 프로세스에 고립되며 웹 페이지의 작동에만 영향을 끼칩니다.
웹 페이지 내에서 네이티브 GUI 리소스를 관리하는 것은 보안에 취약하고 리소스를 누수시킬 수 있기 때문에
@ -124,7 +125,7 @@ app.on('ready', function() {
## 앱 실행하기
앱을 작성한 후 [어플리케이션 배포](application-distribution.md) 가이드를 따라 앱을 패키징 하고 패키징한 앱을 실행할 수 있습니다.
Electron 실행파일을 다운로드 받아 바로 실행해 볼 수도 있습니다.
Electron 실행파일을 다운로드 받아 바로 실행해 볼 수도 있습니다.
### electron-prebuilt

View file

@ -1,25 +1,23 @@
# 네이티브 node 모듈 사용하기
# 네이티브 node 모듈 사용하기
__역주: 현재 Electron은 node.js대신 io.js를 사용합니다. 문서에 기재된 버전과 다를 수 있습니다__
Electron에선 node.js 네이티브 모듈이 지원됩니다. 하지만 Electron은 공식 node.js의 V8 엔진과는 달리 다른 V8 버전을 사용합니다.
그런 이유로 네이티브 모듈을 사용하기 위해선 Electron의 V8 버전에 맞춰 네이티브 모듈을 다시 빌드하고 헤더를 변경해야 합니다.
Electron에선 node.js 네이티브 모듈이 지원됩니다. 하지만 Electron은 공식 node.js의 V8 엔진과는 다른 V8 버전을 사용합니다.
이러한 이유로 네이티브 모듈을 사용하기 위해선 Electron의 V8 버전에 맞춰 네이티브 모듈을 다시 빌드하고 헤더를 변경해야 합니다.
## 네이티브 node 모듈 호환성
Node v0.11.x 버전부터는 V8 API의 중대한 변경이 있었습니다. 하지만 일반적으로 모든 네이티브 모듈은 Node v0.10.x 버전을 타겟으로 작성 되었기 때문에
Node v0.11.x 버전에선 작동하지 않습니다. Electron은 내부적으로 Node v0.11.13 버전을 사용합니다. 그래서 위에서 설명한 문제가 발생합니다.
Node v0.11.x 버전부터는 V8 API의 중대한 변경이 있었습니다. 하지만 대부분의 네이티브 모듈은 Node v0.10.x 버전을 타겟으로 작성 되었기 때문에
새로운 Node 또는 io.js 버전에서 작동하지 않을 수 있습니다. Electron은 내부적으로 __io.js v3.1.0__ 버전을 사용하기 때문에 이러한 호환성 문제가 발생할 수 있습니다.
이 문제를 해결하기 위해 모듈이 Node v0.11.x 버전을 지원할 수 있도록 해야합니다.
현재 [많은 모듈들](https://www.npmjs.org/browse/depended/nan)이 안정적으로 두 버전 모두 지원하고 있지만 오래된 모듈의 경우 Node v0.10.x 버전만을 지원하고 있습니다.
예를 들어 [nan](https://github.com/rvagg/nan) 모듈을 사용해야 하는 경우 Node v0.11.x 버전으로 포팅 할 필요가 있습니다.
이 문제를 해결하기 위해 모듈이 v0.11.x 또는 최신 버전을 지원할 수 있도록 변경해야 합니다.
현재 [많은 모듈들](https://www.npmjs.org/browse/depended/nan)이 안정적으로 두 버전 모두 지원하고 있지만 오래된 모듈의 경우 여전히 Node v0.10.x 버전만을 지원하고 있습니다.
예를 들어 [nan](https://github.com/rvagg/nan) 모듈을 사용해야 한다면 Node v0.11.x 또는 최신 버전의 Node와 io.js로 포팅 할 필요가 있습니다.
## 네이티브 모듈 설치하는 방법
### 쉬운 방법 - 권장
### 쉬운 방법
[`electron-rebuild`](https://github.com/paulcbetts/electron-rebuild) 패키지를 사용하면 아주 빠르고 정확하게 네이티브 모듈을 다시 빌드할 수 있습니다.
다음의 간단한 절차를 통해 자동으로 헤더를 다운로드하고 네이티브 모듈을 빌드할 수 있습니다:
[`electron-rebuild`](https://github.com/paulcbetts/electron-rebuild) 패키지를 사용하면 빠르고 간단하게 네이티브 모듈을 다시 빌드할 수 있습니다.
간단한 절차를 통해 자동으로 헤더를 다운로드하고 네이티브 모듈을 빌드할 수 있습니다:
```sh
npm install --save-dev electron-rebuild
@ -30,7 +28,7 @@ npm install --save-dev electron-rebuild
### node-gyp을 이용한 방법
Node 모듈을 `node-gyp`를 사용하여 Electron을 타겟으로 빌드할 `node-gyp`에 헤더 다운로드 주소와 버전을 알려주어야합니다:
Node 모듈을 `node-gyp`를 사용하여 Electron을 타겟으로 빌드할 때는 `node-gyp`에 헤더 다운로드 주소와 버전을 알려주어야 합니다:
```bash
$ cd /path-to-module/
@ -42,8 +40,8 @@ $ HOME=~/.electron-gyp node-gyp rebuild --target=0.29.1 --arch=x64 --dist-url=ht
### npm을 이용한 방법
또한 `npm`사용하여 모듈을 설치할 수도 있습니다.
환경변수가 필요한 것을 제외하고 일반 Node 모듈을 설치하는 방법과 완전히 똑같습니다:
또한 `npm`통해 설치할 수도 있습니다.
환경변수가 필요한 것을 제외하고 일반 Node 모듈을 설치하는 방법과 완전히 똑같습니다:
```bash
export npm_config_disturl=https://atom.io/download/atom-shell

View file

@ -1,6 +1,7 @@
# Pepper 플래시 플러그인 사용하기
필요하다면 Pepper 플래시 플러그인을 사용할 수 있습니다. Electron에서 pepper 플래시 플러그인을 사용하기 위해선 따로 pepper 플래시 플러그인의 위치를 지정해 주어야합니다.
작업에 필요한 경우 pepper 플래시 플러그인을 사용할 수 있습니다.
Electron에서 pepper 플래시 플러그인을 사용하기 위해선 따로 pepper 플래시 플러그인의 위치를 지정해 주어야합니다.
## 플래시 플러그인 준비하기

View file

@ -0,0 +1,70 @@
## 向导
* [应用部署](tutorial/application-distribution.md)
* [应用打包](tutorial/application-packaging.md)
* [使用原生模块](tutorial/using-native-node-modules.md)
* [主进程调试](tutorial/debugging-main-process.md)
* [使用 Selenium 和 WebDriver](tutorial/using-selenium-and-webdriver.md)
* [调试工具扩展](tutorial/devtools-extension.md)
* [使用 PepperFlash 插件](tutorial/using-pepper-flash-plugin.md)
## 教程
* [快速入门](tutorial/quick-start.md)
* [桌面环境集成](tutorial/desktop-environment-integration.md)
* [在线/离线事件探测](tutorial/online-offline-events.md)
## API文档
* [简介](api/synopsis.md)
* [进程对象](api/process.md)
* [支持的Chrome命令行开关](api/chrome-command-line-switches.md)
定制的DOM元素:
* [`File`对象](api/file-object.md)
* [`<webview>`标签](api/web-view-tag.md)
* [`window.open`函数](api/window-open.md)
主进程可用的模块:
* [app](api/app.md)
* [auto-updater](api/auto-updater.md)
* [browser-window](api/browser-window.md)
* [content-tracing](api/content-tracing.md)
* [dialog](api/dialog.md)
* [global-shortcut](api/global-shortcut.md)
* [ipc (main process)](api/ipc-main-process.md)
* [menu](api/menu.md)
* [menu-item](api/menu-item.md)
* [power-monitor](api/power-monitor.md)
* [power-save-blocker](api/power-save-blocker.md)
* [protocol](api/protocol.md)
* [session](api/session.md)
* [webContents](api/web-contents.md)
* [tray](api/tray.md)
渲染进程(网页)可用的模块:
* [ipc (renderer)](api/ipc-renderer.md)
* [remote](api/remote.md)
* [web-frame](api/web-frame.md)
两种进程都可用的模块:
* [clipboard](api/clipboard.md)
* [crash-reporter](api/crash-reporter.md)
* [native-image](api/native-image.md)
* [screen](api/screen.md)
* [shell](api/shell.md)
## 开发
* [编码规范](development/coding-style.md)
* [源码文件结构](development/source-code-directory-structure.md)
* [与 NW.js (原名 node-webkit) 在技术上的差异](development/atom-shell-vs-node-webkit.md)
* [构建系统概况](development/build-system-overview.md)
* [构建步骤 (Mac)](development/build-instructions-mac.md)
* [构建步骤 (Windows)](development/build-instructions-windows.md)
* [构建步骤 (Linux)](development/build-instructions-linux.md)
* [在调试中使用 SymbolServer](development/setting-up-symbol-server.md)

View file

@ -0,0 +1,136 @@
# 快速入门
## 简介
Electron 可以让你使用纯 JavaScript 调用丰富的原生 APIs 来创造桌面应用。你可以把它看作是专注于桌面应用而不是 web 服务器的io.js 的一个变体。
这不意味着 Electron 是绑定了 GUI 库的 JavaScript。相反Electron 使用 web 页面作为它的 GUI所以你能把它看作成一个被 JavaScript 控制的,精简版的 Chromium 浏览器。
## 主进程
在 Electron 里,运行 `package.json``main` 脚本的进程被称为**主进程**。在主进程运行的脚本可以以创建 web 页面的形式展示 GUI。
## 渲染进程
由于 Electron 使用 Chromium 来展示页面,所以 Chromium 的多进程结构也被充分利用。每个 Electron 的页面都在运行着自己的进程,这样的进程我们称之为**渲染进程**。
在一般浏览器中网页通常会在沙盒环境下运行并且不允许访问原生资源。然后Electron 用户拥有在网页中调用 io.js 的 APIs 的能力,从而创造出低等的、与操作系统的交互。
## 主进程与渲染进程的区别
主进程使用 BroswerWindow 实例创建网页。每个 BroswerWindow 实例都在自己的渲染进程里运行着一个网页。当一个 BroswerWindow 实例被销毁,相应的渲染进程也会被终止。
主进程管理所有页面和与之对应的渲染进程。每个渲染进程都是相互独立的,并且只关心他们自己的网页。
由于在网页里管理原生 GUI 资源是非常危险而且容易造成资源泄露的,所以在网页面调用 GUI 相关的 APIs 是不被允许的。如果你想在网页里使用 GUI 操作,其对应的渲染进程必须与主进程进行通讯,请求主进程进行相关的 GUI 操作。
在 Electron,我们提供用于在主进程与渲染进程之间通讯的 [ipc][1] 模块。并且也有一个远程进程调用风格的通讯模块 [remote][2]。
# 打造你第一个 Electron 应用
大体上,一个 Electron 应用的目录结构如下:
````
your-app/
├── package.json
├── main.js
└── index.html
````
`package.json `的格式和 Node 的完全一致,并且那个被 `main` 字段声明的脚本文件是你的应用的启动脚本,它运行在主进程上。你应用里的 `package.json` 看起来应该像:
````
{
"name" : "your-app",
"version" : "0.1.0",
"main" : "main.js"
}
````
**注意**:如果 `main` 字段没有在 `package.json` 声明Electron会优先加载 `index.js`
`main.js` 应该用于创建窗口和处理系统时间,一个典型的例子如下:
````
var app = require('app'); // 控制应用生命周期的模块。
var BrowserWindow = require('browser-window'); // 创建原生浏览器窗口的模块
// 给我们的服务器发送异常报告。
require('crash-reporter').start();
// 保持一个对于 window 对象的全局引用,不然,当 JavaScript 被 GC
// window 会被自动地关闭
var mainWindow = null;
// 当所有窗口被关闭了,退出。
app.on('window-all-closed', function() {
// 在 OS X 上,通常用户在明确地按下 Cmd + Q 之前
// 应用会保持活动状态
if (process.platform != 'darwin') {
app.quit();
}
});
// 当 Electron 完成了初始化并且准备创建浏览器窗口的时候
// 这个方法就被调用
app.on('ready', function() {
// 创建浏览器窗口。
mainWindow = new BrowserWindow({width: 800, height: 600});
// 加载应用的 index.html
mainWindow.loadUrl('file://' + __dirname + '/index.html');
// 打开开发工具
mainWindow.openDevTools();
// 当 window 被关闭,这个事件会被发出
mainWindow.on('closed', function() {
// 取消引用 window 对象,如果你的应用支持多窗口的话,
// 通常会把多个 window 对象存放在一个数组里面,
// 但这次不是。
mainWindow = null;
});
});
````
最后,你想展示的 `index.html`
````
<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
We are using io.js <script>document.write(process.version)</script>
and Electron <script>document.write(process.versions['electron'])</script>.
</body>
</html>
````
# 运行你的应用
一旦你创建了最初的 `main.js` `index.html``package.json` 这几个文件,你可能会想尝试在本地运行并测试,看看是不是和期望的那样正常运行。
## electron-prebuild
如果你已经用 `npm` 全局安装了 `electron-prebuilt`,你只需要按照如下方式直接运行你的应用:
````
electron .
````
如果你是局部安装,那运行:
````
./node_modules/.bin/electron .
````
## 手工下载 Electron 二进制文件
如果你手工下载了 Electron 的二进制文件,你也可以直接使用其中的二进制文件直接运行你的应用。
### Windows
````
$ .\electron\electron.exe your-app\
````
### Linux
````
$ ./electron/electron your-app/
````
### OS X
````
$ ./Electron.app/Contents/MacOS/Electron your-app/
````
`Electron.app` 里面是 Electron 发布包,你可以在[这里][3]下载到。
# 以发行版本运行
在你完成了你的应用后,你可以按照[应用部署][4]指导发布一个版本,并且以已经打包好的形式运行应用。
[1]: https://github.com/atom/electron/blob/master/docs-translations/zh-CN/api/ipc-renderer.md
[2]: https://github.com/atom/electron/blob/master/docs-translations/zh-CN/api/remote.md
[3]: https://github.com/atom/electron/releases
[4]: https://github.com/atom/electron/blob/master/docs-translations/zh-CN/tutorial/application-distribution.md

View file

@ -269,7 +269,6 @@ Adds `tasks` to the [Tasks][tasks] category of the JumpList on Windows.
consists of two or more icons, set this value to identify the icon. If an
icon file consists of one icon, this value is 0.
### `app.commandLine.appendSwitch(switch[, value])`
Append a switch (with optional `value`) to Chromium's command line.

View file

@ -98,6 +98,10 @@ appropriate format.
`pub_date` (if present) must be formatted according to ISO 8601.
## Update server implementations
[Nuts](https://github.com/GitbookIO/nuts) is an open source implementation of the update server described above, it integrates beautifully with GitHub releases. Nuts manages downloads and updates, its compatible with `Squirrel.Mac` and `Squirrel.Windows` so you get cross-platform support out of the box.
## Events
The `autoUpdater` object emits the following events:

View file

@ -8,11 +8,11 @@ generated file to view the result.
```javascript
var contentTracing = require('content-tracing');
tracing.startRecording('*', tracing.DEFAULT_OPTIONS, function() {
contentTracing.startRecording('*', contentTracing.DEFAULT_OPTIONS, function() {
console.log('Tracing started');
setTimeout(function() {
tracing.stopRecording('', function(path) {
contentTracing.stopRecording('', function(path) {
console.log('Tracing data recorded to ' + path);
});
}, 5000);

View file

@ -48,12 +48,13 @@ selected when you want to limit the user to a specific type. For example:
]
}
```
The `extensions` array should contain extensions without wildcards or dots (e.g.
`'png'` is good but `'.png'` and `'*.png'` are bad). To show all files, use the
`'*'` wildcard (no other wildcard is supported).
If a `callback` is passed, the API call will be asynchronous and the result
wil be passed via `callback(filenames)`
will be passed via `callback(filenames)`
**Note:** On Windows and Linux an open dialog can not be both a file selector
and a directory selector, so if you set `properties` to

View file

@ -1,9 +1,12 @@
# global-shortcut
The `global-shortcut` module can register/unregister a global keyboard shortcut
with the operating system, so that you can customize the operations for various shortcuts.
Note that the shortcut is global; it will work even if the app does not have the keyboard focus.
You should not use this module until the `ready` event of the app module is emitted.
with the operating system so that you can customize the operations for various
shortcuts.
**Note**: The shortcut is global; it will work even if the app does
not have the keyboard focus. You should not use this module until the `ready`
event of the app module is emitted.
```javascript
var app = require('app');
@ -32,7 +35,11 @@ app.on('will-quit', function() {
});
```
## globalShortcut.register(accelerator, callback)
## Methods
The `global-shortcut` module has the following methods:
### `globalShortcut.register(accelerator, callback)`
* `accelerator` [Accelerator](accelerator.md)
* `callback` Function
@ -40,18 +47,19 @@ app.on('will-quit', function() {
Registers a global shortcut of `accelerator`. The `callback` is called when
the registered shortcut is pressed by the user.
## globalShortcut.isRegistered(accelerator)
### `globalShortcut.isRegistered(accelerator)`
* `accelerator` [Accelerator](accelerator.md)
Returns `true` or `false` depending on whether the shortcut `accelerator` is registered.
Returns `true` or `false` depending on whether the shortcut `accelerator` is
registered.
## globalShortcut.unregister(accelerator)
### `globalShortcut.unregister(accelerator)`
* `accelerator` [Accelerator](accelerator.md)
Unregisters the global shortcut of `keycode`.
Unregisters the global shortcut of `accelerator`.
## globalShortcut.unregisterAll()
### `globalShortcut.unregisterAll()`
Unregisters all the global shortcuts.

View file

@ -1,17 +1,22 @@
# ipc (main process)
Handles asynchronous and synchronous message sent from a renderer process (web
page).
The `ipc` module, when used in the main process, handles asynchronous and
synchronous messages sent from a renderer process (web page). Messages sent from
a renderer will be emitted to this module.
The messages sent from a renderer would be emitted to this module, the event name
is the `channel` when sending message. To reply a synchronous message, you need
to set `event.returnValue`, to send an asynchronous back to the sender, you can
use `event.sender.send(...)`.
## Sending Messages
It's also possible to send messages from main process to the renderer process,
see [WebContents.send](browser-window.md#webcontentssendchannel-args) for more.
It is also possible to send messages from the main process to the renderer
process, see [WebContents.send](browser-window.md#webcontentssendchannel-args)
for more information.
An example of sending and handling messages:
- When sending a message, the event name is the `channel`.
- To reply a synchronous message, you need to set `event.returnValue`.
- To send an asynchronous back to the sender, you can use
`event.sender.send(...)`.
An example of sending and handling messages between the render and main
processes:
```javascript
// In main process.
@ -38,12 +43,34 @@ ipc.on('asynchronous-reply', function(arg) {
ipc.send('asynchronous-message', 'ping');
```
## Class: Event
## Listening for Messages
### Event.returnValue
The `ipc` module has the following method to listen for events:
Assign to this to return an value to synchronous messages.
### `ipc.on(channel, callback)`
### Event.sender
* `channel` String - The event name.
* `callback` Function
The `WebContents` that sent the message.
When the event occurs the `callback` is called with an `event` object and a
message, `arg`.
## IPC Events
The `event` object passed to the `callback` has the following methods:
### `Event.returnValue`
Set this to the value to be returned in a synchronous message.
### `Event.sender`
Returns the `WebContents` that sent the message.
### `Event.sender.send(channel[, arg1][, arg2][, ...])`
* `channel` String - The event name.
* `arg` (optional)
This sends an asynchronous message back to the render process. Optionally, there
can be one or a series of arguments, `arg`, which can have any type.

View file

@ -1,29 +1,52 @@
# ipc (renderer)
The `ipc` module provides a few methods so you can send synchronous and
asynchronous messages to the main process, and also receive messages sent from
main process. If you want to make use of modules of main process from renderer
asynchronous messages from the render process (web page) to the main process.
You can also receive replies from the main process.
**Note**: If you want to make use of modules in the main process from the renderer
process, you might consider using the [remote](remote.md) module.
See [ipc (main process)](ipc-main-process.md) for examples.
See [ipc (main process)](ipc-main-process.md) for code examples.
## ipc.send(channel[, args...])
## Methods
Send `args..` to the renderer via `channel` in asynchronous message, the main
process can handle it by listening to the `channel` event of `ipc` module.
The `ipc` module has the following methods for sending messages:
## ipc.sendSync(channel[, args...])
**Note**: When using these methods to send a `message` you must also listen
for it in the main process with [`ipc (main process)`](ipc-main-process.md).
Send `args..` to the renderer via `channel` in synchronous message, and returns
the result sent from main process. The main process can handle it by listening to
the `channel` event of `ipc` module, and returns by setting `event.returnValue`.
### `ipc.send(channel[, arg1][, arg2][, ...])`
**Note:** Usually developers should never use this API, since sending
synchronous message would block the whole renderer process.
* `channel` String - The event name.
* `arg` (optional)
## ipc.sendToHost(channel[, args...])
Send an event to the main process asynchronously via a `channel`. Optionally,
there can be a message: one or a series of arguments, `arg`, which can have any
type. The main process handles it by listening for the `channel` event with
`ipc`.
Like `ipc.send` but the message will be sent to the host page instead of the
main process.
### `ipc.sendSync(channel[, arg1][, arg2][, ...])`
This is mainly used by the page in `<webview>` to communicate with host page.
* `channel` String - The event name.
* `arg` (optional)
Send an event to the main process synchronously via a `channel`. Optionally,
there can be a message: one or a series of arguments, `arg`, which can have any
type. The main process handles it by listening for the `channel` event with
`ipc`.
The main process handles it by listening for the `channel` event with `ipc` and
replies by setting the `event.returnValue`.
**Note:** Sending a synchronous message will block the whole renderer process so
using this method is not recommended.
### `ipc.sendToHost(channel[, arg1][, arg2][, ...])`
* `channel` String - The event name.
* `arg` (optional)
Like `ipc.send` but the event will be sent to the host page in a `<webview>`
instead of the main process. Optionally, there can be a message: one or a series
of arguments, `arg`, which can have any type.

View file

@ -1,13 +1,21 @@
# menu-item
# MenuItem
The `menu-item` module allows you to add items to an application or content
[`menu`](menu.md).
See [`menu`](menu.md) for examples.
## Class: MenuItem
Create a new `MenuItem` with the following method:
### new MenuItem(options)
* `options` Object
* `click` Function - Callback when the menu item is clicked
* `selector` String - Call the selector of first responder when clicked (OS
X only)
* `click` Function - Will be called with `click(menuItem, browserWindow)` when
the menu item is clicked
* `role` String - Define the action of the menu item, when specified the
`click` property will be ignored
* `type` String - Can be `normal`, `separator`, `submenu`, `checkbox` or
`radio`
* `label` String
@ -23,3 +31,29 @@
as a reference to this item by the position attribute.
* `position` String - This field allows fine-grained definition of the
specific location within a given menu.
When creating menu items, it is recommended to specify `role` instead of
manually implementing the behavior if there is matching action, so menu can have
best native experience.
The `role` property can have following values:
* `undo`
* `redo`
* `cut`
* `copy`
* `paste`
* `selectall`
* `minimize` - Minimize current window
* `close` - Close current window
On OS X `role` can also have following additional values:
* `about` - Map to the `orderFrontStandardAboutPanel` action
* `hide` - Map to the `hide` action
* `hideothers` - Map to the `hideOtherApplications` action
* `unhide` - Map to the `unhideAllApplications` action
* `front` - Map to the `arrangeInFront` action
* `window` - The submenu is a "Window" menu
* `help` - The submenu is a "Help" menu
* `services` - The submenu is a "Services" menu

View file

@ -1,12 +1,17 @@
# menu
# Menu
The `Menu` class is used to create native menus that can be used as
application menus and context menus. Each menu consists of multiple menu
items, and each menu item can have a submenu.
The `menu` class is used to create native menus that can be used as
application menus and
[context menus](https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/PopupGuide/ContextMenus).
This module is a main process module which can be used in a render process via
the `remote` module.
Below is an example of creating a menu dynamically in a web page by using
the [remote](remote.md) module, and showing it when the user right clicks
the page:
Each menu consists of multiple [menu items](menu-item.md) and each menu item can
have a submenu.
Below is an example of creating a menu dynamically in a web page
(render process) by using the [remote](remote.md) module, and showing it when
the user right clicks the page:
```html
<!-- index.html -->
@ -27,69 +32,23 @@ window.addEventListener('contextmenu', function (e) {
</script>
```
Another example of creating the application menu with the simple template API:
An example of creating the application menu in the render process with the
simple template API:
**Note to Window and Linux users** the `selector` member of each menu item is a Mac-only [Accelerator option](https://github.com/atom/electron/blob/master/docs/api/accelerator.md).
```html
<!-- index.html -->
<script>
var remote = require('remote');
var Menu = remote.require('menu');
```javascript
var template = [
{
label: 'Electron',
submenu: [
{
label: 'About Electron',
selector: 'orderFrontStandardAboutPanel:'
},
{
type: 'separator'
},
{
label: 'Services',
submenu: []
},
{
type: 'separator'
},
{
label: 'Hide Electron',
accelerator: 'CmdOrCtrl+H',
selector: 'hide:'
},
{
label: 'Hide Others',
accelerator: 'CmdOrCtrl+Shift+H',
selector: 'hideOtherApplications:'
},
{
label: 'Show All',
selector: 'unhideAllApplications:'
},
{
type: 'separator'
},
{
label: 'Quit',
accelerator: 'CmdOrCtrl+Q',
selector: 'terminate:'
},
]
},
{
label: 'Edit',
submenu: [
{
label: 'Undo',
accelerator: 'CmdOrCtrl+Z',
selector: 'undo:'
role: 'undo'
},
{
label: 'Redo',
accelerator: 'Shift+CmdOrCtrl+Z',
selector: 'redo:'
role: 'redo'
},
{
type: 'separator'
@ -97,23 +56,23 @@ var template = [
{
label: 'Cut',
accelerator: 'CmdOrCtrl+X',
selector: 'cut:'
role: 'cut'
},
{
label: 'Copy',
accelerator: 'CmdOrCtrl+C',
selector: 'copy:'
role: 'copy'
},
{
label: 'Paste',
accelerator: 'CmdOrCtrl+V',
selector: 'paste:'
role: 'paste'
},
{
label: 'Select All',
accelerator: 'CmdOrCtrl+A',
selector: 'selectAll:'
}
role: 'selectall'
},
]
},
{
@ -122,147 +81,224 @@ var template = [
{
label: 'Reload',
accelerator: 'CmdOrCtrl+R',
click: function() { remote.getCurrentWindow().reload(); }
click: function(item, focusedWindow) {
if (focusedWindow)
focusedWindow.reload();
}
},
{
label: 'Toggle DevTools',
accelerator: 'Alt+CmdOrCtrl+I',
click: function() { remote.getCurrentWindow().toggleDevTools(); }
label: 'Toggle Full Screen',
accelerator: (function() {
if (process.platform == 'darwin')
return 'Ctrl+Command+F';
else
return 'F11';
})(),
click: function(item, focusedWindow) {
if (focusedWindow)
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
}
},
{
label: 'Toggle Developer Tools',
accelerator: (function() {
if (process.platform == 'darwin')
return 'Alt+Command+I';
else
return 'Ctrl+Shift+I';
})(),
click: function(item, focusedWindow) {
if (focusedWindow)
focusedWindow.toggleDevTools();
}
},
]
},
{
label: 'Window',
role: 'window',
submenu: [
{
label: 'Minimize',
accelerator: 'CmdOrCtrl+M',
selector: 'performMiniaturize:'
role: 'minimize'
},
{
label: 'Close',
accelerator: 'CmdOrCtrl+W',
selector: 'performClose:'
role: 'close'
},
]
},
{
label: 'Help',
role: 'help',
submenu: [
{
label: 'Learn More',
click: function() { require('shell').openExternal('http://electron.atom.io') }
},
]
},
];
if (process.platform == 'darwin') {
var name = require('app').getName();
template.unshift({
label: name,
submenu: [
{
label: 'About ' + name,
role: 'about'
},
{
type: 'separator'
},
{
label: 'Bring All to Front',
selector: 'arrangeInFront:'
}
label: 'Services',
role: 'services',
submenu: []
},
{
type: 'separator'
},
{
label: 'Hide ' + name,
accelerator: 'Command+H',
role: 'hide'
},
{
label: 'Hide Others',
accelerator: 'Command+Shift+H',
role: 'hideothers:'
},
{
label: 'Show All',
role: 'unhide:'
},
{
type: 'separator'
},
{
label: 'Quit',
accelerator: 'Command+Q',
click: function() { app.quit(); }
},
]
},
{
label: 'Help',
submenu: []
}
];
});
// Window menu.
template[3].submenu.push(
{
type: 'separator'
},
{
label: 'Bring All to Front',
role: 'front'
}
);
}
menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
</script>
```
## Class: Menu
### new Menu()
### `new Menu()`
Creates a new menu.
### Class Method: Menu.setApplicationMenu(menu)
## Methods
The `menu` class has the following methods:
### `Menu.setApplicationMenu(menu)`
* `menu` Menu
Sets `menu` as the application menu on OS X. On Windows and Linux, the `menu`
will be set as each window's top menu.
### Class Method: Menu.sendActionToFirstResponder(action)
### `Menu.sendActionToFirstResponder(action)` _OS X_
* `action` String
Sends the `action` to the first responder of application, this is used for
Sends the `action` to the first responder of application. This is used for
emulating default Cocoa menu behaviors, usually you would just use the
`selector` property of `MenuItem`.
**Note:** This method is OS X only.
### Class Method: Menu.buildFromTemplate(template)
### `Menu.buildFromTemplate(template)`
* `template` Array
Generally, the `template` is just an array of `options` for constructing
[MenuItem](menu-item.md), the usage can be referenced above.
Generally, the `template` is just an array of `options` for constructing a
[MenuItem](menu-item.md). The usage can be referenced above.
You can also attach other fields to element of the `template`, and they will
become properties of the constructed menu items.
You can also attach other fields to the element of the `template` and they
will become properties of the constructed menu items.
### Menu.popup(browserWindow, [x, y])
### `Menu.popup(browserWindow[, x, y])`
* `browserWindow` BrowserWindow
* `x` Number
* `y` Number
* `x` Number (optional)
* `y` Number (**required** if `x` is used)
Popups this menu as a context menu in the `browserWindow`. You can optionally
provide a `(x,y)` coordinate to place the menu at, otherwise it will be placed
at the current mouse cursor position.
Pops up this menu as a context menu in the `browserWindow`. You
can optionally provide a `x,y` coordinate to place the menu at, otherwise it
will be placed at the current mouse cursor position.
### Menu.append(menuItem)
### `Menu.append(menuItem)`
* `menuItem` MenuItem
Appends the `menuItem` to the menu.
### Menu.insert(pos, menuItem)
### `Menu.insert(pos, menuItem)`
* `pos` Integer
* `menuItem` MenuItem
Inserts the `menuItem` to the `pos` position of the menu.
### Menu.items
### `Menu.items()`
Get the array containing the menu's items.
Get an array containing the menu's items.
## Notes on OS X application menu
## Notes on OS X Application Menu
OS X has a completely different style of application menu from Windows and
Linux, and here are some notes on making your app's menu more native-like.
Linux, here are some notes on making your app's menu more native-like.
### Standard menus
### Standard Menus
On OS X there are many system defined standard menus, like the `Services` and
`Windows` menus. To make your menu a standard menu, you can just set your menu's
label to one of followings, and Electron will recognize them and make them
`Windows` menus. To make your menu a standard menu, you should set your menu's
`role` to one of following and Electron will recognize them and make them
become standard menus:
* `Window`
* `Help`
* `Services`
* `window`
* `help`
* `services`
### Standard menu item actions
### Standard Menu Item Actions
OS X has provided standard actions for some menu items (which are called
`selector`s), like `About xxx`, `Hide xxx`, and `Hide Others`. To set the action
of a menu item to a standard action, you can set the `selector` attribute of the
menu item.
OS X has provided standard actions for some menu items, like `About xxx`,
`Hide xxx`, and `Hide Others`. To set the action of a menu item to a standard
action, you should set the `role` attribute of the menu item.
### Main menu's name
### Main Menu's Name
On OS X the label of application menu's first item is always your app's name,
no matter what label you set. To change it you have to change your app's name
by modifying your app bundle's `Info.plist` file. See
[About Information Property List Files](https://developer.apple.com/library/ios/documentation/general/Reference/InfoPlistKeyReference/Articles/AboutInformationPropertyListFiles.html)
for more.
by modifying your app bundle's `Info.plist` file. See [About Information
Property List Files][AboutInformationPropertyListFiles] for more information.
## Menu Item Position
## Menu item position
You can make use of `position` and `id` to control how the item would be placed
You can make use of `position` and `id` to control how the item will be placed
when building a menu with `Menu.buildFromTemplate`.
The `position` attribute of `MenuItem` has the form `[placement]=[id]` where
The `position` attribute of `MenuItem` has the form `[placement]=[id]`, where
placement is one of `before`, `after`, or `endof` and `id` is the unique ID of
an existing item in the menu:
@ -272,12 +308,12 @@ an existing item in the menu:
* `after` - Inserts this item after id referenced item. If the referenced
item doesn't exist the item will be inserted at the end of the menu.
* `endof` - Inserts this item at the end of the logical group containing
the id referenced item. (Groups are created by separator items). If
the referenced item doesn't exist a new separator group is created with
the id referenced item (groups are created by separator items). If
the referenced item doesn't exist, a new separator group is created with
the given id and this item is inserted after that separator.
When an item is positioned following unpositioned items are inserted after
it, until a new item is positioned. So if you want to position a group of
When an item is positioned, all un-positioned items are inserted after
it until a new item is positioned. So if you want to position a group of
menu items in the same location you only need to specify a position for
the first item.
@ -330,3 +366,5 @@ Menu:
- 2
- 3
```
[AboutInformationPropertyListFiles]: https://developer.apple.com/library/ios/documentation/general/Reference/InfoPlistKeyReference/Articles/AboutInformationPropertyListFiles.html

View file

@ -1,17 +1,17 @@
# NativeImage
In Electron for the APIs that take images, you can pass either file paths or
`NativeImage` instances. When passing `null`, an empty image will be used.
In Electron, for the APIs that take images, you can pass either file paths or
`NativeImage` instances. An empty image will be used when `null` is passed.
For example, when creating a tray or setting a window's icon, you can pass an image
file path as a `String`:
For example, when creating a tray or setting a window's icon, you can pass an
image file path as a `String`:
```javascript
var appIcon = new Tray('/Users/somebody/images/icon.png');
var window = new BrowserWindow({icon: '/Users/somebody/images/window.png'});
```
Or read the image from the clipboard:
Or read the image from the clipboard which returns a `NativeImage`:
```javascript
var clipboard = require('clipboard');
@ -19,25 +19,25 @@ var image = clipboard.readImage();
var appIcon = new Tray(image);
```
## Supported formats
## Supported Formats
Currently `PNG` and `JPEG` are supported. It is recommended to use `PNG` because
of its support for transparency and lossless compression.
Currently `PNG` and `JPEG` image formats are supported. `PNG` is recommended
because of its support for transparency and lossless compression.
On Windows, you can also load `ICO` icon from a file path.
On Windows, you can also load an `ICO` icon from a file path.
## High resolution image
## High Resolution Image
On platforms that have high-DPI support, you can append `@2x` after image's
file name's base name to mark it as a high resolution image.
base filename to mark it as a high resolution image.
For example if `icon.png` is a normal image that has standard resolution, the
`icon@2x.png` would be treated as a high resolution image that has double DPI
For example if `icon.png` is a normal image that has standard resolution, then
`icon@2x.png` will be treated as a high resolution image that has double DPI
density.
If you want to support displays with different DPI density at the same time, you
can put images with different sizes in the same folder, and use the filename
without DPI suffixes, like this:
If you want to support displays with different DPI densities at the same time,
you can put images with different sizes in the same folder and use the filename
without DPI suffixes. For example:
```text
images/
@ -51,7 +51,7 @@ images/
var appIcon = new Tray('/Users/somebody/images/icon.png');
```
Following suffixes as DPI denses are also supported:
Following suffixes for DPI are also supported:
* `@1x`
* `@1.25x`
@ -65,81 +65,91 @@ Following suffixes as DPI denses are also supported:
* `@4x`
* `@5x`
## Template image
## Template Image
Template images consist of black and clear colors (and an alpha channel).
Template images are not intended to be used as standalone images and are usually
mixed with other content to create the desired final appearance.
The most common case is to use template image for menu bar icon so it can adapt
to both light and dark menu bars.
The most common case is to use template images for a menu bar icon so it can
adapt to both light and dark menu bars.
Template image is only supported on Mac.
**Note**: Template image is only supported on OS X.
To mark an image as template image, its filename should end with the word
`Template`, examples are:
To mark an image as a template image, its filename should end with the word
`Template`. For example:
* `xxxTemplate.png`
* `xxxTemplate@2x.png`
## nativeImage.createEmpty()
## Methods
The `NativeImage` class has the following methods:
### `NativeImage.createEmpty()`
Creates an empty `NativeImage` instance.
## nativeImage.createFromPath(path)
### `NativeImage.createFromPath(path)`
* `path` String
Creates a new `NativeImage` instance from a file located at `path`.
## nativeImage.createFromBuffer(buffer[, scaleFactor])
### `NativeImage.createFromBuffer(buffer[, scaleFactor])`
* `buffer` [Buffer][buffer]
* `scaleFactor` Double
* `scaleFactor` Double (optional)
Creates a new `NativeImage` instance from `buffer`. The `scaleFactor` is 1.0 by
default.
Creates a new `NativeImage` instance from `buffer`. The default `scaleFactor` is
1.0.
## nativeImage.createFromDataUrl(dataUrl)
### `NativeImage.createFromDataUrl(dataUrl)`
* `dataUrl` String
Creates a new `NativeImage` instance from `dataUrl`.
## Class: NativeImage
## Instance Methods
This class is used to represent an image.
The following methods are available on instances of `nativeImage`:
### NativeImage.toPng()
```javascript
var NativeImage = require('native-image');
Returns a [Buffer][buffer] that contains image's `PNG` encoded data.
var image = NativeImage.createFromPath('/Users/somebody/images/icon.png');
```
### NativeImage.toJpeg(quality)
### `image.toPng()`
* `quality` Integer between 0 - 100 (required)
Returns a [Buffer][buffer] that contains the image's `PNG` encoded data.
Returns a [Buffer][buffer] that contains image's `JPEG` encoded data.
### `image.toJpeg(quality)`
### NativeImage.toDataUrl()
* `quality` Integer between 0 - 100 (**required**)
Returns the data URL of image.
Returns a [Buffer][buffer] that contains the image's `JPEG` encoded data.
### NativeImage.isEmpty()
### `image.toDataUrl()`
Returns whether the image is empty.
Returns the data URL of the image.
### NativeImage.getSize()
### `image.isEmpty()`
Returns a boolean whether the image is empty.
### `image.getSize()`
Returns the size of the image.
[buffer]: https://iojs.org/api/buffer.html#buffer_class_buffer
### NativeImage.setTemplateImage(option)
### `image.setTemplateImage(option)`
* `option` Boolean
Marks the image as template image.
### NativeImage.isTemplateImage()
### `image.isTemplateImage()`
Returns whether the image is a template image.
Returns a boolean whether the image is a template image.

View file

@ -1,10 +1,10 @@
# power-monitor
The `power-monitor` module is used to monitor the power state change. You can
only use it on the main process. You should not use this module until the `ready`
event of `app` module gets emitted.
The `power-monitor` module is used to monitor power state changes. You can
only use it on the main process. You should not use this module until the `ready`
event of the `app` module is emitted.
An example is:
For example:
```javascript
var app = require('app');
@ -16,18 +16,22 @@ app.on('ready', function() {
});
```
## Event: suspend
## Events
The `power-monitor` module emits the following events:
### Event: 'suspend'
Emitted when the system is suspending.
## Event: resume
### Event: 'resume'
Emitted when system is resuming.
## Event: on-ac
### Event: 'on-ac'
Emitted when the system changes to AC power.
## Event: on-battery
### Event: 'on-battery'
Emitted when system changes to battery power.

View file

@ -1,9 +1,10 @@
# power-save-blocker
# powerSaveBlocker
The `power-save-blocker` module is used to block the system from entering
low-power(sleep) mode, allowing app to keep system and screen active.
low-power (sleep) mode and thus allowing the app to keep the system and screen
active.
An example is:
For example:
```javascript
var powerSaveBlocker = require('power-save-blocker');
@ -14,35 +15,40 @@ console.log(powerSaveBlocker.isStarted(id));
powerSaveBlocker.stop(id);
```
## powerSaveBlocker.start(type)
## Methods
* `type` String - Power save blocker type
The `powerSaveBlocker` module has the following methods:
### `powerSaveBlocker.start(type)`
* `type` String - Power save blocker type.
* `prevent-app-suspension` - Prevent the application from being suspended.
Keeps system active, but allows screen to be turned off. Example use cases:
downloading a file, playing audio.
* `prevent-display-sleep`- Prevent the display from going to sleep. Keeps system
and screen active. Example use case: playing video.
Keeps system active but allows screen to be turned off. Example use cases:
downloading a file or playing audio.
* `prevent-display-sleep`- Prevent the display from going to sleep. Keeps
system and screen active. Example use case: playing video.
Starts the power save blocker preventing the system entering lower-power mode.
Returns an integer identified the power save blocker.
Starts preventing the system from entering lower-power mode. Returns an integer
identifying the power save blocker.
**Note:**
`prevent-display-sleep` has higher precedence level than `prevent-app-suspension`.
Only the highest precedence type takes effect. In other words, `prevent-display-sleep`
always take precedence over `prevent-app-suspension`.
**Note:** `prevent-display-sleep` has higher has precedence over
`prevent-app-suspension`. Only the highest precedence type takes effect. In
other words, `prevent-display-sleep` always takes precedence over
`prevent-app-suspension`.
For example, an API calling A requests for `prevent-app-suspension`, and
another calling B requests for `prevent-display-sleep`. `prevent-display-sleep`
will be used until B stops its request. After that, `prevent-app-suspension` is used.
will be used until B stops its request. After that, `prevent-app-suspension`
is used.
## powerSaveBlocker.stop(id)
### `powerSaveBlocker.stop(id)`
* `id` Integer - The power save blocker id returned by `powerSaveBlocker.start`.
Stops the specified power save blocker.
## powerSaveBlocker.isStarted(id)
### `powerSaveBlocker.isStarted(id)`
* `id` Integer - The power save blocker id returned by `powerSaveBlocker.start`.
Returns whether the corresponding `powerSaveBlocker` starts.
Returns a boolean whether the corresponding `powerSaveBlocker` has started.

View file

@ -1,13 +1,25 @@
# Process object
# process
The `process` object in Electron has the following differences from the one in
upstream node:
* `process.type` String - Process's type, can be `browser` (i.e. main process) or `renderer`.
* `process.type` String - Process's type, can be `browser` (i.e. main process)
or `renderer`.
* `process.versions['electron']` String - Version of Electron.
* `process.versions['chrome']` String - Version of Chromium.
* `process.resourcesPath` String - Path to JavaScript source code.
## process.hang
# Methods
The `process` object has the following method:
### `process.hang`
Causes the main thread of the current process hang.
## process.setFdLimit(maxDescriptors) _OS X_ _Linux_
* `maxDescriptors` Integer
Sets the file descriptor soft limit to `maxDescriptors` or the OS hard
limit, whichever is lower for the current process.

View file

@ -3,7 +3,7 @@
The `protocol` module can register a custom protocol or intercept an existing
protocol.
An example of implementing a protocol that has the same effect with the
An example of implementing a protocol that has the same effect as the
`file://` protocol:
```javascript
@ -22,50 +22,56 @@ app.on('ready', function() {
});
```
**Note:** This module can only be used after the `ready` event was emitted.
**Note:** This module can only be used after the `ready` event in the `app`
module is emitted.
## protocol.registerStandardSchemes(schemes)
## Methods
The `protocol` module has the following methods:
### `protocol.registerStandardSchemes(schemes)`
* `schemes` Array - Custom schemes to be registered as standard schemes.
A standard scheme adheres to what RFC 3986 calls
A standard `scheme` adheres to what RFC 3986 calls
[generic URI syntax](https://tools.ietf.org/html/rfc3986#section-3). This
includes `file:` and `filesystem:`.
## protocol.registerFileProtocol(scheme, handler[, completion])
### `protocol.registerFileProtocol(scheme, handler[, completion])`
* `scheme` String
* `handler` Function
* `completion` Function
* `completion` Function (optional)
Registers a protocol of `scheme` that will send file as response, the `handler`
will be called with `handler(request, callback)` when a `request` is going to be
created with `scheme`, and `completion` will be called with `completion(null)`
when `scheme` is successfully registered, or `completion(error)` when failed.
Registers a protocol of `scheme` that will send the file as a response. The
`handler` will be called with `handler(request, callback)` when a `request` is
going to be created with `scheme`. `completion` will be called with
`completion(null)` when `scheme` is successfully registered or
`completion(error)` when failed.
To handle the `request`, the `callback` should be called with either file's path
or an object that has `path` property, e.g. `callback(filePath)` or
To handle the `request`, the `callback` should be called with either the file's
path or an object that has a `path` property, e.g. `callback(filePath)` or
`callback({path: filePath})`.
When `callback` is called with nothing, or a number, or an object that has
`error` property, the `request` will be failed with the `error` number you
specified. For the available error numbers you can use, please check:
https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h
When `callback` is called with nothing, a number, or an object that has an
`error` property, the `request` will fail with the `error` number you
specified. For the available error numbers you can use, please see the
[net error list](https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h).
By default the scheme is treated like `http:`, which is parsed differently
from protocols that follows "generic URI syntax" like `file:`, so you probably
want to call `protocol.registerStandardSchemes` to make your scheme treated as
standard scheme.
By default the `scheme` is treated like `http:`, which is parsed differently
than protocols that follow the "generic URI syntax" like `file:`, so you
probably want to call `protocol.registerStandardSchemes` to have your scheme
treated as a standard scheme.
## protocol.registerBufferProtocol(scheme, handler[, completion])
### `protocol.registerBufferProtocol(scheme, handler[, completion])`
* `scheme` String
* `handler` Function
* `completion` Function
* `completion` Function (optional)
Registers a protocol of `scheme` that will send `Buffer` as response, the
`callback` should be called with either an `Buffer` object, or an object that
has `data`, `mimeType`, `chart` properties.
Registers a protocol of `scheme` that will send a `Buffer` as a response. The
`callback` should be called with either a `Buffer` object or an object that
has the `data`, `mimeType`, and `chart` properties.
Example:
@ -78,37 +84,37 @@ protocol.registerBufferProtocol('atom', function(request, callback) {
});
```
## protocol.registerStringProtocol(scheme, handler[, completion])
### `protocol.registerStringProtocol(scheme, handler[, completion])`
* `scheme` String
* `handler` Function
* `completion` Function
* `completion` Function (optional)
Registers a protocol of `scheme` that will send `String` as response, the
`callback` should be called with either a `String`, or an object that
has `data`, `mimeType`, `chart` properties.
Registers a protocol of `scheme` that will send a `String` as a response. The
`callback` should be called with either a `String` or an object that has the
`data`, `mimeType`, and `chart` properties.
## protocol.registerHttpProtocol(scheme, handler[, completion])
### `protocol.registerHttpProtocol(scheme, handler[, completion])`
* `scheme` String
* `handler` Function
* `completion` Function
* `completion` Function (optional)
Registers a protocol of `scheme` that will send a HTTP request as response, the
`callback` should be called with an object that has `url`, `method`, `referer`,
`session` properties.
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.
By default the HTTP request will reuse current session, if you want the request
to have different session you should specify `session` to `null`.
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`.
## protocol.unregisterProtocol(scheme[, completion])
### `protocol.unregisterProtocol(scheme[, completion])`
* `scheme` String
* `completion` Function
* `completion` Function (optional)
Unregisters the custom protocol of `scheme`.
## protocol.isProtocolHandled(scheme, callback)
### `protocol.isProtocolHandled(scheme, callback)`
* `scheme` String
* `callback` Function
@ -116,43 +122,43 @@ Unregisters the custom protocol of `scheme`.
The `callback` will be called with a boolean that indicates whether there is
already a handler for `scheme`.
## protocol.interceptFileProtocol(scheme, handler[, completion])
### `protocol.interceptFileProtocol(scheme, handler[, completion])`
* `scheme` String
* `handler` Function
* `completion` Function
* `completion` Function (optional)
Intercepts `scheme` protocol and use `handler` as the protocol's new handler
which sends file as response.
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
which sends a file as a response.
## protocol.interceptStringProtocol(scheme, handler[, completion])
### `protocol.interceptStringProtocol(scheme, handler[, completion])`
* `scheme` String
* `handler` Function
* `completion` Function
* `completion` Function (optional)
Intercepts `scheme` protocol and use `handler` as the protocol's new handler
which sends String as response.
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
which sends a `String` as a response.
## protocol.interceptBufferProtocol(scheme, handler[, completion])
## `protocol.interceptBufferProtocol(scheme, handler[, completion])`
* `scheme` String
* `handler` Function
* `completion` Function
* `completion` Function (optional)
Intercepts `scheme` protocol and use `handler` as the protocol's new handler
which sends `Buffer` as response.
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
which sends a `Buffer` as a response.
## protocol.interceptHttpProtocol(scheme, handler[, completion])
## `protocol.interceptHttpProtocol(scheme, handler[, completion])`
* `scheme` String
* `handler` Function
* `completion` Function
* `completion` Function (optional)
Intercepts `scheme` protocol and use `handler` as the protocol's new handler
which sends a new HTTP request as response.
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
which sends a new HTTP request as a response.
## protocol.uninterceptProtocol(scheme[, completion])
## `protocol.uninterceptProtocol(scheme[, completion])`
* `scheme` String
* `completion` Function

View file

@ -1,29 +1,29 @@
# remote
The `remote` module provides a simple way to do inter-process communication
between the renderer process and the main process.
(IPC) between the renderer process (web page) and the main process.
In Electron, only GUI-unrelated modules are available in the renderer process.
Without the `remote` module, users who wanted to call a main process API in
the renderer process would have to explicitly send inter-process messages
to the main process. With the `remote` module, users can invoke methods of
main process object without explicitly sending inter-process messages,
similar to Java's
[RMI](http://en.wikipedia.org/wiki/Java_remote_method_invocation).
Without the `remote` module, users who want to call a main process API in
the renderer process will have to explicitly send inter-process messages
to the main process. With the `remote` module, you can invoke methods of the
main process object without explicitly sending inter-process messages, similar
to Java's [RMI](http://en.wikipedia.org/wiki/Java_remote_method_invocation).
An example of creating a browser window in renderer process:
An example of creating a browser window from a renderer process:
```javascript
var remote = require('remote');
var BrowserWindow = remote.require('browser-window');
var win = new BrowserWindow({ width: 800, height: 600 });
win.loadUrl('https://github.com');
```
Note: for the reverse (access renderer process from main process), you can use
[webContents.executeJavascript](browser-window.md#webcontents-executejavascript-code).
**Note**: for the reverse (access the renderer process from the main process),
you can use [webContents.executeJavascript](browser-window.md#webcontents-executejavascript-code).
## Remote objects
## Remote Objects
Each object (including functions) returned by the `remote` module represents an
object in the main process (we call it a remote object or remote function).
@ -32,34 +32,37 @@ a new object with the remote constructor (function), you are actually sending
synchronous inter-process messages.
In the example above, both `BrowserWindow` and `win` were remote objects and
`new BrowserWindow` didn't create a `BrowserWindow` object in the renderer process.
Instead, it created a `BrowserWindow` object in the main process and returned the
corresponding remote object in the renderer process, namely the `win` object.
`new BrowserWindow` didn't create a `BrowserWindow` object in the renderer
process. Instead, it created a `BrowserWindow` object in the main process and
returned the corresponding remote object in the renderer process, namely the
`win` object.
## Lifetime of remote objects
## Lifetime of Remote Objects
Electron makes sure that as long as the remote object in the renderer process
lives (in other words, has not been garbage collected), the corresponding object
in the main process would never be released. When the remote object has been
garbage collected, the corresponding object in the main process would be
in the main process will not be released. When the remote object has been
garbage collected, the corresponding object in the main process will be
dereferenced.
If the remote object is leaked in renderer process (e.g. stored in a map but never
freed), the corresponding object in the main process would also be leaked,
If the remote object is leaked in the renderer process (e.g. stored in a map but
never freed), the corresponding object in the main process will also be leaked,
so you should be very careful not to leak remote objects.
Primary value types like strings and numbers, however, are sent by copy.
## Passing callbacks to the main process
Code in the main process can accept callbacks from the renderer - for instance the `remote` module -
but you should be extremely careful when using this feature.
Code in the main process can accept callbacks from the renderer - for instance
the `remote` module - but you should be extremely careful when using this
feature.
First, in order to avoid deadlocks, the callbacks passed to the main process
are called asynchronously. You should not expect the main process to
get the return value of the passed callbacks.
For instance you can't use a function from the renderer process in a `Array.map` called in the main process:
For instance you can't use a function from the renderer process in an
`Array.map` called in the main process:
```javascript
// main process mapNumbers.js
@ -69,10 +72,12 @@ exports.withRendererCallback = function(mapper) {
exports.withLocalCallback = function() {
return exports.mapNumbers(function(x) {
return x + 1;
return x + 1;
});
}
```
```javascript
// renderer process
var mapNumbers = require("remote").require("mapNumbers");
@ -85,8 +90,9 @@ var withLocalCb = mapNumbers.withLocalCallback()
console.log(withRendererCb, withLocalCb) // [true, true, true], [2, 3, 4]
```
As you can see, the renderer callback's synchronous return value was not as expected,
and didn't match the return value of an indentical callback that lives in the main process.
As you can see, the renderer callback's synchronous return value was not as
expected, and didn't match the return value of an identical callback that lives
in the main process.
Second, the callbacks passed to the main process will persist until the
main process garbage-collects them.
@ -96,45 +102,52 @@ callback for the `close` event on a remote object:
```javascript
var remote = require('remote');
remote.getCurrentWindow().on('close', function() {
// blabla...
});
```
But remember the callback is referenced by the main process until you
explicitly uninstall it! If you do not, each time you reload your window the callback will
be installed again, leaking one callback each restart.
explicitly uninstall it. If you do not, each time you reload your window the
callback will be installed again, leaking one callback for each restart.
To make things worse, since the context of previously installed callbacks have been released,
when the `close` event was emitted exceptions would be raised in the main process.
To make things worse, since the context of previously installed callbacks has
been released, exceptions will be raised in the main process when the `close`
event is emitted.
To avoid this problem, ensure you clean up any references to renderer callbacks passed to the main
process. This involves cleaning up event handlers, or ensuring the main process is explicitly told to deference
callbacks that came from a renderer process that is exiting.
To avoid this problem, ensure you clean up any references to renderer callbacks
passed to the main process. This involves cleaning up event handlers, or
ensuring the main process is explicitly told to deference callbacks that came
from a renderer process that is exiting.
## remote.require(module)
## Methods
The `remote` module has the following methods:
### `remote.require(module)`
* `module` String
Returns the object returned by `require(module)` in the main process.
## remote.getCurrentWindow()
### `remote.getCurrentWindow()`
Returns the [BrowserWindow](browser-window.md) object which this web page
belongs to.
Returns the [`BrowserWindow`](browser-window.md) object to which this web page
belongs.
## remote.getCurrentWebContents()
### `remote.getCurrentWebContents()`
Returns the WebContents object of this web page.
Returns the [`WebContents`](web-contents.md) object of this web page.
## remote.getGlobal(name)
### `remote.getGlobal(name)`
* `name` String
Returns the global variable of `name` (e.g. `global[name]`) in the main
process.
## remote.process
### `remote.process`
Returns the `process` object in the main process. This is the same as
`remote.getGlobal('process')`, but gets cached.
`remote.getGlobal('process')` but is cached.

View file

@ -1,11 +1,14 @@
# screen
Gets various info about screen size, displays, cursor position, etc. You should
not use this module until the `ready` event of `app` module gets emitted.
The `screen` module retrieves information about screen size, displays, cursor
position, etc. You should not use this module until the `ready` event of the
`app` module is emitted.
`screen` is an [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter).
Make sure to note that in the renderer / DevTools, `window.screen` is a reserved DOM property, so writing `screen = require('screen')` won't work. In our examples below, we use `atomScreen` as the variable name instead.
**Note**: In the renderer / DevTools, `window.screen` is a reserved
DOM property, so writing `var screen = require('screen')` will not work. In our
examples below, we use `atomScreen` as the variable name instead.
An example of creating a window that fills the whole screen:
@ -50,43 +53,57 @@ app.on('ready', function() {
});
```
## Event: display-added
## Events
The `screen` module emits the following events:
### Event: 'display-added'
Returns:
* `event` Event
* `newDisplay` Object
Emitted when `newDisplay` has been added.
## Event: display-removed
### Event: 'display-removed'
Returns:
* `event` Event
* `oldDisplay` Object
Emitted when `oldDisplay` has been removed.
## Event: display-metrics-changed
### Event: 'display-metrics-changed'
Returns:
* `event` Event
* `display` Object
* `changedMetrics` Array
Emitted when a `display` has one or more metrics changed, `changedMetrics` is
Emitted when one or more metrics change in a `display`. The `changedMetrics` is
an array of strings that describe the changes. Possible changes are `bounds`,
`workArea`, `scaleFactor` and `rotation`.
## screen.getCursorScreenPoint()
## Methods
The `screen` module has the following methods:
### `screen.getCursorScreenPoint()`
Returns the current absolute position of the mouse pointer.
## screen.getPrimaryDisplay()
### `screen.getPrimaryDisplay()`
Returns the primary display.
## screen.getAllDisplays()
### `screen.getAllDisplays()`
Returns an array of displays that are currently available.
## screen.getDisplayNearestPoint(point)
### `screen.getDisplayNearestPoint(point)`
* `point` Object
* `x` Integer
@ -94,7 +111,7 @@ Returns an array of displays that are currently available.
Returns the display nearest the specified point.
## screen.getDisplayMatching(rect)
### `screen.getDisplayMatching(rect)`
* `rect` Object
* `x` Integer

View file

@ -13,6 +13,31 @@ win.loadUrl("http://github.com");
var session = win.webContents.session
```
## Events
### Event: 'will-download'
* `event` Event
* `item` Object
* `url` String
* `filename` String
* `mimeType` String
* `hasUserGesture` Boolean
* `webContents` [WebContents](web-contents.md)
Fired when Electron is about to download `item` in `webContents`.
Calling `event.preventDefault()` will cancel the download.
```javascript
session.on('will-download', function(event, item, webContents) {
event.preventDefault();
require('request')(item.url, function(data) {
require('fs').writeFileSync('/somewhere', data);
});
});
```
## Methods
The `session` object has the following methods:

View file

@ -2,38 +2,43 @@
The `shell` module provides functions related to desktop integration.
An example of opening a URL in default browser:
An example of opening a URL in the user's default browser:
```javascript
var shell = require('shell');
shell.openExternal('https://github.com');
```
## shell.showItemInFolder(fullPath)
## Methods
The `shell` module has the following methods:
### `shell.showItemInFolder(fullPath)`
* `fullPath` String
Show the given file in a file manager. If possible, select the file.
## shell.openItem(fullPath)
### `shell.openItem(fullPath)`
* `fullPath` String
Open the given file in the desktop's default manner.
## shell.openExternal(url)
### `shell.openExternal(url)`
* `url` String
Open the given external protocol URL in the desktop's default manner. (For
example, mailto: URLs in the default mail user agent.)
example, mailto: URLs in the user's default mail agent.)
## shell.moveItemToTrash(fullPath)
### `shell.moveItemToTrash(fullPath)`
* `fullPath` String
Move the given file to trash and returns boolean status for the operation.
Move the given file to trash and returns a boolean status for the operation.
## shell.beep()
### `shell.beep()`
Play the beep sound.

View file

@ -1,18 +1,22 @@
# Synopsis
All of [node.js's built-in modules](http://nodejs.org/api/) are available in
Electron, and third-party node modules are fully supported too (including the
[native modules](../tutorial/using-native-node-modules.md)).
All of [Node.js's built-in modules](http://nodejs.org/api/) are available in
Electron and third-party node modules also fully supported as well (including
the [native modules](../tutorial/using-native-node-modules.md)).
Electron also provides some extra built-in modules for developing native
desktop applications. Some modules are only available on the main process, some
are only available on the renderer process, and some can be used on both processes.
The basic rule is: if a module is GUI or low-level system related, then it should
be only available on the main process. You need to be familiar with the concept of
are only available in the renderer process (web page), and some can be used in
both processes.
The basic rule is: if a module is
[GUI](https://en.wikipedia.org/wiki/Graphical_user_interface) or low-level
system related, then it should be only available on the main process. You need
to be familiar with the concept of
[main process vs. renderer process](../tutorial/quick-start.md#the-main-process)
scripts to be able to use those modules.
The main process script is just like a normal `node.js` script:
The main process script is just like a normal Node.js script:
```javascript
var app = require('app');
@ -26,7 +30,7 @@ app.on('ready', function() {
});
```
The web page is no different than a normal web page, except for the extra
The renderer process is no different than a normal web page, except for the extra
ability to use node modules:
```html

View file

@ -1,6 +1,6 @@
# tray
# Tray
A `Tray` represents an icon in operating system's notification area, it is
A `Tray` represents an icon in an operating system's notification area, it is
usually attached with a context menu.
```javascript
@ -25,26 +25,33 @@ app.on('ready', function(){
__Platform limitations:__
* On Linux app indicator will be used if it is supported, otherwise
* On Linux the app indicator will be used if it is supported, otherwise
`GtkStatusIcon` will be used instead.
* On Linux distributions that only have app indicator support, you have to
install `libappindicator1` to make tray icon work.
* App indicator will only be showed when it has context menu.
* When app indicator is used on Linux, `clicked` event is ignored.
install `libappindicator1` to make the tray icon work.
* App indicator will only be shown when it has a context menu.
* When app indicator is used on Linux, the `clicked` event is ignored.
So if you want to keep exact same behaviors on all platforms, you should not
rely on `clicked` event and always attach a context menu to the tray icon.
If you want to keep exact same behaviors on all platforms, you should not
rely on the `clicked` event and always attach a context menu to the tray icon.
## Class: Tray
`Tray` is an [EventEmitter][event-emitter].
### new Tray(image)
### `new Tray(image)`
* `image` [NativeImage](native-image.md)
Creates a new tray icon associated with the `image`.
## Events
The `Tray` module emits the following events:
**Note:** Some events are only available on specific operating systems and are
labeled as such.
### Event: 'clicked'
* `event` Event
@ -52,7 +59,7 @@ Creates a new tray icon associated with the `image`.
* `shiftKey` Boolean
* `ctrlKey` Boolean
* `metaKey` Boolean
* `bounds` Object - the bounds of tray icon
* `bounds` Object - the bounds of tray icon.
* `x` Integer
* `y` Integer
* `width` Integer
@ -62,14 +69,14 @@ Emitted when the tray icon is clicked.
__Note:__ The `bounds` payload is only implemented on OS X and Windows.
### Event: 'right-clicked'
### Event: 'right-clicked' _OS X_ _Windows_
* `event` Event
* `altKey` Boolean
* `shiftKey` Boolean
* `ctrlKey` Boolean
* `metaKey` Boolean
* `bounds` Object - the bounds of tray icon
* `bounds` Object - the bounds of tray icon.
* `x` Integer
* `y` Integer
* `width` Integer
@ -77,9 +84,7 @@ __Note:__ The `bounds` payload is only implemented on OS X and Windows.
Emitted when the tray icon is right clicked.
__Note:__ This is only implemented on OS X and Windows.
### Event: 'double-clicked'
### Event: 'double-clicked' _OS X_ _Windows_
* `event` Event
* `altKey` Boolean
@ -94,75 +99,68 @@ __Note:__ This is only implemented on OS X and Windows.
Emitted when the tray icon is double clicked.
__Note:__ This is only implemented on OS X and Windows.
### Event: 'balloon-show'
### Event: 'balloon-show' _Windows_
Emitted when the tray balloon shows.
__Note:__ This is only implemented on Windows.
### Event: 'balloon-clicked'
### Event: 'balloon-clicked' _Windows_
Emitted when the tray balloon is clicked.
__Note:__ This is only implemented on Windows.
### Event: 'balloon-closed'
### Event: 'balloon-closed' _Windows_
Emitted when the tray balloon is closed because of timeout or user manually
closes it.
__Note:__ This is only implemented on Windows.
### Event: 'drop-files'
### Event: 'drop-files' _OS X_
* `event`
* `files` Array - the file path of dropped files.
Emitted when dragged files are dropped in the tray icon.
__Note:__ This is only implemented on OS X.
## Methods
### Tray.destroy()
The `Tray` module has the following methods:
**Note**: Some methods are only available on specific operating systems and are
labeled as such.
### `Tray.destroy()`
Destroys the tray icon immediately.
### Tray.setImage(image)
### `Tray.setImage(image)`
* `image` [NativeImage](native-image.md)
Sets the `image` associated with this tray icon.
### Tray.setPressedImage(image)
### `Tray.setPressedImage(image)` _OS X_
* `image` [NativeImage](native-image.md)
Sets the `image` associated with this tray icon when pressed on OS X.
### Tray.setToolTip(toolTip)
### `Tray.setToolTip(toolTip)`
* `toolTip` String
Sets the hover text for this tray icon.
### Tray.setTitle(title)
### `Tray.setTitle(title)` _OS X_
* `title` String
Sets the title displayed aside of the tray icon in the status bar.
__Note:__ This is only implemented on OS X.
### Tray.setHighlightMode(highlight)
### `Tray.setHighlightMode(highlight)` _OS X_
* `highlight` Boolean
Sets whether the tray icon is highlighted when it is clicked.
__Note:__ This is only implemented on OS X.
### Tray.displayBalloon(options)
### `Tray.displayBalloon(options)` _Windows_
* `options` Object
* `icon` [NativeImage](native-image.md)
@ -171,19 +169,15 @@ __Note:__ This is only implemented on OS X.
Displays a tray balloon.
__Note:__ This is only implemented on Windows.
### `Tray.popUpContextMenu([position])` _OS X_ _Windows_
### Tray.popUpContextMenu([position])
* `position` Object - The pop position
* `position` Object (optional)- The pop up position.
* `x` Integer
* `y` Integer
The `position` is only available on Windows, and it is (0, 0) by default.
__Note:__ This is only implemented on OS X and Windows.
### Tray.setContextMenu(menu)
### `Tray.setContextMenu(menu)`
* `menu` Menu

View file

@ -22,8 +22,16 @@ $ sudo apt-get install build-essential clang libdbus-1-dev libgtk2.0-dev \
libxss1 libnss3-dev gcc-multilib g++-multilib
```
On Fedora, install the following libraries:
```bash
$ sudo yum install clang dbus-devel gtk2-devel libnotify-devel libgnome-keyring-devel \
xorg-x11-server-utils libcap-devel cups-devel libXtst-devel \
alsa-lib-devel libXrandr-devel GConf2-devel nss-devel
```
Other distributions may offer similar packages for installation via package
managers such as `yum`. Or you can compile from source code.
managers such as pacman. Or one can compile from source code.
## If You Use Virtual Machines For Building

View file

@ -29,7 +29,7 @@ var app = require('app');
app.addRecentDocument('/Users/USERNAME/Desktop/work.type');
```
And you can use [app.clearRecentDocuments](clearrecentdocuments) API to empty
And you can use [app.clearRecentDocuments][clearrecentdocuments] API to empty
the recent documents list:
```javascript

View file

@ -8,14 +8,8 @@ From [ChromeDriver - WebDriver for Chrome][chrome-driver]:
> implements WebDriver's wire protocol for Chromium. It is being developed by
> members of the Chromium and WebDriver teams.
In Electron's [releases](https://github.com/atom/electron/releases) page you
can find archives of `chromedriver`, there is no difference between Electron's
distribution of `chromedriver` and upstream ones, so in order to use
`chromedriver` together with Electron, you will need some special setup.
Also notice that only minor version update releases (e.g. `vX.X.0` releases)
include `chromedriver` archives, because `chromedriver` doesn't change as
frequent as Electron itself.
In order to use `chromedriver` together with Electron you have to tell it where to
find Electron and make it think Electron is Chrome browser.
## Setting up with WebDriverJs

View file

@ -63,6 +63,15 @@ describe 'chromium feature', ->
b.close()
done(if opener isnt null then undefined else opener)
describe 'window.opener.postMessage', ->
it 'sets source and origin correctly', (done) ->
b = window.open "file://#{fixtures}/pages/window-opener-postMessage.html", 'test', 'show=no'
window.addEventListener 'message', (event) ->
b.close()
assert.equal event.source.guestId, b.guestId
assert.equal event.origin, 'file://'
done()
describe 'creating a Uint8Array under browser side', ->
it 'does not crash', ->
RUint8Array = remote.getGlobal 'Uint8Array'

10
spec/fixtures/pages/post.html vendored Normal file
View file

@ -0,0 +1,10 @@
<html>
<body>
<form id="form" action="d.html" method="post" accept-charset="utf-8">
<p><input type="submit" value="submit"></p>
</form>
<script type="text/javascript" charset="utf-8">
document.getElementById("form").submit();
</script>
</body>
</html>

View file

@ -0,0 +1,7 @@
<html>
<body>
<script type="text/javascript" charset="utf-8">
window.opener.postMessage('message', '*');
</script>
</body>
</html>

View file

@ -48,6 +48,14 @@ describe '<webview> tag', ->
webview.src = "file://#{fixtures}/pages/d.html"
document.body.appendChild webview
it 'loads node symbols after POST navigation when set', (done) ->
webview.addEventListener 'console-message', (e) ->
assert.equal e.message, 'function object object'
done()
webview.setAttribute 'nodeintegration', 'on'
webview.src = "file://#{fixtures}/pages/post.html"
document.body.appendChild webview
# If the test is executed with the debug build on Windows, we will skip it
# because native modules don't work with the debug build (see issue #2558).
if process.platform isnt 'win32' or