michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: * http://creativecommons.org/publicdomain/zero/1.0/ michael@0: */ michael@0: michael@0: /** michael@0: * Tests some basic jar channel functionality michael@0: */ michael@0: michael@0: michael@0: const {classes: Cc, michael@0: interfaces: Ci, michael@0: results: Cr, michael@0: Constructor: ctor michael@0: } = Components; michael@0: michael@0: const ios = Cc["@mozilla.org/network/io-service;1"]. michael@0: getService(Ci.nsIIOService); michael@0: const dirSvc = Cc["@mozilla.org/file/directory_service;1"]. michael@0: getService(Ci.nsIProperties); michael@0: const obs = Cc["@mozilla.org/observer-service;1"]. michael@0: getService(Ci.nsIObserverService); michael@0: michael@0: const nsIBinaryInputStream = ctor("@mozilla.org/binaryinputstream;1", michael@0: "nsIBinaryInputStream", michael@0: "setInputStream" michael@0: ); michael@0: michael@0: const fileBase = "test_bug637286.zip"; michael@0: const file = do_get_file("data/" + fileBase); michael@0: // on child we'll test with jar:remoteopenfile:// instead of jar:file:// michael@0: const jarBase = "jar:" + filePrefix + ios.newFileURI(file).spec + "!"; michael@0: const tmpDir = dirSvc.get("TmpD", Ci.nsIFile); michael@0: michael@0: function Listener(callback) { michael@0: this._callback = callback; michael@0: } michael@0: Listener.prototype = { michael@0: gotStartRequest: false, michael@0: available: -1, michael@0: gotStopRequest: false, michael@0: QueryInterface: function(iid) { michael@0: if (iid.equals(Ci.nsISupports) || michael@0: iid.equals(Ci.nsIRequestObserver)) michael@0: return this; michael@0: throw Cr.NS_ERROR_NO_INTERFACE; michael@0: }, michael@0: onDataAvailable: function(request, ctx, stream, offset, count) { michael@0: try { michael@0: this.available = stream.available(); michael@0: do_check_eq(this.available, count); michael@0: // Need to consume stream to avoid assertion michael@0: new nsIBinaryInputStream(stream).readBytes(count); michael@0: } michael@0: catch (ex) { michael@0: do_throw(ex); michael@0: } michael@0: }, michael@0: onStartRequest: function(request, ctx) { michael@0: this.gotStartRequest = true; michael@0: }, michael@0: onStopRequest: function(request, ctx) { michael@0: this.gotStopRequest = true; michael@0: if (this._callback) { michael@0: this._callback.call(null, this); michael@0: } michael@0: } michael@0: }; michael@0: michael@0: /** michael@0: * Basic reading test for asynchronously opened jar channel michael@0: */ michael@0: function testAsync() { michael@0: var uri = jarBase + "/inner40.zip"; michael@0: var chan = ios.newChannel(uri, null, null); michael@0: do_check_true(chan.contentLength < 0); michael@0: chan.asyncOpen(new Listener(function(l) { michael@0: do_check_true(chan.contentLength > 0); michael@0: do_check_true(l.gotStartRequest); michael@0: do_check_true(l.gotStopRequest); michael@0: do_check_eq(l.available, chan.contentLength); michael@0: michael@0: run_next_test(); michael@0: }), null); michael@0: } michael@0: michael@0: add_test(testAsync); michael@0: // Run same test again so we test the codepath for a zipcache hit michael@0: add_test(testAsync); michael@0: michael@0: michael@0: // In e10s child processes we don't currently support michael@0: // 1) synchronously opening jar files on parent michael@0: // 2) nested jar channels in e10s: (app:// doesn't use them). michael@0: // 3) we can't do file lock checks on android, so skip those tests too. michael@0: if (!inChild) { michael@0: michael@0: /** michael@0: * Basic reading test for synchronously opened jar channels michael@0: */ michael@0: add_test(function testSync() { michael@0: var uri = jarBase + "/inner40.zip"; michael@0: var chan = ios.newChannel(uri, null, null); michael@0: var stream = chan.open(); michael@0: do_check_true(chan.contentLength > 0); michael@0: do_check_eq(stream.available(), chan.contentLength); michael@0: stream.close(); michael@0: stream.close(); // should still not throw michael@0: michael@0: run_next_test(); michael@0: }); michael@0: michael@0: michael@0: /** michael@0: * Basic reading test for synchronously opened, nested jar channels michael@0: */ michael@0: add_test(function testSyncNested() { michael@0: var uri = "jar:" + jarBase + "/inner40.zip!/foo"; michael@0: var chan = ios.newChannel(uri, null, null); michael@0: var stream = chan.open(); michael@0: do_check_true(chan.contentLength > 0); michael@0: do_check_eq(stream.available(), chan.contentLength); michael@0: stream.close(); michael@0: stream.close(); // should still not throw michael@0: michael@0: run_next_test(); michael@0: }); michael@0: michael@0: /** michael@0: * Basic reading test for asynchronously opened, nested jar channels michael@0: */ michael@0: add_test(function testAsyncNested(next) { michael@0: var uri = "jar:" + jarBase + "/inner40.zip!/foo"; michael@0: var chan = ios.newChannel(uri, null, null); michael@0: chan.asyncOpen(new Listener(function(l) { michael@0: do_check_true(chan.contentLength > 0); michael@0: do_check_true(l.gotStartRequest); michael@0: do_check_true(l.gotStopRequest); michael@0: do_check_eq(l.available, chan.contentLength); michael@0: michael@0: run_next_test(); michael@0: }), null); michael@0: }); michael@0: michael@0: /** michael@0: * Verify that file locks are released when closing a synchronously michael@0: * opened jar channel stream michael@0: */ michael@0: add_test(function testSyncCloseUnlocks() { michael@0: var copy = tmpDir.clone(); michael@0: copy.append(fileBase); michael@0: file.copyTo(copy.parent, copy.leafName); michael@0: michael@0: var uri = "jar:" + ios.newFileURI(copy).spec + "!/inner40.zip"; michael@0: var chan = ios.newChannel(uri, null, null); michael@0: var stream = chan.open(); michael@0: do_check_true(chan.contentLength > 0); michael@0: stream.close(); michael@0: michael@0: // Drop any jar caches michael@0: obs.notifyObservers(null, "chrome-flush-caches", null); michael@0: michael@0: try { michael@0: copy.remove(false); michael@0: } michael@0: catch (ex) { michael@0: do_throw(ex); michael@0: } michael@0: michael@0: run_next_test(); michael@0: }); michael@0: michael@0: /** michael@0: * Verify that file locks are released when closing an asynchronously michael@0: * opened jar channel stream michael@0: */ michael@0: add_test(function testAsyncCloseUnlocks() { michael@0: var copy = tmpDir.clone(); michael@0: copy.append(fileBase); michael@0: file.copyTo(copy.parent, copy.leafName); michael@0: michael@0: var uri = "jar:" + ios.newFileURI(copy).spec + "!/inner40.zip"; michael@0: var chan = ios.newChannel(uri, null, null); michael@0: chan.asyncOpen(new Listener(function (l) { michael@0: do_check_true(chan.contentLength > 0); michael@0: michael@0: // Drop any jar caches michael@0: obs.notifyObservers(null, "chrome-flush-caches", null); michael@0: michael@0: try { michael@0: copy.remove(false); michael@0: } michael@0: catch (ex) { michael@0: do_throw(ex); michael@0: } michael@0: michael@0: run_next_test(); michael@0: }), null); michael@0: }); michael@0: michael@0: } // if !inChild michael@0: michael@0: function run_test() run_next_test();