chromium/chrome/browser/ui/ash/birch/birch_keyed_service.cc

// Copyright 2023 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/ui/ash/birch/birch_keyed_service.h"

#include <memory>
#include <optional>

#include "ash/birch/birch_model.h"
#include "ash/shell.h"
#include "base/functional/bind.h"
#include "chrome/browser/ash/file_suggest/file_suggest_keyed_service_factory.h"
#include "chrome/browser/favicon/favicon_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/ash/birch/birch_calendar_provider.h"
#include "chrome/browser/ui/ash/birch/birch_file_suggest_provider.h"
#include "chrome/browser/ui/ash/birch/birch_last_active_provider.h"
#include "chrome/browser/ui/ash/birch/birch_lost_media_provider.h"
#include "chrome/browser/ui/ash/birch/birch_most_visited_provider.h"
#include "chrome/browser/ui/ash/birch/birch_recent_tabs_provider.h"
#include "chrome/browser/ui/ash/birch/birch_release_notes_provider.h"
#include "chrome/browser/ui/ash/birch/birch_self_share_provider.h"
#include "chrome/browser/ui/ash/birch/refresh_token_waiter.h"
#include "components/favicon/core/favicon_service.h"
#include "components/favicon_base/favicon_types.h"
#include "ui/base/models/image_model.h"
#include "ui/gfx/image/image_skia_operations.h"

namespace ash {

namespace {

// The file within the cryptohome to save removed items into.
constexpr char kRemovedBirchItemsFile[] = "birch/removed_items.pb";

// The minimum size to query for favicons.
constexpr int kMinimumFaviconSize = 32;

// Utility method to resize the raw favicon bitmap into a `gfx::Image`.
gfx::Image ResizeLargeIcon(
    const favicon_base::FaviconRawBitmapResult& db_result,
    int desired_size) {
  gfx::Image image = gfx::Image::CreateFrom1xPNGBytes(db_result.bitmap_data);

  SkBitmap resized = skia::ImageOperations::Resize(
      image.AsBitmap(), skia::ImageOperations::RESIZE_BEST, desired_size,
      desired_size);

  return gfx::Image::CreateFrom1xBitmap(resized);
}

// Callback for FaviconService icon lookup that uses the
// `favicon_base::FaviconRawBitmapResult`.
void OnGotFaviconImageRaw(
    base::OnceCallback<void(const ui::ImageModel&)> callback,
    const favicon_base::FaviconRawBitmapResult& image_result) {
  if (!image_result.is_valid()) {
    std::move(callback).Run(ui::ImageModel());
    return;
  }

  gfx::Image image = ResizeLargeIcon(image_result, kMinimumFaviconSize);

  std::move(callback).Run(ui::ImageModel::FromImage(image));
}

}  // namespace

BirchKeyedService::BirchKeyedService(Profile* profile)
    : profile_(profile),
      calendar_provider_(std::make_unique<BirchCalendarProvider>(profile)),
      file_suggest_provider_(
          std::make_unique<BirchFileSuggestProvider>(profile)),
      recent_tabs_provider_(std::make_unique<BirchRecentTabsProvider>(profile)),
      last_active_provider_(std::make_unique<BirchLastActiveProvider>(profile)),
      most_visited_provider_(
          std::make_unique<BirchMostVisitedProvider>(profile)),
      release_notes_provider_(
          std::make_unique<BirchReleaseNotesProvider>(profile)),
      self_share_provider_(std::make_unique<BirchSelfShareProvider>(profile)),
      lost_media_provider_(std::make_unique<BirchLostMediaProvider>(profile)),
      refresh_token_waiter_(std::make_unique<RefreshTokenWaiter>(profile)) {
  calendar_provider_->Initialize();
  Shell::Get()->birch_model()->SetClientAndInit(this);
  shell_observation_.Observe(Shell::Get());
}

BirchKeyedService::~BirchKeyedService() {
  ShutdownBirch();
}

void BirchKeyedService::OnShellDestroying() {
  ShutdownBirch();
}

BirchDataProvider* BirchKeyedService::GetCalendarProvider() {
  if (calendar_provider_for_test_) {
    return calendar_provider_for_test_;
  }
  return calendar_provider_.get();
}

BirchDataProvider* BirchKeyedService::GetFileSuggestProvider() {
  if (file_suggest_provider_for_test_) {
    return file_suggest_provider_for_test_;
  }
  return file_suggest_provider_.get();
}

BirchDataProvider* BirchKeyedService::GetRecentTabsProvider() {
  if (recent_tabs_provider_for_test_) {
    return recent_tabs_provider_for_test_;
  }
  return recent_tabs_provider_.get();
}

BirchDataProvider* BirchKeyedService::GetLastActiveProvider() {
  if (last_active_provider_for_test_) {
    return last_active_provider_for_test_;
  }
  return last_active_provider_.get();
}

BirchDataProvider* BirchKeyedService::GetMostVisitedProvider() {
  if (most_visited_provider_for_test_) {
    return most_visited_provider_for_test_;
  }
  return most_visited_provider_.get();
}

BirchDataProvider* BirchKeyedService::GetReleaseNotesProvider() {
  if (release_notes_provider_for_test_) {
    return release_notes_provider_for_test_;
  }
  return release_notes_provider_.get();
}

BirchDataProvider* BirchKeyedService::GetSelfShareProvider() {
  if (self_share_provider_for_test_) {
    return self_share_provider_for_test_;
  }
  return self_share_provider_.get();
}

BirchDataProvider* BirchKeyedService::GetLostMediaProvider() {
  if (lost_media_provider_for_test_) {
    return lost_media_provider_for_test_;
  }
  return lost_media_provider_.get();
}

void BirchKeyedService::WaitForRefreshTokens(base::OnceClosure callback) {
  refresh_token_waiter_->Wait(std::move(callback));
}

base::FilePath BirchKeyedService::GetRemovedItemsFilePath() {
  return profile_->GetPath().AppendASCII(kRemovedBirchItemsFile);
}

void BirchKeyedService::RemoveFileItemFromLauncher(const base::FilePath& path) {
  std::vector<base::FilePath> file_paths;
  file_paths.push_back(path);
  auto* file_suggest_keyed_service =
      FileSuggestKeyedServiceFactory::GetInstance()->GetService(profile_);
  file_suggest_keyed_service->RemoveSuggestionsAndNotify(file_paths);
}

void BirchKeyedService::GetFaviconImage(
    const GURL& url,
    const bool is_page_url,
    base::OnceCallback<void(const ui::ImageModel&)> callback) {
  favicon::FaviconService* service =
      FaviconServiceFactory::GetInstance()->GetForProfile(
          profile_, ServiceAccessType::EXPLICIT_ACCESS);
  favicon_base::IconType icon_type = favicon_base::IconType::kFavicon;

  if (is_page_url) {
    const favicon_base::IconTypeSet icon_types = {icon_type};
    service->GetLargestRawFaviconForPageURL(
        url, {icon_types}, kMinimumFaviconSize,
        base::BindOnce(&OnGotFaviconImageRaw, std::move(callback)),
        &cancelable_task_tracker_);
  } else {
    service->GetRawFavicon(
        url, icon_type, kMinimumFaviconSize,
        base::BindOnce(&OnGotFaviconImageRaw, std::move(callback)),
        &cancelable_task_tracker_);
  }
}

void BirchKeyedService::ShutdownBirch() {
  if (is_shutdown_) {
    return;
  }
  is_shutdown_ = true;
  shell_observation_.Reset();
  Shell::Get()->birch_model()->SetClientAndInit(nullptr);
  calendar_provider_->Shutdown();
}

}  // namespace ash