Merge branch 'main' into main

This commit is contained in:
daijro 2025-03-03 03:58:36 -06:00 committed by GitHub
commit 46f35637f3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 114 additions and 123 deletions

View file

@ -12,7 +12,7 @@ RUN apt-get update && apt-get install -y \
# Python # Python
python3 python3-dev python3-pip \ python3 python3-dev python3-pip \
# Camoufox build system tools # Camoufox build system tools
git p7zip-full golang-go aria2 curl \ git p7zip-full golang-go aria2 curl rsync \
# CA certificates # CA certificates
ca-certificates \ ca-certificates \
&& update-ca-certificates && update-ca-certificates
@ -23,10 +23,10 @@ ENV PATH="/root/.cargo/bin:${PATH}"
# Fetch Firefox & apply initial patches # Fetch Firefox & apply initial patches
RUN make setup-minimal && \ RUN make setup-minimal && \
make mozbootstrap && \ make mozbootstrap && \
mkdir /app/dist mkdir -p /app/dist
# Mount .mozbuild directory and dist folder # Mount .mozbuild directory and dist folder
VOLUME /root/.mozbuild VOLUME /root/.mozbuild
VOLUME /app/dist VOLUME /app/dist
ENTRYPOINT ["python3", "./multibuild.py"] ENTRYPOINT ["python3", "./multibuild.py"]

View file

