Files
brave-core/build/commands/lib/branding.js
T
Brian R. Bondy 139d44583b Fix Windows build when enable_brave_vpn is false and create_dist (#33372)
* Fix Windows build when enable_brave_vpn is false

When VPN is disabled (e.g. Origin builds), copy chrome's resource
allowlist instead of trying to merge with wireguard resources.

* create_dist Origin fixes
2026-01-23 10:29:27 -05:00

527 lines
14 KiB
JavaScript

// Copyright (c) 2025 The Brave Authors. All rights reserved.
// 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 https://mozilla.org/MPL/2.0/.
const path = require('path')
const config = require('./config')
const fs = require('fs-extra')
const l10nUtil = require('./l10nUtil')
const util = require('./util')
const Log = require('./logging')
exports.update = () => {
Log.progressStart('update branding')
const chromeComponentsDir = path.join(config.srcDir, 'components')
const braveComponentsDir = path.join(config.braveCoreDir, 'components')
const chromeAppDir = path.join(config.srcDir, 'chrome', 'app')
const braveAppDir = path.join(config.braveCoreDir, 'app')
const braveChromiumResources = path.join(
config.braveCoreDir,
'build',
'chromium',
'resources',
)
const braveAppVectorIconsDir = path.join(config.braveCoreDir, 'components')
const chromeAndroidJavaStringsTranslationsDir = path.join(
config.srcDir,
'chrome',
'browser',
'ui',
'android',
'strings',
'translations',
)
const braveAndroidJavaStringsTranslationsDir = path.join(
config.braveCoreDir,
'browser',
'ui',
'android',
'strings',
'translations',
)
const chromeAndroidTabUiJavaStringsTranslationsDir = path.join(
config.srcDir,
'chrome',
'android',
'features',
'tab_ui',
'java',
'strings',
'translations',
)
const braveAndroidTabUiJavaStringsTranslationsDir = path.join(
config.braveCoreDir,
'android',
'features',
'tab_ui',
'java',
'strings',
'translations',
)
let fileMap = new Set()
const autoGeneratedBraveToChromiumMapping = Object.assign(
{},
l10nUtil.getAutoGeneratedBraveToChromiumMapping(),
)
// Map branded string files to chromium directories
for (const branding of ['brave', 'brave_origin']) {
autoGeneratedBraveToChromiumMapping[
path.join(braveAppDir, `${branding}_strings.grd`)
] = path.join(chromeAppDir, `${branding}_strings.grd`)
autoGeneratedBraveToChromiumMapping[
path.join(braveComponentsDir, `components_${branding}_strings.grd`)
] = path.join(chromeComponentsDir, `components_${branding}_strings.grd`)
}
// Shared grdp files (only need brave versions, brave_origin includes them)
autoGeneratedBraveToChromiumMapping[
path.join(braveAppDir, 'settings_brave_strings.grdp')
] = path.join(chromeAppDir, 'settings_brave_strings.grdp')
Object.entries(autoGeneratedBraveToChromiumMapping).forEach((mapping) =>
fileMap.add(mapping),
)
// Copy xtb files for:
// brave/app/resources/chromium_strings*.xtb
// brave/app/resources/generated_resoruces*.xtb
// brave/components/strings/components_chromium_strings*.xtb
// brave/browser/ui/android/strings/translations/android_chrome_strings*.xtb
// brave/android/features/tab_ui/java/strings/translations/android_chrome_tab_ui_strings*.xtb
fileMap.add([
path.join(braveAppDir, 'resources'),
path.join(chromeAppDir, 'resources'),
])
fileMap.add([
path.join(braveComponentsDir, 'strings'),
path.join(chromeComponentsDir, 'strings'),
])
fileMap.add([
braveAndroidJavaStringsTranslationsDir,
chromeAndroidJavaStringsTranslationsDir,
])
fileMap.add([
braveAndroidTabUiJavaStringsTranslationsDir,
chromeAndroidTabUiJavaStringsTranslationsDir,
])
// By overwriting, we don't need to modify some grd files.
for (const branding of ['brave', 'brave_origin']) {
fileMap.add([
path.join(braveAppDir, 'theme', branding),
path.join(chromeAppDir, 'theme', branding),
])
for (const scale of ['default_100_percent', 'default_200_percent']) {
fileMap.add([
path.join(braveAppDir, 'theme', scale, branding),
path.join(chromeAppDir, 'theme', scale, branding),
])
}
}
fileMap.add([path.join(braveChromiumResources), path.join(config.srcDir)])
// Copy product_logo for version UI (about:version page).
// product_logo_name_48.png is renamed to product_logo.png during copy.
// Use brave_origin logos when is_brave_origin_branded is true.
const productLogoSource = config.isBraveOriginBranded
? 'brave_origin'
: 'brave'
for (const scale of ['default_100_percent', 'default_200_percent']) {
fileMap.add([
path.join(
braveAppDir,
'theme',
scale,
productLogoSource,
'product_logo_name_48.png',
),
path.join(
chromeComponentsDir,
'resources',
scale,
'chromium',
'product_logo.png',
),
])
fileMap.add([
path.join(
braveAppDir,
'theme',
scale,
productLogoSource,
'product_logo_white.png',
),
path.join(
chromeComponentsDir,
'resources',
scale,
'chromium',
'product_logo_white.png',
),
])
}
for (const branding of ['brave', 'brave_origin']) {
fileMap.add([
path.join(braveAppVectorIconsDir, 'vector_icons', branding),
path.join(chromeComponentsDir, 'vector_icons', branding),
])
// Copy to make our ${branding_path_product}_behaviors.cc
fileMap.add([
path.join(
config.braveCoreDir,
'chromium_src',
'chrome',
'installer',
'setup',
`${branding}_behaviors.cc`,
),
path.join(
config.srcDir,
'chrome',
'installer',
'setup',
`${branding}_behaviors.cc`,
),
])
}
// Replace webui CSS to use our fonts.
fileMap.add([
path.join(
config.braveCoreDir,
'ui',
'webui',
'resources',
'css',
'text_defaults_md.css',
),
path.join(
config.srcDir,
'ui',
'webui',
'resources',
'css',
'text_defaults_md.css',
),
])
// Replace chrome dark logo with channel specific brave logo.
fileMap.add([
path.join(
config.braveCoreDir,
'node_modules',
'@brave',
'leo',
'icons',
config.getBraveLogoIconName(),
),
path.join(
config.srcDir,
'ui',
'webui',
'resources',
'images',
'chrome_logo_dark.svg',
),
])
// Replace webui bookmark svg icon.
fileMap.add([
path.join(
config.braveCoreDir,
'node_modules',
'@brave',
'leo',
'icons',
'browser-bookmark-normal.svg',
),
path.join(
config.srcDir,
'ui',
'webui',
'resources',
'images',
'icon_bookmark.svg',
),
])
let explicitSourceFiles = new Set()
if (config.targetOS === 'mac') {
// Set proper branding file name based on channel.
let brandingFileName = 'BRANDING'
if (config.channel) {
brandingFileName = brandingFileName + '.' + config.channel
}
for (const branding of ['brave', 'brave_origin']) {
// Set proper mac app icon for channel to chrome/app/theme/mac/app.icns.
// Each channel's app icons are stored in
// brave/app/theme/$channel/app.icns.
// With this copying, we don't need to modify chrome/BUILD.gn for this.
const iconSource = path.join(
braveAppDir,
'theme',
branding,
'mac',
config.channel,
'app.icns',
)
const iconDest = path.join(
chromeAppDir,
'theme',
branding,
'mac',
'app.icns',
)
explicitSourceFiles[iconDest] = iconSource
// Set proper mac app asset catalog for channel to
// chrome/app/theme/mac/Assets.car. Each channel's resource catalog is
// stored in brave/app/theme/$channel/Assets.car. With this copying, we
// don't need to modify chrome/BUILD.gn for this.
const assetCatalogSource = path.join(
braveAppDir,
'theme',
branding,
'mac',
config.channel,
'Assets.car',
)
const assetCatalogDest = path.join(
chromeAppDir,
'theme',
branding,
'mac',
'Assets.car',
)
explicitSourceFiles[assetCatalogDest] = assetCatalogSource
// Set proper branding file.
const brandingSource = path.join(
braveAppDir,
'theme',
branding,
brandingFileName,
)
const brandingDest = path.join(
chromeAppDir,
'theme',
branding,
'BRANDING',
)
explicitSourceFiles[brandingDest] = brandingSource
}
}
for (const [source, output] of fileMap) {
if (!fs.existsSync(source)) {
console.warn(
`Warning: The following file-system entry was not found for copying contents to a chromium destination: ${source}. Consider removing the entry from the file-map, or investigating whether the correct source code reference is checked out.`,
)
continue
}
let sourceFiles = []
// get all the files if source if a directory
if (fs.statSync(source).isDirectory()) {
sourceFiles = util.walkSync(source)
} else {
sourceFiles = [source]
}
for (let sourceFile of sourceFiles) {
if (path.basename(sourceFile) === 'README.md') {
continue
}
const destinationFile = path.join(
output,
path.relative(source, sourceFile),
)
sourceFile = explicitSourceFiles[destinationFile] || sourceFile
if (
!fs.existsSync(destinationFile)
|| util.calculateFileChecksum(sourceFile)
!== util.calculateFileChecksum(destinationFile)
) {
fs.copySync(sourceFile, destinationFile)
console.log(sourceFile + ' copied to ' + destinationFile)
}
}
}
if (config.targetOS === 'android') {
let braveOverwrittenFiles = new Set()
const removeUnlistedAndroidResources = (braveOverwrittenFiles) => {
const suspectedDir = path.join(
config.srcDir,
'chrome',
'android',
'java',
'res',
)
let untrackedChromiumFiles = util
.runGit(
suspectedDir,
['ls-files', '--others', '--exclude-standard'],
true,
)
.split('\n')
let untrackedChromiumPaths = []
for (const untrackedChromiumFile of untrackedChromiumFiles) {
untrackedChromiumPath = path.join(suspectedDir, untrackedChromiumFile)
if (!fs.statSync(untrackedChromiumPath).isDirectory()) {
untrackedChromiumPaths.push(untrackedChromiumPath)
}
}
const isChildOf = (child, parent) => {
const relative = path.relative(parent, child)
return (
relative && !relative.startsWith('..') && !path.isAbsolute(relative)
)
}
for (const untrackedChromiumPath of untrackedChromiumPaths) {
if (
isChildOf(untrackedChromiumPath, suspectedDir)
&& !braveOverwrittenFiles.has(untrackedChromiumPath)
) {
fs.removeSync(untrackedChromiumPath)
console.log(`Deleted not listed file: ${untrackedChromiumPath}`)
}
}
}
let androidIconSet = ''
if (config.channel === 'development') {
androidIconSet = 'res_brave_default'
} else if (config.channel === '') {
androidIconSet = 'res_brave'
} else if (config.channel === 'beta') {
androidIconSet = 'res_brave_beta'
} else if (config.channel === 'dev') {
androidIconSet = 'res_brave_dev'
} else if (config.channel === 'nightly') {
androidIconSet = 'res_brave_nightly'
}
const androidResSource = path.join(
config.braveCoreDir,
'android',
'java',
'res',
)
const androidResDest = path.join(
config.srcDir,
'chrome',
'android',
'java',
'res',
)
const androidFeaturesTabUiResSource = path.join(
config.braveCoreDir,
'android',
'features',
'tab_ui',
'java',
'res',
)
const androidFeaturesTabUiDest = path.join(
config.srcDir,
'chrome',
'android',
'features',
'tab_ui',
'java',
'res',
)
const androidDownloadInternalResSource = path.join(
config.braveCoreDir,
'browser',
'download',
'internal',
'android',
'java',
'res',
)
const androidDownloadInternalResDest = path.join(
config.srcDir,
'chrome',
'browser',
'download',
'internal',
'android',
'java',
'res',
)
const androidIconSource = path.join(
braveAppDir,
'theme',
'brave',
'android',
androidIconSet,
)
const androidIconDest = path.join(
config.srcDir,
'chrome',
'android',
'java',
'res_chromium',
)
const androidIconBaseSource = path.join(
braveAppDir,
'theme',
'brave',
'android',
androidIconSet + '_base',
)
const androidIconBaseDest = path.join(
config.srcDir,
'chrome',
'android',
'java',
'res_chromium_base',
)
// Mapping for copying Brave's Android resource into chromium folder.
const copyAndroidResourceMapping = {
[androidResSource]: [androidResDest],
[androidFeaturesTabUiResSource]: [androidFeaturesTabUiDest],
[androidDownloadInternalResSource]: [androidDownloadInternalResDest],
[androidIconSource]: [androidIconDest],
[androidIconBaseSource]: [androidIconBaseDest],
}
console.log('copy Android app icons and app resources')
Object.entries(copyAndroidResourceMapping).map(
([sourcePath, destPaths]) => {
let androidSourceFiles = []
if (fs.statSync(sourcePath).isDirectory()) {
androidSourceFiles = util.walkSync(sourcePath)
} else {
androidSourceFiles = [sourcePath]
}
for (const destPath of destPaths) {
for (const androidSourceFile of androidSourceFiles) {
let destinationFile = path.join(
destPath,
path.relative(sourcePath, androidSourceFile),
)
if (
!fs.existsSync(destinationFile)
|| util.calculateFileChecksum(androidSourceFile)
!== util.calculateFileChecksum(destinationFile)
) {
fs.copySync(androidSourceFile, destinationFile)
}
braveOverwrittenFiles.add(destinationFile)
}
}
},
)
removeUnlistedAndroidResources(braveOverwrittenFiles)
}
Log.progressFinish('update branding')
}