diff --git a/browser/base/content/browser-defaultBrowserNotificationOnNewTabPage.js b/browser/base/content/browser-defaultBrowserNotificationOnNewTabPage.js index 673fa2e81f65..9e65cc127017 100644 --- a/browser/base/content/browser-defaultBrowserNotificationOnNewTabPage.js +++ b/browser/base/content/browser-defaultBrowserNotificationOnNewTabPage.js @@ -7,17 +7,22 @@ XPCOMUtils.defineLazyModuleGetters(this, { AboutNewTab: "resource:///modules/AboutNewTab.jsm", - ShellService: "resource:///modules/ShellService.jsm", }); var DefaultBrowserNotificationOnNewTabPage = { - init() { - this.willCheckDefaultBrowser().then(willPrompt => { - if (!willPrompt) { - return; - } + _eventListenerAdded: false, + async init() { + // The guards in this function are present to allow + // tests to re-init between test runs. + + let willPrompt = await this.willCheckDefaultBrowser(); + if (!willPrompt) { + return; + } + if (!this._eventListenerAdded) { window.addEventListener("TabSelect", this); - }); + this._eventListenerAdded = true; + } }, closePrompt(aNode) { @@ -33,6 +38,7 @@ var DefaultBrowserNotificationOnNewTabPage = { ) { DefaultBrowserNotificationOnNewTabPage.prompt(event.target.linkedBrowser); window.removeEventListener("TabSelect", this); + this._eventListenerAdded = false; } }, @@ -53,7 +59,7 @@ var DefaultBrowserNotificationOnNewTabPage = { "l10n-id": "default-browser-notification-button", primary: true, callback: () => { - ShellService.setAsDefault(); + window.getShellService().setAsDefault(); this.closePrompt(); }, }, @@ -107,7 +113,7 @@ var DefaultBrowserNotificationOnNewTabPage = { // Don't show the prompt if we're already the default browser. let isDefault = false; try { - isDefault = ShellService.isDefaultBrowser(false, false); + isDefault = window.getShellService().isDefaultBrowser(false, false); } catch (ex) {} if (!isDefault) { diff --git a/browser/base/content/test/about/browser.ini b/browser/base/content/test/about/browser.ini index 5039f3611a73..86e3a64ab604 100644 --- a/browser/base/content/test/about/browser.ini +++ b/browser/base/content/test/about/browser.ini @@ -32,6 +32,7 @@ support-files = support-files = iframe_page_xfo.html xfo_iframe.sjs +[browser_aboutNewTab_defaultBrowserNotification.js] [browser_aboutStopReload.js] [browser_aboutSupport.js] [browser_aboutSupport_newtab_security_state.js] diff --git a/browser/base/content/test/about/browser_aboutNewTab_defaultBrowserNotification.js b/browser/base/content/test/about/browser_aboutNewTab_defaultBrowserNotification.js new file mode 100644 index 000000000000..2a666a48726f --- /dev/null +++ b/browser/base/content/test/about/browser_aboutNewTab_defaultBrowserNotification.js @@ -0,0 +1,238 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_task(async function notification_shown_on_first_newtab_when_not_default() { + await test_with_mock_shellservice({ isDefault: false }, async function() { + ok( + !gBrowser.getNotificationBox(gBrowser.selectedBrowser) + .currentNotification, + "There shouldn't be a notification when the test starts" + ); + let firstTab = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + opening: "about:newtab", + waitForLoad: false, + }); + let notification = await TestUtils.waitForCondition( + () => + firstTab.linkedBrowser && + gBrowser.getNotificationBox(firstTab.linkedBrowser) && + gBrowser.getNotificationBox(firstTab.linkedBrowser).currentNotification, + "waiting for notification" + ); + ok(notification, "A notification should be shown on the new tab page"); + is( + notification.getAttribute("value"), + "default-browser", + "Notification should be default browser" + ); + + let secondTab = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + opening: "about:newtab", + waitForLoad: false, + }); + + ok( + secondTab.linkedBrowser && + gBrowser.getNotificationBox(secondTab.linkedBrowser) && + !gBrowser.getNotificationBox(secondTab.linkedBrowser) + .currentNotification, + "A notification should not be shown on the second new tab page" + ); + + gBrowser.removeTab(firstTab); + gBrowser.removeTab(secondTab); + }); +}); + +add_task(async function notification_not_shown_on_first_newtab_when_default() { + await test_with_mock_shellservice({ isDefault: true }, async function() { + ok( + !gBrowser.getNotificationBox(gBrowser.selectedBrowser) + .currentNotification, + "There shouldn't be a notification when the test starts" + ); + let firstTab = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + opening: "about:newtab", + waitForLoad: false, + }); + ok( + firstTab.linkedBrowser && + gBrowser.getNotificationBox(firstTab.linkedBrowser) && + !gBrowser.getNotificationBox(firstTab.linkedBrowser) + .currentNotification, + "No notification on first tab when browser is default" + ); + + let secondTab = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + opening: "about:newtab", + waitForLoad: false, + }); + + ok( + secondTab.linkedBrowser && + gBrowser.getNotificationBox(secondTab.linkedBrowser) && + !gBrowser.getNotificationBox(secondTab.linkedBrowser) + .currentNotification, + "A notification should not be shown on the second new tab page" + ); + + gBrowser.removeTab(firstTab); + gBrowser.removeTab(secondTab); + }); +}); + +add_task(async function clicking_button_on_notification_calls_setAsDefault() { + await test_with_mock_shellservice({ isDefault: false }, async function() { + let firstTab = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + opening: "about:newtab", + waitForLoad: false, + }); + let notification = await TestUtils.waitForCondition( + () => + firstTab.linkedBrowser && + gBrowser.getNotificationBox(firstTab.linkedBrowser) && + gBrowser.getNotificationBox(firstTab.linkedBrowser).currentNotification, + "waiting for notification" + ); + ok(notification, "A notification should be shown on the new tab page"); + is( + notification.getAttribute("value"), + "default-browser", + "Notification should be default browser" + ); + + let shellService = window.getShellService(); + ok( + !shellService.isDefaultBrowser(), + "should not be default prior to clicking button" + ); + let button = notification.querySelector(".notification-button"); + button.click(); + ok( + shellService.isDefaultBrowser(), + "should be default after clicking button" + ); + + gBrowser.removeTab(firstTab); + }); +}); + +add_task(async function clicking_dismiss_disables_default_browser_checking() { + await test_with_mock_shellservice({ isDefault: false }, async function() { + let firstTab = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + opening: "about:newtab", + waitForLoad: false, + }); + let notification = await TestUtils.waitForCondition( + () => + firstTab.linkedBrowser && + gBrowser.getNotificationBox(firstTab.linkedBrowser) && + gBrowser.getNotificationBox(firstTab.linkedBrowser).currentNotification, + "waiting for notification" + ); + ok(notification, "A notification should be shown on the new tab page"); + is( + notification.getAttribute("value"), + "default-browser", + "Notification should be default browser" + ); + + let closeButton = notification.querySelector(".close-icon"); + closeButton.click(); + ok( + !Services.prefs.getBoolPref("browser.shell.checkDefaultBrowser"), + "checkDefaultBrowser bar pref should be false after dismissing notification" + ); + + gBrowser.removeTab(firstTab); + }); +}); + +add_task(async function notification_bar_removes_itself_on_navigation() { + await test_with_mock_shellservice({ isDefault: false }, async function() { + let firstTab = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + opening: "about:newtab", + waitForLoad: false, + }); + let notification = await TestUtils.waitForCondition( + () => + firstTab.linkedBrowser && + gBrowser.getNotificationBox(firstTab.linkedBrowser) && + gBrowser.getNotificationBox(firstTab.linkedBrowser).currentNotification, + "waiting for notification" + ); + ok(notification, "A notification should be shown on the new tab page"); + is( + notification.getAttribute("value"), + "default-browser", + "Notification should be default browser" + ); + + await BrowserTestUtils.loadURI( + gBrowser.selectedBrowser, + "https://example.com" + ); + + let notificationRemoved = await TestUtils.waitForCondition( + () => + firstTab.linkedBrowser && + gBrowser.getNotificationBox(firstTab.linkedBrowser) && + !gBrowser.getNotificationBox(firstTab.linkedBrowser) + .currentNotification, + "waiting for notification to get removed" + ); + ok( + notificationRemoved, + "A notification should not be shown after navigation" + ); + + gBrowser.removeTab(firstTab); + }); +}); + +async function test_with_mock_shellservice(options, testFn) { + let oldShellService = window.getShellService; + let mockShellService = { + _isDefault: false, + canSetDesktopBackground() {}, + isDefaultBrowserOptOut() {}, + get shouldCheckDefaultBrowser() { + return true; + }, + isDefaultBrowser() { + return this._isDefault; + }, + setAsDefault() { + this.setDefaultBrowser(); + }, + setDefaultBrowser() { + this._isDefault = true; + }, + }; + window.getShellService = function() { + return mockShellService; + }; + mockShellService._isDefault = options.isDefault; + await SpecialPowers.pushPrefEnv({ + set: [ + ["browser.shell.checkDefaultBrowser", true], + ["browser.defaultbrowser.notificationbar", true], + ["browser.defaultbrowser.notificationbar.checkcount", 0], + ], + }); + // Re-add the event listener since it gets removed on the first about:newtab + await window.DefaultBrowserNotificationOnNewTabPage.init(); + + await testFn(); + + window.getShellService = oldShellService; +} diff --git a/browser/components/BrowserGlue.jsm b/browser/components/BrowserGlue.jsm index d910561a3677..68b77e6f42cf 100644 --- a/browser/components/BrowserGlue.jsm +++ b/browser/components/BrowserGlue.jsm @@ -3756,12 +3756,12 @@ BrowserGlue.prototype = { _maybeShowDefaultBrowserPrompt() { DefaultBrowserCheck.willCheckDefaultBrowser(/* isStartupCheck */ true).then( - willPrompt => { + async willPrompt => { let win = BrowserWindowTracker.getTopWindow(); if (!willPrompt) { // If we're not showing the modal prompt, maybe we // still want to show the passive notification bar. - win.DefaultBrowserNotificationOnNewTabPage.init(); + await win.DefaultBrowserNotificationOnNewTabPage.init(); return; } DefaultBrowserCheck.prompt(win);