From 40c06747807c3b1681462cc64eb2ed44b7bd580f Mon Sep 17 00:00:00 2001 From: Neil Deakin Date: Mon, 2 Mar 2020 15:53:57 +0000 Subject: [PATCH] Bug 1616352, add a general out-of-process frames test that verifies the frame structure and that the right process is used for each frame. This will further be used for future tests, r=mconley Differential Revision: https://phabricator.services.mozilla.com/D63237 --HG-- extra : moz-landing-system : lando --- browser/base/content/moz.build | 3 + .../content/test/outOfProcess/.eslintrc.js | 7 + .../content/test/outOfProcess/browser.ini | 9 ++ .../browser_basic_outofprocess.js | 148 ++++++++++++++++++ .../content/test/outOfProcess/file_base.html | 5 + .../test/outOfProcess/file_frame1.html | 5 + .../test/outOfProcess/file_frame2.html | 11 ++ .../test/outOfProcess/file_innerframe.html | 3 + .../base/content/test/outOfProcess/head.js | 86 ++++++++++ browser/base/moz.build | 1 + 10 files changed, 278 insertions(+) create mode 100644 browser/base/content/test/outOfProcess/.eslintrc.js create mode 100644 browser/base/content/test/outOfProcess/browser.ini create mode 100644 browser/base/content/test/outOfProcess/browser_basic_outofprocess.js create mode 100644 browser/base/content/test/outOfProcess/file_base.html create mode 100644 browser/base/content/test/outOfProcess/file_frame1.html create mode 100644 browser/base/content/test/outOfProcess/file_frame2.html create mode 100644 browser/base/content/test/outOfProcess/file_innerframe.html create mode 100644 browser/base/content/test/outOfProcess/head.js diff --git a/browser/base/content/moz.build b/browser/base/content/moz.build index 1db5053992ef..6926c9e584f3 100644 --- a/browser/base/content/moz.build +++ b/browser/base/content/moz.build @@ -40,6 +40,9 @@ with Files("test/historySwipeAnimation/**"): with Files("test/keyboard/**"): BUG_COMPONENT = ("Firefox", "Keyboard Navigation") +with Files("test/outOfProcess/**"): + BUG_COMPONENT = ("Firefox", "General") + with Files("test/pageActions/**"): BUG_COMPONENT = ("Firefox", "Toolbars and Customization") diff --git a/browser/base/content/test/outOfProcess/.eslintrc.js b/browser/base/content/test/outOfProcess/.eslintrc.js new file mode 100644 index 000000000000..b1c842d8a6db --- /dev/null +++ b/browser/base/content/test/outOfProcess/.eslintrc.js @@ -0,0 +1,7 @@ +"use strict"; + +module.exports = { + "extends": [ + "plugin:mozilla/browser-test" + ] +}; diff --git a/browser/base/content/test/outOfProcess/browser.ini b/browser/base/content/test/outOfProcess/browser.ini new file mode 100644 index 000000000000..774e7bf5e0df --- /dev/null +++ b/browser/base/content/test/outOfProcess/browser.ini @@ -0,0 +1,9 @@ +[DEFAULT] +support-files = + file_base.html + file_frame1.html + file_frame2.html + file_innerframe.html + head.js + +[browser_basic_outofprocess.js] diff --git a/browser/base/content/test/outOfProcess/browser_basic_outofprocess.js b/browser/base/content/test/outOfProcess/browser_basic_outofprocess.js new file mode 100644 index 000000000000..2ab0b0d4ff03 --- /dev/null +++ b/browser/base/content/test/outOfProcess/browser_basic_outofprocess.js @@ -0,0 +1,148 @@ +/** + * Verify that the colors were set properly. This has the effect of + * verifying that the processes are assigned for child frames correctly. + */ +async function verifyBaseFrameStructure( + browsingContexts, + testname, + expectedHTML +) { + function checkColorAndText(bc, desc, expectedColor, expectedText) { + return SpecialPowers.spawn( + bc, + [expectedColor, expectedText, desc], + (expectedColorChild, expectedTextChild, descChild) => { + Assert.equal( + content.document.documentElement.style.backgroundColor, + expectedColorChild, + descChild + " color" + ); + Assert.equal( + content.document.getElementById("insertPoint").innerHTML, + expectedTextChild, + descChild + " text" + ); + } + ); + } + + let useOOPFrames = gFissionBrowser; + + is( + browsingContexts.length, + TOTAL_FRAME_COUNT, + "correct number of browsing contexts" + ); + await checkColorAndText( + browsingContexts[0], + testname + " base", + "white", + expectedHTML.next().value + ); + await checkColorAndText( + browsingContexts[1], + testname + " frame 1", + useOOPFrames ? "seashell" : "white", + expectedHTML.next().value + ); + await checkColorAndText( + browsingContexts[2], + testname + " frame 1-1", + useOOPFrames ? "seashell" : "white", + expectedHTML.next().value + ); + await checkColorAndText( + browsingContexts[3], + testname + " frame 2", + useOOPFrames ? "lightcyan" : "white", + expectedHTML.next().value + ); + await checkColorAndText( + browsingContexts[4], + testname + " frame 2-1", + useOOPFrames ? "seashell" : "white", + expectedHTML.next().value + ); + await checkColorAndText( + browsingContexts[5], + testname + " frame 2-2", + useOOPFrames ? "lightcyan" : "white", + expectedHTML.next().value + ); + await checkColorAndText( + browsingContexts[6], + testname + " frame 2-3", + useOOPFrames ? "palegreen" : "white", + expectedHTML.next().value + ); + await checkColorAndText( + browsingContexts[7], + testname + " frame 2-4", + "white", + expectedHTML.next().value + ); +} + +/** + * Test setting up all of the frames where a string of markup is passed + * to initChildFrames. + */ +add_task(async function test_subframes_string() { + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + OOP_BASE_PAGE_URI + ); + + const markup = "

