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>
|
<string>Firefox Protocol</string>
|
||||||
<key>CFBundleURLSchemes</key>
|
<key>CFBundleURLSchemes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>firefox</string>
|
<string>firefox-bridge</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
|
|
@ -245,7 +245,7 @@
|
||||||
<string>Firefox Private Browsing Protocol</string>
|
<string>Firefox Private Browsing Protocol</string>
|
||||||
<key>CFBundleURLSchemes</key>
|
<key>CFBundleURLSchemes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>firefox-private</string>
|
<string>firefox-private-bridge</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
|
|
|
||||||
|
|
@ -298,9 +298,6 @@ pref("browser.shell.checkDefaultPDF.silencedByUser", false);
|
||||||
// URL to navigate to when launching Firefox after accepting the Windows Default
|
// URL to navigate to when launching Firefox after accepting the Windows Default
|
||||||
// Browser Agent "Set Firefox as default" call to action.
|
// Browser Agent "Set Firefox as default" call to action.
|
||||||
pref("browser.shell.defaultBrowserAgent.thanksURL", "https://www.mozilla.org/%LOCALE%/firefox/set-as-default/thanks/");
|
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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ function resolveURIInternal(
|
||||||
if (aArgument.startsWith(protocolWithColon)) {
|
if (aArgument.startsWith(protocolWithColon)) {
|
||||||
if (!validateFirefoxProtocol(aCmdLine, launchedWithArg_osint)) {
|
if (!validateFirefoxProtocol(aCmdLine, launchedWithArg_osint)) {
|
||||||
throw new Error(
|
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);
|
aArgument = aArgument.substring(protocolWithColon.length);
|
||||||
|
|
@ -100,7 +100,7 @@ function resolveURIInternal(
|
||||||
!aArgument.startsWith("https://")
|
!aArgument.startsWith("https://")
|
||||||
) {
|
) {
|
||||||
throw new Error(
|
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-bridge");
|
||||||
handleFirefoxProtocol("firefox-private");
|
handleFirefoxProtocol("firefox-private-bridge");
|
||||||
|
|
||||||
var uri = aCmdLine.resolveURI(aArgument);
|
var uri = aCmdLine.resolveURI(aArgument);
|
||||||
var uriFixup = Services.uriFixup;
|
var uriFixup = Services.uriFixup;
|
||||||
|
|
@ -599,7 +599,7 @@ nsBrowserContentHandler.prototype = {
|
||||||
if (urlFlagIdx > -1 && cmdLine.length > 1) {
|
if (urlFlagIdx > -1 && cmdLine.length > 1) {
|
||||||
url = cmdLine.getArgument(urlFlagIdx + 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
|
// Check if the osint flag is present on Windows
|
||||||
let launchedWithArg_osint =
|
let launchedWithArg_osint =
|
||||||
AppConstants.platform == "win" &&
|
AppConstants.platform == "win" &&
|
||||||
|
|
@ -614,7 +614,7 @@ nsBrowserContentHandler.prototype = {
|
||||||
uri: Services.io.newURI("about:privatebrowsing"),
|
uri: Services.io.newURI("about:privatebrowsing"),
|
||||||
principal: lazy.gSystemPrincipal,
|
principal: lazy.gSystemPrincipal,
|
||||||
};
|
};
|
||||||
} else if (url?.startsWith("firefox-private:")) {
|
} else if (url?.startsWith("firefox-private-bridge:")) {
|
||||||
cmdLine.removeArguments(urlFlagIdx, urlFlagIdx + 1);
|
cmdLine.removeArguments(urlFlagIdx, urlFlagIdx + 1);
|
||||||
resolvedInfo = resolveURIInternal(
|
resolvedInfo = resolveURIInternal(
|
||||||
cmdLine,
|
cmdLine,
|
||||||
|
|
@ -1463,7 +1463,7 @@ nsDefaultCommandLineHandler.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can't open multiple URLs without using system principal.
|
// 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
|
// accept a single URL due to using the -osint option
|
||||||
// so this isn't very relevant.
|
// so this isn't very relevant.
|
||||||
var URLlist = urilist.filter(shouldLoadURI).map(u => u.spec);
|
var URLlist = urilist.filter(shouldLoadURI).map(u => u.spec);
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||||
E10SUtils: "resource://gre/modules/E10SUtils.sys.mjs",
|
E10SUtils: "resource://gre/modules/E10SUtils.sys.mjs",
|
||||||
ExtensionsUI: "resource:///modules/ExtensionsUI.sys.mjs",
|
ExtensionsUI: "resource:///modules/ExtensionsUI.sys.mjs",
|
||||||
FeatureGate: "resource://featuregates/FeatureGate.sys.mjs",
|
FeatureGate: "resource://featuregates/FeatureGate.sys.mjs",
|
||||||
|
FirefoxBridgeExtensionUtils:
|
||||||
|
"resource:///modules/FirefoxBridgeExtensionUtils.sys.mjs",
|
||||||
FxAccounts: "resource://gre/modules/FxAccounts.sys.mjs",
|
FxAccounts: "resource://gre/modules/FxAccounts.sys.mjs",
|
||||||
HomePage: "resource:///modules/HomePage.sys.mjs",
|
HomePage: "resource:///modules/HomePage.sys.mjs",
|
||||||
Integration: "resource://gre/modules/Integration.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
|
// Ensure a Private Browsing Shortcut exists. This is needed in case
|
||||||
// a user tries to use Windows functionality to pin our Private Browsing
|
// 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).
|
// mode icon to the Taskbar (eg: the "Pin to Taskbar" context menu item).
|
||||||
|
|
@ -3821,13 +3703,20 @@ BrowserGlue.prototype = {
|
||||||
_migrateUI() {
|
_migrateUI() {
|
||||||
// Use an increasing number to keep track of the current migration state.
|
// Use an increasing number to keep track of the current migration state.
|
||||||
// Completely unrelated to the current Firefox release number.
|
// Completely unrelated to the current Firefox release number.
|
||||||
const UI_VERSION = 142;
|
const UI_VERSION = 143;
|
||||||
const BROWSER_DOCURL = AppConstants.BROWSER_CHROME_URL;
|
const BROWSER_DOCURL = AppConstants.BROWSER_CHROME_URL;
|
||||||
|
|
||||||
if (!Services.prefs.prefHasUserValue("browser.migration.version")) {
|
if (!Services.prefs.prefHasUserValue("browser.migration.version")) {
|
||||||
// This is a new profile, nothing to migrate.
|
// This is a new profile, nothing to migrate.
|
||||||
Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
|
Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
|
||||||
this._isNewProfile = true;
|
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;
|
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.
|
// Update the migration version.
|
||||||
Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
|
Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -92,14 +92,14 @@
|
||||||
</uap3:Protocol>
|
</uap3:Protocol>
|
||||||
</uap3:Extension>
|
</uap3:Extension>
|
||||||
<uap3:Extension Category="windows.protocol">
|
<uap3:Extension Category="windows.protocol">
|
||||||
<uap3:Protocol Name="firefox" Parameters="-osint -url "%1"">
|
<uap3:Protocol Name="firefox-bridge" Parameters="-osint -url "%1"">
|
||||||
<uap:DisplayName>Firefox Protocol</uap:DisplayName>
|
<uap:DisplayName>Firefox Bridge Protocol</uap:DisplayName>
|
||||||
<uap:Logo>Assets\Document44x44.png</uap:Logo>
|
<uap:Logo>Assets\Document44x44.png</uap:Logo>
|
||||||
</uap3:Protocol>
|
</uap3:Protocol>
|
||||||
</uap3:Extension>
|
</uap3:Extension>
|
||||||
<uap3:Extension Category="windows.protocol">
|
<uap3:Extension Category="windows.protocol">
|
||||||
<uap3:Protocol Name="firefox-private" Parameters="-osint -private-window "%1"">
|
<uap3:Protocol Name="firefox-private-bridge" Parameters="-osint -private-window "%1"">
|
||||||
<uap:DisplayName>Firefox Private Browsing Protocol</uap:DisplayName>
|
<uap:DisplayName>Firefox Private Bridge Protocol</uap:DisplayName>
|
||||||
<uap:Logo>Assets\Document44x44.png</uap:Logo>
|
<uap:Logo>Assets\Document44x44.png</uap:Logo>
|
||||||
</uap3:Protocol>
|
</uap3:Protocol>
|
||||||
</uap3:Extension>
|
</uap3:Extension>
|
||||||
|
|
|
||||||
|
|
@ -474,22 +474,22 @@ Section "-Application" APP_IDX
|
||||||
${AddDisabledDDEHandlerValues} "FirefoxURL-$AppUserModelID" "$2" "$8,${IDI_DOCUMENT_ZERO_BASED}" \
|
${AddDisabledDDEHandlerValues} "FirefoxURL-$AppUserModelID" "$2" "$8,${IDI_DOCUMENT_ZERO_BASED}" \
|
||||||
"${AppRegName} URL" "true"
|
"${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
|
SetShellVarContext current ; Set SHCTX to HKCU
|
||||||
!define FIREFOX_PROTOCOL "firefox"
|
!define FIREFOX_PROTOCOL "firefox-bridge"
|
||||||
ClearErrors
|
ClearErrors
|
||||||
ReadRegStr $0 SHCTX "Software\Classes\${FIREFOX_PROTOCOL}" ""
|
ReadRegStr $0 SHCTX "Software\Classes\${FIREFOX_PROTOCOL}" ""
|
||||||
${If} $0 == ""
|
${If} $0 == ""
|
||||||
${AddDisabledDDEHandlerValues} "${FIREFOX_PROTOCOL}" "$2" "$8,${IDI_APPICON_ZERO_BASED}" \
|
${AddDisabledDDEHandlerValues} "${FIREFOX_PROTOCOL}" "$2" "$8,${IDI_APPICON_ZERO_BASED}" \
|
||||||
"Firefox Browsing Protocol" "true"
|
"Firefox Bridge Protocol" "true"
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
!define FIREFOX_PRIVATE_PROTOCOL "firefox-private"
|
!define FIREFOX_PRIVATE_PROTOCOL "firefox-private-bridge"
|
||||||
ClearErrors
|
ClearErrors
|
||||||
ReadRegStr $0 SHCTX "Software\Classes\${FIREFOX_PRIVATE_PROTOCOL}" ""
|
ReadRegStr $0 SHCTX "Software\Classes\${FIREFOX_PRIVATE_PROTOCOL}" ""
|
||||||
${If} $0 == ""
|
${If} $0 == ""
|
||||||
${AddDisabledDDEHandlerValues} "${FIREFOX_PRIVATE_PROTOCOL}" "$\"$8$\" -osint -private-window $\"%1$\"" \
|
${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}
|
${EndIf}
|
||||||
SetShellVarContext all ; Set SHCTX to HKLM
|
SetShellVarContext all ; Set SHCTX to HKLM
|
||||||
|
|
||||||
|
|
@ -794,6 +794,15 @@ Section "-InstallEndCleanup"
|
||||||
; Refresh desktop icons
|
; Refresh desktop icons
|
||||||
${RefreshShellIcons}
|
${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}
|
${InstallEndCleanupCommon}
|
||||||
|
|
||||||
${If} $PreventRebootRequired == "true"
|
${If} $PreventRebootRequired == "true"
|
||||||
|
|
|
||||||
|
|
@ -1824,3 +1824,49 @@ FunctionEnd
|
||||||
${WriteRegStr2} ${RegKey} "Software\Classes\CLSID\$0\InProcServer32" "" "$INSTDIR\notificationserver.dll" 0
|
${WriteRegStr2} ${RegKey} "Software\Classes\CLSID\$0\InProcServer32" "" "$INSTDIR\notificationserver.dll" 0
|
||||||
!macroend
|
!macroend
|
||||||
!define WriteToastNotificationRegistration "!insertmacro WriteToastNotificationRegistration"
|
!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
|
# 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"
|
Section "Uninstall"
|
||||||
SetDetailsPrint textonly
|
SetDetailsPrint textonly
|
||||||
DetailPrint $(STATUS_UNINSTALL_MAIN)
|
DetailPrint $(STATUS_UNINSTALL_MAIN)
|
||||||
|
|
@ -571,9 +523,12 @@ Section "Uninstall"
|
||||||
; Clean up "launch on login" registry key for this installation.
|
; Clean up "launch on login" registry key for this installation.
|
||||||
DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "Mozilla-${AppName}-$AppUserModelID"
|
DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "Mozilla-${AppName}-$AppUserModelID"
|
||||||
|
|
||||||
; Remove dual browser extension protocol handlers
|
; Remove FirefoxBridge extension protocol handlers
|
||||||
${DeleteProtocolRegistryIfSetToInstallation} "firefox"
|
Push $1
|
||||||
${DeleteProtocolRegistryIfSetToInstallation} "firefox-private"
|
${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
|
; Remove old protocol handler and StartMenuInternet keys without install path
|
||||||
; hashes, but only if they're for this installation. We've never supported
|
; 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("**"):
|
with Files("**"):
|
||||||
BUG_COMPONENT = ("Firefox", "General")
|
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*"):
|
with Files("test/browser/*Telemetry*"):
|
||||||
BUG_COMPONENT = ("Toolkit", "Telemetry")
|
BUG_COMPONENT = ("Toolkit", "Telemetry")
|
||||||
|
|
||||||
|
|
@ -128,6 +134,7 @@ EXTRA_JS_MODULES += [
|
||||||
"EveryWindow.sys.mjs",
|
"EveryWindow.sys.mjs",
|
||||||
"ExtensionsUI.sys.mjs",
|
"ExtensionsUI.sys.mjs",
|
||||||
"FaviconLoader.sys.mjs",
|
"FaviconLoader.sys.mjs",
|
||||||
|
"FirefoxBridgeExtensionUtils.sys.mjs",
|
||||||
"HomePage.sys.mjs",
|
"HomePage.sys.mjs",
|
||||||
"LaterRun.sys.mjs",
|
"LaterRun.sys.mjs",
|
||||||
"NewTabPagePreloading.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_E10SUtils_nested_URIs.js"]
|
||||||
|
|
||||||
|
["test_FirefoxBridgeExtensionUtils.js"]
|
||||||
|
run-if = ["os == 'win'"] # Test of a Windows-specific feature
|
||||||
|
|
||||||
["test_HomePage.js"]
|
["test_HomePage.js"]
|
||||||
|
|
||||||
["test_HomePage_ignore.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.disks", false);
|
||||||
pref("network.protocol-handler.external.afp", false);
|
pref("network.protocol-handler.external.afp", false);
|
||||||
pref("network.protocol-handler.external.moz-icon", false);
|
pref("network.protocol-handler.external.moz-icon", false);
|
||||||
pref("network.protocol-handler.external.firefox", false);
|
pref("network.protocol-handler.external.firefox-bridge", false);
|
||||||
pref("network.protocol-handler.external.firefox-private", false);
|
pref("network.protocol-handler.external.firefox-private-bridge", false);
|
||||||
|
|
||||||
// Don't allow external protocol handlers for common typos
|
// Don't allow external protocol handlers for common typos
|
||||||
pref("network.protocol-handler.external.ttp", false); // http
|
pref("network.protocol-handler.external.ttp", false); // http
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue