Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
123 lines
3.8 KiB
JavaScript
Executable file
123 lines
3.8 KiB
JavaScript
Executable file
'use strict';
|
|
|
|
/* global KeyboardHelper */
|
|
|
|
/**
|
|
* DynamicInputRegistry takes mozChromeEvent, check it, and save/remove the
|
|
* dynamic input definition to mozSettings.
|
|
*
|
|
* InputAppListSettings will then pick up the change in mozSettings and update
|
|
* the available layouts to all apps -- we do not communicate to it directly
|
|
* here.
|
|
*/
|
|
(function(exports) {
|
|
|
|
var DynamicInputRegistry = function() {
|
|
this.taskQueue = null;
|
|
};
|
|
|
|
DynamicInputRegistry.prototype.SETTING_KEY = 'keyboard.dynamic-inputs';
|
|
|
|
DynamicInputRegistry.prototype.start = function() {
|
|
this.taskQueue = Promise.resolve();
|
|
|
|
navigator.mozInputMethod.mgmt.addEventListener('addinputrequest', this);
|
|
navigator.mozInputMethod.mgmt.addEventListener('removeinputrequest', this);
|
|
};
|
|
|
|
DynamicInputRegistry.prototype.stop = function() {
|
|
this.taskQueue = null;
|
|
|
|
navigator.mozInputMethod.mgmt.removeEventListener('addinputrequest', this);
|
|
navigator.mozInputMethod.mgmt.removeEventListener('removeinputrequest', this);
|
|
};
|
|
|
|
DynamicInputRegistry.prototype.handleEvent = function(evt) {
|
|
var detail = evt.detail;
|
|
|
|
var p = this.taskQueue.then(function() {
|
|
return KeyboardHelper.inputAppList.getList();
|
|
}).then(function(inputApps) {
|
|
var inputApp = (inputApps.filter(function(inputApp) {
|
|
return (inputApp.domApp.manifestURL === detail.manifestURL);
|
|
}) || [])[0];
|
|
|
|
if (!inputApp) {
|
|
throw 'App not installed';
|
|
}
|
|
|
|
var currentInputs = inputApp.getInputs();
|
|
var currentInputIds = Object.keys(currentInputs);
|
|
if (currentInputIds.indexOf(detail.inputId) !== -1 &&
|
|
!currentInputs[detail.inputId].isDynamic) {
|
|
throw 'Can\'t mutate a statically declared input.';
|
|
}
|
|
|
|
return this._updateSetting(evt.type, detail)
|
|
.catch(function(e) {
|
|
console.error(e);
|
|
throw 'Error updating input.';
|
|
}.bind(this));
|
|
}.bind(this));
|
|
|
|
// Push the Promise queue to Gecko so it would respond to app accordingly.
|
|
detail.waitUntil(p);
|
|
|
|
// Tell Gecko this event is handled
|
|
evt.preventDefault();
|
|
|
|
this.taskQueue = p
|
|
.catch(function(e) {
|
|
console.error('DynamicInputRegistry rejects', e);
|
|
});
|
|
};
|
|
|
|
DynamicInputRegistry.prototype._updateSetting = function(evtType, detail) {
|
|
if (!navigator.mozSettings) {
|
|
throw new Error('DynamicInputRegistry: No mozSettings?');
|
|
}
|
|
|
|
// We must mutate the setting with the same lock there.
|
|
// As much as I want to use Promise interface, chainning callbacks in
|
|
// DOMRequest#then does not keep the lock (transaction) alive;
|
|
// we therefore have to work with EventTarget interface directly.
|
|
return new Promise(function(resolve, reject) {
|
|
var lock = navigator.mozSettings.createLock();
|
|
var getReq = lock.get(this.SETTING_KEY);
|
|
getReq.onerror = function() { reject(getReq.error); };
|
|
getReq.onsuccess = (function() {
|
|
var dynamicInputs = getReq.result[this.SETTING_KEY] || {};
|
|
switch (evtType) {
|
|
case 'addinputrequest':
|
|
if (!(detail.manifestURL in dynamicInputs)) {
|
|
dynamicInputs[detail.manifestURL] = {};
|
|
}
|
|
dynamicInputs[detail.manifestURL][detail.inputId] =
|
|
detail.inputManifest;
|
|
break;
|
|
|
|
case 'removeinputrequest':
|
|
if (!(detail.manifestURL in dynamicInputs)) {
|
|
break;
|
|
}
|
|
delete dynamicInputs[detail.manifestURL][detail.inputId];
|
|
if (Object.keys(dynamicInputs[detail.manifestURL]).length === 0) {
|
|
delete dynamicInputs[detail.manifestURL];
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
var toSet = {};
|
|
toSet[this.SETTING_KEY] = dynamicInputs;
|
|
|
|
var setReq = lock.set(toSet);
|
|
setReq.onerror = function() { reject(setReq.error); };
|
|
setReq.onsuccess = function() { resolve(); };
|
|
}).bind(this);
|
|
}.bind(this));
|
|
};
|
|
|
|
exports.DynamicInputRegistry = DynamicInputRegistry;
|
|
|
|
})(window);
|