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

#include "components/sync_sessions/favicon_cache.h"

#include <utility>

#include "base/location.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "components/favicon/core/favicon_service.h"
#include "components/history/core/browser/history_service.h"
#include "components/sync/model/time.h"
#include "components/sync/protocol/favicon_image_specifics.pb.h"
#include "components/sync/protocol/favicon_tracking_specifics.pb.h"
#include "components/sync/protocol/sync.pb.h"
#include "ui/gfx/favicon_size.h"

namespace sync_sessions {

// Synced favicon storage and tracking.
// Note: we don't use the favicon service for storing these because these
// favicons are not necessarily associated with any local navigation, and
// hence would not work with the current expiration logic. We have custom
// expiration logic based on visit time/bookmark status/etc.
// See crbug.com/122890.
struct SyncedFaviconInfo {
  explicit SyncedFaviconInfo(const GURL& favicon_url)
      : favicon_url(favicon_url),
        is_bookmarked(false),
        received_local_update(false) {}

  // The actual favicon data.
  // TODO(zea): don't keep around the actual data for locally sourced
  // favicons (UI can access those directly).
  favicon_base::FaviconRawBitmapResult bitmap_data[NUM_SIZES];
  // The URL this favicon was loaded from.
  const GURL favicon_url;
  // Is the favicon for a bookmarked page?
  bool is_bookmarked;
  // The last time a tab needed this favicon.
  // Note: Do not modify this directly! It should only be modified via
  // UpdateFaviconVisitTime(..).
  base::Time last_visit_time;
  // Whether we've received a local update for this favicon since starting up.
  bool received_local_update;

 private:
  DISALLOW_COPY_AND_ASSIGN(SyncedFaviconInfo);
};

// Information for handling local favicon updates. Used in
// OnFaviconDataAvailable.
struct LocalFaviconUpdateInfo {
  LocalFaviconUpdateInfo()
      : new_image(false),
        new_tracking(false),
        image_needs_rewrite(false),
        favicon_info(nullptr) {}

