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 Components.utils.import("resource://gre/modules/osfile.jsm");
3 function getEventDir() {
4 return OS.Path.join(do_get_tempdir().path, "crash-events");
5 }
7 /*
8 * Run an xpcshell subprocess and crash it.
9 *
10 * @param setup
11 * A string of JavaScript code to execute in the subprocess
12 * before crashing. If this is a function and not a string,
13 * it will have .toSource() called on it, and turned into
14 * a call to itself. (for programmer convenience)
15 * This code will be evaluted between crasher_subprocess_head.js
16 * and crasher_subprocess_tail.js, so it will have access
17 * to everything defined in crasher_subprocess_head.js,
18 * which includes "crashReporter", a variable holding
19 * the crash reporter service.
20 *
21 * @param callback
22 * A JavaScript function to be called after the subprocess
23 * crashes. It will be passed (minidump, extra), where
24 * minidump is an nsILocalFile of the minidump file produced,
25 * and extra is an object containing the key,value pairs from
26 * the .extra file.
27 *
28 * @param canReturnZero
29 * If true, the subprocess may return with a zero exit code.
30 * Certain types of crashes may not cause the process to
31 * exit with an error.
32 */
33 function do_crash(setup, callback, canReturnZero)
34 {
35 // get current process filename (xpcshell)
36 let ds = Components.classes["@mozilla.org/file/directory_service;1"]
37 .getService(Components.interfaces.nsIProperties);
38 let bin = ds.get("CurProcD", Components.interfaces.nsILocalFile);
39 bin.append("xpcshell");
40 if (!bin.exists()) {
41 bin.leafName = "xpcshell.exe";
42 do_check_true(bin.exists());
43 if (!bin.exists())
44 // weird, can't find xpcshell binary?
45 do_throw("Can't find xpcshell binary!");
46 }
47 // get Gre dir (GreD)
48 let greD = ds.get("GreD", Components.interfaces.nsILocalFile);
49 let headfile = do_get_file("crasher_subprocess_head.js");
50 let tailfile = do_get_file("crasher_subprocess_tail.js");
51 // run xpcshell -g GreD -f head -e "some setup code" -f tail
52 let process = Components.classes["@mozilla.org/process/util;1"]
53 .createInstance(Components.interfaces.nsIProcess);
54 process.init(bin);
55 let args = ['-g', greD.path,
56 '-f', headfile.path];
57 if (setup) {
58 if (typeof(setup) == "function")
59 // funky, but convenient
60 setup = "("+setup.toSource()+")();";
61 args.push('-e', setup);
62 }
63 args.push('-f', tailfile.path);
65 let env = Components.classes["@mozilla.org/process/environment;1"]
66 .getService(Components.interfaces.nsIEnvironment);
68 let crashD = do_get_tempdir();
69 crashD.append("crash-events");
70 if (!crashD.exists()) {
71 crashD.create(crashD.DIRECTORY_TYPE, 0700);
72 }
74 env.set("CRASHES_EVENTS_DIR", crashD.path);
76 try {
77 process.run(true, args, args.length);
78 }
79 catch(ex) {} // on Windows we exit with a -1 status when crashing.
80 finally {
81 env.set("CRASHES_EVENTS_DIR", "");
82 }
84 if (!canReturnZero) {
85 // should exit with an error (should have crashed)
86 do_check_neq(process.exitValue, 0);
87 }
89 handleMinidump(callback);
90 }
92 function handleMinidump(callback)
93 {
94 // find minidump
95 let minidump = null;
96 let en = do_get_tempdir().directoryEntries;
97 while (en.hasMoreElements()) {
98 let f = en.getNext().QueryInterface(Components.interfaces.nsILocalFile);
99 if (f.leafName.substr(-4) == ".dmp") {
100 minidump = f;
101 break;
102 }
103 }
105 if (minidump == null)
106 do_throw("No minidump found!");
108 let extrafile = minidump.clone();
109 extrafile.leafName = extrafile.leafName.slice(0, -4) + ".extra";
111 // Just in case, don't let these files linger.
112 do_register_cleanup(function() {
113 if (minidump.exists())
114 minidump.remove(false);
115 if (extrafile.exists())
116 extrafile.remove(false);
117 });
118 do_check_true(extrafile.exists());
119 let extra = parseKeyValuePairsFromFile(extrafile);
121 if (callback)
122 callback(minidump, extra);
124 if (minidump.exists())
125 minidump.remove(false);
126 if (extrafile.exists())
127 extrafile.remove(false);
128 }
130 function do_content_crash(setup, callback)
131 {
132 do_load_child_test_harness();
133 do_test_pending();
135 // Setting the minidump path won't work in the child, so we need to do
136 // that here.
137 let crashReporter =
138 Components.classes["@mozilla.org/toolkit/crash-reporter;1"]
139 .getService(Components.interfaces.nsICrashReporter);
140 crashReporter.minidumpPath = do_get_tempdir();
142 let headfile = do_get_file("../unit/crasher_subprocess_head.js");
143 let tailfile = do_get_file("../unit/crasher_subprocess_tail.js");
144 if (setup) {
145 if (typeof(setup) == "function")
146 // funky, but convenient
147 setup = "("+setup.toSource()+")();";
148 }
150 let handleCrash = function() {
151 try {
152 handleMinidump(callback);
153 } catch (x) {
154 do_report_unexpected_exception(x);
155 }
156 do_test_finished();
157 };
159 sendCommand("load(\"" + headfile.path.replace(/\\/g, "/") + "\");", function()
160 sendCommand(setup, function()
161 sendCommand("load(\"" + tailfile.path.replace(/\\/g, "/") + "\");",
162 function() do_execute_soon(handleCrash)
163 )
164 )
165 );
166 }
168 // Import binary APIs via js-ctypes.
169 Components.utils.import("resource://test/CrashTestUtils.jsm");
170 Components.utils.import("resource://gre/modules/KeyValueParser.jsm");