|
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 |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 Cu.import("resource://gre/modules/Services.jsm"); |
|
6 |
|
7 const CRASH_URL = "http://example.com/browser/browser/base/content/test/plugins/plugin_crashCommentAndURL.html"; |
|
8 |
|
9 const SERVER_URL = "http://example.com/browser/toolkit/crashreporter/test/browser/crashreport.sjs"; |
|
10 |
|
11 function test() { |
|
12 // Crashing the plugin takes up a lot of time, so extend the test timeout. |
|
13 requestLongerTimeout(runs.length); |
|
14 waitForExplicitFinish(); |
|
15 setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED); |
|
16 |
|
17 // The test harness sets MOZ_CRASHREPORTER_NO_REPORT, which disables plugin |
|
18 // crash reports. This test needs them enabled. The test also needs a mock |
|
19 // report server, and fortunately one is already set up by toolkit/ |
|
20 // crashreporter/test/Makefile.in. Assign its URL to MOZ_CRASHREPORTER_URL, |
|
21 // which CrashSubmit.jsm uses as a server override. |
|
22 let env = Cc["@mozilla.org/process/environment;1"]. |
|
23 getService(Components.interfaces.nsIEnvironment); |
|
24 let noReport = env.get("MOZ_CRASHREPORTER_NO_REPORT"); |
|
25 let serverURL = env.get("MOZ_CRASHREPORTER_URL"); |
|
26 env.set("MOZ_CRASHREPORTER_NO_REPORT", ""); |
|
27 env.set("MOZ_CRASHREPORTER_URL", SERVER_URL); |
|
28 |
|
29 let tab = gBrowser.loadOneTab("about:blank", { inBackground: false }); |
|
30 let browser = gBrowser.getBrowserForTab(tab); |
|
31 browser.addEventListener("PluginCrashed", onCrash, false); |
|
32 Services.obs.addObserver(onSubmitStatus, "crash-report-status", false); |
|
33 |
|
34 registerCleanupFunction(function cleanUp() { |
|
35 env.set("MOZ_CRASHREPORTER_NO_REPORT", noReport); |
|
36 env.set("MOZ_CRASHREPORTER_URL", serverURL); |
|
37 gBrowser.selectedBrowser.removeEventListener("PluginCrashed", onCrash, |
|
38 false); |
|
39 Services.obs.removeObserver(onSubmitStatus, "crash-report-status"); |
|
40 gBrowser.removeCurrentTab(); |
|
41 }); |
|
42 |
|
43 doNextRun(); |
|
44 } |
|
45 |
|
46 let runs = [ |
|
47 { |
|
48 shouldSubmissionUIBeVisible: true, |
|
49 comment: "", |
|
50 urlOptIn: false, |
|
51 }, |
|
52 { |
|
53 shouldSubmissionUIBeVisible: true, |
|
54 comment: "a test comment", |
|
55 urlOptIn: true, |
|
56 }, |
|
57 { |
|
58 width: 300, |
|
59 height: 300, |
|
60 shouldSubmissionUIBeVisible: false, |
|
61 }, |
|
62 ]; |
|
63 |
|
64 let currentRun = null; |
|
65 |
|
66 function doNextRun() { |
|
67 try { |
|
68 if (!runs.length) { |
|
69 finish(); |
|
70 return; |
|
71 } |
|
72 currentRun = runs.shift(); |
|
73 let args = ["width", "height"].reduce(function (memo, arg) { |
|
74 if (arg in currentRun) |
|
75 memo[arg] = currentRun[arg]; |
|
76 return memo; |
|
77 }, {}); |
|
78 gBrowser.loadURI(CRASH_URL + "?" + |
|
79 encodeURIComponent(JSON.stringify(args))); |
|
80 // And now wait for the crash. |
|
81 } |
|
82 catch (err) { |
|
83 failWithException(err); |
|
84 finish(); |
|
85 } |
|
86 } |
|
87 |
|
88 function onCrash() { |
|
89 try { |
|
90 let plugin = gBrowser.contentDocument.getElementById("plugin"); |
|
91 let elt = gPluginHandler.getPluginUI.bind(gPluginHandler, plugin); |
|
92 let style = |
|
93 gBrowser.contentWindow.getComputedStyle(elt("pleaseSubmit")); |
|
94 is(style.display, |
|
95 currentRun.shouldSubmissionUIBeVisible ? "block" : "none", |
|
96 "Submission UI visibility should be correct"); |
|
97 if (!currentRun.shouldSubmissionUIBeVisible) { |
|
98 // Done with this run. |
|
99 doNextRun(); |
|
100 return; |
|
101 } |
|
102 elt("submitComment").value = currentRun.comment; |
|
103 elt("submitURLOptIn").checked = currentRun.urlOptIn; |
|
104 elt("submitButton").click(); |
|
105 // And now wait for the submission status notification. |
|
106 } |
|
107 catch (err) { |
|
108 failWithException(err); |
|
109 doNextRun(); |
|
110 } |
|
111 } |
|
112 |
|
113 function onSubmitStatus(subj, topic, data) { |
|
114 try { |
|
115 // Wait for success or failed, doesn't matter which. |
|
116 if (data != "success" && data != "failed") |
|
117 return; |
|
118 |
|
119 let extra = getPropertyBagValue(subj.QueryInterface(Ci.nsIPropertyBag), |
|
120 "extra"); |
|
121 ok(extra instanceof Ci.nsIPropertyBag, "Extra data should be property bag"); |
|
122 |
|
123 let val = getPropertyBagValue(extra, "PluginUserComment"); |
|
124 if (currentRun.comment) |
|
125 is(val, currentRun.comment, |
|
126 "Comment in extra data should match comment in textbox"); |
|
127 else |
|
128 ok(val === undefined, |
|
129 "Comment should be absent from extra data when textbox is empty"); |
|
130 |
|
131 val = getPropertyBagValue(extra, "PluginContentURL"); |
|
132 if (currentRun.urlOptIn) |
|
133 is(val, gBrowser.currentURI.spec, |
|
134 "URL in extra data should match browser URL when opt-in checked"); |
|
135 else |
|
136 ok(val === undefined, |
|
137 "URL should be absent from extra data when opt-in not checked"); |
|
138 } |
|
139 catch (err) { |
|
140 failWithException(err); |
|
141 } |
|
142 doNextRun(); |
|
143 } |
|
144 |
|
145 function getPropertyBagValue(bag, key) { |
|
146 try { |
|
147 var val = bag.getProperty(key); |
|
148 } |
|
149 catch (e if e.result == Cr.NS_ERROR_FAILURE) {} |
|
150 return val; |
|
151 } |
|
152 |
|
153 function failWithException(err) { |
|
154 ok(false, "Uncaught exception: " + err + "\n" + err.stack); |
|
155 } |