  bool new_image;
  bool new_tracking;
  bool image_needs_rewrite;
  SyncedFaviconInfo* favicon_info;
};

namespace {

// Maximum width/height resolution supported.
const int kMaxFaviconResolution = 16;

// Returns a mask of the supported favicon types.
// TODO(zea): Supporting other favicons types will involve some work in the
// favicon service and navigation controller. See crbug.com/181068.
favicon_base::IconTypeSet SupportedFaviconTypes() {
  return {favicon_base::IconType::kFavicon};
}

// Returns the appropriate IconSize to use for a given gfx::Size pixel
// dimensions.
IconSize GetIconSizeBinFromBitmapResult(const gfx::Size& pixel_size) {
  int max_size =
      (pixel_size.width() > pixel_size.height() ?
       pixel_size.width() : pixel_size.height());
  // TODO(zea): re-enable 64p and 32p resolutions once we support them.
  if (max_size > 64)
    return SIZE_INVALID;
  else if (max_size > 32)
    return SIZE_INVALID;
  else if (max_size > 16)
    return SIZE_INVALID;
  else
    return SIZE_16;
}

// Helper for debug statements.
std::string IconSizeToString(IconSize icon_size) {
  switch (icon_size) {
    case SIZE_16:
      return "16";
    case SIZE_32:
      return "32";
    case SIZE_64:
      return "64";
    default:
      return "INVALID";
  }
}

// Extract the favicon url from either of the favicon types.
GURL GetFaviconURLFromSpecifics(const sync_pb::EntitySpecifics& specifics) {
  if (specifics.has_favicon_tracking())
    return GURL(specifics.favicon_tracking().favicon_url());
  else
    return GURL(specifics.favicon_image().favicon_url());
}

// Convert protobuf image data into a FaviconRawBitmapResult.
favicon_base::FaviconRawBitmapResult GetImageDataFromSpecifics(
    const sync_pb::FaviconData& favicon_data) {
  base::RefCountedString* temp_string =
      new base::RefCountedString();
  temp_string->data() = favicon_data.favicon();
  favicon_base::FaviconRawBitmapResult bitmap_result;
  bitmap_result.bitmap_data = temp_string;
  bitmap_result.pixel_size.set_height(favicon_data.height());
  bitmap_result.pixel_size.set_width(favicon_data.width());
  return bitmap_result;
}

// Convert a FaviconRawBitmapResult into protobuf image data.
void FillSpecificsWithImageData(
    const favicon_base::FaviconRawBitmapResult& bitmap_result,
    sync_pb::FaviconData* favicon_data) {
  if (!bitmap_result.bitmap_data.get())
    return;
  favicon_data->set_height(bitmap_result.pixel_size.height());
  favicon_data->set_width(bitmap_result.pixel_size.width());
  favicon_data->set_favicon(bitmap_result.bitmap_data->front(),
                            bitmap_result.bitmap_data->size());
}

// Build a FaviconImageSpecifics from a SyncedFaviconInfo.
void BuildImageSpecifics(
    const SyncedFaviconInfo* favicon_info,
    sync_pb::FaviconImageSpecifics* image_specifics) {
  image_specifics->set_favicon_url(favicon_info->favicon_url.spec());
  FillSpecificsWithImageData(favicon_info->bitmap_data[SIZE_16],
                             image_specifics->mutable_favicon_web());
  // TODO(zea): bring this back if we can handle the load.
  // FillSpecificsWithImageData(favicon_info->bitmap_data[SIZE_32],
  //                            image_specifics->mutable_favicon_web_32());
  // FillSpecificsWithImageData(favicon_info->bitmap_data[SIZE_64],
  //                            image_specifics->mutable_favicon_touch_64());
}

// Build a FaviconTrackingSpecifics from a SyncedFaviconInfo.
void BuildTrackingSpecifics(
    const SyncedFaviconInfo* favicon_info,
    sync_pb::FaviconTrackingSpecifics* tracking_specifics) {
  tracking_specifics->set_favicon_url(favicon_info->favicon_url.spec());
  tracking_specifics->set_last_visit_time_ms(
      syncer::TimeToProtoTime(favicon_info->last_visit_time));
  tracking_specifics->set_is_bookmarked(favicon_info->is_bookmarked);
}

// Updates |favicon_info| with the image data in |bitmap_result|.
bool UpdateFaviconFromBitmapResult(
    const favicon_base::FaviconRawBitmapResult& bitmap_result,
    SyncedFaviconInfo* favicon_info) {
  DCHECK_EQ(favicon_info->favicon_url, bitmap_result.icon_url);
  if (!bitmap_result.is_valid()) {
    DVLOG(1) << "Received invalid favicon at " << bitmap_result.icon_url.spec();
    return false;
  }

  IconSize icon_size = GetIconSizeBinFromBitmapResult(
      bitmap_result.pixel_size);
  if (icon_size == SIZE_INVALID) {
    DVLOG(1) << "Ignoring unsupported resolution "
             << bitmap_result.pixel_size.height() << "x"
             << bitmap_result.pixel_size.width();
    return false;
  } else if (!favicon_info->bitmap_data[icon_size].bitmap_data.get() ||
             !favicon_info->received_local_update) {
    DVLOG(1) << "Storing " << IconSizeToString(icon_size) << "p"
             << " favicon for " << favicon_info->favicon_url.spec()
             << " with size " << bitmap_result.bitmap_data->size()
             << " bytes.";
    favicon_info->bitmap_data[icon_size] = bitmap_result;
    favicon_info->received_local_update = true;
    return true;
  } else {
    // We only allow updating the image data once per restart.
    DVLOG(2) << "Ignoring local update for " << bitmap_result.icon_url.spec();
    return false;
  }
}

bool FaviconInfoHasImages(const SyncedFaviconInfo& favicon_info) {
  return favicon_info.bitmap_data[SIZE_16].bitmap_data.get() ||
         favicon_info.bitmap_data[SIZE_32].bitmap_data.get() ||
         favicon_info.bitmap_data[SIZE_64].bitmap_data.get();
}

bool FaviconInfoHasTracking(const SyncedFaviconInfo& favicon_info) {
  return !favicon_info.last_visit_time.is_null();
}

bool FaviconInfoHasValidTypeData(const SyncedFaviconInfo& favicon_info,
                             syncer::ModelType type) {
  if (type == syncer::FAVICON_IMAGES)
    return FaviconInfoHasImages(favicon_info);
  else if (type == syncer::FAVICON_TRACKING)
    return FaviconInfoHasTracking(favicon_info);
  NOTREACHED();
  return false;
}

}  // namespace

FaviconCache::FaviconCache(favicon::FaviconService* favicon_service,
                           history::HistoryService* history_service,
                           int max_sync_favicon_limit)
    : favicon_service_(favicon_service),
      max_sync_favicon_limit_(max_sync_favicon_limit),
      history_service_observer_(this),
      weak_ptr_factory_(this) {
  if (history_service)
    history_service_observer_.Add(history_service);
  DVLOG(1) << "Setting favicon limit to " << max_sync_favicon_limit;
}

FaviconCache::~FaviconCache() {}

syncer::SyncMergeResult FaviconCache::MergeDataAndStartSyncing(
    syncer::ModelType type,
    const syncer::SyncDataList& initial_sync_data,
    std::unique_ptr<syncer::SyncChangeProcessor> sync_processor,
    std::unique_ptr<syncer::SyncErrorFactory> error_handler) {
  DCHECK(type == syncer::FAVICON_IMAGES || type == syncer::FAVICON_TRACKING);
  if (type == syncer::FAVICON_IMAGES)
    favicon_images_sync_processor_ = std::move(sync_processor);
  else
    favicon_tracking_sync_processor_ = std::move(sync_processor);

  syncer::SyncMergeResult merge_result(type);
  merge_result.set_num_items_before_association(synced_favicons_.size());
  std::set<GURL> unsynced_favicon_urls;
  for (const auto& url_icon_pair : synced_favicons_) {
    if (FaviconInfoHasValidTypeData(*url_icon_pair.second, type))
      unsynced_favicon_urls.insert(url_icon_pair.first);
  }

  syncer::SyncChangeList local_changes;
  for (auto iter = initial_sync_data.begin(); iter != initial_sync_data.end();
       ++iter) {
    GURL remote_url = GetFaviconURLFromSpecifics(iter->GetSpecifics());
    GURL favicon_url = GetLocalFaviconFromSyncedData(*iter);
    if (favicon_url.is_valid()) {
      unsynced_favicon_urls.erase(favicon_url);
      MergeSyncFavicon(*iter, &local_changes);
      merge_result.set_num_items_modified(
          merge_result.num_items_modified() + 1);
    } else {
      AddLocalFaviconFromSyncedData(*iter);
      merge_result.set_num_items_added(merge_result.num_items_added() + 1);
    }
  }

  // Rather than trigger a bunch of deletions when we set up sync, we drop
  // local favicons. Those pages that are currently open are likely to result in
  // loading new favicons/refreshing old favicons anyways, at which point
  // they'll be re-added and the appropriate synced favicons will be evicted.
  // TODO(zea): implement a smarter ordering of the which favicons to drop.
  int available_favicons = max_sync_favicon_limit_ - initial_sync_data.size();
  for (auto iter = unsynced_favicon_urls.begin();
       iter != unsynced_favicon_urls.end(); ++iter) {
    if (available_favicons > 0) {
      local_changes.push_back(
          syncer::SyncChange(FROM_HERE,
                             syncer::SyncChange::ACTION_ADD,
                             CreateSyncDataFromLocalFavicon(type, *iter)));
      available_favicons--;
    } else {
      auto favicon_iter = synced_favicons_.find(*iter);
      DVLOG(1) << "Dropping local favicon "
               << favicon_iter->second->favicon_url.spec();
      DropPartialFavicon(favicon_iter, type);
      merge_result.set_num_items_deleted(merge_result.num_items_deleted() + 1);
    }
  }
  merge_result.set_num_items_after_association(synced_favicons_.size());

  if (type == syncer::FAVICON_IMAGES) {
    favicon_images_sync_processor_->ProcessSyncChanges(FROM_HERE,
                                                       local_changes);
  } else {
    favicon_tracking_sync_processor_->ProcessSyncChanges(FROM_HERE,
                                                         local_changes);
  }
  return merge_result;
}

void FaviconCache::StopSyncing(syncer::ModelType type) {
  favicon_images_sync_processor_.reset();
  favicon_tracking_sync_processor_.reset();
  cancelable_task_tracker_.TryCancelAll();
  page_task_map_.clear();
}

syncer::SyncDataList FaviconCache::GetAllSyncData(syncer::ModelType type)
    const {
  syncer::SyncDataList data_list;
  for (auto iter = synced_favicons_.begin(); iter != synced_favicons_.end();
       ++iter) {
    if ((type == syncer::FAVICON_IMAGES &&
         FaviconInfoHasImages(*iter->second)) ||
        (type == syncer::FAVICON_TRACKING &&
         FaviconInfoHasTracking(*iter->second))) {
      data_list.push_back(CreateSyncDataFromLocalFavicon(type, iter->first));
    }
  }
  return data_list;
}

syncer::SyncError FaviconCache::ProcessSyncChanges(
    const base::Location& from_here,
    const syncer::SyncChangeList& change_list) {
  if (!favicon_images_sync_processor_.get() ||
      !favicon_tracking_sync_processor_.get()) {
    return syncer::SyncError(FROM_HERE,
                             syncer::SyncError::DATATYPE_ERROR,
                             "One or both favicon types disabled.",
                             change_list[0].sync_data().GetDataType());
  }

  syncer::SyncChangeList new_changes;
  syncer::SyncError error;
  syncer::ModelType type = syncer::UNSPECIFIED;
  for (auto iter = change_list.begin(); iter != change_list.end(); ++iter) {
    type = iter->sync_data().GetDataType();
    DCHECK(type == syncer::FAVICON_IMAGES || type == syncer::FAVICON_TRACKING);
    GURL favicon_url =
        GetFaviconURLFromSpecifics(iter->sync_data().GetSpecifics());
    if (!favicon_url.is_valid()) {
      error.Reset(FROM_HERE, "Received invalid favicon url.", type);
      break;
    }
    auto favicon_iter = synced_favicons_.find(favicon_url);
    if (iter->change_type() == syncer::SyncChange::ACTION_DELETE) {
      if (favicon_iter == synced_favicons_.end()) {
        // Two clients might wind up deleting different parts of the same
        // favicon, so ignore this.
        continue;
      } else {
        DVLOG(1) << "Deleting favicon at " << favicon_url.spec();
        // If we only have partial data for the favicon (which implies orphaned
        // nodes), delete the local favicon only if the type corresponds to the
        // partial data we have. If we do have orphaned nodes, we rely on the
        // expiration logic to remove them eventually.
        DropPartialFavicon(favicon_iter, type);
      }
    } else if (iter->change_type() == syncer::SyncChange::ACTION_UPDATE ||
               iter->change_type() == syncer::SyncChange::ACTION_ADD) {
      // Adds and updates are treated the same due to the lack of strong
      // consistency (it's possible we'll receive an update for a tracking info
      // before we've received the add for the image, and should handle both
      // gracefully).
      if (favicon_iter == synced_favicons_.end()) {
        DVLOG(1) << "Adding favicon at " << favicon_url.spec();
        AddLocalFaviconFromSyncedData(iter->sync_data());
      } else {
        DVLOG(1) << "Updating favicon at " << favicon_url.spec();
        MergeSyncFavicon(iter->sync_data(), &new_changes);
      }
    } else {
      error.Reset(FROM_HERE, "Invalid action received.", type);
      break;
    }
  }

  // Note: we deliberately do not expire favicons here. If we received new
  // favicons and are now over the limit, the next local favicon change will
  // trigger the necessary expiration.
  if (!error.IsSet() && !new_changes.empty()) {
    if (type == syncer::FAVICON_IMAGES) {
        favicon_images_sync_processor_->ProcessSyncChanges(FROM_HERE,
                                                           new_changes);
    } else {
        favicon_tracking_sync_processor_->ProcessSyncChanges(FROM_HERE,
                                                             new_changes);
    }
  }

  return error;
}

void FaviconCache::OnPageFaviconUpdated(const GURL& page_url,
                                        base::Time mtime) {
  DCHECK(page_url.is_valid());

  // If a favicon load is already happening for this url, let it finish.
  if (page_task_map_.find(page_url) != page_task_map_.end())
    return;

  auto url_iter = page_favicon_map_.find(page_url);
  if (url_iter != page_favicon_map_.end()) {
    auto icon_iter = synced_favicons_.find(url_iter->second);
    // TODO(zea): consider what to do when only a subset of supported
    // resolutions are available.
    if (icon_iter != synced_favicons_.end() &&
        icon_iter->second->bitmap_data[SIZE_16].bitmap_data.get()) {
      DVLOG(2) << "Using cached favicon url for " << page_url.spec()
               << ": " << icon_iter->second->favicon_url.spec();
      UpdateFaviconVisitTime(icon_iter->second->favicon_url, mtime);
      UpdateSyncState(icon_iter->second->favicon_url,
                      syncer::SyncChange::ACTION_INVALID,
                      syncer::SyncChange::ACTION_UPDATE);
      return;
    }
  }

  DVLOG(1) << "Triggering favicon load for url " << page_url.spec();

  if (!favicon_service_) {
    page_task_map_[page_url] = 0;  // For testing only.
    return;
  }

  // TODO(zea): This appears to only fetch one favicon (best match based on
  // desired_size_in_dip). Figure out a way to fetch all favicons we support.
  // See crbug.com/181068.
  base::CancelableTaskTracker::TaskId id =
      favicon_service_->GetFaviconForPageURL(
          page_url, SupportedFaviconTypes(), kMaxFaviconResolution,
          base::Bind(&FaviconCache::OnFaviconDataAvailable,
                     weak_ptr_factory_.GetWeakPtr(), page_url, mtime),
          &cancelable_task_tracker_);
  page_task_map_[page_url] = id;
}

void FaviconCache::OnFaviconVisited(const GURL& page_url,
                                    const GURL& favicon_url) {
  DCHECK(page_url.is_valid());
  if (!favicon_url.is_valid() ||
      synced_favicons_.find(favicon_url) == synced_favicons_.end()) {
    // TODO(zea): consider triggering a favicon load if we have some but not
    // all desired resolutions?
    OnPageFaviconUpdated(page_url, base::Time::Now());
    return;
  }

  DVLOG(1) << "Associating " << page_url.spec() << " with favicon at "
           << favicon_url.spec() << " and marking visited.";
  page_favicon_map_[page_url] = favicon_url;
  bool had_tracking = FaviconInfoHasTracking(
      *synced_favicons_.find(favicon_url)->second);
  UpdateFaviconVisitTime(favicon_url, base::Time::Now());

  UpdateSyncState(favicon_url,
                  syncer::SyncChange::ACTION_INVALID,
                  (had_tracking ?
                   syncer::SyncChange::ACTION_UPDATE :
                   syncer::SyncChange::ACTION_ADD));
}

bool FaviconCache::GetSyncedFaviconForFaviconURL(
    const GURL& favicon_url,
    scoped_refptr<base::RefCountedMemory>* favicon_png) const {
  if (!favicon_url.is_valid())
    return false;
  auto iter = synced_favicons_.find(favicon_url);

  UMA_HISTOGRAM_BOOLEAN("Sync.FaviconCacheLookupSucceeded",
                        iter != synced_favicons_.end());
  if (iter == synced_favicons_.end())
    return false;

  // TODO(zea): support getting other resolutions.
  if (!iter->second->bitmap_data[SIZE_16].bitmap_data.get())
    return false;

  *favicon_png = iter->second->bitmap_data[SIZE_16].bitmap_data;
  return true;
}

bool FaviconCache::GetSyncedFaviconForPageURL(
    const GURL& page_url,
    scoped_refptr<base::RefCountedMemory>* favicon_png) const {
  if (!page_url.is_valid())
    return false;
  auto iter = page_favicon_map_.find(page_url);

  if (iter == page_favicon_map_.end())
    return false;

  return GetSyncedFaviconForFaviconURL(iter->second, favicon_png);
}

void FaviconCache::UpdateMappingsFromForeignTab(const sync_pb::SessionTab& tab,
                                                base::Time visit_time) {
  for (const sync_pb::TabNavigation& navigation : tab.navigation()) {
    const GURL page_url(navigation.virtual_url());
    const GURL icon_url(navigation.favicon_url());

    if (!icon_url.is_valid() || !page_url.is_valid() ||
        icon_url.SchemeIs("data")) {
      continue;
    }

    DVLOG(1) << "Associating " << page_url << " with favicon at " << icon_url;
    page_favicon_map_[page_url] = icon_url;

    if (synced_favicons_.count(icon_url) != 0)
      UpdateFaviconVisitTime(icon_url, visit_time);
  }
}

size_t FaviconCache::NumFaviconsForTest() const {
  return synced_favicons_.size();
}

size_t FaviconCache::NumTasksForTest() const {
  return page_task_map_.size();
}

base::Time FaviconCache::GetLastVisitTimeForTest(
    const GURL& favicon_url) const {
  auto iter = synced_favicons_.find(favicon_url);
  DCHECK(iter != synced_favicons_.end());
  return iter->second->last_visit_time;
}

bool FaviconCache::FaviconRecencyFunctor::operator()(
    const SyncedFaviconInfo* lhs,
    const SyncedFaviconInfo* rhs) const {
  // TODO(zea): incorporate bookmarked status here once we care about it.
  if (lhs->last_visit_time < rhs->last_visit_time)
    return true;
  else if (lhs->last_visit_time == rhs->last_visit_time)
    return lhs->favicon_url.spec() < rhs->favicon_url.spec();
  return false;
}

void FaviconCache::OnFaviconDataAvailable(
    const GURL& page_url,
    base::Time mtime,
    const std::vector<favicon_base::FaviconRawBitmapResult>& bitmap_results) {
  auto page_iter = page_task_map_.find(page_url);
  if (page_iter == page_task_map_.end())
    return;
  page_task_map_.erase(page_iter);

  if (bitmap_results.size() == 0) {
    // Either the favicon isn't loaded yet or there is no valid favicon.
    // We already cleared the task id, so just return.
    DVLOG(1) << "Favicon load failed for page " << page_url.spec();
    return;
  }

  std::map<GURL, LocalFaviconUpdateInfo> favicon_updates;
  for (size_t i = 0; i < bitmap_results.size(); ++i) {
    const favicon_base::FaviconRawBitmapResult& bitmap_result =
        bitmap_results[i];
    GURL favicon_url = bitmap_result.icon_url;
    if (!favicon_url.is_valid() || favicon_url.SchemeIs("data"))
      continue;  // Can happen if the page is still loading.

    SyncedFaviconInfo* favicon_info = GetFaviconInfo(favicon_url);
    if (!favicon_info)
      return;  // We reached the in-memory limit.

    favicon_updates[favicon_url].new_image |=
        !FaviconInfoHasImages(*favicon_info);
    favicon_updates[favicon_url].new_tracking |=
        !FaviconInfoHasTracking(*favicon_info);
    favicon_updates[favicon_url].image_needs_rewrite |=
        UpdateFaviconFromBitmapResult(bitmap_result, favicon_info);
    favicon_updates[favicon_url].favicon_info = favicon_info;
  }

  for (std::map<GURL, LocalFaviconUpdateInfo>::const_iterator
           iter = favicon_updates.begin(); iter != favicon_updates.end();
       ++iter) {
    SyncedFaviconInfo* favicon_info = iter->second.favicon_info;
    const GURL& favicon_url = favicon_info->favicon_url;

    // TODO(zea): support multiple favicon urls per page.
    page_favicon_map_[page_url] = favicon_url;

    favicon_info->received_local_update = true;
    UpdateFaviconVisitTime(favicon_url, mtime);

    syncer::SyncChange::SyncChangeType image_change =
        syncer::SyncChange::ACTION_INVALID;
    if (iter->second.new_image)
      image_change = syncer::SyncChange::ACTION_ADD;
    else if (iter->second.image_needs_rewrite)
      image_change = syncer::SyncChange::ACTION_UPDATE;
    syncer::SyncChange::SyncChangeType tracking_change =
        syncer::SyncChange::ACTION_UPDATE;
    if (iter->second.new_tracking)
      tracking_change = syncer::SyncChange::ACTION_ADD;
    UpdateSyncState(favicon_url, image_change, tracking_change);
  }
}

void FaviconCache::UpdateSyncState(
    const GURL& icon_url,
    syncer::SyncChange::SyncChangeType image_change_type,
    syncer::SyncChange::SyncChangeType tracking_change_type) {
  DCHECK(icon_url.is_valid());
  // It's possible that we'll receive a favicon update before both types
  // have finished setting up. In that case ignore the update.
  // TODO(zea): consider tracking these skipped updates somehow?
  if (!favicon_images_sync_processor_.get() ||
      !favicon_tracking_sync_processor_.get()) {
    return;
  }

  auto iter = synced_favicons_.find(icon_url);
  DCHECK(iter != synced_favicons_.end());
  const SyncedFaviconInfo* favicon_info = iter->second.get();

  syncer::SyncChangeList image_changes;
  syncer::SyncChangeList tracking_changes;
  if (image_change_type != syncer::SyncChange::ACTION_INVALID) {
    sync_pb::EntitySpecifics new_specifics;
    sync_pb::FaviconImageSpecifics* image_specifics =
        new_specifics.mutable_favicon_image();
    BuildImageSpecifics(favicon_info, image_specifics);

    image_changes.push_back(
        syncer::SyncChange(FROM_HERE,
                           image_change_type,
                           syncer::SyncData::CreateLocalData(
                               icon_url.spec(),
                               icon_url.spec(),
                               new_specifics)));
  }
  if (tracking_change_type != syncer::SyncChange::ACTION_INVALID) {
    sync_pb::EntitySpecifics new_specifics;
    sync_pb::FaviconTrackingSpecifics* tracking_specifics =
        new_specifics.mutable_favicon_tracking();
    BuildTrackingSpecifics(favicon_info, tracking_specifics);

    tracking_changes.push_back(
        syncer::SyncChange(FROM_HERE,
                           tracking_change_type,
                           syncer::SyncData::CreateLocalData(
                               icon_url.spec(),
                               icon_url.spec(),
                               new_specifics)));
  }
  ExpireFaviconsIfNecessary(&image_changes, &tracking_changes);
  if (!image_changes.empty()) {
    favicon_images_sync_processor_->ProcessSyncChanges(FROM_HERE,
                                                       image_changes);
  }
  if (!tracking_changes.empty()) {
    favicon_tracking_sync_processor_->ProcessSyncChanges(FROM_HERE,
                                                         tracking_changes);
  }
}

SyncedFaviconInfo* FaviconCache::GetFaviconInfo(
    const GURL& icon_url) {
  DCHECK_EQ(recent_favicons_.size(), synced_favicons_.size());
  if (synced_favicons_.count(icon_url) != 0)
    return synced_favicons_[icon_url].get();

  // TODO(zea): implement in-memory eviction.
  DVLOG(1) << "Adding favicon info for " << icon_url.spec();
  auto favicon_info = std::make_unique<SyncedFaviconInfo>(icon_url);
  SyncedFaviconInfo* favicon_info_ptr = favicon_info.get();
  synced_favicons_[icon_url] = std::move(favicon_info);
  recent_favicons_.insert(favicon_info_ptr);
  DCHECK_EQ(recent_favicons_.size(), synced_favicons_.size());
  return favicon_info_ptr;
}

void FaviconCache::UpdateFaviconVisitTime(const GURL& icon_url,
                                          base::Time time) {
  DCHECK_EQ(recent_favicons_.size(), synced_favicons_.size());
  auto iter = synced_favicons_.find(icon_url);
  DCHECK(iter != synced_favicons_.end());
  if (iter->second->last_visit_time >= time)
    return;
  // Erase, update the time, then re-insert to maintain ordering.
  recent_favicons_.erase(iter->second.get());
  DVLOG(1) << "Updating " << icon_url.spec() << " visit time to "
           << syncer::GetTimeDebugString(time);
  iter->second->last_visit_time = time;
  recent_favicons_.insert(iter->second.get());

  if (VLOG_IS_ON(2)) {
    for (const auto* icon : recent_favicons_) {
      DVLOG(2) << "Favicon " << icon->favicon_url.spec() << ": "
               << syncer::GetTimeDebugString(icon->last_visit_time);
    }
  }
  DCHECK_EQ(recent_favicons_.size(), synced_favicons_.size());
}

void FaviconCache::ExpireFaviconsIfNecessary(
    syncer::SyncChangeList* image_changes,
    syncer::SyncChangeList* tracking_changes) {
  DCHECK_EQ(recent_favicons_.size(), synced_favicons_.size());
  // TODO(zea): once we have in-memory eviction, we'll need to track sync
  // favicon count separately from the synced_favicons_/recent_favicons_.

  // Iterate until we've removed the necessary amount. |recent_favicons_| is
  // already in recency order, so just start from the beginning.
  // TODO(zea): to reduce thrashing, consider removing more than the minimum.
  while (recent_favicons_.size() > max_sync_favicon_limit_) {
    SyncedFaviconInfo* candidate = *recent_favicons_.begin();
    DVLOG(1) << "Expiring favicon " << candidate->favicon_url.spec();
    DeleteSyncedFavicon(synced_favicons_.find(candidate->favicon_url),
                        image_changes,
                        tracking_changes);
  }
  DCHECK_EQ(recent_favicons_.size(), synced_favicons_.size());
}

GURL FaviconCache::GetLocalFaviconFromSyncedData(
    const syncer::SyncData& sync_favicon) const {
  syncer::ModelType type = sync_favicon.GetDataType();
  DCHECK(type == syncer::FAVICON_IMAGES || type == syncer::FAVICON_TRACKING);
  GURL favicon_url = GetFaviconURLFromSpecifics(sync_favicon.GetSpecifics());
  return (synced_favicons_.count(favicon_url) > 0 ? favicon_url : GURL());
}

void FaviconCache::MergeSyncFavicon(const syncer::SyncData& sync_favicon,
                                    syncer::SyncChangeList* sync_changes) {
  syncer::ModelType type = sync_favicon.GetDataType();
  DCHECK(type == syncer::FAVICON_IMAGES || type == syncer::FAVICON_TRACKING);
  sync_pb::EntitySpecifics new_specifics;
  GURL favicon_url = GetFaviconURLFromSpecifics(sync_favicon.GetSpecifics());
  auto iter = synced_favicons_.find(favicon_url);
  DCHECK(iter != synced_favicons_.end());
  SyncedFaviconInfo* favicon_info = iter->second.get();
  if (type == syncer::FAVICON_IMAGES) {
    sync_pb::FaviconImageSpecifics image_specifics =
        sync_favicon.GetSpecifics().favicon_image();

    // Remote image data always clobbers local image data.
    bool needs_update = false;
    if (image_specifics.has_favicon_web()) {
      favicon_info->bitmap_data[SIZE_16] = GetImageDataFromSpecifics(
          image_specifics.favicon_web());
    } else if (favicon_info->bitmap_data[SIZE_16].bitmap_data.get()) {
      needs_update = true;
    }
    if (image_specifics.has_favicon_web_32()) {
      favicon_info->bitmap_data[SIZE_32] = GetImageDataFromSpecifics(
          image_specifics.favicon_web_32());
    } else if (favicon_info->bitmap_data[SIZE_32].bitmap_data.get()) {
      needs_update = true;
    }
    if (image_specifics.has_favicon_touch_64()) {
      favicon_info->bitmap_data[SIZE_64] = GetImageDataFromSpecifics(
          image_specifics.favicon_touch_64());
    } else if (favicon_info->bitmap_data[SIZE_64].bitmap_data.get()) {
      needs_update = true;
    }

    if (needs_update)
      BuildImageSpecifics(favicon_info, new_specifics.mutable_favicon_image());
  } else {
    sync_pb::FaviconTrackingSpecifics tracking_specifics =
        sync_favicon.GetSpecifics().favicon_tracking();

    // Tracking data is merged, such that bookmark data is the logical OR
    // of the two, and last visit time is the most recent.

    base::Time last_visit =  syncer::ProtoTimeToTime(
        tracking_specifics.last_visit_time_ms());
    // Due to crbug.com/258196, there are tracking nodes out there with
    // null visit times. If this is one of those, artificially make it a valid
    // visit time, so we know the node exists and update it properly on the next
    // real visit.
    if (last_visit.is_null())
      last_visit = last_visit + base::TimeDelta::FromMilliseconds(1);
    UpdateFaviconVisitTime(favicon_url, last_visit);
    favicon_info->is_bookmarked = (favicon_info->is_bookmarked ||
                                   tracking_specifics.is_bookmarked());

    if (syncer::TimeToProtoTime(favicon_info->last_visit_time) !=
            tracking_specifics.last_visit_time_ms() ||
        favicon_info->is_bookmarked != tracking_specifics.is_bookmarked()) {
      BuildTrackingSpecifics(favicon_info,
                             new_specifics.mutable_favicon_tracking());
    }
    DCHECK(!favicon_info->last_visit_time.is_null());
  }

  if (new_specifics.has_favicon_image() ||
      new_specifics.has_favicon_tracking()) {
    sync_changes->push_back(syncer::SyncChange(
        FROM_HERE,
        syncer::SyncChange::ACTION_UPDATE,
        syncer::SyncData::CreateLocalData(favicon_url.spec(),
                                          favicon_url.spec(),
                                          new_specifics)));
  }
}

void FaviconCache::AddLocalFaviconFromSyncedData(
    const syncer::SyncData& sync_favicon) {
  syncer::ModelType type = sync_favicon.GetDataType();
  DCHECK(type == syncer::FAVICON_IMAGES || type == syncer::FAVICON_TRACKING);
  if (type == syncer::FAVICON_IMAGES) {
    sync_pb::FaviconImageSpecifics image_specifics =
        sync_favicon.GetSpecifics().favicon_image();
    GURL favicon_url = GURL(image_specifics.favicon_url());
    DCHECK(favicon_url.is_valid());
    DCHECK(!synced_favicons_.count(favicon_url));

    SyncedFaviconInfo* favicon_info = GetFaviconInfo(favicon_url);
    if (!favicon_info)
      return;  // We reached the in-memory limit.
    if (image_specifics.has_favicon_web()) {
      favicon_info->bitmap_data[SIZE_16] = GetImageDataFromSpecifics(
          image_specifics.favicon_web());
    }
    if (image_specifics.has_favicon_web_32()) {
      favicon_info->bitmap_data[SIZE_32] = GetImageDataFromSpecifics(
          image_specifics.favicon_web_32());
    }
    if (image_specifics.has_favicon_touch_64()) {
      favicon_info->bitmap_data[SIZE_64] = GetImageDataFromSpecifics(
          image_specifics.favicon_touch_64());
    }
  } else {
    sync_pb::FaviconTrackingSpecifics tracking_specifics =
        sync_favicon.GetSpecifics().favicon_tracking();
    GURL favicon_url = GURL(tracking_specifics.favicon_url());
    DCHECK(favicon_url.is_valid());
    DCHECK(!synced_favicons_.count(favicon_url));

    SyncedFaviconInfo* favicon_info = GetFaviconInfo(favicon_url);
    if (!favicon_info)
      return;  // We reached the in-memory limit.
    base::Time last_visit =  syncer::ProtoTimeToTime(
        tracking_specifics.last_visit_time_ms());
    // Due to crbug.com/258196, there are tracking nodes out there with
    // null visit times. If this is one of those, artificially make it a valid
    // visit time, so we know the node exists and update it properly on the next
    // real visit.
    if (last_visit.is_null())
      last_visit = last_visit + base::TimeDelta::FromMilliseconds(1);
    UpdateFaviconVisitTime(favicon_url, last_visit);
    favicon_info->is_bookmarked = tracking_specifics.is_bookmarked();
    DCHECK(!favicon_info->last_visit_time.is_null());
  }
}

syncer::SyncData FaviconCache::CreateSyncDataFromLocalFavicon(
    syncer::ModelType type,
    const GURL& favicon_url) const {
  DCHECK(type == syncer::FAVICON_IMAGES || type == syncer::FAVICON_TRACKING);
  DCHECK(favicon_url.is_valid());
  auto iter = synced_favicons_.find(favicon_url);
  DCHECK(iter != synced_favicons_.end());
  SyncedFaviconInfo* favicon_info = iter->second.get();

  syncer::SyncData data;
  sync_pb::EntitySpecifics specifics;
  if (type == syncer::FAVICON_IMAGES) {
    sync_pb::FaviconImageSpecifics* image_specifics =
        specifics.mutable_favicon_image();
    BuildImageSpecifics(favicon_info, image_specifics);
  } else {
    sync_pb::FaviconTrackingSpecifics* tracking_specifics =
        specifics.mutable_favicon_tracking();
    BuildTrackingSpecifics(favicon_info, tracking_specifics);
  }
  data = syncer::SyncData::CreateLocalData(favicon_url.spec(),
                                           favicon_url.spec(),
                                           specifics);
  return data;
}

void FaviconCache::DeleteSyncedFavicons(const std::set<GURL>& favicon_urls) {
  syncer::SyncChangeList image_deletions, tracking_deletions;
  for (auto iter = favicon_urls.begin(); iter != favicon_urls.end(); ++iter) {
    auto favicon_iter = synced_favicons_.find(*iter);
    if (favicon_iter == synced_favicons_.end())
      continue;
    DeleteSyncedFavicon(favicon_iter,
                        &image_deletions,
                        &tracking_deletions);
  }
  DVLOG(1) << "Deleting " << image_deletions.size() << " synced favicons.";
  if (favicon_images_sync_processor_.get()) {
    favicon_images_sync_processor_->ProcessSyncChanges(FROM_HERE,
                                                       image_deletions);
  }
  if (favicon_tracking_sync_processor_.get()) {
    favicon_tracking_sync_processor_->ProcessSyncChanges(FROM_HERE,
                                                         tracking_deletions);
  }
}

void FaviconCache::DeleteSyncedFavicon(
    FaviconMap::iterator favicon_iter,
    syncer::SyncChangeList* image_changes,
    syncer::SyncChangeList* tracking_changes) {
  SyncedFaviconInfo* favicon_info = favicon_iter->second.get();
  if (FaviconInfoHasImages(*(favicon_iter->second))) {
    DVLOG(1) << "Deleting image for "
             << favicon_iter->second.get()->favicon_url;
    image_changes->push_back(
        syncer::SyncChange(FROM_HERE,
                           syncer::SyncChange::ACTION_DELETE,
                           syncer::SyncData::CreateLocalDelete(
                               favicon_info->favicon_url.spec(),
                               syncer::FAVICON_IMAGES)));
  }
  if (FaviconInfoHasTracking(*(favicon_iter->second))) {
    DVLOG(1) << "Deleting tracking for "
             << favicon_iter->second.get()->favicon_url;
    tracking_changes->push_back(
        syncer::SyncChange(FROM_HERE,
                           syncer::SyncChange::ACTION_DELETE,
                           syncer::SyncData::CreateLocalDelete(
                               favicon_info->favicon_url.spec(),
                               syncer::FAVICON_TRACKING)));
  }
  DropSyncedFavicon(favicon_iter);
}

void FaviconCache::DropSyncedFavicon(FaviconMap::iterator favicon_iter) {
  DVLOG(1) << "Dropping favicon " << favicon_iter->second.get()->favicon_url;
  const GURL& url = favicon_iter->first;
  recent_favicons_.erase(favicon_iter->second.get());
  base::EraseIf(page_favicon_map_,
                [url](const auto& kv) { return kv.second == url; });
  synced_favicons_.erase(favicon_iter);
}

void FaviconCache::DropPartialFavicon(FaviconMap::iterator favicon_iter,
                                      syncer::ModelType type) {
  // If the type being dropped has no valid data, do nothing.
  if ((type == syncer::FAVICON_TRACKING &&
       !FaviconInfoHasTracking(*favicon_iter->second)) ||
      (type == syncer::FAVICON_IMAGES &&
       !FaviconInfoHasImages(*favicon_iter->second))) {
    return;
  }

  // If the type being dropped is the only type with valid data, just delete
  // the favicon altogether.
  if ((type == syncer::FAVICON_TRACKING &&
       !FaviconInfoHasImages(*favicon_iter->second)) ||
      (type == syncer::FAVICON_IMAGES &&
       !FaviconInfoHasTracking(*favicon_iter->second))) {
    DropSyncedFavicon(favicon_iter);
    return;
  }

  if (type == syncer::FAVICON_IMAGES) {
    DVLOG(1) << "Dropping favicon image "
             << favicon_iter->second.get()->favicon_url;
    for (int i = 0; i < NUM_SIZES; ++i) {
      favicon_iter->second->bitmap_data[i] =
          favicon_base::FaviconRawBitmapResult();
    }
    DCHECK(!FaviconInfoHasImages(*favicon_iter->second));
  } else {
    DCHECK_EQ(type, syncer::FAVICON_TRACKING);
    DVLOG(1) << "Dropping favicon tracking "
             << favicon_iter->second.get()->favicon_url;
    recent_favicons_.erase(favicon_iter->second.get());
    favicon_iter->second->last_visit_time = base::Time();
    favicon_iter->second->is_bookmarked = false;
    recent_favicons_.insert(favicon_iter->second.get());
    DCHECK(!FaviconInfoHasTracking(*favicon_iter->second));
  }
}

void FaviconCache::OnURLsDeleted(history::HistoryService* history_service,
                                 const history::DeletionInfo& deletion_info) {
  // We only care about actual user (or sync) deletions.
  if (deletion_info.is_from_expiration())
    return;

  if (!deletion_info.IsAllHistory()) {
    DeleteSyncedFavicons(deletion_info.favicon_urls());
    return;
  }

  // All history was cleared: just delete all favicons.
  DVLOG(1) << "History clear detected, deleting all synced favicons.";
  syncer::SyncChangeList image_deletions, tracking_deletions;
  while (!synced_favicons_.empty()) {
    DeleteSyncedFavicon(synced_favicons_.begin(), &image_deletions,
                        &tracking_deletions);
  }

  if (favicon_images_sync_processor_.get()) {
    favicon_images_sync_processor_->ProcessSyncChanges(FROM_HERE,
                                                       image_deletions);
  }
  if (favicon_tracking_sync_processor_.get()) {
    favicon_tracking_sync_processor_->ProcessSyncChanges(FROM_HERE,
                                                         tracking_deletions);
  }
}

}  // namespace sync_sessions
