Blame view

node_modules/sockjs-client/lib/iframe-bootstrap.js 2.83 KB
aaac7fed   liuqimichale   add
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
  'use strict';
  
  var urlUtils = require('./utils/url')
    , eventUtils = require('./utils/event')
    , JSON3 = require('json3')
    , FacadeJS = require('./facade')
    , InfoIframeReceiver = require('./info-iframe-receiver')
    , iframeUtils = require('./utils/iframe')
    , loc = require('./location')
    ;
  
  var debug = function() {};
  if (process.env.NODE_ENV !== 'production') {
    debug = require('debug')('sockjs-client:iframe-bootstrap');
  }
  
  module.exports = function(SockJS, availableTransports) {
    var transportMap = {};
    availableTransports.forEach(function(at) {
      if (at.facadeTransport) {
        transportMap[at.facadeTransport.transportName] = at.facadeTransport;
      }
    });
  
    // hard-coded for the info iframe
    // TODO see if we can make this more dynamic
    transportMap[InfoIframeReceiver.transportName] = InfoIframeReceiver;
    var parentOrigin;
  
    /* eslint-disable camelcase */
    SockJS.bootstrap_iframe = function() {
      /* eslint-enable camelcase */
      var facade;
      iframeUtils.currentWindowId = loc.hash.slice(1);
      var onMessage = function(e) {
        if (e.source !== parent) {
          return;
        }
        if (typeof parentOrigin === 'undefined') {
          parentOrigin = e.origin;
        }
        if (e.origin !== parentOrigin) {
          return;
        }
  
        var iframeMessage;
        try {
          iframeMessage = JSON3.parse(e.data);
        } catch (ignored) {
          debug('bad json', e.data);
          return;
        }
  
        if (iframeMessage.windowId !== iframeUtils.currentWindowId) {
          return;
        }
        switch (iframeMessage.type) {
        case 's':
          var p;
          try {
            p = JSON3.parse(iframeMessage.data);
          } catch (ignored) {
            debug('bad json', iframeMessage.data);
            break;
          }
          var version = p[0];
          var transport = p[1];
          var transUrl = p[2];
          var baseUrl = p[3];
          debug(version, transport, transUrl, baseUrl);
          // change this to semver logic
          if (version !== SockJS.version) {
            throw new Error('Incompatible SockJS! Main site uses:' +
                      ' "' + version + '", the iframe:' +
                      ' "' + SockJS.version + '".');
          }
  
          if (!urlUtils.isOriginEqual(transUrl, loc.href) ||
              !urlUtils.isOriginEqual(baseUrl, loc.href)) {
            throw new Error('Can\'t connect to different domain from within an ' +
                      'iframe. (' + loc.href + ', ' + transUrl + ', ' + baseUrl + ')');
          }
          facade = new FacadeJS(new transportMap[transport](transUrl, baseUrl));
          break;
        case 'm':
          facade._send(iframeMessage.data);
          break;
        case 'c':
          if (facade) {
            facade._close();
          }
          facade = null;
          break;
        }
      };
  
      eventUtils.attachEvent('message', onMessage);
  
      // Start
      iframeUtils.postMessage('s');
    };
  };