From e029a89c66e39e8809d8a87136c53c856eba5bfb Mon Sep 17 00:00:00 2001 From: "Abdoulaye O. Ly" Date: Thu, 15 Aug 2019 17:01:45 +0000 Subject: [PATCH] Bug 1559244 - Step 1: make BrowserTestUtils@crashBrowser function work with JSWindowActor. r=mconley Differential Revision: https://phabricator.services.mozilla.com/D37318 --HG-- extra : moz-landing-system : lando --- dom/base/ChromeUtils.cpp | 11 +++ dom/base/ChromeUtils.h | 3 + dom/chrome-webidl/ChromeUtils.webidl | 8 +++ .../BrowserTestUtils/BrowserTestUtils.jsm | 67 ++++++++++++------- .../BrowserTestUtilsChild.jsm | 34 ++++++++++ testing/mochitest/BrowserTestUtils/moz.build | 1 + 6 files changed, 100 insertions(+), 24 deletions(-) create mode 100644 testing/mochitest/BrowserTestUtils/BrowserTestUtilsChild.jsm diff --git a/dom/base/ChromeUtils.cpp b/dom/base/ChromeUtils.cpp index 1f4ee0aca83d..bf2bb0ee0707 100644 --- a/dom/base/ChromeUtils.cpp +++ b/dom/base/ChromeUtils.cpp @@ -14,6 +14,7 @@ #include "mozilla/Base64.h" #include "mozilla/BasePrincipal.h" #include "mozilla/CycleCollectedJSRuntime.h" +#include "mozilla/IntentionalCrash.h" #include "mozilla/PerformanceMetricsCollector.h" #include "mozilla/PerfStats.h" #include "mozilla/Preferences.h" @@ -1118,5 +1119,15 @@ bool ChromeUtils::IsClassifierBlockingErrorCode(GlobalObject& aGlobal, static_cast(aError)); } +/* static */ +void ChromeUtils::PrivateNoteIntentionalCrash(const GlobalObject& aGlobal, + ErrorResult& aError) { + if (XRE_IsContentProcess()) { + NoteIntentionalCrash("tab"); + return; + } + aError.Throw(NS_ERROR_NOT_IMPLEMENTED); +} + } // namespace dom } // namespace mozilla diff --git a/dom/base/ChromeUtils.h b/dom/base/ChromeUtils.h index e0ed875e9f67..153d71168985 100644 --- a/dom/base/ChromeUtils.h +++ b/dom/base/ChromeUtils.h @@ -192,6 +192,9 @@ class ChromeUtils { static bool IsClassifierBlockingErrorCode(GlobalObject& aGlobal, uint32_t aError); + + static void PrivateNoteIntentionalCrash(const GlobalObject& aGlobal, + ErrorResult& aError); }; } // namespace dom diff --git a/dom/chrome-webidl/ChromeUtils.webidl b/dom/chrome-webidl/ChromeUtils.webidl index b3c1c957fc4b..098d86841222 100644 --- a/dom/chrome-webidl/ChromeUtils.webidl +++ b/dom/chrome-webidl/ChromeUtils.webidl @@ -427,6 +427,14 @@ partial namespace ChromeUtils { [ChromeOnly] // aError should a nsresult. boolean isClassifierBlockingErrorCode(unsigned long aError); + + /** + * If leak detection is enabled, print a note to the leak log that this + * process will intentionally crash. This should be called only on child + * processes for testing purpose. + */ + [ChromeOnly, Throws] + void privateNoteIntentionalCrash(); }; /** diff --git a/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm b/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm index f9af40ef041c..83480c15edff 100644 --- a/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm +++ b/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm @@ -88,6 +88,23 @@ var gSynthesizeCompositionChangeCount = 0; const kAboutPageRegistrationContentScript = "chrome://mochikit/content/tests/BrowserTestUtils/content-about-page-utils.js"; +/** + * Create and register BrowserTestUtils Window Actor. + */ +function registerActor() { + let actorOptions = { + child: { + moduleURI: "resource://testing-common/BrowserTestUtilsChild.jsm", + }, + + allFrames: true, + includeChrome: true, + }; + ChromeUtils.registerWindowActor("BrowserTestUtils", actorOptions); +} + +registerActor(); + var BrowserTestUtils = { /** * Loads a page in a new tab, executes a Task and closes the tab. @@ -1660,26 +1677,6 @@ var BrowserTestUtils = { } } - // This frame script is injected into the remote browser, and used to - // intentionally crash the tab. We crash by using js-ctypes and dereferencing - // a bad pointer. The crash should happen immediately upon loading this - // frame script. - let frame_script = () => { - const { ctypes } = ChromeUtils.import( - "resource://gre/modules/ctypes.jsm" - ); - - let dies = function() { - privateNoteIntentionalCrash(); - let zero = new ctypes.intptr_t(8); - let badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t)); - badptr.contents; - }; - - dump("\nEt tu, Brute?\n"); - dies(); - }; - let expectedPromises = []; let crashCleanupPromise = new Promise((resolve, reject) => { @@ -1771,10 +1768,12 @@ var BrowserTestUtils = { ); } - // This frame script will crash the remote browser as soon as it is - // evaluated. - let mm = browser.messageManager; - mm.loadFrameScript("data:,(" + frame_script.toString() + ")();", false); + // Trigger crash by sending a message to BrowserTestUtils actor. + this.sendAsyncMessage( + browser.browsingContext, + "BrowserTestUtils:CrashFrame", + {} + ); await Promise.all(expectedPromises); @@ -2207,4 +2206,24 @@ var BrowserTestUtils = { } return tabbrowser.addTab(uri, params); }, + + /** + * Sends a message to a specific BrowserTestUtils window actor. + * @param aBrowsingContext + * The browsing context where the actor lives. + * @param {string} aMessageName + * Name of the message to be sent to the actor. + * @param {object} aMessageData + * Extra information to pass to the actor. + */ + async sendAsyncMessage(aBrowsingContext, aMessageName, aMessageData) { + if (!aBrowsingContext.currentWindowGlobal) { + await this.waitForCondition(() => aBrowsingContext.currentWindowGlobal); + } + + let actor = aBrowsingContext.currentWindowGlobal.getActor( + "BrowserTestUtils" + ); + actor.sendAsyncMessage(aMessageName, aMessageData); + }, }; diff --git a/testing/mochitest/BrowserTestUtils/BrowserTestUtilsChild.jsm b/testing/mochitest/BrowserTestUtils/BrowserTestUtilsChild.jsm new file mode 100644 index 000000000000..a42d81b308be --- /dev/null +++ b/testing/mochitest/BrowserTestUtils/BrowserTestUtilsChild.jsm @@ -0,0 +1,34 @@ +/* vim: set ts=2 sw=2 sts=2 et tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +var EXPORTED_SYMBOLS = ["BrowserTestUtilsChild"]; + +class BrowserTestUtilsChild extends JSWindowActorChild { + receiveMessage(aMessage) { + switch (aMessage.name) { + case "BrowserTestUtils:CrashFrame": { + // This is to intentionally crash the frame. + // We crash by using js-ctypes and dereferencing + // a bad pointer. The crash should happen immediately + // upon loading this frame script. + + const { ctypes } = ChromeUtils.import( + "resource://gre/modules/ctypes.jsm" + ); + + let dies = function() { + ChromeUtils.privateNoteIntentionalCrash(); + let zero = new ctypes.intptr_t(8); + let badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t)); + badptr.contents; + }; + + dump("\nEt tu, Brute?\n"); + dies(); + } + } + } +} diff --git a/testing/mochitest/BrowserTestUtils/moz.build b/testing/mochitest/BrowserTestUtils/moz.build index fc476e2b56b3..a5b450455a21 100644 --- a/testing/mochitest/BrowserTestUtils/moz.build +++ b/testing/mochitest/BrowserTestUtils/moz.build @@ -6,6 +6,7 @@ TESTING_JS_MODULES += [ 'BrowserTestUtils.jsm', + 'BrowserTestUtilsChild.jsm', 'content/content-task.js', 'ContentTask.jsm', 'ContentTaskUtils.jsm',