187 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			187 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| '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);
 | |
|       setTimeout(function() {
 | |
|         try {
 | |
|           // When the iframe is not loaded, IE raises an exception
 | |
|           // on 'contentWindow'.
 | |
|           if (iframe && iframe.contentWindow) {
 | |
|             iframe.contentWindow.postMessage(msg, origin);
 | |
|           }
 | |
|         } catch (x) {
 | |
|           // intentionally empty
 | |
|         }
 | |
|       }, 0);
 | |
|     };
 | |
| 
 | |
|     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('<html><s' + 'cript>' +
 | |
|               'document.domain="' + global.document.domain + '";' +
 | |
|               '</s' + 'cript></html>');
 | |
|     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());
 | |
| }
 |