blob: 33c8edc0bb7ff0082b90c687f2095bd80a0417d6 [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ai/ai_crx_component.h"
#include <memory>
#include "components/update_client/crx_update_item.h"
namespace on_device_ai {
namespace {
bool IsDownloadEvent(const component_updater::CrxUpdateItem& item) {
// See class comment: components/update_client/component.h
switch (item.state) {
case update_client::ComponentState::kDownloading:
case update_client::ComponentState::kUpdating:
case update_client::ComponentState::kUpToDate:
return item.downloaded_bytes >= 0 && item.total_bytes >= 0;
case update_client::ComponentState::kNew:
case update_client::ComponentState::kChecking:
case update_client::ComponentState::kCanUpdate:
case update_client::ComponentState::kUpdated:
case update_client::ComponentState::kUpdateError:
case update_client::ComponentState::kRun:
return false;
}
}
bool IsAlreadyInstalled(const component_updater::CrxUpdateItem& item) {
// See class comment: components/update_client/component.h
switch (item.state) {
case update_client::ComponentState::kUpdated:
case update_client::ComponentState::kUpToDate:
return true;
case update_client::ComponentState::kNew:
case update_client::ComponentState::kChecking:
case update_client::ComponentState::kCanUpdate:
case update_client::ComponentState::kDownloading:
case update_client::ComponentState::kUpdating:
case update_client::ComponentState::kUpdateError:
case update_client::ComponentState::kRun:
return false;
}
}
} // namespace
// static
base::flat_set<std::unique_ptr<AIModelDownloadProgressManager::Component>>
AICrxComponent::FromComponentIds(
component_updater::ComponentUpdateService* component_update_service,
base::flat_set<std::string> component_ids) {
base::flat_set<std::unique_ptr<Component>> components;
components.reserve(component_ids.size());
for (std::string component_id : component_ids) {
components.emplace(std::make_unique<AICrxComponent>(
component_update_service, std::move(component_id)));
}
return components;
}
AICrxComponent::AICrxComponent(
component_updater::ComponentUpdateService* component_update_service,
std::string component_id)
: component_id_(std::move(component_id)) {
component_updater::CrxUpdateItem item;
bool success =
component_update_service->GetComponentDetails(component_id_, &item);
// When `success` returns false, it means the component hasn't
// been registered yet. `GetComponentDetails` doesn't fill out `item` in this
// case, and we can just treat the component as if it had a state of `kNew`.
if (success && IsAlreadyInstalled(item)) {
// We just need to set the downloaded bytes and total bytes equal to each
// other to indicate to the `AIModelDownloadProgressManager` that we're
// installed.
//
// We don't set it to `item`'s `downloaded_bytes` and `total_bytes` because
// they may be less than zero which `AIModelDownloadProgressManager` doesn't
// allow.
SetDownloadedBytes(0);
SetTotalBytes(0);
return;
}
// Watch for progress updates.
component_updater_observation_.Observe(component_update_service);
}
AICrxComponent::~AICrxComponent() = default;
// component_updater::ServiceObserver:
void AICrxComponent::OnEvent(const component_updater::CrxUpdateItem& item) {
if (!IsDownloadEvent(item) || item.id != component_id_) {
return;
}
SetDownloadedBytes(item.downloaded_bytes);
SetTotalBytes(item.total_bytes);
}
} // namespace on_device_ai