blob: cbd9aea73d1af9f9e7fdc7e53b961991e822b12f [file] [log] [blame]
// Copyright 2017 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.
/**
* Class to manage user preferences.
*/
class SwitchAccessPreferences {
/**
* @param {!SwitchAccessInterface} switchAccess
*/
constructor(switchAccess) {
/**
* SwitchAccess reference.
* @private {!SwitchAccessInterface}
*/
this.switchAccess_ = switchAccess;
/**
* User preferences, initially set to the default preference values.
* @private
*/
this.preferences_ = Object.assign({}, SAConstants.DEFAULT_PREFERENCES);
this.init_();
}
/**
* Store any changes from |chrome.storage.sync| to |this.preferences_|, if
* |this.preferences_| is not already set to that value.
*
* @param {!Object} storageChanges
* @param {string} areaName
* @private
*/
handleStorageChange_(storageChanges, areaName) {
let updatedPreferences = {};
for (const name of Object.keys(storageChanges)) {
if (this.preferences_[name] !== storageChanges[name].newValue) {
this.preferences_[name] = storageChanges[name].newValue;
updatedPreferences[name] = storageChanges[name].newValue;
}
}
if (Object.keys(updatedPreferences).length > 0)
this.switchAccess_.onPreferencesChanged(updatedPreferences);
}
/**
* @private
*/
init_() {
this.loadPreferences_();
chrome.storage.onChanged.addListener(this.handleStorageChange_.bind(this));
}
/**
* Asynchronously load the current preferences from |chrome.storage.sync| and
* store them in |this.preferences_|, if |this.preferences_| is not already
* set to that value.
*
* @private
*/
loadPreferences_() {
const defaultKeys = Object.values(SAConstants.Preference);
chrome.storage.sync.get(defaultKeys, (loadedPreferences) => {
let updatedPreferences = {};
for (const name of Object.keys(loadedPreferences)) {
if (this.preferences_[name] !== loadedPreferences[name]) {
this.preferences_[name] = loadedPreferences[name];
updatedPreferences[name] = loadedPreferences[name];
}
}
if (Object.keys(updatedPreferences).length > 0)
this.switchAccess_.onPreferencesChanged(updatedPreferences);
});
}
/**
* Set the value of the preference |name| to |value| in |chrome.storage.sync|.
* |this.preferences_| is not set until |handleStorageChange_|.
*
* @param {SAConstants.Preference} name
* @param {boolean|number} value
*/
setPreference(name, value) {
let preference = {};
preference[name] = value;
chrome.storage.sync.set(preference);
}
/**
* Get the boolean value for the given name. Will throw a type error if the
* value associated with |name| is not a boolean, or undefined.
*
* @param {SAConstants.Preference} name
* @return {boolean}
*/
getBooleanPreference(name) {
const value = this.preferences_[name];
if (typeof value === 'boolean')
return value;
else
throw new TypeError('No value of boolean type named \'' + name + '\'');
}
/**
* Get the number value for the given name. Will throw a type error if the
* value associated with |name| is not a number, or undefined.
*
* @param {SAConstants.Preference} name
* @return {number}
*/
getNumberPreference(name) {
const value = this.getNumberPreferenceIfDefined(name);
if (!value)
throw new TypeError('No value of number type named \'' + name + '\'');
return value;
}
/**
* Get the number value for the given name, or |null| if the value is not a
* number or does not exist.
*
* @param {SAConstants.Preference} name
* @return {number|null}
*/
getNumberPreferenceIfDefined(name) {
const value = this.preferences_[name];
if (typeof value === 'number')
return value;
return null;
}
/**
* Returns true if |keyCode| is already used to run a command from the
* keyboard.
*
* @param {number} keyCode
* @return {boolean}
*/
keyCodeIsUsed(keyCode) {
for (const command of this.switchAccess_.getCommands()) {
if (keyCode === this.preferences_[command])
return true;
}
return false;
}
}