github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/themes/wind/static/libs/sockjs-client-1.1.0/lib/transport/iframe.js (about)

     1  'use strict';
     2  
     3  // Few cool transports do work only for same-origin. In order to make
     4  // them work cross-domain we shall use iframe, served from the
     5  // remote domain. New browsers have capabilities to communicate with
     6  // cross domain iframe using postMessage(). In IE it was implemented
     7  // from IE 8+, but of course, IE got some details wrong:
     8  //    http://msdn.microsoft.com/en-us/library/cc197015(v=VS.85).aspx
     9  //    http://stevesouders.com/misc/test-postmessage.php
    10  
    11  var inherits = require('inherits')
    12    , JSON3 = require('json3')
    13    , EventEmitter = require('events').EventEmitter
    14    , version = require('../version')
    15    , urlUtils = require('../utils/url')
    16    , iframeUtils = require('../utils/iframe')
    17    , eventUtils = require('../utils/event')
    18    , random = require('../utils/random')
    19    ;
    20  
    21  var debug = function() {};
    22  if (process.env.NODE_ENV !== 'production') {
    23    debug = require('debug')('sockjs-client:transport:iframe');
    24  }
    25  
    26  function IframeTransport(transport, transUrl, baseUrl) {
    27    if (!IframeTransport.enabled()) {
    28      throw new Error('Transport created when disabled');
    29    }
    30    EventEmitter.call(this);
    31  
    32    var self = this;
    33    this.origin = urlUtils.getOrigin(baseUrl);
    34    this.baseUrl = baseUrl;
    35    this.transUrl = transUrl;
    36    this.transport = transport;
    37    this.windowId = random.string(8);
    38  
    39    var iframeUrl = urlUtils.addPath(baseUrl, '/iframe.html') + '#' + this.windowId;
    40    debug(transport, transUrl, iframeUrl);
    41  
    42    this.iframeObj = iframeUtils.createIframe(iframeUrl, function(r) {
    43      debug('err callback');
    44      self.emit('close', 1006, 'Unable to load an iframe (' + r + ')');
    45      self.close();
    46    });
    47  
    48    this.onmessageCallback = this._message.bind(this);
    49    eventUtils.attachEvent('message', this.onmessageCallback);
    50  }
    51  
    52  inherits(IframeTransport, EventEmitter);
    53  
    54  IframeTransport.prototype.close = function() {
    55    debug('close');
    56    this.removeAllListeners();
    57    if (this.iframeObj) {
    58      eventUtils.detachEvent('message', this.onmessageCallback);
    59      try {
    60        // When the iframe is not loaded, IE raises an exception
    61        // on 'contentWindow'.
    62        this.postMessage('c');
    63      } catch (x) {
    64        // intentionally empty
    65      }
    66      this.iframeObj.cleanup();
    67      this.iframeObj = null;
    68      this.onmessageCallback = this.iframeObj = null;
    69    }
    70  };
    71  
    72  IframeTransport.prototype._message = function(e) {
    73    debug('message', e.data);
    74    if (!urlUtils.isOriginEqual(e.origin, this.origin)) {
    75      debug('not same origin', e.origin, this.origin);
    76      return;
    77    }
    78  
    79    var iframeMessage;
    80    try {
    81      iframeMessage = JSON3.parse(e.data);
    82    } catch (ignored) {
    83      debug('bad json', e.data);
    84      return;
    85    }
    86  
    87    if (iframeMessage.windowId !== this.windowId) {
    88      debug('mismatched window id', iframeMessage.windowId, this.windowId);
    89      return;
    90    }
    91  
    92    switch (iframeMessage.type) {
    93    case 's':
    94      this.iframeObj.loaded();
    95      // window global dependency
    96      this.postMessage('s', JSON3.stringify([
    97        version
    98      , this.transport
    99      , this.transUrl
   100      , this.baseUrl
   101      ]));
   102      break;
   103    case 't':
   104      this.emit('message', iframeMessage.data);
   105      break;
   106    case 'c':
   107      var cdata;
   108      try {
   109        cdata = JSON3.parse(iframeMessage.data);
   110      } catch (ignored) {
   111        debug('bad json', iframeMessage.data);
   112        return;
   113      }
   114      this.emit('close', cdata[0], cdata[1]);
   115      this.close();
   116      break;
   117    }
   118  };
   119  
   120  IframeTransport.prototype.postMessage = function(type, data) {
   121    debug('postMessage', type, data);
   122    this.iframeObj.post(JSON3.stringify({
   123      windowId: this.windowId
   124    , type: type
   125    , data: data || ''
   126    }), this.origin);
   127  };
   128  
   129  IframeTransport.prototype.send = function(message) {
   130    debug('send', message);
   131    this.postMessage('m', message);
   132  };
   133  
   134  IframeTransport.enabled = function() {
   135    return iframeUtils.iframeEnabled;
   136  };
   137  
   138  IframeTransport.transportName = 'iframe';
   139  IframeTransport.roundTrips = 2;
   140  
   141  module.exports = IframeTransport;