Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
|
|
@ -0,0 +1,349 @@
|
|||
/*
|
||||
* TransferManager is responsible for:
|
||||
* - Handling system message 'activity' while there is an activity request
|
||||
* incoming. Then, it will post result/error to requesting app.
|
||||
* - Watching Bluetooth enabled/disabled state, then show/hide turn Bluetooth
|
||||
* on dialog.
|
||||
* - Watching default adapter existed or not. And will post error if we cannot
|
||||
* get default adapter.
|
||||
* - Watching 'devicePicked', 'cancelSelection' events from DevicePickerPanel
|
||||
* module. Then, do corrected activity service flow regarding user decision.
|
||||
*
|
||||
* @module BluetoothContext
|
||||
*/
|
||||
define(['require','modules/bluetooth/bluetooth_adapter_manager','modules/bluetooth/bluetooth_context','views/cannot_transfer_dialog','views/device_picker_panel','views/turn_bluetooth_on_dialog'],function(require) {
|
||||
'use strict';
|
||||
|
||||
var AdapterManager = require('modules/bluetooth/bluetooth_adapter_manager');
|
||||
var BtContext = require('modules/bluetooth/bluetooth_context');
|
||||
var CannotTransferDialog = require('views/cannot_transfer_dialog');
|
||||
var DevicePickerPanel = require('views/device_picker_panel');
|
||||
var TurnBluetoothOnDialog = require('views/turn_bluetooth_on_dialog');
|
||||
|
||||
var _debug = false;
|
||||
var debug = function() {};
|
||||
if (_debug) {
|
||||
debug = function bttm_debug(msg) {
|
||||
console.log('--> [TransferManager]: ' + msg);
|
||||
};
|
||||
}
|
||||
|
||||
var TransferManager = {
|
||||
/**
|
||||
* An instance to access activity source.
|
||||
*
|
||||
* @access private
|
||||
* @memberOf TransferManager
|
||||
* @type {Object}
|
||||
*/
|
||||
_activity: null,
|
||||
|
||||
/**
|
||||
* The init function only watches the 'activity' event from system message.
|
||||
*
|
||||
* @access private
|
||||
* @memberOf TransferManager
|
||||
*/
|
||||
init: function bttm_init() {
|
||||
// Watch 'activity' event from system message.
|
||||
this._watchActivityRequest();
|
||||
},
|
||||
|
||||
/**
|
||||
* Watch 'activity' event with callback function from system message.
|
||||
*
|
||||
* @access private
|
||||
* @memberOf TransferManager
|
||||
*/
|
||||
_watchActivityRequest: function bttm__watchActivityRequest() {
|
||||
navigator.mozSetMessageHandler('activity',
|
||||
this._activityHandler.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle 'activity' request. Then make decision to service the request or
|
||||
* reject it.
|
||||
*
|
||||
* @access private
|
||||
* @memberOf TransferManager
|
||||
* @param {Object} activityRequest
|
||||
*/
|
||||
_activityHandler: function bttm__activityHandler(activityRequest) {
|
||||
debug('_activityHandler(): activityRequest = ' +
|
||||
JSON.stringify(activityRequest));
|
||||
if (activityRequest.source.data.blobs &&
|
||||
activityRequest.source.data.blobs.length > 0) {
|
||||
this._activity = activityRequest;
|
||||
// Source info is enough to servie file transfer.
|
||||
// Start to init and observe Bluetooth relative modules.
|
||||
this._observeDefaultAdapter();
|
||||
this._observeBluetoothEnabled();
|
||||
this._watchEventFromDevicePicker();
|
||||
DevicePickerPanel.visible = true;
|
||||
} else {
|
||||
debug('_activityHandler(): Cannot transfer without blobs data!');
|
||||
this._cannotTransfer();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Show alert dialog. End the activity service while a user confirm to close
|
||||
* the dialog.
|
||||
*
|
||||
* @access private
|
||||
* @memberOf TransferManager
|
||||
*/
|
||||
_cannotTransfer: function bttm__cannotTransfer() {
|
||||
debug('_cannotTransfer(): show alert dialog!!');
|
||||
// show an alert with the overdue message
|
||||
if (!CannotTransferDialog.isVisible) {
|
||||
CannotTransferDialog.showConfirm().then(() => {
|
||||
// Post error with reason then end the activity service.
|
||||
this._endTransferWithReason('cancelled');
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Post result/error to end the activity service.
|
||||
*
|
||||
* @access private
|
||||
* @memberOf TransferManager
|
||||
*/
|
||||
_endTransferWithReason: function bttm__endTransferWithReason(reason) {
|
||||
debug('_endTransferWithReason(): reason = ' + reason);
|
||||
if (reason === 'transferred') {
|
||||
this._activity.postResult(reason);
|
||||
} else if (reason === 'cancelled') {
|
||||
this._activity.postError(reason);
|
||||
}
|
||||
|
||||
this._activity = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Observe and get default adapter from bluetooth adapter manager.
|
||||
*
|
||||
* @access private
|
||||
* @memberOf TransferManager
|
||||
*/
|
||||
_observeDefaultAdapter: function bttm__observeDefaultAdapter() {
|
||||
// Observe 'defaultAdapter' property for reaching default adapter.
|
||||
AdapterManager.observe('defaultAdapter',
|
||||
this._onDefaultAdapterChanged.bind(this));
|
||||
this._onDefaultAdapterChanged(AdapterManager.defaultAdapter);
|
||||
},
|
||||
|
||||
/**
|
||||
* Observe and get 'enabled' property from bluetooth context.
|
||||
*
|
||||
* @access private
|
||||
* @memberOf TransferManager
|
||||
*/
|
||||
_observeBluetoothEnabled: function bttm__observeBluetoothEnabled() {
|
||||
// Observe Bluetooth 'enabled' property from hardware side.
|
||||
BtContext.observe('enabled', this._onBluetoothEnabledChanged.bind(this));
|
||||
this._onBluetoothEnabledChanged(BtContext.enabled);
|
||||
},
|
||||
|
||||
/**
|
||||
* 'defaultAdapter' change event handler from adapter manager for
|
||||
* updating it immediately.
|
||||
*
|
||||
* @access private
|
||||
* @memberOf TransferManager
|
||||
* @param {Object} BluetoothAdapter newAdapter
|
||||
* @param {Object} BluetoothAdapter oldAdapter
|
||||
*/
|
||||
_onDefaultAdapterChanged:
|
||||
function bttm__onDefaultAdapterChanged(newAdapter, oldAdapter) {
|
||||
if (oldAdapter && (newAdapter === null)) {
|
||||
debug('_onDefaultAdapterChanged(): Can not get bluetooth adapter!');
|
||||
// Post error with reason then end the activity service.
|
||||
this._endTransferWithReason('cancelled');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 'enabled' change event handler from bluetooth context for
|
||||
* updating UI flow immediately.
|
||||
*
|
||||
* @access private
|
||||
* @memberOf TransferManager
|
||||
* @param {Boolean} enabled
|
||||
*/
|
||||
_onBluetoothEnabledChanged:
|
||||
function bttm__onBluetoothEnabledChanged(enabled) {
|
||||
debug('_onBluetoothEnabledChanged(): enabled = ' + enabled);
|
||||
switch(enabled) {
|
||||
case undefined:
|
||||
break;
|
||||
case true:
|
||||
// Close the confirmation dialog
|
||||
TurnBluetoothOnDialog.close();
|
||||
break;
|
||||
default:
|
||||
TurnBluetoothOnDialog.showConfirm().then((result) => {
|
||||
if (result === 'confirm') {
|
||||
// Turn Bluetooth on.
|
||||
BtContext.setEnabled(true);
|
||||
} else if (result === 'cancel') {
|
||||
// Post error with reason then end the activity service.
|
||||
this._endTransferWithReason('cancelled');
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Watch 'devicePicked', 'cancelSelection' event from device picker panel.
|
||||
*
|
||||
* @access private
|
||||
* @memberOf TransferManager
|
||||
*/
|
||||
_watchEventFromDevicePicker: function bttm__watchEventFromDevicePicker() {
|
||||
debug('_watchEventFromDevicePicker():');
|
||||
// Watch 'devicePicked' event for reaching device picked from user.
|
||||
DevicePickerPanel.addEventListener('devicePicked',
|
||||
this._onDevicePicked.bind(this));
|
||||
|
||||
// Watch 'cancelSelection' event for reaching cancel selection from user.
|
||||
DevicePickerPanel.addEventListener('cancelSelection',
|
||||
this._onCancelSelection.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* While the device is picked from user, let's send file(s) to the device.
|
||||
*
|
||||
* @access private
|
||||
* @memberOf TransferManager
|
||||
* @param {Object} event
|
||||
* @param {String} event.type - type of event name
|
||||
* @param {Object} event.detail - device info in this object
|
||||
* @param {Object} event.detail.address - address of device
|
||||
* @returns {Promise}
|
||||
*/
|
||||
_onDevicePicked: function bttm__onDevicePicked(event) {
|
||||
// Send file to the device via address
|
||||
debug('_onDevicePicked(): address of target device = ' +
|
||||
event.detail.address);
|
||||
var targetDeviceAddress = event.detail.address;
|
||||
var blobs = this._activity.source.data.blobs;
|
||||
|
||||
// Produce sending files schedule.
|
||||
// Then, post message to system app for sending files in queue.
|
||||
var schedule = this._produceSendingFilesSchedule(blobs.length);
|
||||
this._postMessageToSystemApp(schedule);
|
||||
|
||||
// Send each file via Bluetooth sendFile API
|
||||
return Promise.all(blobs.map((blob, index) => {
|
||||
/**
|
||||
* Check blob.name because sendFile() API needs a "file"
|
||||
* object and a filaname before sending it.
|
||||
* If there is no filename in the blob, Bluetooth API will give a
|
||||
* default name "Unknown.jpeg".
|
||||
* So Bluetooth app has to find out the name via device storage.
|
||||
*/
|
||||
if (blob.name) {
|
||||
// The blob has name, send the blob directly.
|
||||
debug('blob is sending with name...');
|
||||
return BtContext.sendFile(targetDeviceAddress, blob);
|
||||
} else if (this._activity.source.data.filepaths) {
|
||||
// The blob does not have name,
|
||||
// browse the file via filepath from storage again.
|
||||
var filepath = this._activity.source.data.filepaths[index];
|
||||
var storage = navigator.getDeviceStorage('sdcard');
|
||||
return storage.get(filepath).then((file) => {
|
||||
debug('getFile succeed & file is sending... file = ' + file);
|
||||
return BtContext.sendFile(targetDeviceAddress, file);
|
||||
}, (error) => {
|
||||
debug('getFile failed so that blob is sending without filename ' +
|
||||
error && error.name);
|
||||
return BtContext.sendFile(targetDeviceAddress, blob);
|
||||
});
|
||||
} else {
|
||||
// The blob does not have name and filepath,
|
||||
// pass the blob without name to send file directly.
|
||||
debug('no filepath to get from device storage ' +
|
||||
'so that blob is sending without filename');
|
||||
return BtContext.sendFile(targetDeviceAddress, blob);
|
||||
}
|
||||
})).then(() => {
|
||||
debug('all files are already sent out..');
|
||||
// Post result with reason then end the activity service.
|
||||
this._endTransferWithReason('transferred');
|
||||
return Promise.resolve();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* While a user cancel selection, let's post result then end the activity
|
||||
* service.
|
||||
*
|
||||
* @access private
|
||||
* @memberOf TransferManager
|
||||
* @param {Object} event
|
||||
* @param {String} event.type - type of event name
|
||||
*/
|
||||
_onCancelSelection: function bttm__onCancelSelection(event) {
|
||||
debug('_onCancelSelection(): cancel from user decision');
|
||||
// Post error with reason then end the activity service.
|
||||
this._endTransferWithReason('cancelled');
|
||||
},
|
||||
|
||||
/**
|
||||
* A function is a role producer.
|
||||
* Bluetooth app produce one message for each sending file request.
|
||||
*
|
||||
* @access private
|
||||
* @memberOf TransferManager
|
||||
* @param {Number} numberOfTasks - number of tasks
|
||||
* @returns {Object}
|
||||
*/
|
||||
_produceSendingFilesSchedule:
|
||||
function bttm__produceSendingFilesSchedule(numberOfTasks) {
|
||||
// Construct a object to contain info of sending files schedule.
|
||||
// And the info will be posted message to system app.
|
||||
// The result of send files will be displayed on notification.
|
||||
var sendingFilesSchedule = {
|
||||
numberOfFiles: numberOfTasks,
|
||||
numSuccessful: 0,
|
||||
numUnsuccessful: 0
|
||||
};
|
||||
return sendingFilesSchedule;
|
||||
},
|
||||
|
||||
/**
|
||||
* A function to do inner app communcation.
|
||||
*
|
||||
* @access private
|
||||
* @memberOf TransferManager
|
||||
* @param {Object} message - the info of sending files schedule
|
||||
*/
|
||||
_postMessageToSystemApp:
|
||||
function bttm__postMessageToSystemApp(message) {
|
||||
// Set up Inter-App Communications
|
||||
var getRequest = navigator.mozApps.getSelf();
|
||||
getRequest.onsuccess = (evt) => {
|
||||
var app = evt.target.result;
|
||||
// If IAC doesn't exist, just bail out.
|
||||
if (!app.connect) {
|
||||
debug('_postMessageToSystemApp(): Cannot post message since no ' +
|
||||
'connect function, message = ' + JSON.stringify(message));
|
||||
return;
|
||||
}
|
||||
// Post message object to system app.
|
||||
app.connect('bluetoothTransfercomms').then((ports) => {
|
||||
ports.forEach((port) => {
|
||||
port.postMessage(message);
|
||||
debug('_postMessageToSystemApp(): sending files schedule = ' +
|
||||
JSON.stringify(message));
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
return TransferManager;
|
||||
});
|
||||
Loading…
Reference in a new issue