summaryrefslogtreecommitdiffstats
path: root/remoting/webapp/wcs_loader.js
blob: 3ab10bffae86b474e85d630ec793dfee59e99cb2 (plain)
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/**
 * @fileoverview
 * A class that loads a WCS IQ client and constructs remoting.wcs as a
 * wrapper for it.
 */

'use strict';

/** @suppress {duplicate} */
var remoting = remoting || {};

/** @type {remoting.WcsLoader} */
remoting.wcsLoader = null;

/**
 * @constructor
 */
remoting.WcsLoader = function() {
  /**
   * The WCS client that will be downloaded. This variable is initialized (via
   * remoting.wcsLoader) by the downloaded Javascript.
   * @type {remoting.WcsIqClient}
   */
  this.wcsIqClient = null;
};

/**
 * The id of the script node.
 * @type {string}
 * @private
 */
remoting.WcsLoader.prototype.SCRIPT_NODE_ID_ = 'wcs-script-node';

/**
 * Starts loading the WCS IQ client.
 *
 * When it's loaded, construct remoting.wcs as a wrapper for it.
 * When the WCS connection is ready, or on error, call |onReady| or |onError|,
 * respectively.
 *
 * @param {string} token An OAuth2 access token.
 * @param {function(string): void} onReady The callback function, called with
 *     a client JID when WCS has been loaded.
 * @param {function(remoting.Error):void} onError Function to invoke with an
 *     error code on failure.
 * @return {void} Nothing.
 */
remoting.WcsLoader.prototype.start = function(token, onReady, onError) {
  var node = document.getElementById(this.SCRIPT_NODE_ID_);
  if (node) {
    console.error('Multiple calls to WcsLoader.start are not allowed.');
    onError(remoting.Error.UNEXPECTED);
    return;
  }

  // Create a script node to load the WCS driver.
  node = document.createElement('script');
  node.id = this.SCRIPT_NODE_ID_;
  node.src = remoting.settings.TALK_GADGET_URL + 'iq?access_token=' + token;
  node.type = 'text/javascript';
  document.body.insertBefore(node, document.body.firstChild);

  /** @type {remoting.WcsLoader} */
  var that = this;
  var onLoad = function() {
    that.constructWcs_(token, onReady);
  };
  var onLoadError = function(event) {
    // The DOM Event object has no detail on the nature of the error, so try to
    // validate the token to get a better idea.
    /** @param {remoting.Error} error Error code. */
    var onValidateError = function(error) {
      var typedNode = /** @type {Element} */ (node);
      typedNode.parentNode.removeChild(node);
      onError(error);
    };
    var onValidateOk = function() {
      // We can reach the authentication server and validate the token. Either
      // there's something wrong with the talkgadget service, or there is a
      // cookie problem. Only the cookie problem can be fixed by the user, so
      // suggest that fix.
      onValidateError(remoting.Error.AUTHENTICATION_FAILED);
    }
    that.validateToken(token, onValidateOk, onValidateError);
  }
  node.addEventListener('load', onLoad, false);
  node.addEventListener('error', onLoadError, false);
};

/**
 * Constructs the remoting.wcs object.
 *
 * @param {string} token An OAuth2 access token.
 * @param {function(string): void} onReady The callback function, called with
 *     an OAuth2 access token when WCS has been loaded.
 * @return {void} Nothing.
 * @private
 */
remoting.WcsLoader.prototype.constructWcs_ = function(token, onReady) {
  remoting.wcs = new remoting.Wcs(
      remoting.wcsLoader.wcsIqClient, token, onReady);
};

/**
 * Validates an OAuth2 access token.
 *
 * @param {string} token The access token.
 * @param {function():void} onOk Callback to invoke if the token is valid.
 * @param {function(remoting.Error):void} onError Function to invoke with an
 *     error code on failure.
 * @return {void} Nothing.
 */
remoting.WcsLoader.prototype.validateToken = function(token, onOk, onError) {
  /** @type {XMLHttpRequest} */
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (xhr.readyState != 4) {
      return;
    }
    if (xhr.status == 200) {
      onOk();
    } else {
      var error = remoting.Error.AUTHENTICATION_FAILED;
      switch (xhr.status) {
        case 0:
          error = remoting.Error.NETWORK_FAILURE;
          break;
        case 502: // No break
        case 503:
          error = remoting.Error.SERVICE_UNAVAILABLE;
          break;
      }
      onError(error);
    }
  };
  var parameters = '?access_token=' + encodeURIComponent(token);
  xhr.open('GET',
           remoting.settings.OAUTH2_API_BASE_URL + '/v1/tokeninfo' + parameters,
           true);
  xhr.send(null);
};