favicon_service_impl.cc 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "weblayer/browser/favicon/favicon_service_impl.h"
  5. #include <stddef.h>
  6. #include <vector>
  7. #include "base/bind.h"
  8. #include "base/files/file_path.h"
  9. #include "base/hash/hash.h"
  10. #include "base/task/task_traits.h"
  11. #include "base/task/thread_pool.h"
  12. #include "build/build_config.h"
  13. #include "components/favicon_base/favicon_util.h"
  14. #include "components/favicon_base/select_favicon_frames.h"
  15. #include "content/public/common/url_constants.h"
  16. #include "third_party/skia/include/core/SkBitmap.h"
  17. #include "ui/gfx/favicon_size.h"
  18. #include "url/gurl.h"
  19. #include "weblayer/browser/favicon/favicon_backend_wrapper.h"
  20. #include "weblayer/browser/favicon/favicon_service_impl_observer.h"
  21. namespace weblayer {
  22. namespace {
  23. bool CanAddUrl(const GURL& url) {
  24. if (!url.is_valid())
  25. return false;
  26. if (url.SchemeIs(url::kJavaScriptScheme) || url.SchemeIs(url::kAboutScheme) ||
  27. url.SchemeIs(url::kContentScheme) ||
  28. url.SchemeIs(content::kChromeDevToolsScheme) ||
  29. url.SchemeIs(content::kChromeUIScheme) ||
  30. url.SchemeIs(content::kViewSourceScheme)) {
  31. return false;
  32. }
  33. return true;
  34. }
  35. // Returns the IconTypeSet for the current platform. This matches the set
  36. // of favicon types that are requested for the platform (see
  37. // FaviconDriverImpl).
  38. favicon_base::IconTypeSet GetIconTypeSet() {
  39. #if BUILDFLAG(IS_ANDROID)
  40. return {favicon_base::IconType::kFavicon, favicon_base::IconType::kTouchIcon,
  41. favicon_base::IconType::kTouchPrecomposedIcon,
  42. favicon_base::IconType::kWebManifestIcon};
  43. #else
  44. return {favicon_base::IconType::kFavicon};
  45. #endif
  46. }
  47. int GetDesiredFaviconSizeInDips() {
  48. #if BUILDFLAG(IS_ANDROID)
  49. // This is treatest as the largest available icon.
  50. return 0;
  51. #else
  52. return gfx::kFaviconSize;
  53. #endif
  54. }
  55. void OnGotFaviconsForPageUrl(
  56. int desired_size_in_dip,
  57. base::OnceCallback<void(gfx::Image)> callback,
  58. std::vector<favicon_base::FaviconRawBitmapResult> results) {
  59. favicon_base::FaviconImageResult image_result;
  60. image_result.image = favicon_base::SelectFaviconFramesFromPNGs(
  61. results, favicon_base::GetFaviconScales(), desired_size_in_dip);
  62. favicon_base::SetFaviconColorSpace(&image_result.image);
  63. std::move(callback).Run(image_result.image);
  64. }
  65. } // namespace
  66. FaviconServiceImpl::FaviconServiceImpl() = default;
  67. FaviconServiceImpl::~FaviconServiceImpl() {
  68. backend_task_runner_->PostTask(
  69. FROM_HERE,
  70. base::BindOnce(&FaviconBackendWrapper::Shutdown, std::move(backend_)));
  71. }
  72. void FaviconServiceImpl::Init(const base::FilePath& db_path) {
  73. if (!backend_task_runner_) {
  74. // BLOCK_SHUTDOWN matches that of HistoryService. It's done in hopes of
  75. // preventing database corruption.
  76. backend_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
  77. {base::MayBlock(), base::WithBaseSyncPrimitives(),
  78. base::TaskPriority::USER_BLOCKING,
  79. base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
  80. }
  81. backend_ = base::MakeRefCounted<FaviconBackendWrapper>(backend_task_runner_);
  82. backend_task_runner_->PostTask(
  83. FROM_HERE,
  84. base::BindOnce(&FaviconBackendWrapper::Init, backend_, db_path));
  85. }
  86. void FaviconServiceImpl::DeleteAndRecreateDatabase(base::OnceClosure callback) {
  87. backend_task_runner_->PostTaskAndReply(
  88. FROM_HERE,
  89. base::BindOnce(&FaviconBackendWrapper::DeleteAndRecreateDatabase,
  90. backend_),
  91. std::move(callback));
  92. }
  93. base::CancelableTaskTracker::TaskId FaviconServiceImpl::GetFaviconForPageUrl(
  94. const GURL& page_url,
  95. base::OnceCallback<void(gfx::Image)> callback,
  96. base::CancelableTaskTracker* tracker) {
  97. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  98. // The arguments supplied to this function should return an image matching
  99. // that returned by FaviconFetcher.
  100. return tracker->PostTaskAndReplyWithResult(
  101. backend_task_runner_.get(), FROM_HERE,
  102. base::BindOnce(&FaviconBackendWrapper::GetFaviconsForUrl, backend_,
  103. page_url, GetIconTypeSet(),
  104. GetDesiredFaviconSizesInPixels()),
  105. base::BindOnce(&OnGotFaviconsForPageUrl, GetDesiredFaviconSizeInDips(),
  106. std::move(callback)));
  107. }
  108. base::CancelableTaskTracker::TaskId
  109. FaviconServiceImpl::GetLargestRawFaviconForPageURL(
  110. const GURL& page_url,
  111. const std::vector<favicon_base::IconTypeSet>& icon_types,
  112. int minimum_size_in_pixels,
  113. favicon_base::FaviconRawBitmapCallback callback,
  114. base::CancelableTaskTracker* tracker) {
  115. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  116. return tracker->PostTaskAndReplyWithResult(
  117. backend_task_runner_.get(), FROM_HERE,
  118. base::BindOnce(&FaviconBackendWrapper::GetLargestFaviconForUrl, backend_,
  119. page_url, icon_types, minimum_size_in_pixels),
  120. std::move(callback));
  121. }
  122. base::CancelableTaskTracker::TaskId FaviconServiceImpl::GetFaviconForPageURL(
  123. const GURL& page_url,
  124. const favicon_base::IconTypeSet& icon_types,
  125. int desired_size_in_dip,
  126. favicon_base::FaviconResultsCallback callback,
  127. base::CancelableTaskTracker* tracker) {
  128. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  129. return tracker->PostTaskAndReplyWithResult(
  130. backend_task_runner_.get(), FROM_HERE,
  131. base::BindOnce(&FaviconBackendWrapper::GetFaviconsForUrl, backend_,
  132. page_url, icon_types,
  133. GetPixelSizesForFaviconScales(desired_size_in_dip)),
  134. std::move(callback));
  135. }
  136. void FaviconServiceImpl::SetFaviconOutOfDateForPage(const GURL& page_url) {
  137. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  138. backend_task_runner_->PostTask(
  139. FROM_HERE,
  140. base::BindOnce(&FaviconBackendWrapper::SetFaviconsOutOfDateForPage,
  141. backend_, page_url));
  142. }
  143. void FaviconServiceImpl::SetFavicons(const base::flat_set<GURL>& page_urls,
  144. const GURL& icon_url,
  145. favicon_base::IconType icon_type,
  146. const gfx::Image& image) {
  147. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  148. base::flat_set<GURL> page_urls_to_save;
  149. page_urls_to_save.reserve(page_urls.capacity());
  150. for (const GURL& page_url : page_urls) {
  151. if (CanAddUrl(page_url))
  152. page_urls_to_save.insert(page_url);
  153. }
  154. if (page_urls_to_save.empty())
  155. return;
  156. backend_task_runner_->PostTask(
  157. FROM_HERE, base::BindOnce(&FaviconBackendWrapper::SetFavicons, backend_,
  158. page_urls_to_save, icon_type, icon_url,
  159. ExtractSkBitmapsToStore(image)));
  160. }
  161. void FaviconServiceImpl::CloneFaviconMappingsForPages(
  162. const GURL& page_url_to_read,
  163. const favicon_base::IconTypeSet& icon_types,
  164. const base::flat_set<GURL>& page_urls_to_write) {
  165. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  166. backend_task_runner_->PostTask(
  167. FROM_HERE,
  168. base::BindOnce(&FaviconBackendWrapper::CloneFaviconMappingsForPages,
  169. backend_, page_url_to_read, icon_types,
  170. page_urls_to_write));
  171. }
  172. base::CancelableTaskTracker::TaskId FaviconServiceImpl::GetFavicon(
  173. const GURL& icon_url,
  174. favicon_base::IconType icon_type,
  175. int desired_size_in_dip,
  176. favicon_base::FaviconResultsCallback callback,
  177. base::CancelableTaskTracker* tracker) {
  178. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  179. return tracker->PostTaskAndReplyWithResult(
  180. backend_task_runner_.get(), FROM_HERE,
  181. base::BindOnce(&FaviconBackendWrapper::GetFavicon, backend_, icon_url,
  182. icon_type,
  183. GetPixelSizesForFaviconScales(desired_size_in_dip)),
  184. std::move(callback));
  185. }
  186. base::CancelableTaskTracker::TaskId
  187. FaviconServiceImpl::UpdateFaviconMappingsAndFetch(
  188. const base::flat_set<GURL>& page_urls,
  189. const GURL& icon_url,
  190. favicon_base::IconType icon_type,
  191. int desired_size_in_dip,
  192. favicon_base::FaviconResultsCallback callback,
  193. base::CancelableTaskTracker* tracker) {
  194. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  195. return tracker->PostTaskAndReplyWithResult(
  196. backend_task_runner_.get(), FROM_HERE,
  197. base::BindOnce(&FaviconBackendWrapper::UpdateFaviconMappingsAndFetch,
  198. backend_, page_urls, icon_url, icon_type,
  199. GetPixelSizesForFaviconScales(desired_size_in_dip)),
  200. std::move(callback));
  201. }
  202. void FaviconServiceImpl::DeleteFaviconMappings(
  203. const base::flat_set<GURL>& page_urls,
  204. favicon_base::IconType icon_type) {
  205. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  206. backend_task_runner_->PostTask(
  207. FROM_HERE, base::BindOnce(&FaviconBackendWrapper::DeleteFaviconMappings,
  208. backend_, page_urls, icon_type));
  209. }
  210. void FaviconServiceImpl::UnableToDownloadFavicon(const GURL& icon_url) {
  211. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  212. missing_favicon_urls_.insert(base::FastHash(icon_url.spec()));
  213. if (observer_)
  214. observer_->OnUnableToDownloadFavicon();
  215. }
  216. void FaviconServiceImpl::ClearUnableToDownloadFavicons() {
  217. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  218. missing_favicon_urls_.clear();
  219. }
  220. bool FaviconServiceImpl::WasUnableToDownloadFavicon(
  221. const GURL& icon_url) const {
  222. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  223. MissingFaviconUrlHash url_hash = base::FastHash(icon_url.spec());
  224. return missing_favicon_urls_.find(url_hash) != missing_favicon_urls_.end();
  225. }
  226. // static
  227. std::vector<int> FaviconServiceImpl::GetDesiredFaviconSizesInPixels() {
  228. return GetPixelSizesForFaviconScales(GetDesiredFaviconSizeInDips());
  229. }
  230. } // namespace weblayer