1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
3
* You can obtain one at http://mozilla.org/MPL/2.0/ */
6
const BUFFER_SIZE = 5 * 1024 * 1024;
9
const DTA = require("api");
10
const {TimerManager} = require("support/timers");
11
const Prefs = require("preferences");
13
const Timers = new TimerManager();
15
function Decompressor(download, callback) {
16
this.download = download;
17
this.callback = callback;
18
this.to = download.destinationLocalFile.clone();
19
this.from = download.tmpFile.clone();
22
this._outStream = new Instances.FileOutputStream(this.to, 0x04 | 0x08, Prefs.getExt('permissions', 384), 0);
23
this.outStream = new Instances.BinaryOutputStream(
24
new Instances.BufferedOutputStream(this._outStream, BUFFER_SIZE));
26
let converter = Cc["@mozilla.org/streamconv;1?from=" + download.compression + "&to=uncompressed"]
27
.createInstance(Ci.nsIStreamConverter);
29
converter.asyncConvertData(
36
let chan = Services.oldio.newChannelFromURI(Services.io.newFileURI(this.from));
37
chan.asyncOpen(converter, null);
42
this.outStream.close();
44
if (this.to.exists()) {
45
this.to.remove(false);
47
if (this.from.exists()) {
48
this.from.remove(false);
54
log(LOG_ERROR, "err. :p", ex);
55
callback.call(download, ex);
58
Decompressor.prototype = {
60
QueryInterface: function(iid) {
61
if (iid.equals(Ci.nsISupports) || iid.equals(Ci.nsIStreamListener) || iid.equals(Ci.nsIRequestObserver)) {
64
throw Cr.NS_ERROR_NO_INTERFACE;
66
onStartRequest: function(r, c) {
67
this._timer = Timers.createRepeating(FREQ, this.download.invalidate, this.download);
69
onStopRequest: function(request, c) {
70
Timers.killTimer(this._timer);
71
// important, or else we don't write out the last buffer and truncate too early. :p
72
this.outStream.flush();
74
this._outStream.QueryInterface(Ci.nsISeekableStream).setEOF();
80
this.outStream.close();
81
this._outStream.close();
85
log(LOG_ERROR, "Decompressor: close streams", ex);
89
this.to.remove(false);
92
// no-op: we're already bad :p
96
this.from.remove(false);
99
log(LOG_ERROR, "Failed to remove tmpFile", ex);
101
this.callback.call(this.download, this.exception);
103
onDataAvailable: function(request, c, stream, offset, count) {
105
var binStream = new Instances.BinaryInputStream(stream);
106
if (count !== this.outStream.write(binStream.readBytes(count), count)) {
107
throw new Exception("Failed to write!");
109
this.download.partialSize = offset;
113
var reason = 0x804b0002; // NS_BINDING_ABORTED;
114
request.cancel(reason);
119
exports.Decompressor = Decompressor;