Merge pull request #924 from atom/webview-ipc-message

Add ipc-message event for <webview>
This commit is contained in:
Cheng Zhao 2014-12-17 15:06:25 -08:00
commit 2fc1e2a4e6
8 changed files with 76 additions and 12 deletions

View file

@ -66,6 +66,10 @@ createGuest = (embedder, params) ->
guest.on event, (_, args...) ->
embedder.send "ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-#{guest.viewInstanceId}", event, args...
# Dispatch guest's IPC messages to embedder.
guest.on 'ipc-message-host', (_, channel, args...) ->
embedder.send "ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-#{guest.viewInstanceId}", channel, args...
# Autosize.
guest.on 'size-changed', (_, args...) ->
embedder.send "ATOM_SHELL_GUEST_VIEW_INTERNAL_SIZE_CHANGED-#{guest.viewInstanceId}", args...

View file

@ -16,6 +16,9 @@ class Ipc extends EventEmitter
sendSync: (args...) ->
JSON.parse ipc.sendSync('ipc-message-sync', [args...])
sendToHost: (args...) ->
ipc.send 'ipc-message-host', [args...]
# Discarded
sendChannel: -> @send.apply this, arguments
sendChannelSync: -> @sendSync.apply this, arguments

View file

@ -40,7 +40,7 @@ metaToValue = (meta) ->
constructor: ->
if @constructor == RemoteFunction
# Constructor call.
obj = ipc.sendChannelSync 'ATOM_BROWSER_CONSTRUCTOR', meta.id, wrapArgs(arguments)
obj = ipc.sendSync 'ATOM_BROWSER_CONSTRUCTOR', meta.id, wrapArgs(arguments)
# Returning object in constructor will replace constructed object
# with the returned object.
@ -48,7 +48,7 @@ metaToValue = (meta) ->
return metaToValue obj
else
# Function call.
ret = ipc.sendChannelSync 'ATOM_BROWSER_FUNCTION_CALL', meta.id, wrapArgs(arguments)
ret = ipc.sendSync 'ATOM_BROWSER_FUNCTION_CALL', meta.id, wrapArgs(arguments)
return metaToValue ret
else
ret = v8Util.createObjectWithName meta.name
@ -62,27 +62,27 @@ metaToValue = (meta) ->
constructor: ->
if @constructor is RemoteMemberFunction
# Constructor call.
obj = ipc.sendChannelSync 'ATOM_BROWSER_MEMBER_CONSTRUCTOR', meta.id, member.name, wrapArgs(arguments)
obj = ipc.sendSync 'ATOM_BROWSER_MEMBER_CONSTRUCTOR', meta.id, member.name, wrapArgs(arguments)
return metaToValue obj
else
# Call member function.
ret = ipc.sendChannelSync 'ATOM_BROWSER_MEMBER_CALL', meta.id, member.name, wrapArgs(arguments)
ret = ipc.sendSync 'ATOM_BROWSER_MEMBER_CALL', meta.id, member.name, wrapArgs(arguments)
return metaToValue ret
else
ret.__defineSetter__ member.name, (value) ->
# Set member data.
ipc.sendChannelSync 'ATOM_BROWSER_MEMBER_SET', meta.id, member.name, value
ipc.sendSync 'ATOM_BROWSER_MEMBER_SET', meta.id, member.name, value
value
ret.__defineGetter__ member.name, ->
# Get member data.
ret = ipc.sendChannelSync 'ATOM_BROWSER_MEMBER_GET', meta.id, member.name
ret = ipc.sendSync 'ATOM_BROWSER_MEMBER_GET', meta.id, member.name
metaToValue ret
# Track delegate object's life time, and tell the browser to clean up
# when the object is GCed.
v8Util.setDestructor ret, ->
ipc.sendChannel 'ATOM_BROWSER_DEREFERENCE', meta.storeId
ipc.send 'ATOM_BROWSER_DEREFERENCE', meta.storeId
# Remember object's id.
v8Util.setHiddenValue ret, 'atomId', meta.id
@ -104,19 +104,19 @@ moduleCache = {}
exports.require = (module) ->
return moduleCache[module] if moduleCache[module]?
meta = ipc.sendChannelSync 'ATOM_BROWSER_REQUIRE', module
meta = ipc.sendSync 'ATOM_BROWSER_REQUIRE', module
moduleCache[module] = metaToValue meta
# Get current window object.
windowCache = null
exports.getCurrentWindow = ->
return windowCache if windowCache?
meta = ipc.sendChannelSync 'ATOM_BROWSER_CURRENT_WINDOW', process.guestInstanceId
meta = ipc.sendSync 'ATOM_BROWSER_CURRENT_WINDOW', process.guestInstanceId
windowCache = metaToValue meta
# Get a global object in browser.
exports.getGlobal = (name) ->
meta = ipc.sendChannelSync 'ATOM_BROWSER_GLOBAL', name
meta = ipc.sendSync 'ATOM_BROWSER_GLOBAL', name
metaToValue meta
# Get the process object in browser.
@ -133,5 +133,5 @@ exports.createFunctionWithReturnValue = (returnValue) ->
# Get the guest WebContents from guestInstanceId.
exports.getGuestWebContents = (guestInstanceId) ->
meta = ipc.sendChannelSync 'ATOM_BROWSER_GUEST_WEB_CONTENTS', guestInstanceId
meta = ipc.sendSync 'ATOM_BROWSER_GUEST_WEB_CONTENTS', guestInstanceId
metaToValue meta

