'use strict'; var eventUtils = require('./event') , JSON3 = require('json3') , browser = require('./browser') ; var debug = function() {}; if (process.env.NODE_ENV !== 'production') { debug = require('debug')('sockjs-client:utils:iframe'); } module.exports = { WPrefix: '_jp' , currentWindowId: null , polluteGlobalNamespace: function() { if (!(module.exports.WPrefix in global)) { global[module.exports.WPrefix] = {}; } } , postMessage: function(type, data) { if (global.parent !== global) { global.parent.postMessage(JSON3.stringify({ windowId: module.exports.currentWindowId , type: type , data: data || '' }), '*'); } else { debug('Cannot postMessage, no parent window.', type, data); } } , createIframe: function(iframeUrl, errorCallback) { var iframe = global.document.createElement('iframe'); var tref, unloadRef; var unattach = function() { debug('unattach'); clearTimeout(tref); // Explorer had problems with that. try { iframe.onload = null; } catch (x) { // intentionally empty } iframe.onerror = null; }; var cleanup = function() { debug('cleanup'); if (iframe) { unattach(); // This timeout makes chrome fire onbeforeunload event // within iframe. Without the timeout it goes straight to // onunload. setTimeout(function() { if (iframe) { iframe.parentNode.removeChild(iframe); } iframe = null; }, 0); eventUtils.unloadDel(unloadRef); } }; var onerror = function(err) { debug('onerror', err); if (iframe) { cleanup(); errorCallback(err); } }; var post = function(msg, origin) { debug('post', msg, origin); try { // When the iframe is not loaded, IE raises an exception // on 'contentWindow'. setTimeout(function() { if (iframe && iframe.contentWindow) { iframe.contentWindow.postMessage(msg, origin); } }, 0); } catch (x) { // intentionally empty } }; iframe.src = iframeUrl; iframe.style.display = 'none'; iframe.style.position = 'absolute'; iframe.onerror = function() { onerror('onerror'); }; iframe.onload = function() { debug('onload'); // `onload` is triggered before scripts on the iframe are // executed. Give it few seconds to actually load stuff. clearTimeout(tref); tref = setTimeout(function() { onerror('onload timeout'); }, 2000); }; global.document.body.appendChild(iframe); tref = setTimeout(function() { onerror('timeout'); }, 15000); unloadRef = eventUtils.unloadAdd(cleanup); return { post: post , cleanup: cleanup , loaded: unattach }; } /* eslint no-undef: "off", new-cap: "off" */ , createHtmlfile: function(iframeUrl, errorCallback) { var axo = ['Active'].concat('Object').join('X'); var doc = new global[axo]('htmlfile'); var tref, unloadRef; var iframe; var unattach = function() { clearTimeout(tref); iframe.onerror = null; }; var cleanup = function() { if (doc) { unattach(); eventUtils.unloadDel(unloadRef); iframe.parentNode.removeChild(iframe); iframe = doc = null; CollectGarbage(); } }; var onerror = function(r) { debug('onerror', r); if (doc) { cleanup(); errorCallback(r); } }; var post = function(msg, origin) { try { // When the iframe is not loaded, IE raises an exception // on 'contentWindow'. setTimeout(function() { if (iframe && iframe.contentWindow) { iframe.contentWindow.postMessage(msg, origin); } }, 0); } catch (x) { // intentionally empty } }; doc.open(); doc.write('' + 'document.domain="' + global.document.domain + '";' + ''); doc.close(); doc.parentWindow[module.exports.WPrefix] = global[module.exports.WPrefix]; var c = doc.createElement('div'); doc.body.appendChild(c); iframe = doc.createElement('iframe'); c.appendChild(iframe); iframe.src = iframeUrl; iframe.onerror = function() { onerror('onerror'); }; tref = setTimeout(function() { onerror('timeout'); }, 15000); unloadRef = eventUtils.unloadAdd(cleanup); return { post: post , cleanup: cleanup , loaded: unattach }; } }; module.exports.iframeEnabled = false; if (global.document) { // postMessage misbehaves in konqueror 4.6.5 - the messages are delivered with // huge delay, or not at all. module.exports.iframeEnabled = (typeof global.postMessage === 'function' || typeof global.postMessage === 'object') && (!browser.isKonqueror()); }