From cd678fb5916246f586b9345db7d8a3dfa6cd6236 Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Fri, 25 Jan 2019 15:25:54 -0500 Subject: [PATCH] chore(juggler): Roll Firefox to 120450a2 (#3842) This patch: - rebaselines C++ patchset atop of [Global Firefox Reformat](https://bugzilla.mozilla.org/show_bug.cgi?id=1511181) - rolls firefox to [120450a2](https://github.com/mozilla/gecko-dev/commit/120450a2c56c25e7c410a909192b5b9ad7b0dff2) - splits out preference installation step from Puppeteer-Firefox's `install.js` into a separate `puppeteer-firefox/misc/install-preferences.js`. This script is re-used to install preferences when run with a custom executable path. - fixes issue with ScrollbarManager that was re-injecting the same stylesheet multiple times --- experimental/juggler/FIREFOX_SHA | 2 +- experimental/juggler/README.md | 12 ++- ...ProgressListener2-onFrameLocationCha.patch | 77 +++++++++---------- .../juggler/src/content/ScrollbarManager.js | 13 +++- experimental/puppeteer-firefox/install.js | 65 +--------------- .../misc/install-preferences.js | 57 ++++++++++++++ .../puppeteer-firefox/misc/puppeteer.cfg | 3 + .../puppeteer-firefox/test/puppeteer.spec.js | 9 ++- 8 files changed, 127 insertions(+), 111 deletions(-) create mode 100644 experimental/puppeteer-firefox/misc/install-preferences.js diff --git a/experimental/juggler/FIREFOX_SHA b/experimental/juggler/FIREFOX_SHA index fcdfbe57..577133a2 100644 --- a/experimental/juggler/FIREFOX_SHA +++ b/experimental/juggler/FIREFOX_SHA @@ -1 +1 @@ -663997bb1dd09a5d93135b1707feb59024eb9db4 +120450a2c56c25e7c410a909192b5b9ad7b0dff2 diff --git a/experimental/juggler/README.md b/experimental/juggler/README.md index 3aede547..640b4633 100644 --- a/experimental/juggler/README.md +++ b/experimental/juggler/README.md @@ -25,10 +25,18 @@ SOURCE=$PWD bash scripts/fetch_firefox.sh ```bash cd firefox git am ../patches/* -ln -s $PWD/../src $PWD/testing/juggler ``` -4. Bootstrap host environment for Firefox build and compile firefox locally +4. Add Juggler to Firefox. NOTE: On Linux, symlinks work. On OSX, files have to be copied. + +```bash +# LINUX: +ln -s $PWD/../src $PWD/testing/juggler +# OSX: +cp -r $PWD/../src $PWD/testing/juggler +``` + +5. Bootstrap host environment for Firefox build and compile firefox locally ```bash # OPTIONAL - bootstrap host environment. diff --git a/experimental/juggler/patches/0001-Introduce-nsIWebProgressListener2-onFrameLocationCha.patch b/experimental/juggler/patches/0001-Introduce-nsIWebProgressListener2-onFrameLocationCha.patch index 0ecfa24d..648e43c1 100644 --- a/experimental/juggler/patches/0001-Introduce-nsIWebProgressListener2-onFrameLocationCha.patch +++ b/experimental/juggler/patches/0001-Introduce-nsIWebProgressListener2-onFrameLocationCha.patch @@ -1,26 +1,25 @@ -From fb96032ad20cb0dc5fbabe52a80d13d6e6808bb8 Mon Sep 17 00:00:00 2001 +From 5082f80b83290be204cd80124d292d1c563d2d13 Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov -Date: Tue, 27 Nov 2018 13:37:12 -0800 -Subject: [PATCH 1/3] Introduce nsIWebProgressListener2::onFrameLocationChange - event +Date: Thu, 24 Jan 2019 11:13:22 -0500 +Subject: [PATCH] Introduce nsIWebProgressListener2::onFrameLocationChange The event is fired when subframes commit navigation. Juggler uses this event to track same-document iframe navigations. --- docshell/base/nsDocShell.cpp | 1 + - .../statusfilter/nsBrowserStatusFilter.cpp | 10 ++++++++ - uriloader/base/nsDocLoader.cpp | 20 ++++++++++++++++ + .../statusfilter/nsBrowserStatusFilter.cpp | 8 +++++++ + uriloader/base/nsDocLoader.cpp | 18 +++++++++++++++ uriloader/base/nsDocLoader.h | 5 ++++ uriloader/base/nsIWebProgress.idl | 7 +++++- uriloader/base/nsIWebProgressListener2.idl | 23 +++++++++++++++++++ - 6 files changed, 65 insertions(+), 1 deletion(-) + 6 files changed, 61 insertions(+), 1 deletion(-) diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp -index ea0926732..3f738d39c 100644 +index ef2e46b33a..31471e3465 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp -@@ -1349,6 +1349,7 @@ nsDocShell::SetCurrentURI(nsIURI* aURI, nsIRequest* aRequest, - mLSHE->GetIsSubFrame(&isSubFrame); +@@ -1198,6 +1198,7 @@ bool nsDocShell::SetCurrentURI(nsIURI* aURI, nsIRequest* aRequest, + isSubFrame = mLSHE->GetIsSubFrame(); } + FireOnFrameLocationChange(this, aRequest, aURI, aLocationFlags); @@ -28,20 +27,18 @@ index ea0926732..3f738d39c 100644 /* * We don't want to send OnLocationChange notifications when diff --git a/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp b/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp -index c4d04dcc4..bb9e40cca 100644 +index 61fcfef258..264f9c1e61 100644 --- a/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp +++ b/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp -@@ -188,6 +188,16 @@ nsBrowserStatusFilter::OnStateChange(nsIWebProgress *aWebProgress, - return NS_OK; +@@ -170,6 +170,14 @@ nsBrowserStatusFilter::OnStateChange(nsIWebProgress *aWebProgress, + return NS_OK; } -+ +NS_IMETHODIMP +nsBrowserStatusFilter::OnFrameLocationChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, + nsIURI *aLocation, -+ uint32_t aFlags) -+{ ++ uint32_t aFlags) { + return NS_OK; +} + @@ -49,19 +46,17 @@ index c4d04dcc4..bb9e40cca 100644 nsBrowserStatusFilter::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, diff --git a/uriloader/base/nsDocLoader.cpp b/uriloader/base/nsDocLoader.cpp -index 524681ad8..68d3f976c 100644 +index a3bc24e603..67b3d3eaeb 100644 --- a/uriloader/base/nsDocLoader.cpp +++ b/uriloader/base/nsDocLoader.cpp -@@ -1330,6 +1330,26 @@ nsDocLoader::FireOnLocationChange(nsIWebProgress* aWebProgress, +@@ -1252,6 +1252,24 @@ void nsDocLoader::FireOnLocationChange(nsIWebProgress* aWebProgress, } } -+void -+nsDocLoader::FireOnFrameLocationChange(nsIWebProgress* aWebProgress, ++void nsDocLoader::FireOnFrameLocationChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, + nsIURI *aUri, -+ uint32_t aFlags) -+{ ++ uint32_t aFlags) { + NOTIFY_LISTENERS(nsIWebProgress::NOTIFY_FRAME_LOCATION, + nsCOMPtr listener2 = + do_QueryReferent(info.mWeakListener); @@ -76,27 +71,27 @@ index 524681ad8..68d3f976c 100644 + } +} + - void - nsDocLoader::FireOnStatusChange(nsIWebProgress* aWebProgress, - nsIRequest* aRequest, + void nsDocLoader::FireOnStatusChange(nsIWebProgress* aWebProgress, + nsIRequest* aRequest, nsresult aStatus, + const char16_t* aMessage) { diff --git a/uriloader/base/nsDocLoader.h b/uriloader/base/nsDocLoader.h -index 2dc1d0cae..05f8b2877 100644 +index 45f0d3d88e..7848878b70 100644 --- a/uriloader/base/nsDocLoader.h +++ b/uriloader/base/nsDocLoader.h -@@ -167,6 +167,11 @@ protected: - nsIURI *aUri, - uint32_t aFlags); +@@ -153,6 +153,11 @@ class nsDocLoader : public nsIDocumentLoader, + void FireOnLocationChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, + nsIURI* aUri, uint32_t aFlags); -+ void FireOnFrameLocationChange(nsIWebProgress* aWebProgress, -+ nsIRequest* aRequest, -+ nsIURI *aUri, -+ uint32_t aFlags); ++ void FireOnFrameLocationChange(nsIWebProgress* aWebProgress, ++ nsIRequest* aRequest, ++ nsIURI *aUri, ++ uint32_t aFlags); + - MOZ_MUST_USE bool RefreshAttempted(nsIWebProgress* aWebProgress, - nsIURI *aURI, - int32_t aDelay, + MOZ_MUST_USE bool RefreshAttempted(nsIWebProgress* aWebProgress, nsIURI* aURI, + int32_t aDelay, bool aSameURI); + diff --git a/uriloader/base/nsIWebProgress.idl b/uriloader/base/nsIWebProgress.idl -index 0549f32e1..3078e35d7 100644 +index 0549f32e1e..3078e35d7a 100644 --- a/uriloader/base/nsIWebProgress.idl +++ b/uriloader/base/nsIWebProgress.idl @@ -84,17 +84,22 @@ interface nsIWebProgress : nsISupports @@ -124,7 +119,7 @@ index 0549f32e1..3078e35d7 100644 /** * Registers a listener to receive web progress events. diff --git a/uriloader/base/nsIWebProgressListener2.idl b/uriloader/base/nsIWebProgressListener2.idl -index 87701f8d2..8a69e6b29 100644 +index 87701f8d2c..ae1aa85c01 100644 --- a/uriloader/base/nsIWebProgressListener2.idl +++ b/uriloader/base/nsIWebProgressListener2.idl @@ -66,4 +66,27 @@ interface nsIWebProgressListener2 : nsIWebProgressListener { @@ -151,9 +146,9 @@ index 87701f8d2..8a69e6b29 100644 + * the location has changed. + */ + void onFrameLocationChange(in nsIWebProgress aWebProgress, -+ in nsIRequest aRequest, -+ in nsIURI aLocation, -+ [optional] in unsigned long aFlags); ++ in nsIRequest aRequest, ++ in nsIURI aLocation, ++ [optional] in unsigned long aFlags); }; -- 2.19.0.605.g01d371f741-goog diff --git a/experimental/juggler/src/content/ScrollbarManager.js b/experimental/juggler/src/content/ScrollbarManager.js index 840b85d6..a54219fb 100644 --- a/experimental/juggler/src/content/ScrollbarManager.js +++ b/experimental/juggler/src/content/ScrollbarManager.js @@ -34,11 +34,12 @@ class ScrollbarManager { _setCustomScrollbars(customScrollbars) { if (this._customScrollbars === customScrollbars) return; + const windowUtils = this._docShell.domWindow.windowUtils; if (this._customScrollbars) - this._docShell.domWindow.windowUtils.removeSheet(this._customScrollbars, this._docShell.domWindow.AGENT_SHEET); + windowUtils.removeSheet(this._customScrollbars, windowUtils.AGENT_SHEET); this._customScrollbars = customScrollbars; if (this._customScrollbars) - this._docShell.domWindow.windowUtils.loadSheet(this._customScrollbars, this._docShell.domWindow.AGENT_SHEET); + windowUtils.loadSheet(this._customScrollbars, windowUtils.AGENT_SHEET); } dispose() { @@ -48,8 +49,12 @@ class ScrollbarManager { _onDOMWindowCreated(event) { const docShell = event.target.ownerGlobal.docShell; - if (this._customScrollbars) - docShell.domWindow.windowUtils.loadSheet(this._customScrollbars, docShell.domWindow.AGENT_SHEET); + if (docShell === this._docShell) + return; + const windowUtils = docShell.domWindow.windowUtils; + if (this._customScrollbars) { + windowUtils.loadSheet(this._customScrollbars, windowUtils.AGENT_SHEET); + } } } diff --git a/experimental/puppeteer-firefox/install.js b/experimental/puppeteer-firefox/install.js index cd2807c7..2ae9f414 100644 --- a/experimental/puppeteer-firefox/install.js +++ b/experimental/puppeteer-firefox/install.js @@ -15,10 +15,6 @@ */ -const os = require('os'); -const fs = require('fs'); -const path = require('path'); - // puppeteer-core should not install anything. if (require('./package.json').name === 'puppeteer-core') return; @@ -62,7 +58,10 @@ function onSuccess(localRevisions) { localRevisions = localRevisions.filter(revision => revision !== revisionInfo.revision); // Remove previous firefox revisions. const cleanupOldVersions = localRevisions.map(revision => browserFetcher.remove(revision)); - return Promise.all([...cleanupOldVersions, installFirefoxPreferences()]); + const installFirefoxPreferences = require('./misc/install-preferences'); + return Promise.all([...cleanupOldVersions, installFirefoxPreferences(revisionInfo.executablePath)]).then(() => { + console.log('Firefox preferences installed!'); + }); } /** @@ -95,59 +94,3 @@ function toMegabytes(bytes) { const mb = bytes / 1024 / 1024; return `${Math.round(mb * 10) / 10} Mb`; } - -// Install browser preferences after downloading and unpacking -// firefox instances. -// Based on: https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Enterprise_deployment_before_60#Configuration -async function installFirefoxPreferences() { - const revisionInfo = browserFetcher.revisionInfo(revision); - const firefoxFolder = path.dirname(revisionInfo.executablePath); - const {helper} = require('./lib/firefox/helper'); - const mkdirAsync = helper.promisify(fs.mkdir.bind(fs)); - - let prefPath = ''; - let configPath = ''; - if (os.platform() === 'darwin') { - prefPath = path.join(firefoxFolder, '..', 'Resources', 'defaults', 'pref'); - configPath = path.join(firefoxFolder, '..', 'Resources'); - } else if (os.platform() === 'linux') { - await mkdirAsync(path.join(firefoxFolder, 'browser', 'defaults')); - await mkdirAsync(path.join(firefoxFolder, 'browser', 'defaults', 'preferences')); - prefPath = path.join(firefoxFolder, 'browser', 'defaults', 'preferences'); - configPath = firefoxFolder; - } else if (os.platform() === 'win32') { - prefPath = path.join(firefoxFolder, 'defaults', 'pref'); - configPath = firefoxFolder; - } else { - throw new Error('Unsupported platform: ' + os.platform()); - } - - await Promise.all([ - copyFile({ - from: path.join(__dirname, 'misc', '00-puppeteer-prefs.js'), - to: path.join(prefPath, '00-puppeteer-prefs.js'), - }), - copyFile({ - from: path.join(__dirname, 'misc', 'puppeteer.cfg'), - to: path.join(configPath, 'puppeteer.cfg'), - }), - ]).then(() => { - console.log('Firefox preferences installed!'); - }); -} - -function copyFile({from, to}) { - var rd = fs.createReadStream(from); - var wr = fs.createWriteStream(to); - return new Promise(function(resolve, reject) { - rd.on('error', reject); - wr.on('error', reject); - wr.on('finish', resolve); - rd.pipe(wr); - }).catch(function(error) { - rd.destroy(); - wr.end(); - throw error; - }); -} - diff --git a/experimental/puppeteer-firefox/misc/install-preferences.js b/experimental/puppeteer-firefox/misc/install-preferences.js new file mode 100644 index 00000000..b00f5744 --- /dev/null +++ b/experimental/puppeteer-firefox/misc/install-preferences.js @@ -0,0 +1,57 @@ +const os = require('os'); +const fs = require('fs'); +const path = require('path'); + +// Install browser preferences after downloading and unpacking +// firefox instances. +// Based on: https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Enterprise_deployment_before_60#Configuration +async function installFirefoxPreferences(executablePath) { + const firefoxFolder = path.dirname(executablePath); + const {helper} = require('../lib/firefox/helper'); + const mkdirAsync = helper.promisify(fs.mkdir.bind(fs)); + + let prefPath = ''; + let configPath = ''; + if (os.platform() === 'darwin') { + prefPath = path.join(firefoxFolder, '..', 'Resources', 'defaults', 'pref'); + configPath = path.join(firefoxFolder, '..', 'Resources'); + } else if (os.platform() === 'linux') { + await mkdirAsync(path.join(firefoxFolder, 'browser', 'defaults')); + await mkdirAsync(path.join(firefoxFolder, 'browser', 'defaults', 'preferences')); + prefPath = path.join(firefoxFolder, 'browser', 'defaults', 'preferences'); + configPath = firefoxFolder; + } else if (os.platform() === 'win32') { + prefPath = path.join(firefoxFolder, 'defaults', 'pref'); + configPath = firefoxFolder; + } else { + throw new Error('Unsupported platform: ' + os.platform()); + } + + await Promise.all([ + copyFile({ + from: path.join(__dirname, '00-puppeteer-prefs.js'), + to: path.join(prefPath, '00-puppeteer-prefs.js'), + }), + copyFile({ + from: path.join(__dirname, 'puppeteer.cfg'), + to: path.join(configPath, 'puppeteer.cfg'), + }), + ]); +} + +function copyFile({from, to}) { + var rd = fs.createReadStream(from); + var wr = fs.createWriteStream(to); + return new Promise(function(resolve, reject) { + rd.on('error', reject); + wr.on('error', reject); + wr.on('finish', resolve); + rd.pipe(wr); + }).catch(function(error) { + rd.destroy(); + wr.end(); + throw error; + }); +} + +module.exports = installFirefoxPreferences; diff --git a/experimental/puppeteer-firefox/misc/puppeteer.cfg b/experimental/puppeteer-firefox/misc/puppeteer.cfg index 952da4df..234a5a32 100644 --- a/experimental/puppeteer-firefox/misc/puppeteer.cfg +++ b/experimental/puppeteer-firefox/misc/puppeteer.cfg @@ -137,6 +137,9 @@ pref( "http://%(server)s/dummy/discoveryURL", ); +pref("extensions.screenshots.disabled", true); +pref("extensions.screenshots.upload-disabled", true); + // Allow the application to have focus even it runs in the background pref("focusmanager.testmode", true); diff --git a/experimental/puppeteer-firefox/test/puppeteer.spec.js b/experimental/puppeteer-firefox/test/puppeteer.spec.js index 0cee7815..e3d644df 100644 --- a/experimental/puppeteer-firefox/test/puppeteer.spec.js +++ b/experimental/puppeteer-firefox/test/puppeteer.spec.js @@ -28,12 +28,17 @@ module.exports.addTests = ({testRunner, product, puppeteer}) => testRunner.descr toBeGolden: GoldenUtils.compare.bind(null, GOLDEN_DIR, OUTPUT_DIR) }); - beforeAll(state => { + + beforeAll(async state => { state.defaultBrowserOptions = { handleSIGINT: false, - dumpio: (process.env.DUMPIO || 'false').trim().toLowerCase() === 'true', + executablePath: product === 'chromium' ? process.env.CHROME : process.env.FFOX, + dumpio: !!process.env.DUMPIO, args: product === 'chromium' ? ['--no-sandbox'] : [], }; + if (product === 'firefox' && state.defaultBrowserOptions.executablePath) { + await require('../misc/install-preferences')(state.defaultBrowserOptions.executablePath); + } }); afterAll(state => { state.defaultBrowserOptions = undefined;