* Enable HEVC/H.265 software video decoding on Linux Adds FFmpeg-based HEVC/H.265 software decoding support for Linux, providing a fallback when hardware decode is unavailable (e.g., NVIDIA GPUs where VA-API is not functional in Chromium). - chromium_src override for supported_types.cc (HEVC as built-in codec) - brave/third_party/ffmpeg/sources.gni with HEVC source lists, imported via ffmpeg_generated.gni patch - Minimal patches for ffmpeg_common.cc and ffmpeg_video_decoder.cc (anonymous namespace / file-local functions, not overridable) - All HEVC code paths gated on BUILDFLAG(ENABLE_PLATFORM_HEVC) to allow disabling via build args - FFmpeg config patches for Linux x64 (config.h, config_components.h, codec_list.c, parser_list.c, autorename wrappers) - Enable enable_platform_hevc and enable_hevc_parser_and_hw_decoder - Add ffmpeg to patch apply/update infrastructure with s.path guard Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Address review: advertise HEVC support to web content on Linux On Linux, upstream's IsDecoderHevcProfileSupported takes the PLATFORM_HAS_OPTIONAL_HEVC_DECODE_SUPPORT path and consults the supplemental profile cache, which is populated only by hardware decoders registering via the GPU mojo interface. Since we ship a bundled FFmpeg software decoder that never touches that cache, MediaSource.isTypeSupported('video/mp4;codecs="hev1.1.6.L93.B0"') returned false even though the decoder could handle the stream. Override IsDefaultDecoderSupportedVideoType so that when upstream rejects HEVC for that reason alone (cache empty), we fall back to returning true. HDR, color space, and proprietary-codec gating from upstream are preserved. * Address review: round-trip new-file patches through apply/update_patches Two related issues with how brave's patch tooling handles patches that create new files (new file mode diffs): apply_patches would fail on a fresh checkout with "Target file does not exist" because isPatchStale treats a missing target as SRC_REMOVED and bails out before apply. Teach it to recognize "new file mode" patches and re-route through SRC_CHANGED so apply proceeds. Also unlink any leftover target before apply so re-runs on an existing checkout don't hit "already exists in working directory". update_patches would silently delete new-file patches because getModifiedPaths only inspected tracked/modified files. git apply creates new files without staging them, so they show up as untracked (??) and never reach the diff. Extend it to pick up untracked paths that correspond to an existing patch, and generate their diff via git diff --no-index /dev/null <path> to match the new-file-mode format produced by git apply. The four autorename_*.c.patch files in third_party/ffmpeg now round- trip cleanly across apply/update cycles, which addresses the "update_patches currently removes some patches you added here" review comment. * Address review: rebase HEVC patches onto Chromium 147 ffmpeg Refresh patch index hashes to the current third_party/ffmpeg tree, tighten the ffmpeg_generated.gni patch to avoid an empty line at the hunk boundary (presubmit warning), and pick up libavcodec/x86/hevc/ dequant.asm, which upstream added since the original patch set and whose absence caused an ff_hevc_dequant_8_ssse3 link error. All four autorename_*.c patches, the config/config_components toggles, the generated-list import, and the BUILD.gn include_dirs tweak now apply cleanly on Chromium 147 and the resulting build links and plays HEVC streams end-to-end. * Address review: host autorename stubs in brave/third_party/ffmpeg Moves the four HEVC autorename .c stubs from patches/third_party/ffmpeg/ into brave/third_party/ffmpeg/libavcodec/ (and libavcodec/hevc/) so they're regular brave-owned sources rather than new-file patches against upstream ffmpeg. This is what goodov suggested in review. The stubs use fully-qualified includes like "libavcodec/hevc/cabac.c", which resolve through the existing -I "." on ffmpeg_internal — so the upstream source is what actually gets compiled, just under a different object name to keep the linker happy. sources.gni references the new files with absolute //brave/... paths. One thing I missed on the first build: libavcodec/cabac.c and libavcodec/hevc/cabac.c are two different files, and the hevc stub needs to point at the latter or the linker complains about duplicate ff_init_cabac_decoder. Fixed before pushing. Since no new-file patches are left in the PR, the apply/update_patches tooling changes from c1b2b937cf9 don't have a reason to be here anymore. Reverted them — gitPatcher.js and updatePatches.js are back to where they were before this PR. Tested locally on Linux x64 component build: apply_patches and update_patches round-trip cleanly, gn_check passes, ffmpeg and media targets both build, and HEVC playback still works end to end. * Address review: centralize HEVC enabled check via FFmpegSupportsHEVC helper Introduces FFmpegSupportsHEVC() and HEVCAsH264IfFFmpegSupportsHEVC() in chromium_src/media/base/supported_types.{h,cc}. The helpers wrap the BUILDFLAG(IS_LINUX) && BUILDFLAG(ENABLE_PLATFORM_HEVC) check in one place so callers don't have to repeat it. Most of this is shrinking the existing patches: - patches/media-filters-ffmpeg_video_decoder.cc.patch: drops the nested #if BUILDFLAG blocks around the kHEVC switch case and IsCodecSupported. The switch now reads `HEVCAsH264IfFFmpegSupportsHEVC(config.codec())` so kHEVC reuses the kH264 threading branch, and IsCodecSupported maps the incoming codec the same way before its kH264 comparison. - patches/media-ffmpeg-ffmpeg_common.cc.patch: one-line `if (FFmpegSupportsHEVC()) return "h264,hevc";` instead of a C-preprocessor branch. - chromium_src/media/base/supported_types.cc: IsDecoderBuiltInVideoCodec, IsDefaultDecoderSupportedVideoType and IsDecoderSupportedVideoType all go through FFmpegSupportsHEVC() now. The third one matters: blink (webcodecs, media_capabilities) calls the public IsDecoderSupportedVideoType, and the upstream definition calls IsDefaultDecoderSupportedVideoType internally — which under our #define rebrand routes to _ChromiumImpl and bypasses our override. Overriding the public entry point too keeps the helper authoritative whichever path the caller takes. The override file now includes media/base/supported_types.h *before* the rebrand #defines and forward-declares the *_ChromiumImpl variants. That way the MEDIA_EXPORT declarations of the three Is* functions are visible with their original names when our override definitions are compiled, so the symbols get the right visibility without having to repeat MEDIA_EXPORT on every override body. Verified by checking `nm -D libmedia.so` — IsDecoderBuiltInVideoCodec, IsDefaultDecoderSupportedVideoType and IsDecoderSupportedVideoType are all exported, and media:media_unittests links cleanly. sources.gni: collapses the two duplicated `is_linux && ffmpeg_branding` conditions into a single `enable_ffmpeg_hevc_support` flag derived from the upstream `enable_hevc_parser_and_hw_decoder` build arg. Drops chromeos / fuchsia from the condition (not relevant for this PR). Test adjustments for the new HEVC-supported reality on Linux: - media_unittests: SupportedTypesTest.IsDecoderBuiltInVideoCodec and IsDecoderSupportedVideoTypeBasics asserted HEVC=false unconditionally; switched to `EXPECT_EQ(..., FFmpegSupportsHEVC())` so they pass on Linux with the FFmpeg HEVC decoder built in and stay correct everywhere else. - browser_tests: EncryptedMediaSupportedTypesTest::CheckPlatformHevcSupport asserted UNSUPPORTED for HEVC on Linux. With the software decoder built in HEVC is supported via Clear Key too, so the assertion now flips to EXPECT_ECK_PROPRIETARY when FFmpegSupportsHEVC() is true. This fixes EncryptedMediaSupportedTypesClearKeyTest.Video_MP4 and the two ExternalClearKey variants (Basic, Video_MP4). Also renames the four autorename stubs to drop the "autorename_" prefix and removes the "Auto-generated" wording from their comments — they aren't produced by a script, they're hand-placed brave sources. The sources.gni references are updated to match. Verified on Linux x64 component build with chromium 149: gn_check, format, presubmit, full brave build, SupportedTypesTest.* (32 tests) and the four EME browser_tests above all green. HEVC playback + MSE isTypeSupported confirmed end to end on a Main / Main10 / Level 5 test clip. * Address review: enable HEVC software decoder on linux-arm64 Mirrors the linux-x64 enablement on linux-arm64 so HEVC isn't a brave-on-x64-only feature. ffmpeg config patches: four new patches under chromium/config/Chrome/ linux/arm64/, symmetric to the existing x64 ones — flip CONFIG_BSWAPDSP, CONFIG_HEVC_DECODER and CONFIG_HEVC_PARSER to 1, and add ff_hevc_decoder / ff_hevc_parser to codec_list.c / parser_list.c. sources.gni: new `if (enable_ffmpeg_hevc_support && current_cpu == "arm64")` block pulling in the libavcodec/aarch64 HEVC NEON files that upstream's Makefile lists for CONFIG_HEVC_DECODER (hevcdsp_init, hevcdsp_{deblock,dequant,idct}_neon and h26x/{epel,qpel,sao}_neon). Also introduce a `brave_third_party_ffmpeg_gas_sources` list — arm64 hand-written assembly goes through ffmpeg_gas_sources upstream rather than ffmpeg_asm_sources (which is nasm-only). The ffmpeg_generated.gni patch is extended to append it. Verified: gn_check, format, presubmit all green. autoninja third_party/ffmpeg:ffmpeg in a cross-compiled Component_arm64 build dir links cleanly. Couldn't get a full media:media_unittests build past unrelated clang segfaults on V8 torque-generated sources locally, but that's host-side flake — the brave CI arm64 builders should hit a clean environment. Don't have arm64 hardware to runtime-verify; relying on CI for that. --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
409 lines
19 KiB
Python
409 lines
19 KiB
Python
# Copyright (c) 2019 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/.
|
|
|
|
import os
|
|
from pathlib import Path
|
|
import re
|
|
import subprocess
|
|
import tomllib
|
|
|
|
BRAVE_SCRIPT_PATH = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
BRAVE_THIRD_PARTY_DIRS = [
|
|
'vendor',
|
|
]
|
|
|
|
ANDROID_ONLY_PATHS = []
|
|
|
|
DESKTOP_ONLY_PATHS = []
|
|
|
|
_REPOSITORY_ROOT = None
|
|
|
|
|
|
def GetRustWorkspaceTransitiveDeps(workspace):
|
|
ws_abs_path = Path(f'{_REPOSITORY_ROOT}/{workspace}')
|
|
|
|
def GetMembers():
|
|
with open(Path(f'{ws_abs_path}/Cargo.toml'), 'rb') as f:
|
|
return tomllib.load(f)['workspace']['members']
|
|
|
|
# The `members` field in `[workspace]` is an array of directories
|
|
# (as opposed to an array of package names), hence inspecting the
|
|
# Cargo.toml of each member, instead of using the Cargo.lock
|
|
# of the workspace.
|
|
def GetDepsForMember(member):
|
|
with open(Path(f'{ws_abs_path}/{member}/Cargo.toml'), 'rb') as f:
|
|
return list(tomllib.load(f)['dependencies'].keys())
|
|
|
|
all_deps = next(os.walk(Path(f'{ws_abs_path}/vendor')))[1]
|
|
direct_deps = [GetDepsForMember(member) for member in GetMembers()]
|
|
return [
|
|
str(Path(f'{workspace}/vendor/{dep}')) for dep in all_deps
|
|
if dep not in sum(direct_deps, [])
|
|
]
|
|
|
|
def AddBraveCredits(root, prune_paths, special_cases, prune_dirs,
|
|
additional_paths):
|
|
global _REPOSITORY_ROOT # pylint: disable=global-statement
|
|
_REPOSITORY_ROOT = root
|
|
|
|
# Exclude these specific paths from needing a README.chromium file.
|
|
prune_paths.update([
|
|
# Formerly external Brave code which has moved to brave-core
|
|
# (i.e these are already covered by the Brave Browser license notice).
|
|
os.path.join('brave', 'vendor', 'brave-ios'),
|
|
os.path.join('brave', 'vendor', 'brave_base'),
|
|
|
|
# Metadata files for Rust crates are located in the subfolders of
|
|
# brave/third_party/rust/<crate_name>/<v>, the crates themselves in
|
|
# brave/third_party/rust/chromium_crates_io can be skipped.
|
|
os.path.join('brave', 'third_party', 'rust', 'chromium_crates_io'),
|
|
|
|
# Same for upstream
|
|
os.path.join('third_party', 'rust', 'chromium_crates_io'),
|
|
|
|
# Rust code written by Brave and under the same license as the browser.
|
|
os.path.join('brave', 'third_party', 'rust', 'adblock_cxx'),
|
|
os.path.join('brave', 'third_party', 'rust', 'anonymous_credentials'),
|
|
os.path.join('brave', 'third_party', 'rust', 'brave_news_cxx'),
|
|
os.path.join('brave', 'third_party', 'rust', 'brave_wallet'),
|
|
os.path.join('brave', 'third_party', 'rust',
|
|
'challenge_bypass_ristretto_cxx'),
|
|
os.path.join('brave', 'third_party', 'rust', 'constellation_cxx'),
|
|
os.path.join('brave', 'third_party', 'rust', 'document_extractor'),
|
|
os.path.join('brave', 'third_party', 'rust', 'json_cxx'),
|
|
os.path.join('brave', 'third_party', 'rust', 'filecoin_cxx'),
|
|
os.path.join('brave', 'third_party', 'rust', 'skus'),
|
|
os.path.join('brave', 'third_party', 'rust', 'skus_cxx'),
|
|
os.path.join('brave', 'third_party', 'rust', 'speedreader'),
|
|
os.path.join('brave', 'third_party', 'rust', 'speedreader_ffi'),
|
|
|
|
# Rust crates that are references to upstream crates and should have
|
|
# licenses in upstream //third_party/rust.
|
|
os.path.join('brave', 'third_party', 'rust', 'aho_corasick'),
|
|
os.path.join('brave', 'third_party', 'rust', 'anyhow'),
|
|
os.path.join('brave', 'third_party', 'rust', 'base64'),
|
|
os.path.join('brave', 'third_party', 'rust', 'bitflags'),
|
|
os.path.join('brave', 'third_party', 'rust', 'bitflags', 'v2'),
|
|
os.path.join('brave', 'third_party', 'rust', 'byteorder', 'v1'),
|
|
os.path.join('brave', 'third_party', 'rust', 'cfg_if'),
|
|
os.path.join('brave', 'third_party', 'rust', 'cxx'),
|
|
os.path.join('brave', 'third_party', 'rust', 'cxxbridge_flags'),
|
|
os.path.join('brave', 'third_party', 'rust', 'cxxbridge_macro'),
|
|
os.path.join('brave', 'third_party', 'rust', 'foldhash'),
|
|
os.path.join('brave', 'third_party', 'rust', 'getrandom', 'v0_2'),
|
|
os.path.join('brave', 'third_party', 'rust', 'hex'),
|
|
os.path.join('brave', 'third_party', 'rust', 'itoa', 'v1'),
|
|
os.path.join('brave', 'third_party', 'rust', 'lazy_static'),
|
|
os.path.join('brave', 'third_party', 'rust', 'libc'),
|
|
os.path.join('brave', 'third_party', 'rust', 'log'),
|
|
os.path.join('brave', 'third_party', 'rust', 'memchr'),
|
|
os.path.join('brave', 'third_party', 'rust', 'ppv_lite86'),
|
|
os.path.join('brave', 'third_party', 'rust', 'proc_macro2'),
|
|
os.path.join('brave', 'third_party', 'rust', 'quote'),
|
|
os.path.join('brave', 'third_party', 'rust', 'rand', 'v0_8'),
|
|
os.path.join('brave', 'third_party', 'rust', 'rand_core', 'v0_6'),
|
|
os.path.join('brave', 'third_party', 'rust', 'rustc_version', 'v0_4'),
|
|
os.path.join('brave', 'third_party', 'rust', 'regex'),
|
|
os.path.join('brave', 'third_party', 'rust', 'regex_automata'),
|
|
os.path.join('brave', 'third_party', 'rust', 'regex_syntax'),
|
|
os.path.join('brave', 'third_party', 'rust', 'rustversion'),
|
|
os.path.join('brave', 'third_party', 'rust', 'ryu'),
|
|
os.path.join('brave', 'third_party', 'rust', 'serde'),
|
|
os.path.join('brave', 'third_party', 'rust', 'serde_json'),
|
|
os.path.join('brave', 'third_party', 'rust', 'static_assertions'),
|
|
os.path.join('brave', 'third_party', 'rust', 'syn'),
|
|
os.path.join('brave', 'third_party', 'rust', 'unicode_ident'),
|
|
os.path.join('brave', 'third_party', 'rust', 'winapi'),
|
|
os.path.join('brave', 'third_party', 'rust', 'zerocopy', 'v0_7'),
|
|
os.path.join('brave', 'third_party', 'rust', 'zerocopy_derive',
|
|
'v0_7'),
|
|
|
|
# Rust crates that are downloaded but not used (due to Cargo.toml
|
|
# misconfigurations in other crates).
|
|
os.path.join('brave', 'third_party', 'rust', 'valuable'),
|
|
os.path.join('brave', 'third_party', 'rust',
|
|
'windows_aarch64_gnullvm'),
|
|
os.path.join('brave', 'third_party', 'rust', 'windows_i686_gnu'),
|
|
os.path.join('brave', 'third_party', 'rust', 'windows_x86_64_gnu'),
|
|
os.path.join('brave', 'third_party', 'rust', 'windows_x86_64_gnullvm'),
|
|
|
|
# No third-party code directly under android_deps. It's all under
|
|
# android_deps/libs instead and it's special-cased further down.
|
|
os.path.join('brave', 'third_party', 'android_deps'),
|
|
|
|
# Brave overrides to third-party code, also covered by main notice.
|
|
os.path.join('brave', 'third_party', 'blink'),
|
|
os.path.join('brave', 'third_party', 'ffmpeg'),
|
|
os.path.join('brave', 'third_party', 'libaddressinput'),
|
|
os.path.join('brave', 'patches', 'third_party'),
|
|
os.path.join('brave', 'third_party', 'polymer'),
|
|
os.path.join('brave', 'third_party', 'lit'),
|
|
os.path.join('brave', 'third_party', 'devtools-frontend'),
|
|
|
|
# Dependencies that are already in brave-core, and whose notices
|
|
# therefore do not need to be repeated.
|
|
os.path.join('brave', 'third_party', 'updater'),
|
|
os.path.join('brave', 'vendor', 'omaha', 'omaha', 'third_party',
|
|
'chrome'),
|
|
os.path.join('brave', 'vendor', 'omaha', 'third_party', 'libzip'),
|
|
os.path.join('brave', 'vendor', 'omaha', 'third_party', 'lzma'),
|
|
os.path.join('brave', 'vendor', 'omaha', 'third_party', 'zlib'),
|
|
|
|
# Dependencies already mentioned in the main breakpad notice.
|
|
os.path.join('brave', 'vendor', 'omaha', 'third_party', 'breakpad',
|
|
'src', 'third_party', 'curl'),
|
|
os.path.join('brave', 'vendor', 'omaha', 'third_party', 'breakpad',
|
|
'src', 'third_party', 'libdisasm'),
|
|
os.path.join('brave', 'vendor', 'omaha', 'third_party', 'breakpad',
|
|
'src', 'third_party', 'linux'),
|
|
os.path.join('brave', 'vendor', 'omaha', 'third_party', 'breakpad',
|
|
'src', 'third_party', 'mac_headers'),
|
|
|
|
# Essentially empty directories that should be cleaned up upstream.
|
|
os.path.join('brave', 'vendor', 'omaha', 'omaha', 'third_party',
|
|
'hashlib'),
|
|
|
|
# No licensing information in recursive dependency. This should be
|
|
# added upstream.
|
|
os.path.join('brave', 'vendor', 'omaha', 'omaha', 'third_party',
|
|
'smartany'),
|
|
|
|
# Build dependencies which don't end up in the binaries.
|
|
os.path.join('brave', 'vendor', 'depot_tools'),
|
|
os.path.join('brave', 'vendor', 'gn-project-generators'),
|
|
os.path.join('brave', 'vendor', 'omaha', 'omaha', 'scons-out'),
|
|
os.path.join('brave', 'third_party', 'libdmg-hfsplus'),
|
|
os.path.join('brave', 'tools', 'crates', 'vendor'),
|
|
|
|
# plaster .toml file location should be skipped.
|
|
os.path.join('brave', 'rewrite', 'third_party'),
|
|
|
|
# TODO(https://github.com/brave/brave-browser/issues/54804)
|
|
# remove the following line once we start putting
|
|
# WinTun binaries into the browser distribution on Windows.
|
|
os.path.join('brave', 'third_party', 'wintun'),
|
|
|
|
# vendored boringtun crate has a top-level LICENSE file.
|
|
os.path.join('brave', 'third_party', 'boringtun', 'vendor',
|
|
'boringtun'),
|
|
# vendored ring third-party dependencies are covered by its top
|
|
# level license.
|
|
os.path.join('brave', 'third_party', 'boringtun', 'vendor', 'ring',
|
|
'third_party'),
|
|
|
|
# TODO(https://github.com/brave/brave-browser/issues/54804)
|
|
# remove the following line once we start putting
|
|
# boringtun binaries into the browser distribution.
|
|
os.path.join('brave', 'third_party', 'boringtun'),
|
|
|
|
# Transitive deps in brave/third_party/wasm.
|
|
*GetRustWorkspaceTransitiveDeps(Path('brave/third_party/wasm')),
|
|
])
|
|
|
|
# Add the licensing info that would normally be in a README.chromium file.
|
|
# This is for when we pull in external repos directly.
|
|
special_cases.update({
|
|
os.path.join('brave', 'vendor', 'bat-native-tweetnacl'): {
|
|
"Name": "TweetNaCl",
|
|
"URL": "https://github.com/brave-intl/bat-native-tweetnacl",
|
|
"License": "MPL-2.0",
|
|
},
|
|
os.path.join('brave', 'third_party', 'bip39wally-core-native'): {
|
|
"Name": "libwally-core",
|
|
"URL": "https://github.com/brave-intl/bat-native-bip39wally-core",
|
|
"License": "MIT",
|
|
},
|
|
os.path.join('brave', 'third_party', 'rust', 'futures_retry', 'v0_5'): {
|
|
"Name": "futures-retry",
|
|
"URL": "https://crates.io/crates/futures-retry",
|
|
"License": "Apache-2.0",
|
|
},
|
|
os.path.join('brave', 'vendor', 'brave-extension'): {
|
|
"Name": "Brave Only Extension",
|
|
"URL": "https://github.com/brave/brave-extension",
|
|
"License": "MPL-2.0",
|
|
},
|
|
os.path.join('brave', 'vendor', 'web-discovery-project'): {
|
|
"Name": "Web Discovery Project",
|
|
"URL": "https://github.com/brave/web-discovery-project",
|
|
"License": "MPL-2.0",
|
|
},
|
|
os.path.join('brave', 'vendor', 'omaha'): {
|
|
"Name": "Omaha",
|
|
"URL": "https://github.com/brave/omaha",
|
|
"License": "Apache-2.0",
|
|
"License File": ["/brave/vendor/omaha/LICENSE.txt"],
|
|
},
|
|
os.path.join('brave', 'vendor', 'omaha', 'third_party', 'breakpad'): {
|
|
"Name": "Breakpad",
|
|
"URL": "https://chromium.googlesource.com/breakpad/breakpad",
|
|
"License File": [
|
|
"/brave/vendor/omaha/third_party/breakpad/LICENSE"
|
|
],
|
|
},
|
|
# Unclear why, but presumbit wants this line formatted this way, while
|
|
# at the same time complaining it's too long when it is formatted so.
|
|
os.path.join('brave', 'vendor', 'omaha', 'third_party', 'breakpad', 'src', 'third_party', 'musl'): { # pylint: disable=line-too-long
|
|
"Name": "musl",
|
|
"URL": "https://musl.libc.org/",
|
|
"License File": [
|
|
"/brave/vendor/omaha/third_party/breakpad/src/third_party/"
|
|
"musl/COPYRIGHT"
|
|
],
|
|
},
|
|
os.path.join('brave', 'vendor', 'omaha', 'third_party', 'googletest'): {
|
|
"Name": "GoogleTest",
|
|
"URL": "https://github.com/google/googletest",
|
|
"License": "BSD",
|
|
"License File": [
|
|
"/brave/vendor/omaha/third_party/googletest/LICENSE"
|
|
],
|
|
},
|
|
os.path.join('brave', 'third_party', 'reclient_configs'): {
|
|
"Name": "reclient-configs",
|
|
"URL": "https://github.com/EngFlow/reclient-configs",
|
|
"License": "Apache-2.0",
|
|
"License File": ["/brave/third_party/reclient_configs/src/LICENSE"],
|
|
},
|
|
os.path.join('brave', 'vendor', 'python-patch'): {
|
|
"Name": "Python Patch",
|
|
"URL": "https://github.com/brave/python-patch",
|
|
"License": "MIT",
|
|
"License File": ["/brave/vendor/python-patch/doc/LICENSE"],
|
|
},
|
|
os.path.join('brave', 'vendor', 'sparkle'): {
|
|
"Name": "Sparkle",
|
|
"URL": "https://github.com/brave/Sparkle",
|
|
"License": "MIT",
|
|
},
|
|
os.path.join('brave', 'third_party', 'cryptography'): {
|
|
"Name": "cryptography",
|
|
"URL": "https://cryptography.io",
|
|
"License": "Apache-2.0",
|
|
"License File": ["/brave/common/licenses/Apache-2.0"],
|
|
},
|
|
os.path.join('brave', 'third_party', 'macholib'): {
|
|
"Name": "macholib",
|
|
"URL": "https://github.com/ronaldoussoren/macholib",
|
|
"License": "MIT",
|
|
},
|
|
})
|
|
|
|
# Don't recurse into these directories looking for third-party code.
|
|
prune_list = list(prune_dirs)
|
|
prune_list += [
|
|
'chromium_src', # Brave's overrides, covered by main notice.
|
|
'node_modules', # See brave/third_party/npm-* instead.
|
|
'.vscode', # Automatically added by Visual Studio.
|
|
]
|
|
prune_dirs = tuple(prune_list)
|
|
|
|
# Look for a README.chromium file directly inside these directories.
|
|
# This is for directories which include third-party code that isn't
|
|
# contained under a "third_party" or "vendor" directory.
|
|
additional_list = list(additional_paths)
|
|
additional_list += [
|
|
os.path.join('brave', 'resources', 'brave_new_tab_page_refresh',
|
|
'state', 'background_images'),
|
|
os.path.join('brave', 'browser', 'brave_vpn', 'win',
|
|
'brave_vpn_wireguard_service'),
|
|
os.path.join('brave', 'components', 'filecoin'),
|
|
os.path.join('brave', 'android', 'java', 'org', 'chromium', 'chrome',
|
|
'browser', 'util'),
|
|
]
|
|
|
|
# Add all Android libraries since they're not directly contained
|
|
# within a third_party directory.
|
|
android_libs = os.path.join('brave', 'third_party', 'android_deps', 'libs')
|
|
for _, dirs, _ in os.walk(os.path.join(root, android_libs)):
|
|
for dirpath in dirs:
|
|
dirname = os.path.basename(dirpath)
|
|
additional_list += [os.path.join(android_libs, dirname)]
|
|
|
|
additional_paths = tuple(additional_list)
|
|
|
|
return (prune_dirs, additional_paths)
|
|
|
|
|
|
def CheckBraveMissingLicense(path, error):
|
|
if path.startswith('brave'):
|
|
# brave/third_party/rust and brave/third_party/wasm themselves
|
|
# don't need to have a license, but all subfolders should.
|
|
if path in (os.path.join('brave', 'third_party', 'rust'),
|
|
os.path.join('brave', 'third_party', 'wasm')):
|
|
return
|
|
output = subprocess.check_output(
|
|
[
|
|
'git', 'status', '-z',
|
|
os.path.join(os.path.relpath(path, 'brave'), 'LICENSE')
|
|
],
|
|
cwd=os.path.abspath(os.path.join(BRAVE_SCRIPT_PATH,
|
|
os.pardir))).decode("utf-8")
|
|
if output.startswith('??'):
|
|
return # Ignore untracked files
|
|
|
|
if not ContainsFiles(os.path.join(_REPOSITORY_ROOT, path)):
|
|
return # Empty directories do not require license.
|
|
print('\nERROR: missing license information in %s\n'
|
|
"If this is code you added, then you'll have to add the required "
|
|
"metadata.\nIf the path that's mentioned isn't something you "
|
|
"added, then you probably just need to remove that obsolete path "
|
|
"from your local checkout.\n" % path)
|
|
raise error
|
|
|
|
|
|
def ContainsFiles(path):
|
|
assert os.path.exists(path), f'{path} not found'
|
|
|
|
def reraise(e):
|
|
raise e
|
|
|
|
for _, _, filenames in os.walk(path, onerror=reraise):
|
|
if filenames:
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
def IsBraveRustCrate(path):
|
|
if not path:
|
|
return False
|
|
sep = re.escape(os.path.sep)
|
|
path_regex = re.compile(
|
|
r'''^(brave{sep})?third_party{sep}rust{sep}{nonsep}+'''.format(
|
|
sep=sep, nonsep=f'[^{sep}]'))
|
|
return path_regex.fullmatch(path) != None
|
|
|
|
|
|
def ReportBraveIncompleteMetadataFile(path):
|
|
if path.startswith('brave'):
|
|
# If there's no LICENSE file in the third party downloaded code, then
|
|
# we place LICENSE file next to README.chromium. This file cannot be
|
|
# added as a 'License File' into the README.chromium metadata, though,
|
|
# so this third party code won't be added into the credits page.
|
|
added_license_file = os.path.join(_REPOSITORY_ROOT,
|
|
os.path.join(path, 'LICENSE'))
|
|
if (os.path.isfile(added_license_file)):
|
|
return
|
|
|
|
raise ValueError(
|
|
'\n\nMETADATA ERROR: missing required fields in README.chromium in '
|
|
f'{path}\nIf this is code you added, then these metadata fields '
|
|
'in generated README.chromium are required: Name, URL, Shipped, '
|
|
'License File. You can fix it in one of these ways:'
|
|
'\n* If this is a Rust crate that you added and it has a custom '
|
|
'License File name, you can configure the custom name in '
|
|
'//brave/third_party/rust/chromium_crates_io/gnrt_config.toml.'
|
|
'\n* If this is a Rust crate that does not have a LICENSE file, '
|
|
'then either add LICENSE file in the same folder where the '
|
|
'README.chromium file is if the code has MIT license, or configure '
|
|
'the custom relative path to shared Apache-2.0 or MPL-2.0 licenses '
|
|
'(in //brave/commone/licenses) in '
|
|
'//brave/third_party/rust/chromium_crates_io/gnrt_config.toml'
|
|
'\n* If this is a Rust crate that is just a reference to an '
|
|
'upstream crate, then add it as an exception to prune_paths in '
|
|
'//brave/script/brave_license_helper.py.\n')
|