Skip to content

Commit 15a7505

Browse files
Crash: Add initialize() method to CrashReportStorage
This CL introduces the `initialize()` method to the `CrashReportStorage` interface, introduced in [1] and [2]. This API gives an asynchronous gap for the implementation to initialize any relevant backing memory for the crash report storage. In the current Chromium implementation, this isn't used since the web APIs `set()` and `remove()` are backed by synchronous IPCs, but this method is required by the spec proposal to allow for more sophisticated mechanisms to be used for the backing memory. In Chromium, we are exploring taking advantage of this in https://crrev.com/c/6788146, where we're considering replacing `RenderFrameHostImpl::crash_storage_map_` with a shared memory region that spans the browser and renderer process. [1]: https://github.com/WICG/crash-reporting/blob/gh-pages/crashReport-explainer.md [2]: WICG/crash-reporting#37 R=creis, dcheng Bug: 400432195 Change-Id: I7ee67d29c6d4601b4d7ecb2d0b54dd24d0111e39
1 parent 37dc10d commit 15a7505

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed

reporting/crashReport-test.html

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
<!DOCTYPE html>
2+
<meta charset=utf-8>
3+
<title>CrashReportStorage API</title>
4+
<link rel="author" title="Dominic Farolino" href="mailto:[email protected]">
5+
<script src="/resources/testharness.js"></script>
6+
<script src="/resources/testharnessreport.js"></script>
7+
<body>
8+
<script>
9+
'use strict';
10+
11+
// These tests verify the throwing and promise rejection behavior of the
12+
// crashReport API. Each test is run in an iframe to ensure a fresh state.
13+
14+
promise_test(async t => {
15+
const iframe = document.createElement('iframe');
16+
const loadPromise = new Promise(resolve => iframe.onload = resolve);
17+
document.body.appendChild(iframe);
18+
await loadPromise;
19+
20+
const child_window = iframe.contentWindow;
21+
// Detach the document.
22+
iframe.remove();
23+
assert_equals(child_window.crashReport, null, "getter returns null");
24+
}, 'crashReport getter returns null in detached Documents');
25+
26+
promise_test(async t => {
27+
const iframe = document.createElement('iframe');
28+
const loadPromise = new Promise(resolve => iframe.onload = resolve);
29+
document.body.appendChild(iframe);
30+
await loadPromise;
31+
32+
// Cache the iframe's `crashReport` and other important things for the
33+
// following assertions.
34+
const child_window = iframe.contentWindow;
35+
const cachedCrashReport = child_window.crashReport;
36+
const cachedDOMExceptionConstructor = child_window.DOMException;
37+
38+
iframe.remove();
39+
const createRejection = cachedCrashReport.initialize(256);
40+
try {
41+
await createRejection;
42+
assert_unreached('createRejection must reject');
43+
} catch (e) {
44+
// Note that we should be using `promise_rejects_dom` here, but this does
45+
// not reliably work with detached Windows/event loops, so we have to run
46+
// some manual assertions here.
47+
assert_true(e instanceof cachedDOMExceptionConstructor,
48+
"promise rejects with DOMException");
49+
assert_equals(e.code, cachedDOMExceptionConstructor.INVALID_STATE_ERR,
50+
"promise rejects with InvalidStateError specifically");
51+
}
52+
}, 'crashReport initialize() throws InvalidStateError in detached Documents');
53+
54+
promise_test(async t => {
55+
const iframe = document.createElement('iframe');
56+
const loadPromise = new Promise(resolve => iframe.onload = resolve);
57+
document.body.appendChild(iframe);
58+
await loadPromise;
59+
60+
const child_window = iframe.contentWindow;
61+
const cachedCrashReport = child_window.crashReport;
62+
await cachedCrashReport.initialize(256);
63+
assert_throws_dom('InvalidStateError', child_window.DOMException, () => {
64+
// Detach the document.
65+
iframe.remove();
66+
cachedCrashReport.set('key', 'value');
67+
});
68+
}, 'crashReport.set() throws InvalidStateError in detached Documents');
69+
70+
promise_test(async t => {
71+
const iframe = document.createElement('iframe');
72+
const loadPromise = new Promise(resolve => iframe.onload = resolve);
73+
document.body.appendChild(iframe);
74+
await loadPromise;
75+
76+
const child_window = iframe.contentWindow;
77+
const cachedCrashReport = child_window.crashReport;
78+
await cachedCrashReport.initialize(256);
79+
cachedCrashReport.set('key', 'value');
80+
81+
assert_throws_dom('InvalidStateError', child_window.DOMException, () => {
82+
// Detach the document.
83+
iframe.remove();
84+
cachedCrashReport.remove('key', 'value');
85+
});
86+
}, 'crashReport.remove() throws InvalidStateError in detached Documents');
87+
88+
promise_test(async t => {
89+
const iframe = document.createElement('iframe');
90+
const loadPromise = new Promise(resolve => iframe.onload = resolve);
91+
document.body.appendChild(iframe);
92+
t.add_cleanup(() => iframe.remove());
93+
await loadPromise;
94+
95+
const child_window = iframe.contentWindow;
96+
// The maximum allowed size is 5MB.
97+
const large_size = 5 * 1024 * 1024 + 1;
98+
await promise_rejects_dom(t, 'NotAllowedError', child_window.DOMException,
99+
child_window.crashReport.initialize(large_size));
100+
}, 'crashReport.initialize() with size > 5MB rejects with NotAllowedError');
101+
102+
promise_test(async t => {
103+
const iframe = document.createElement('iframe');
104+
const loadPromise = new Promise(resolve => iframe.onload = resolve);
105+
document.body.appendChild(iframe);
106+
t.add_cleanup(() => iframe.remove());
107+
await loadPromise;
108+
109+
const child_window = iframe.contentWindow;
110+
child_window.crashReport.initialize(1024);
111+
await promise_rejects_dom(t, 'InvalidStateError', child_window.DOMException,
112+
child_window.crashReport.initialize(1024));
113+
}, 'Calling crashReport.initialize() a second time throws InvalidStateError');
114+
115+
promise_test(async t => {
116+
const iframe = document.createElement('iframe');
117+
const loadPromise = new Promise(resolve => iframe.onload = resolve);
118+
document.body.appendChild(iframe);
119+
t.add_cleanup(() => iframe.remove());
120+
await loadPromise;
121+
122+
const child_window = iframe.contentWindow;
123+
child_window.crashReport.initialize(1024);
124+
assert_throws_dom('InvalidStateError', child_window.DOMException, () => {
125+
child_window.crashReport.set('key', 'value');
126+
});
127+
}, 'crashReport.set() throws before initialize() resolves');
128+
129+
promise_test(async t => {
130+
const iframe = document.createElement('iframe');
131+
const loadPromise = new Promise(resolve => iframe.onload = resolve);
132+
document.body.appendChild(iframe);
133+
t.add_cleanup(() => iframe.remove());
134+
await loadPromise;
135+
136+
const child_window = iframe.contentWindow;
137+
await child_window.crashReport.initialize(1024);
138+
child_window.crashReport.set('key', 'value');
139+
child_window.crashReport.remove('key');
140+
}, 'crashReport.set() and .remove() succeed after initialize() resolves');
141+
</script>
142+
</body>

0 commit comments

Comments
 (0)