summaryrefslogtreecommitdiffstats
path: root/remoting/webapp/third_party_host_permissions.js
blob: 1fd3edf3d6054c536c622ae71c8bbb69a9b9cc3c (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
// Copyright 2013 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
 * Obtains additional host permissions, showing a consent dialog if needed.
 *
 * When third party authentication is being used, the client must talk to a
 * third-party server. For that, once the URL is received from the host the
 * webapp must use Chrome's optional permissions API to check if it has the
 * "host" permission needed to access that URL. If the webapp hasn't already
 * been granted that permission, it shows a dialog explaining why it is being
 * requested, then uses the Chrome API ask the user for the new permission.
 */

'use strict';

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

/**
 * @constructor
 * Encapsulates the UI to check/request permissions to a new host.
 *
 * @param {string} url The URL to request permission for.
 */
remoting.ThirdPartyHostPermissions = function(url) {
  this.url_ = url;
  this.permissions_ = {'origins': [url]};
};

/**
 * Get permissions to the URL, asking interactively if necessary.
 *
 * @param {function(): void} onOk Called if the permission is granted.
 * @param {function(): void} onError Called if the permission is denied.
 */
remoting.ThirdPartyHostPermissions.prototype.getPermission = function(
    onOk, onError) {
  /** @type {remoting.ThirdPartyHostPermissions} */
  var that = this;
  chrome.permissions.contains(this.permissions_,
    /** @param {boolean} allowed Whether this extension has this permission. */
    function(allowed) {
      if (allowed) {
        onOk();
      } else {
        // Optional permissions must be requested in a user action context. This
        // is called from an asynchronous plugin callback, so we have to open a
        // confirmation dialog to perform the request on an interactive event.
        // In any case, we can use this dialog to explain to the user why we are
        // asking for the additional permission.
        that.showPermissionConfirmation_(onOk, onError);
      }
    });
};

/**
 * Show an interactive dialog informing the user of the new permissions.
 *
 * @param {function(): void} onOk Called if the permission is granted.
 * @param {function(): void} onError Called if the permission is denied.
 * @private
 */
remoting.ThirdPartyHostPermissions.prototype.showPermissionConfirmation_ =
    function(onOk, onError) {
  /** @type {HTMLElement} */
  var button = document.getElementById('third-party-auth-button');
  /** @type {HTMLElement} */
  var url = document.getElementById('third-party-auth-url');
  url.innerText = this.url_;

  /** @type {remoting.ThirdPartyHostPermissions} */
  var that = this;

  var consentGranted = function(event) {
    remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
    button.removeEventListener('click', consentGranted, false);
    that.requestPermission_(onOk, onError);
  };

  button.addEventListener('click', consentGranted, false);
  remoting.setMode(remoting.AppMode.CLIENT_THIRD_PARTY_AUTH);
};


/**
 * Request permission from the user to access the token-issue URL.
 *
 * @param {function(): void} onOk Called if the permission is granted.
 * @param {function(): void} onError Called if the permission is denied.
 * @private
 */
remoting.ThirdPartyHostPermissions.prototype.requestPermission_ = function(
    onOk, onError) {
  chrome.permissions.request(
    this.permissions_,
    /** @param {boolean} result Whether the permission was granted. */
    function(result) {
      if (result) {
        onOk();
      } else {
        onError();
      }
  });
};