Text

"; + + let browser = tab.linkedBrowser; + let browsingContexts = await initChildFrames(browser, markup); + + function* getExpectedHTML() { + for (let c = 1; c <= TOTAL_FRAME_COUNT; c++) { + yield markup; + } + ok(false, "Frame count does not match actual number of frames"); + } + await verifyBaseFrameStructure(browsingContexts, "string", getExpectedHTML()); + + BrowserTestUtils.removeTab(tab); +}); + +/** + * Test setting up all of the frames where a function that returns different markup + * is passed to initChildFrames. + */ +add_task(async function test_subframes_function() { + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + OOP_BASE_PAGE_URI + ); + let browser = tab.linkedBrowser; + + let counter = 0; + let browsingContexts = await initChildFrames(browser, function( + browsingContext + ) { + return "

Text " + ++counter + "

"; + }); + + is( + counter, + TOTAL_FRAME_COUNT, + "insert HTML function called the correct number of times" + ); + + function* getExpectedHTML() { + for (let c = 1; c <= TOTAL_FRAME_COUNT; c++) { + yield "

Text " + c + "

"; + } + } + await verifyBaseFrameStructure( + browsingContexts, + "function", + getExpectedHTML() + ); + + BrowserTestUtils.removeTab(tab); +}); diff --git a/browser/base/content/test/outOfProcess/file_base.html b/browser/base/content/test/outOfProcess/file_base.html new file mode 100644 index 000000000000..03f0731a8e57 --- /dev/null +++ b/browser/base/content/test/outOfProcess/file_base.html @@ -0,0 +1,5 @@ + +
+ + + diff --git a/browser/base/content/test/outOfProcess/file_frame1.html b/browser/base/content/test/outOfProcess/file_frame1.html new file mode 100644 index 000000000000..d39e970c0f07 --- /dev/null +++ b/browser/base/content/test/outOfProcess/file_frame1.html @@ -0,0 +1,5 @@ + +
+Same domain:
+ + diff --git a/browser/base/content/test/outOfProcess/file_frame2.html b/browser/base/content/test/outOfProcess/file_frame2.html new file mode 100644 index 000000000000..f0bc91ba20d6 --- /dev/null +++ b/browser/base/content/test/outOfProcess/file_frame2.html @@ -0,0 +1,11 @@ + +
+Same domain as to the left:
+ +Same domain as parent:
+ +Different domain:
+ +Same as top-level domain:
+ + diff --git a/browser/base/content/test/outOfProcess/file_innerframe.html b/browser/base/content/test/outOfProcess/file_innerframe.html new file mode 100644 index 000000000000..23c516232c62 --- /dev/null +++ b/browser/base/content/test/outOfProcess/file_innerframe.html @@ -0,0 +1,3 @@ + +
+ diff --git a/browser/base/content/test/outOfProcess/head.js b/browser/base/content/test/outOfProcess/head.js new file mode 100644 index 000000000000..f7035ca7d15a --- /dev/null +++ b/browser/base/content/test/outOfProcess/head.js @@ -0,0 +1,86 @@ +const OOP_BASE_PAGE_URI = + "https://example.com/browser/browser/base/content/test/outOfProcess/file_base.html"; + +// The number of frames and subframes that exist for the basic OOP test. If frames are +// modified within file_base.html, update this value. +const TOTAL_FRAME_COUNT = 8; + +// The frames are assigned different colors based on their process ids. If you add a +// frame you might need to add more colors to this list. +const FRAME_COLORS = ["white", "seashell", "lightcyan", "palegreen"]; + +/** + * Set up a set of child frames for the given browser for testing + * out of process frames. 'OOP_BASE_PAGE_URI' is the base page and subframes + * contain pages from the same or other domains. + * + * @param browser browser containing frame hierarchy to set up + * @param insertHTML HTML or function that returns what to insert into each frame + * @returns array of all browsing contexts in depth-first order + * + * This function adds a browsing context and process id label to each + * child subframe. It also sets the background color of each frame to + * different colors based on the process id. The browser_basic_outofprocess.js + * test verifies these colors to ensure that the frame/process hierarchy + * has been set up as expected. Colors are used to help people visualize + * the process setup. + * + * The insertHTML argument may be either a fixed string of HTML to insert + * into each subframe, or a function that returns the string to insert. The + * function takes one argument, the browsing context being processed. + */ +async function initChildFrames(browser, insertHTML) { + let colors = FRAME_COLORS.slice(); + let colorMap = new Map(); + + let browsingContexts = []; + + async function processBC(bc) { + browsingContexts.push(bc); + + let pid = bc.currentWindowGlobal.osPid; + let ident = "BrowsingContext: " + bc.id + "\nProcess: " + pid; + + let color = colorMap.get(pid); + if (!color) { + if (!colors.length) { + ok(false, "ran out of available colors"); + } + + color = colors.shift(); + colorMap.set(pid, color); + } + + let insertHTMLString = insertHTML; + if (typeof insertHTML == "function") { + insertHTMLString = insertHTML(bc); + } + + await SpecialPowers.spawn( + bc, + [ident, color, insertHTMLString], + (identChild, colorChild, insertHTMLChild) => { + let root = content.document.documentElement; + root.style = "background-color: " + colorChild; + + let pre = content.document.createElement("pre"); + pre.textContent = identChild; + root.insertBefore(pre, root.firstChild); + + if (insertHTMLChild) { + // eslint-disable-next-line no-unsanitized/property + content.document.getElementById( + "insertPoint" + ).innerHTML = insertHTMLChild; + } + } + ); + + for (let childBC of bc.children) { + await processBC(childBC); + } + } + await processBC(browser.browsingContext); + + return browsingContexts; +} diff --git a/browser/base/moz.build b/browser/base/moz.build index a2717f005969..fd886a934a4c 100644 --- a/browser/base/moz.build +++ b/browser/base/moz.build @@ -31,6 +31,7 @@ BROWSER_CHROME_MANIFESTS += [ 'content/test/keyboard/browser.ini', 'content/test/menubar/browser.ini', 'content/test/metaTags/browser.ini', + 'content/test/outOfProcess/browser.ini', 'content/test/pageActions/browser.ini', 'content/test/pageinfo/browser.ini', 'content/test/performance/browser.ini',