-
Notifications
You must be signed in to change notification settings - Fork 975
How auto updates for Brave work on Windows
The Windows version of Brave uses the open source library Squirrel for keeping itself up-to-date
Here's everything you need to know to start from scratch.
- Setup your environment (clone / npm install). Check this doc for help if you're having trouble
git clone git@github.com:brave/browser-laptop.git
cd browser-laptop
npm install
- build the package and then build the installer
set CHANNEL=dev
npm run build-package
The package gets put into a folder like .\Brave-win32-x64\
. This will contain all the files you need to actually run Brave without having to use npm run watch
and npm start
. These files are what get put into the installer.
NOTE: you won't be able to build the installer unless you are an employee of Brave Software since it uses an authenticode certificate which must be kept private
set CERT="c:\path-to-cert-here"
set CERT_PASSWORD="authenticode cert password here"
npm run build-installer
Running the above will execute tools/buildInstaller.js
which uses the Electron Installer package to build the signed installers. Here's what the code for that looks like:
var electronInstaller = require('electron-winstaller')
var resultPromise = electronInstaller.createWindowsInstaller({
appDirectory: buildDir,
outputDirectory: outDir,
title: 'Brave',
authors: 'Brave Software',
loadingGif: 'res/brave_splash_installing.gif',
setupIcon: 'res/brave_installer.ico',
iconUrl: 'https://brave.com/favicon.ico',
signWithParams: format('-a -fd sha256 -f "%s" -p "%s" -t http://timestamp.verisign.com/scripts/timstamp.dll', path.resolve(cert), certPassword),
exe: 'Brave.exe'
})
resultPromise.then(() => {
cmds = [
`mv ${outDir}/Setup.exe ${outDir}/BraveSetup-${arch}.exe`,
`mv ${outDir}/Setup.msi ${outDir}/BraveSetup-${arch}.msi`
]
execute(cmds, {}, console.log.bind(null, 'done'))
}, (e) => console.log(`No dice: ${e.message}`))
At the end of this snippet, you'll have an EXE and MSI installer.
It's important to note that behind the scenes, the electronInstaller
object is configuring a nuget package which includes Squirrel. The file which contains the important stuff is called template.nuspectemplate
and looks like this:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id><%- name %></id>
<title><%- title %></title>
<version><%- version %></version>
<authors><%- authors %></authors>
<owners><%- owners %></owners>
<iconUrl><%- iconUrl %></iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description><%- description %></description>
<copyright><%- copyright %></copyright>
</metadata>
<files>
<file src="locales\**" target="lib\net45\locales" />
<file src="resources\**" target="lib\net45\resources" />
<file src="*.bin" target="lib\net45" />
<file src="*.dll" target="lib\net45" />
<file src="*.pak" target="lib\net45" />
<file src="*.txt" target="lib\net45" />
<file src="Update.exe" target="lib\net45\squirrel.exe" />
<file src="icudtl.dat" target="lib\net45\icudtl.dat" />
<file src="LICENSE" target="lib\net45\LICENSE" />
<file src="LICENSES.chromium.html" target="lib\net45\LICENSES.chromium.html" />
<file src="<%- exe %>" target="lib\net45\<%- exe %>" />
</files>
</package>
These fields get filled out by the code in the electronInstaller object. There are a few important fields under the files section:
- Update.exe: this is key to how Squirrel gets used. Instead of launching into your executable, you launch into this Squirrel executable which can check for updates. Launching this will get you to the most recent version of the product.
- <%- exe %>: this gets filled in when the installer is being created and in our case would be
Brave.exe
.
There are two key locations to remember:
-
%USERPROFILE%\AppData\Local\brave
: this is where the binaries get installed to -
%APPDATA%\brave
: this is where the SESSION data gets installed to
The binaries are in a directory structure like this:
-
%USERPROFILE%\AppData\Local\brave
- app-0.12.13
- Brave.exe
- all other files created in the packaging process
- app-0.12.14
- Brave.exe
- all other files created in the packaging process
- packages
- temp files; for example the nupkg file, the RELEASE file, etc.
- app.ico
- SquirrelSetup.log (contains lots of great info for troubleshooting! these are the logs from when the install or upgrade takes place)
- Update.exe (our entry point into Brave)
- Update.VisualElementsManifest.xml
- app-0.12.13
With the exception of a log file, nothing in the SESSION directory is touched by Squirrel. Here are some files that are included there:
-
%APPDATA%\brave
- session-store-1 (contains all your bookmarks, current windows, most recently closed windows, preferences and really important settings. See our docs to learn more)
- updateLog.log (contains logs captured when updates were checked during program execution)
- ledger-* (files used for Brave Payments)
There is a file called Updater.js which has the logic to check for updates and (when ready) to quit / install / re-launch Brave. This wraps the electron.autoUpdater
functionality exposed by electron and is used in app/index.js
. The important parts of this file you'll want to see (just search for these):
checkForUpdate
autoUpdater.on('update-downloaded'
quitAndInstall
When the above (Updater.js) finds an update, it'll ask the user if they want to restart with the latest update. At this point, it's put the downloaded content into the %USERPROFILE%\AppData\Local\brave\packages
folder.
If the user says "Yes", Brave will immediately dump it's state and quit the program. It's important to note that the quitAndInstall method gets called in Electron, which starts the next part of the process.
This is where the new directory gets created with the contents of the nupkg. Squirrel then updates any shortcuts that exist with the new location (since it has moved). It's VERY important to note that for this to work, we have to call setAppUserModelId. This basically ties all the shortcuts together using the app ID set by Squirrel. In our case, this is com.squirrel.brave.Brave
.
During the install / upgrade process, logs will be updated showing what was updated (notice that multiple shortcuts are updated auto-magically!):
2016-12-07 13:21:41> ApplyReleasesImpl: Writing files to app directory: C:\Users\brian\AppData\Local\brave\app-0.12.13
2016-12-07 13:21:45> ApplyReleasesImpl: Squirrel Enabled Apps: [C:\Users\brian\AppData\Local\brave\app-0.12.13\Brave.exe,C:\Users\brian\AppData\Local\brave\app-0.12.13\Brave_ExecutionStub.exe]
2016-12-07 13:21:47> ApplyReleasesImpl: Processing shortcut 'C:\Users\brian\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Brave.lnk'
2016-12-07 13:21:47> ApplyReleasesImpl: Old shortcut target: 'C:\Users\brian\AppData\Local\brave\Update.exe'
2016-12-07 13:21:47> ApplyReleasesImpl: New shortcut target: 'C:\Users\brian\AppData\Local\brave\Update.exe'
2016-12-07 13:21:47> ApplyReleasesImpl: Old iconPath is: 'C:\Users\brian\AppData\Local\brave\app-0.12.13\Brave.exe'
2016-12-07 13:21:47> ApplyReleasesImpl: Setting iconPath to: 'C:\Users\brian\AppData\Local\brave\app-0.12.13\Brave.exe'
Why yes, we can. We have a script specifically for doing that. This makes use of a Brave owned fork of Electron Squirrel Startup. A good example of where we needed this logic is used is to execute braveDefaults.exe which is used so that Windows sees our application as an HTTP/HTTPS handler.
This would be the place we want to investigate resetting the default browser setting (which is lost during the upgrade). For more info, see https://github.com/brave/browser-laptop/issues/5246
insecurity test
Vertical Side Tabs Tab Suspender