@ -13,6 +13,7 @@ Written by daijro.
#include "mozilla/glue/Debug.h" #include "mozilla/glue/Debug.h"
#include <cstdlib> #include <cstdlib>
#include <cstdio> #include <cstdio>
#include <mutex>
#include <variant> #include <variant>
#include <cstddef> #include <cstddef>
#include <vector> #include <vector>
@ -27,185 +28,174 @@ namespace MaskConfig {
// Function to get the value of an environment variable as a UTF-8 string. // Function to get the value of an environment variable as a UTF-8 string.
inline std::optional<std::string> get_env_utf8(const std::string& name) { inline std::optional<std::string> get_env_utf8(const std::string& name) {
#ifdef _WIN32 #ifdef _WIN32
std::wstring wName(name.begin(), name.end()); std::wstring wName(name.begin(), name.end());
DWORD size = GetEnvironmentVariableW(wName.c_str(), nullptr, 0); DWORD size = GetEnvironmentVariableW(wName.c_str(), nullptr, 0);
if (size == 0) return std::nullopt; // Environment variable not found if (size == 0) return std::nullopt; // Environment variable not found
std::vector<wchar_t> buffer(size); std::vector<wchar_t> buffer(size);
GetEnvironmentVariableW(wName.c_str(), buffer.data(), size); GetEnvironmentVariableW(wName.c_str(), buffer.data(), size);
std::wstring wValue(buffer.data()); std::wstring wValue(buffer.data());
// Convert UTF-16 to UTF-8 // Convert UTF-16 to UTF-8
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
return converter.to_bytes(wValue); return converter.to_bytes(wValue);
#else #else
const char* value = std::getenv(name.c_str()); const char* value = std::getenv(name.c_str());
if (!value) return std::nullopt; if (!value) return std::nullopt;
return std::string(value); return std::string(value);
#endif #endif
} }
// Helper function to load and parse configuration from environment variables. inline const nlohmann::json& GetJson() {
namespace { static std::once_flag initFlag;
nlohmann::json loadConfig() { static nlohmann::json jsonConfig;
std::call_once(initFlag, []() {
std::string jsonString; std::string jsonString;
int index = 1; int index = 1;
// Read environment variables CAMOU_CONFIG_1, CAMOU_CONFIG_2, ...
while (true) { while (true) {
std::string envName = "CAMOU_CONFIG_" + std::to_string(index); std::string envName = "CAMOU_CONFIG_" + std::to_string(index);
auto partialConfig = get_env_utf8(envName); auto partialConfig = get_env_utf8(envName);
if (!partialConfig) if (!partialConfig) break;
break;
jsonString += *partialConfig; jsonString += *partialConfig;
index++; index++;
} }
// If the concatenated string is empty, try reading the original CAMOU_CONFIG variable.
if (jsonString.empty()) { if (jsonString.empty()) {
auto originalConfig = get_env_utf8("CAMOU_CONFIG"); // Check for the original CAMOU_CONFIG as fallback
if (originalConfig) auto originalConfig = get_env_utf8("CAMOU_CONFIG");
jsonString = *originalConfig; if (originalConfig) jsonString = *originalConfig;
} }
// If no configuration is provided, return an empty JSON.
if (jsonString.empty()) { if (jsonString.empty()) {
return nlohmann::json{}; jsonConfig = nlohmann::json{};
return;
} }
// Validate JSON correctness. // Validate
if (!nlohmann::json::accept(jsonString)) { if (!nlohmann::json::accept(jsonString)) {
printf_stderr("ERROR: Invalid JSON passed to CAMOU_CONFIG!\n"); printf_stderr("ERROR: Invalid JSON passed to CAMOU_CONFIG!\n");
return nlohmann::json{}; jsonConfig = nlohmann::json{};
return;
} }
return nlohmann::json::parse(jsonString); jsonConfig = nlohmann::json::parse(jsonString);
} });
} // namespace
// Global configuration cache, initialized only once. return jsonConfig;
static const nlohmann::json g_jsonConfig = loadConfig();
// Function returns a reference to the already parsed JSON.
inline const nlohmann::json& GetJson() {
return g_jsonConfig;
} }
inline bool HasKey(const std::string& key, const nlohmann::json& data) { inline bool HasKey(const std::string& key, const nlohmann::json& data) {
return data.contains(key); return data.contains(key);
} }
inline std::optional<std::string> GetString(const std::string& key) { inline std::optional<std::string> GetString(const std::string& key) {
const auto& data = GetJson(); const auto& data = GetJson();
if (!HasKey(key, data)) return std::nullopt; if (!HasKey(key, data)) return std::nullopt;
return data[key].get<std::string>(); return data[key].get<std::string>();
} }
inline std::vector<std::string> GetStringList(const std::string& key) { inline std::vector<std::string> GetStringList(const std::string& key) {
std::vector<std::string> result; std::vector<std::string> result;
const auto& data = GetJson(); const auto& data = GetJson();
if (!HasKey(key, data)) return {}; if (!HasKey(key, data)) return {};
for (const auto& item : data[key]) { for (const auto& item : data[key]) {
result.push_back(item.get<std::string>()); result.push_back(item.get<std::string>());
} }
return result; return result;
} }
inline std::vector<std::string> GetStringListLower(const std::string& key) { inline std::vector<std::string> GetStringListLower(const std::string& key) {
std::vector<std::string> result = GetStringList(key); std::vector<std::string> result = GetStringList(key);
for (auto& str : result) { for (auto& str : result) {
std::transform(str.begin(), str.end(), str.begin(), std::transform(str.begin(), str.end(), str.begin(),
[](unsigned char c) { return std::tolower(c); }); [](unsigned char c) { return std::tolower(c); });
} }
return result; return result;
} }
template <typename T> template <typename T>
inline std::optional<T> GetUintImpl(const std::string& key) { inline std::optional<T> GetUintImpl(const std::string& key) {
const auto& data = GetJson(); const auto& data = GetJson();
if (!HasKey(key, data)) return std::nullopt; if (!HasKey(key, data)) return std::nullopt;
if (data[key].is_number_unsigned()) if (data[key].is_number_unsigned()) return data[key].get<T>();
return data[key].get<T>(); printf_stderr("ERROR: Value for key '%s' is not an unsigned integer\n",
printf_stderr("ERROR: Value for key '%s' is not an unsigned integer\n", key.c_str()); key.c_str());
return std::nullopt; return std::nullopt;
} }
inline std::optional<uint64_t> GetUint64(const std::string& key) { inline std::optional<uint64_t> GetUint64(const std::string& key) {
return GetUintImpl<uint64_t>(key); return GetUintImpl<uint64_t>(key);
} }
inline std::optional<uint32_t> GetUint32(const std::string& key) { inline std::optional<uint32_t> GetUint32(const std::string& key) {
return GetUintImpl<uint32_t>(key); return GetUintImpl<uint32_t>(key);
} }
inline std::optional<int32_t> GetInt32(const std::string& key) { inline std::optional<int32_t> GetInt32(const std::string& key) {
const auto& data = GetJson(); const auto& data = GetJson();
if (!HasKey(key, data)) return std::nullopt; if (!HasKey(key, data)) return std::nullopt;
if (data[key].is_number_integer()) if (data[key].is_number_integer()) return data[key].get<int32_t>();
return data[key].get<int32_t>(); printf_stderr("ERROR: Value for key '%s' is not an integer\n", key.c_str());
printf_stderr("ERROR: Value for key '%s' is not an integer\n", key.c_str()); return std::nullopt;
return std::nullopt;
} }
inline std::optional<double> GetDouble(const std::string& key) { inline std::optional<double> GetDouble(const std::string& key) {
const auto& data = GetJson(); const auto& data = GetJson();
if (!HasKey(key, data)) return std::nullopt; if (!HasKey(key, data)) return std::nullopt;
if (data[key].is_number_float()) if (data[key].is_number_float()) return data[key].get<double>();
return data[key].get<double>(); if (data[key].is_number_unsigned() || data[key].is_number_integer())
if (data[key].is_number_unsigned() || data[key].is_number_integer()) return static_cast<double>(data[key].get<int64_t>());
return static_cast<double>(data[key].get<int64_t>()); printf_stderr("ERROR: Value for key '%s' is not a double\n", key.c_str());
printf_stderr("ERROR: Value for key '%s' is not a double\n", key.c_str()); return std::nullopt;
return std::nullopt;
} }
inline std::optional<bool> GetBool(const std::string& key) { inline std::optional<bool> GetBool(const std::string& key) {
const auto& data = GetJson(); const auto& data = GetJson();
if (!HasKey(key, data)) return std::nullopt; if (!HasKey(key, data)) return std::nullopt;
if (data[key].is_boolean()) return data[key].get<bool>(); if (data[key].is_boolean()) return data[key].get<bool>();
printf_stderr("ERROR: Value for key '%s' is not a boolean\n", key.c_str()); printf_stderr("ERROR: Value for key '%s' is not a boolean\n", key.c_str());
return std::nullopt; return std::nullopt;
} }
inline bool CheckBool(const std::string& key) { inline bool CheckBool(const std::string& key) {
return GetBool(key).value_or(false); return GetBool(key).value_or(false);
} }
inline std::optional<std::array<uint32_t, 4>> GetRect(const std::string& left, inline std::optional<std::array<uint32_t, 4>> GetRect(
const std::string& top, const std::string& left, const std::string& top, const std::string& width,
const std::string& width, const std::string& height) {
const std::string& height) { std::array<std::optional<uint32_t>, 4> values = {
std::array<std::optional<uint32_t>, 4> values = { GetUint32(left).value_or(0), GetUint32(top).value_or(0), GetUint32(width),
GetUint32(left).value_or(0), GetUint32(height)};
GetUint32(top).value_or(0),
GetUint32(width),
GetUint32(height)
};
if (!values[2].has_value() || !values[3].has_value()) { if (!values[2].has_value() || !values[3].has_value()) {
if (values[2].has_value() ^ values[3].has_value()) if (values[2].has_value() ^ values[3].has_value())
printf_stderr("Both %s and %s must be provided. Using default behavior.\n", printf_stderr(
height.c_str(), width.c_str()); "Both %s and %s must be provided. Using default behavior.\n",
return std::nullopt; height.c_str(), width.c_str());
}
std::array<uint32_t, 4> result;
std::transform(values.begin(), values.end(), result.begin(),
[](const auto& value) { return value.value(); });
return result;
}
inline std::optional<std::array<int32_t, 4>> GetInt32Rect(const std::string& left,
const std::string& top,
const std::string& width,
const std::string& height) {
if (auto optValue = GetRect(left, top, width, height)) {
std::array<int32_t, 4> result;
std::transform(optValue->begin(), optValue->end(), result.begin(),
[](const auto& val) { return static_cast<int32_t>(val); });
return result;
}
return std::nullopt; return std::nullopt;
}
std::array<uint32_t, 4> result;
std::transform(values.begin(), values.end(), result.begin(),
[](const auto& value) { return value.value(); });
return result;
}
inline std::optional<std::array<int32_t, 4>> GetInt32Rect(
const std::string& left, const std::string& top, const std::string& width,
const std::string& height) {
if (auto optValue = GetRect(left, top, width, height)) {
std::array<int32_t, 4> result;
std::transform(optValue->begin(), optValue->end(), result.begin(),
[](const auto& val) { return static_cast<int32_t>(val); });
return result;
}
return std::nullopt;
} }
// Helpers for WebGL // Helpers for WebGL

View file

@ -22,6 +22,7 @@ import os
import sys import sys
from dataclasses import dataclass from dataclasses import dataclass
from typing import List from typing import List
import shutil
# Constants # Constants
AVAILABLE_TARGETS = ["linux", "windows", "macos"] AVAILABLE_TARGETS = ["linux", "windows", "macos"]
@ -86,7 +87,7 @@ def run_build(target, arch):
# Move assets to dist # Move assets to dist
print('Assets:', ', '.join(builder.assets)) print('Assets:', ', '.join(builder.assets))
for asset in builder.assets: for asset in builder.assets:
os.rename(asset, f'dist/{asset}') shutil.move(asset, f'dist/{asset}')
def main(): def main():