View file

@ -28,6 +28,12 @@ module.exports =
ipc.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-#{viewInstanceId}", (event, args...) ->
dispatchEvent webView, event, args...
ipc.on "ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-#{viewInstanceId}", (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...) ->
domEvent = new Event('size-changed')
for f, i in ['oldWidth', 'oldHeight', 'newWidth', 'newHeight']

View file

@ -20,3 +20,10 @@ the `channel` event of `ipc` module, and returns by setting `event.returnValue`.
**Note:** Usually developers should never use this API, since sending
synchronous message would block the whole web page.
## ipc.sendToHost(channel[, args...])
Like `ipc.send` but the message will be sent to the host page instead of the
browser process.
This is mainly used by the page in `<webview>` to communicate with host page.

View file

@ -295,7 +295,7 @@ webview.addEventListener('new-window', function(e) {
### close
Fired when the guest window attempts to close itself.
Fired when the guest page attempts to close itself.
The following example code navigates the `webview` to `about:blank` when the
guest attempts to close itself.
@ -306,6 +306,33 @@ webview.addEventListener('close', function() {
});
```
### ipc-message
* `channel` String
* `args` Array
Fired when the guest page has sent an asynchronous message to embedder page.
With `sendToHost` method and `ipc-message` event you can easily communicate
between guest page and embedder page:
```javascript
// In embedder page.
webview.addEventListener('ipc-message', function(event) {
console.log(event.channel);
// Prints "pong"
});
webview.send('ping');
```
```javascript
// In guest page.
var ipc = require('ipc');
ipc.on('ping', function() {
ipc.sendToHost('pong');
})
```
### crashed
Fired when the renderer process is crashed.

7
spec/fixtures/pages/ipc-message.html vendored Normal file
View file

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

View file

@ -86,3 +86,13 @@ describe '<webview> tag', ->
done()
webview.src = "file://#{fixtures}/pages/target-name.html"
document.body.appendChild webview
describe 'ipc-message event', ->
it 'emits when guest sends a ipc message to browser', (done) ->
webview.addEventListener 'ipc-message', (e) ->
assert.equal e.channel, 'channel'
assert.deepEqual e.args, ['arg1', 'arg2']
done()
webview.src = "file://#{fixtures}/pages/ipc-message.html"
webview.setAttribute 'nodeintegration', 'on'
document.body.appendChild webview