Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* Any copyright is dedicated to the Public Domain.
4 * http://creativecommons.org/publicdomain/zero/1.0/ */
6 /**
7 * This file tests signature extraction using Windows Authenticode APIs of
8 * downloaded files.
9 */
11 ////////////////////////////////////////////////////////////////////////////////
12 //// Globals
14 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
16 XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
17 "resource://gre/modules/FileUtils.jsm");
18 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
19 "resource://gre/modules/NetUtil.jsm");
20 XPCOMUtils.defineLazyModuleGetter(this, "Promise",
21 "resource://gre/modules/Promise.jsm");
22 XPCOMUtils.defineLazyModuleGetter(this, "Task",
23 "resource://gre/modules/Task.jsm");
25 const BackgroundFileSaverOutputStream = Components.Constructor(
26 "@mozilla.org/network/background-file-saver;1?mode=outputstream",
27 "nsIBackgroundFileSaver");
29 const StringInputStream = Components.Constructor(
30 "@mozilla.org/io/string-input-stream;1",
31 "nsIStringInputStream",
32 "setData");
34 const TEST_FILE_NAME_1 = "test-backgroundfilesaver-1.txt";
36 /**
37 * Returns a reference to a temporary file. If the file is then created, it
38 * will be removed when tests in this file finish.
39 */
40 function getTempFile(aLeafName) {
41 let file = FileUtils.getFile("TmpD", [aLeafName]);
42 do_register_cleanup(function GTF_cleanup() {
43 if (file.exists()) {
44 file.remove(false);
45 }
46 });
47 return file;
48 }
50 /**
51 * Waits for the given saver object to complete.
52 *
53 * @param aSaver
54 * The saver, with the output stream or a stream listener implementation.
55 * @param aOnTargetChangeFn
56 * Optional callback invoked with the target file name when it changes.
57 *
58 * @return {Promise}
59 * @resolves When onSaveComplete is called with a success code.
60 * @rejects With an exception, if onSaveComplete is called with a failure code.
61 */
62 function promiseSaverComplete(aSaver, aOnTargetChangeFn) {
63 let deferred = Promise.defer();
64 aSaver.observer = {
65 onTargetChange: function BFSO_onSaveComplete(aSaver, aTarget)
66 {
67 if (aOnTargetChangeFn) {
68 aOnTargetChangeFn(aTarget);
69 }
70 },
71 onSaveComplete: function BFSO_onSaveComplete(aSaver, aStatus)
72 {
73 if (Components.isSuccessCode(aStatus)) {
74 deferred.resolve();
75 } else {
76 deferred.reject(new Components.Exception("Saver failed.", aStatus));
77 }
78 },
79 };
80 return deferred.promise;
81 }
83 /**
84 * Feeds a string to a BackgroundFileSaverOutputStream.
85 *
86 * @param aSourceString
87 * The source data to copy.
88 * @param aSaverOutputStream
89 * The BackgroundFileSaverOutputStream to feed.
90 * @param aCloseWhenDone
91 * If true, the output stream will be closed when the copy finishes.
92 *
93 * @return {Promise}
94 * @resolves When the copy completes with a success code.
95 * @rejects With an exception, if the copy fails.
96 */
97 function promiseCopyToSaver(aSourceString, aSaverOutputStream, aCloseWhenDone) {
98 let deferred = Promise.defer();
99 let inputStream = new StringInputStream(aSourceString, aSourceString.length);
100 let copier = Cc["@mozilla.org/network/async-stream-copier;1"]
101 .createInstance(Ci.nsIAsyncStreamCopier);
102 copier.init(inputStream, aSaverOutputStream, null, false, true, 0x8000, true,
103 aCloseWhenDone);
104 copier.asyncCopy({
105 onStartRequest: function () { },
106 onStopRequest: function (aRequest, aContext, aStatusCode)
107 {
108 if (Components.isSuccessCode(aStatusCode)) {
109 deferred.resolve();
110 } else {
111 deferred.reject(new Components.Exception(aResult));
112 }
113 },
114 }, null);
115 return deferred.promise;
116 }
118 let gStillRunning = true;
120 ////////////////////////////////////////////////////////////////////////////////
121 //// Tests
123 function run_test()
124 {
125 run_next_test();
126 }
128 add_task(function test_setup()
129 {
130 // Wait 10 minutes, that is half of the external xpcshell timeout.
131 do_timeout(10 * 60 * 1000, function() {
132 if (gStillRunning) {
133 do_throw("Test timed out.");
134 }
135 })
136 });
138 function readFileToString(aFilename) {
139 let f = do_get_file(aFilename);
140 let stream = Cc["@mozilla.org/network/file-input-stream;1"]
141 .createInstance(Ci.nsIFileInputStream);
142 stream.init(f, -1, 0, 0);
143 let buf = NetUtil.readInputStreamToString(stream, stream.available());
144 return buf;
145 }
147 add_task(function test_signature()
148 {
149 // Check that we get a signature if the saver is finished on Windows.
150 let destFile = getTempFile(TEST_FILE_NAME_1);
152 let data = readFileToString("data/signed_win.exe");
153 let saver = new BackgroundFileSaverOutputStream();
154 let completionPromise = promiseSaverComplete(saver);
156 try {
157 let signatureInfo = saver.signatureInfo;
158 do_throw("Can't get signature before saver is complete.");
159 } catch (ex if ex.result == Cr.NS_ERROR_NOT_AVAILABLE) { }
161 saver.enableSignatureInfo();
162 saver.setTarget(destFile, false);
163 yield promiseCopyToSaver(data, saver, true);
165 saver.finish(Cr.NS_OK);
166 yield completionPromise;
168 // There's only one nsIX509CertList in the signature array.
169 do_check_eq(1, saver.signatureInfo.length);
170 let certLists = saver.signatureInfo.enumerate();
171 do_check_true(certLists.hasMoreElements());
172 let certList = certLists.getNext().QueryInterface(Ci.nsIX509CertList);
173 do_check_false(certLists.hasMoreElements());
175 // Check that it has 3 certs.
176 let certs = certList.getEnumerator();
177 do_check_true(certs.hasMoreElements());
178 let signer = certs.getNext().QueryInterface(Ci.nsIX509Cert);
179 do_check_true(certs.hasMoreElements());
180 let issuer = certs.getNext().QueryInterface(Ci.nsIX509Cert);
181 do_check_true(certs.hasMoreElements());
182 let root = certs.getNext().QueryInterface(Ci.nsIX509Cert);
183 do_check_false(certs.hasMoreElements());
185 // Check that the certs have expected strings attached.
186 let organization = "Microsoft Corporation";
187 do_check_eq("Microsoft Corporation", signer.commonName);
188 do_check_eq(organization, signer.organization);
189 do_check_eq("Copyright (c) 2002 Microsoft Corp.", signer.organizationalUnit);
191 do_check_eq("Microsoft Code Signing PCA", issuer.commonName);
192 do_check_eq(organization, issuer.organization);
193 do_check_eq("Copyright (c) 2000 Microsoft Corp.", issuer.organizationalUnit);
195 do_check_eq("Microsoft Root Authority", root.commonName);
196 do_check_false(root.organization);
197 do_check_eq("Copyright (c) 1997 Microsoft Corp.", root.organizationalUnit);
199 // Clean up.
200 destFile.remove(false);
201 });
203 add_task(function test_teardown()
204 {
205 gStillRunning = false;
206 });