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,124 @@
|
|||
/* global LazyLoader, DownloadFormatter, DownloadNotification, DownloadIcon,
|
||||
Service */
|
||||
'use strict';
|
||||
|
||||
/*
|
||||
* The DownloadManager listens for new downloads when they start. This
|
||||
* component will create notifications in the utility tray and will store them
|
||||
* Also it will create an icon in statusbar
|
||||
*
|
||||
* WARNING: This library will load these resources:
|
||||
*
|
||||
* - style/notifications/downloads.css
|
||||
* - shared/js/download/download_formatter.js
|
||||
* - js/download/download_notification.js
|
||||
*/
|
||||
/* exported DownloadManager */
|
||||
var DownloadManager = (function() {
|
||||
|
||||
var mozDownloadManager = navigator.mozDownloadManager;
|
||||
|
||||
if (!mozDownloadManager) {
|
||||
console.error('navigator.mozDownloadManager not supported!');
|
||||
return;
|
||||
}
|
||||
|
||||
// XXX bug 1097435 -- This is the only safe place we can call this for now.
|
||||
mozDownloadManager.clearAllDone();
|
||||
|
||||
// This object stores download notification objects by id
|
||||
var notifications = {};
|
||||
var started = false;
|
||||
var icon = null;
|
||||
|
||||
// Define and set our download start handler.
|
||||
function onDownloadStart(ev) {
|
||||
if (started) {
|
||||
createDownloadNotificationAndIcon(ev.download);
|
||||
} else {
|
||||
LazyLoader.load(['shared/js/download/download_formatter.js',
|
||||
'shared/js/download/download_ui.js',
|
||||
'shared/js/download/download_store.js',
|
||||
'shared/js/download/download_helper.js',
|
||||
'js/download/download_notification.js']).then(
|
||||
function() {
|
||||
started = true;
|
||||
createDownloadNotificationAndIcon(ev.download);
|
||||
window.addEventListener('notification-clicked', handleEvent);
|
||||
|
||||
// Bug 1102810 - After this bug gets fixed, this listener won't be
|
||||
// needed anymore. The API itself should handle startTime when killing
|
||||
// the process.
|
||||
window.addEventListener('will-shutdown', function onShutdown() {
|
||||
ev.download.pause();
|
||||
});
|
||||
})['catch'](function(err) { // XXX: workaround gjslint
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
mozDownloadManager.addEventListener('downloadstart', onDownloadStart);
|
||||
|
||||
function createDownloadNotificationAndIcon(download) {
|
||||
var id = DownloadFormatter.getUUID(download);
|
||||
notifications[id] = new DownloadNotification(download);
|
||||
loadDownloadIconIfNecessary().then(function() {
|
||||
icon.handle(download);
|
||||
});
|
||||
}
|
||||
|
||||
var downloadManager = {
|
||||
name: 'DownloadManager',
|
||||
incDownloads: function() {
|
||||
loadDownloadIconIfNecessary().then(function() {
|
||||
icon.incDownloads();
|
||||
})['catch'](function(err) { // XXX: workaround gjslint
|
||||
console.error(err);
|
||||
});
|
||||
},
|
||||
decDownloads: function() {
|
||||
loadDownloadIconIfNecessary().then(function() {
|
||||
icon.decDownloads();
|
||||
})['catch'](function(err) { // XXX: workaround gjslint
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function loadDownloadIconIfNecessary() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (!icon) {
|
||||
LazyLoader.load(['js/download_icon.js']).then(function() {
|
||||
icon = new DownloadIcon(this);
|
||||
icon.start();
|
||||
resolve();
|
||||
}.bind(this))['catch'](function(err) { // XXX: workaround gjslint
|
||||
console.error(err);
|
||||
reject();
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Service.register('incDownloads', downloadManager);
|
||||
Service.register('decDownloads', downloadManager);
|
||||
|
||||
function handleEvent(evt) {
|
||||
var detail = evt.detail;
|
||||
|
||||
if (!detail || !detail.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
var id = detail.id;
|
||||
var notification = notifications[id];
|
||||
|
||||
if (notification) {
|
||||
notification.onClick(function onRemovedNotification() {
|
||||
notifications[id] = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
}());
|
||||
|
|
@ -0,0 +1,266 @@
|
|||
/* global DownloadFormatter, NotificationScreen, DownloadUI, DownloadHelper,
|
||||
MozActivity, DownloadStore */
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* This is the constructor that will represent a download notification
|
||||
* in the system
|
||||
*
|
||||
* @param {Object} download object provided by the API.
|
||||
*/
|
||||
function DownloadNotification(download) {
|
||||
this.download = download;
|
||||
this.fileName = DownloadFormatter.getFileName(download);
|
||||
this.state = 'started';
|
||||
this.id = DownloadFormatter.getUUID(download);
|
||||
|
||||
// We have to listen for state changes
|
||||
this.listener = this._update.bind(this);
|
||||
this.download.addEventListener('statechange', this.listener);
|
||||
|
||||
if (download.state === 'started') {
|
||||
NotificationScreen.addNotification(this._getInfo());
|
||||
} else {
|
||||
// For adopted downloads, it is possible for the download to already be
|
||||
// completed.
|
||||
this._update();
|
||||
}
|
||||
}
|
||||
|
||||
DownloadNotification.prototype = {
|
||||
|
||||
/**
|
||||
* This method knows when the toaster should be displayed. Basically
|
||||
* the toaster shouldn't be displayed if the download state does not change
|
||||
* or the download was stopped by the user or because of connectivity lost
|
||||
*
|
||||
* @return {boolean} True whether the toaster should be displayed.
|
||||
*/
|
||||
_wontNotify: function dn_wontNotify() {
|
||||
var download = this.download;
|
||||
return this.state === download.state ||
|
||||
(download.state === 'stopped' && download.error === null);
|
||||
},
|
||||
|
||||
/**
|
||||
* It updates the notification when the download state changes.
|
||||
*/
|
||||
_update: function dn_update() {
|
||||
if (this.download.state === 'finalized') {
|
||||
// If the user delete the file, we will see this state and what we have to
|
||||
// do, is to remove the notification
|
||||
this._close();
|
||||
return;
|
||||
}
|
||||
var noNotify = this._wontNotify();
|
||||
this.state = this.download.state;
|
||||
if (this.download.state === 'stopped') {
|
||||
this._onStopped();
|
||||
}
|
||||
var info = this._getInfo();
|
||||
if (noNotify) {
|
||||
info.noNotify = true;
|
||||
}
|
||||
if (this.state === 'downloading') {
|
||||
info.mozbehavior = {
|
||||
noscreen: true
|
||||
};
|
||||
}
|
||||
NotificationScreen.addNotification(info);
|
||||
if (this.state === 'succeeded') {
|
||||
this._onSucceeded();
|
||||
}
|
||||
},
|
||||
|
||||
_onStopped: function dn_onStopped() {
|
||||
if (this.download.error !== null) {
|
||||
// Error attr will be not null when a download is stopped because
|
||||
// something failed
|
||||
this.state = 'failed';
|
||||
this._onError();
|
||||
} else if (!window.navigator.onLine) {
|
||||
// Remain downloading state when the connectivity was lost
|
||||
this.state = 'downloading';
|
||||
}
|
||||
},
|
||||
|
||||
_onError: function dn_onError() {
|
||||
var result = parseInt(this.download.error.message);
|
||||
|
||||
switch (result) {
|
||||
case DownloadUI.ERRORS.NO_MEMORY:
|
||||
DownloadUI.show(DownloadUI.TYPE.NO_MEMORY,
|
||||
this.download,
|
||||
true);
|
||||
break;
|
||||
case DownloadUI.ERRORS.NO_SDCARD:
|
||||
DownloadUI.show(DownloadUI.TYPE.NO_SDCARD,
|
||||
this.download,
|
||||
true);
|
||||
break;
|
||||
case DownloadUI.ERRORS.UNMOUNTED_SDCARD:
|
||||
DownloadUI.show(DownloadUI.TYPE.UNMOUNTED_SDCARD,
|
||||
this.download,
|
||||
true);
|
||||
break;
|
||||
|
||||
default:
|
||||
DownloadHelper.getFreeSpace((function gotFreeMemory(bytes) {
|
||||
if (bytes === 0) {
|
||||
DownloadUI.show(DownloadUI.TYPE.NO_MEMORY, this.download, true);
|
||||
}
|
||||
}).bind(this));
|
||||
}
|
||||
},
|
||||
|
||||
_onSucceeded: function dn_onSucceeded() {
|
||||
this._storeDownload(this.download);
|
||||
},
|
||||
|
||||
/**
|
||||
* This method stores complete downloads to share them with the download list
|
||||
* in settings app
|
||||
*
|
||||
* @param {Object} The download object provided by the API.
|
||||
*/
|
||||
_storeDownload: function dn_storeDownload(download) {
|
||||
var req = DownloadStore.add(download);
|
||||
|
||||
req.onsuccess = (function _storeDownloadOnSuccess(request) {
|
||||
// We don't care about any more state changes to the download.
|
||||
this.download.removeEventListener('statechange', this.listener);
|
||||
// Update the download object to the datastore representation.
|
||||
this.download = req.result;
|
||||
}).bind(this);
|
||||
|
||||
req.onerror = function _storeDownloadOnError(e) {
|
||||
console.error('Exception storing the download', download.id, '(',
|
||||
download.url, ').', e.target.error);
|
||||
};
|
||||
},
|
||||
|
||||
_ICONS_PATH: 'style/notifications/images/',
|
||||
|
||||
_ICONS_EXTENSION: '.png',
|
||||
|
||||
/**
|
||||
* It returns the icon depending on current state
|
||||
*
|
||||
* @return {String} Icon path.
|
||||
*/
|
||||
_getIcon: function dn_getIcon() {
|
||||
var icon = (this.state === 'downloading' ? 'downloading' : 'download');
|
||||
return this._ICONS_PATH + icon + this._ICONS_EXTENSION;
|
||||
},
|
||||
|
||||
/**
|
||||
* This method returns an object to update the notification composed by the
|
||||
* text, icon and type
|
||||
*
|
||||
* @return {object} Object descriptor.
|
||||
*/
|
||||
_getInfo: function dn_getInfo() {
|
||||
var state = this.state;
|
||||
var _ = navigator.mozL10n.get;
|
||||
|
||||
var info = {
|
||||
id: this.id,
|
||||
title: _('download_' + state),
|
||||
icon: this._getIcon(),
|
||||
type: 'download-notification-' + state
|
||||
};
|
||||
|
||||
if (state === 'downloading') {
|
||||
info.text = _('download_downloading_text_2', {
|
||||
name: this.fileName,
|
||||
percentage: DownloadFormatter.getPercentage(this.download)
|
||||
});
|
||||
} else {
|
||||
info.text = _('download_text_by_default', {
|
||||
name: this.fileName
|
||||
});
|
||||
}
|
||||
|
||||
return info;
|
||||
},
|
||||
|
||||
/**
|
||||
* Closes the notification
|
||||
*/
|
||||
_close: function dn_close() {
|
||||
NotificationScreen.removeNotification(this.id);
|
||||
this.onClose();
|
||||
},
|
||||
|
||||
/**
|
||||
* It performs the action when the notification is clicked by the user
|
||||
* depending on state:
|
||||
*
|
||||
* - 'downloading' -> launch the download list
|
||||
* - 'stopped' -> show confirmation to resume the download
|
||||
* - 'finalized' -> show confirmation to retry the download
|
||||
* - 'succeeded' -> open the downloaded file
|
||||
*
|
||||
* @param {function} Function that will be invoked when the notification
|
||||
* is removed from utility tray.
|
||||
*/
|
||||
onClick: function dn_onClick(done) {
|
||||
var cb = (function() {
|
||||
this._close();
|
||||
done();
|
||||
}).bind(this);
|
||||
|
||||
var req;
|
||||
|
||||
switch (this.download.state) {
|
||||
case 'downloading':
|
||||
// Launching settings > download list
|
||||
/* jshint nonew: false */
|
||||
new MozActivity({
|
||||
name: 'configure',
|
||||
data: {
|
||||
target: 'device',
|
||||
section: 'downloads'
|
||||
}
|
||||
});
|
||||
/* jshint nonew: true */
|
||||
|
||||
// The notification won't be removed when users open the download list
|
||||
// activity.onsuccess = activity.onerror = cb;
|
||||
|
||||
break;
|
||||
|
||||
case 'stopped':
|
||||
// Prompts the user if he wishes to retry the download
|
||||
req = DownloadUI.show(null, this.download, true);
|
||||
|
||||
// The notification won't be removed when users decline to resume
|
||||
// req.oncancel = cb;
|
||||
|
||||
req.onconfirm = this.download.resume.bind(this.download);
|
||||
|
||||
break;
|
||||
|
||||
case 'succeeded':
|
||||
// Attempts to open the file
|
||||
var download = this.download;
|
||||
req = DownloadHelper.open(download);
|
||||
|
||||
req.onerror = function req_onerror() {
|
||||
DownloadHelper.handlerError(req.error, download);
|
||||
};
|
||||
|
||||
cb();
|
||||
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* This method releases memory destroying the notification object
|
||||
*/
|
||||
onClose: function dn_onClose() {
|
||||
this.download.onstatechange = this.download = this.id = this.state = null;
|
||||
}
|
||||
};
|
||||
Loading…
Reference in a new issue