Pier Angelo Vendrame pushed to branch main at The Tor Project / Applications / tor-browser-build
Commits: a382aeb7 by Pier Angelo Vendrame at 2024-02-13T19:09:27+01:00 Bug 41076: Include the ShellLink plugin in NSIS.
We will need this plugin for the Mullvad Browser uninstaller.
- - - - - 8deb68f2 by Pier Angelo Vendrame at 2024-02-13T19:09:29+01:00 Bug 41077: Draft the new installer for Mullvad Browser.
The installer for Mullvad Browser is going to be different from Tor Browser's, because it will offer both a traditional installation (at the moment only for the current user, to avoid enabling privilege elevation code paths, but still with a control panel entry) and portable "installations".
The traditional one will support also setting MB as the default browser and file associations. However, this is quite tricky, and having a base installer to start implementing the feature is helpful. Thus this commit, even though the final installer will be likely changed.
- - - - -
15 changed files:
- projects/browser/build - projects/browser/config - − projects/browser/windows-installer.nsi - + projects/browser/windows-installer/browser-install.nsi - + projects/browser/windows-installer/browser-portable.nsi - + projects/browser/windows-installer/common.nsh - + projects/browser/windows-installer/defines.nsh.in - + projects/browser/windows-installer/language-map.sh - + projects/browser/windows-installer/languages.nsh - + projects/browser/windows-installer/postupdate.nsi - + projects/browser/windows-installer/registry.nsh - + projects/nsis/ShellLink.cpp - projects/nsis/build - projects/nsis/config - rbm.conf
Changes:
===================================== projects/browser/build ===================================== @@ -303,9 +303,27 @@ done export PATH="/var/tmp/dist/nsis/bin:$PATH"
mv $rootdir/windows-installer $distdir/windows-installer - cat > $distdir/windows-installer/browser-portable.nsi << 'BROWSER_NSI' -[% INCLUDE 'windows-installer.nsi' %] -BROWSER_NSI + mv $rootdir/defines.nsh $distdir/windows-installer/ + [% IF !c('var/testbuild') -%] + source $distdir/windows-installer/language-map.sh + supported_locales="[% tmpl(c('var/locales').join(' ')) %]" + for code in $supported_locales; do + if [[ -n ${nsis_languages[$code]} ]]; then + echo '!insertmacro MUI_LANGUAGE "'${nsis_languages[$code]}'"' >> $distdir/windows-installer/languages.nsh + fi + done + [% END -%] + + [% IF c('var/mullvad-browser') -%] + pushd $distdir/windows-installer + # While Firefox re-uses the uninstaller for this, we cannot do it, because + # we write the uninstaller from the installer. + # Instead, we need to write an updated postupdate.exe also when updating. + makensis postupdate.nsi + mv postupdate.exe ${TB_STAGE_DIR}/Browser/ + popd + [% END -%] + mv ${TB_STAGE_DIR} $distdir/windows-installer/"[% c('var/Project_Name') %]" mv $distdir/windows-installer ${TB_STAGE_DIR} [% END %] @@ -383,8 +401,13 @@ cd $distdir pushd "$PKG_DIR" makensis browser-portable.nsi # Working around NSIS braindamage - python3 $rootdir/pe_checksum_fix.py browser-install.exe - mv browser-install.exe $OUTDIR/[% c("var/project-name") %]-[% c("var/osname") %]-portable-[% c("var/torbrowser_version") %].exe + python3 $rootdir/pe_checksum_fix.py browser-portable.exe + mv browser-portable.exe $OUTDIR/[% c("var/project-name") %]-[% c("var/osname") %]-portable-[% c("var/torbrowser_version") %].exe + [% IF c('var/mullvad-browser') -%] + makensis browser-install.nsi + python3 $rootdir/pe_checksum_fix.py browser-install.exe + mv browser-install.exe $OUTDIR/[% c("var/project-name") %]-[% c("var/osname") %]-install-[% c("var/torbrowser_version") %].exe + [% END -%] popd [% END %] rm -rf $distdir/${PKG_DIR}
===================================== projects/browser/config ===================================== @@ -120,6 +120,9 @@ input_files: enable: '[% c("var/windows") %]' - filename: windows-installer enable: '[% c("var/windows") %]' + - filename: 'defines.nsh' + content: '[% INCLUDE "windows-installer/defines.nsh.in" %]' + refresh_input: 1 - filename: pe_checksum_fix.py enable: '[% c("var/windows") %]' # To generate a new keystore, see how-to-generate-keystore.txt
===================================== projects/browser/windows-installer.nsi deleted ===================================== @@ -1,169 +0,0 @@ -; NSIS Installer for Tor/Base/Mullvad Browser -; Based on NSIS examples by Joost Verburg. -; Originally adapted to Tor Browser by Moritz Bartl -; https://github.com/moba/tbb-windows-installer -; Released under the zlib/libpng license. - -;-------------------------------- - !include "FileFunc.nsh" - !include "LogicLib.nsh" - !include "MUI2.nsh" - !include "WinVer.nsh" - -;-------------------------------- -; General - ; Location of Tor/Base/Mullvad Browser to put into installer - !define PROGRAM_SOURCE ".[% c('var/Project_Name') %]" - -[% IF c("var/channel") == "release"; - SET display_name = c('var/Project_Name'); - ELSIF c("var/testbuild"); - SET display_name = c('var/Project_Name') _ " Testbuild"; - ELSE; - SET display_name = c('var/Project_Name_Channel'); - END --%] - Name "[% display_name %]" - OutFile "browser-install.exe" - - ; Default installation folder - InstallDir "$DESKTOP[% display_name %]" - - ; Best (but slowest) compression - SetCompressor /SOLID lzma - SetCompressorDictSize 32 - - ; Do not require elevated privileges - RequestExecutionLevel user - - ; Support HiDPI displays - ManifestDPIAware true - -;-------------------------------- -; Metadata - VIProductVersion "[% pc('firefox', 'var/browser_series') %].0.0" - VIAddVersionKey "ProductName" "[% display_name %]" - VIAddVersionKey "ProductVersion" "[% c('var/torbrowser_version') %]" - VIAddVersionKey "FileDescription" "[% display_name %] Portable Installer" - VIAddVersionKey "LegalCopyright" "© [% pc('firefox', 'var/copyright_year') %] [% IF c('var/mullvad-browser') %]Mullvad, Tor Browser and Mozilla Developers[% ELSE %]The Tor Project[% END %]" - -;-------------------------------- -; Interface Configuration - !define MUI_ICON "[% c('var/projectname') %][% IF !c('var/base-browser') %]-[% c('var/channel') %][% END %].ico" - !define MUI_ABORTWARNING - -;-------------------------------- -; Modern UI settings - !define MUI_FINISHPAGE_NOREBOOTSUPPORT ; Reboot not required - !define MUI_FINISHPAGE_RUN - !define MUI_FINISHPAGE_RUN_FUNCTION "StartBrowser" - - ; Misuse the option to show the readme to create the shortcuts. - ; Less ugly than MUI_PAGE_COMPONENTS. - !define MUI_FINISHPAGE_SHOWREADME - !define MUI_FINISHPAGE_SHOWREADME_TEXT "&Add Start Menu && Desktop shortcuts" - !define MUI_FINISHPAGE_SHOWREADME_FUNCTION "CreateShortCuts" - -;-------------------------------- -; Pages - !define MUI_PAGE_CUSTOMFUNCTION_LEAVE CheckIfTargetDirectoryExists - !insertmacro MUI_PAGE_DIRECTORY - !insertmacro MUI_PAGE_INSTFILES - !insertmacro MUI_PAGE_FINISH - -;-------------------------------- -; Languages - !insertmacro MUI_LANGUAGE "English" ; First language is the default language - !insertmacro MUI_LANGUAGE "Arabic" ; ar - !insertmacro MUI_LANGUAGE "Catalan" ; ca - !insertmacro MUI_LANGUAGE "Czech" ; cs - !insertmacro MUI_LANGUAGE "Danish" ; da - !insertmacro MUI_LANGUAGE "German" ; de - !insertmacro MUI_LANGUAGE "Greek" ; el - !insertmacro MUI_LANGUAGE "Spanish" ; es-ES - !insertmacro MUI_LANGUAGE "Farsi" ; fa - !insertmacro MUI_LANGUAGE "Finnish" ; fi - !insertmacro MUI_LANGUAGE "French" ; fr - !insertmacro MUI_LANGUAGE "ScotsGaelic" ; ga-IE - !insertmacro MUI_LANGUAGE "Hebrew" ; he - !insertmacro MUI_LANGUAGE "Hungarian" ; hu - !insertmacro MUI_LANGUAGE "Indonesian"; id - !insertmacro MUI_LANGUAGE "Icelandic" ; is - !insertmacro MUI_LANGUAGE "Italian" ; it - !insertmacro MUI_LANGUAGE "Japanese" ; ja - !insertmacro MUI_LANGUAGE "Georgian" ; ka - !insertmacro MUI_LANGUAGE "Korean" ; ko - !insertmacro MUI_LANGUAGE "Lithuanian" ; lt - !insertmacro MUI_LANGUAGE "Macedonian" ; mk - !insertmacro MUI_LANGUAGE "Malay" ; ms - ; Burmese - my: not available on NSIS - !insertmacro MUI_LANGUAGE "Norwegian" ; nb-NO - !insertmacro MUI_LANGUAGE "Dutch" ; nl - !insertmacro MUI_LANGUAGE "Polish" ; pl - !insertmacro MUI_LANGUAGE "PortugueseBR" ; pt-BR - !insertmacro MUI_LANGUAGE "Romanian" ; ro - !insertmacro MUI_LANGUAGE "Russian" ; ru - !insertmacro MUI_LANGUAGE "Albanian" ; sq - !insertmacro MUI_LANGUAGE "Swedish" ; sv-SE - !insertmacro MUI_LANGUAGE "Thai" ; th - !insertmacro MUI_LANGUAGE "Turkish" ; tr - !insertmacro MUI_LANGUAGE "Ukrainian" ; uk - !insertmacro MUI_LANGUAGE "Vietnamese" ; vi - !insertmacro MUI_LANGUAGE "SimpChinese" ; zh-hans, zh-cn - !insertmacro MUI_LANGUAGE "TradChinese" ; zh-hant, zh-tw - -;-------------------------------- -; Reserve Files - - ; If you are using solid compression, files that are required before - ; the actual installation should be stored first in the data block, - ; because this will make your installer start faster. - - !insertmacro MUI_RESERVEFILE_LANGDLL - -;-------------------------------- -; Installer Sections - -Section "Browser" SecBrowser - SetOutPath "$INSTDIR" - File /r "${PROGRAM_SOURCE}*.*" - CreateShortCut "$INSTDIR[% display_name %].lnk" "$INSTDIR\Browser[% c('var/exe_name') %].exe" -SectionEnd - -;-------------------------------- -; Installer Functions - -Function .onInit - ${IfNot} ${AtLeastWin7} - MessageBox MB_USERICON|MB_OK "[% c('var/Project_Name') %] requires at least Windows 7" - SetErrorLevel 1 - Quit - ${EndIf} - - ; Don't install on systems that don't support SSE2. The parameter value of - ; 10 is for PF_XMMI64_INSTRUCTIONS_AVAILABLE which will check whether the - ; SSE2 instruction set is available. - System::Call "kernel32::IsProcessorFeaturePresent(i 10)i .R7" - ${If} "$R7" == "0" - MessageBox MB_OK|MB_ICONSTOP "Sorry, [% c('var/Project_Name') %] can't be installed. This version of [% c('var/Project_Name') %] requires a processor with SSE2 support." - Abort - ${EndIf} - - !insertmacro MUI_LANGDLL_DISPLAY -FunctionEnd - -Function CheckIfTargetDirectoryExists - ${If} ${FileExists} "$INSTDIR*.*" - MessageBox MB_YESNO "The destination directory already exists. Do you want to continue anyway?" IDYES +2 - Abort - ${EndIf} -FunctionEnd - -Function CreateShortcuts - CreateShortCut "$SMPROGRAMS[% display_name %].lnk" "$INSTDIR[% IF !system_install_mode -%]Browser[% END -%][% c('var/exe_name') %].exe" - CreateShortCut "$DESKTOP[% display_name %].lnk" "$INSTDIR[% IF !system_install_mode -%]Browser[% END -%][% c('var/exe_name') %].exe" -FunctionEnd - -Function StartBrowser - ExecShell "open" "$INSTDIR/[% display_name %].lnk" -FunctionEnd
===================================== projects/browser/windows-installer/browser-install.nsi ===================================== @@ -0,0 +1,263 @@ + !include "common.nsh" + !include "registry.nsh" + +;-------------------------------- + OutFile "browser-install.exe" + VIAddVersionKey "FileDescription" "${DISPLAY_NAME} Installer" + + !define DEFAULT_INSTALL_DIR "$LocalAppdata${APP_DIR}${NAME_NO_SPACES}${UPDATE_CHANNEL}" + InstallDir "${DEFAULT_INSTALL_DIR}" + +;-------------------------------- +; Pages + Page custom SetupType SetupTypeLeave + Page custom CustomSetup CustomSetupLeave + ; Disable the directory selection when updating + !define MUI_PAGE_CUSTOMFUNCTION_PRE CustomPageDirectory + !define MUI_PAGE_CUSTOMFUNCTION_LEAVE CheckIfTargetDirectoryExists + !insertmacro MUI_PAGE_DIRECTORY + !insertmacro MUI_PAGE_INSTFILES + !insertmacro MUI_PAGE_FINISH + + !insertmacro MUI_UNPAGE_CONFIRM + !insertmacro MUI_UNPAGE_INSTFILES + !insertmacro MUI_UNPAGE_FINISH + + ; Languages must be defined after pages + !include "languages.nsh" + +;-------------------------------- +; Installer + +; Path to an existing install. If not empty we are in update mode. +var existingInstall + +; Installation settings +var isCustomMode +var isPortableMode +var createDesktopShortcut + +; Variable used by the setup type page +var typeRadioStandard +var typeRadioCustom +var typeRadioClicked +var typeNextButton + +; Variables used in the custom setup page +var customCheckboxPortable +var customCheckboxDesktop + +Function .onInit + Call CheckRequirements + + !insertmacro MUI_LANGDLL_DISPLAY + + ReadRegStr $existingInstall HKCU "${UNINST_KEY}" "InstallLocation" + StrCpy $createDesktopShortcut "true" +FunctionEnd + +Function SetupType + !insertmacro MUI_HEADER_TEXT "Setup Type" "Choose setup options" + nsDialogs::Create 1018 + Pop $0 + ${If} $0 == error + Abort + ${EndIf} + + ${NSD_CreateLabel} 0 0 100% 18% "Choose the type of setup you prefer." + ${If} $existingInstall == "" + ${NSD_CreateRadioButton} 0 18% 100% 6% "Standard" + Pop $typeRadioStandard + ${NSD_CreateRadioButton} 0 30% 100% 6% "Custom" + Pop $typeRadioCustom + ${Else} + ${NSD_CreateRadioButton} 0 18% 100% 6% "Update your existing installation" + Pop $typeRadioStandard + ${NSD_CreateRadioButton} 0 30% 100% 6% "Portable installation" + Pop $typeRadioCustom + ${EndIf} + ${NSD_OnClick} $typeRadioStandard SetupTypeRadioClick + ${NSD_OnClick} $typeRadioCustom SetupTypeRadioClick + + GetDlgItem $typeNextButton $HWNDPARENT 1 + + ; Re-check radios if the user presses back + ${If} $isCustomMode == "true" + StrCpy $typeRadioClicked $typeRadioCustom + ${Else} + StrCpy $typeRadioClicked $typeRadioStandard + ${EndIf} + ${NSD_Check} $typeRadioClicked + Call SetupTypeUpdate + + nsDialogs::Show +FunctionEnd + +Function SetupTypeRadioClick + Pop $typeRadioClicked + Call SetupTypeUpdate +FunctionEnd + +Function SetupTypeUpdate + ${If} $typeRadioClicked == $typeRadioCustom + StrCpy $isCustomMode "true" + SendMessage $typeNextButton ${WM_SETTEXT} 0 "STR:$(^NextBtn)" + ${ElseIf} $typeRadioClicked == $typeRadioStandard + StrCpy $isCustomMode "false" + StrCpy $isPortableMode "false" + ${If} $existingInstall == "" + SendMessage $typeNextButton ${WM_SETTEXT} 0 "STR:$(^InstallBtn)" + ${Else} + SendMessage $typeNextButton ${WM_SETTEXT} 0 "STR:&Update" + ${EndIf} + ${EndIf} +FunctionEnd + +Function SetupTypeLeave + ${If} $typeRadioClicked == $typeRadioCustom + StrCpy $isCustomMode "true" + ${ElseIf} $typeRadioClicked == $typeRadioStandard + StrCpy $isCustomMode "false" + StrCpy $isPortableMode "false" + ${Else} + Abort + ${EndIf} +FunctionEnd + +Function CustomSetup + ${If} $isCustomMode != "true" + Return + ${EndIf} + + !insertmacro MUI_HEADER_TEXT "Custom Setup" "Customize your setup options" + nsDialogs::Create 1018 + Pop $0 + ${If} $0 == error + Abort + ${EndIf} + + ${NSD_CreateCheckbox} 0 18% 100% 6% "Portable installation" + Pop $customCheckboxPortable + ${NSD_CreateCheckbox} 0 30% 100% 6% "Create a desktop shortcut" + Pop $customCheckboxDesktop + ${NSD_OnClick} $customCheckboxPortable CustomSetupCheckboxClick + ${NSD_OnClick} $customCheckboxDesktop CustomSetupCheckboxClick + + ${If} $existingInstall != "" + ; If we already have an installation, this is already portable mode. + StrCpy $isPortableMode "true" + ${NSD_Check} $customCheckboxPortable + EnableWindow $customCheckboxPortable 0 + ${ElseIf} $isPortableMode == "true" + ${NSD_Check} $customCheckboxPortable + ${EndIf} + ${If} $createDesktopShortcut == "true" + ${NSD_Check} $customCheckboxDesktop + ${EndIf} + + nsDialogs::Show +FunctionEnd + +Function CustomSetupUpdate + ${NSD_GetState} $customCheckboxPortable $0 + ${If} $0 == "${BST_CHECKED}" + StrCpy $isPortableMode "true" + ${Else} + StrCpy $isPortableMode "false" + ${EndIf} + + ${NSD_GetState} $customCheckboxDesktop $0 + ${If} $0 == "${BST_CHECKED}" + StrCpy $createDesktopShortcut "true" + ${Else} + StrCpy $createDesktopShortcut "false" + ${EndIf} +FunctionEnd + +Function CustomSetupCheckboxClick + Pop $0 + Call CustomSetupUpdate +FunctionEnd + +Function CustomSetupLeave + Call CustomSetupUpdate +FunctionEnd + +Function CustomPageDirectory + ${If} $isPortableMode == "true" + StrCpy $INSTDIR "${DEFAULT_PORTABLE_DIR}" + ; Always go through this page in portable mode. + Return + ${ElseIf} $existingInstall != "" + ; When updating, force the old directory and skip the page. + StrCpy $INSTDIR $existingInstall + Abort + ${Else} + StrCpy $INSTDIR "${DEFAULT_INSTALL_DIR}" + ${EndIf} + + ${If} $isCustomMode != "true" + ; Standard install, use the default directory and skip the page. + Abort + ${EndIf} +FunctionEnd + +Section "Browser" SecBrowser + SetOutPath "$INSTDIR" + + ${If} $isPortableMode == "true" + File /r "${PROGRAM_SOURCE}*.*" + CreateShortCut "$INSTDIR${DISPLAY_NAME}.lnk" "$INSTDIR\Browser${EXE_NAME}" + ${Else} + ; Do not use a Browser directory for installs. + File /r "${PROGRAM_SOURCE}\Browser*.*" + + ; Tell the browser we are not in portable mode anymore. + FileOpen $0 "$INSTDIR\system-install" w + FileClose $0 + + ; Write the uninstaller + WriteUninstaller $INSTDIR\uninstall.exe + + !insertmacro UPDATE_REGISTRY + + CreateShortCut "$SMPROGRAMS${DISPLAY_NAME}.lnk" "$INSTDIR${EXE_NAME}" + ${If} $createDesktopShortcut == "true" + CreateShortCut "$DESKTOP${DISPLAY_NAME}.lnk" "$INSTDIR${EXE_NAME}" + ${EndIf} + ${EndIf} +SectionEnd + +Function StartBrowser + ${If} $isPortableMode == "true" + ExecShell "open" "$INSTDIR${DISPLAY_NAME}.lnk" + ${Else} + ExecShell "open" "$INSTDIR${EXE_NAME}" + ${EndIf} +FunctionEnd + +;-------------------------------- +; Uninstaller +Section "Uninstall" + RMDir /r "$INSTDIR" + DeleteRegKey HKCU "${UNINST_KEY}" + + StrCpy $0 "" + ShellLink::GetShortCutTarget "$SMPROGRAMS${DISPLAY_NAME}.lnk" + Pop $0 + ${If} $0 == "$INSTDIR${EXE_NAME}" + Delete "$SMPROGRAMS${DISPLAY_NAME}.lnk" + ${EndIf} + + StrCpy $0 "" + ShellLink::GetShortCutTarget "$DESKTOP${DISPLAY_NAME}.lnk" + Pop $0 + ${If} $0 == "$INSTDIR${EXE_NAME}" + Delete "$DESKTOP${DISPLAY_NAME}.lnk" + ${EndIf} + + ; TODO: Optionally remove profiles. + ; This operation is not trivial, because it involes finding our installation + ; hash, its associated default profile and making sure it is not shared with + ; another channel/installation. +SectionEnd
===================================== projects/browser/windows-installer/browser-portable.nsi ===================================== @@ -0,0 +1,45 @@ + !include "common.nsh" + +;-------------------------------- + OutFile "browser-portable.exe" + VIAddVersionKey "FileDescription" "${DISPLAY_NAME} Portable Installer" + InstallDir "$DESKTOP${DISPLAY_NAME}" + +;-------------------------------- +; Pages + ; Misuse the option to show the readme to create the shortcuts. + ; Less ugly than MUI_PAGE_COMPONENTS. + !define MUI_FINISHPAGE_SHOWREADME + !define MUI_FINISHPAGE_SHOWREADME_TEXT "&Add Start Menu && Desktop shortcuts" + !define MUI_FINISHPAGE_SHOWREADME_FUNCTION "CreateShortcuts" + + !define MUI_PAGE_CUSTOMFUNCTION_LEAVE CheckIfTargetDirectoryExists + !insertmacro MUI_PAGE_DIRECTORY + !insertmacro MUI_PAGE_INSTFILES + !insertmacro MUI_PAGE_FINISH + + ; Languages must be defined after pages + !include "languages.nsh" + +;-------------------------------- +; Installer +Function .onInit + Call CheckRequirements + + !insertmacro MUI_LANGDLL_DISPLAY +FunctionEnd + +Section "Browser" SecBrowser + SetOutPath "$INSTDIR" + File /r "${PROGRAM_SOURCE}*.*" + CreateShortCut "$INSTDIR${DISPLAY_NAME}.lnk" "$INSTDIR\Browser${EXE_NAME}" +SectionEnd + +Function CreateShortcuts + CreateShortCut "$SMPROGRAMS${DISPLAY_NAME}.lnk" "$INSTDIR\Browser${EXE_NAME}" + CreateShortCut "$DESKTOP${DISPLAY_NAME}.lnk" "$INSTDIR\Browser${EXE_NAME}" +FunctionEnd + +Function StartBrowser + ExecShell "open" "$INSTDIR/${DISPLAY_NAME}.lnk" +FunctionEnd
===================================== projects/browser/windows-installer/common.nsh ===================================== @@ -0,0 +1,82 @@ +; Common code for the NSIS Installers for Tor/Base/Mullvad Browser. +; Based on NSIS examples by Joost Verburg. +; Originally adapted to Tor Browser by Moritz Bartl +; https://github.com/moba/tbb-windows-installer +; Released under the zlib/libpng license. + +;-------------------------------- + !include "FileFunc.nsh" + !include "LogicLib.nsh" + !include "MUI2.nsh" + !include "WinVer.nsh" + + !include "defines.nsh" + +;-------------------------------- +; General settings + Name "${DISPLAY_NAME}" + + ; Best (but slowest) compression + SetCompressor /SOLID lzma + SetCompressorDictSize 32 + + ; Do not require elevated privileges. + ; Even for the installer, we install only for the current user, so we do not + ; need high privileges. + RequestExecutionLevel user + + ; Support HiDPI displays + ManifestDPIAware true + +;-------------------------------- +; Version information + VIProductVersion "${VERSION_WINDOWS}" + VIAddVersionKey "ProductName" "${DISPLAY_NAME}" + VIAddVersionKey "ProductVersion" "${VERSION}" + VIAddVersionKey "FileVersion" "${VERSION}" + VIAddVersionKey "LegalCopyright" "${COPYRIGHT_STRING}" + +;-------------------------------- +; Interface Configuration + ; Installer icon + !define MUI_ICON "${ICON_NAME}" + !define MUI_ABORTWARNING + +;-------------------------------- +; Modern UI settings + !define MUI_FINISHPAGE_NOREBOOTSUPPORT ; Reboot not required + !define MUI_FINISHPAGE_RUN + !define MUI_FINISHPAGE_RUN_FUNCTION "StartBrowser" + +;-------------------------------- +; Reserve Files + ; If you are using solid compression, files that are required before + ; the actual installation should be stored first in the data block, + ; because this will make your installer start faster. + !insertmacro MUI_RESERVEFILE_LANGDLL + +;-------------------------------- +; Helper functions +Function CheckRequirements + ${IfNot} ${AtLeastWin7} + MessageBox MB_USERICON|MB_OK "${PROJECT_NAME} requires at least Windows 7" + SetErrorLevel 1 + Quit + ${EndIf} + + ; Don't install on systems that don't support SSE2. The parameter value of + ; 10 is for PF_XMMI64_INSTRUCTIONS_AVAILABLE which will check whether the + ; SSE2 instruction set is available. + System::Call "kernel32::IsProcessorFeaturePresent(i 10)i .R7" + ${If} "$R7" == "0" + MessageBox MB_OK|MB_ICONSTOP "${PROJECT_NAME} requires a processor with SSE2 support." + Quit + ${EndIf} +FunctionEnd + +Function CheckIfTargetDirectoryExists + ${If} ${FileExists} "$INSTDIR*.*" + MessageBox MB_YESNO "The destination directory already exists. Do you want to continue anyway?" IDYES +2 + Abort + ${EndIf} +FunctionEnd
===================================== projects/browser/windows-installer/defines.nsh.in ===================================== @@ -0,0 +1,52 @@ +;-------------------------------- +; Defines + ; Location of Tor/Base/Mullvad Browser to put into installer + !define PROGRAM_SOURCE ".[% c('var/Project_Name') %]" + + ; Project and display name + !define PROJECT_NAME "[% c('var/Project_Name') %]" +[% IF c("var/channel") == "release" -%] + !define DISPLAY_NAME "[% c('var/Project_Name') %]" +[% ELSIF c("var/testbuild") -%] + !define DISPLAY_NAME "[% c('var/Project_Name') %] Testbuild" +[% ELSE -%] + !define DISPLAY_NAME "[% c('var/Project_Name_Channel') %]" +[% END -%] + !define NAME_NO_SPACES "[% c('var/ProjectName') %]" + !define UPDATE_CHANNEL "[% c('var/channel') FILTER ucfirst %]" + + ; Version + !define VERSION "[% c('var/torbrowser_version') %]" + ; String for use with Windows's Product Version. + ; It must be 4 integers separated by a dot. + !define VERSION_WINDOWS "[% pc('firefox', 'var/browser_series') %].0.0" + + !define DEFAULT_PORTABLE_DIR "$DESKTOP${DISPLAY_NAME}" + !define EXE_NAME "[% c('var/exe_name') %].exe" +[% IF !c("var/base-browser") -%] + !define ICON_NAME "[% c('var/projectname') %]-[% c('var/channel') %].ico" +[% ELSE -%] + !define ICON_NAME "[% c('var/projectname') %].ico" +[% END -%] + +[% IF c('var/mullvad-browser') -%] + ; Firefox's --with-user-appdir + !define APP_DIR "Mullvad" + + !define PUBLISHER "Mullvad VPN" + !define COPYRIGHT_STRING "© [% pc('firefox', 'var/copyright_year') %] Mullvad, Tor Browser and Mozilla Developers" + + !define URL_ABOUT "https://mullvad.net/en/browser" + !define URL_UPDATE "https://github.com/mullvad/mullvad-browser/releases/%5B% c('var/torbrowser_version') %]" + !define URL_HELP "https://mullvad.net/help/tag/browser/" +[% ELSE -%] + ; Not defined for Tor Browser + !define APP_DIR "TorProject" + + !define PUBLISHER "The Tor Project" + !define COPYRIGHT_STRING "© [% pc('firefox', 'var/copyright_year') %] The Tor Project" + + !define URL_ABOUT "https://www.torproject.org/" + !define URL_UPDATE "https://blog.torproject.org/new%5B% IF c('var/alpha') %]-alpha[% END %]-release-tor-browser-[% c('var/torbrowser_version') FILTER remove('.') %]" + !define URL_HELP "https://tb-manual.torproject.org/" +[% END -%]
===================================== projects/browser/windows-installer/language-map.sh ===================================== @@ -0,0 +1,39 @@ +#!/bin/bash +declare -A nsis_languages +nsis_languages[ar]="Arabic" +nsis_languages[ca]="Catalan" +nsis_languages[cs]="Czech" +nsis_languages[da]="Danish" +nsis_languages[de]="German" +nsis_languages[el]="Greek" +nsis_languages[es-ES]="Spanish" +nsis_languages[fa]="Farsi" +nsis_languages[fi]="Finnish" +nsis_languages[fr]="French" +nsis_languages[ga-IE]="ScotsGaelic" +nsis_languages[he]="Hebrew" +nsis_languages[hu]="Hungarian" +nsis_languages[d]="Indonesian" +nsis_languages[is]="Icelandic" +nsis_languages[it]="Italian" +nsis_languages[ja]="Japanese" +nsis_languages[ka]="Georgian" +nsis_languages[ko]="Korean" +nsis_languages[lt]="Lithuanian" +nsis_languages[mk]="Macedonian" +nsis_languages[ms]="Malay" +# nsis_languages[my]="Burmese" # Not available on NSIS +nsis_languages[nb-NO]="Norwegian" +nsis_languages[nl]="Dutch" +nsis_languages[pl]="Polish" +nsis_languages[pt-BR]="PortugueseBR" +nsis_languages[ro]="Romanian" +nsis_languages[ru]="Russian" +nsis_languages[sq]="Albanian" +nsis_languages[sv-SE]="Swedish" +nsis_languages[th]="Thai" +nsis_languages[tr]="Turkish" +nsis_languages[uk]="Ukrainian" +nsis_languages[vi]="Vietnamese" +nsis_languages[zh-CN]="SimpChinese" +nsis_languages[zh-TW]="TradChinese"
===================================== projects/browser/windows-installer/languages.nsh ===================================== @@ -0,0 +1,4 @@ +;-------------------------------- +; Additional languages + !insertmacro MUI_LANGUAGE "English" ; Always available + ; The rest of the languages will be added here during the build.
===================================== projects/browser/windows-installer/postupdate.nsi ===================================== @@ -0,0 +1,28 @@ +!include "FileFunc.nsh" +!include "LogicLib.nsh" + +!include "defines.nsh" +!include "registry.nsh" + +OutFile "postupdate.exe" +Icon "${ICON_NAME}" +RequestExecutionLevel user + +Function .onInit + ${GetOptions} $CMDLINE "/Visible" $0 + IfErrors 0 +2 + SetSilent silent +FunctionEnd + +Section PostUpdate "PostUpdate" + StrCpy $0 "false" + IfFileExists $EXEDIR\system-install 0 +2 + StrCpy $0 "true" + ${If} $0 == "true" + StrCpy $INSTDIR $EXEDIR + !insertmacro UPDATE_REGISTRY + RMDir /r /REBOOTOK $EXEDIR\tobedeleted + ${Else} + RMDir /r $EXEDIR\tobedeleted + ${EndIf} +SectionEnd
===================================== projects/browser/windows-installer/registry.nsh ===================================== @@ -0,0 +1,19 @@ +!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall${NAME_NO_SPACES}${UPDATE_CHANNEL}" + +!macro UPDATE_REGISTRY + WriteRegStr HKCU "${UNINST_KEY}" "DisplayName" "${DISPLAY_NAME}" + WriteRegStr HKCU "${UNINST_KEY}" "DisplayIcon" "$"$INSTDIR${EXE_NAME}$"" + WriteRegStr HKCU "${UNINST_KEY}" "DisplayVersion" "${VERSION}" + WriteRegStr HKCU "${UNINST_KEY}" "UninstallString" "$"$INSTDIR\uninstall.exe$"" + WriteRegStr HKCU "${UNINST_KEY}" "QuietUninstallString" "$"$INSTDIR\uninstall.exe$" /S" + WriteRegDWORD HKCU "${UNINST_KEY}" "NoModify" "1" + WriteRegDWORD HKCU "${UNINST_KEY}" "NoRepair" "1" + ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 + IntFmt $0 "0x%08X" $0 + WriteRegDWORD HKCU "${UNINST_KEY}" "EstimatedSize" "$0" + WriteRegStr HKCU "${UNINST_KEY}" "InstallLocation" "$INSTDIR" + WriteRegStr HKCU "${UNINST_KEY}" "Publisher" "${PUBLISHER}" + WriteRegStr HKCU "${UNINST_KEY}" "URLInfoAbout" "${URL_ABOUT}" + WriteRegStr HKCU "${UNINST_KEY}" "URLUpdateInfo" "${URL_UPDATE}" + WriteRegStr HKCU "${UNINST_KEY}" "HelpLink" "${URL_HELP}" +!macroend
===================================== projects/nsis/ShellLink.cpp ===================================== @@ -0,0 +1,358 @@ +/* +Module : ShellLink.cpp +Purpose: NSIS Plug-in for retriving shell link information +Created: 12/16/2003 +Last Update: 01/14/2004 + +Copyright (c) 2004 Angelo Mandato. +See ShellLink.html for more information + + +Modified: 21/09/2005 +Author: Shengalts Aleksander aka Instructor (Shengalts@mail.ru) +Changes: -code has been rewritten + -added functions to change shell link information + -reduced dll size 44Kb -> 4Kb + +Modified by The Tor Project to remove the unneeded ConvFunc.h and updated the +include for pluginapi.h. +The original plugin is available at https://nsis.sourceforge.io/ShellLink_plug-in. + +© 2004 Angelo Mandato + +This software is provided 'as-is', without any express or implied warranty. In +no event will the authors be held liable for any damages arising from the use of +this software. + +Permission is granted to anyone to use this software for any purpose, including +commercial applications, and to alter it and redistribute it freely, subject to +the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim + that you wrote the original software. If you use this software in a product, + an acknowledgment in the product documentation would be appreciated but is + not required. +2. Altered versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any distribution. + +*/ + +// Uncomment for debugging message boxes +//#define SHELLLINK_DEBUG + +#include <windows.h> +#include <shlobj.h> + +#define xatoi +#include "nsis/pluginapi.h" + +#define NSISFUNC(name) extern "C" void __declspec(dllexport) name(HWND hWndParent, int string_size, TCHAR* variables, stack_t** stacktop, extra_parameters* extra) + +#define SHELLLINKTYPE_GETARGS 1 +#define SHELLLINKTYPE_GETDESC 2 +#define SHELLLINKTYPE_GETHOTKEY 3 +#define SHELLLINKTYPE_GETICONLOC 4 +#define SHELLLINKTYPE_GETICONINDEX 5 +#define SHELLLINKTYPE_GETPATH 6 +#define SHELLLINKTYPE_GETSHOWMODE 7 +#define SHELLLINKTYPE_GETWORKINGDIR 8 +#define SHELLLINKTYPE_SETARGS 9 +#define SHELLLINKTYPE_SETDESC 10 +#define SHELLLINKTYPE_SETHOTKEY 11 +#define SHELLLINKTYPE_SETICONLOC 12 +#define SHELLLINKTYPE_SETICONINDEX 13 +#define SHELLLINKTYPE_SETPATH 14 +#define SHELLLINKTYPE_SETSHOWMODE 15 +#define SHELLLINKTYPE_SETWORKINGDIR 16 +#define SHELLLINKTYPE_SETRUNASADMIN 17 + +void ShortCutData(int nType); + +//Get +NSISFUNC(GetShortCutArgs) +{ + EXDLL_INIT(); + ShortCutData(SHELLLINKTYPE_GETARGS); +} + +NSISFUNC(GetShortCutDescription) +{ + EXDLL_INIT(); + ShortCutData(SHELLLINKTYPE_GETDESC); +} + +NSISFUNC(GetShortCutHotkey) +{ + EXDLL_INIT(); + ShortCutData(SHELLLINKTYPE_GETHOTKEY); +} + +NSISFUNC(GetShortCutIconLocation) +{ + EXDLL_INIT(); + ShortCutData(SHELLLINKTYPE_GETICONLOC); +} + +NSISFUNC(GetShortCutIconIndex) +{ + EXDLL_INIT(); + ShortCutData(SHELLLINKTYPE_GETICONINDEX); +} + +NSISFUNC(GetShortCutTarget) +{ + EXDLL_INIT(); + ShortCutData(SHELLLINKTYPE_GETPATH); +} + +NSISFUNC(GetShortCutShowMode) +{ + EXDLL_INIT(); + ShortCutData(SHELLLINKTYPE_GETSHOWMODE); +} + +NSISFUNC(GetShortCutWorkingDirectory) +{ + EXDLL_INIT(); + ShortCutData(SHELLLINKTYPE_GETWORKINGDIR); +} + +//Set +NSISFUNC(SetShortCutArgs) +{ + EXDLL_INIT(); + ShortCutData(SHELLLINKTYPE_SETARGS); +} + +NSISFUNC(SetShortCutDescription) +{ + EXDLL_INIT(); + ShortCutData(SHELLLINKTYPE_SETDESC); +} + +NSISFUNC(SetShortCutHotkey) +{ + EXDLL_INIT(); + ShortCutData(SHELLLINKTYPE_SETHOTKEY); +} + +NSISFUNC(SetShortCutIconLocation) +{ + EXDLL_INIT(); + ShortCutData(SHELLLINKTYPE_SETICONLOC); +} + +NSISFUNC(SetShortCutIconIndex) +{ + EXDLL_INIT(); + ShortCutData(SHELLLINKTYPE_SETICONINDEX); +} + +NSISFUNC(SetShortCutTarget) +{ + EXDLL_INIT(); + ShortCutData(SHELLLINKTYPE_SETPATH); +} + +NSISFUNC(SetShortCutShowMode) +{ + EXDLL_INIT(); + ShortCutData(SHELLLINKTYPE_SETSHOWMODE); +} + +NSISFUNC(SetShortCutWorkingDirectory) +{ + EXDLL_INIT(); + ShortCutData(SHELLLINKTYPE_SETWORKINGDIR); +} + +NSISFUNC(SetRunAsAdministrator) +{ + EXDLL_INIT(); + ShortCutData(SHELLLINKTYPE_SETRUNASADMIN); +} + +void ShortCutData(int nType) +{ + HRESULT hRes; + IShellLink* psl; + IPersistFile* ppf; + + int nBuf; + WORD wHotkey; + TCHAR* szBuf = (TCHAR*)LocalAlloc(LPTR, sizeof(TCHAR)*MAX_PATH); + TCHAR* szBuf2 = (TCHAR*)LocalAlloc(LPTR, sizeof(TCHAR)*MAX_PATH); + + popstring(szBuf); + if (nType > SHELLLINKTYPE_GETWORKINGDIR) popstring(szBuf2); + + hRes=CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*) &psl); + if (hRes == S_OK) + { + hRes=psl->QueryInterface(IID_IPersistFile, (LPVOID*) &ppf); + if (hRes == S_OK) + { +#ifdef UNICODE + hRes=ppf->Load(szBuf, STGM_READWRITE); +#else + WCHAR* wszPath = (WCHAR*)LocalAlloc(LPTR, sizeof(WCHAR)*MAX_PATH); + MultiByteToWideChar(CP_ACP, 0, szBuf, -1, wszPath, MAX_PATH); + hRes=ppf->Load(wszPath, STGM_READWRITE); + LocalFree(wszPath); +#endif + if (hRes == S_OK) + { + if (nType <= SHELLLINKTYPE_GETWORKINGDIR) + { + //Get + switch(nType) + { + case SHELLLINKTYPE_GETARGS: + { + hRes=psl->GetArguments(szBuf, MAX_PATH); + if (hRes != S_OK) szBuf[0]='\0'; + }; break; + case SHELLLINKTYPE_GETDESC: + { + hRes=psl->GetDescription(szBuf, MAX_PATH); + if (hRes != S_OK) szBuf[0]='\0'; + }; break; + case SHELLLINKTYPE_GETHOTKEY: + { + hRes=psl->GetHotkey(&wHotkey); + if (hRes == S_OK) wsprintf(szBuf, TEXT("%d"), wHotkey); + else szBuf[0]='\0'; + }; break; + case SHELLLINKTYPE_GETICONLOC: + { + hRes=psl->GetIconLocation(szBuf, MAX_PATH, &nBuf); + if (hRes != S_OK) szBuf[0]='\0'; + }; break; + case SHELLLINKTYPE_GETICONINDEX: + { + hRes=psl->GetIconLocation(szBuf, MAX_PATH, &nBuf); + if (hRes == S_OK) wsprintf(szBuf, TEXT("%d"), nBuf); + else szBuf[0]='\0'; + }; break; + case SHELLLINKTYPE_GETPATH: + { + WIN32_FIND_DATA fd; + + hRes=psl->GetPath(szBuf, MAX_PATH, &fd, SLGP_UNCPRIORITY); + if (hRes != S_OK) szBuf[0]='\0'; + }; break; + case SHELLLINKTYPE_GETSHOWMODE: + { + hRes=psl->GetShowCmd(&nBuf); + if (hRes == S_OK) wsprintf(szBuf, TEXT("%d"), nBuf); + else szBuf[0]='\0'; + }; break; + case SHELLLINKTYPE_GETWORKINGDIR: + { + hRes=psl->GetWorkingDirectory(szBuf, MAX_PATH); + if (hRes != S_OK) szBuf[0]='\0'; + }; break; + } + } + else + { + //Set + switch(nType) + { + case SHELLLINKTYPE_SETARGS: + { + hRes=psl->SetArguments(szBuf2); + }; break; + case SHELLLINKTYPE_SETDESC: + { + hRes=psl->SetDescription(szBuf2); + }; break; + case SHELLLINKTYPE_SETHOTKEY: + { + wHotkey=(unsigned short)myatoi(szBuf2); + hRes=psl->SetHotkey(wHotkey); + }; break; + case SHELLLINKTYPE_SETICONLOC: + { + hRes=psl->GetIconLocation(szBuf, MAX_PATH, &nBuf); + if (hRes == S_OK) + hRes=psl->SetIconLocation(szBuf2, nBuf); + }; break; + case SHELLLINKTYPE_SETICONINDEX: + { + int nBuf2; + nBuf=myatoi(szBuf2); + + hRes=psl->GetIconLocation(szBuf, MAX_PATH, &nBuf2); + if (hRes == S_OK) + hRes=psl->SetIconLocation(szBuf, nBuf); + }; break; + case SHELLLINKTYPE_SETPATH: + { + hRes=psl->SetPath(szBuf2); + }; break; + case SHELLLINKTYPE_SETSHOWMODE: + { + nBuf=myatoi(szBuf2); + hRes=psl->SetShowCmd(nBuf); + }; break; + case SHELLLINKTYPE_SETWORKINGDIR: + { + hRes=psl->SetWorkingDirectory(szBuf2); + }; break; + case SHELLLINKTYPE_SETRUNASADMIN: + { + IShellLinkDataList* pdl; + hRes=psl->QueryInterface(IID_IShellLinkDataList, (void**)&pdl); + if (hRes == S_OK) + { + DWORD dwFlags = 0; + hRes=pdl->GetFlags(&dwFlags); + if (hRes == S_OK && (dwFlags & SLDF_RUNAS_USER) != SLDF_RUNAS_USER) + hRes=pdl->SetFlags(dwFlags | SLDF_RUNAS_USER); + pdl->Release(); + } + }; break; + } + if (hRes == S_OK) hRes=ppf->Save(NULL, FALSE); + #ifdef SHELLLINK_DEBUG + else MessageBox(hwndParent, TEXT("ERROR: Save()"), TEXT("ShellLink plug-in"), MB_OK); + #endif + } + } + #ifdef SHELLLINK_DEBUG + else MessageBox(hwndParent, TEXT("ERROR: Load()"), TEXT("ShellLink plug-in"), MB_OK); + #endif + } + #ifdef SHELLLINK_DEBUG + else MessageBox(hwndParent, TEXT("CShellLink::Initialise, Failed in call to QueryInterface for IPersistFile, HRESULT was %x\n"), TEXT("ShellLink plug-in"), MB_OK); + #endif + + // Cleanup: + if (ppf) ppf->Release(); + if (psl) psl->Release(); + } + #ifdef SHELLLINK_DEBUG + else MessageBox(hwndParent, TEXT("ERROR: CoCreateInstance()"), TEXT("ShellLink plug-in"), MB_OK); + #endif + + if (hRes == S_OK) + { + if (nType <= SHELLLINKTYPE_GETWORKINGDIR) pushstring(szBuf); + else pushstring(TEXT("0")); + } + else + { + if (nType <= SHELLLINKTYPE_GETWORKINGDIR) pushstring(TEXT("")); + else pushstring(TEXT("-1")); + } + + LocalFree(szBuf); + LocalFree(szBuf2); +} + +BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) +{ + return TRUE; +}
===================================== projects/nsis/build ===================================== @@ -30,7 +30,8 @@ EOF chmod +x "$compiler_prefix-gcc" ln -s "$compiler_prefix-clang++" "$compiler_prefix-g++"
-cd /var/tmp/build/nsis-[% c('version') %]-src +builddir=/var/tmp/build/nsis-[% c('version') %]-src +cd "$builddir"
# These two sed commands also come from build-mingw32-nsis.sh sed -i 's/-Wl,--exclude-libs,msvcrt.a/-Wl,-Xlink=-fixed/' SCons/Config/gnu @@ -60,6 +61,22 @@ patch -p1 < "$rootdir/resource-reproducible.diff" scons [% scons_args %] -j[% c("num_procs") %] || true scons [% scons_args %] scons [% scons_args %] install + +# Plugins +target="[% target %]-unicode" +plugins="/var/tmp/dist/nsis/share/nsis/Plugins/$target" +plugin_lib="$builddir/build/urelease/api/nsis/libpluginapi-$target.a" + +# This is not needed to build installers, but it makes easier to adapt plugins +# outside our build system. +mkdir /var/tmp/dist/nsis/share/nsis/Lib +cp $plugin_lib /var/tmp/dist/nsis/share/nsis/Lib/ + +$compiler_prefix-clang++ -I "$builddir/build/urelease/api" -O2 $plugin_lib \ + -DUNICODE "$rootdir/ShellLink.cpp" \ + -Wl,--no-insert-timestamp -lole32 -luuid -shared -o "$plugins/ShellLink.dll" +llvm-strip "$plugins/ShellLink.dll" + cd /var/tmp/dist [% c('tar', { tar_src => [ project ],
===================================== projects/nsis/config ===================================== @@ -24,3 +24,4 @@ input_files: - name: zlib project: zlib - filename: resource-reproducible.diff + - filename: ShellLink.cpp
===================================== rbm.conf ===================================== @@ -112,6 +112,8 @@ var: Project_Name_Channel: '[% c("var/Project_Name") %] [% c("var/channel") FILTER ucfirst %]' exe_name: firefox locale_ja: ja + # When adding new languages, add the equivalent NSIS name to + # projects/browser/windows-installer/language-map.sh. locales: - ar - ca
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/compare/5...
tor-commits@lists.torproject.org