/* 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/. */ #include "imgIContainer.idl" #include "nsIShellService.idl" interface nsIFile; [scriptable, uuid(fb9b59db-5a91-4e67-92b6-35e7d6e6d3fd)] interface nsIWindowsShellService : nsIShellService { /* * Bit flags for launchSetDefaultAppPicker's aFlags argument. They map 1:1 * onto the flags accepted by the undocumented Windows IOpenWithLauncher COM * interface's Launch method. * The mapping below was determined empirically and determines the picker's * messaging and actions. */ // Suppresses the default open-in-selected-app behavior. Remote-controlled // by Microsoft. const long OPEN_WITH_SUPPRESS_OPEN = 1 << 2; // Switches picker messaging to protocol mode ("Select a default handler // for ___ links"). const long OPEN_WITH_PROTOCOL_MESSAGING = 1 << 3; // Opens with the selected app just once; does not set a default. const long OPEN_WITH_OPEN_ONCE = 1 << 6; // Asks the user to set a default for the given file type or protocol. Messaging is // ideal on Windows 11 only. const long OPEN_WITH_SET_HANDLER = 1 << 7; // Like OPEN_WITH_SET_HANDLER, but with ideal messaging for Windows 10. const long OPEN_WITH_SET_HANDLER_WIN10 = 1 << 13; /* * Creates a new shortcut (.lnk) file. This shortcut will be recorded in * a new shortcuts log file located in %PROGRAMDATA%\Mozilla-1de4eec8-1241-4177-a864-e594e8d1fb38 * that is named after the currently running application and current user, eg: * Firefox_user123_shortcuts.ini. * * For reasons that we haven't been able to pin down, these shortcuts get created with * extra metadata on them (KnownFolderDataBlock, SpecialFolderDataBlock) that cause * the Windows ShellLink classes to improperly read their target path with certain * parameters. This causes any 32-bit programs that read the links (such as our * installer and uninstaller) to think that 64-bit installs are located in the 32-bit * Program Files directory. * See https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/6f2e7920-50a9-459d-bfdd-316e459e87c0/ishelllink-getpath-returns-wrong-folder-for-64-bit-application-when-called-from-32-bit-application * for some additional discussion of this. * * @param aBinary Target file of the shortcut. * @param aArguments Arguments to set for the shortcut. May be empty. * @param aDescription The description of the shortcut. The string used here * shows up as the hover text of the shortcut in Explorer and on the * Taskbar (if the shortcut is pinned there). * @param aIconFile The file containing the desired icon for the shortcut. This * can be the same file as aBinary. * @param aIconIndex The index of the in aIconFile. Note that this is 0 based index * that IShellLinkW requires, _not_ a Resource ID that is sometimes used * for icons. * @param aAppUserModelId The App User Model ID to set for the shortcut. This will * affect which icon on the Taskbar the application groups with when first * launched. * @param aShortcutFolder The special Windows folder to create the shortcut in. Must be * either "Programs" or "Desktop". * @param aShortcutRelativePath The relative path of the shortcut from the shortcut * folder. * @return The full native path to the created shortcut. * * @throws NS_ERROR_INVALID_ARG if an invalid shortcut folder is passed * @throws NS_ERROR_FILE_NOT_FOUND if the shortcut file or shortcuts log cannot be * created or accessed * @throws NS_ERROR_FAILURE for other types of failures */ [implicit_jscontext] Promise createShortcut(in nsIFile aBinary, in Array aArguments, in AString aDescription, in nsIFile aIconFile, in unsigned short aIconIndex, in AString aAppUserModelId, in AString aShortcutFolder, in AString aShortcutRelativePath); /* * Deletes the provided shortcut path relative to the shortcut folder, and removes it * from the uninstaller's log file. * * @param aShortcutFolder The special Windows folder to create the shortcut in. * Should be either Desktop or StartMenu. * @param aShortcutRelativePath The relative path to the shortcut file from the folder. * * @throws NS_ERROR_INVALID_ARG if an invalid shortcut folder is passed */ [implicit_jscontext] Promise deleteShortcut(in AString aShortcutFolder, in AString aShortcutRelativePath); /* * Searches the %USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup * folder and returns an array with the path of all shortcuts with a target matching the * current Firefox install location. The AUMID isn't required here as we are only looking * for the currently running binary, whether that's firefox.exe or the private browsing * proxy executable. * * It is possible to return an empty array if no shortcuts are found. * * @return An array of paths for all launch on login shortcuts.s * * @throws NS_ERROR_ABORT * if instance cannot be created. * @throws NS_ERROR_FILE_NOT_FOUND * if %USERPROFILE%\AppData\Roaming\ cannot be opened. * @throws NS_ERROR_FAILURE * if the executable file cannot be found. * @throws NS_ERROR_FILE_UNRECOGNIZED_PATH * if the executable file cannot be converted into a string. */ Array getLaunchOnLoginShortcuts(); /* * Pins the current application to the Windows Start Menu * * The APIs used within this function are MSIX only and * will also not work on MINGW. * * @return True if the application was successfully pinned * to the Start Menu. * * @throws NS_ERROR_NOT_AVAILABLE * If used on a non-MSIX build * @throws NS_ERROR_NOT_IMPLEMENTED * If used on a MinGW build * @throws NS_ERROR_NOT_SAME_THREAD * If called off main thread * @throws NS_ERROR_FAILURE * For Windows API failures */ [implicit_jscontext] Promise pinCurrentAppToStartMenu(); /* * Whether the current app is among Windows Start Menu pins * * @return True if pinned, false otherwise * * The APIs used within this function are MSIX only and * will also not work on MINGW. * * @throws NS_ERROR_NOT_AVAILABLE * If used on a non-MSIX build * @throws NS_ERROR_NOT_IMPLEMENTED * If used on a MinGW build * @throws NS_ERROR_NOT_SAME_THREAD * If called off main thread * @throws NS_ERROR_FAILURE * For Windows API failures */ [implicit_jscontext] Promise isCurrentAppPinnedToStartMenu(); /* * Disables the startup task corresponding to the provided taskId * to launch upon OS login. The startup task is declared * within the App Manifest. * * If the task was previously disabled by the user this function * will not re-enable it. * * The APIs used within this function are MSIX only and * will also not work on MINGW. * * @param aTaskId Target taskId to enable * * @return True if the application was successfully set up to * launch on OS login. * * @throws NS_ERROR_NOT_AVAILABLE * If used on a non-MSIX build * @throws NS_ERROR_NOT_IMPLEMENTED * If used on a MinGW build * @throws NS_ERROR_NOT_SAME_THREAD * If called off main thread * @throws NS_ERROR_FAILURE * For other types of failures */ [implicit_jscontext] Promise enableLaunchOnLoginMSIX(in AString aTaskId); /* * Disables the startup task corresponding to the provided taskId * to launch upon OS login. The startup task is declared * within the App Manifest. * * The APIs used within this function are MSIX only and * will also not work on MINGW. * * @param aTaskId Target taskId to disable * * @return True if the application was successfully disabled from * launching on OS login. * * @throws NS_ERROR_NOT_AVAILABLE * If used on a non-MSIX build * @throws NS_ERROR_NOT_IMPLEMENTED * If used on a MinGW build * @throws NS_ERROR_NOT_SAME_THREAD * If called off main thread * @throws NS_ERROR_FAILURE * For other types of failures */ [implicit_jscontext] Promise disableLaunchOnLoginMSIX(in AString aTaskId); /* * Status of launch on login enablement. */ cenum LaunchOnLoginEnabledEnumerator : 8 { LAUNCH_ON_LOGIN_DISABLED_BY_SETTINGS = 0, LAUNCH_ON_LOGIN_DISABLED = 1, LAUNCH_ON_LOGIN_ENABLED = 2, LAUNCH_ON_LOGIN_ENABLED_BY_POLICY = 3, }; /* * Determines if the startup task corresponding to the provided taskId to * launch upon OS login is enabled. The startup task is declared * within the App Manifest. The APIs used within this function are MSIX * only and will also not work on MINGW. * * If the user has disabled the application from launching on login, it * cannot be re-enabled by the application. * * @param aTaskId Target taskId to check status of * * @return 0/1/2/3 if the application's OS launch on login is disabled in settings / disabled / enabled / enabled by policy * * @throws NS_ERROR_NOT_AVAILABLE * If used on a non-MSIX build * @throws NS_ERROR_NOT_IMPLEMENTED * If used on a MinGW build * @throws NS_ERROR_NOT_SAME_THREAD * If called off main thread * @throws NS_ERROR_FAILURE * For other types of failures */ [implicit_jscontext] Promise getLaunchOnLoginEnabledMSIX(in AString aTaskId); /* * Result for attempts to pin to taskbar. */ cenum PinResult : 8 { // Successfully pinned. PINNED, // User or system rejected pin attempt. REJECTED, // Result of pin attempt unknown. Examples include when we intentionally // return before the user choice is known, and when using APIs which don't // provide means to know the success or failure of the pin attempt. UNKNOWN, }; /* * Pin the current app to the taskbar. If aPrivateBrowsing is true, the * Private Browsing version of the app (with a different icon and launch * arguments) will be pinned instead. * * This MUST only be used in response to an active request from the user. * * If it exists, uses an existing shortcut on the User or Common Start Menu, * which would have been created by the installer (for All Users or * Current User). If none can be found, one will be created with the correct * AUMID in the User Start Menu for proper launching and grouping. * * NOTE: It is possible for the shortcut match to fail even when a * shortcut refers to the current executable, if the paths differ due * to e.g. symlinks. This should be rare. * * This will definitely fail on an OS before Windows 10 build 1809 * (October 2018 Update). * * @param aPrivateBrowsing * Pins private browsing. * @param aFireAndForget * Skips waiting for user to confirm or reject pin prompt if present. * * @throws NS_ERROR_NOT_SAME_THREAD * if called off main thread. * @throws NS_ERROR_NOT_AVAILABLE * if OS is not at least Windows 10 build 1809, or if creating the * Taskband Pin object fails * @throws NS_ERROR_FAILURE * for unexpected errors * * @rejects NS_ERROR_FILE_NOT_FOUND * if a shortcut matching this app's AUMID and exe path wasn't found in shell:appsfolder * * @returns {Promise} A Promise that resolves to * nsIWindowsShellService_PinResult if * successful or rejects with an nserror. */ [implicit_jscontext] Promise pinCurrentAppToTaskbar(in boolean aPrivateBrowsing, [optional] in boolean aFireAndForget); /* * Checks if a taskbar pinning API is available. * * @throws NS_ERROR_NOT_SAME_THREAD * if called off main thread * @throws NS_ERROR_NOT_AVAILABLE * if pinning APIs are unavailable for use */ void canPinToTaskbar(); /* * Search for the current executable among taskbar pins * * NOTE: It is possible for the check to fail even when a taskbar pin refers * to this executable, if the paths differ due to e.g. symlinks. * It is also possible for the check to succeed with a shortcut that doesn't * actually appear on the taskbar. * These cases should be rare. * * @return Promise that always resolves, true if pinned, false otherwise * @throws NS_ERROR_NOT_SAME_THREAD if not run on the main thread * */ [implicit_jscontext] Promise isCurrentAppPinnedToTaskbar(in AString aumid); /* * Similar to createShortcut except it removes most of the checking in that * function that ensures we are pinning a Firefox executable instead allowing * any shortcut to be pinned. * * This function should not be called unless it is certain that it's * necessary given how few checks there are within. * @param aAppUserModelId * The aumid to be contained in the .lnk file * @param aShortcutFolder The special Windows folder to create the shortcut * in. Must be either "Programs" or "Desktop". * @param aShortcutRelativePath * The path to the .lnk file that should be pinned to the taskbar, * relative to aShortcutFolder. * @returns {Promise} A Promise that resolves to * nsIWindowsShellService_PinResult if * successful or rejects with an nserror. */ [implicit_jscontext] Promise pinShortcutToTaskbar( in AString aAppUserModelId, in AString aShortcutFolder, in AString aShortcutRelativePath ); /* * This function is a counterpart to pinShortcutToTaskbar and allows * the unpinning of any shortcut, including non-Firefox executables, * without the checks of createShortcut. * * This function should not be called unless it is certain that it's * necessary given how few checks there are within. * @param aShortcutFolder The special Windows folder that the shortcut * is in. Must be either "Programs" or "Desktop". * @param aShortcutRelativePath * The path to the .lnk file that should be unpinned, relative * to aShortcutFolder. * @throws NS_ERROR_FAILURE * If the COM service could not be initialized * @throws NS_ERROR_FILE_NOT_FOUND * If aShortcutPath cannot be found * @throws NS_ERROR_NOT_AVAILABLE * If the taskbar pinning service cannot be initialized * @throws NS_ERROR_FILE_ACCESS_DENIED * If the taskbar pins cannot be modified */ void unpinShortcutFromTaskbar( in AString aShortcutFolder, in AString aShortcutRelativePath ); /* * Launch the default app picker via the Windows IOpenWithLauncher COM * interface. The caller picks the target (a file path whose extension * determines the picker for file-type defaults, or a URL for protocol * defaults) and the flag bits that drive the picker's messaging and actions. * * @param aTarget * File path or URL. * @param aFlags * Flag combination that determines the behavior of the IOpenWithLauncher dialog. * @throws NS_ERROR_FAILURE * If IOpenWithLauncher is unavailable or fails. */ void launchSetDefaultAppPicker(in AString aTarget, in long aFlags); /* * Open the Windows modern settings dialog for choosing default apps * (ms-settings:defaultapps). * * @throws NS_ERROR_FAILURE * If the settings dialog cannot be launched. */ void launchModernSettingsDialogDefaultApps(); /* * Determine where a given shortcut likely appears in the shell. * * Returns one of: * - "StartMenu" or "StartMenuPrivate", Current User or All Users Start * Menu, including pins * - "Desktop" or "DesktopPrivate", Current User or All Users Desktop * - "Taskbar" or "TaskbarPrivate", Taskbar Pins * - "" otherwise * * If a Private Browsing shortcut was used to launch, the "Private" * variant of one of the above entries will be returned. * * NOTE: This tries to avoid I/O, so paths are compared directly as * strings, which may not be accurate in all cases. It is intended * for noncritical telemetry use. */ AString classifyShortcut(in AString aPath); /* * Determine whether a pinnable shortcut with matching AUMID is present. * * @param aAUMID * AUMID of the shortcut to find. * @param aPrivateBrowsing * `true` to have the private browsing suffix added to `aAUMID`. * * @returns {Promise} Always resolves with boolean, true if a pinnable * shortcut exists. */ [implicit_jscontext] Promise hasPinnableShortcut(in AString aAUMID, in boolean aPrivateBrowsing); /* * Check if setDefaultBrowserUserChoice() is expected to succeed. * * This checks the ProgIDs for this installation, and the hash of the existing * UserChoice association. * * @return true if the check succeeds, false otherwise. */ boolean canSetDefaultBrowserUserChoice(); /* * checkAllProgIDsExist() and checkBrowserUserChoiceHashes() are components * of canSetDefaultBrowserUserChoice(), broken out for telemetry purposes. * * @return true if the check succeeds, false otherwise. */ boolean checkAllProgIDsExist(); boolean checkBrowserUserChoiceHashes(); /* * Retrieves the application-defined, explicit Application User Model ID * for the current process. This function is only to be used on * Windows for testing purposes * * @return string AUMID * @throws NS_ERROR_FAILURE when the AUMID cannot be fetched */ AString checkCurrentProcessAUMIDForTesting(); /* * Determines whether or not Firefox is the "Default Handler", i.e., * is registered to handle, the given file extension (like ".pdf") * or protocol (like "https"). */ boolean isDefaultHandlerFor(in AString aFileExtensionOrProtocol); /* * Return the Windows ProgID currently registered to handle the gven * file extension (like ".pdf") or protocol (like "https"). * * @return string ProgID, or "" when no association is registered. * @throws NS_ERROR_FAILURE when the file extension or protocol * cannot be determined. */ AString queryCurrentDefaultHandlerFor(in AString aFileExtensionOrProtocol); /* * Update the icons of existing .lnk shortcuts. Loads each shortcut, calls * IShellLinkW::SetIconLocation, saves it, and notifies the shell so Explorer * re-reads the icon. Shortcuts that don't exist or cannot be updated are * ignored. * * @param aShortcutPaths * Absolute paths to the .lnk files to modify. * @param aIconPath * Absolute path to the icon source. Either an .ico file or an * executable/DLL containing icon resources. * @param aIconResourceId * Resource ID of the icon within aIconPath to use (e.g. * IDI_CUSTOM_RETRO when aIconPath is firefox.exe). The icon is * referenced by resource ID rather than positional index so the * reference stays valid no matter what order icons are embedded in * aIconPath. Pass 0 to use the binary's default icon. * * @returns {Promise} Resolves when one or more shortcut * is successfully updated, rejects with an nserror if no shortcuts * were updated or on unrecoverable failure. * * @throws NS_ERROR_NOT_SAME_THREAD if not run on the main thread. * @rejects NS_ERROR_NOT_AVAILABLE when no shortcuts were able to be updated. * @rejects NS_ERROR_FAILURE for Windows API failures. */ [implicit_jscontext] Promise setShortcutsIcon(in Array aShortcutPaths, in AString aIconPath, in unsigned short aIconResourceId); /* * Enumerate the .lnk files for this install across the per-user shortcut * locations (taskbar pin folder, Desktop, Start Menu Programs) whose AUMID * matches aAppUserModelId and whose target matches the currently running * executable. * * Common (all-users) locations are not currently scanned: they typically * require elevation to modify, and changing them would alter the icon that * other users on the machine see. The intended use is "find every shortcut I * am allowed to update without prompting." * * @param aAppUserModelId * AUMID identifying this install's shortcuts. * * @returns {Promise>} Resolves with absolute paths to all * matching shortcuts. May be empty. * * @throws NS_ERROR_NOT_SAME_THREAD if not run on the main thread. * @rejects NS_ERROR_FAILURE on Windows API initialization failure. */ [implicit_jscontext] Promise enumerateInstallShortcuts(in AString aAppUserModelId); };