electron/atom/browser/lib/guest-view-manager.coffee

165 lines
5.3 KiB
CoffeeScript
Raw Normal View History

{ipcMain, webContents} = require 'electron'
2014-10-23 15:08:48 +00:00
webViewManager = null # Doesn't exist in early initialization.
supportedWebViewEvents = [
2015-08-05 11:50:23 +00:00
'load-commit'
'did-finish-load'
'did-fail-load'
'did-frame-finish-load'
'did-start-loading'
'did-stop-loading'
'did-get-response-details'
'did-get-redirect-request'
2015-04-29 13:49:31 +00:00
'dom-ready'
'console-message'
2014-10-25 05:21:09 +00:00
'new-window'
'close'
'crashed'
'gpu-crashed'
'plugin-crashed'
'destroyed'
'page-title-updated'
'page-favicon-updated'
'enter-html-full-screen'
'leave-html-full-screen'
]
nextInstanceId = 0
guestInstances = {}
2014-12-08 16:05:34 +00:00
embedderElementsMap = {}
reverseEmbedderElementsMap = {}
# Moves the last element of array to the first one.
moveLastToFirst = (list) ->
list.unshift list.pop()
# Generate guestInstanceId.
getNextInstanceId = (webContents) ->
++nextInstanceId
# Create a new guest instance.
createGuest = (embedder, params) ->
2014-10-23 15:08:48 +00:00
webViewManager ?= process.atomBinding 'web_view_manager'
id = getNextInstanceId embedder
2015-09-06 01:22:32 +00:00
guest = webContents.create {isGuest: true, partition: params.partition, embedder}
guestInstances[id] = {guest, embedder}
# Destroy guest when the embedder is gone or navigated.
destroyEvents = ['destroyed', 'crashed', 'did-navigate-to-different-page']
destroy = ->
destroyGuest embedder, id if guestInstances[id]?
for event in destroyEvents
embedder.once event, destroy
# Users might also listen to the crashed event, so We must ensure the guest
# is destroyed before users' listener gets called. It is done by moving our
# listener to the first one in queue.
listeners = embedder._events[event]
moveLastToFirst listeners if Array.isArray listeners
guest.once 'destroyed', ->
embedder.removeListener event, destroy for event in destroyEvents
2014-10-24 08:48:21 +00:00
# Init guest web view after attached.
2014-12-08 16:05:34 +00:00
guest.once 'did-attach', ->
params = @attachParams
delete @attachParams
@viewInstanceId = params.instanceId
2015-05-29 03:44:49 +00:00
@setSize
2015-05-29 05:47:09 +00:00
normal:
width: params.elementWidth, height: params.elementHeight
2015-05-29 03:44:49 +00:00
enableAutoSize: params.autosize
min:
width: params.minwidth, height: params.minheight
max:
width: params.maxwidth, height: params.maxheight
2015-05-11 17:00:41 +00:00
2014-10-24 08:48:21 +00:00
if params.src
opts = {}
opts.httpReferrer = params.httpreferrer if params.httpreferrer
opts.userAgent = params.useragent if params.useragent
2015-11-13 08:03:40 +00:00
@loadURL params.src, opts
2015-05-11 17:00:41 +00:00
2014-10-24 08:48:21 +00:00
if params.allowtransparency?
@setAllowTransparency params.allowtransparency
2015-09-22 12:11:05 +00:00
guest.allowPopups = params.allowpopups
# Dispatch events to embedder.
for event in supportedWebViewEvents
do (event) ->
guest.on event, (_, args...) ->
embedder.send "ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-#{guest.viewInstanceId}", event, args...
2014-12-17 19:09:11 +00:00
# Dispatch guest's IPC messages to embedder.
guest.on 'ipc-message-host', (_, packed) ->
[channel, args...] = packed
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...
id
2014-12-08 16:05:34 +00:00
# Attach the guest to an element of embedder.
attachGuest = (embedder, elementInstanceId, guestInstanceId, params) ->
guest = guestInstances[guestInstanceId].guest
# Destroy the old guest when attaching.
key = "#{embedder.getId()}-#{elementInstanceId}"
oldGuestInstanceId = embedderElementsMap[key]
if oldGuestInstanceId?
# Reattachment to the same guest is not currently supported.
return unless oldGuestInstanceId != guestInstanceId
return unless guestInstances[oldGuestInstanceId]?
destroyGuest embedder, oldGuestInstanceId
2014-12-08 16:05:34 +00:00
webPreferences =
guestInstanceId: guestInstanceId
nodeIntegration: params.nodeintegration ? false
plugins: params.plugins
webSecurity: !params.disablewebsecurity
2015-11-13 08:03:40 +00:00
webPreferences.preloadURL = params.preload if params.preload
webViewManager.addGuest guestInstanceId, elementInstanceId, embedder, guest, webPreferences
2014-12-08 16:05:34 +00:00
guest.attachParams = params
embedderElementsMap[key] = guestInstanceId
reverseEmbedderElementsMap[guestInstanceId] = key
# Destroy an existing guest instance.
destroyGuest = (embedder, id) ->
webViewManager.removeGuest embedder, id
guestInstances[id].guest.destroy()
delete guestInstances[id]
2014-12-08 16:05:34 +00:00
key = reverseEmbedderElementsMap[id]
if key?
delete reverseEmbedderElementsMap[id]
delete embedderElementsMap[key]
ipcMain.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', (event, params, requestId) ->
2014-10-23 15:08:48 +00:00
event.sender.send "ATOM_SHELL_RESPONSE_#{requestId}", createGuest(event.sender, params)
ipcMain.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', (event, elementInstanceId, guestInstanceId, params) ->
2014-12-08 16:05:34 +00:00
attachGuest event.sender, elementInstanceId, guestInstanceId, params
ipcMain.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', (event, id) ->
destroyGuest event.sender, id
ipcMain.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_SIZE', (event, id, params) ->
guestInstances[id]?.guest.setSize params
2014-10-24 08:48:21 +00:00
ipcMain.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_ALLOW_TRANSPARENCY', (event, id, allowtransparency) ->
guestInstances[id]?.guest.setAllowTransparency allowtransparency
2014-10-24 11:57:29 +00:00
# Returns WebContents from its guest id.
exports.getGuest = (id) ->
guestInstances[id]?.guest
# Returns the embedder of the guest.
exports.getEmbedder = (id) ->
guestInstances[id]?.embedder