/*
* Copyright (c) 2015-2017, Michael A. Updike All rights reserved.
* Licensed under the BSD-3-Clause
* https://opensource.org/licenses/BSD-3-Clause
* https://github.com/opus1269/photo-screen-saver/blob/master/LICENSE.md
*/
window.app = window.app || {};
/**
* Handle optional permissions
* @namespace
*/
app.Permissions = (function() {
'use strict';
new ExceptionHandler();
const chromep = new ChromePromise();
/**
* A permission state enum
* @typedef {{}} app.Permissions.State
* @property {string} notSet - never been allowed or denied
* @property {string} allowed - user allowed
* @property {string} denied - user denied
* @memberOf app.Permissions
*/
/**
* A permission type
* @typedef {{}} app.Permissions.Type
* @property {string} name - name in localStorage
* @property {string[]} permissions - array of permissions
* @property {string[]} origins - array of origins
* @memberOf app.Permissions
*/
/**
* Possible states of an {@link app.Permissions.Type}
* @type {app.Permissions.State}
* @const
* @private
* @memberOf app.Permissions
*/
const _STATE = {
notSet: 'notSet',
allowed: 'allowed',
denied: 'denied',
};
/**
* Permission for access to users' Google Photos
* @const
* @type {app.Permissions.Type}
* @memberOf app.Permissions
*/
const PICASA = {
name: 'permPicasa',
permissions: [],
origins: ['https://picasaweb.google.com/'],
};
/**
* Permission for running in background
* @const
* @type {app.Permissions.Type}
* @memberOf app.Permissions
*/
const BACKGROUND = {
name: 'permBackground',
permissions: ['background'],
origins: [],
};
/**
* Persist the state of an {@link app.Permissions.Type}
* @param {app.Permissions.Type} type - permission type
* @param {string} value - permission state
* @private
* @memberOf app.Permissions
*/
function _setState(type, value) {
// send message to store value so items that are bound
// to it will get storage event
const msg = Chrome.JSONUtils.shallowCopy(Chrome.Msg.STORE);
msg.key = type.name;
msg.value = value;
Chrome.Msg.send(msg).catch(() => {});
}
/**
* Determine if we have the optional permissions
* @param {app.Permissions.Type} type - permission type
* @returns {Promise<boolean>} true if we have permissions
* @memberOf app.Permissions
*/
function _contains(type) {
return chromep.permissions.contains({
permissions: type.permissions,
origins: type.origins,
});
}
return {
/**
* @type {app.Permissions.Type}
* @memberOf app.Permissions
*/
PICASA: PICASA,
/**
* @type {app.Permissions.Type}
* @memberOf app.Permissions
*/
BACKGROUND: BACKGROUND,
/**
* Has user made choice on permissions
* @param {app.Permissions.Type} type - permission type
* @returns {boolean} true if allowed or denied
* @memberOf app.Permissions
*/
notSet: function(type) {
return Chrome.Storage.get(type.name) === _STATE.notSet;
},
/**
* Has the user allowed the optional permissions
* @param {app.Permissions.Type} type - permission type
* @returns {boolean} true if allowed
* @memberOf app.Permissions
*/
isAllowed: function(type) {
return Chrome.Storage.get(type.name) === _STATE.allowed;
},
/**
* Request optional permission - may block
* @param {app.Permissions.Type} type - permission type
* @returns {Promise<boolean>} true if permission granted
* @memberOf app.Permissions
*/
request: function(type) {
let isGranted;
return chromep.permissions.request({
permissions: type.permissions,
origins: type.origins,
}).then((granted) => {
isGranted = granted;
if (granted) {
_setState(type, _STATE.allowed);
return Promise.resolve();
} else {
_setState(type, _STATE.denied);
// try to remove if it has been previously granted
return app.Permissions.remove(type);
}
}).then(() => {
return Promise.resolve(isGranted);
});
},
/**
* Remove the optional permissions
* @param {app.Permissions.Type} type - permission type
* @returns {Promise<boolean>} true if removed
* @memberOf app.Permissions
*/
remove: function(type) {
return _contains(type).then((contains) => {
if (contains) {
// try to remove permission
return chromep.permissions.remove({
permissions: type.permissions,
origins: type.origins,
});
} else {
return Promise.resolve(false);
}
}).then((removed) => {
if (removed) {
_setState(type, _STATE.notSet);
}
return Promise.resolve(removed);
});
},
};
})();