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

This commit is contained in:
Plusb Preco 2015-11-11 07:57:59 +09:00
commit 8774e7cf8d
53 changed files with 444 additions and 280 deletions

View file

@ -1,3 +1,4 @@
deprecate = require 'deprecate'
EventEmitter = require('events').EventEmitter
bindings = process.atomBinding 'app'
@ -7,19 +8,6 @@ downloadItemBindings = process.atomBinding 'download_item'
app = bindings.app
app.__proto__ = EventEmitter.prototype
wrapSession = (session) ->
# session is an Event Emitter.
session.__proto__ = EventEmitter.prototype
wrapDownloadItem = (downloadItem) ->
# downloadItem is an Event Emitter.
downloadItem.__proto__ = EventEmitter.prototype
# Be compatible with old APIs.
downloadItem.url = downloadItem.getUrl()
downloadItem.filename = downloadItem.getFilename()
downloadItem.mimeType = downloadItem.getMimeType()
downloadItem.hasUserGesture = downloadItem.hasUserGesture()
app.setApplicationMenu = (menu) ->
require('menu').setApplicationMenu menu
@ -47,17 +35,37 @@ app.setAppPath = (path) ->
app.getAppPath = ->
appPath
# Be compatible with old API.
app.once 'ready', -> @emit 'finish-launching'
app.terminate = app.quit
app.getHomeDir = -> @getPath 'home'
app.getDataPath = -> @getPath 'userData'
app.setDataPath = (path) -> @setPath 'userData', path
app.resolveProxy = -> @defaultSession.resolveProxy.apply @defaultSession, arguments
app.on 'activate', (event, hasVisibleWindows) -> @emit 'activate-with-no-open-windows' if not hasVisibleWindows
# Helpers.
app.resolveProxy = (url, callback) -> @defaultSession.resolveProxy url, callback
# Deprecated.
app.getHomeDir = deprecate 'app.getHomeDir', 'app.getPath', ->
@getPath 'home'
app.getDataPath = deprecate 'app.getDataPath', 'app.getPath', ->
@getPath 'userData'
app.setDataPath = deprecate 'app.setDataPath', 'app.setPath', (path) ->
@setPath 'userData', path
deprecate.rename app, 'terminate', 'quit'
deprecate.event app, 'finish-launching', 'ready', ->
setImmediate => # give default app a chance to setup default menu.
@emit 'finish-launching'
deprecate.event app, 'activate-with-no-open-windows', 'activate', (event, hasVisibleWindows) ->
@emit 'activate-with-no-open-windows' if not hasVisibleWindows
# Wrappers for native classes.
wrapSession = (session) ->
# session is an EventEmitter.
session.__proto__ = EventEmitter.prototype
sessionBindings._setWrapSession wrapSession
wrapDownloadItem = (downloadItem) ->
# downloadItem is an EventEmitter.
downloadItem.__proto__ = EventEmitter.prototype
# Deprecated.
deprecate.property downloadItem, 'url', 'getUrl'
deprecate.property downloadItem, 'filename', 'getFilename'
deprecate.property downloadItem, 'mimeType', 'getMimeType'
deprecate.property downloadItem, 'hasUserGesture', 'hasUserGesture'
downloadItemBindings._setWrapDownloadItem wrapDownloadItem
# Only one App object pemitted.

View file

@ -1,6 +0,0 @@
module.exports =
browserMainParts:
preMainMessageLoopRun: ->
setImmediate ->
module.exports.browserMainParts.preMainMessageLoopRun()

View file

@ -1,6 +1,7 @@
EventEmitter = require('events').EventEmitter
app = require 'app'
ipc = require 'ipc'
ipc = require 'ipc-main'
deprecate = require 'deprecate'
BrowserWindow = process.atomBinding('window').BrowserWindow
BrowserWindow::__proto__ = EventEmitter.prototype
@ -71,32 +72,32 @@ BrowserWindow.fromDevToolsWebContents = (webContents) ->
# Helpers.
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
BrowserWindow::reloadIgnoringCache = -> @webContents.reloadIgnoringCache.apply @webContents, arguments
BrowserWindow::getPageTitle = -> @webContents.getTitle()
BrowserWindow::isLoading = -> @webContents.isLoading()
BrowserWindow::isWaitingForResponse = -> @webContents.isWaitingForResponse()
BrowserWindow::stop = -> @webContents.stop()
BrowserWindow::isCrashed = -> @webContents.isCrashed()
BrowserWindow::executeJavaScriptInDevTools = (code) -> @devToolsWebContents?.executeJavaScript code
BrowserWindow::send = -> @webContents.send.apply @webContents, arguments
BrowserWindow::openDevTools = -> @webContents.openDevTools.apply @webContents, arguments
BrowserWindow::closeDevTools = -> @webContents.closeDevTools()
BrowserWindow::isDevToolsOpened = -> @webContents.isDevToolsOpened()
BrowserWindow::toggleDevTools = -> @webContents.toggleDevTools()
BrowserWindow::inspectElement = -> @webContents.inspectElement.apply @webContents, arguments
BrowserWindow::inspectServiceWorker = -> @webContents.inspectServiceWorker()
BrowserWindow::print = -> @webContents.print.apply @webContents, arguments
BrowserWindow::printToPDF = -> @webContents.printToPDF.apply @webContents, arguments
# Deprecated.
deprecate.rename BrowserWindow, 'restart', 'reload'
deprecate.member BrowserWindow, 'undo', 'webContents'
deprecate.member BrowserWindow, 'redo', 'webContents'
deprecate.member BrowserWindow, 'cut', 'webContents'
deprecate.member BrowserWindow, 'copy', 'webContents'
deprecate.member BrowserWindow, 'paste', 'webContents'
deprecate.member BrowserWindow, 'selectAll', 'webContents'
deprecate.member BrowserWindow, 'getUrl', 'webContents'
deprecate.member BrowserWindow, 'reloadIgnoringCache', 'webContents'
deprecate.member BrowserWindow, 'getPageTitle', 'webContents'
deprecate.member BrowserWindow, 'isLoading', 'webContents'
deprecate.member BrowserWindow, 'isWaitingForResponse', 'webContents'
deprecate.member BrowserWindow, 'stop', 'webContents'
deprecate.member BrowserWindow, 'isCrashed', 'webContents'
deprecate.member BrowserWindow, 'executeJavaScriptInDevTools', 'webContents'
deprecate.member BrowserWindow, 'print', 'webContents'
deprecate.member BrowserWindow, 'printToPDF', 'webContents'
module.exports = BrowserWindow

