forked from mirrors/gecko-dev
Bug 1880368 - change firefox and firefox-private protocols to firefox-bridge and firefox-private-bridge protocols r=nshukla,mossop
Differential Revision: https://phabricator.services.mozilla.com/D201879
This commit is contained in:
parent
98aecb3ad4
commit
09024f2525
13 changed files with 694 additions and 195 deletions
|
|
@ -237,7 +237,7 @@
|
|||
<string>Firefox Protocol</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>firefox</string>
|
||||
<string>firefox-bridge</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
|
|
@ -245,7 +245,7 @@
|
|||
<string>Firefox Private Browsing Protocol</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>firefox-private</string>
|
||||
<string>firefox-private-bridge</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
|
|
|
|||
|
|
@ -298,9 +298,6 @@ pref("browser.shell.checkDefaultPDF.silencedByUser", false);
|
|||
// URL to navigate to when launching Firefox after accepting the Windows Default
|
||||
// Browser Agent "Set Firefox as default" call to action.
|
||||
pref("browser.shell.defaultBrowserAgent.thanksURL", "https://www.mozilla.org/%LOCALE%/firefox/set-as-default/thanks/");
|
||||
// Whether or not we want to run through the early startup idle task
|
||||
// which registers the firefox and firefox-private registry keys.
|
||||
pref("browser.shell.customProtocolsRegistered", false);
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ function resolveURIInternal(
|
|||
if (aArgument.startsWith(protocolWithColon)) {
|
||||
if (!validateFirefoxProtocol(aCmdLine, launchedWithArg_osint)) {
|
||||
throw new Error(
|
||||
"Invalid use of Firefox and Firefox-private protocols."
|
||||
"Invalid use of Firefox-bridge and Firefox-private-bridge protocols."
|
||||
);
|
||||
}
|
||||
aArgument = aArgument.substring(protocolWithColon.length);
|
||||
|
|
@ -100,7 +100,7 @@ function resolveURIInternal(
|
|||
!aArgument.startsWith("https://")
|
||||
) {
|
||||
throw new Error(
|
||||
"Firefox and Firefox-private protocols can only be used in conjunction with http and https urls."
|
||||
"Firefox-bridge and Firefox-private-bridge protocols can only be used in conjunction with http and https urls."
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -113,8 +113,8 @@ function resolveURIInternal(
|
|||
}
|
||||
};
|
||||
|
||||
handleFirefoxProtocol("firefox");
|
||||
handleFirefoxProtocol("firefox-private");
|
||||
handleFirefoxProtocol("firefox-bridge");
|
||||
handleFirefoxProtocol("firefox-private-bridge");
|
||||
|
||||
var uri = aCmdLine.resolveURI(aArgument);
|
||||
var uriFixup = Services.uriFixup;
|
||||
|
|
@ -599,7 +599,7 @@ nsBrowserContentHandler.prototype = {
|
|||
if (urlFlagIdx > -1 && cmdLine.length > 1) {
|
||||
url = cmdLine.getArgument(urlFlagIdx + 1);
|
||||
}
|
||||
if (privateWindowParam || url?.startsWith("firefox-private:")) {
|
||||
if (privateWindowParam || url?.startsWith("firefox-private-bridge:")) {
|
||||
// Check if the osint flag is present on Windows
|
||||
let launchedWithArg_osint =
|
||||
AppConstants.platform == "win" &&
|
||||
|
|
@ -614,7 +614,7 @@ nsBrowserContentHandler.prototype = {
|
|||
uri: Services.io.newURI("about:privatebrowsing"),
|
||||
principal: lazy.gSystemPrincipal,
|
||||
};
|
||||
} else if (url?.startsWith("firefox-private:")) {
|
||||
} else if (url?.startsWith("firefox-private-bridge:")) {
|
||||
cmdLine.removeArguments(urlFlagIdx, urlFlagIdx + 1);
|
||||
resolvedInfo = resolveURIInternal(
|
||||
cmdLine,
|
||||
|
|
@ -1463,7 +1463,7 @@ nsDefaultCommandLineHandler.prototype = {
|
|||
}
|
||||
|
||||
// Can't open multiple URLs without using system principal.
|
||||
// The firefox and firefox-private protocols should only
|
||||
// The firefox-bridge and firefox-private-bridge protocols should only
|
||||
// accept a single URL due to using the -osint option
|
||||
// so this isn't very relevant.
|
||||
var URLlist = urilist.filter(shouldLoadURI).map(u => u.spec);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
|||
E10SUtils: "resource://gre/modules/E10SUtils.sys.mjs",
|
||||
ExtensionsUI: "resource:///modules/ExtensionsUI.sys.mjs",
|
||||
FeatureGate: "resource://featuregates/FeatureGate.sys.mjs",
|
||||
FirefoxBridgeExtensionUtils:
|
||||
"resource:///modules/FirefoxBridgeExtensionUtils.sys.mjs",
|
||||
FxAccounts: "resource://gre/modules/FxAccounts.sys.mjs",
|
||||
HomePage: "resource:///modules/HomePage.sys.mjs",
|
||||
Integration: "resource://gre/modules/Integration.sys.mjs",
|
||||
|
|
@ -2641,126 +2643,6 @@ BrowserGlue.prototype = {
|
|||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "dualBrowserProtocolHandler",
|
||||
condition:
|
||||
AppConstants.platform == "win" &&
|
||||
!Services.prefs.getBoolPref(
|
||||
"browser.shell.customProtocolsRegistered"
|
||||
),
|
||||
task: async () => {
|
||||
Services.prefs.setBoolPref(
|
||||
"browser.shell.customProtocolsRegistered",
|
||||
true
|
||||
);
|
||||
const FIREFOX_HANDLER_NAME = "firefox";
|
||||
const FIREFOX_PRIVATE_HANDLER_NAME = "firefox-private";
|
||||
const path = Services.dirsvc.get("XREExeF", Ci.nsIFile).path;
|
||||
let wrk = Cc["@mozilla.org/windows-registry-key;1"].createInstance(
|
||||
Ci.nsIWindowsRegKey
|
||||
);
|
||||
try {
|
||||
wrk.open(wrk.ROOT_KEY_CLASSES_ROOT, "", wrk.ACCESS_READ);
|
||||
let FxSet = wrk.hasChild(FIREFOX_HANDLER_NAME);
|
||||
let FxPrivateSet = wrk.hasChild(FIREFOX_PRIVATE_HANDLER_NAME);
|
||||
wrk.close();
|
||||
if (FxSet && FxPrivateSet) {
|
||||
return;
|
||||
}
|
||||
wrk.open(
|
||||
wrk.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Classes",
|
||||
wrk.ACCESS_ALL
|
||||
);
|
||||
const maybeUpdateRegistry = (
|
||||
isSetAlready,
|
||||
handler,
|
||||
protocolName
|
||||
) => {
|
||||
if (isSetAlready) {
|
||||
return;
|
||||
}
|
||||
let FxKey = wrk.createChild(handler, wrk.ACCESS_ALL);
|
||||
try {
|
||||
// Write URL protocol key
|
||||
FxKey.writeStringValue("", protocolName);
|
||||
FxKey.writeStringValue("URL Protocol", "");
|
||||
FxKey.close();
|
||||
// Write defaultIcon key
|
||||
FxKey.create(
|
||||
FxKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Classes\\" + handler + "\\DefaultIcon",
|
||||
FxKey.ACCESS_ALL
|
||||
);
|
||||
FxKey.open(
|
||||
FxKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Classes\\" + handler + "\\DefaultIcon",
|
||||
FxKey.ACCESS_ALL
|
||||
);
|
||||
FxKey.writeStringValue("", `\"${path}\",1`);
|
||||
FxKey.close();
|
||||
// Write shell\\open\\command key
|
||||
FxKey.create(
|
||||
FxKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Classes\\" + handler + "\\shell",
|
||||
FxKey.ACCESS_ALL
|
||||
);
|
||||
FxKey.create(
|
||||
FxKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Classes\\" + handler + "\\shell\\open",
|
||||
FxKey.ACCESS_ALL
|
||||
);
|
||||
FxKey.create(
|
||||
FxKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Classes\\" + handler + "\\shell\\open\\command",
|
||||
FxKey.ACCESS_ALL
|
||||
);
|
||||
FxKey.open(
|
||||
FxKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Classes\\" + handler + "\\shell\\open\\command",
|
||||
FxKey.ACCESS_ALL
|
||||
);
|
||||
if (handler == FIREFOX_PRIVATE_HANDLER_NAME) {
|
||||
FxKey.writeStringValue(
|
||||
"",
|
||||
`\"${path}\" -osint -private-window \"%1\"`
|
||||
);
|
||||
} else {
|
||||
FxKey.writeStringValue("", `\"${path}\" -osint -url \"%1\"`);
|
||||
}
|
||||
} catch (ex) {
|
||||
console.log(ex);
|
||||
} finally {
|
||||
FxKey.close();
|
||||
}
|
||||
};
|
||||
try {
|
||||
maybeUpdateRegistry(
|
||||
FxSet,
|
||||
FIREFOX_HANDLER_NAME,
|
||||
"URL:Firefox Protocol"
|
||||
);
|
||||
} catch (ex) {
|
||||
console.log(ex);
|
||||
}
|
||||
try {
|
||||
maybeUpdateRegistry(
|
||||
FxPrivateSet,
|
||||
FIREFOX_PRIVATE_HANDLER_NAME,
|
||||
"URL:Firefox Private Browsing Protocol"
|
||||
);
|
||||
} catch (ex) {
|
||||
console.log(ex);
|
||||
}
|
||||
} catch (ex) {
|
||||
console.log(ex);
|
||||
} finally {
|
||||
wrk.close();
|
||||
}
|
||||
},
|
||||
timeout: 5000,
|
||||
},
|
||||
|
||||
// Ensure a Private Browsing Shortcut exists. This is needed in case
|
||||
// a user tries to use Windows functionality to pin our Private Browsing
|
||||
// mode icon to the Taskbar (eg: the "Pin to Taskbar" context menu item).
|
||||
|
|
@ -3821,13 +3703,20 @@ BrowserGlue.prototype = {
|
|||
_migrateUI() {
|
||||
// Use an increasing number to keep track of the current migration state.
|
||||
// Completely unrelated to the current Firefox release number.
|
||||
const UI_VERSION = 142;
|
||||
const UI_VERSION = 143;
|
||||
const BROWSER_DOCURL = AppConstants.BROWSER_CHROME_URL;
|
||||
|
||||
if (!Services.prefs.prefHasUserValue("browser.migration.version")) {
|
||||
// This is a new profile, nothing to migrate.
|
||||
Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
|
||||
this._isNewProfile = true;
|
||||
|
||||
if (AppConstants.platform == "win") {
|
||||
// Ensure that the Firefox Bridge protocols are registered for the new profile.
|
||||
// No-op if they are registered for the user or the local machine already.
|
||||
lazy.FirefoxBridgeExtensionUtils.maybeRegisterFirefoxBridgeProtocols();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -4427,6 +4316,27 @@ BrowserGlue.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
if (currentUIVersion < 143) {
|
||||
if (AppConstants.platform == "win") {
|
||||
// In Firefox 122, we enabled the firefox and firefox-private protocols.
|
||||
// We switched over to using firefox-bridge and firefox-private-bridge,
|
||||
// but we want to clean up the use of the other protocols.
|
||||
lazy.FirefoxBridgeExtensionUtils.maybeDeleteBridgeProtocolRegistryEntries();
|
||||
|
||||
// Register the new firefox bridge related protocols now
|
||||
lazy.FirefoxBridgeExtensionUtils.maybeRegisterFirefoxBridgeProtocols();
|
||||
|
||||
// Clean up the old user prefs from FX 122
|
||||
Services.prefs.clearUserPref(
|
||||
"network.protocol-handler.external.firefox"
|
||||
);
|
||||
Services.prefs.clearUserPref(
|
||||
"network.protocol-handler.external.firefox-private"
|
||||
);
|
||||
Services.prefs.clearUserPref("browser.shell.customProtocolsRegistered");
|
||||
}
|
||||
}
|
||||
|
||||
// Update the migration version.
|
||||
Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -92,14 +92,14 @@
|
|||
</uap3:Protocol>
|
||||
</uap3:Extension>
|
||||
<uap3:Extension Category="windows.protocol">
|
||||
<uap3:Protocol Name="firefox" Parameters="-osint -url "%1"">
|
||||
<uap:DisplayName>Firefox Protocol</uap:DisplayName>
|
||||
<uap3:Protocol Name="firefox-bridge" Parameters="-osint -url "%1"">
|
||||
<uap:DisplayName>Firefox Bridge Protocol</uap:DisplayName>
|
||||
<uap:Logo>Assets\Document44x44.png</uap:Logo>
|
||||
</uap3:Protocol>
|
||||
</uap3:Extension>
|
||||
<uap3:Extension Category="windows.protocol">
|
||||
<uap3:Protocol Name="firefox-private" Parameters="-osint -private-window "%1"">
|
||||
<uap:DisplayName>Firefox Private Browsing Protocol</uap:DisplayName>
|
||||
<uap3:Protocol Name="firefox-private-bridge" Parameters="-osint -private-window "%1"">
|
||||
<uap:DisplayName>Firefox Private Bridge Protocol</uap:DisplayName>
|
||||
<uap:Logo>Assets\Document44x44.png</uap:Logo>
|
||||
</uap3:Protocol>
|
||||
</uap3:Extension>
|
||||
|
|
|
|||
|
|
@ -474,22 +474,22 @@ Section "-Application" APP_IDX
|
|||
${AddDisabledDDEHandlerValues} "FirefoxURL-$AppUserModelID" "$2" "$8,${IDI_DOCUMENT_ZERO_BASED}" \
|
||||
"${AppRegName} URL" "true"
|
||||
|
||||
; Create protocol registry keys for dual browser extensions - only if not already set
|
||||
; Create protocol registry keys for FirefoxBridge extensions - only if not already set
|
||||
SetShellVarContext current ; Set SHCTX to HKCU
|
||||
!define FIREFOX_PROTOCOL "firefox"
|
||||
!define FIREFOX_PROTOCOL "firefox-bridge"
|
||||
ClearErrors
|
||||
ReadRegStr $0 SHCTX "Software\Classes\${FIREFOX_PROTOCOL}" ""
|
||||
${If} $0 == ""
|
||||
${AddDisabledDDEHandlerValues} "${FIREFOX_PROTOCOL}" "$2" "$8,${IDI_APPICON_ZERO_BASED}" \
|
||||
"Firefox Browsing Protocol" "true"
|
||||
"Firefox Bridge Protocol" "true"
|
||||
${EndIf}
|
||||
|
||||
!define FIREFOX_PRIVATE_PROTOCOL "firefox-private"
|
||||
!define FIREFOX_PRIVATE_PROTOCOL "firefox-private-bridge"
|
||||
ClearErrors
|
||||
ReadRegStr $0 SHCTX "Software\Classes\${FIREFOX_PRIVATE_PROTOCOL}" ""
|
||||
${If} $0 == ""
|
||||
${AddDisabledDDEHandlerValues} "${FIREFOX_PRIVATE_PROTOCOL}" "$\"$8$\" -osint -private-window $\"%1$\"" \
|
||||
"$8,${IDI_PBICON_PB_EXE_ZERO_BASED}" "Firefox Private Browsing Protocol" "true"
|
||||
"$8,${IDI_PBICON_PB_EXE_ZERO_BASED}" "Firefox Private Bridge Protocol" "true"
|
||||
${EndIf}
|
||||
SetShellVarContext all ; Set SHCTX to HKLM
|
||||
|
||||
|
|
@ -794,6 +794,15 @@ Section "-InstallEndCleanup"
|
|||
; Refresh desktop icons
|
||||
${RefreshShellIcons}
|
||||
|
||||
; Remove old unsupported firefox and firefox-private extension protocol
|
||||
; handlers which were added in FX122 for the dual browser extension, since
|
||||
; renamed to FirefoxBridge
|
||||
Push $1
|
||||
${GetLongPath} "$INSTDIR\${FileMainEXE}" $1
|
||||
${DeleteProtocolRegistryIfSetToInstallation} "$1" "firefox"
|
||||
${DeleteProtocolRegistryIfSetToInstallation} "$1" "firefox-private"
|
||||
Pop $1
|
||||
|
||||
${InstallEndCleanupCommon}
|
||||
|
||||
${If} $PreventRebootRequired == "true"
|
||||
|
|
|
|||
|
|
@ -1824,3 +1824,49 @@ FunctionEnd
|
|||
${WriteRegStr2} ${RegKey} "Software\Classes\CLSID\$0\InProcServer32" "" "$INSTDIR\notificationserver.dll" 0
|
||||
!macroend
|
||||
!define WriteToastNotificationRegistration "!insertmacro WriteToastNotificationRegistration"
|
||||
|
||||
/**
|
||||
* Deletes the registry keys for a protocol handler but only if those registry
|
||||
* keys were pointed to the installation being uninstalled.
|
||||
* Does this with both the HKLM and the HKCU registry entries.
|
||||
*
|
||||
* @param _PROTOCOL
|
||||
* The protocol to delete the registry keys for
|
||||
*/
|
||||
!macro DeleteProtocolRegistryIfSetToInstallation INSTALL_PATH _PROTOCOL
|
||||
Push $0
|
||||
|
||||
; Check if there is a protocol handler registered by fetching the DefaultIcon value
|
||||
; in the registry.
|
||||
; If there is something registered for the icon, it will be the path to the executable,
|
||||
; plus a comma and a number for the id of the resource for the icon.
|
||||
; Use StrCpy with -2 to remove the comma and the resource id so that
|
||||
; the whole path to the executable can be compared against what's being
|
||||
; uninstalled.
|
||||
|
||||
; Do all of that twice, once for the local machine and once for the current user
|
||||
|
||||
; Remove protocol handlers
|
||||
ClearErrors
|
||||
ReadRegStr $0 HKLM "Software\Classes\${_PROTOCOL}\DefaultIcon" ""
|
||||
${If} $0 != ""
|
||||
StrCpy $0 $0 -2
|
||||
${If} $0 == '"${INSTALL_PATH}"'
|
||||
DeleteRegKey HKLM "Software\Classes\${_PROTOCOL}"
|
||||
${EndIf}
|
||||
${EndIf}
|
||||
|
||||
ClearErrors
|
||||
ReadRegStr $0 HKCU "Software\Classes\${_PROTOCOL}\DefaultIcon" ""
|
||||
${If} $0 != ""
|
||||
StrCpy $0 $0 -2
|
||||
${If} $0 == '"${INSTALL_PATH}"'
|
||||
DeleteRegKey HKCU "Software\Classes\${_PROTOCOL}"
|
||||
${EndIf}
|
||||
${EndIf}
|
||||
|
||||
ClearErrors
|
||||
|
||||
Pop $0
|
||||
!macroend
|
||||
!define DeleteProtocolRegistryIfSetToInstallation '!insertmacro DeleteProtocolRegistryIfSetToInstallation'
|
||||
|
|
|
|||
|
|
@ -411,54 +411,6 @@ SectionEnd
|
|||
################################################################################
|
||||
# Uninstall Sections
|
||||
|
||||
/**
|
||||
* Deletes the registry keys for a protocol handler but only if those registry
|
||||
* keys were pointed to the installation being uninstalled.
|
||||
* Does this with both the HKLM and the HKCU registry entries.
|
||||
*
|
||||
* @param _PROTOCOL
|
||||
* The protocol to delete the registry keys for
|
||||
*/
|
||||
!macro DeleteProtocolRegistryIfSetToInstallation _PROTOCOL
|
||||
Push $0
|
||||
Push $1
|
||||
; Check if there is a protocol handler registered by fetching the DefaultIcon value
|
||||
; in the registry.
|
||||
; If there is something registered for the icon, it will be the path to the executable,
|
||||
; plus a comma and a number for the id of the resource for the icon.
|
||||
; Use StrCpy with -2 to remove the comma and the resource id so that
|
||||
; the whole path to the executable can be compared against what's being
|
||||
; uninstalled.
|
||||
|
||||
; Do all of that twice, once for the local machine and once for the current user
|
||||
|
||||
; Remove protocol handlers
|
||||
ClearErrors
|
||||
${un.GetLongPath} "$INSTDIR\${FileMainEXE}" $1
|
||||
ReadRegStr $0 HKLM "Software\Classes\${_PROTOCOL}\DefaultIcon" ""
|
||||
${If} $0 != ""
|
||||
StrCpy $0 $0 -2
|
||||
${If} $0 == $1
|
||||
DeleteRegKey HKLM "Software\Classes\${_PROTOCOL}"
|
||||
${EndIf}
|
||||
${EndIf}
|
||||
|
||||
ClearErrors
|
||||
ReadRegStr $0 HKCU "Software\Classes\${_PROTOCOL}\DefaultIcon" ""
|
||||
${If} $0 != ""
|
||||
StrCpy $0 $0 -2
|
||||
${If} $0 == $1
|
||||
DeleteRegKey HKCU "Software\Classes\${_PROTOCOL}"
|
||||
${EndIf}
|
||||
${EndIf}
|
||||
|
||||
ClearErrors
|
||||
|
||||
Pop $0
|
||||
Pop $1
|
||||
!macroend
|
||||
!define DeleteProtocolRegistryIfSetToInstallation '!insertmacro DeleteProtocolRegistryIfSetToInstallation'
|
||||
|
||||
Section "Uninstall"
|
||||
SetDetailsPrint textonly
|
||||
DetailPrint $(STATUS_UNINSTALL_MAIN)
|
||||
|
|
@ -571,9 +523,12 @@ Section "Uninstall"
|
|||
; Clean up "launch on login" registry key for this installation.
|
||||
DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "Mozilla-${AppName}-$AppUserModelID"
|
||||
|
||||
; Remove dual browser extension protocol handlers
|
||||
${DeleteProtocolRegistryIfSetToInstallation} "firefox"
|
||||
${DeleteProtocolRegistryIfSetToInstallation} "firefox-private"
|
||||
; Remove FirefoxBridge extension protocol handlers
|
||||
Push $1
|
||||
${un.GetLongPath} "$INSTDIR\${FileMainEXE}" $1
|
||||
${DeleteProtocolRegistryIfSetToInstallation} "$1" "firefox-bridge"
|
||||
${DeleteProtocolRegistryIfSetToInstallation} "$1" "firefox-private-bridge"
|
||||
Pop $1
|
||||
|
||||
; Remove old protocol handler and StartMenuInternet keys without install path
|
||||
; hashes, but only if they're for this installation. We've never supported
|
||||
|
|
|
|||
222
browser/modules/FirefoxBridgeExtensionUtils.sys.mjs
Normal file
222
browser/modules/FirefoxBridgeExtensionUtils.sys.mjs
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
/* 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/. */
|
||||
|
||||
/**
|
||||
* Default implementation of the helper class to assist in deleting the firefox protocols.
|
||||
* See maybeDeleteBridgeProtocolRegistryEntries for more info.
|
||||
*/
|
||||
class DeleteBridgeProtocolRegistryEntryHelperImplementation {
|
||||
getApplicationPath() {
|
||||
return Services.dirsvc.get("XREExeF", Ci.nsIFile).path;
|
||||
}
|
||||
|
||||
openRegistryRoot() {
|
||||
const wrk = Cc["@mozilla.org/windows-registry-key;1"].createInstance(
|
||||
Ci.nsIWindowsRegKey
|
||||
);
|
||||
|
||||
wrk.open(wrk.ROOT_KEY_CURRENT_USER, "Software\\Classes", wrk.ACCESS_ALL);
|
||||
|
||||
return wrk;
|
||||
}
|
||||
|
||||
deleteChildren(start) {
|
||||
// Recursively delete all of the children of the children
|
||||
// Go through the list in reverse order, so that shrinking
|
||||
// the list doesn't rearrange things while iterating
|
||||
for (let i = start.childCount; i > 0; i--) {
|
||||
const childName = start.getChildName(i - 1);
|
||||
const child = start.openChild(childName, start.ACCESS_ALL);
|
||||
this.deleteChildren(child);
|
||||
child.close();
|
||||
|
||||
start.removeChild(childName);
|
||||
}
|
||||
}
|
||||
|
||||
deleteRegistryTree(root, toDeletePath) {
|
||||
var start = root.openChild(toDeletePath, root.ACCESS_ALL);
|
||||
this.deleteChildren(start);
|
||||
start.close();
|
||||
|
||||
root.removeChild(toDeletePath);
|
||||
}
|
||||
}
|
||||
|
||||
export const FirefoxBridgeExtensionUtils = {
|
||||
/**
|
||||
* In Firefox 122, we enabled the firefox and firefox-private protocols.
|
||||
* We switched over to using firefox-bridge and firefox-private-bridge,
|
||||
*
|
||||
* but we want to clean up the use of the other protocols.
|
||||
*
|
||||
* deleteBridgeProtocolRegistryEntryHelper handles everything outside of the logic needed for
|
||||
* this method so that the logic in maybeDeleteBridgeProtocolRegistryEntries can be unit tested
|
||||
*
|
||||
* We only delete the entries for the firefox and firefox-private protocols if
|
||||
* they were set up to use this install and in the format that Firefox installed
|
||||
* them with. If the entries are changed in any way, it is assumed that the user
|
||||
* mucked with them manually and knows what they are doing.
|
||||
*/
|
||||
maybeDeleteBridgeProtocolRegistryEntries(
|
||||
deleteBridgeProtocolRegistryEntryHelper = new DeleteBridgeProtocolRegistryEntryHelperImplementation()
|
||||
) {
|
||||
try {
|
||||
var wrk = deleteBridgeProtocolRegistryEntryHelper.openRegistryRoot();
|
||||
const path = deleteBridgeProtocolRegistryEntryHelper.getApplicationPath();
|
||||
|
||||
const maybeDeleteRegistryKey = (protocol, protocolCommand) => {
|
||||
const openCommandPath = protocol + "\\shell\\open\\command";
|
||||
if (wrk.hasChild(openCommandPath)) {
|
||||
let deleteProtocolEntry = false;
|
||||
|
||||
try {
|
||||
var openCommandKey = wrk.openChild(
|
||||
openCommandPath,
|
||||
wrk.ACCESS_READ
|
||||
);
|
||||
if (openCommandKey.valueCount == 1) {
|
||||
const defaultKeyName = "";
|
||||
if (openCommandKey.getValueName(0) == defaultKeyName) {
|
||||
if (
|
||||
openCommandKey.getValueType(defaultKeyName) ==
|
||||
Ci.nsIWindowsRegKey.TYPE_STRING
|
||||
) {
|
||||
const val = openCommandKey.readStringValue(defaultKeyName);
|
||||
if (val == protocolCommand) {
|
||||
deleteProtocolEntry = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
openCommandKey.close();
|
||||
}
|
||||
|
||||
if (deleteProtocolEntry) {
|
||||
deleteBridgeProtocolRegistryEntryHelper.deleteRegistryTree(
|
||||
wrk,
|
||||
protocol
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
maybeDeleteRegistryKey("firefox", `\"${path}\" -osint -url \"%1\"`);
|
||||
maybeDeleteRegistryKey(
|
||||
"firefox-private",
|
||||
`\"${path}\" -osint -private-window \"%1\"`
|
||||
);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
} finally {
|
||||
wrk.close();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Registers the firefox-bridge and firefox-private-bridge protocols
|
||||
* on the Windows platform.
|
||||
*/
|
||||
maybeRegisterFirefoxBridgeProtocols() {
|
||||
const FIREFOX_BRIDGE_HANDLER_NAME = "firefox-bridge";
|
||||
const FIREFOX_PRIVATE_BRIDGE_HANDLER_NAME = "firefox-private-bridge";
|
||||
const path = Services.dirsvc.get("XREExeF", Ci.nsIFile).path;
|
||||
let wrk = Cc["@mozilla.org/windows-registry-key;1"].createInstance(
|
||||
Ci.nsIWindowsRegKey
|
||||
);
|
||||
try {
|
||||
wrk.open(wrk.ROOT_KEY_CLASSES_ROOT, "", wrk.ACCESS_READ);
|
||||
let FxSet = wrk.hasChild(FIREFOX_BRIDGE_HANDLER_NAME);
|
||||
let FxPrivateSet = wrk.hasChild(FIREFOX_PRIVATE_BRIDGE_HANDLER_NAME);
|
||||
wrk.close();
|
||||
if (FxSet && FxPrivateSet) {
|
||||
return;
|
||||
}
|
||||
wrk.open(wrk.ROOT_KEY_CURRENT_USER, "Software\\Classes", wrk.ACCESS_ALL);
|
||||
const maybeUpdateRegistry = (isSetAlready, handler, protocolName) => {
|
||||
if (isSetAlready) {
|
||||
return;
|
||||
}
|
||||
let FxKey = wrk.createChild(handler, wrk.ACCESS_ALL);
|
||||
try {
|
||||
// Write URL protocol key
|
||||
FxKey.writeStringValue("", protocolName);
|
||||
FxKey.writeStringValue("URL Protocol", "");
|
||||
FxKey.close();
|
||||
// Write defaultIcon key
|
||||
FxKey.create(
|
||||
FxKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Classes\\" + handler + "\\DefaultIcon",
|
||||
FxKey.ACCESS_ALL
|
||||
);
|
||||
FxKey.open(
|
||||
FxKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Classes\\" + handler + "\\DefaultIcon",
|
||||
FxKey.ACCESS_ALL
|
||||
);
|
||||
FxKey.writeStringValue("", `\"${path}\",1`);
|
||||
FxKey.close();
|
||||
// Write shell\\open\\command key
|
||||
FxKey.create(
|
||||
FxKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Classes\\" + handler + "\\shell",
|
||||
FxKey.ACCESS_ALL
|
||||
);
|
||||
FxKey.create(
|
||||
FxKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Classes\\" + handler + "\\shell\\open",
|
||||
FxKey.ACCESS_ALL
|
||||
);
|
||||
FxKey.create(
|
||||
FxKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Classes\\" + handler + "\\shell\\open\\command",
|
||||
FxKey.ACCESS_ALL
|
||||
);
|
||||
FxKey.open(
|
||||
FxKey.ROOT_KEY_CURRENT_USER,
|
||||
"Software\\Classes\\" + handler + "\\shell\\open\\command",
|
||||
FxKey.ACCESS_ALL
|
||||
);
|
||||
if (handler == FIREFOX_PRIVATE_BRIDGE_HANDLER_NAME) {
|
||||
FxKey.writeStringValue(
|
||||
"",
|
||||
`\"${path}\" -osint -private-window \"%1\"`
|
||||
);
|
||||
} else {
|
||||
FxKey.writeStringValue("", `\"${path}\" -osint -url \"%1\"`);
|
||||
}
|
||||
} catch (ex) {
|
||||
console.error(ex);
|
||||
} finally {
|
||||
FxKey.close();
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
maybeUpdateRegistry(
|
||||
FxSet,
|
||||
FIREFOX_BRIDGE_HANDLER_NAME,
|
||||
"URL:Firefox Bridge Protocol"
|
||||
);
|
||||
} catch (ex) {
|
||||
console.error(ex);
|
||||
}
|
||||
|
||||
try {
|
||||
maybeUpdateRegistry(
|
||||
FxPrivateSet,
|
||||
FIREFOX_PRIVATE_BRIDGE_HANDLER_NAME,
|
||||
"URL:Firefox Private Bridge Protocol"
|
||||
);
|
||||
} catch (ex) {
|
||||
console.error(ex);
|
||||
}
|
||||
} catch (ex) {
|
||||
console.error(ex);
|
||||
} finally {
|
||||
wrk.close();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
@ -7,6 +7,12 @@
|
|||
with Files("**"):
|
||||
BUG_COMPONENT = ("Firefox", "General")
|
||||
|
||||
with Files("FirefoxBridgeExtensionUtils.sys.mjs"):
|
||||
BUG_COMPONENT = ("Firefox", "Shell Integration")
|
||||
|
||||
with Files("test/unit/test_FirefoxBridgeExtensionUtils.sys.mjs"):
|
||||
BUG_COMPONENT = ("Firefox", "Shell Integration")
|
||||
|
||||
with Files("test/browser/*Telemetry*"):
|
||||
BUG_COMPONENT = ("Toolkit", "Telemetry")
|
||||
|
||||
|
|
@ -128,6 +134,7 @@ EXTRA_JS_MODULES += [
|
|||
"EveryWindow.sys.mjs",
|
||||
"ExtensionsUI.sys.mjs",
|
||||
"FaviconLoader.sys.mjs",
|
||||
"FirefoxBridgeExtensionUtils.sys.mjs",
|
||||
"HomePage.sys.mjs",
|
||||
"LaterRun.sys.mjs",
|
||||
"NewTabPagePreloading.sys.mjs",
|
||||
|
|
|
|||
350
browser/modules/test/unit/test_FirefoxBridgeExtensionUtils.js
Normal file
350
browser/modules/test/unit/test_FirefoxBridgeExtensionUtils.js
Normal file
|
|
@ -0,0 +1,350 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { FirefoxBridgeExtensionUtils } = ChromeUtils.importESModule(
|
||||
"resource:///modules/FirefoxBridgeExtensionUtils.sys.mjs"
|
||||
);
|
||||
|
||||
const FIREFOX_SHELL_OPEN_COMMAND_PATH = "firefox\\shell\\open\\command";
|
||||
const FIREFOX_PRIVATE_SHELL_OPEN_COMMAND_PATH =
|
||||
"firefox-private\\shell\\open\\command";
|
||||
|
||||
class StubbedRegistryKey {
|
||||
#children;
|
||||
#originalChildren;
|
||||
#closeCalled;
|
||||
#deletedChildren;
|
||||
#openedForRead;
|
||||
#values;
|
||||
|
||||
constructor(children, values) {
|
||||
this.#children = children;
|
||||
this.#values = values;
|
||||
this.#originalChildren = new Map(children);
|
||||
|
||||
this.#closeCalled = false;
|
||||
this.#openedForRead = false;
|
||||
this.#deletedChildren = new Set([]);
|
||||
}
|
||||
|
||||
get ACCESS_READ() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.#closeCalled = false;
|
||||
this.#deletedChildren = new Set([]);
|
||||
this.#children = new Map(this.#originalChildren);
|
||||
}
|
||||
|
||||
open(accessLevel) {
|
||||
this.#openedForRead = true;
|
||||
}
|
||||
|
||||
get wasOpenedForRead() {
|
||||
return this.#openedForRead;
|
||||
}
|
||||
|
||||
openChild(path, accessLevel) {
|
||||
const result = this.#children.get(path);
|
||||
result?.open(accessLevel);
|
||||
return result;
|
||||
}
|
||||
|
||||
hasChild(path) {
|
||||
return this.#children.has(path);
|
||||
}
|
||||
|
||||
close() {
|
||||
this.#closeCalled = true;
|
||||
}
|
||||
|
||||
removeChild(path) {
|
||||
this.#deletedChildren.add(path);
|
||||
|
||||
// delete the actual child if it's in there
|
||||
this.#children.delete(path);
|
||||
}
|
||||
|
||||
isChildDeleted(path) {
|
||||
return this.#deletedChildren.has(path);
|
||||
}
|
||||
|
||||
getChildName(index) {
|
||||
let i = 0;
|
||||
for (const [key] of this.#children) {
|
||||
if (i == index) {
|
||||
return key;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
readStringValue(name) {
|
||||
return this.#values.get(name);
|
||||
}
|
||||
|
||||
get childCount() {
|
||||
return this.#children.size;
|
||||
}
|
||||
|
||||
getValueType(entryName) {
|
||||
if (typeof this.readStringValue(entryName) == "string") {
|
||||
return Ci.nsIWindowsRegKey.TYPE_STRING;
|
||||
}
|
||||
|
||||
throw new Error(`${entryName} not found in registry`);
|
||||
}
|
||||
|
||||
get wasCloseCalled() {
|
||||
return this.#closeCalled;
|
||||
}
|
||||
|
||||
getValueName(index) {
|
||||
let i = 0;
|
||||
for (const [key] of this.#values) {
|
||||
if (i == index) {
|
||||
return key;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
get valueCount() {
|
||||
return this.#values.size;
|
||||
}
|
||||
}
|
||||
|
||||
class StubbedDeleteBridgeProtocolRegistryEntryHelper {
|
||||
#applicationPath;
|
||||
#registryRootKey;
|
||||
|
||||
constructor({ applicationPath, registryRootKey }) {
|
||||
this.#applicationPath = applicationPath;
|
||||
this.#registryRootKey = registryRootKey;
|
||||
}
|
||||
|
||||
getApplicationPath() {
|
||||
return this.#applicationPath;
|
||||
}
|
||||
|
||||
openRegistryRoot() {
|
||||
return this.#registryRootKey;
|
||||
}
|
||||
|
||||
deleteRegistryTree(root, toDeletePath) {
|
||||
// simplify this for tests
|
||||
root.removeChild(toDeletePath);
|
||||
}
|
||||
}
|
||||
|
||||
add_task(async function test_DeleteWhenSameFirefoxInstall() {
|
||||
const applicationPath = "testPath";
|
||||
|
||||
const firefoxEntries = new Map();
|
||||
firefoxEntries.set("", `\"${applicationPath}\" -osint -url \"%1\"`);
|
||||
|
||||
const firefoxProtocolRegKey = new StubbedRegistryKey(
|
||||
new Map(),
|
||||
firefoxEntries
|
||||
);
|
||||
|
||||
const firefoxPrivateEntries = new Map();
|
||||
firefoxPrivateEntries.set(
|
||||
"",
|
||||
`\"${applicationPath}\" -osint -private-window \"%1\"`
|
||||
);
|
||||
const firefoxPrivateProtocolRegKey = new StubbedRegistryKey(
|
||||
new Map(),
|
||||
firefoxPrivateEntries
|
||||
);
|
||||
|
||||
const children = new Map();
|
||||
children.set(FIREFOX_SHELL_OPEN_COMMAND_PATH, firefoxProtocolRegKey);
|
||||
children.set(
|
||||
FIREFOX_PRIVATE_SHELL_OPEN_COMMAND_PATH,
|
||||
firefoxPrivateProtocolRegKey
|
||||
);
|
||||
|
||||
const registryRootKey = new StubbedRegistryKey(children, new Map());
|
||||
|
||||
const stubbedDeleteBridgeProtocolRegistryHelper =
|
||||
new StubbedDeleteBridgeProtocolRegistryEntryHelper({
|
||||
applicationPath,
|
||||
registryRootKey,
|
||||
});
|
||||
|
||||
FirefoxBridgeExtensionUtils.maybeDeleteBridgeProtocolRegistryEntries(
|
||||
stubbedDeleteBridgeProtocolRegistryHelper
|
||||
);
|
||||
|
||||
ok(registryRootKey.wasCloseCalled, "Root key closed");
|
||||
|
||||
ok(firefoxProtocolRegKey.wasOpenedForRead, "Firefox key opened");
|
||||
ok(firefoxProtocolRegKey.wasCloseCalled, "Firefox key closed");
|
||||
ok(
|
||||
registryRootKey.isChildDeleted("firefox"),
|
||||
"Firefox protocol registry entry deleted"
|
||||
);
|
||||
|
||||
ok(
|
||||
firefoxPrivateProtocolRegKey.wasOpenedForRead,
|
||||
"Firefox private key opened"
|
||||
);
|
||||
ok(firefoxPrivateProtocolRegKey.wasCloseCalled, "Firefox private key closed");
|
||||
ok(
|
||||
registryRootKey.isChildDeleted("firefox-private"),
|
||||
"Firefox private protocol registry entry deleted"
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function test_DeleteWhenDifferentFirefoxInstall() {
|
||||
const applicationPath = "testPath";
|
||||
const badApplicationPath = "testPath2";
|
||||
|
||||
const firefoxEntries = new Map();
|
||||
firefoxEntries.set("", `\"${badApplicationPath}\" -osint -url \"%1\"`);
|
||||
|
||||
const firefoxProtocolRegKey = new StubbedRegistryKey(
|
||||
new Map(),
|
||||
firefoxEntries
|
||||
);
|
||||
|
||||
const firefoxPrivateEntries = new Map();
|
||||
firefoxPrivateEntries.set(
|
||||
"",
|
||||
`\"${badApplicationPath}\" -osint -private-window \"%1\"`
|
||||
);
|
||||
const firefoxPrivateProtocolRegKey = new StubbedRegistryKey(
|
||||
new Map(),
|
||||
firefoxPrivateEntries
|
||||
);
|
||||
|
||||
const children = new Map();
|
||||
children.set(FIREFOX_SHELL_OPEN_COMMAND_PATH, firefoxProtocolRegKey);
|
||||
children.set(
|
||||
FIREFOX_PRIVATE_SHELL_OPEN_COMMAND_PATH,
|
||||
firefoxPrivateProtocolRegKey
|
||||
);
|
||||
|
||||
const registryRootKey = new StubbedRegistryKey(children, new Map());
|
||||
|
||||
const stubbedDeleteBridgeProtocolRegistryHelper =
|
||||
new StubbedDeleteBridgeProtocolRegistryEntryHelper({
|
||||
applicationPath,
|
||||
registryRootKey,
|
||||
});
|
||||
|
||||
FirefoxBridgeExtensionUtils.maybeDeleteBridgeProtocolRegistryEntries(
|
||||
stubbedDeleteBridgeProtocolRegistryHelper
|
||||
);
|
||||
|
||||
ok(registryRootKey.wasCloseCalled, "Root key closed");
|
||||
|
||||
ok(firefoxProtocolRegKey.wasOpenedForRead, "Firefox key opened");
|
||||
ok(firefoxProtocolRegKey.wasCloseCalled, "Firefox key closed");
|
||||
ok(
|
||||
!registryRootKey.isChildDeleted("firefox"),
|
||||
"Firefox protocol registry entry not deleted"
|
||||
);
|
||||
|
||||
ok(
|
||||
firefoxPrivateProtocolRegKey.wasOpenedForRead,
|
||||
"Firefox private key opened"
|
||||
);
|
||||
ok(firefoxPrivateProtocolRegKey.wasCloseCalled, "Firefox private key closed");
|
||||
ok(
|
||||
!registryRootKey.isChildDeleted("firefox-private"),
|
||||
"Firefox private protocol registry entry not deleted"
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function test_DeleteWhenNoRegistryEntries() {
|
||||
const applicationPath = "testPath";
|
||||
|
||||
const firefoxPrivateEntries = new Map();
|
||||
const firefoxPrivateProtocolRegKey = new StubbedRegistryKey(
|
||||
new Map(),
|
||||
firefoxPrivateEntries
|
||||
);
|
||||
|
||||
const children = new Map();
|
||||
children.set(
|
||||
FIREFOX_PRIVATE_SHELL_OPEN_COMMAND_PATH,
|
||||
firefoxPrivateProtocolRegKey
|
||||
);
|
||||
|
||||
const registryRootKey = new StubbedRegistryKey(children, new Map());
|
||||
|
||||
const stubbedDeleteBridgeProtocolRegistryHelper =
|
||||
new StubbedDeleteBridgeProtocolRegistryEntryHelper({
|
||||
applicationPath,
|
||||
registryRootKey,
|
||||
});
|
||||
|
||||
FirefoxBridgeExtensionUtils.maybeDeleteBridgeProtocolRegistryEntries(
|
||||
stubbedDeleteBridgeProtocolRegistryHelper
|
||||
);
|
||||
|
||||
ok(registryRootKey.wasCloseCalled, "Root key closed");
|
||||
|
||||
ok(
|
||||
firefoxPrivateProtocolRegKey.wasOpenedForRead,
|
||||
"Firefox private key opened"
|
||||
);
|
||||
ok(firefoxPrivateProtocolRegKey.wasCloseCalled, "Firefox private key closed");
|
||||
ok(
|
||||
!registryRootKey.isChildDeleted("firefox"),
|
||||
"Firefox protocol registry entry deleted when it shouldn't be"
|
||||
);
|
||||
ok(
|
||||
!registryRootKey.isChildDeleted("firefox-private"),
|
||||
"Firefox private protocol registry deleted when it shouldn't be"
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function test_DeleteWhenUnexpectedRegistryEntries() {
|
||||
const applicationPath = "testPath";
|
||||
|
||||
const firefoxEntries = new Map();
|
||||
firefoxEntries.set("", `\"${applicationPath}\" -osint -url \"%1\"`);
|
||||
firefoxEntries.set("extraEntry", "extraValue");
|
||||
const firefoxProtocolRegKey = new StubbedRegistryKey(
|
||||
new Map(),
|
||||
firefoxEntries
|
||||
);
|
||||
|
||||
const children = new Map();
|
||||
children.set(FIREFOX_SHELL_OPEN_COMMAND_PATH, firefoxProtocolRegKey);
|
||||
|
||||
const registryRootKey = new StubbedRegistryKey(children, new Map());
|
||||
|
||||
const stubbedDeleteBridgeProtocolRegistryHelper =
|
||||
new StubbedDeleteBridgeProtocolRegistryEntryHelper({
|
||||
applicationPath,
|
||||
registryRootKey,
|
||||
});
|
||||
|
||||
FirefoxBridgeExtensionUtils.maybeDeleteBridgeProtocolRegistryEntries(
|
||||
stubbedDeleteBridgeProtocolRegistryHelper
|
||||
);
|
||||
|
||||
ok(registryRootKey.wasCloseCalled, "Root key closed");
|
||||
|
||||
ok(firefoxProtocolRegKey.wasOpenedForRead, "Firefox key opened");
|
||||
ok(firefoxProtocolRegKey.wasCloseCalled, "Firefox key closed");
|
||||
ok(
|
||||
!registryRootKey.isChildDeleted("firefox"),
|
||||
"Firefox protocol registry entry deleted when it shouldn't be"
|
||||
);
|
||||
ok(
|
||||
!registryRootKey.isChildDeleted("firefox-private"),
|
||||
"Firefox private protocol registry deleted when it shouldn't be"
|
||||
);
|
||||
});
|
||||
|
|
@ -5,6 +5,9 @@ skip-if = ["os == 'android'"] # bug 1730213
|
|||
|
||||
["test_E10SUtils_nested_URIs.js"]
|
||||
|
||||
["test_FirefoxBridgeExtensionUtils.js"]
|
||||
run-if = ["os == 'win'"] # Test of a Windows-specific feature
|
||||
|
||||
["test_HomePage.js"]
|
||||
|
||||
["test_HomePage_ignore.js"]
|
||||
|
|
|
|||
|
|
@ -1074,8 +1074,8 @@ pref("network.protocol-handler.external.disk", false);
|
|||
pref("network.protocol-handler.external.disks", false);
|
||||
pref("network.protocol-handler.external.afp", false);
|
||||
pref("network.protocol-handler.external.moz-icon", false);
|
||||
pref("network.protocol-handler.external.firefox", false);
|
||||
pref("network.protocol-handler.external.firefox-private", false);
|
||||
pref("network.protocol-handler.external.firefox-bridge", false);
|
||||
pref("network.protocol-handler.external.firefox-private-bridge", false);
|
||||
|
||||
// Don't allow external protocol handlers for common typos
|
||||
pref("network.protocol-handler.external.ttp", false); // http
|
||||
|
|
|
|||
Loading…
Reference in a new issue