Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
321 lines
9.1 KiB
JavaScript
321 lines
9.1 KiB
JavaScript
'use strict';
|
|
/* global SettingsListener, Service */
|
|
|
|
(function(exports) {
|
|
|
|
const DEBUG = false;
|
|
var debug = function(str) {
|
|
//dump('usb_storage: ' + str + '\n');
|
|
console.log('usb_storage: ' + str);
|
|
};
|
|
|
|
/**
|
|
* UsbStorage listens to lock and unlock events and changes the
|
|
* setting which controls automount behavior of USB storage.
|
|
* Storage operates both on lock/unlock events, as well as the
|
|
* ums.enabled setting which is set in the settings app.
|
|
*
|
|
* Once storage has been enabled (which requires the phone to be
|
|
* unlocked), we want to keep it enabled, even if the phone is
|
|
* locked afterwards. However, unplugging the USB cable should
|
|
* then require being unlocked before enabling again.
|
|
*
|
|
* This also needs to work properly if the lockscreen is
|
|
* disabled.
|
|
*
|
|
* Some further potential wrinkles:
|
|
*
|
|
* - MTP can be enabled/disabled at will
|
|
* - UMS can be enabled at will, but requires a USB cable unplug
|
|
* to complete.
|
|
*
|
|
* @class UsbStorage
|
|
*/
|
|
function UsbStorage() {
|
|
// The AutoMounter already sets ums.mode to disabled at startup, so we
|
|
// just set our internal state. We shouldn't blindly call _setMode since
|
|
// when B2G is restarted, it only restarts the b2g executable, and
|
|
// vold isn't restarted. So we need to adapt to the initial conditions
|
|
// not set them.
|
|
this._mode = this.automounterDisable;
|
|
this.bindUsbStorageChanged = this._usbStorageChanged.bind(this);
|
|
}
|
|
|
|
UsbStorage.prototype = {
|
|
|
|
/**
|
|
* ums.mode setting value when the automounter is disabled.
|
|
* @memberof UsbStorage.prototype
|
|
* @type {Number}
|
|
*/
|
|
automounterDisable: 0,
|
|
|
|
/**
|
|
* ums.mode setting value when the automounter is enabled.
|
|
* @memberof UsbStorage.prototype
|
|
* @type {Number}
|
|
*/
|
|
automounterUmsEnable: 1,
|
|
|
|
/**
|
|
* ums.mode setting value when the automounter is disabled
|
|
* during the lock event.
|
|
* @memberof UsbStorage.prototype
|
|
* @type {Number}
|
|
*/
|
|
automounterDisableWhenUnplugged: 2,
|
|
|
|
/**
|
|
* ums.mode setting value when the automounter is in mtp modenot
|
|
* mcuy
|
|
* @memberof UsbStorage.prototype
|
|
* @type {Number}
|
|
*/
|
|
automounterMtpEnable: 3,
|
|
|
|
/**
|
|
* usb.transter setting value for ums mode
|
|
* @memberof UsbStorage.prototype
|
|
* @type {String}
|
|
*/
|
|
protocolUMS: '0',
|
|
|
|
/**
|
|
* ums.mode setting value for mtp mode
|
|
* @memberof UsbStorage.prototype
|
|
* @type {String}
|
|
*/
|
|
protocolMTP: '1',
|
|
|
|
/**
|
|
* The name of the setting to enable or disable USB storage.
|
|
* @memberof UsbStorage.prototype
|
|
* @type {String}
|
|
*/
|
|
umsEnabled: 'ums.enabled',
|
|
|
|
/**
|
|
* The name of the setting that defines automount behavior.
|
|
* @memberof UsbStorage.prototype
|
|
* @type {String}
|
|
*/
|
|
umsMode: 'ums.mode',
|
|
|
|
/**
|
|
* The name of the setting that defines usb transfer protocol.
|
|
* @memberof UsbStorage.prototype
|
|
* @type {String}
|
|
*/
|
|
usbTransferProtocol: 'usb.transfer',
|
|
|
|
/**
|
|
* The current value of USB tranfer mode.
|
|
* @memberof UsbStorage.prototype
|
|
* @type {String}
|
|
*/
|
|
_mode: undefined,
|
|
|
|
/**
|
|
* The current value of whether or not USB storage is enabled.
|
|
* @memberof UsbStorage.prototype
|
|
* @type {Boolean}
|
|
*/
|
|
_enabled: undefined,
|
|
|
|
/**
|
|
* The current value of current USB transfer protocol.
|
|
* @memberof UsbStorage.prototype
|
|
* @type {String}
|
|
*/
|
|
_protocol: undefined,
|
|
|
|
/**
|
|
* start usb storage
|
|
* @memberof UsbStorage.prototype
|
|
*/
|
|
start: function() {
|
|
DEBUG && debug('UsbStorage.start called');
|
|
window.addEventListener('lockscreen-appopened', this);
|
|
window.addEventListener('lockscreen-appclosed', this);
|
|
SettingsListener.observe(this.umsEnabled, false,
|
|
this.bindUsbStorageChanged);
|
|
},
|
|
|
|
/**
|
|
* stop usb storage
|
|
* @memberof UsbStorage.prototype
|
|
*/
|
|
stop: function() {
|
|
DEBUG && debug('UsbStorage.stop called');
|
|
window.removeEventListener('lockscreen-appopened', this);
|
|
window.removeEventListener('lockscreen-appclosed', this);
|
|
SettingsListener.unobserve(this.umsEnabled,
|
|
this.bindUsbStorageChanged);
|
|
},
|
|
|
|
/**
|
|
* Get a string version of the protocol.
|
|
* @memberof UsbStorage.prototype
|
|
* @param {Number} protocol current protocol denotes ums or mtp.
|
|
*/
|
|
|
|
_protocolStr: function(protocol) {
|
|
if (protocol == this.protocolUMS) {
|
|
return 'UMS';
|
|
}
|
|
if (protocol == this.protocolMTP) {
|
|
return 'MTP';
|
|
}
|
|
return '???';
|
|
},
|
|
|
|
/**
|
|
* Get a string version of the mode.
|
|
* @memberof UsbStorage.prototype
|
|
* @param {Number} mode for automounter.
|
|
*/
|
|
|
|
_modeStr: function(mode) {
|
|
if (mode == this.automounterDisable) {
|
|
return 'Disabled';
|
|
}
|
|
if (mode == this.automounterUmsEnable) {
|
|
return 'Enable-UMS';
|
|
}
|
|
if (mode == this.automounterDisableWhenUnplugged) {
|
|
return 'DisabledWhenUnplugged';
|
|
}
|
|
if (mode == this.automounterMtpEnable) {
|
|
return 'Enable-MTP';
|
|
}
|
|
return '???';
|
|
},
|
|
|
|
/**
|
|
* Handle USB storage enabled/disabled functionality.
|
|
* @memberof UsbStorage.prototype
|
|
* @param {Boolean} enabled enables/disables automounting.
|
|
*/
|
|
_usbStorageChanged: function(enabled) {
|
|
this._enabled = enabled;
|
|
DEBUG && debug('USB Storage Changed: ' + enabled);
|
|
this._getUsbProtocol();
|
|
},
|
|
|
|
/**
|
|
* Retrieve the protocol so that that we know whether MTP or UMS
|
|
* was enabled/disabled.
|
|
* @memberof UsbStorage.prototype
|
|
*/
|
|
_getUsbProtocol: function() {
|
|
var req = navigator.mozSettings.createLock()
|
|
.get(this.usbTransferProtocol);
|
|
req.onsuccess = function() {
|
|
var protocol = this._keyMigration(
|
|
req.result[this.usbTransferProtocol]);
|
|
this._protocol = protocol;
|
|
DEBUG && debug('_getUsbProtocol: ' + this._protocolStr(protocol));
|
|
this._updateMode();
|
|
}.bind(this);
|
|
},
|
|
|
|
/**
|
|
* Set mtp mode as default value.
|
|
* @memberof UsbStorage.prototype
|
|
* @param {Number} protocol current protocol denotes ums or mtp.
|
|
*/
|
|
_keyMigration: function(protocol) {
|
|
if (protocol === undefined || protocol === 'auto') {
|
|
protocol = this.protocolUMS;
|
|
var storages = navigator.getDeviceStorages('sdcard');
|
|
for (var i = 0; i < storages.length; i++) {
|
|
var storage = storages[i];
|
|
if (storage.storageName == 'sdcard') {
|
|
if (!storage.canBeShared) {
|
|
protocol = this.protocolMTP;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
var cset = {};
|
|
cset[this.usbTransferProtocol] = protocol;
|
|
navigator.mozSettings.createLock().set(cset);
|
|
}
|
|
return protocol;
|
|
},
|
|
|
|
/**
|
|
* Sets the mode to agree with the current state of things.
|
|
* @memberof UsbStorage.prototype
|
|
*/
|
|
_updateMode: function() {
|
|
if (typeof(this._enabled) == 'undefined') {
|
|
DEBUG && debug('_updateMode: _enabled not yet set - ignoring');
|
|
return;
|
|
}
|
|
|
|
var mode = this.automounterDisable;
|
|
|
|
if (this._enabled && !Service.query('locked')) {
|
|
// This is the only time that UMS or MTP should be enabled.
|
|
if (this._protocol == this.protocolMTP) {
|
|
mode = this.automounterMtpEnable;
|
|
} else {
|
|
mode = this.automounterUmsEnable;
|
|
}
|
|
} else {
|
|
// DisableWhenUnplugged can also be interpreted as EnableUntilUnplugged
|
|
// so we need to make sure that we only transition to
|
|
// automounterDisableWhenUnplugged if we're already in an enabled mode.
|
|
|
|
if (this._mode != this.automounterDisable &&
|
|
(this._protocol == this.protocolUMS || this._enabled)) {
|
|
// For UMS, we can't disable immediately, so we always defer
|
|
// to when the usb cable is unplugged.
|
|
// For MTP, if the user disables it, we can act immediately, but
|
|
// for screen lock we want to defer until the usb cable is unplugged.
|
|
mode = this.automounterDisableWhenUnplugged;
|
|
}
|
|
}
|
|
|
|
this._setMode(mode);
|
|
},
|
|
|
|
/**
|
|
* Sets the automount mode. This is split into a separate
|
|
* function to facilitate testing, and should only be called
|
|
* from _updateMode().
|
|
* @memberof UsbStorage.prototype
|
|
* @param {Number} val The value we are setting automount to.
|
|
* */
|
|
_setMode: function(mode) {
|
|
if (mode != this._mode) {
|
|
this._mode = mode;
|
|
var param = {};
|
|
param[this.umsMode] = mode;
|
|
SettingsListener.getSettingsLock().set(param);
|
|
}
|
|
},
|
|
|
|
|
|
/**
|
|
* General event handler interface.
|
|
* Updates the overlay with as we receive load events.
|
|
* @memberof UsbStorage.prototype
|
|
* @param {DOMEvent} evt The event.
|
|
*/
|
|
handleEvent: function(e) {
|
|
switch (e.type) {
|
|
case 'lockscreen-appopened':
|
|
case 'lockscreen-appclosed':
|
|
this._updateMode();
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
};
|
|
|
|
exports.UsbStorage = UsbStorage;
|
|
|
|
}(window));
|