blob: 70db1a41386b4027cd40734b1df289408e322694 [file] [log] [blame]
// Copyright 2020 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/query_tiles/internal/image_prefetcher.h"
#include <utility>
#include <vector>
#include "base/callback_helpers.h"
#include "base/memory/weak_ptr.h"
#include "base/notreached.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/query_tiles/internal/image_loader.h"
#include "components/query_tiles/internal/tile_group.h"
#include "components/query_tiles/internal/tile_iterator.h"
#include "third_party/skia/include/core/SkBitmap.h"
namespace query_tiles {
namespace {
int ToTileIteratorLevel(ImagePrefetchMode mode) {
switch (mode) {
case ImagePrefetchMode::kTopLevel:
return 0;
case ImagePrefetchMode::kAll:
return TileIterator::kAllTiles;
default:
NOTREACHED();
return 0;
}
}
class ImagePrefetcherImpl : public ImagePrefetcher {
public:
ImagePrefetcherImpl(ImagePrefetchMode mode,
std::unique_ptr<ImageLoader> image_loader)
: mode_(mode), image_loader_(std::move(image_loader)) {}
~ImagePrefetcherImpl() override = default;
private:
// ImagePrefetcher implementation.
void Prefetch(TileGroup tile_group,
bool is_from_reduced_mode,
base::OnceClosure done_callback) override {
DCHECK(done_callback);
if (mode_ == ImagePrefetchMode::kNone) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(done_callback)));
return;
}
// Get the URLs to fetch.
std::vector<GURL> urls_to_fetch;
int level = ToTileIteratorLevel(mode_);
TileIterator it(tile_group, level);
while (it.HasNext()) {
const auto* tile = it.Next();
DCHECK(tile);
if (tile->image_metadatas.empty())
continue;
GURL url = tile->image_metadatas.front().url;
if (!url.is_valid() || url.is_empty())
continue;
urls_to_fetch.emplace_back(std::move(url));
}
FetchImages(std::move(urls_to_fetch), is_from_reduced_mode,
std::move(done_callback));
}
// Fetch all images in |urls_to_fetch|.
void FetchImages(std::vector<GURL> urls_to_fetch,
bool is_from_reduced_mode,
base::OnceClosure done_callback) {
// All image urls are fetched.
if (urls_to_fetch.empty()) {
DCHECK(done_callback);
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(done_callback)));
return;
}
// Prefetch images one by one.
GURL url = urls_to_fetch.back();
DCHECK(url.is_valid());
urls_to_fetch.pop_back();
auto next =
base::BindOnce(&ImagePrefetcherImpl::FetchImages,
weak_ptr_factory_.GetWeakPtr(), std::move(urls_to_fetch),
is_from_reduced_mode, std::move(done_callback));
if (is_from_reduced_mode) {
// The image won't be decoded in reduced mode.
image_loader_->PrefetchImage(
url, base::BindOnce(&ImagePrefetcherImpl::OnImageFetchedInReducedMode,
weak_ptr_factory_.GetWeakPtr(), std::move(next)));
} else {
image_loader_->FetchImage(
url, base::BindOnce(&ImagePrefetcherImpl::OnImageFetched,
weak_ptr_factory_.GetWeakPtr(), std::move(next)));
}
}
void OnImageFetched(base::OnceClosure next, SkBitmap bitmap) {
if (next) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(next)));
}
}
void OnImageFetchedInReducedMode(base::OnceClosure next, bool success) {
if (next) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(next)));
}
}
ImagePrefetchMode mode_;
std::unique_ptr<ImageLoader> image_loader_;
base::WeakPtrFactory<ImagePrefetcherImpl> weak_ptr_factory_{this};
};
} // namespace
// static
std::unique_ptr<ImagePrefetcher> ImagePrefetcher::Create(
ImagePrefetchMode prefetch_mode,
std::unique_ptr<ImageLoader> image_loader) {
return std::make_unique<ImagePrefetcherImpl>(prefetch_mode,
std::move(image_loader));
}
} // namespace query_tiles