View file

@ -0,0 +1,3 @@
{EventEmitter} = require 'events'
module.exports = new EventEmitter

View file

@ -1,3 +1,6 @@
EventEmitter = require('events').EventEmitter
deprecate = require 'deprecate'
module.exports = new EventEmitter
# This module is deprecated, we mirror everything from ipcMain.
deprecate.warn 'ipc module', 'ipcMain module'
module.exports = require 'ipc-main'

View file

@ -1,4 +1,4 @@
ipc = require 'ipc'
ipc = require 'ipc-main'
# The history operation in renderer is redirected to browser.
ipc.on 'ATOM_SHELL_NAVIGATION_CONTROLLER', (event, method, args...) ->

View file

@ -2,7 +2,7 @@ EventEmitter = require('events').EventEmitter
Menu = require './menu'
NavigationController = require './navigation-controller'
binding = process.atomBinding 'web_contents'
ipc = require 'ipc'
ipc = require 'ipc-main'
nextId = 0
getNextId = -> ++nextId

View file

@ -55,7 +55,7 @@ app.once 'ready', ->
BrowserWindow = require 'browser-window'
# Load persistented extensions.
loadedExtensionsPath = path.join app.getDataPath(), 'DevTools Extensions'
loadedExtensionsPath = path.join app.getPath('userData'), 'DevTools Extensions'
try
loadedExtensions = JSON.parse fs.readFileSync(loadedExtensionsPath)

View file

@ -1,4 +1,4 @@
ipc = require 'ipc'
ipc = require 'ipc-main'
webContents = require 'web-contents'
webViewManager = null # Doesn't exist in early initialization.

View file

@ -1,4 +1,4 @@
ipc = require 'ipc'
ipc = require 'ipc-main'
v8Util = process.atomBinding 'v8_util'
BrowserWindow = require 'browser-window'

View file

@ -1,4 +1,4 @@
ipc = require 'ipc'
ipc = require 'ipc-main'
path = require 'path'
objectsRegistry = require './objects-registry.js'
v8Util = process.atomBinding 'v8_util'

View file

