chromium/ash/birch/birch_item_remover.cc

// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/birch/birch_item_remover.h"

#include <string>
#include <vector>

#include "ash/birch/birch_item.h"
#include "base/functional/bind.h"
#include "base/hash/sha1.h"
#include "base/task/task_traits.h"
#include "base/time/time.h"

namespace ash {

BirchItemRemover::BirchItemRemover(base::FilePath path,
                                   base::OnceClosure on_init_callback)
    : removed_items_proto_(path,
                           /*write_delay=*/base::TimeDelta(),
                           base::TaskPriority::USER_VISIBLE) {
  removed_items_proto_.RegisterOnInitUnsafe(std::move(on_init_callback));
  removed_items_proto_.Init();
}

BirchItemRemover::~BirchItemRemover() = default;

bool BirchItemRemover::Initialized() {
  return removed_items_proto_.initialized();
}

void BirchItemRemover::RemoveItem(BirchItem* item) {
  CHECK(removed_items_proto_.initialized());

  // Note: We are using a map for removed items for its set capabilities; the
  // map value is arbitrary.
  auto hash_and_insert = [&](const std::string& identifier,
                             google::protobuf::Map<std::string, bool>* map) {
    const std::string hashed_identifier = base::SHA1HashString(identifier);
    map->insert({hashed_identifier, false});
    removed_items_proto_.StartWrite();
  };

  switch (item->GetType()) {
    case BirchItemType::kTab: {
      hash_and_insert(static_cast<BirchTabItem*>(item)->url().spec(),
                      removed_items_proto_->mutable_removed_tab_items());
      return;
    };
    case BirchItemType::kLastActive: {
      hash_and_insert(
          static_cast<BirchLastActiveItem*>(item)->page_url().spec(),
          removed_items_proto_->mutable_removed_tab_items());
      return;
    }
    case BirchItemType::kMostVisited: {
      hash_and_insert(
          static_cast<BirchMostVisitedItem*>(item)->page_url().spec(),
          removed_items_proto_->mutable_removed_tab_items());
      return;
    }
    case BirchItemType::kSelfShare: {
      hash_and_insert(static_cast<BirchSelfShareItem*>(item)->url().spec(),
                      removed_items_proto_->mutable_removed_tab_items());
      return;
    }
    case BirchItemType::kCalendar: {
      hash_and_insert(static_cast<BirchCalendarItem*>(item)->event_id(),
                      removed_items_proto_->mutable_removed_calendar_items());
      return;
    }
    case BirchItemType::kAttachment: {
      hash_and_insert(static_cast<BirchAttachmentItem*>(item)->file_id(),
                      removed_items_proto_->mutable_removed_file_items());
      return;
    }
    case BirchItemType::kFile: {
      hash_and_insert(static_cast<BirchFileItem*>(item)->file_id(),
                      removed_items_proto_->mutable_removed_file_items());
      return;
    }
    case ash::BirchItemType::kCoral: {
      // TODO(yulunwu): implement coral birch item removal once defined.
      return;
    }
    case ash::BirchItemType::kReleaseNotes:
    case ash::BirchItemType::kWeather:
    case ash::BirchItemType::kLostMedia:
    case ash::BirchItemType::kTest: {
      NOTREACHED();
    }
  }
}

void BirchItemRemover::FilterRemovedTabs(std::vector<BirchTabItem>* tab_items) {
  CHECK(removed_items_proto_.initialized());
  std::erase_if(*tab_items, [this](const BirchTabItem& item) {
    const std::string hashed_url = base::SHA1HashString(item.url().spec());
    return removed_items_proto_->removed_tab_items().contains(hashed_url);
  });
}

void BirchItemRemover::FilterRemovedLastActiveItems(
    std::vector<BirchLastActiveItem>* items) {
  CHECK(removed_items_proto_.initialized());
  std::erase_if(*items, [this](const BirchLastActiveItem& item) {
    const std::string hashed_url = base::SHA1HashString(item.page_url().spec());
    return removed_items_proto_->removed_tab_items().contains(hashed_url);
  });
}

void BirchItemRemover::FilterRemovedMostVisitedItems(
    std::vector<BirchMostVisitedItem>* items) {
  CHECK(removed_items_proto_.initialized());
  std::erase_if(*items, [this](const BirchMostVisitedItem& item) {
    const std::string hashed_url = base::SHA1HashString(item.page_url().spec());
    return removed_items_proto_->removed_tab_items().contains(hashed_url);
  });
}

void BirchItemRemover::FilterRemovedSelfShareItems(
    std::vector<BirchSelfShareItem>* self_share_items) {
  CHECK(removed_items_proto_.initialized());
  std::erase_if(*self_share_items, [this](const BirchSelfShareItem& item) {
    const std::string hashed_url = base::SHA1HashString(item.url().spec());
    return removed_items_proto_->removed_tab_items().contains(hashed_url);
  });
}

void BirchItemRemover::FilterRemovedCalendarItems(
    std::vector<BirchCalendarItem>* calendar_items) {
  CHECK(removed_items_proto_.initialized());
  std::erase_if(*calendar_items, [this](const BirchCalendarItem& item) {
    const std::string hashed_id = base::SHA1HashString(item.event_id());
    return removed_items_proto_->removed_calendar_items().contains(hashed_id);
  });
}

void BirchItemRemover::FilterRemovedAttachmentItems(
    std::vector<BirchAttachmentItem>* attachment_items) {
  CHECK(removed_items_proto_.initialized());
  std::erase_if(*attachment_items, [this](const BirchAttachmentItem& item) {
    const std::string hashed_id = base::SHA1HashString(item.file_id());
    return removed_items_proto_->removed_file_items().contains(hashed_id);
  });
}

void BirchItemRemover::FilterRemovedFileItems(
    std::vector<BirchFileItem>* file_items) {
  CHECK(removed_items_proto_.initialized());
  std::erase_if(*file_items, [this](const BirchFileItem& item) {
    const std::string hashed_id = base::SHA1HashString(item.file_id());
    return removed_items_proto_->removed_file_items().contains(hashed_id);
  });
}

void BirchItemRemover::SetProtoInitCallbackForTest(base::OnceClosure callback) {
  removed_items_proto_.RegisterOnInitUnsafe(std::move(callback));
}

}  // namespace ash