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