summaryrefslogtreecommitdiffstats
path: root/browser/components/sessionstore/test/browser_send_async_message_oom.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/sessionstore/test/browser_send_async_message_oom.js')
-rw-r--r--browser/components/sessionstore/test/browser_send_async_message_oom.js75
1 files changed, 75 insertions, 0 deletions
diff --git a/browser/components/sessionstore/test/browser_send_async_message_oom.js b/browser/components/sessionstore/test/browser_send_async_message_oom.js
new file mode 100644
index 0000000000..7e807f2fbd
--- /dev/null
+++ b/browser/components/sessionstore/test/browser_send_async_message_oom.js
@@ -0,0 +1,75 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+/* eslint-disable mozilla/no-arbitrary-setTimeout */
+
+const HISTOGRAM_NAME = "FX_SESSION_RESTORE_SEND_UPDATE_CAUSED_OOM";
+
+/**
+ * Test that an OOM in sendAsyncMessage in a framescript will be reported
+ * to Telemetry.
+ */
+
+add_setup(async function () {
+ Services.telemetry.canRecordExtended = true;
+});
+
+function frameScript() {
+ // Make send[A]syncMessage("SessionStore:update", ...) simulate OOM.
+ // Other operations are unaffected.
+ let mm = docShell.messageManager;
+
+ let wrap = function (original) {
+ return function (name, ...args) {
+ if (name != "SessionStore:update") {
+ return original(name, ...args);
+ }
+ throw new Components.Exception(
+ "Simulated OOM",
+ Cr.NS_ERROR_OUT_OF_MEMORY
+ );
+ };
+ };
+
+ mm.sendAsyncMessage = wrap(mm.sendAsyncMessage.bind(mm));
+ mm.sendSyncMessage = wrap(mm.sendSyncMessage.bind(mm));
+}
+
+add_task(async function () {
+ // Capture original state.
+ let snapshot = Services.telemetry.getHistogramById(HISTOGRAM_NAME).snapshot();
+
+ // Open a browser, configure it to cause OOM.
+ let newTab = BrowserTestUtils.addTab(gBrowser, "about:robots");
+ let browser = newTab.linkedBrowser;
+ await ContentTask.spawn(browser, null, frameScript);
+
+ let promiseReported = new Promise(resolve => {
+ browser.messageManager.addMessageListener("SessionStore:error", resolve);
+ });
+
+ // Attempt to flush. This should fail.
+ let promiseFlushed = TabStateFlusher.flush(browser);
+ promiseFlushed.then(success => {
+ if (success) {
+ throw new Error("Flush should have failed");
+ }
+ });
+
+ // The frame script should report an error.
+ await promiseReported;
+
+ // Give us some time to handle that error.
+ await new Promise(resolve => setTimeout(resolve, 10));
+
+ // By now, Telemetry should have been updated.
+ let snapshot2 = Services.telemetry
+ .getHistogramById(HISTOGRAM_NAME)
+ .snapshot();
+ gBrowser.removeTab(newTab);
+
+ Assert.ok(snapshot2.sum > snapshot.sum);
+});
+
+add_task(async function cleanup() {
+ Services.telemetry.canRecordExtended = false;
+});