From: uazo Date: Wed, 29 Jan 2025 12:50:13 +0000 Subject: Enable component updater Activates component updaters in one-shot mode: downloading occurs only once and updates are inhibited. Only cromite-specific components can be enabled. License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- .../browser/aw_browser_main_parts.cc | 7 +++ .../component_updater/registration.cc | 12 +++-- .../nonembedded/webview_apk_application.cc | 2 +- .../nonembedded/webview_apk_process.cc | 20 +++++--- .../nonembedded/webview_apk_process.h | 4 +- .../browser/component_updater/registration.cc | 2 + .../elevated_recovery_impl.cc | 2 +- .../component_updater/component_installer.cc | 46 +++++++++++-------- .../component_updater/component_installer.h | 4 +- .../component_updater_url_constants.cc | 4 +- .../component_updater/configurator_impl.cc | 8 +--- .../component_updater/configurator_impl.h | 2 - components/crx_file/crx_build_action_main.cc | 10 +++- components/crx_file/crx_verifier.cc | 29 ++++++++++-- components/crx_file/crx_verifier.h | 2 +- .../prediction_model_download_manager.cc | 2 +- components/update_client/component.cc | 13 ++++++ components/update_client/crx_downloader.cc | 5 ++ components/update_client/net/network_impl.cc | 2 + components/update_client/op_install.cc | 2 +- components/update_client/protocol_parser.cc | 2 + .../update_client/protocol_parser_json.cc | 2 + components/update_client/request_sender.cc | 3 +- components/update_client/unpacker.cc | 7 +-- components/update_client/unpacker.h | 4 +- components/update_client/update_checker.cc | 6 ++- components/update_client/update_engine.cc | 9 ++++ components/update_client/utils.cc | 4 ++ extensions/browser/sandboxed_unpacker.cc | 2 +- 29 files changed, 155 insertions(+), 62 deletions(-) diff --git a/android_webview/browser/aw_browser_main_parts.cc b/android_webview/browser/aw_browser_main_parts.cc --- a/android_webview/browser/aw_browser_main_parts.cc +++ b/android_webview/browser/aw_browser_main_parts.cc @@ -73,6 +73,9 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/gl/gl_surface.h" +#include "android_webview/nonembedded/webview_apk_process.h" +#include "android_webview/nonembedded/component_updater/aw_component_update_service.h" + // Must come after all headers that specialize FromJniType() / ToJniType(). #include "android_webview/browser_jni_headers/AwBrowserMainParts_jni.h" #include "android_webview/browser_jni_headers/AwInterfaceRegistrar_jni.h" @@ -486,6 +489,10 @@ int AwBrowserMainParts::PreMainMessageLoopRun() { Java_AwInterfaceRegistrar_registerMojoInterfaces( base::android::AttachCurrentThread()); + WebViewApkProcess::Init(/*embedded*/ true); + AwComponentUpdateService::GetInstance()->StartComponentUpdateService( + base::DoNothing(), false); + return content::RESULT_CODE_NORMAL_EXIT; } diff --git a/android_webview/nonembedded/component_updater/registration.cc b/android_webview/nonembedded/component_updater/registration.cc --- a/android_webview/nonembedded/component_updater/registration.cc +++ b/android_webview/nonembedded/component_updater/registration.cc @@ -33,19 +33,25 @@ void RegisterComponentsForUpdate( std::vector> component_installer_list; + std::vector> + component_installer_list_cromite; + component_installer_list.push_back( std::make_unique< component_updater::OriginTrialsComponentInstallerPolicy>()); base::RepeatingClosure barrier_closure = base::BarrierClosure( - component_installer_list.size(), std::move(on_finished)); - for (auto& component : component_installer_list) { + component_installer_list_cromite.size(), std::move(on_finished)); + for (auto& component : component_installer_list_cromite) { base::MakeRefCounted( std::make_unique(std::move(component))) ->Register(base::OnceCallback( register_callback), - base::OnceClosure(barrier_closure)); + base::OnceClosure(barrier_closure), + /* registered_version */ base::Version(component_updater::kNullVersion), + /* max_previous_product_version */ base::Version(component_updater::kNullVersion), + /* allowed */ true); } } diff --git a/android_webview/nonembedded/webview_apk_application.cc b/android_webview/nonembedded/webview_apk_application.cc --- a/android_webview/nonembedded/webview_apk_application.cc +++ b/android_webview/nonembedded/webview_apk_application.cc @@ -15,7 +15,7 @@ namespace android_webview { static void JNI_WebViewApkApplication_InitializeGlobalsAndResources( JNIEnv* env) { InitIcuAndResourceBundleBrowserSide(); - WebViewApkProcess::Init(); + WebViewApkProcess::Init(/*embedded*/ false); } } // namespace android_webview diff --git a/android_webview/nonembedded/webview_apk_process.cc b/android_webview/nonembedded/webview_apk_process.cc --- a/android_webview/nonembedded/webview_apk_process.cc +++ b/android_webview/nonembedded/webview_apk_process.cc @@ -36,30 +36,36 @@ WebViewApkProcess* WebViewApkProcess::GetInstance() { // static // Must be called exactly once during the process startup. -void WebViewApkProcess::Init() { +void WebViewApkProcess::Init(bool embedded) { // TODO(crbug.com/40749658): Add check to assert this is only loaded by // LibraryProcessType PROCESS_WEBVIEW_NONEMBEDDED. // This doesn't have to be thread safe, because it should only happen once on // the main thread before any GetInstances calls are made. DCHECK(!g_webview_apk_process); - g_webview_apk_process = new WebViewApkProcess(); + g_webview_apk_process = new WebViewApkProcess(embedded); } -WebViewApkProcess::WebViewApkProcess() { - base::ThreadPoolInstance::CreateAndStartWithDefaultParams( +WebViewApkProcess::WebViewApkProcess(bool embedded) { + if (!embedded) { + base::ThreadPoolInstance::CreateAndStartWithDefaultParams( "WebViewApkProcess"); + } // There's no UI message pump in nonembedded WebView, using // `base::MessagePumpType::JAVA` so that the `SingleThreadExecutor` will bind // to the java thread the `WebViewApkProcess` is created on. - main_task_executor_ = std::make_unique( - base::MessagePumpType::JAVA); + if (!embedded) { + main_task_executor_ = std::make_unique( + base::MessagePumpType::JAVA); + } // WebView is not compatible with new compression protocols. base::CommandLine::ForCurrentProcess()->AppendSwitch( update_client::switches::kComponentUpdaterCompatProtocols); - RegisterPathProvider(); + if (!embedded) { + RegisterPathProvider(); + } component_updater::RegisterPathProvider( /*components_system_root_key=*/android_webview::DIR_COMPONENTS_ROOT, /*components_system_root_key_alt=*/android_webview::DIR_COMPONENTS_ROOT, diff --git a/android_webview/nonembedded/webview_apk_process.h b/android_webview/nonembedded/webview_apk_process.h --- a/android_webview/nonembedded/webview_apk_process.h +++ b/android_webview/nonembedded/webview_apk_process.h @@ -17,13 +17,13 @@ namespace android_webview { // Class that holds global state in the webview apk process. class WebViewApkProcess { public: - static void Init(); + static void Init(bool embedded); static WebViewApkProcess* GetInstance(); PrefService* GetPrefService() const; private: - WebViewApkProcess(); + WebViewApkProcess(bool embedded); ~WebViewApkProcess(); void CreatePrefService(); diff --git a/chrome/browser/component_updater/registration.cc b/chrome/browser/component_updater/registration.cc --- a/chrome/browser/component_updater/registration.cc +++ b/chrome/browser/component_updater/registration.cc @@ -136,6 +136,8 @@ void DeleteOldComponents(const base::FilePath& user_data_dir) { void RegisterComponentsForUpdate() { auto* const cus = g_browser_process->component_updater(); + if ((true)) return; + #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) RegisterRecoveryImprovedComponent(cus, g_browser_process->local_state()); #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) diff --git a/chrome/elevation_service/elevated_recovery_impl.cc b/chrome/elevation_service/elevated_recovery_impl.cc --- a/chrome/elevation_service/elevated_recovery_impl.cc +++ b/chrome/elevation_service/elevated_recovery_impl.cc @@ -183,7 +183,7 @@ HRESULT ValidateAndUnpackCRX(const base::FilePath& from_crx_path, std::string public_key; if (crx_file::Verify(to_crx_path, crx_format, {crx_hash}, {}, &public_key, - nullptr, /*compressed_verified_contents=*/nullptr) != + nullptr, /*compressed_verified_contents=*/nullptr, /* is_extension */ false) != crx_file::VerifierResult::OK_FULL) { return CRYPT_E_NO_MATCH; } diff --git a/components/component_updater/component_installer.cc b/components/component_updater/component_installer.cc --- a/components/component_updater/component_installer.cc +++ b/components/component_updater/component_installer.cc @@ -105,7 +105,9 @@ ComponentInstaller::ComponentInstaller( ComponentInstaller::~ComponentInstaller() = default; void ComponentInstaller::Register(ComponentUpdateService* cus, - base::OnceClosure callback) { + base::OnceClosure callback, + bool allowed) { + if (!allowed) return; DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); CHECK(cus); @@ -115,14 +117,16 @@ void ComponentInstaller::Register(ComponentUpdateService* cus, Register(base::BindOnce(&ComponentUpdateService::RegisterComponent, base::Unretained(cus)), std::move(callback), cus->GetRegisteredVersion(crx_id), - cus->GetMaxPreviousProductVersion(crx_id)); + cus->GetMaxPreviousProductVersion(crx_id), allowed); } void ComponentInstaller::Register( RegisterCallback register_callback, base::OnceClosure callback, const base::Version& registered_version, - const base::Version& max_previous_product_version) { + const base::Version& max_previous_product_version, + bool allowed) { + if (!allowed) return; DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!installer_policy_) { @@ -149,6 +153,7 @@ Result ComponentInstaller::InstallHelper(const base::FilePath& unpack_path, std::optional local_manifest = update_client::ReadManifest(unpack_path); if (!local_manifest) { + LOG(ERROR) << "Bad manifest"; return Result(InstallError::BAD_MANIFEST); } @@ -159,7 +164,7 @@ Result ComponentInstaller::InstallHelper(const base::FilePath& unpack_path, const base::Version manifest_version(*version_ascii); - VLOG(1) << "Install: version=" << manifest_version.GetString() + LOG(INFO) << "Install: version=" << manifest_version.GetString() << " current version=" << current_version_.GetString(); if (!manifest_version.IsValid()) { @@ -178,11 +183,11 @@ Result ComponentInstaller::InstallHelper(const base::FilePath& unpack_path, } } - VLOG(1) << "unpack_path=" << unpack_path.AsUTF8Unsafe() + LOG(INFO) << "unpack_path=" << unpack_path.AsUTF8Unsafe() << " install_path=" << local_install_path.AsUTF8Unsafe(); if (!base::Move(unpack_path, local_install_path)) { - VPLOG(0) << "Move failed."; + LOG(INFO) << "Move failed."; base::DeletePathRecursively(local_install_path); return Result(InstallError::MOVE_FILES_ERROR); } @@ -243,6 +248,9 @@ void ComponentInstaller::Install( InstallHelper(unpack_path, &manifest, &version, &install_path); base::DeletePathRecursively(unpack_path); if (result.result.category != update_client::ErrorCategory::kNone) { + LOG(ERROR) << "ComponentInstaller:" + << " Install error " << result.result.code + << " extra " << result.result.extra; main_task_runner_->PostTask(FROM_HERE, base::BindOnce(std::move(callback), result)); return; @@ -282,34 +290,34 @@ bool ComponentInstaller::FindPreinstallation( scoped_refptr registration_info) { base::FilePath path = root.Append(installer_policy_->GetRelativeInstallDir()); if (!base::PathExists(path)) { - DVLOG(1) << "Relative install dir does not exist: " << path.MaybeAsASCII(); + LOG(INFO) << "Relative install dir does not exist: " << path.MaybeAsASCII(); return false; } std::optional manifest = update_client::ReadManifest(path); if (!manifest) { - DVLOG(1) << "Manifest does not exist: " << path.MaybeAsASCII(); + LOG(INFO) << "Manifest does not exist: " << path.MaybeAsASCII(); return false; } if (!installer_policy_->VerifyInstallation(*manifest, path)) { - DVLOG(1) << "Installation verification failed: " << path.MaybeAsASCII(); + LOG(INFO) << "Installation verification failed: " << path.MaybeAsASCII(); return false; } std::string* version_lexical = manifest->FindString("version"); if (!version_lexical || !base::IsStringASCII(*version_lexical)) { - DVLOG(1) << "Failed to get component version from the manifest."; + LOG(INFO) << "Failed to get component version from the manifest."; return false; } const base::Version version(*version_lexical); if (!version.IsValid()) { - DVLOG(1) << "Version in the manifest is invalid:" << *version_lexical; + LOG(INFO) << "Version in the manifest is invalid:" << *version_lexical; return false; } - VLOG(1) << "Preinstalled component found for " << installer_policy_->GetName() + LOG(INFO) << "Preinstalled component found for " << installer_policy_->GetName() << " at " << path.MaybeAsASCII() << " with version " << version << "."; @@ -326,13 +334,13 @@ std::optional ComponentInstaller::GetValidInstallationManifest( const base::FilePath& path) { std::optional manifest = update_client::ReadManifest(path); if (!manifest) { - VPLOG(0) << "Failed to read manifest for " << installer_policy_->GetName() + LOG(INFO) << "Failed to read manifest for " << installer_policy_->GetName() << " (" << path.MaybeAsASCII() << ")."; return std::nullopt; } if (!installer_policy_->VerifyInstallation(*manifest, path)) { - VPLOG(0) << "Failed to verify installation for " + LOG(INFO) << "Failed to verify installation for " << installer_policy_->GetName() << " (" << path.MaybeAsASCII() << ")."; return std::nullopt; @@ -449,7 +457,7 @@ std::optional ComponentInstaller::GetComponentDirectory() { base::FilePath base_dir = base_component_dir.Append(installer_policy_->GetRelativeInstallDir()); if (!base::CreateDirectory(base_dir)) { - VPLOG(0) << "Could not create the base directory for " + LOG(INFO) << "Could not create the base directory for " << installer_policy_->GetName() << " (" << base_dir.MaybeAsASCII() << ")."; return std::nullopt; @@ -534,14 +542,14 @@ void ComponentInstaller::UninstallOnTaskRunner() { } if (!base::DeletePathRecursively(path)) { - DVLOG(0) << "Couldn't delete " << path.value(); + LOG(INFO) << "Couldn't delete " << path.value(); } } // Delete the base directory if it's empty now. if (base::IsDirectoryEmpty(*base_dir)) { if (!base::DeleteFile(*base_dir)) { - DVLOG(0) << "Couldn't delete " << base_dir->value(); + LOG(INFO) << "Couldn't delete " << base_dir->value(); } } @@ -585,7 +593,7 @@ void ComponentInstaller::FinishRegistration( if (registration_info->manifest) { ComponentReady(std::move(*registration_info->manifest)); } else { - DVLOG(1) << "No component found for " << installer_policy_->GetName(); + LOG(INFO) << "No component found for " << installer_policy_->GetName(); } if (!callback.is_null()) { @@ -594,7 +602,7 @@ void ComponentInstaller::FinishRegistration( } void ComponentInstaller::ComponentReady(base::DictValue manifest) { - VLOG(1) << "Component ready, version " << current_version_.GetString() + LOG(INFO) << "Component ready, version " << current_version_.GetString() << " in " << current_install_dir_.value(); installer_policy_->ComponentReady(current_version_, current_install_dir_, std::move(manifest)); diff --git a/components/component_updater/component_installer.h b/components/component_updater/component_installer.h --- a/components/component_updater/component_installer.h +++ b/components/component_updater/component_installer.h @@ -152,7 +152,7 @@ class ComponentInstaller final : public update_client::CrxInstaller { // |cus| provides the registration logic. // The passed |callback| will be called once the initial check for installed // versions is done and the component has been registered. - void Register(ComponentUpdateService* cus, base::OnceClosure callback); + void Register(ComponentUpdateService* cus, base::OnceClosure callback, bool allowed = false); // Registers the component for update checks and installs. // |register_callback| is called to do the registration. @@ -162,7 +162,7 @@ class ComponentInstaller final : public update_client::CrxInstaller { base::OnceClosure callback, const base::Version& registered_version = base::Version(kNullVersion), const base::Version& max_previous_product_version = - base::Version(kNullVersion)); + base::Version(kNullVersion), bool allowed = false); void Install(const base::FilePath& unpack_path, const std::string& public_key, diff --git a/components/component_updater/component_updater_url_constants.cc b/components/component_updater/component_updater_url_constants.cc --- a/components/component_updater/component_updater_url_constants.cc +++ b/components/component_updater/component_updater_url_constants.cc @@ -15,9 +15,9 @@ namespace component_updater { // The value of |kDefaultUrlSource| can be overridden with // --component-updater=url-source=someurl. const char kUpdaterJSONDefaultUrl[] = - "https://update.googleapis.com/service/update2/json"; + "https://www.cromite.org/components/query4_0.json"; const char kUpdaterJSONFallbackUrl[] = - "http://update.googleapis.com/service/update2/json"; + "about:blank"; } // namespace component_updater diff --git a/components/component_updater/configurator_impl.cc b/components/component_updater/configurator_impl.cc --- a/components/component_updater/configurator_impl.cc +++ b/components/component_updater/configurator_impl.cc @@ -40,8 +40,6 @@ ConfiguratorImpl::ConfiguratorImpl( : background_downloads_enabled_(config_policy.BackgroundDownloadsEnabled()), deltas_enabled_(config_policy.DeltaUpdatesEnabled()), fast_update_(config_policy.FastUpdate()), - pings_enabled_(config_policy.PingsEnabled()), - require_encryption_(require_encryption), url_source_override_(config_policy.UrlSourceOverride()), initial_delay_(config_policy.InitialDelay()) { if (config_policy.TestRequest()) { @@ -83,16 +81,14 @@ std::vector ConfiguratorImpl::UpdateUrl() const { std::vector urls{GURL(kUpdaterJSONDefaultUrl), GURL(kUpdaterJSONFallbackUrl)}; - if (require_encryption_) { - update_client::RemoveUnsecureUrls(&urls); - } + update_client::RemoveUnsecureUrls(&urls); return urls; } std::vector ConfiguratorImpl::PingUrl() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return pings_enabled_ ? UpdateUrl() : std::vector(); + return std::vector(); } const base::Version& ConfiguratorImpl::GetBrowserVersion() const { diff --git a/components/component_updater/configurator_impl.h b/components/component_updater/configurator_impl.h --- a/components/component_updater/configurator_impl.h +++ b/components/component_updater/configurator_impl.h @@ -106,8 +106,6 @@ class ConfiguratorImpl { const bool background_downloads_enabled_; const bool deltas_enabled_; const bool fast_update_; - const bool pings_enabled_; - const bool require_encryption_; const GURL url_source_override_; const base::TimeDelta initial_delay_; }; diff --git a/components/crx_file/crx_build_action_main.cc b/components/crx_file/crx_build_action_main.cc --- a/components/crx_file/crx_build_action_main.cc +++ b/components/crx_file/crx_build_action_main.cc @@ -9,6 +9,7 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/logging.h" +#include "base/strings/string_number_conversions.h" #include "components/crx_file/crx_creator.h" #include "crypto/keypair.h" @@ -30,8 +31,13 @@ int main(int argc, char** raw_argv) { VLOG(0) << "Failed to read key material from " << argv[3]; return -1; } + auto signing_key = crypto::RSAPrivateKey::CreateFromPrivateKeyInfo( + base::as_byte_span(key_file)); + std::vector public_key; + signing_key->ExportPublicKey(&public_key); + VLOG(0) << "Pubkey: " << base::HexEncode(public_key); + return static_cast(crx_file::Create( base::FilePath::FromASCII(argv[1]), base::FilePath::FromASCII(argv[2]), - *crypto::keypair::PrivateKey::FromPrivateKeyInfo( - base::as_byte_span(key_file)))); + signing_key.get())); } diff --git a/components/crx_file/crx_verifier.cc b/components/crx_file/crx_verifier.cc --- a/components/crx_file/crx_verifier.cc +++ b/components/crx_file/crx_verifier.cc @@ -13,6 +13,7 @@ #include #include +#include "base/logging.h" #include "base/base64.h" #include "base/files/file.h" #include "base/files/file_path.h" @@ -35,11 +36,17 @@ namespace { using KeyHash = std::array; // The SHA256 hash of the DER SPKI "ecdsa_2017_public" Crx3 key. -constexpr KeyHash kPublisherKeyHash = { +constexpr KeyHash kPublisherKeyHashCromite = { + 0x9F, 0x4A, 0x10, 0x80, 0x0F, 0x84, 0x13, 0xCB, 0x8F, 0x69, 0x92, + 0xA6, 0x03, 0x44, 0x9D, 0xC5, 0xFE, 0x01, 0x4D, 0x00, 0xF3, 0x4E, + 0x16, 0x79, 0xA1, 0x81, 0x95, 0x77, 0x1C, 0x5A, 0x21, 0x24}; + +constexpr KeyHash kPublisherKeyHashGoogle = { 0x61, 0xf7, 0xf2, 0xa6, 0xbf, 0xcf, 0x74, 0xcd, 0x0b, 0xc1, 0xfe, 0x24, 0x97, 0xcc, 0x9b, 0x04, 0x25, 0x4c, 0x65, 0x8f, 0x79, 0xf2, 0x14, 0x53, 0x92, 0x86, 0x7e, 0xa8, 0x36, 0x63, 0x67, 0xcf}; + // The SHA256 hash of the DER SPKI "ecdsa_2017_public" Crx3 test key. constexpr KeyHash kPublisherTestKeyHash = { 0x6c, 0x46, 0x41, 0x3b, 0x00, 0xd0, 0xfa, 0x0e, 0x72, 0xc8, 0xd2, @@ -110,7 +117,8 @@ VerifierResult VerifyCrx3( std::string* crx_id, std::vector* compressed_verified_contents, bool require_publisher_key, - bool accept_publisher_test_key) { + bool accept_publisher_test_key, + bool is_extension) { // Parse [header-size] and [header]. int header_size = base::saturated_cast(ReadAndHashLittleEndianUInt32(file, hash)); @@ -192,9 +200,18 @@ VerifierResult VerifyCrx3( } auto key_hash = crypto::hash::Sha256(key); required_key_set.erase(key_hash); + auto kPublisherKey = is_extension ? kPublisherKeyHashGoogle : kPublisherKeyHashCromite; found_publisher_key = - found_publisher_key || key_hash == kPublisherKeyHash || + found_publisher_key || key_hash == kPublisherKey || (accept_publisher_test_key && key_hash == kPublisherTestKeyHash); + + LOG(INFO) << "---is_extension: " << is_extension; + LOG(INFO) << "---key_hash: " << base::HexEncode(key_hash); + LOG(INFO) << "---publisher_key: " << base::HexEncode(kPublisherKey); + LOG(INFO) << "---found_publisher_key: " << found_publisher_key; + LOG(INFO) << "---sig: " << sig; + LOG(INFO) << "---key: " << key; + auto v = std::make_unique(); if (!v->VerifyInit(proof_type.second, base::as_byte_span(sig), base::as_byte_span(key))) { @@ -206,9 +223,11 @@ VerifierResult VerifyCrx3( verifiers.push_back(std::move(v)); } } +#if !BUILDFLAG(IS_ANDROID) if (public_key_bytes.empty() || !required_key_set.empty()) { return VerifierResult::ERROR_REQUIRED_PROOF_MISSING; } +#endif if (require_publisher_key && !found_publisher_key) { return VerifierResult::ERROR_REQUIRED_PROOF_MISSING; @@ -233,7 +252,7 @@ VerifierResult Verify( const std::vector& required_file_hash, std::string* public_key, std::string* crx_id, - std::vector* compressed_verified_contents) { + std::vector* compressed_verified_contents, bool is_extension) { std::string public_key_local; std::string crx_id_local; base::File file(crx_path, base::File::FLAG_OPEN | base::File::FLAG_READ); @@ -266,7 +285,7 @@ VerifierResult Verify( result = VerifyCrx3( &file, file_hash, required_key_hashes, &public_key_local, &crx_id_local, compressed_verified_contents, require_publisher_key, - format == VerifierFormat::CRX3_WITH_TEST_PUBLISHER_PROOF); + format == VerifierFormat::CRX3_WITH_TEST_PUBLISHER_PROOF, is_extension); } else { result = VerifierResult::ERROR_HEADER_INVALID; } diff --git a/components/crx_file/crx_verifier.h b/components/crx_file/crx_verifier.h --- a/components/crx_file/crx_verifier.h +++ b/components/crx_file/crx_verifier.h @@ -51,7 +51,7 @@ VerifierResult Verify( const std::vector& required_file_hash, std::string* public_key, std::string* crx_id, - std::vector* compressed_verified_contents); + std::vector* compressed_verified_contents, bool is_extension); } // namespace crx_file diff --git a/components/optimization_guide/core/delivery/prediction_model_download_manager.cc b/components/optimization_guide/core/delivery/prediction_model_download_manager.cc --- a/components/optimization_guide/core/delivery/prediction_model_download_manager.cc +++ b/components/optimization_guide/core/delivery/prediction_model_download_manager.cc @@ -313,7 +313,7 @@ bool PredictionModelDownloadManager::VerifyDownload( download_file_path, crx_file::VerifierFormat::CRX3, /*required_key_hashes=*/{}, /*required_file_hash=*/{}, &public_key, - /*crx_id=*/nullptr, /*compressed_verified_contents=*/nullptr); + /*crx_id=*/nullptr, /*compressed_verified_contents=*/nullptr, /* is_extension */ false); if (verifier_result != crx_file::VerifierResult::OK_FULL) { RecordPredictionModelDownloadStatus( PredictionModelDownloadStatus::kFailedCrxVerification); diff --git a/components/update_client/component.cc b/components/update_client/component.cc --- a/components/update_client/component.cc +++ b/components/update_client/component.cc @@ -368,6 +368,19 @@ void Component::StateChecking::DoHandle() { return; } + LOG(INFO) << "Component: StateChecking" + << " component.id=" << component.id() + << " previous_version()=" << component.previous_version().GetString() + << " next_version()=" << component.next_version().GetString(); + +#if BUILDFLAG(IS_ANDROID) + if (component.previous_version().CompareTo(component.next_version()) == 0) { + LOG(INFO) << "Component: No update needed"; + TransitionState(std::make_unique(&component)); + return; + } +#endif + if (component.pipeline_.has_value()) { TransitionState(std::make_unique(&component)); return; diff --git a/components/update_client/crx_downloader.cc b/components/update_client/crx_downloader.cc --- a/components/update_client/crx_downloader.cc +++ b/components/update_client/crx_downloader.cc @@ -32,6 +32,7 @@ #include "components/update_client/url_fetcher_downloader.h" #include "components/update_client/utils.h" #include "url/gurl.h" +#include "base/logging.h" namespace update_client { @@ -103,6 +104,9 @@ base::OnceClosure CrxDownloader::StartDownload( current_url_ = urls_.begin(); download_callback_ = std::move(download_callback); + LOG(INFO) << "CrxDownloader: StartDownload" + << " current_url_=" << *current_url_ + << " expected_hash=" << expected_hash; return DoStartDownload(*current_url_); } @@ -140,6 +144,7 @@ void CrxDownloader::OnDownloadComplete( return CrxDownloaderError::NONE; } DeleteFileAndEmptyParentDirectory(filepath); + LOG(ERROR) << "CrxDownloaderError: BAD_HASH"; return CrxDownloaderError::BAD_HASH; }, result.response, expected_hash_), diff --git a/components/update_client/net/network_impl.cc b/components/update_client/net/network_impl.cc --- a/components/update_client/net/network_impl.cc +++ b/components/update_client/net/network_impl.cc @@ -131,7 +131,9 @@ void NetworkFetcherImpl::PostRequest( network::SimpleURLLoader::RETRY_ON_NETWORK_CHANGE); // The `Content-Type` header set by |AttachStringForUpload| overwrites any // `Content-Type` header present in the |ResourceRequest| above. +#if !BUILDFLAG(IS_ANDROID) simple_url_loader->AttachStringForUpload(post_data, content_type); +#endif simple_url_loader->SetOnResponseStartedCallback(base::BindOnce( &NetworkFetcherImpl::OnResponseStartedCallback, weak_ptr_factory_.GetWeakPtr(), std::move(response_started_callback))); diff --git a/components/update_client/op_install.cc b/components/update_client/op_install.cc --- a/components/update_client/op_install.cc +++ b/components/update_client/op_install.cc @@ -202,7 +202,7 @@ void Unpack(base::OnceCallback callback, &Unpacker::Unpack, id, prod_id, pk_hash, // If and only if cached, the original path no longer exists. cache_result.has_value() ? cache_result.value() : crx_file, - std::move(unzipper), crx_format, is_foreground, + std::move(unzipper), /*is_extension*/ false, crx_format, is_foreground, base::BindPostTaskToCurrentDefault(std::move(callback)))); } diff --git a/components/update_client/protocol_parser.cc b/components/update_client/protocol_parser.cc --- a/components/update_client/protocol_parser.cc +++ b/components/update_client/protocol_parser.cc @@ -7,6 +7,7 @@ #include #include "base/strings/stringprintf.h" +#include "base/logging.h" namespace update_client { @@ -54,6 +55,7 @@ void ProtocolParser::ParseError(const char* details, ...) { UNSAFE_TODO(base::StringAppendV(&errors_, details, args)); va_end(args); + LOG(INFO) << "ParseError " << errors_; } bool ProtocolParser::Parse(const std::string& response) { diff --git a/components/update_client/protocol_parser_json.cc b/components/update_client/protocol_parser_json.cc --- a/components/update_client/protocol_parser_json.cc +++ b/components/update_client/protocol_parser_json.cc @@ -19,6 +19,7 @@ #include "base/values.h" #include "base/version.h" #include "components/update_client/protocol_definition.h" +#include "base/logging.h" namespace update_client { @@ -262,6 +263,7 @@ bool ProtocolParserJSON::DoParse(std::string_view response_json, Results* results) { CHECK(results); + LOG(INFO) << "ProtocolParserJSON: DoParse " << response_json; if (response_json.empty()) { ParseError("Empty JSON."); return false; diff --git a/components/update_client/request_sender.cc b/components/update_client/request_sender.cc --- a/components/update_client/request_sender.cc +++ b/components/update_client/request_sender.cc @@ -101,7 +101,8 @@ void RequestSender::SendInternal() { } VLOG_IF(2, !url.is_valid()) << "url is not valid."; - VLOG(2) << "Sending Omaha request: " << request_body_; + LOG(INFO) << "Sending Omaha request: " << url.spec(); + DLOG(INFO) << "Request body (not send): " << request_body_; if (!fetcher_factory_) { // The request was cancelled. diff --git a/components/update_client/unpacker.cc b/components/update_client/unpacker.cc --- a/components/update_client/unpacker.cc +++ b/components/update_client/unpacker.cc @@ -72,16 +72,17 @@ void Unpacker::Unpack(const std::string& app_id, const std::vector& pk_hash, const base::FilePath& path, std::unique_ptr unzipper, + bool is_extension, crx_file::VerifierFormat crx_format, bool is_foreground, base::OnceCallback callback) { base::WrapRefCounted(new Unpacker(app_id, prod_id, path, std::move(unzipper), is_foreground, std::move(callback))) - ->Verify(pk_hash, crx_format); + ->Verify(pk_hash, crx_format, is_extension); } void Unpacker::Verify(const std::vector& pk_hash, - crx_file::VerifierFormat crx_format) { + crx_file::VerifierFormat crx_format, bool is_extension) { TRACE_EVENT("update_client", "Unpacker::Verify", perfetto::Flow::FromPointer(this)); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -96,7 +97,7 @@ void Unpacker::Verify(const std::vector& pk_hash, } const crx_file::VerifierResult result = crx_file::Verify( path_, crx_format, required_keys, std::vector(), &public_key_, - /*crx_id=*/nullptr, &compressed_verified_contents_); + /*crx_id=*/nullptr, &compressed_verified_contents_, is_extension); if (result != crx_file::VerifierResult::OK_FULL) { EndUnpacking(UnpackerError::kInvalidFile, static_cast(result)); return; diff --git a/components/update_client/unpacker.h b/components/update_client/unpacker.h --- a/components/update_client/unpacker.h +++ b/components/update_client/unpacker.h @@ -75,6 +75,7 @@ class Unpacker : public base::RefCountedThreadSafe { const std::vector& pk_hash, const base::FilePath& path, std::unique_ptr unzipper, + bool is_extension, crx_file::VerifierFormat crx_format, bool is_foreground, base::OnceCallback callback); @@ -99,7 +100,8 @@ class Unpacker : public base::RefCountedThreadSafe { // `BeginUnzipping` if successful. Triggers `EndUnpacking` if an early error // is encountered. void Verify(const std::vector& pk_hash, - crx_file::VerifierFormat crx_format); + crx_file::VerifierFormat crx_format, + bool is_extension); // The next step of unpacking is to unzip. Triggers `EndUnzipping` if // successful. Triggers `EndUnpacking` if an early error is encountered. diff --git a/components/update_client/update_checker.cc b/components/update_client/update_checker.cc --- a/components/update_client/update_checker.cc +++ b/components/update_client/update_checker.cc @@ -263,6 +263,10 @@ void UpdateCheckerImpl::CheckForUpdatesHelper( config_->IsMachineExternallyManaged(), additional_attributes, updater_state_attributes, std::move(apps)); + bool enabled_cup_signing = config_->EnabledCupSigning(); +#if BUILDFLAG(IS_ANDROID) + enabled_cup_signing = false; +#endif cancellation_->OnCancel( base::MakeRefCounted(config_->GetNetworkFetcherFactory()) ->Send({url}, @@ -272,7 +276,7 @@ void UpdateCheckerImpl::CheckForUpdatesHelper( config_->GetProtocolHandlerFactory() ->CreateSerializer() ->Serialize(request), - config_->EnabledCupSigning(), + enabled_cup_signing, base::BindOnce( &UpdateCheckerImpl::OnRequestSenderComplete, weak_factory_.GetWeakPtr(), context, diff --git a/components/update_client/update_engine.cc b/components/update_client/update_engine.cc --- a/components/update_client/update_engine.cc +++ b/components/update_client/update_engine.cc @@ -210,6 +210,15 @@ void UpdateEngine::StartOperation( component->set_crx_component(*crx_component); component->set_previous_version(component->crx_component()->version); component->set_previous_fp(component->crx_component()->fingerprint); +#if BUILDFLAG(IS_ANDROID) + if (!update_context->is_foreground && component->crx_component()->version.IsValid() + && component->crx_component()->version.components()[0] != 0) { + LOG(INFO) << "Component " << id << " do not need updates. " + << "Current Version: " << component->crx_component()->version.GetString(); + continue; + } +#endif + LOG(INFO) << "Component " << id << " can be checked for updates."; update_context->components_to_check_for_updates.push_back(id); } else { // |CrxDataCallback| did not return a CrxComponent instance for this diff --git a/components/update_client/utils.cc b/components/update_client/utils.cc --- a/components/update_client/utils.cc +++ b/components/update_client/utils.cc @@ -25,6 +25,7 @@ #include "base/files/memory_mapped_file.h" #include "base/functional/callback.h" #include "base/functional/function_ref.h" +#include "base/logging.h" #include "base/json/json_file_value_serializer.h" #include "base/path_service.h" #include "base/strings/string_number_conversions.h" @@ -111,6 +112,9 @@ bool VerifyFileHash256(const base::FilePath& filepath, return false; } + DLOG(INFO) << "VerifyFileHash256 " + << "sha256_hash=" << base::HexEncode(hash); + return base::span(hash) == base::span(expected_hash); } diff --git a/extensions/browser/sandboxed_unpacker.cc b/extensions/browser/sandboxed_unpacker.cc --- a/extensions/browser/sandboxed_unpacker.cc +++ b/extensions/browser/sandboxed_unpacker.cc @@ -908,7 +908,7 @@ bool SandboxedUnpacker::ValidateSignature( const crx_file::VerifierResult result = crx_file::Verify( crx_path, required_format, std::vector>(), hash, - &public_key_, &extension_id_, &compressed_verified_contents_); + &public_key_, &extension_id_, &compressed_verified_contents_, /* is_extension */ true); switch (result) { case crx_file::VerifierResult::OK_FULL: { --