@ -69,9 +69,6 @@ void AtomBindings::BindTo(v8::Isolate* isolate,
dict.SetMethod("activateUvLoop",
base::Bind(&AtomBindings::ActivateUVLoop, base::Unretained(this)));
// Do not warn about deprecated APIs.
dict.Set("noDeprecation", true);
#if defined(MAS_BUILD)
dict.Set("mas", true);
#endif

View file

@ -0,0 +1,62 @@
# Deprecate a method.
deprecate = (oldName, newName, fn) ->
warned = false
->
unless warned or process.noDeprecation
warned = true
deprecate.warn oldName, newName
fn.apply this, arguments
# The method is renamed.
deprecate.rename = (object, oldName, newName) ->
warned = false
newMethod = ->
unless warned or process.noDeprecation
warned = true
deprecate.warn oldName, newName
this[newName].apply this, arguments
if typeof object is 'function'
object.prototype[oldName] = newMethod
else
object[oldName] = newMethod
# Forward the method to member.
deprecate.member = (object, method, member) ->
warned = false
object.prototype[method] = ->
unless warned or process.noDeprecation
warned = true
deprecate.warn method, "#{member}.#{method}"
this[member][method].apply this[member], arguments
# Deprecate a property.
deprecate.property = (object, property, method) ->
Object.defineProperty object, property,
get: ->
warned = false
unless warned or process.noDeprecation
warned = true
deprecate.warn "#{property} property", "#{method} method"
this[method]()
# Deprecate an event.
deprecate.event = (emitter, oldName, newName, fn) ->
warned = false
emitter.on newName, ->
if @listenerCount(oldName) > 0 # there is listeners for old API.
unless warned or process.noDeprecation
warned = true
deprecate.warn "'#{oldName}' event", "'#{newName}' event"
fn.apply this, arguments
# Print deprecate warning.
deprecate.warn = (oldName, newName) ->
message = "#{oldName} is deprecated. Use #{newName} instead."
if process.throwDeprecation
throw new Error(message)
else if process.traceDeprecation
console.trace message
else
console.warn "(electron) #{message}"
module.exports = deprecate

View file

@ -0,0 +1,16 @@
binding = process.atomBinding 'ipc'
v8Util = process.atomBinding 'v8_util'
# Created by init.coffee.
ipcRenderer = v8Util.getHiddenValue global, 'ipc'
ipcRenderer.send = (args...) ->
binding.send 'ipc-message', [args...]
ipcRenderer.sendSync = (args...) ->
JSON.parse binding.sendSync('ipc-message-sync', [args...])
ipcRenderer.sendToHost = (args...) ->
binding.send 'ipc-message-host', [args...]
module.exports = ipcRenderer

View file

@ -1,20 +1,20 @@
binding = process.atomBinding 'ipc'
v8Util = process.atomBinding 'v8_util'
deprecate = require 'deprecate'
ipcRenderer = require 'ipc-renderer'
{EventEmitter} = require 'events'
# Created by init.coffee.
ipc = v8Util.getHiddenValue global, 'ipc'
# This module is deprecated, we mirror everything from ipcRenderer.
deprecate.warn 'ipc module', 'ipcRenderer module'
ipc.send = (args...) ->
binding.send 'ipc-message', [args...]
ipc.sendSync = (args...) ->
JSON.parse binding.sendSync('ipc-message-sync', [args...])
ipc.sendToHost = (args...) ->
binding.send 'ipc-message-host', [args...]
# Routes events of ipcRenderer.
ipc = new EventEmitter
ipcRenderer.emit = (channel, event, args...) ->
ipc.emit channel, args...
EventEmitter::emit.apply ipcRenderer, arguments
# Deprecated.
ipc.sendChannel = ipc.send
ipc.sendChannelSync = ipc.sendSync
for method of ipcRenderer when method.startsWith 'send'
ipc[method] = ipcRenderer[method]
deprecate.rename ipc, 'sendChannel', 'send'
deprecate.rename ipc, 'sendChannelSync', 'sendSync'
module.exports = ipc

View file

@ -1,4 +1,4 @@
ipc = require 'ipc'
ipc = require 'ipc-renderer'
v8Util = process.atomBinding 'v8_util'
CallbacksRegistry = require 'callbacks-registry'
@ -119,11 +119,11 @@ metaToPlainObject = (meta) ->
obj
# Browser calls a callback in renderer.
ipc.on 'ATOM_RENDERER_CALLBACK', (id, args) ->
ipc.on 'ATOM_RENDERER_CALLBACK', (event, id, args) ->
callbacksRegistry.apply id, metaToValue(args)
# A callback in browser is released.
ipc.on 'ATOM_RENDERER_RELEASE_CALLBACK', (id) ->
ipc.on 'ATOM_RENDERER_RELEASE_CALLBACK', (event, id) ->
callbacksRegistry.remove id
# Get remote module.

View file

@ -31,6 +31,7 @@
#include "third_party/WebKit/public/web/WebScriptSource.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "ui/base/resource/resource_bundle.h"
#include "native_mate/dictionary.h"
namespace atom {
@ -142,7 +143,12 @@ void AtomRenderViewObserver::OnBrowserMessage(const base::string16& channel,
v8::Local<v8::Object> ipc;
if (GetIPCObject(isolate, context, &ipc)) {
mate::EmitEvent(isolate, ipc, channel, ListValueToVector(isolate, args));
auto args_vector = ListValueToVector(isolate, args);
// Insert the Event object, event.sender is ipc.
mate::Dictionary event = mate::Dictionary::CreateEmpty(isolate);
event.Set("sender", ipc);
args_vector.insert(args_vector.begin(), event.GetHandle());
mate::EmitEvent(isolate, ipc, channel, args_vector);
}
}

View file

@ -1,4 +1,4 @@
ipc = require 'ipc'
ipc = require 'ipc-renderer'
remote = require 'remote'
# Helper function to resolve relative url.
@ -11,7 +11,7 @@ resolveUrl = (url) ->
class BrowserWindowProxy
constructor: (@guestId) ->
@closed = false
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED', (guestId) =>
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED', (event, guestId) =>
if guestId is @guestId
@closed = true
@ -99,7 +99,7 @@ if guestId?
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', (guestId, message, sourceOrigin) ->
ipc.on 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', (event, guestId, message, sourceOrigin) ->
# Manually dispatch event instead of using postMessage because we also need to
# set event.source.
event = document.createEvent 'Event'

View file

@ -1,4 +1,4 @@
ipc = require 'ipc'
ipc = require 'ipc-renderer'
webFrame = require 'web-frame'
requestId = 0
@ -37,16 +37,16 @@ dispatchEvent = (webView, event, args...) ->
module.exports =
registerEvents: (webView, viewInstanceId) ->
ipc.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-#{viewInstanceId}", (event, args...) ->
dispatchEvent webView, event, args...
ipc.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-#{viewInstanceId}", (event, domEvent, args...) ->
dispatchEvent webView, domEvent, args...
ipc.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-#{viewInstanceId}", (channel, args...) ->
ipc.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-#{viewInstanceId}", (event, channel, args...) ->
domEvent = new Event('ipc-message')
domEvent.channel = channel
domEvent.args = [args...]
webView.dispatchEvent domEvent
ipc.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_SIZE_CHANGED-#{viewInstanceId}", (args...) ->
ipc.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_SIZE_CHANGED-#{viewInstanceId}", (event, args...) ->
domEvent = new Event('size-changed')
for f, i in ['oldWidth', 'oldHeight', 'newWidth', 'newHeight']
domEvent[f] = args[i]

View file

@ -135,7 +135,7 @@ class WebViewImpl
guestViewInternal.setSize @guestInstanceId, normal: newSize
createGuest: ->
guestViewInternal.createGuest @buildParams(), (guestInstanceId) =>
guestViewInternal.createGuest @buildParams(), (event, guestInstanceId) =>
@attachWindow guestInstanceId
dispatchEvent: (webViewEvent) ->

View file

@ -36,7 +36,7 @@
* [content-tracing](api/content-tracing.md)
* [dialog](api/dialog.md)
* [global-shortcut](api/global-shortcut.md)
* [ipc (main process)](api/ipc-main-process.md)
* [ipc-main](api/ipc-main.md)
* [menu](api/menu.md)
* [menu-item](api/menu-item.md)
* [power-monitor](api/power-monitor.md)
@ -48,7 +48,7 @@
### Modules for the Renderer Process (Web Page):
* [ipc (renderer)](api/ipc-renderer.md)
* [ipc-renderer](api/ipc-renderer.md)
* [remote](api/remote.md)
* [web-frame](api/web-frame.md)

View file

@ -1,76 +0,0 @@
# ipc (main process)
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.
## Sending Messages
It is also possible to send messages from the main process to the renderer
process, see [WebContents.send](web-contents.md#webcontentssendchannel-args)
for more information.
- 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.
var ipc = require('ipc');
ipc.on('asynchronous-message', function(event, arg) {
console.log(arg); // prints "ping"
event.sender.send('asynchronous-reply', 'pong');
});
ipc.on('synchronous-message', function(event, arg) {
console.log(arg); // prints "ping"
event.returnValue = 'pong';
});
```
```javascript
// In renderer process (web page).
var ipc = require('ipc');
console.log(ipc.sendSync('synchronous-message', 'ping')); // prints "pong"
ipc.on('asynchronous-reply', function(arg) {
console.log(arg); // prints "pong"
});
ipc.send('asynchronous-message', 'ping');
```
## Listening for Messages
The `ipc` module has the following method to listen for events:
### `ipc.on(channel, callback)`
* `channel` String - The event name.
* `callback` Function
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.

71
docs/api/ipc-main.md Normal file
View file

@ -0,0 +1,71 @@
# ipcMain
The `ipcMain` 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.
## Sending Messages
It is also possible to send messages from the main process to the renderer
process, see [WebContents.send][webcontents-send] for more information.
* 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.
var ipcMain = require('ipc-main');
ipcMain.on('asynchronous-message', function(event, arg) {
console.log(arg); // prints "ping"
event.sender.send('asynchronous-reply', 'pong');
});
ipcMain.on('synchronous-message', function(event, arg) {
console.log(arg); // prints "ping"
event.returnValue = 'pong';
});
```
```javascript
// In renderer process (web page).
var ipcRenderer = require('ipc-renderer');
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')); // prints "pong"
ipcRenderer.on('asynchronous-reply', function(event, arg) {
console.log(arg); // prints "pong"
});
ipcRenderer.send('asynchronous-message', 'ping');
```
## Listening for Messages
The `ipcMain` module has the following method to listen for events:
### `ipcMain.on(channel, callback)`
* `channel` String - The event name.
* `callback` Function
When the event occurs the `callback` is called with an `event` object and a
message, `arg`.
## IPC Event
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, you can call
`event.sender.send` to reply to the asynchronous message, see
[WebContents.send][webcontents-send] for more information.
[webcontents-send]: web-contents.md#webcontentssendchannel-args

View file

@ -1,52 +1,55 @@
# ipc (renderer)
# ipcRenderer
The `ipc` module provides a few methods so you can send synchronous and
The `ipcRenderer` module provides a few methods so you can send synchronous and
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 [ipcMain](ipc-main.md) for code examples.
See [ipc (main process)](ipc-main-process.md) for code examples.
## Listening for Messages
## Methods
The `ipcRenderer` module has the following method to listen for events:
The `ipc` module has the following methods for sending messages:
### `ipcRenderer.on(channel, callback)`
**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).
* `channel` String - The event name.
* `callback` Function
### `ipc.send(channel[, arg1][, arg2][, ...])`
When the event occurs the `callback` is called with an `event` object and
arbitrary arguments.
## Sending Messages
The `ipcRenderer` module has the following methods for sending messages:
### `ipcRenderer.send(channel[, arg1][, arg2][, ...])`
* `channel` String - The event name.
* `arg` (optional)
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`.
Send an event to the main process asynchronously via a `channel`, you can also
send arbitrary arguments. The main process handles it by listening for the
`channel` event with `ipcMain`.
### `ipc.sendSync(channel[, arg1][, arg2][, ...])`
### `ipcRenderer.sendSync(channel[, arg1][, arg2][, ...])`
* `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`.
Send an event to the main process synchronously via a `channel`, you can also
send arbitrary arguments. The main process handles it by listening for the
`channel` event with `ipcMain`.
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.
__Note:__ Sending a synchronous message will block the whole renderer process,
unless you know what you are doing you should never use it.
### `ipc.sendToHost(channel[, arg1][, arg2][, ...])`
### `ipcRenderer.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.
Like `ipcRenderer.send` but the event will be sent to the `<webview>` element in
the host page instead of the main process.

View file

@ -510,13 +510,14 @@ Starts inspecting element at position (`x`, `y`).
Opens the developer tools for the service worker context.
### `webContents.send(channel[, args...])`
### `webContents.send(channel[, arg1][, arg2][, ...])`
* `channel` String
* `args...` (optional)
* `arg` (optional)
Send `args...` to the web page via `channel` in an asynchronous message, the web
page can handle it by listening to the `channel` event of the `ipc` module.
Send an asynchronous message to renderer process via `channel`, you can also
send arbitrary arguments. The renderer process can handle the message by
listening to the `channel` event with the `ipcRenderer` module.
An example of sending messages from the main process to the renderer process:
@ -537,7 +538,7 @@ app.on('ready', function() {
<html>
<body>
<script>
require('ipc').on('ping', function(message) {
require('ipcRenderer').on('ping', function(event, message) {
console.log(message); // Prints "whoooooooh!"
});
</script>
@ -545,13 +546,6 @@ app.on('ready', function() {
</html>
```
**Note:**
1. The IPC message handler in web pages does not have an `event` parameter,
which is different from the handlers in the main process.
2. There is no way to send synchronous messages from the main process to a
renderer process, because it would be very easy to cause dead locks.
### `webContents.enableDeviceEmulation(parameters)`
`parameters` Object, properties:

View file

@ -355,15 +355,16 @@ Prints `webview`'s web page. Same with `webContents.print([options])`.
Prints webview's web page as PDF, Same with `webContents.printToPDF(options, callback)`
### `<webview>.send(channel[, args...])`
### `<webview>.send(channel[, arg1][, arg2][, ...])`
* `channel` String
* `arg` (optional)
Send `args..` to guest page via `channel` in asynchronous message, the guest
page can handle it by listening to the `channel` event of `ipc` module.
Send an asynchronous message to renderer process via `channel`, you can also
send arbitrary arguments. The renderer process can handle the message by
listening to the `channel` event with the `ipcRenderer` module.
See [WebContents.send](web-contents.md#webcontentssendchannel-args) for
See [webContents.send](web-contents.md#webcontentssendchannel-args) for
examples.
### `<webview>.sendInputEvent(event)`
@ -372,7 +373,7 @@ examples.
Sends an input `event` to the page.
See [WebContents.sendInputEvent](web-contents.md##webcontentssendinputeventevent)
See [webContents.sendInputEvent](web-contents.md##webcontentssendinputeventevent)
for detailed description of `event` object.
## DOM events

View file

@ -8,6 +8,67 @@ applications can put a custom menu in the dock menu.
This guide explains how to integrate your application into those desktop
environments with Electron APIs.
## Notifications (Windows, Linux, OS X)
All three operating systems provide means for applications to send notifications
to the user. Electron conveniently allows developers to send notifications with
the [HTML5 Notification API](https://notifications.spec.whatwg.org/), using
the currently running operating system's native notification APIs to display it.
```javascript
var myNotificiation = new Notification('Title', {
body: 'Lorem Ipsum Dolor Sit Amet'
});
myNotification.onclick = function () {
console.log('Notification clicked')
}
```
While code and user experience across operating systems are similar, but there
are fine differences.
### Windows
* On Windows 10, notifications "just work".
* On Windows 8.1 and Windows 8, a shortcut to your app, with a [Application User
Model ID][app-user-model-id], must be installed to the Start screen. Note,
however, that it does not need to be pinned to the Start screen.
* On Windows 7 and below, notifications are not supported. You can however send
"balloon notifications" using the [Tray API](tray-balloon).
To use an image in your notification, pass a local image file (preferably `png`)
in the `icon` property of your notification's options. The notification will
still display if you submit and incorrect or `http/https`-based URL, but the
image will not be displayed.
```javascript
new Notification('Title', {
body: 'Notification with icon',
icon: 'file:///C:/Users/feriese/Desktop/icon.png'
});
```
Keep furthermore in mind that the maximum length for the body is 250 characters,
with the Windows team recommending that notifications should be kept to 200
characters.
### Linux
Notifications are sent using `libnotify`, it can show notifications on any
desktop environment that follows [Desktop Notifications
Specification][notification-spec], including Cinnamon, Enlightenment, Unity,
GNOME, KDE.
### OS X
Notifications are straight-forward on OS X, you should however be aware of
[Apple's Human Interface guidelines regarding
notifications](https://developer.apple.com/library/mac/documentation/UserExperience/Conceptual/OSXHIGuidelines/NotificationCenter.html).
Note that notifications are limited to 256 bytes in size - and will be truncated
if you exceed that limit.
## Recent documents (Windows & OS X)
Windows and OS X provide easy access to a list of recent documents opened by
@ -43,7 +104,8 @@ registered as a handler of the file type of the document, otherwise the file
won't appear in JumpList even after you have added it. You can find everything
on registering your application in [Application Registration][app-registration].
When a user clicks a file from the JumpList, a new instance of your application will be started with the path of the file added as a command line argument.
When a user clicks a file from the JumpList, a new instance of your application
will be started with the path of the file added as a command line argument.
### OS X Notes
@ -154,10 +216,10 @@ __Thumbnail toolbar of Windows Media Player:__
![player](https://i-msdn.sec.s-msft.com/dynimg/IC420540.png)
You can use [BrowserWindow.setThumbarButtons][setthumbarbuttons] to set thumbnail
toolbar in your application:
You can use [BrowserWindow.setThumbarButtons][setthumbarbuttons] to set
thumbnail toolbar in your application:
```
```javascript
var BrowserWindow = require('browser-window');
var path = require('path');
var win = new BrowserWindow({
@ -188,8 +250,8 @@ win.setThumbarButtons([]);
## Unity Launcher Shortcuts (Linux)
In Unity, you can add custom entries to its launcher via modifying the `.desktop`
file, see [Adding Shortcuts to a Launcher][unity-launcher].
In Unity, you can add custom entries to its launcher via modifying the
`.desktop` file, see [Adding Shortcuts to a Launcher][unity-launcher].
__Launcher shortcuts of Audacious:__
@ -252,3 +314,6 @@ window.setDocumentEdited(true);
[app-registration]: http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121(v=vs.85).aspx
[unity-launcher]: https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles#Adding_shortcuts_to_a_launcher
[setthumbarbuttons]: ../api/browser-window.md#browserwindowsetthumbarbuttonsbuttons
[tray-balloon]: ../api/tray.md#traydisplayballoonoptions-windows
[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx
[notification-spec]: https://developer.gnome.org/notification-spec/

View file

@ -77,10 +77,10 @@ codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP
codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper EH.app/"
codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper NP.app/"
codesign -fs "$APP_KEY" --entitlements parent.plist "$APP_PATH"
productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$APP_PATH"
productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$RESULT_PATH"
```
If you are new to app sandboxing under OS X, you should also read through
If you are new to app sandboxing under OS X, you should also read through
Apple's [Enabling App Sandbox][enable-app-sandbox] to have a basic idea, then
add keys for the permissions needed by your app to the entitlements files.

View file

@ -21,18 +21,18 @@ _online-status.html_
```html
<!DOCTYPE html>
<html>
<body>
<script>
var alertOnlineStatus = function() {
window.alert(navigator.onLine ? 'online' : 'offline');
};
<body>
<script>
var alertOnlineStatus = function() {
window.alert(navigator.onLine ? 'online' : 'offline');
};
window.addEventListener('online', alertOnlineStatus);
window.addEventListener('offline', alertOnlineStatus);
window.addEventListener('online', alertOnlineStatus);
window.addEventListener('offline', alertOnlineStatus);
alertOnlineStatus();
</script>
</body>
alertOnlineStatus();
</script>
</body>
</html>
```
@ -46,7 +46,7 @@ _main.js_
```javascript
var app = require('app');
var ipc = require('ipc');
var ipcMain = require('ipc-main');
var BrowserWindow = require('browser-window');
var onlineStatusWindow;
@ -55,7 +55,7 @@ app.on('ready', function() {
onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html');
});
ipc.on('online-status-changed', function(event, status) {
ipcMain.on('online-status-changed', function(event, status) {
console.log(status);
});
```
@ -65,18 +65,18 @@ _online-status.html_
```html
<!DOCTYPE html>
<html>
<body>
<script>
var ipc = require('ipc');
var updateOnlineStatus = function() {
ipc.send('online-status-changed', navigator.onLine ? 'online' : 'offline');
};
<body>
<script>
var ipcRenderer = require('ipc-renderer');
var updateOnlineStatus = function() {
ipcRenderer.send('online-status-changed', navigator.onLine ? 'online' : 'offline');
};
window.addEventListener('online', updateOnlineStatus);
window.addEventListener('offline', updateOnlineStatus);
window.addEventListener('online', updateOnlineStatus);
window.addEventListener('offline', updateOnlineStatus);
updateOnlineStatus();
</script>
</body>
updateOnlineStatus();
</script>
</body>
</html>
```

View file

@ -9,7 +9,6 @@
],
'coffee_sources': [
'atom/browser/api/lib/app.coffee',
'atom/browser/api/lib/atom-delegate.coffee',
'atom/browser/api/lib/auto-updater.coffee',
'atom/browser/api/lib/auto-updater/auto-updater-mac.coffee',
'atom/browser/api/lib/auto-updater/auto-updater-win.coffee',
@ -19,6 +18,7 @@
'atom/browser/api/lib/dialog.coffee',
'atom/browser/api/lib/global-shortcut.coffee',
'atom/browser/api/lib/ipc.coffee',
'atom/browser/api/lib/ipc-main.coffee',
'atom/browser/api/lib/menu.coffee',
'atom/browser/api/lib/menu-item.coffee',
'atom/browser/api/lib/navigation-controller.coffee',
@ -37,6 +37,7 @@
'atom/common/api/lib/callbacks-registry.coffee',
'atom/common/api/lib/clipboard.coffee',
'atom/common/api/lib/crash-reporter.coffee',
'atom/common/api/lib/deprecate.coffee',
'atom/common/api/lib/native-image.coffee',
'atom/common/api/lib/shell.coffee',
'atom/common/lib/init.coffee',
@ -50,6 +51,7 @@
'atom/renderer/lib/web-view/web-view-attributes.coffee',
'atom/renderer/lib/web-view/web-view-constants.coffee',
'atom/renderer/api/lib/ipc.coffee',
'atom/renderer/api/lib/ipc-renderer.coffee',
'atom/renderer/api/lib/remote.coffee',
'atom/renderer/api/lib/screen.coffee',
'atom/renderer/api/lib/web-frame.coffee',

View file

@ -39,7 +39,9 @@ def main():
update_submodules()
setup_python_libs()
update_node_modules('.')
bootstrap_brightray(args.dev, args.url, args.target_arch)
bootstrap_brightray(args.dev, args.url, args.target_arch,
args.libcc_source_path, args.libcc_shared_library_path,
args.libcc_static_library_path)
if args.target_arch in ['arm', 'ia32'] and PLATFORM == 'linux':
download_sysroot(args.target_arch)
@ -69,6 +71,14 @@ def parse_args():
'prompts.')
parser.add_argument('--target_arch', default=get_target_arch(),
help='Manually specify the arch to build for')
parser.add_argument('--libcc_source_path', required=False,
help='The source path of libchromiumcontent. ' \
'NOTE: All options of libchromiumcontent are ' \
'required OR let electron choose it')
parser.add_argument('--libcc_shared_library_path', required=False,
help='The shared library path of libchromiumcontent.')
parser.add_argument('--libcc_static_library_path', required=False,
help='The static library path of libchromiumcontent.')
return parser.parse_args()
@ -91,15 +101,23 @@ def setup_python_libs():
execute_stdout([sys.executable, 'setup.py', 'build'])
def bootstrap_brightray(is_dev, url, target_arch):
def bootstrap_brightray(is_dev, url, target_arch, libcc_source_path,
libcc_shared_library_path,
libcc_static_library_path):
bootstrap = os.path.join(VENDOR_DIR, 'brightray', 'script', 'bootstrap')
args = [
'--commit', LIBCHROMIUMCONTENT_COMMIT,
'--target_arch', target_arch,
url,
url
]
if is_dev:
args = ['--dev'] + args
if (libcc_source_path != None and
libcc_shared_library_path != None and
libcc_static_library_path != None):
args += ['--libcc_source_path', libcc_source_path,
'--libcc_shared_library_path', libcc_shared_library_path,
'--libcc_static_library_path', libcc_static_library_path]
execute_stdout([sys.executable, bootstrap] + args)

View file

@ -201,12 +201,12 @@ describe 'browser-window module', ->
describe '"web-preferences" option', ->
afterEach ->
remote.require('ipc').removeAllListeners('answer')
remote.require('ipc-main').removeAllListeners('answer')
describe '"preload" option', ->
it 'loads the script before other scripts in window', (done) ->
preload = path.join fixtures, 'module', 'set-global.js'
remote.require('ipc').once 'answer', (event, test) ->
remote.require('ipc-main').once 'answer', (event, test) ->
assert.equal(test, 'preload')
done()
w.destroy()
@ -219,7 +219,7 @@ describe 'browser-window module', ->
describe '"node-integration" option', ->
it 'disables node integration when specified to false', (done) ->
preload = path.join fixtures, 'module', 'send-later.js'
remote.require('ipc').once 'answer', (event, test) ->
remote.require('ipc-main').once 'answer', (event, test) ->
assert.equal(test, 'undefined')
done()
w.destroy()

View file

@ -3,7 +3,7 @@ path = require 'path'
http = require 'http'
url = require 'url'
remote = require 'remote'
formidable = require 'formidable'
multiparty = require 'multiparty'
crashReporter = remote.require 'crash-reporter'
BrowserWindow = remote.require 'browser-window'
@ -26,10 +26,8 @@ describe 'crash-reporter module', ->
@timeout 120000
server = http.createServer (req, res) ->
server.close()
form = new formidable.IncomingForm()
process.throwDeprecation = false
form = new multiparty.Form()
form.parse req, (error, fields, files) ->
process.throwDeprecation = true
assert.equal fields['prod'], 'Electron'
assert.equal fields['ver'], process.versions['electron']
assert.equal fields['process_type'], 'renderer'
@ -39,7 +37,6 @@ describe 'crash-reporter module', ->
assert.equal fields['_productName'], 'Zombies'
assert.equal fields['_companyName'], 'Umbrella Corporation'
assert.equal fields['_version'], require('remote').require('app').getVersion()
assert files['upload_file_minidump']['name']?
res.end('abc-123-def')
done()

View file

@ -1,5 +1,5 @@
assert = require 'assert'
ipc = require 'ipc'
ipc = require 'ipc-renderer'
path = require 'path'
remote = require 'remote'
@ -70,7 +70,7 @@ describe 'ipc module', ->
describe 'ipc.sender.send', ->
it 'should work when sending an object containing id property', (done) ->
obj = id: 1, name: 'ly'
ipc.once 'message', (message) ->
ipc.once 'message', (event, message) ->
assert.deepEqual message, obj
done()
ipc.send 'message', obj
@ -83,7 +83,7 @@ describe 'ipc module', ->
it 'does not crash when reply is not sent and browser is destroyed', (done) ->
@timeout 10000
w = new BrowserWindow(show: false)
remote.require('ipc').once 'send-sync-message', (event) ->
remote.require('ipc-main').once 'send-sync-message', (event) ->
event.returnValue = null
w.destroy()
done()

View file

@ -60,9 +60,9 @@ describe 'session module', ->
describe 'session.clearStorageData(options)', ->
fixtures = path.resolve __dirname, 'fixtures'
it 'clears localstorage data', (done) ->
ipc = remote.require('ipc')
ipc.on 'count', (event, count) ->
ipc.removeAllListeners 'count'
ipcMain = remote.require('ipc-main')
ipcMain.on 'count', (event, count) ->
ipcMain.removeAllListeners 'count'
assert not count
done()
w.loadUrl 'file://' + path.join(fixtures, 'api', 'localstorage.html')
@ -78,7 +78,7 @@ describe 'session module', ->
# A 5 MB mock pdf.
mockPDF = new Buffer 1024 * 1024 * 5
contentDisposition = 'inline; filename="mock.pdf"'
ipc = require 'ipc'
ipc = require 'ipc-renderer'
downloadFilePath = path.join fixtures, 'mock.pdf'
downloadServer = http.createServer (req, res) ->
res.writeHead 200, {
@ -94,8 +94,7 @@ describe 'session module', ->
{port} = downloadServer.address()
ipc.sendSync 'set-download-option', false
w.loadUrl "#{url}:#{port}"
ipc.once 'download-done', (state, url, mimeType, receivedBytes,
totalBytes, disposition, filename) ->
ipc.once 'download-done', (event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) ->
assert.equal state, 'completed'
assert.equal filename, 'mock.pdf'
assert.equal url, "http://127.0.0.1:#{port}/"
@ -112,8 +111,7 @@ describe 'session module', ->
{port} = downloadServer.address()
ipc.sendSync 'set-download-option', true
w.loadUrl "#{url}:#{port}/"
ipc.once 'download-done', (state, url, mimeType, receivedBytes,
totalBytes, disposition, filename) ->
ipc.once 'download-done', (event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) ->
assert.equal state, 'cancelled'
assert.equal filename, 'mock.pdf'
assert.equal mimeType, 'application/pdf'

View file

@ -407,7 +407,7 @@ describe 'asar package', ->
describe 'asar protocol', ->
url = require 'url'
remote = require 'remote'
ipc = remote.require 'ipc'
ipc = remote.require 'ipc-main'
BrowserWindow = remote.require 'browser-window'
it 'can request a file in package', (done) ->

View file

@ -2,7 +2,7 @@
<body>
<script type="text/javascript" charset="utf-8">
window.localStorage.setItem('test', 'test');
var ipc = require('ipc');
var ipc = require('ipc-renderer');
ipc.on('getcount', function() {
ipc.send('count', window.localStorage.length);
})

View file

@ -3,7 +3,7 @@
<script type="text/javascript" charset="utf-8">
if (!window.test)
window.test = 'window'
require('ipc').send('answer', window.test);
require('ipc-renderer').send('answer', window.test);
</script>
</body>
</html>

View file

@ -1,7 +1,7 @@
<html>
<body>
<script type="text/javascript" charset="utf-8">
var ipc = require('ipc');
var ipc = require('ipc-renderer');
ipc.sendSync('send-sync-message', 'message');
</script>
</body>

View file

@ -1,4 +1,4 @@
var ipc = require('ipc');
ipc.on('ping', function(message) {
var ipc = require('ipc-renderer');
ipc.on('ping', function(event, message) {
ipc.sendToHost('pong', message);
});

View file

@ -1,4 +1,4 @@
var ipc = require('ipc');
var ipc = require('ipc-renderer');
window.onload = function() {
ipc.send('answer', typeof window.process);
}

View file

@ -2,7 +2,7 @@
<body>
<script src="../../static/jquery-2.0.3.min.js"></script>
<script type="text/javascript" charset="utf-8">
var ipc = require('ipc');
var ipc = require('ipc-renderer');
var port = location.search.substr("?port=".length);
$.ajax({
type: "GET",

View file

@ -3,7 +3,7 @@
<script type="text/javascript" charset="utf-8">
window.onbeforeunload = function() {
setTimeout(function() {
var ipc = require('ipc');
var ipc = require('ipc-renderer');
ipc.sendToHost('onbeforeunload');
}, 0);
return false;

View file

@ -1,7 +1,7 @@
<html>
<body>
<script type="text/javascript" charset="utf-8">
require('ipc').send('hidden', document.hidden);
require('ipc-renderer').send('hidden', document.hidden);
</script>
</body>
</html>

View file

@ -2,7 +2,7 @@
<body>
<script type="text/javascript" charset="utf-8">
window.history.pushState(window.history.state, "test page", "foo.html")
require('ipc').sendToHost('history', window.history.length);
require('ipc-renderer').sendToHost('history', window.history.length);
</script>
</body>
</html>

View file

@ -1,7 +1,7 @@
<html>
<body>
<script type="text/javascript" charset="utf-8">
require('ipc').sendToHost('channel', 'arg1', 'arg2');
require('ipc-renderer').sendToHost('channel', 'arg1', 'arg2');
</script>
</body>
</html>

View file

@ -2,7 +2,7 @@
<body>
<script type="text/javascript" charset="utf-8">
document.onkeyup = function(e) {
require('ipc').sendToHost('keyup', e.keyCode, e.shiftKey, e.ctrlKey);
require('ipc-renderer').sendToHost('keyup', e.keyCode, e.shiftKey, e.ctrlKey);
}
</script>
</body>

View file

@ -2,7 +2,7 @@
<body>
<script type="text/javascript" charset="utf-8">
document.onmouseup = function(e) {
require('ipc').sendToHost('mouseup', e.x, e.y, e.shiftKey, e.ctrlKey);
require('ipc-renderer').sendToHost('mouseup', e.x, e.y, e.shiftKey, e.ctrlKey);
}
</script>
</body>

View file

@ -4,7 +4,7 @@
if (window.opener !== null)
window.opener.postMessage(typeof window.opener, '*');
else
require('ipc').send('opener', window.opener);
require('ipc-renderer').send('opener', window.opener);
</script>
</body>
</html>

View file

@ -5,7 +5,7 @@
"version": "0.1.0",
"devDependencies": {
"basic-auth": "^1.0.0",
"formidable": "1.0.16",
"multiparty": "4.1.2",
"graceful-fs": "3.0.5",
"mocha": "2.1.0",
"q": "0.9.7",

View file

@ -29,7 +29,7 @@
}
require('coffee-script/register'); // Supports .coffee tests.
var ipc = require('ipc');
var ipc = require('ipc-renderer');
// Rediret all output to browser.
if (isCi) {

View file

@ -1,5 +1,5 @@
var app = require('app');
var ipc = require('ipc');
var ipc = require('ipc-main');
var dialog = require('dialog');
var path = require('path');
var BrowserWindow = require('browser-window');
@ -9,6 +9,7 @@ process.port = 0; // will be used by crash-reporter spec.
app.commandLine.appendSwitch('js-flags', '--expose_gc');
app.commandLine.appendSwitch('ignore-certificate-errors');
app.commandLine.appendSwitch('disable-renderer-backgrounding');
// Accessing stdout in the main process will result in the process.stdout
// throwing UnknownSystemError in renderer process sometimes. This line makes
@ -78,7 +79,7 @@ app.on('ready', function() {
// For session's download test, listen 'will-download' event in browser, and
// reply the result to renderer for verifying
var downloadFilePath = path.join(__dirname, '..', 'fixtures', 'mock.pdf');
require('ipc').on('set-download-option', function(event, need_cancel) {
ipc.on('set-download-option', function(event, need_cancel) {
window.webContents.session.once('will-download',
function(e, item, webContents) {
item.setSavePath(downloadFilePath);

2
vendor/brightray vendored

@ -1 +1 @@
Subproject commit 98b3eb04d85a8a70b8d9f29477437061c2e77a83
Subproject commit 4e069f1806efe5da9a965e61f329b19b7791104a