1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/**
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @fileoverview
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Obtains additional host permissions, showing a consent dialog if needed.
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * When third party authentication is being used, the client must talk to a
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * third-party server. For that, once the URL is received from the host the
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * webapp must use Chrome's optional permissions API to check if it has the
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * "host" permission needed to access that URL. If the webapp hasn't already
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * been granted that permission, it shows a dialog explaining why it is being
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * requested, then uses the Chrome API ask the user for the new permission.
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)'use strict';
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/** @suppress {duplicate} */
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)var remoting = remoting || {};
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/**
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @constructor
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Encapsulates the UI to check/request permissions to a new host.
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param {string} url The URL to request permission for.
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)remoting.ThirdPartyHostPermissions = function(url) {
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  this.url_ = url;
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  this.permissions_ = {'origins': [url]};
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/**
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Get permissions to the URL, asking interactively if necessary.
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param {function(): void} onOk Called if the permission is granted.
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param {function(): void} onError Called if the permission is denied.
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)remoting.ThirdPartyHostPermissions.prototype.getPermission = function(
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    onOk, onError) {
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /** @type {remoting.ThirdPartyHostPermissions} */
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  var that = this;
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  chrome.permissions.contains(this.permissions_,
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /** @param {boolean} allowed Whether this extension has this permission. */
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    function(allowed) {
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (allowed) {
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        onOk();
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else {
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // Optional permissions must be requested in a user action context. This
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // is called from an asynchronous plugin callback, so we have to open a
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // confirmation dialog to perform the request on an interactive event.
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // In any case, we can use this dialog to explain to the user why we are
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // asking for the additional permission.
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        that.showPermissionConfirmation_(onOk, onError);
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    });
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/**
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Show an interactive dialog informing the user of the new permissions.
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param {function(): void} onOk Called if the permission is granted.
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param {function(): void} onError Called if the permission is denied.
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @private
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)remoting.ThirdPartyHostPermissions.prototype.showPermissionConfirmation_ =
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    function(onOk, onError) {
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /** @type {HTMLElement} */
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  var button = document.getElementById('third-party-auth-button');
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /** @type {HTMLElement} */
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  var url = document.getElementById('third-party-auth-url');
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  url.innerText = this.url_;
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /** @type {remoting.ThirdPartyHostPermissions} */
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  var that = this;
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  var consentGranted = function(event) {
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    button.removeEventListener('click', consentGranted, false);
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    that.requestPermission_(onOk, onError);
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  button.addEventListener('click', consentGranted, false);
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  remoting.setMode(remoting.AppMode.CLIENT_THIRD_PARTY_AUTH);
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/**
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Request permission from the user to access the token-issue URL.
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param {function(): void} onOk Called if the permission is granted.
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param {function(): void} onError Called if the permission is denied.
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @private
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)remoting.ThirdPartyHostPermissions.prototype.requestPermission_ = function(
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    onOk, onError) {
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  chrome.permissions.request(
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    this.permissions_,
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /** @param {boolean} result Whether the permission was granted. */
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    function(result) {
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (result) {
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        onOk();
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else {
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        onError();
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  });
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
108