mirror of
https://github.com/aphrody-labs/cef.git
synced 2026-10-13 21:07:07 +00:00
bootstrap: Add sandbox compatibility hash (fixes #4092)
Introduce a hash of Chromium sandbox interface files to detect incompatibilities between bootstrap.exe and libcef.dll at runtime, allowing the strict version check to be skipped when interfaces match. Core implementation: - Add sandbox_compat_hash.py to calculate SHA-256 of interface files (chrome_elf_main.h, sandbox.h, sandbox_types.h, sandbox.mojom) - Update make_version_header.py to generate CEF_SANDBOX_COMPAT_HASH - Add sandbox_compat_hash field to cef_version_info_t struct - Add entry 3 to cef_api_hash() for retrieving the hash - Compare hashes in cef_scoped_library_loader_win.cc during load Version management: - Include sandbox_compat in cef_api_versions.json and cef_api_untracked.json - Compare sandbox_compat for untracked versions (NEXT, EXPERIMENTAL) - Trigger version bumps when sandbox interface files change Build automation: - Update cefbuilds JSON builder to include sandbox_compat in version records - Run version_manager.py -a after Chromium updates on release branches to auto-detect hash changes and add new API versions
This commit is contained in:
1 parent
58fa5d380a
commit
5d801ed841
11 files changed
+656
-35
No files matched your search
@@ -1584,8 +1584,21 @@ action("make_version_header") {
|
||||
"//chrome/VERSION",
|
||||
]
|
||||
outputs = [ "$root_gen_dir/cef/include/cef_version.h" ]
|
||||
|
||||
args = rebase_path(outputs, root_build_dir)
|
||||
|
||||
if (is_win) {
|
||||
# Sandbox interface files for Windows-only compatibility hash.
|
||||
_sandbox_compat_files = [
|
||||
"//chrome/chrome_elf/chrome_elf_main.h",
|
||||
"//sandbox/policy/mojom/sandbox.mojom",
|
||||
"//sandbox/win/src/sandbox.h",
|
||||
"//sandbox/win/src/sandbox_types.h",
|
||||
]
|
||||
|
||||
inputs += _sandbox_compat_files
|
||||
args += [ "--sandbox-files" ]
|
||||
args += rebase_path(_sandbox_compat_files, root_build_dir)
|
||||
}
|
||||
}
|
||||
|
||||
# This no-op action lists args.gn as an output, allowing it to be referenced as
|
||||
|
||||
@@ -131,6 +131,7 @@ extern "C" {
|
||||
/// 0 - CEF_API_HASH_PLATFORM
|
||||
/// 1 - CEF_API_HASH_UNIVERSAL (deprecated, same as CEF_API_HASH_PLATFORM)
|
||||
/// 2 - CEF_COMMIT_HASH (from cef_version.h)
|
||||
/// 3 - CEF_SANDBOX_COMPAT_HASH (from cef_version.h, Windows only)
|
||||
///
|
||||
CEF_EXPORT const char* cef_api_hash(int version, int entry);
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#define CEF_INCLUDE_CEF_VERSION_INFO_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "include/cef_api_hash.h"
|
||||
#include "include/internal/cef_export.h"
|
||||
@@ -77,8 +78,25 @@ typedef struct _cef_version_info_t {
|
||||
int chrome_version_minor;
|
||||
int chrome_version_build;
|
||||
int chrome_version_patch;
|
||||
|
||||
#if CEF_API_ADDED(CEF_NEXT)
|
||||
///
|
||||
/// Sandbox compatibility hash (Windows only, empty on other platforms).
|
||||
///
|
||||
char sandbox_compat_hash[17];
|
||||
#endif
|
||||
} cef_version_info_t;
|
||||
|
||||
#if CEF_API_ADDED(CEF_NEXT)
|
||||
///
|
||||
/// Minimum struct size required to contain the sandbox_compat_hash field.
|
||||
/// Used for version compatibility checks.
|
||||
///
|
||||
#define CEF_VERSION_INFO_SIZE_WITH_SANDBOX_HASH \
|
||||
(offsetof(cef_version_info_t, sandbox_compat_hash) + \
|
||||
sizeof(((cef_version_info_t*)0)->sandbox_compat_hash))
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Return all CEF version information for the libcef library.
|
||||
///
|
||||
@@ -104,6 +122,16 @@ typedef struct _cef_version_info_t {
|
||||
|
||||
#endif // !defined(GENERATING_CEF_API_HASH)
|
||||
|
||||
// Helper macro for setting sandbox_compat_hash.
|
||||
#if CEF_API_ADDED(CEF_NEXT)
|
||||
#define _CEF_POPULATE_SANDBOX_HASH(info) \
|
||||
strncpy((info)->sandbox_compat_hash, CEF_SANDBOX_COMPAT_HASH, \
|
||||
sizeof((info)->sandbox_compat_hash) - 1); \
|
||||
(info)->sandbox_compat_hash[sizeof((info)->sandbox_compat_hash) - 1] = '\0'
|
||||
#else
|
||||
#define _CEF_POPULATE_SANDBOX_HASH(info)
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Populate CEF version information for the client library.
|
||||
///
|
||||
@@ -116,7 +144,8 @@ typedef struct _cef_version_info_t {
|
||||
(info)->chrome_version_major = CHROME_VERSION_MAJOR; \
|
||||
(info)->chrome_version_minor = CHROME_VERSION_MINOR; \
|
||||
(info)->chrome_version_build = CHROME_VERSION_BUILD; \
|
||||
(info)->chrome_version_patch = CHROME_VERSION_PATCH
|
||||
(info)->chrome_version_patch = CHROME_VERSION_PATCH; \
|
||||
_CEF_POPULATE_SANDBOX_HASH(info)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -46,6 +46,11 @@ CEF_EXPORT int cef_version_info(int entry) {
|
||||
}
|
||||
|
||||
CEF_EXPORT void cef_version_info_all(cef_version_info_t* info) {
|
||||
if (!info || info->size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Always populate base version fields (present in all struct versions).
|
||||
info->cef_version_major = CEF_VERSION_MAJOR;
|
||||
info->cef_version_minor = CEF_VERSION_MINOR;
|
||||
info->cef_version_patch = CEF_VERSION_PATCH;
|
||||
@@ -54,6 +59,14 @@ CEF_EXPORT void cef_version_info_all(cef_version_info_t* info) {
|
||||
info->chrome_version_minor = CHROME_VERSION_MINOR;
|
||||
info->chrome_version_build = CHROME_VERSION_BUILD;
|
||||
info->chrome_version_patch = CHROME_VERSION_PATCH;
|
||||
|
||||
// Populate sandbox_compat_hash if the struct is large enough to contain it.
|
||||
// This allows older clients with smaller structs to still work.
|
||||
if (info->size >= CEF_VERSION_INFO_SIZE_WITH_SANDBOX_HASH) {
|
||||
strncpy(info->sandbox_compat_hash, CEF_SANDBOX_COMPAT_HASH,
|
||||
sizeof(info->sandbox_compat_hash) - 1);
|
||||
info->sandbox_compat_hash[sizeof(info->sandbox_compat_hash) - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
#include "cef/libcef_dll/cef_api_versions.inc"
|
||||
@@ -91,6 +104,8 @@ CEF_EXPORT const char* cef_api_hash(int version, int entry) {
|
||||
return current_version_hash->hash;
|
||||
case 2:
|
||||
return CEF_COMMIT_HASH;
|
||||
case 3:
|
||||
return CEF_SANDBOX_COMPAT_HASH;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// can be found in the LICENSE file.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
#include "include/base/cef_logging.h"
|
||||
#include "include/wrapper/cef_certificate_util_win.h"
|
||||
@@ -64,16 +65,71 @@ HMODULE Load(const std::wstring& dll_path,
|
||||
cef_version_info_all(&dll_info);
|
||||
#else
|
||||
// Only populating the members that are used below.
|
||||
dll_info.cef_version_major = cef_version_info(0);
|
||||
dll_info.cef_version_minor = cef_version_info(1);
|
||||
dll_info.cef_version_patch = cef_version_info(2);
|
||||
dll_info.chrome_version_major = cef_version_info(4);
|
||||
dll_info.chrome_version_patch = cef_version_info(7);
|
||||
#endif
|
||||
if (dll_info.chrome_version_major != version_info->chrome_version_major ||
|
||||
dll_info.chrome_version_patch != version_info->chrome_version_patch) {
|
||||
LOG(FATAL) << "Failed libcef.dll version check; expected "
|
||||
<< version_info->chrome_version_major << "."
|
||||
<< version_info->chrome_version_patch << ", got "
|
||||
<< dll_info.chrome_version_major << "."
|
||||
<< dll_info.chrome_version_patch;
|
||||
|
||||
bool check_dll_version = true;
|
||||
|
||||
#if CEF_API_ADDED(CEF_NEXT)
|
||||
// Check sandbox compatibility hash. Only compare if both structs are
|
||||
// large enough to contain the hash field.
|
||||
const bool version_info_has_hash =
|
||||
version_info->size >= CEF_VERSION_INFO_SIZE_WITH_SANDBOX_HASH;
|
||||
const bool dll_info_has_hash =
|
||||
dll_info.size >= CEF_VERSION_INFO_SIZE_WITH_SANDBOX_HASH;
|
||||
|
||||
if (version_info_has_hash && dll_info_has_hash) {
|
||||
if (version_info->sandbox_compat_hash[0] != '\0' &&
|
||||
dll_info.sandbox_compat_hash[0] != '\0') {
|
||||
if (std::strcmp(version_info->sandbox_compat_hash,
|
||||
dll_info.sandbox_compat_hash) != 0) {
|
||||
LOG(FATAL) << "Failed libcef.dll sandbox compatibility check; "
|
||||
"bootstrap hash: "
|
||||
<< version_info->sandbox_compat_hash
|
||||
<< ", bootstrap version: "
|
||||
<< version_info->cef_version_major << "."
|
||||
<< version_info->cef_version_minor << "."
|
||||
<< version_info->cef_version_patch
|
||||
<< ", libcef hash: " << dll_info.sandbox_compat_hash
|
||||
<< ", libcef version: " << dll_info.cef_version_major
|
||||
<< "." << dll_info.cef_version_minor << "."
|
||||
<< dll_info.cef_version_patch;
|
||||
}
|
||||
check_dll_version = false;
|
||||
}
|
||||
}
|
||||
#endif // CEF_API_ADDED(CEF_NEXT)
|
||||
|
||||
if (check_dll_version && (dll_info.chrome_version_major !=
|
||||
version_info->chrome_version_major ||
|
||||
dll_info.chrome_version_patch !=
|
||||
version_info->chrome_version_patch)) {
|
||||
LOG(FATAL) << "Failed libcef.dll version compatibility check; "
|
||||
"bootstrap version: "
|
||||
<< version_info->cef_version_major << "."
|
||||
<< version_info->cef_version_minor << "."
|
||||
<< version_info->cef_version_patch
|
||||
<< ", libcef version: " << dll_info.cef_version_major << "."
|
||||
<< dll_info.cef_version_minor << "."
|
||||
<< dll_info.cef_version_patch;
|
||||
}
|
||||
|
||||
const char* api_hash = cef_api_hash(CEF_API_VERSION, 0);
|
||||
if (std::strcmp(api_hash, CEF_API_HASH_PLATFORM) != 0) {
|
||||
LOG(FATAL) << "Failed libcef.dll API compatibility check; "
|
||||
"API version: "
|
||||
<< CEF_API_VERSION
|
||||
<< ", wrapper hash: " << CEF_API_HASH_PLATFORM
|
||||
<< ", wrapper version: " << CEF_VERSION_MAJOR << "."
|
||||
<< CEF_VERSION_MINOR << "." << CEF_VERSION_PATCH
|
||||
<< ", libcef hash: " << api_hash
|
||||
<< ", libcef version: " << dll_info.cef_version_major << "."
|
||||
<< dll_info.cef_version_minor << "."
|
||||
<< dll_info.cef_version_patch;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1636,6 +1636,14 @@ if chromium_checkout != chromium_compat_version:
|
||||
out_file = None
|
||||
check_pattern_matches(output_file=out_file)
|
||||
|
||||
# On release branches, check for sandbox compat hash changes that require
|
||||
# a new API version. This can happen when Chromium updates modify sandbox
|
||||
# interface files.
|
||||
if not branch_is_master and chromium_checkout_changed:
|
||||
msg('Checking for sandbox compat hash changes...')
|
||||
tool = os.path.join(cef_src_dir, 'tools', 'version_manager.py')
|
||||
run('%s %s -a' % (python_exe, tool), cef_src_dir)
|
||||
|
||||
##
|
||||
# Build CEF.
|
||||
##
|
||||
|
||||
@@ -24,7 +24,8 @@ else:
|
||||
# "versions": [
|
||||
# {
|
||||
# "cef_version": "3.2704.1414.g185cd6c",
|
||||
# "chromium_version": "51.0.2704.47"
|
||||
# "chromium_version": "51.0.2704.47",
|
||||
# "sandbox_compat": "abc123def4567890", # Optional, queried from GitHub
|
||||
# "files": [
|
||||
# {
|
||||
# "last_modified": "2016-05-18T22:42:14.066Z"
|
||||
@@ -125,6 +126,32 @@ class cef_json_builder:
|
||||
return version == 'master' or \
|
||||
bool(re.compile('^' + _chromium_version_regex + '$').match(version))
|
||||
|
||||
@staticmethod
|
||||
def is_valid_sandbox_compat(sandbox_compat):
|
||||
""" Returns true if the specified sandbox_compat hash is valid. """
|
||||
if sandbox_compat is None:
|
||||
return False
|
||||
# 16-character hex string
|
||||
return bool(re.compile('^[0-9a-f]{16}$').match(sandbox_compat))
|
||||
|
||||
@staticmethod
|
||||
def cef_version_to_api_version(cef_version):
|
||||
""" Convert CEF version to API version number.
|
||||
E.g., '138.0.1+g...' -> '13800', '138.1.0+g...' -> '13801'
|
||||
Returns None for old-style version numbers that predate API versioning.
|
||||
"""
|
||||
if '+' not in cef_version:
|
||||
# Old style version numbers don't have API versioning.
|
||||
return None
|
||||
|
||||
# New style: 138.0.1+g...
|
||||
version_part = cef_version.split('+')[0]
|
||||
parts = version_part.split('.')
|
||||
chrome_major = int(parts[0])
|
||||
cef_minor = int(parts[1])
|
||||
|
||||
return '%d%02d' % (chrome_major, cef_minor)
|
||||
|
||||
@staticmethod
|
||||
def get_file_name(version, platform, type, channel='stable'):
|
||||
""" Returns the expected distribution file name excluding extension based on
|
||||
@@ -139,6 +166,8 @@ class cef_json_builder:
|
||||
for platform in self.get_platforms():
|
||||
self._data[platform] = {'versions': []}
|
||||
self._versions = {}
|
||||
self._sandbox_compats = {}
|
||||
self._api_versions_cache = {}
|
||||
self._queryct = 0
|
||||
|
||||
def filter_files(self, files, file_type, sha1, name):
|
||||
@@ -246,6 +275,84 @@ class cef_json_builder:
|
||||
""" Return True if a matching Chromium version is known. """
|
||||
return cef_version in self._versions
|
||||
|
||||
def _query_api_versions_json(self, cef_version):
|
||||
""" Query cef_api_versions.json from GitHub for the given CEF version. """
|
||||
# Get Chromium version and extract branch (build number).
|
||||
chromium_version = self.get_chromium_version(cef_version)
|
||||
if not self.is_valid_chromium_version(chromium_version):
|
||||
return None
|
||||
|
||||
parts = chromium_version.split('.')
|
||||
branch = parts[2] # Chromium build number (e.g., 7204 from 138.0.7204.0)
|
||||
|
||||
# Check cache first.
|
||||
if branch in self._api_versions_cache:
|
||||
return self._api_versions_cache[branch]
|
||||
|
||||
query_url = 'https://raw.githubusercontent.com/chromiumembedded/cef/%s/cef_api_versions.json' % branch
|
||||
self._queryct = self._queryct + 1
|
||||
if not self._silent:
|
||||
print('Reading %s' % query_url)
|
||||
|
||||
try:
|
||||
handle = urlopen(query_url)
|
||||
json_data = json.loads(handle.read().decode('utf-8'))
|
||||
handle.close()
|
||||
self._api_versions_cache[branch] = json_data
|
||||
return json_data
|
||||
except Exception as e:
|
||||
if not self._silent:
|
||||
print('Failed to read cef_api_versions.json: %s' % e)
|
||||
return None
|
||||
|
||||
def _query_sandbox_compat(self, cef_version):
|
||||
""" Query sandbox_compat from cef_api_versions.json on GitHub. """
|
||||
target_version = self.cef_version_to_api_version(cef_version)
|
||||
if target_version is None:
|
||||
# Old-style version numbers don't have API versioning.
|
||||
return None
|
||||
|
||||
json_data = self._query_api_versions_json(cef_version)
|
||||
if json_data is None or 'hashes' not in json_data:
|
||||
return None
|
||||
|
||||
# Find exact match or closest lower version.
|
||||
available = sorted(json_data['hashes'].keys(), reverse=True)
|
||||
for version in available:
|
||||
if version <= target_version:
|
||||
return json_data['hashes'][version].get('sandbox_compat')
|
||||
|
||||
return None
|
||||
|
||||
def set_sandbox_compat(self, cef_version, sandbox_compat=None):
|
||||
""" Set the sandbox_compat hash for the given CEF version. If not provided
|
||||
or invalid, it will be queried remotely. """
|
||||
if not self.is_valid_version(cef_version):
|
||||
raise Exception('Invalid CEF version: %s' % cef_version)
|
||||
|
||||
if not self.is_valid_sandbox_compat(sandbox_compat):
|
||||
if cef_version in self._sandbox_compats:
|
||||
# Keep the sandbox_compat that we already know about.
|
||||
return self._sandbox_compats[cef_version]
|
||||
|
||||
sandbox_compat = self._query_sandbox_compat(cef_version)
|
||||
|
||||
if sandbox_compat is not None:
|
||||
self._sandbox_compats[cef_version] = sandbox_compat
|
||||
|
||||
return sandbox_compat
|
||||
|
||||
def get_sandbox_compat(self, cef_version):
|
||||
""" Return the sandbox_compat hash. If not currently known it will be
|
||||
queried remotely. May return None if not available. """
|
||||
if cef_version in self._sandbox_compats:
|
||||
return self._sandbox_compats[cef_version]
|
||||
return self.set_sandbox_compat(cef_version)
|
||||
|
||||
def has_sandbox_compat(self, cef_version):
|
||||
""" Return True if a sandbox_compat hash is known. """
|
||||
return cef_version in self._sandbox_compats
|
||||
|
||||
def load(self, json_string, fatalerrors=True):
|
||||
""" Load new JSON into this object. Any existing contents will be cleared.
|
||||
If |fatalerrors| is True then any errors while loading the JSON file
|
||||
@@ -311,7 +418,7 @@ class cef_json_builder:
|
||||
})
|
||||
|
||||
if len(valid_files) > 0:
|
||||
valid_versions.append({
|
||||
version_record = {
|
||||
'cef_version':
|
||||
version['cef_version'],
|
||||
'chromium_version':
|
||||
@@ -321,7 +428,13 @@ class cef_json_builder:
|
||||
version.get('channel', 'stable'),
|
||||
'files':
|
||||
self._sort_files(valid_files)
|
||||
})
|
||||
}
|
||||
# Include sandbox_compat if available.
|
||||
sandbox_compat = self.set_sandbox_compat(
|
||||
version['cef_version'], version.get('sandbox_compat'))
|
||||
if sandbox_compat is not None:
|
||||
version_record['sandbox_compat'] = sandbox_compat
|
||||
valid_versions.append(version_record)
|
||||
|
||||
if len(valid_versions) > 0:
|
||||
self._data[platform]['versions'] = valid_versions
|
||||
@@ -447,12 +560,17 @@ class cef_json_builder:
|
||||
if version_idx == -1:
|
||||
# Add a new version record.
|
||||
self._print('add_file: Add %s %s %s' % (platform, version, channel))
|
||||
self._data[platform]['versions'].append({
|
||||
version_record = {
|
||||
'cef_version': version,
|
||||
'chromium_version': self.get_chromium_version(version),
|
||||
'channel': channel,
|
||||
'files': []
|
||||
})
|
||||
}
|
||||
# Include sandbox_compat if available.
|
||||
sandbox_compat = self.get_sandbox_compat(version)
|
||||
if sandbox_compat is not None:
|
||||
version_record['sandbox_compat'] = sandbox_compat
|
||||
self._data[platform]['versions'].append(version_record)
|
||||
version_idx = len(self._data[platform]['versions']) - 1
|
||||
|
||||
files = self._data[platform]['versions'][version_idx]['files']
|
||||
@@ -498,6 +616,8 @@ class cef_json_builder:
|
||||
result_obj['cef_version'] = version_obj['cef_version']
|
||||
result_obj['chromium_version'] = version_obj['chromium_version']
|
||||
result_obj['channel'] = version_obj['channel']
|
||||
if 'sandbox_compat' in version_obj:
|
||||
result_obj['sandbox_compat'] = version_obj['sandbox_compat']
|
||||
results.append(result_obj)
|
||||
|
||||
return results
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
from __future__ import absolute_import
|
||||
from cef_json_builder import cef_json_builder
|
||||
import datetime
|
||||
import json
|
||||
import unittest
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
|
||||
class TestCefJSONBuilder(unittest.TestCase):
|
||||
@@ -100,6 +102,10 @@ class TestCefJSONBuilder(unittest.TestCase):
|
||||
chromium_version = '49.0.2705.50'
|
||||
self.assertEqual(chromium_version,
|
||||
builder.set_chromium_version(version, chromium_version))
|
||||
# For new-style versions, set a dummy sandbox_compat to avoid GitHub queries.
|
||||
# Old-style versions don't have sandbox_compat.
|
||||
if '+' in version:
|
||||
builder.set_sandbox_compat(version, 'abc123def4567890')
|
||||
self.assertEqual(0, builder.get_query_count())
|
||||
|
||||
result = builder.add_file(name, attribs[attrib_idx]['size'],
|
||||
@@ -109,7 +115,7 @@ class TestCefJSONBuilder(unittest.TestCase):
|
||||
self.assertEqual(not shouldfail, result)
|
||||
|
||||
# Return the result expected from get_files().
|
||||
return {
|
||||
expected = {
|
||||
'chromium_version': chromium_version,
|
||||
'sha1': attribs[attrib_idx]['sha1'],
|
||||
'name': name,
|
||||
@@ -120,6 +126,10 @@ class TestCefJSONBuilder(unittest.TestCase):
|
||||
'type': type,
|
||||
'size': attribs[attrib_idx]['size']
|
||||
}
|
||||
# Include sandbox_compat only for new-style versions.
|
||||
if '+' in version:
|
||||
expected['sandbox_compat'] = 'abc123def4567890'
|
||||
return expected
|
||||
|
||||
# Test with no file contents.
|
||||
def test_empty(self):
|
||||
@@ -457,6 +467,265 @@ class TestCefJSONBuilder(unittest.TestCase):
|
||||
files = builder.get_files()
|
||||
self.assertEqual(len(files), 2)
|
||||
|
||||
# Test sandbox_compat hash validation.
|
||||
def test_valid_sandbox_compat(self):
|
||||
# Valid 16-character hex string.
|
||||
self.assertTrue(
|
||||
cef_json_builder.is_valid_sandbox_compat('0123456789abcdef'))
|
||||
self.assertTrue(
|
||||
cef_json_builder.is_valid_sandbox_compat('abcdef0123456789'))
|
||||
|
||||
# Invalid values.
|
||||
self.assertFalse(cef_json_builder.is_valid_sandbox_compat(None))
|
||||
self.assertFalse(cef_json_builder.is_valid_sandbox_compat(''))
|
||||
self.assertFalse(cef_json_builder.is_valid_sandbox_compat('foobar'))
|
||||
# Too short.
|
||||
self.assertFalse(
|
||||
cef_json_builder.is_valid_sandbox_compat('0123456789abcde'))
|
||||
# Too long.
|
||||
self.assertFalse(
|
||||
cef_json_builder.is_valid_sandbox_compat('0123456789abcdef0'))
|
||||
# Invalid characters.
|
||||
self.assertFalse(
|
||||
cef_json_builder.is_valid_sandbox_compat('0123456789abcdeg'))
|
||||
# Uppercase not allowed.
|
||||
self.assertFalse(
|
||||
cef_json_builder.is_valid_sandbox_compat('0123456789ABCDEF'))
|
||||
|
||||
# Test CEF version to API version conversion.
|
||||
def test_cef_version_to_api_version(self):
|
||||
# New-style version numbers.
|
||||
self.assertEqual('13800',
|
||||
cef_json_builder.cef_version_to_api_version(
|
||||
'138.0.1+g62d140e+chromium-138.0.7204.0'))
|
||||
self.assertEqual('13801',
|
||||
cef_json_builder.cef_version_to_api_version(
|
||||
'138.1.0+g62d140e+chromium-138.0.7204.0'))
|
||||
self.assertEqual('13802',
|
||||
cef_json_builder.cef_version_to_api_version(
|
||||
'138.2.5+g62d140e+chromium-138.0.7204.0'))
|
||||
self.assertEqual('7401',
|
||||
cef_json_builder.cef_version_to_api_version(
|
||||
'74.1.0+g62d140e+chromium-74.0.3729.6'))
|
||||
self.assertEqual('10000',
|
||||
cef_json_builder.cef_version_to_api_version(
|
||||
'100.0.0+g62d140e+chromium-100.0.4896.0'))
|
||||
|
||||
# Old-style version numbers return None (no API versioning).
|
||||
self.assertIsNone(
|
||||
cef_json_builder.cef_version_to_api_version('3.2704.1414.g185cd6c'))
|
||||
self.assertIsNone(
|
||||
cef_json_builder.cef_version_to_api_version('3.2623.9999.gb90a3be'))
|
||||
|
||||
# Helper to create mock API versions JSON response.
|
||||
def _create_mock_api_versions_json(self, versions_with_sandbox):
|
||||
"""Create a mock cef_api_versions.json structure."""
|
||||
hashes = {}
|
||||
for version, sandbox_compat in versions_with_sandbox:
|
||||
hashes[version] = {
|
||||
'comment': 'Test version.',
|
||||
'linux': 'a' * 40,
|
||||
'mac': 'b' * 40,
|
||||
'windows': 'c' * 40,
|
||||
}
|
||||
if sandbox_compat:
|
||||
hashes[version]['sandbox_compat'] = sandbox_compat
|
||||
return {'hashes': hashes, 'min': min(versions_with_sandbox)[0]}
|
||||
|
||||
# Test sandbox_compat query with mocked GitHub response.
|
||||
@patch('cef_json_builder.urlopen')
|
||||
def test_sandbox_compat_query(self, mock_urlopen):
|
||||
builder = cef_json_builder(silent=True)
|
||||
|
||||
# Mock API versions JSON with sandbox_compat.
|
||||
mock_json = self._create_mock_api_versions_json([
|
||||
('13800', 'abc123def4567890'),
|
||||
('13801', 'def456abc7890123'),
|
||||
])
|
||||
mock_response = MagicMock()
|
||||
mock_response.read.return_value = json.dumps(mock_json).encode('utf-8')
|
||||
mock_urlopen.return_value = mock_response
|
||||
|
||||
cef_version = '138.0.1+g62d140e+chromium-138.0.7204.0'
|
||||
|
||||
# Test query.
|
||||
self.assertFalse(builder.has_sandbox_compat(cef_version))
|
||||
sandbox_compat = builder.get_sandbox_compat(cef_version)
|
||||
self.assertEqual('abc123def4567890', sandbox_compat)
|
||||
self.assertTrue(builder.has_sandbox_compat(cef_version))
|
||||
|
||||
# Verify URL was called with branch number from Chromium version.
|
||||
mock_urlopen.assert_called_once()
|
||||
call_url = mock_urlopen.call_args[0][0]
|
||||
self.assertIn('/7204/', call_url) # Branch from chromium-138.0.7204.0
|
||||
self.assertIn('cef_api_versions.json', call_url)
|
||||
|
||||
# Test sandbox_compat falls back to closest lower version.
|
||||
@patch('cef_json_builder.urlopen')
|
||||
def test_sandbox_compat_fallback(self, mock_urlopen):
|
||||
builder = cef_json_builder(silent=True)
|
||||
|
||||
# Only 13800 exists, not 13801.
|
||||
mock_json = self._create_mock_api_versions_json([
|
||||
('13800', 'abc123def4567890'),
|
||||
])
|
||||
mock_response = MagicMock()
|
||||
mock_response.read.return_value = json.dumps(mock_json).encode('utf-8')
|
||||
mock_urlopen.return_value = mock_response
|
||||
|
||||
# CEF version 138.1.x should fall back to 13800.
|
||||
cef_version = '138.1.0+g62d140e+chromium-138.0.7204.0'
|
||||
sandbox_compat = builder.get_sandbox_compat(cef_version)
|
||||
self.assertEqual('abc123def4567890', sandbox_compat)
|
||||
|
||||
# Test sandbox_compat returns None when not available.
|
||||
@patch('cef_json_builder.urlopen')
|
||||
def test_sandbox_compat_not_available(self, mock_urlopen):
|
||||
builder = cef_json_builder(silent=True)
|
||||
|
||||
# Version exists but has no sandbox_compat field.
|
||||
mock_json = self._create_mock_api_versions_json([
|
||||
('13800', None),
|
||||
])
|
||||
mock_response = MagicMock()
|
||||
mock_response.read.return_value = json.dumps(mock_json).encode('utf-8')
|
||||
mock_urlopen.return_value = mock_response
|
||||
|
||||
cef_version = '138.0.1+g62d140e+chromium-138.0.7204.0'
|
||||
sandbox_compat = builder.get_sandbox_compat(cef_version)
|
||||
self.assertIsNone(sandbox_compat)
|
||||
|
||||
# Test sandbox_compat handles query failure gracefully.
|
||||
@patch('cef_json_builder.urlopen')
|
||||
def test_sandbox_compat_query_failure(self, mock_urlopen):
|
||||
builder = cef_json_builder(silent=True)
|
||||
|
||||
# Simulate network error.
|
||||
mock_urlopen.side_effect = Exception('Network error')
|
||||
|
||||
cef_version = '138.0.1+g62d140e+chromium-138.0.7204.0'
|
||||
sandbox_compat = builder.get_sandbox_compat(cef_version)
|
||||
self.assertIsNone(sandbox_compat)
|
||||
|
||||
# Test sandbox_compat returns None when target version is older than all available.
|
||||
@patch('cef_json_builder.urlopen')
|
||||
def test_sandbox_compat_no_matching_version(self, mock_urlopen):
|
||||
builder = cef_json_builder(silent=True)
|
||||
|
||||
# Only newer versions available (13900, 14000), target is 13800.
|
||||
mock_json = self._create_mock_api_versions_json([
|
||||
('13900', 'abc123def4567890'),
|
||||
('14000', 'def456abc7890123'),
|
||||
])
|
||||
mock_response = MagicMock()
|
||||
mock_response.read.return_value = json.dumps(mock_json).encode('utf-8')
|
||||
mock_urlopen.return_value = mock_response
|
||||
|
||||
# CEF 138.0.x = API version 13800, which is older than available.
|
||||
cef_version = '138.0.1+g62d140e+chromium-138.0.7204.0'
|
||||
sandbox_compat = builder.get_sandbox_compat(cef_version)
|
||||
self.assertIsNone(sandbox_compat)
|
||||
|
||||
# Test sandbox_compat returns None when fallback version lacks the field.
|
||||
@patch('cef_json_builder.urlopen')
|
||||
def test_sandbox_compat_fallback_no_field(self, mock_urlopen):
|
||||
builder = cef_json_builder(silent=True)
|
||||
|
||||
# 13800 exists but has no sandbox_compat field.
|
||||
mock_json = self._create_mock_api_versions_json([
|
||||
('13800', None),
|
||||
])
|
||||
mock_response = MagicMock()
|
||||
mock_response.read.return_value = json.dumps(mock_json).encode('utf-8')
|
||||
mock_urlopen.return_value = mock_response
|
||||
|
||||
# CEF 138.1.x = API version 13801, falls back to 13800 which lacks field.
|
||||
cef_version = '138.1.0+g62d140e+chromium-138.0.7204.0'
|
||||
sandbox_compat = builder.get_sandbox_compat(cef_version)
|
||||
self.assertIsNone(sandbox_compat)
|
||||
|
||||
# Test sandbox_compat is included in version records.
|
||||
@patch('cef_json_builder.urlopen')
|
||||
def test_sandbox_compat_in_version_record(self, mock_urlopen):
|
||||
builder = cef_json_builder(silent=True)
|
||||
|
||||
# Mock API versions JSON.
|
||||
mock_json = self._create_mock_api_versions_json([
|
||||
('13800', 'abc123def4567890'),
|
||||
])
|
||||
mock_response = MagicMock()
|
||||
mock_response.read.return_value = json.dumps(mock_json).encode('utf-8')
|
||||
mock_urlopen.return_value = mock_response
|
||||
|
||||
cef_version = '138.0.1+g62d140e+chromium-138.0.7204.0'
|
||||
chromium_version = '138.0.7204.0'
|
||||
|
||||
# Pre-populate chromium version to avoid additional queries.
|
||||
builder.set_chromium_version(cef_version, chromium_version)
|
||||
|
||||
# Add a file.
|
||||
name = cef_json_builder.get_file_name(cef_version, 'linux64',
|
||||
'standard') + '.tar.gz'
|
||||
builder.add_file(name, 12345, '2026-02-10T12:00:00.000Z', 'a' * 40)
|
||||
|
||||
# Verify sandbox_compat is in the version record.
|
||||
versions = builder.get_versions('linux64')
|
||||
self.assertEqual(1, len(versions))
|
||||
self.assertEqual('abc123def4567890', versions[0].get('sandbox_compat'))
|
||||
|
||||
# Verify sandbox_compat is in get_files() result.
|
||||
files = builder.get_files()
|
||||
self.assertEqual(1, len(files))
|
||||
self.assertEqual('abc123def4567890', files[0].get('sandbox_compat'))
|
||||
|
||||
# Test sandbox_compat is preserved through load/save cycle.
|
||||
@patch('cef_json_builder.urlopen')
|
||||
def test_sandbox_compat_load_save(self, mock_urlopen):
|
||||
builder = cef_json_builder(silent=True)
|
||||
|
||||
# Mock API versions JSON.
|
||||
mock_json = self._create_mock_api_versions_json([
|
||||
('13800', 'abc123def4567890'),
|
||||
])
|
||||
mock_response = MagicMock()
|
||||
mock_response.read.return_value = json.dumps(mock_json).encode('utf-8')
|
||||
mock_urlopen.return_value = mock_response
|
||||
|
||||
cef_version = '138.0.1+g62d140e+chromium-138.0.7204.0'
|
||||
chromium_version = '138.0.7204.0'
|
||||
|
||||
builder.set_chromium_version(cef_version, chromium_version)
|
||||
|
||||
name = cef_json_builder.get_file_name(cef_version, 'linux64',
|
||||
'standard') + '.tar.gz'
|
||||
builder.add_file(name, 12345, '2026-02-10T12:00:00.000Z', 'a' * 40)
|
||||
|
||||
# Save to string.
|
||||
output = str(builder)
|
||||
self.assertIn('sandbox_compat', output)
|
||||
self.assertIn('abc123def4567890', output)
|
||||
|
||||
# Load into new builder.
|
||||
builder2 = cef_json_builder(silent=True)
|
||||
builder2.load(output)
|
||||
|
||||
# Verify sandbox_compat is preserved.
|
||||
versions = builder2.get_versions('linux64')
|
||||
self.assertEqual(1, len(versions))
|
||||
self.assertEqual('abc123def4567890', versions[0].get('sandbox_compat'))
|
||||
|
||||
# Test set_sandbox_compat with explicit value.
|
||||
def test_set_sandbox_compat_explicit(self):
|
||||
builder = cef_json_builder(silent=True)
|
||||
|
||||
cef_version = '138.0.1+g62d140e+chromium-138.0.7204.0'
|
||||
|
||||
# Set explicit value (no query needed).
|
||||
sandbox_compat = builder.set_sandbox_compat(cef_version, '1234567890abcdef')
|
||||
self.assertEqual('1234567890abcdef', sandbox_compat)
|
||||
self.assertTrue(builder.has_sandbox_compat(cef_version))
|
||||
self.assertEqual(0, builder.get_query_count())
|
||||
|
||||
|
||||
# Program entry point.
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -7,11 +7,12 @@ from cef_parser import get_copyright
|
||||
from cef_version import VersionFormatter
|
||||
from date_util import *
|
||||
from file_util import *
|
||||
from sandbox_compat_hash import calculate_sandbox_compat_hash
|
||||
import git_util as git
|
||||
import sys
|
||||
|
||||
|
||||
def make_version_header(header):
|
||||
def make_version_header(header, sandbox_files=None):
|
||||
result = get_copyright(full=True, translator=False) + \
|
||||
"""//
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -35,6 +36,8 @@ def make_version_header(header):
|
||||
#define CHROME_VERSION_BUILD $CHROME_BUILD$
|
||||
#define CHROME_VERSION_PATCH $CHROME_PATCH$
|
||||
|
||||
#define CEF_SANDBOX_COMPAT_HASH "$SANDBOX_COMPAT_HASH$"
|
||||
|
||||
#define DO_MAKE_STRING(p) #p
|
||||
#define MAKE_STRING(p) DO_MAKE_STRING(p)
|
||||
|
||||
@@ -60,19 +63,36 @@ def make_version_header(header):
|
||||
result = result.replace('$CHROME_%s$' % key,
|
||||
str(chrome_version_components[key]))
|
||||
|
||||
# Calculate sandbox compat hash (Windows only, empty on other platforms)
|
||||
if sandbox_files:
|
||||
sandbox_hash = calculate_sandbox_compat_hash(sandbox_files)
|
||||
else:
|
||||
sandbox_hash = ""
|
||||
result = result.replace('$SANDBOX_COMPAT_HASH$', sandbox_hash)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def write_version_header(output):
|
||||
result = make_version_header(output)
|
||||
def write_version_header(output, sandbox_files=None):
|
||||
result = make_version_header(output, sandbox_files)
|
||||
return write_file_if_changed(output, result)
|
||||
|
||||
|
||||
def main(argv):
|
||||
if len(argv) < 2:
|
||||
print(("Usage:\n %s <output_filename>" % argv[0]))
|
||||
print((
|
||||
"Usage:\n %s <output_filename> [--sandbox-files file1 ...]" % argv[0]))
|
||||
sys.exit(-1)
|
||||
write_version_header(argv[1])
|
||||
|
||||
output = argv[1]
|
||||
sandbox_files = []
|
||||
|
||||
# Check for --sandbox-files flag
|
||||
if '--sandbox-files' in argv:
|
||||
idx = argv.index('--sandbox-files')
|
||||
sandbox_files = argv[idx + 1:]
|
||||
|
||||
write_version_header(output, sandbox_files)
|
||||
|
||||
|
||||
if '__main__' == __name__:
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
# Copyright (c) 2026 The Chromium Embedded Framework Authors. All rights
|
||||
# reserved. Use of this source code is governed by a BSD-style license that
|
||||
# can be found in the LICENSE file.
|
||||
|
||||
from __future__ import absolute_import
|
||||
import hashlib
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def calculate_sandbox_compat_hash(file_paths, verbose=False):
|
||||
"""
|
||||
Calculate a compatibility hash from the contents of the given files.
|
||||
Returns a truncated SHA-256 hash (first 16 hex characters).
|
||||
All files must exist or an error is raised.
|
||||
"""
|
||||
hasher = hashlib.sha256()
|
||||
|
||||
for file_path in sorted(file_paths): # Sort for deterministic order
|
||||
if not os.path.exists(file_path):
|
||||
raise FileNotFoundError(f"Required file not found: {file_path}")
|
||||
|
||||
with open(file_path, 'r', encoding='utf-8', errors='replace') as f:
|
||||
content = f.read()
|
||||
# Normalize line endings for cross-platform consistency
|
||||
content = content.replace('\r\n', '\n')
|
||||
hasher.update(content.encode('utf-8'))
|
||||
if verbose:
|
||||
print(f"Hashed: {file_path} ({len(content)} bytes)")
|
||||
|
||||
return hasher.hexdigest()[:16]
|
||||
|
||||
|
||||
def main(argv):
|
||||
if len(argv) < 2:
|
||||
print(f"Usage: {argv[0]} <file1> [file2] ...")
|
||||
sys.exit(1)
|
||||
|
||||
hash_value = calculate_sandbox_compat_hash(argv[1:], verbose=True)
|
||||
print(f"Sandbox compatibility hash: {hash_value}")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv)
|
||||
+61
-15
@@ -12,9 +12,19 @@ from file_util import read_file, read_json_file, write_file, write_json_file
|
||||
from git_util import exec_git_cmd
|
||||
import os
|
||||
import sys
|
||||
from sandbox_compat_hash import calculate_sandbox_compat_hash
|
||||
from translator import translate
|
||||
from version_util import *
|
||||
|
||||
# Sandbox interface files for compatibility hash (paths relative to src/).
|
||||
# Keep in sync with _sandbox_compat_files in cef/BUILD.gn.
|
||||
SANDBOX_COMPAT_FILES = [
|
||||
'chrome/chrome_elf/chrome_elf_main.h',
|
||||
'sandbox/policy/mojom/sandbox.mojom',
|
||||
'sandbox/win/src/sandbox.h',
|
||||
'sandbox/win/src/sandbox_types.h',
|
||||
]
|
||||
|
||||
|
||||
def get_next_api_revision(api_versions_file, major_version):
|
||||
""" Returns the next available API revision for |major_version|.
|
||||
@@ -44,7 +54,8 @@ def get_next_api_revision(api_versions_file, major_version):
|
||||
|
||||
def compute_api_hashes(api_version: str,
|
||||
hasher: CefApiHasher,
|
||||
next_allowed: bool) -> Dict[str, str]:
|
||||
next_allowed: bool,
|
||||
src_dir: str) -> Dict[str, str]:
|
||||
""" Computes API hashes for the specified |api_version|. """
|
||||
if not next_allowed:
|
||||
# Next usage is banned with explicit API versions.
|
||||
@@ -58,6 +69,10 @@ def compute_api_hashes(api_version: str,
|
||||
|
||||
hashes = hasher.calculate(api_version, added_defines)
|
||||
if hashes:
|
||||
# Add sandbox compatibility hash.
|
||||
sandbox_files = [os.path.join(src_dir, f) for f in SANDBOX_COMPAT_FILES]
|
||||
hashes['sandbox_compat'] = calculate_sandbox_compat_hash(sandbox_files)
|
||||
|
||||
if api_version in UNTRACKED_VERSIONS:
|
||||
label = version_label(api_version)
|
||||
label = label[0:1].upper() + label[1:]
|
||||
@@ -67,9 +82,24 @@ def compute_api_hashes(api_version: str,
|
||||
return hashes
|
||||
|
||||
|
||||
def same_api_hashes(hashes1, hashes2):
|
||||
return all(hashes1[key] == hashes2[key]
|
||||
for key in ['linux', 'mac', 'windows'])
|
||||
def same_api_hashes(hashes1, hashes2, compare_sandbox=True):
|
||||
# Compare platform hashes (always required).
|
||||
for key in ['linux', 'mac', 'windows']:
|
||||
if hashes1.get(key) != hashes2.get(key):
|
||||
return False
|
||||
# Compare sandbox_compat only when requested.
|
||||
if compare_sandbox:
|
||||
has1 = 'sandbox_compat' in hashes1
|
||||
has2 = 'sandbox_compat' in hashes2
|
||||
if has1 and has2:
|
||||
# Both have the field - compare values.
|
||||
if hashes1['sandbox_compat'] != hashes2['sandbox_compat']:
|
||||
return False
|
||||
elif has1 or has2:
|
||||
# One has the field and the other doesn't - not the same.
|
||||
# This ensures the field gets added to entries that lack it.
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def compute_next_api_version(api_versions_file):
|
||||
@@ -200,7 +230,8 @@ def exec_apply(api_versions_file,
|
||||
api_untracked_file,
|
||||
next_version,
|
||||
apply_next,
|
||||
hasher: CefApiHasher) -> int:
|
||||
hasher: CefApiHasher,
|
||||
src_dir: str) -> int:
|
||||
""" Updates untracked API hashes if necessary.
|
||||
Saves the hash for the next API version if |apply_next| is true.
|
||||
"""
|
||||
@@ -214,13 +245,14 @@ def exec_apply(api_versions_file,
|
||||
untracked_changed = False
|
||||
for version in UNTRACKED_VERSIONS:
|
||||
label = version_label(version)
|
||||
hashes = compute_api_hashes(version, hasher, next_allowed=True)
|
||||
hashes = compute_api_hashes(
|
||||
version, hasher, next_allowed=True, src_dir=src_dir)
|
||||
if not hashes:
|
||||
sys.stderr.write('ERROR: Failed to process %s\n' % label)
|
||||
return 1
|
||||
|
||||
if version in json_untracked['hashes'] and same_api_hashes(
|
||||
hashes, json_untracked['hashes'][version]):
|
||||
hashes, json_untracked['hashes'][version], compare_sandbox=True):
|
||||
print('Hashes for %s are unchanged.' % label)
|
||||
else:
|
||||
untracked_changed = True
|
||||
@@ -231,14 +263,20 @@ def exec_apply(api_versions_file,
|
||||
if apply_next:
|
||||
next_label = version_label(next_version)
|
||||
|
||||
hashes = compute_api_hashes(next_version, hasher, next_allowed=False)
|
||||
hashes = compute_api_hashes(
|
||||
next_version, hasher, next_allowed=False, src_dir=src_dir)
|
||||
if not hashes:
|
||||
sys.stderr.write('ERROR: Failed to process %s\n' % next_label)
|
||||
return 1
|
||||
|
||||
last_version = json_versions.get('last', None)
|
||||
if not last_version is None and last_version in json_versions['hashes']:
|
||||
if same_api_hashes(hashes, json_versions['hashes'][last_version]):
|
||||
# Compare sandbox_compat_hash if both have it. For older versions that
|
||||
# don't have the field, the comparison is skipped (handled by
|
||||
# same_api_hashes). Once last_version has the field, sandbox changes
|
||||
# will trigger new version bumps.
|
||||
if same_api_hashes(
|
||||
hashes, json_versions['hashes'][last_version], compare_sandbox=True):
|
||||
print('Hashes for last %s are unchanged.' % version_label(last_version))
|
||||
next_changed = False
|
||||
|
||||
@@ -248,7 +286,8 @@ def exec_apply(api_versions_file,
|
||||
json_versions['hashes'][next_version] = hashes
|
||||
|
||||
if NEXT_VERSION in json_untracked['hashes'] and not \
|
||||
same_api_hashes(hashes, json_untracked['hashes'][NEXT_VERSION]):
|
||||
same_api_hashes(hashes, json_untracked['hashes'][NEXT_VERSION],
|
||||
compare_sandbox=True):
|
||||
print('NOTE: Additional versions are available to generate.')
|
||||
|
||||
write_versions = next_changed or not os.path.isfile(api_versions_file)
|
||||
@@ -273,7 +312,8 @@ def exec_check(api_versions_file,
|
||||
fast_check,
|
||||
force_update,
|
||||
skip_untracked,
|
||||
hasher: CefApiHasher) -> int:
|
||||
hasher: CefApiHasher,
|
||||
src_dir: str) -> int:
|
||||
""" Checks existing API version hashes.
|
||||
Resaves all API hashes if |force_update| is true. Otherwise, hash
|
||||
changes are considered an error.
|
||||
@@ -325,11 +365,16 @@ def exec_check(api_versions_file,
|
||||
else:
|
||||
stored_hashes = json_versions['hashes'][version]
|
||||
label = version_label(version)
|
||||
computed_hashes = compute_api_hashes(version, hasher, next_allowed=True)
|
||||
computed_hashes = compute_api_hashes(
|
||||
version, hasher, next_allowed=True, src_dir=src_dir)
|
||||
if not bool(computed_hashes):
|
||||
sys.stderr.write('ERROR: Failed to process %s\n' % label)
|
||||
return 1
|
||||
if not same_api_hashes(computed_hashes, stored_hashes):
|
||||
# Only compare sandbox_compat_hash for untracked versions since we can
|
||||
# only compute the hash for the current file state, not for historical
|
||||
# versions.
|
||||
if not same_api_hashes(
|
||||
computed_hashes, stored_hashes, compare_sandbox=untracked):
|
||||
if force_update:
|
||||
print('Updating hashes for %s' % label)
|
||||
if untracked:
|
||||
@@ -477,6 +522,7 @@ https://chromiumembedded.github.io/cef/api_versioning
|
||||
|
||||
script_dir = os.path.dirname(__file__)
|
||||
cef_dir = os.path.abspath(os.path.join(script_dir, os.pardir))
|
||||
src_dir = os.path.abspath(os.path.join(cef_dir, os.pardir))
|
||||
|
||||
cpp_header_dir = os.path.join(cef_dir, 'include')
|
||||
if not os.path.isdir(cpp_header_dir):
|
||||
@@ -526,7 +572,7 @@ https://chromiumembedded.github.io/cef/api_versioning
|
||||
api_untracked_file):
|
||||
skip_untracked = True
|
||||
if exec_apply(api_versions_file, api_untracked_file, next_version,
|
||||
options.apply, hasher) > 0:
|
||||
options.apply, hasher, src_dir) > 0:
|
||||
# Apply failed.
|
||||
sys.exit(1)
|
||||
elif not options.check:
|
||||
@@ -536,4 +582,4 @@ https://chromiumembedded.github.io/cef/api_versioning
|
||||
sys.exit(
|
||||
exec_check(api_versions_file, api_untracked_file, options.fastcheck and
|
||||
not options.force_update, options.check and
|
||||
options.force_update, skip_untracked, hasher))
|
||||
options.force_update, skip_untracked, hasher, src_dir))
|
||||
Reference in new issue
Block a user