Source code

Revision control

Copy as Markdown

Other Tools

/* 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/. */
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
let lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.sys.mjs",
CommonDialog: "resource://gre/modules/CommonDialog.sys.mjs",
SessionStartup: "resource:///modules/sessionstore/SessionStartup.sys.mjs",
});
export var DefaultBrowserCheck = {
async prompt(win) {
const shellService = win.getShellService();
const needPin =
(await shellService.doesAppNeedPin()) ||
(await shellService.doesAppNeedStartMenuPin());
win.MozXULElement.insertFTLIfNeeded("branding/brand.ftl");
win.MozXULElement.insertFTLIfNeeded(
"browser/defaultBrowserNotification.ftl"
);
// Record default prompt impression
let now = Math.floor(Date.now() / 1000).toString();
Services.prefs.setCharPref(
"browser.shell.mostRecentDefaultPromptSeen",
now
);
// Resolve the translations for the prompt elements and return only the
// string values
let pinMessage;
if (AppConstants.platform == "macosx") {
pinMessage = "default-browser-prompt-message-pin-mac";
} else if (
AppConstants.platform == "win" &&
Services.sysinfo.getProperty("hasWinPackageId", false)
) {
pinMessage = "default-browser-prompt-message-pin-msix";
} else {
pinMessage = "default-browser-prompt-message-pin";
}
let [promptTitle, promptMessage, askLabel, yesButton, notNowButton] = (
await win.document.l10n.formatMessages([
{
id: needPin
? "default-browser-prompt-title-pin"
: "default-browser-prompt-title-alt",
},
{
id: needPin ? pinMessage : "default-browser-prompt-message-alt",
},
{ id: "default-browser-prompt-checkbox-not-again-label" },
{
id: needPin
? "default-browser-prompt-button-primary-set"
: "default-browser-prompt-button-primary-alt",
},
{ id: "default-browser-prompt-button-secondary" },
])
).map(({ value }) => value);
let ps = Services.prompt;
let buttonFlags =
ps.BUTTON_TITLE_IS_STRING * ps.BUTTON_POS_0 +
ps.BUTTON_TITLE_IS_STRING * ps.BUTTON_POS_1 +
ps.BUTTON_POS_0_DEFAULT;
let rv = await ps.asyncConfirmEx(
win.browsingContext,
ps.MODAL_TYPE_INTERNAL_WINDOW,
promptTitle,
promptMessage,
buttonFlags,
yesButton,
notNowButton,
null,
askLabel,
false, // checkbox state
{
headerIconCSSValue: lazy.CommonDialog.DEFAULT_APP_ICON_CSS,
}
);
let buttonNumClicked = rv.get("buttonNumClicked");
let checkboxState = rv.get("checked");
if (buttonNumClicked == 0) {
// We must explicitly await pinning to the taskbar before
// trying to set as default. If we fall back to setting
// as default through the Windows Settings menu that interferes
// with showing the pinning notification as we no longer have
// window focus.
try {
await shellService.pinToTaskbar();
} catch (e) {
this.log.error("Failed to pin to taskbar", e);
}
try {
await shellService.pinToStartMenu();
} catch (e) {
this.log.error("Failed to pin to Start Menu", e);
}
try {
await shellService.setAsDefault();
} catch (e) {
this.log.error("Failed to set the default browser", e);
}
}
if (checkboxState) {
shellService.shouldCheckDefaultBrowser = false;
Services.prefs.setCharPref("browser.shell.userDisabledDefaultCheck", now);
}
try {
let resultEnum = buttonNumClicked * 2 + !checkboxState;
Glean.browser.setDefaultResult.accumulateSingleSample(resultEnum);
} catch (ex) {
/* Don't break if Telemetry is acting up. */
}
},
/**
* Checks if the default browser check prompt will be shown.
*
* @param {boolean} isStartupCheck
* If true, prefs will be set and telemetry will be recorded.
* @returns {boolean} True if the default browser check prompt will be shown.
*/
async willCheckDefaultBrowser(isStartupCheck) {
let win = lazy.BrowserWindowTracker.getTopWindow();
let shellService = win.getShellService();
// Perform default browser checking.
if (!shellService) {
return false;
}
let shouldCheck =
!AppConstants.DEBUG && shellService.shouldCheckDefaultBrowser;
// Even if we shouldn't check the default browser, we still continue when
// isStartupCheck = true to set prefs and telemetry.
if (!shouldCheck && !isStartupCheck) {
return false;
}
// Skip the "Set Default Browser" check during first-run or after the
// browser has been run a few times.
const skipDefaultBrowserCheck =
Services.prefs.getBoolPref(
"browser.shell.skipDefaultBrowserCheckOnFirstRun"
) &&
!Services.prefs.getBoolPref(
"browser.shell.didSkipDefaultBrowserCheckOnFirstRun"
);
let promptCount = Services.prefs.getIntPref(
"browser.shell.defaultBrowserCheckCount",
0
);
// If SessionStartup's state is not initialized, checking sessionType will set
// its internal state to "do not restore".
await lazy.SessionStartup.onceInitialized;
let willRecoverSession =
lazy.SessionStartup.sessionType == lazy.SessionStartup.RECOVER_SESSION;
// Don't show the prompt if we're already the default browser.
let isDefault = false;
let isDefaultError = false;
try {
isDefault = shellService.isDefaultBrowser(isStartupCheck, false);
} catch (ex) {
isDefaultError = true;
}
if (isDefault && isStartupCheck) {
let now = Math.floor(Date.now() / 1000).toString();
Services.prefs.setCharPref(
"browser.shell.mostRecentDateSetAsDefault",
now
);
}
let willPrompt = shouldCheck && !isDefault && !willRecoverSession;
if (willPrompt) {
if (skipDefaultBrowserCheck) {
if (isStartupCheck) {
Services.prefs.setBoolPref(
"browser.shell.didSkipDefaultBrowserCheckOnFirstRun",
true
);
}
willPrompt = false;
} else {
promptCount++;
if (isStartupCheck) {
Services.prefs.setIntPref(
"browser.shell.defaultBrowserCheckCount",
promptCount
);
}
if (!AppConstants.RELEASE_OR_BETA && promptCount > 3) {
willPrompt = false;
}
}
}
if (isStartupCheck) {
try {
// Report default browser status on startup to telemetry
// so we can track whether we are the default.
Glean.browser.isUserDefault[isDefault ? "true" : "false"].add();
Glean.browser.isUserDefaultError[
isDefaultError ? "true" : "false"
].add();
Glean.browser.setDefaultAlwaysCheck[
shouldCheck ? "true" : "false"
].add();
Glean.browser.setDefaultDialogPromptRawcount.accumulateSingleSample(
promptCount
);
} catch (ex) {
/* Don't break the default prompt if telemetry is broken. */
}
}
return willPrompt;
},
};