Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
266 lines
7.4 KiB
JavaScript
Executable file
266 lines
7.4 KiB
JavaScript
Executable file
/* 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;
|
|
}
|
|
};
|