From a2325ca47440691a1cf041f609a69230e55a0d2c Mon Sep 17 00:00:00 2001 From: Tooru Fujisawa Date: Wed, 10 Jul 2024 06:16:52 +0000 Subject: [PATCH] Bug 1081542 - Part 1: Add nsIBrowserDOMWindow.OPEN_NEWTAB_FOREGROUND. r=smaug,geckoview-reviewers,Gijs,amejiamarmol,tabbrowser-reviewers,dao Given meta/ctrl key should use browser.tabs.loadInBackground pref instead of browser.tabs.loadDivertedInBackground pref, the existing nsIBrowserDOMWindow.OPEN_NEWTAB behavior doesn't match the requirement. Add dedicate flag for "open in foreground tab" to make it controllable from nsWindowWatcher::IsWindowOpenLocationModified. Differential Revision: https://phabricator.services.mozilla.com/D201929 --- browser/base/content/browser.js | 34 +++++++++++-------- .../tabs/browser_openURI_background.js | 1 + dom/interfaces/base/nsIBrowserDOMWindow.idl | 7 ++++ dom/ipc/ContentParent.cpp | 5 ++- .../org/mozilla/geckoview/GeckoSession.java | 4 +-- .../geckoview/GeckoViewNavigation.sys.mjs | 3 +- netwerk/ipc/DocumentLoadListener.cpp | 6 ++-- xpfe/appshell/nsContentTreeOwner.cpp | 1 + 8 files changed, 41 insertions(+), 20 deletions(-) diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 2683a42070a0..7a683aeb6419 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -4409,7 +4409,7 @@ nsBrowserAccess.prototype = { aName = "", aCsp = null, aSkipLoad = false, - aForceLoadInBackground = false + aWhere = undefined ) { let win, needToFocusWin; @@ -4432,11 +4432,20 @@ nsBrowserAccess.prototype = { return win.gBrowser.selectedBrowser; } - let loadInBackground = Services.prefs.getBoolPref( - "browser.tabs.loadDivertedInBackground" - ); - if (aForceLoadInBackground) { + // OPEN_NEWTAB_BACKGROUND and OPEN_NEWTAB_FOREGROUND are used by + // `window.open` with modifiers. + // The last case is OPEN_NEWTAB, which is used by: + // * a link with `target="_blank"`, without modifiers + // * `window.open` without features, without modifiers + let loadInBackground; + if (aWhere === Ci.nsIBrowserDOMWindow.OPEN_NEWTAB_BACKGROUND) { loadInBackground = true; + } else if (aWhere === Ci.nsIBrowserDOMWindow.OPEN_NEWTAB_FOREGROUND) { + loadInBackground = false; + } else { + loadInBackground = Services.prefs.getBoolPref( + "browser.tabs.loadDivertedInBackground" + ); } let tab = win.gBrowser.addTab(aURI ? aURI.spec : "about:blank", { @@ -4614,7 +4623,8 @@ nsBrowserAccess.prototype = { break; } case Ci.nsIBrowserDOMWindow.OPEN_NEWTAB: - case Ci.nsIBrowserDOMWindow.OPEN_NEWTAB_BACKGROUND: { + case Ci.nsIBrowserDOMWindow.OPEN_NEWTAB_BACKGROUND: + case Ci.nsIBrowserDOMWindow.OPEN_NEWTAB_FOREGROUND: { // If we have an opener, that means that the caller is expecting access // to the nsIDOMWindow of the opened tab right away. For e10s windows, // this means forcing the newly opened browser to be non-remote so that @@ -4625,8 +4635,6 @@ nsBrowserAccess.prototype = { let userContextId = aOpenWindowInfo ? aOpenWindowInfo.originAttributes.userContextId : openingUserContextId; - let forceLoadInBackground = - aWhere == Ci.nsIBrowserDOMWindow.OPEN_NEWTAB_BACKGROUND; let browser = this._openURIInNewTab( aURI, referrerInfo, @@ -4640,7 +4648,7 @@ nsBrowserAccess.prototype = { "", aCsp, aSkipLoad, - forceLoadInBackground + aWhere ); if (browser) { browsingContext = browser.browsingContext; @@ -4741,7 +4749,8 @@ nsBrowserAccess.prototype = { if ( aWhere != Ci.nsIBrowserDOMWindow.OPEN_NEWTAB && - aWhere != Ci.nsIBrowserDOMWindow.OPEN_NEWTAB_BACKGROUND + aWhere != Ci.nsIBrowserDOMWindow.OPEN_NEWTAB_BACKGROUND && + aWhere != Ci.nsIBrowserDOMWindow.OPEN_NEWTAB_FOREGROUND ) { dump("Error: openURIInFrame can only open in new tabs or print"); return null; @@ -4755,9 +4764,6 @@ nsBrowserAccess.prototype = { ? aParams.openerOriginAttributes.userContextId : Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID; - var forceLoadInBackground = - aWhere == Ci.nsIBrowserDOMWindow.OPEN_NEWTAB_BACKGROUND; - return this._openURIInNewTab( aURI, aParams.referrerInfo, @@ -4771,7 +4777,7 @@ nsBrowserAccess.prototype = { aName, aParams.csp, aSkipLoad, - forceLoadInBackground + aWhere ); }, diff --git a/browser/components/tabbrowser/test/browser/tabs/browser_openURI_background.js b/browser/components/tabbrowser/test/browser/tabs/browser_openURI_background.js index 53e329dd8f79..d36a42302635 100644 --- a/browser/components/tabbrowser/test/browser/tabs/browser_openURI_background.js +++ b/browser/components/tabbrowser/test/browser/tabs/browser_openURI_background.js @@ -11,6 +11,7 @@ add_task(async function () { const tests = [ ["OPEN_NEWTAB", false], ["OPEN_NEWTAB_BACKGROUND", true], + ["OPEN_NEWTAB_FOREGROUND", false], ]; for (const [flag, isBackground] of tests) { diff --git a/dom/interfaces/base/nsIBrowserDOMWindow.idl b/dom/interfaces/base/nsIBrowserDOMWindow.idl index d9b8e540b1da..0a71a20a8b60 100644 --- a/dom/interfaces/base/nsIBrowserDOMWindow.idl +++ b/dom/interfaces/base/nsIBrowserDOMWindow.idl @@ -65,6 +65,8 @@ interface nsIBrowserDOMWindow : nsISupports /** * Open in a new content tab in the toplevel browser window corresponding to * this nsIBrowserDOMWindow. + * Use browser.tabs.loadDivertedInBackground pref to choose whether to open + * in background tab or foreground tab. */ const short OPEN_NEWTAB = 3; /** @@ -76,6 +78,11 @@ interface nsIBrowserDOMWindow : nsISupports * corresponding to this nsIBrowserDOMWindow. */ const short OPEN_NEWTAB_BACKGROUND = 5; + /** + * Open in a new foreground content tab in the toplevel browser window + * corresponding to this nsIBrowserDOMWindow. + */ + const short OPEN_NEWTAB_FOREGROUND = 6; /** * Values for createContentWindow's and openURI's aFlags parameter. diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 066cc9849d3b..83ec6c7bd235 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -5317,6 +5317,7 @@ mozilla::ipc::IPCResult ContentParent::CommonCreateWindow( MOZ_ASSERT(aOpenLocation == nsIBrowserDOMWindow::OPEN_NEWTAB || aOpenLocation == nsIBrowserDOMWindow::OPEN_NEWTAB_BACKGROUND || + aOpenLocation == nsIBrowserDOMWindow::OPEN_NEWTAB_FOREGROUND || aOpenLocation == nsIBrowserDOMWindow::OPEN_NEWWINDOW || aOpenLocation == nsIBrowserDOMWindow::OPEN_PRINT_BROWSER); @@ -5327,6 +5328,7 @@ mozilla::ipc::IPCResult ContentParent::CommonCreateWindow( if (aOpenLocation == nsIBrowserDOMWindow::OPEN_NEWTAB || aOpenLocation == nsIBrowserDOMWindow::OPEN_NEWTAB_BACKGROUND || + aOpenLocation == nsIBrowserDOMWindow::OPEN_NEWTAB_FOREGROUND || aOpenLocation == nsIBrowserDOMWindow::OPEN_PRINT_BROWSER) { RefPtr openerElement = do_QueryObject(frame); @@ -5558,7 +5560,8 @@ mozilla::ipc::IPCResult ContentParent::RecvCreateWindow( // do this work. MOZ_ALWAYS_SUCCEEDS(newBC->SetHasSiblings( openLocation == nsIBrowserDOMWindow::OPEN_NEWTAB || - openLocation == nsIBrowserDOMWindow::OPEN_NEWTAB_BACKGROUND)); + openLocation == nsIBrowserDOMWindow::OPEN_NEWTAB_BACKGROUND || + openLocation == nsIBrowserDOMWindow::OPEN_NEWTAB_FOREGROUND)); newTab->SwapFrameScriptsFrom(cwi.frameScripts()); newTab->MaybeShowFrame(); diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java index a5f0238fef14..dff6b053ba59 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java @@ -650,7 +650,7 @@ public class GeckoSession { case 0: // OPEN_DEFAULTWINDOW case 1: // OPEN_CURRENTWINDOW return NavigationDelegate.TARGET_WINDOW_CURRENT; - default: // OPEN_NEWWINDOW, OPEN_NEWTAB, OPEN_NEWTAB_BACKGROUND + default: // OPEN_NEWWINDOW, OPEN_NEWTAB, OPEN_NEWTAB_BACKGROUND, OPEN_NEWTAB_FOREGROUND return NavigationDelegate.TARGET_WINDOW_NEW; } } @@ -5027,7 +5027,7 @@ public class GeckoSession { case 0: // OPEN_DEFAULTWINDOW case 1: // OPEN_CURRENTWINDOW return TARGET_WINDOW_CURRENT; - default: // OPEN_NEWWINDOW, OPEN_NEWTAB, OPEN_NEWTAB_BACKGROUND + default: // OPEN_NEWWINDOW, OPEN_NEWTAB, OPEN_NEWTAB_BACKGROUND, OPEN_NEWTAB_FOREGROUND return TARGET_WINDOW_NEW; } } diff --git a/mobile/shared/modules/geckoview/GeckoViewNavigation.sys.mjs b/mobile/shared/modules/geckoview/GeckoViewNavigation.sys.mjs index 8fc2466eab96..10ed8940c50f 100644 --- a/mobile/shared/modules/geckoview/GeckoViewNavigation.sys.mjs +++ b/mobile/shared/modules/geckoview/GeckoViewNavigation.sys.mjs @@ -556,7 +556,8 @@ export class GeckoViewNavigation extends GeckoViewModule { if ( where === Ci.nsIBrowserDOMWindow.OPEN_NEWWINDOW || where === Ci.nsIBrowserDOMWindow.OPEN_NEWTAB || - where === Ci.nsIBrowserDOMWindow.OPEN_NEWTAB_BACKGROUND + where === Ci.nsIBrowserDOMWindow.OPEN_NEWTAB_BACKGROUND || + where === Ci.nsIBrowserDOMWindow.OPEN_NEWTAB_FOREGROUND ) { browser = this.handleNewSession(uri, openWindowInfo, where, flags, name); } diff --git a/netwerk/ipc/DocumentLoadListener.cpp b/netwerk/ipc/DocumentLoadListener.cpp index 10f65a549ce8..ef946929c9bb 100644 --- a/netwerk/ipc/DocumentLoadListener.cpp +++ b/netwerk/ipc/DocumentLoadListener.cpp @@ -1692,8 +1692,9 @@ static int32_t GetWhereToOpen(nsIChannel* aChannel, bool aIsDocumentLoad) { where == nsIBrowserDOMWindow::OPEN_NEWTAB) { return where; } - // NOTE: nsIBrowserDOMWindow::OPEN_NEWTAB_BACKGROUND is not allowed as a pref - // value. + // NOTE: nsIBrowserDOMWindow::OPEN_NEWTAB_BACKGROUND and + // nsIBrowserDOMWindow::OPEN_NEWTAB_FOREGROUND are not allowed as pref + // values. return nsIBrowserDOMWindow::OPEN_NEWTAB; } @@ -1786,6 +1787,7 @@ static RefPtr SwitchToNewTab( CanonicalBrowsingContext* aLoadingBrowsingContext, int32_t aWhere) { MOZ_ASSERT(aWhere == nsIBrowserDOMWindow::OPEN_NEWTAB || aWhere == nsIBrowserDOMWindow::OPEN_NEWTAB_BACKGROUND || + aWhere == nsIBrowserDOMWindow::OPEN_NEWTAB_FOREGROUND || aWhere == nsIBrowserDOMWindow::OPEN_NEWWINDOW, "Unsupported open location"); diff --git a/xpfe/appshell/nsContentTreeOwner.cpp b/xpfe/appshell/nsContentTreeOwner.cpp index 37d5b45def67..9223b202baa2 100644 --- a/xpfe/appshell/nsContentTreeOwner.cpp +++ b/xpfe/appshell/nsContentTreeOwner.cpp @@ -544,6 +544,7 @@ nsContentTreeOwner::ProvideWindow( if (openLocation != nsIBrowserDOMWindow::OPEN_NEWTAB && openLocation != nsIBrowserDOMWindow::OPEN_NEWTAB_BACKGROUND && + openLocation != nsIBrowserDOMWindow::OPEN_NEWTAB_FOREGROUND && openLocation != nsIBrowserDOMWindow::OPEN_CURRENTWINDOW && openLocation != nsIBrowserDOMWindow::OPEN_PRINT_BROWSER) { // Just open a window normally