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