Commit 6dea50ee authored by Scott Violet's avatar Scott Violet Committed by Commit Bot

weblayer: adds Profile::GetCachedFaviconForPageUrl()

This is used to fetch a previously downloaded favicon. For
consistency this returns the same image as that returned
from FaviconFetcher.

BUG=1076463
TEST=none

Change-Id: Icdd01286d1d564c7cb5b62847ffb1d888d9d70fe
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2340796Reviewed-by: default avatarEvan Stade <estade@chromium.org>
Commit-Queue: Scott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/master@{#795685}
parent 20be5e59
......@@ -11,6 +11,7 @@
#include "weblayer/browser/favicon/favicon_service_impl.h"
#include "weblayer/browser/favicon/favicon_service_impl_factory.h"
#include "weblayer/browser/favicon/favicon_service_impl_observer.h"
#include "weblayer/browser/favicon/test_favicon_fetcher_delegate.h"
#include "weblayer/browser/tab_impl.h"
#include "weblayer/public/favicon_fetcher_delegate.h"
#include "weblayer/public/navigation_controller.h"
......@@ -22,40 +23,6 @@
namespace weblayer {
namespace {
// Records calls to OnFaviconChanged().
class FaviconFetcherDelegateImpl : public FaviconFetcherDelegate {
public:
void WaitForFavicon() {
ASSERT_EQ(nullptr, run_loop_.get());
run_loop_ = std::make_unique<base::RunLoop>();
run_loop_->Run();
run_loop_.reset();
}
void ClearLastImage() {
last_image_ = gfx::Image();
on_favicon_changed_call_count_ = 0;
}
const gfx::Image& last_image() const { return last_image_; }
int on_favicon_changed_call_count() const {
return on_favicon_changed_call_count_;
}
// FaviconFetcherDelegate:
void OnFaviconChanged(const gfx::Image& image) override {
last_image_ = image;
++on_favicon_changed_call_count_;
if (run_loop_)
run_loop_->Quit();
}
private:
std::unique_ptr<base::RunLoop> run_loop_;
gfx::Image last_image_;
int on_favicon_changed_call_count_ = 0;
};
// FaviconServiceImplObserver used to wait for download to fail.
class TestFaviconServiceImplObserver : public FaviconServiceImplObserver {
public:
......@@ -82,7 +49,7 @@ using FaviconFetcherBrowserTest = WebLayerBrowserTest;
IN_PROC_BROWSER_TEST_F(FaviconFetcherBrowserTest, Basic) {
ASSERT_TRUE(embedded_test_server()->Start());
FaviconFetcherDelegateImpl fetcher_delegate;
TestFaviconFetcherDelegate fetcher_delegate;
auto fetcher = shell()->tab()->CreateFaviconFetcher(&fetcher_delegate);
NavigateAndWaitForCompletion(
embedded_test_server()->GetURL("/simple_page_with_favicon.html"),
......@@ -113,7 +80,7 @@ IN_PROC_BROWSER_TEST_F(FaviconFetcherBrowserTest, Basic) {
IN_PROC_BROWSER_TEST_F(FaviconFetcherBrowserTest, NavigateToPageWithNoFavicon) {
ASSERT_TRUE(embedded_test_server()->Start());
FaviconFetcherDelegateImpl fetcher_delegate;
TestFaviconFetcherDelegate fetcher_delegate;
auto fetcher = shell()->tab()->CreateFaviconFetcher(&fetcher_delegate);
NavigateAndWaitForCompletion(
embedded_test_server()->GetURL("/simple_page_with_favicon.html"),
......@@ -147,7 +114,7 @@ IN_PROC_BROWSER_TEST_F(FaviconFetcherBrowserTest,
favicon::ContentFaviconDriver::FromWebContents(web_contents));
// Request a fetcher, which should trigger creating ContentFaviconDriver.
FaviconFetcherDelegateImpl fetcher_delegate;
TestFaviconFetcherDelegate fetcher_delegate;
auto fetcher = shell()->tab()->CreateFaviconFetcher(&fetcher_delegate);
EXPECT_NE(nullptr,
favicon::ContentFaviconDriver::FromWebContents(web_contents));
......
......@@ -13,10 +13,12 @@
#include "base/hash/hash.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "build/build_config.h"
#include "components/favicon_base/favicon_util.h"
#include "components/favicon_base/select_favicon_frames.h"
#include "content/public/common/url_constants.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/favicon_size.h"
#include "url/gurl.h"
#include "weblayer/browser/favicon/favicon_backend_wrapper.h"
#include "weblayer/browser/favicon/favicon_service_impl_observer.h"
......@@ -39,6 +41,39 @@ bool CanAddUrl(const GURL& url) {
return true;
}
// Returns the IconTypeSet for the current platform. This matches the set
// of favicon types that are requested for the platform (see
// FaviconDriverImpl).
favicon_base::IconTypeSet GetIconTypeSet() {
#if defined(OS_ANDROID)
return {favicon_base::IconType::kFavicon, favicon_base::IconType::kTouchIcon,
favicon_base::IconType::kTouchPrecomposedIcon,
favicon_base::IconType::kWebManifestIcon};
#else
return {favicon_base::IconType::kFavicon};
#endif
}
int GetDesiredFaviconSizeInDips() {
#if defined(OS_ANDROID)
// This is treatest as the largest available icon.
return 0;
#else
return gfx::kFaviconSize;
#endif
}
void OnGotFaviconsForPageUrl(
int desired_size_in_dip,
base::OnceCallback<void(gfx::Image)> callback,
std::vector<favicon_base::FaviconRawBitmapResult> results) {
favicon_base::FaviconImageResult image_result;
image_result.image = favicon_base::SelectFaviconFramesFromPNGs(
results, favicon_base::GetFaviconScales(), desired_size_in_dip);
favicon_base::SetFaviconColorSpace(&image_result.image);
std::move(callback).Run(image_result.image);
}
} // namespace
FaviconServiceImpl::FaviconServiceImpl() = default;
......@@ -66,6 +101,22 @@ void FaviconServiceImpl::Init(const base::FilePath& db_path) {
base::BindOnce(&FaviconBackendWrapper::Init, backend_, db_path));
}
base::CancelableTaskTracker::TaskId FaviconServiceImpl::GetFaviconForPageUrl(
const GURL& page_url,
base::OnceCallback<void(gfx::Image)> callback,
base::CancelableTaskTracker* tracker) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// The arguments supplied to this function should return an image matching
// that returned by FaviconFetcher.
return tracker->PostTaskAndReplyWithResult(
backend_task_runner_.get(), FROM_HERE,
base::BindOnce(&FaviconBackendWrapper::GetFaviconsForUrl, backend_,
page_url, GetIconTypeSet(),
GetDesiredFaviconSizesInPixels()),
base::BindOnce(&OnGotFaviconsForPageUrl, GetDesiredFaviconSizeInDips(),
std::move(callback)));
}
base::CancelableTaskTracker::TaskId FaviconServiceImpl::GetFaviconForPageURL(
const GURL& page_url,
const favicon_base::IconTypeSet& icon_types,
......@@ -182,4 +233,9 @@ bool FaviconServiceImpl::WasUnableToDownloadFavicon(
return missing_favicon_urls_.find(url_hash) != missing_favicon_urls_.end();
}
// static
std::vector<int> FaviconServiceImpl::GetDesiredFaviconSizesInPixels() {
return GetPixelSizesForFaviconScales(GetDesiredFaviconSizeInDips());
}
} // namespace weblayer
......@@ -35,6 +35,13 @@ class FaviconServiceImpl : public favicon::CoreFaviconService {
observer_ = observer;
}
// Requests the favicon image for a url (page). The returned image matches
// that returned from FaviconFetcher.
base::CancelableTaskTracker::TaskId GetFaviconForPageUrl(
const GURL& page_url,
base::OnceCallback<void(gfx::Image)> callback,
base::CancelableTaskTracker* tracker);
// favicon::CoreFaviconService:
base::CancelableTaskTracker::TaskId GetFaviconForPageURL(
const GURL& page_url,
......@@ -74,6 +81,9 @@ class FaviconServiceImpl : public favicon::CoreFaviconService {
using MissingFaviconUrlHash = size_t;
SEQUENCE_CHECKER(sequence_checker_);
// Returns the desired favicon sizes for the current platform.
static std::vector<int> GetDesiredFaviconSizesInPixels();
// The TaskRunner to which FaviconServiceBackend tasks are posted. Nullptr
// once Cleanup() is called.
scoped_refptr<base::SequencedTaskRunner> backend_task_runner_;
......
// 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 "weblayer/browser/favicon/test_favicon_fetcher_delegate.h"
#include "base/run_loop.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace weblayer {
TestFaviconFetcherDelegate::TestFaviconFetcherDelegate() = default;
TestFaviconFetcherDelegate::~TestFaviconFetcherDelegate() = default;
void TestFaviconFetcherDelegate::WaitForFavicon() {
ASSERT_EQ(nullptr, run_loop_.get());
run_loop_ = std::make_unique<base::RunLoop>();
run_loop_->Run();
run_loop_.reset();
}
void TestFaviconFetcherDelegate::ClearLastImage() {
last_image_ = gfx::Image();
on_favicon_changed_call_count_ = 0;
}
void TestFaviconFetcherDelegate::OnFaviconChanged(const gfx::Image& image) {
last_image_ = image;
++on_favicon_changed_call_count_;
if (run_loop_)
run_loop_->Quit();
}
} // namespace weblayer
// 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.
#ifndef WEBLAYER_BROWSER_FAVICON_TEST_FAVICON_FETCHER_DELEGATE_H_
#define WEBLAYER_BROWSER_FAVICON_TEST_FAVICON_FETCHER_DELEGATE_H_
#include <memory>
#include "ui/gfx/image/image.h"
#include "weblayer/public/favicon_fetcher_delegate.h"
namespace base {
class RunLoop;
}
namespace weblayer {
// Records calls to OnFaviconChanged().
class TestFaviconFetcherDelegate : public FaviconFetcherDelegate {
public:
TestFaviconFetcherDelegate();
TestFaviconFetcherDelegate(const TestFaviconFetcherDelegate&) = delete;
TestFaviconFetcherDelegate& operator=(const TestFaviconFetcherDelegate&) =
delete;
~TestFaviconFetcherDelegate() override;
void WaitForFavicon();
void ClearLastImage();
const gfx::Image& last_image() const { return last_image_; }
int on_favicon_changed_call_count() const {
return on_favicon_changed_call_count_;
}
// FaviconFetcherDelegate:
void OnFaviconChanged(const gfx::Image& image) override;
private:
std::unique_ptr<base::RunLoop> run_loop_;
gfx::Image last_image_;
int on_favicon_changed_call_count_ = 0;
};
} // namespace weblayer
#endif // WEBLAYER_BROWSER_FAVICON_TEST_FAVICON_FETCHER_DELEGATE_H_
......@@ -2,26 +2,61 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/test/bind_test_util.h"
#include "build/build_config.h"
#include "ui/gfx/image/image_unittest_util.h"
#include "weblayer/browser/favicon/favicon_fetcher_impl.h"
#include "weblayer/browser/favicon/test_favicon_fetcher_delegate.h"
#include "weblayer/browser/profile_impl.h"
#include "weblayer/browser/tab_impl.h"
#include "weblayer/shell/browser/shell.h"
#include "weblayer/test/weblayer_browser_test.h"
#include "weblayer/test/weblayer_browser_test_utils.h"
namespace weblayer {
using ProfileBrowsertest = WebLayerBrowserTest;
using ProfileBrowserTest = WebLayerBrowserTest;
// TODO(crbug.com/654704): Android does not support PRE_ tests.
#if !defined(OS_ANDROID)
// UKM enabling via Profile persists across restarts.
IN_PROC_BROWSER_TEST_F(ProfileBrowsertest, PRE_PersistUKM) {
IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, PRE_PersistUKM) {
GetProfile()->SetBooleanSetting(SettingType::UKM_ENABLED, true);
}
IN_PROC_BROWSER_TEST_F(ProfileBrowsertest, PersistUKM) {
IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, PersistUKM) {
ASSERT_TRUE(GetProfile()->GetBooleanSetting(SettingType::UKM_ENABLED));
}
#endif // !defined(OS_ANDROID)
IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, GetCachedFaviconForPageUrl) {
// Navigation to a page with a favicon.
ASSERT_TRUE(embedded_test_server()->Start());
TestFaviconFetcherDelegate fetcher_delegate;
auto fetcher = shell()->tab()->CreateFaviconFetcher(&fetcher_delegate);
const GURL url =
embedded_test_server()->GetURL("/simple_page_with_favicon.html");
NavigateAndWaitForCompletion(url, shell());
fetcher_delegate.WaitForFavicon();
EXPECT_FALSE(fetcher_delegate.last_image().IsEmpty());
EXPECT_EQ(1, fetcher_delegate.on_favicon_changed_call_count());
// Request the favicon.
base::RunLoop run_loop;
static_cast<TabImpl*>(shell()->tab())
->profile()
->GetCachedFaviconForPageUrl(
url, base::BindLambdaForTesting([&](gfx::Image image) {
// The last parameter is the max difference allowed for each color
// component. As the image is encoded before saving to disk some
// variance is expected.
EXPECT_TRUE(gfx::test::AreImagesClose(
image, fetcher_delegate.last_image(), 10));
run_loop.Quit();
}));
run_loop.Run();
}
} // namespace weblayer
......@@ -33,6 +33,8 @@
#include "weblayer/browser/browser_list.h"
#include "weblayer/browser/browsing_data_remover_delegate.h"
#include "weblayer/browser/cookie_manager_impl.h"
#include "weblayer/browser/favicon/favicon_service_impl.h"
#include "weblayer/browser/favicon/favicon_service_impl_factory.h"
#include "weblayer/browser/persistence/browser_persister_file_utils.h"
#include "weblayer/browser/tab_impl.h"
......@@ -567,6 +569,19 @@ bool ProfileImpl::GetBooleanSetting(SettingType type) {
NOTREACHED();
}
void ProfileImpl::GetCachedFaviconForPageUrl(
const GURL& page_url,
base::OnceCallback<void(gfx::Image)> callback) {
auto* service = FaviconServiceImplFactory::GetForProfile(this);
if (!service) {
std::move(callback).Run({});
return;
}
service->GetFaviconForPageUrl(page_url, std::move(callback),
&cancelable_task_tracker_);
}
int ProfileImpl::GetNumberOfBrowsers() {
const auto& browsers = BrowserList::GetInstance()->browsers();
return std::count_if(browsers.begin(), browsers.end(),
......
......@@ -10,6 +10,7 @@
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/task/cancelable_task_tracker.h"
#include "build/build_config.h"
#include "weblayer/browser/i18n_util.h"
#include "weblayer/browser/profile_disk_operations.h"
......@@ -90,6 +91,9 @@ class ProfileImpl : public Profile {
base::flat_set<std::string> ids) override;
void SetBooleanSetting(SettingType type, bool value) override;
bool GetBooleanSetting(SettingType type) override;
void GetCachedFaviconForPageUrl(
const GURL& page_url,
base::OnceCallback<void(gfx::Image)> callback) override;
#if defined(OS_ANDROID)
ProfileImpl(JNIEnv* env,
......@@ -162,6 +166,12 @@ class ProfileImpl : public Profile {
base::android::ScopedJavaGlobalRef<jobject> java_profile_;
#endif
// The typical pattern for CancelableTaskTrackers is to have the caller
// supply one. This code is predominantly called from the Java side, where
// CancelableTaskTracker isn't applicable. Because of this, the
// CancelableTaskTracker is owned by Profile.
base::CancelableTaskTracker cancelable_task_tracker_;
DISALLOW_COPY_AND_ASSIGN(ProfileImpl);
};
......
......@@ -16,6 +16,12 @@ namespace base {
class FilePath;
}
namespace gfx {
class Image;
}
class GURL;
namespace weblayer {
class CookieManager;
class DownloadDelegate;
......@@ -88,6 +94,14 @@ class Profile {
// Get the boolean value of the given setting type.
virtual bool GetBooleanSetting(SettingType type) = 0;
// Returns the cached favicon for the specified url. Off the record profiles
// do not cache favicons. If this is called on an off-the-record profile
// the callback is run with an empty image synchronously. The returned image
// matches that returned by FaviconFetcher.
virtual void GetCachedFaviconForPageUrl(
const GURL& page_url,
base::OnceCallback<void(gfx::Image)> callback) = 0;
};
} // namespace weblayer
......
......@@ -120,6 +120,7 @@ test("weblayer_browsertests") {
"//net:test_support",
"//testing/gtest",
"//ui/base",
"//ui/gfx:test_support",
"//weblayer/shell:weblayer_shell_lib",
]
......@@ -131,6 +132,8 @@ test("weblayer_browsertests") {
"../browser/download_browsertest.cc",
"../browser/errorpage_browsertest.cc",
"../browser/favicon/favicon_fetcher_browsertest.cc",
"../browser/favicon/test_favicon_fetcher_delegate.cc",
"../browser/favicon/test_favicon_fetcher_delegate.h",
"../browser/google_accounts_browsertest.cc",
"../browser/js_communication/web_message_browsertest.cc",
"../browser/navigation_browsertest.cc",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment