chromium/chrome/browser/apps/app_service/webapk/webapk_install_queue.cc

// Copyright 2021 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/apps/app_service/webapk/webapk_install_queue.h"

#include <utility>

#include "ash/components/arc/mojom/webapk.mojom.h"
#include "ash/components/arc/session/arc_bridge_service.h"
#include "ash/components/arc/session/arc_service_manager.h"
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "chrome/browser/apps/app_service/webapk/webapk_install_task.h"
#include "chrome/browser/profiles/profile.h"

namespace apps {

// Queue of WebApks to be installed or updated.
WebApkInstallQueue::WebApkInstallQueue(Profile* profile) : profile_(profile) {
  arc::ArcServiceManager* arc_service_manager = arc::ArcServiceManager::Get();
  DCHECK(arc_service_manager);
  arc_service_manager->arc_bridge_service()->webapk()->AddObserver(this);
}

WebApkInstallQueue::~WebApkInstallQueue() {
  arc::ArcServiceManager* arc_service_manager = arc::ArcServiceManager::Get();
  if (arc_service_manager) {
    arc_service_manager->arc_bridge_service()->webapk()->RemoveObserver(this);
  }
}

void WebApkInstallQueue::InstallOrUpdate(const std::string& app_id) {
  pending_installs_.push_back(
      std::make_unique<WebApkInstallTask>(profile_, app_id));
  PostMaybeStartNext();
}

void WebApkInstallQueue::PostMaybeStartNext() {
  base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
      FROM_HERE, base::BindOnce(&WebApkInstallQueue::MaybeStartNext,
                                weak_ptr_factory_.GetWeakPtr()));
}

void WebApkInstallQueue::MaybeStartNext() {
  if (pending_installs_.empty() || current_install_ || !connection_ready_) {
    return;
  }

  current_install_ = std::move(pending_installs_.front());
  pending_installs_.pop_front();

  current_install_->Start(base::BindOnce(
      &WebApkInstallQueue::OnInstallCompleted, weak_ptr_factory_.GetWeakPtr()));
}

void WebApkInstallQueue::OnInstallCompleted(bool success) {
  current_install_.reset();
  PostMaybeStartNext();
}

void WebApkInstallQueue::OnConnectionReady() {
  // Only start installing when WebApkInstance is ready, since installs cannot
  // complete without it.
  connection_ready_ = true;
  PostMaybeStartNext();
}

void WebApkInstallQueue::OnConnectionClosed() {
  connection_ready_ = false;
}

std::unique_ptr<WebApkInstallTask> WebApkInstallQueue::PopTaskForTest() {
  DCHECK(!current_install_);
  std::unique_ptr<WebApkInstallTask> task;
  if (!pending_installs_.empty()) {
    task = std::move(pending_installs_.front());
    pending_installs_.pop_front();
  }

  return task;
}

}  // namespace apps