var attachGuest, createGuest, destroyGuest, embedderElementsMap, getNextInstanceId, guestInstances, ipcMain, moveLastToFirst, nextInstanceId, ref, reverseEmbedderElementsMap, supportedWebViewEvents, webContents, webViewManager, slice = [].slice; ref = require('electron'), ipcMain = ref.ipcMain, webContents = ref.webContents; /* Doesn't exist in early initialization. */ webViewManager = null; supportedWebViewEvents = ['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', 'dom-ready', 'console-message', 'devtools-opened', 'devtools-closed', 'devtools-focused', 'new-window', 'will-navigate', 'did-navigate', 'did-navigate-in-page', 'close', 'crashed', 'gpu-crashed', 'plugin-crashed', 'destroyed', 'page-title-updated', 'page-favicon-updated', 'enter-html-full-screen', 'leave-html-full-screen', 'media-started-playing', 'media-paused', 'found-in-page', 'did-change-theme-color']; nextInstanceId = 0; guestInstances = {}; embedderElementsMap = {}; reverseEmbedderElementsMap = {}; /* Moves the last element of array to the first one. */ moveLastToFirst = function(list) { return list.unshift(list.pop()); }; /* Generate guestInstanceId. */ getNextInstanceId = function(webContents) { return ++nextInstanceId; }; /* Create a new guest instance. */ createGuest = function(embedder, params) { var destroy, destroyEvents, event, fn, guest, i, id, j, len, len1, listeners; if (webViewManager == null) { webViewManager = process.atomBinding('web_view_manager'); } id = getNextInstanceId(embedder); guest = webContents.create({ isGuest: true, partition: params.partition, embedder: embedder }); guestInstances[id] = { guest: guest, embedder: embedder }; /* Destroy guest when the embedder is gone or navigated. */ destroyEvents = ['destroyed', 'crashed', 'did-navigate']; destroy = function() { if (guestInstances[id] != null) { return destroyGuest(embedder, id); } }; for (i = 0, len = destroyEvents.length; i < len; i++) { event = destroyEvents[i]; 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]; if (Array.isArray(listeners)) { moveLastToFirst(listeners); } } guest.once('destroyed', function() { var j, len1, results; results = []; for (j = 0, len1 = destroyEvents.length; j < len1; j++) { event = destroyEvents[j]; results.push(embedder.removeListener(event, destroy)); } return results; }); /* Init guest web view after attached. */ guest.once('did-attach', function() { var opts; params = this.attachParams; delete this.attachParams; this.viewInstanceId = params.instanceId; this.setSize({ normal: { width: params.elementWidth, height: params.elementHeight }, enableAutoSize: params.autosize, min: { width: params.minwidth, height: params.minheight }, max: { width: params.maxwidth, height: params.maxheight } }); if (params.src) { opts = {}; if (params.httpreferrer) { opts.httpReferrer = params.httpreferrer; } if (params.useragent) { opts.userAgent = params.useragent; } this.loadURL(params.src, opts); } if (params.allowtransparency != null) { this.setAllowTransparency(params.allowtransparency); } return guest.allowPopups = params.allowpopups; }); /* Dispatch events to embedder. */ fn = function(event) { return guest.on(event, function() { var _, args; _ = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : []; return embedder.send.apply(embedder, ["ATOM_SHELL_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-" + guest.viewInstanceId, event].concat(slice.call(args))); }); }; for (j = 0, len1 = supportedWebViewEvents.length; j < len1; j++) { event = supportedWebViewEvents[j]; fn(event); } /* Dispatch guest's IPC messages to embedder. */ guest.on('ipc-message-host', function(_, packed) { var args, channel; channel = packed[0], args = 2 <= packed.length ? slice.call(packed, 1) : []; return embedder.send.apply(embedder, ["ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-" + guest.viewInstanceId, channel].concat(slice.call(args))); }); /* Autosize. */ guest.on('size-changed', function() { var _, args; _ = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : []; return embedder.send.apply(embedder, ["ATOM_SHELL_GUEST_VIEW_INTERNAL_SIZE_CHANGED-" + guest.viewInstanceId].concat(slice.call(args))); }); return id; }; /* Attach the guest to an element of embedder. */ attachGuest = function(embedder, elementInstanceId, guestInstanceId, params) { var guest, key, oldGuestInstanceId, ref1, webPreferences; guest = guestInstances[guestInstanceId].guest; /* Destroy the old guest when attaching. */ key = (embedder.getId()) + "-" + elementInstanceId; oldGuestInstanceId = embedderElementsMap[key]; if (oldGuestInstanceId != null) { /* Reattachment to the same guest is not currently supported. */ if (oldGuestInstanceId === guestInstanceId) { return; } if (guestInstances[oldGuestInstanceId] == null) { return; } destroyGuest(embedder, oldGuestInstanceId); } webPreferences = { guestInstanceId: guestInstanceId, nodeIntegration: (ref1 = params.nodeintegration) != null ? ref1 : false, plugins: params.plugins, webSecurity: !params.disablewebsecurity }; if (params.preload) { webPreferences.preloadURL = params.preload; } webViewManager.addGuest(guestInstanceId, elementInstanceId, embedder, guest, webPreferences); guest.attachParams = params; embedderElementsMap[key] = guestInstanceId; return reverseEmbedderElementsMap[guestInstanceId] = key; }; /* Destroy an existing guest instance. */ destroyGuest = function(embedder, id) { var key; webViewManager.removeGuest(embedder, id); guestInstances[id].guest.destroy(); delete guestInstances[id]; key = reverseEmbedderElementsMap[id]; if (key != null) { delete reverseEmbedderElementsMap[id]; return delete embedderElementsMap[key]; } }; ipcMain.on('ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', function(event, params, requestId) { return event.sender.send("ATOM_SHELL_RESPONSE_" + requestId, createGuest(event.sender, params)); }); ipcMain.on('ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', function(event, elementInstanceId, guestInstanceId, params) { return attachGuest(event.sender, elementInstanceId, guestInstanceId, params); }); ipcMain.on('ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', function(event, id) { return destroyGuest(event.sender, id); }); ipcMain.on('ATOM_SHELL_GUEST_VIEW_MANAGER_SET_SIZE', function(event, id, params) { var ref1; return (ref1 = guestInstances[id]) != null ? ref1.guest.setSize(params) : void 0; }); ipcMain.on('ATOM_SHELL_GUEST_VIEW_MANAGER_SET_ALLOW_TRANSPARENCY', function(event, id, allowtransparency) { var ref1; return (ref1 = guestInstances[id]) != null ? ref1.guest.setAllowTransparency(allowtransparency) : void 0; }); /* Returns WebContents from its guest id. */ exports.getGuest = function(id) { var ref1; return (ref1 = guestInstances[id]) != null ? ref1.guest : void 0; }; /* Returns the embedder of the guest. */ exports.getEmbedder = function(id) { var ref1; return (ref1 = guestInstances[id]) != null ? ref1.embedder : void 0; };