favicon_backend_wrapper.cc 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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_backend_wrapper.h"
  5. #include "base/files/file_util.h"
  6. #include "base/logging.h"
  7. #include "base/task/sequenced_task_runner.h"
  8. #include "components/favicon/core/favicon_backend.h"
  9. #include "components/favicon/core/favicon_database.h"
  10. namespace weblayer {
  11. // Removing out of date entries can be costly. To avoid blocking the thread
  12. // this code runs on, the work is potentially throttled. Specifically at
  13. // most |kMaxNumberOfEntriesToRemoveAtATime| are removed during a single call.
  14. // If |kMaxNumberOfEntriesToRemoveAtATime| are removed, then there may be more
  15. // entries that can be removed, so the timer is restarted with a shorter time
  16. // out (|kTimeDeltaForRunningExpireWithRemainingWork|).
  17. constexpr base::TimeDelta kTimeDeltaForRunningExpireNoRemainingWork =
  18. base::Hours(1);
  19. constexpr int kMaxNumberOfEntriesToRemoveAtATime = 100;
  20. FaviconBackendWrapper::FaviconBackendWrapper(
  21. scoped_refptr<base::SequencedTaskRunner> task_runner)
  22. : base::RefCountedDeleteOnSequence<FaviconBackendWrapper>(task_runner),
  23. task_runner_(task_runner) {}
  24. void FaviconBackendWrapper::Init(const base::FilePath& db_path) {
  25. db_path_ = db_path;
  26. favicon_backend_ = favicon::FaviconBackend::Create(db_path, this);
  27. if (!favicon_backend_) {
  28. LOG(WARNING) << "Could not initialize the favicon database.";
  29. // The favicon db is not critical. On failure initializing try deleting
  30. // the file and repeating. Note that FaviconDatabase already tries to
  31. // initialize twice.
  32. base::DeleteFile(db_path);
  33. favicon_backend_ = favicon::FaviconBackend::Create(db_path, this);
  34. if (!favicon_backend_) {
  35. LOG(WARNING) << "Could not initialize db second time, giving up.";
  36. return;
  37. }
  38. }
  39. expire_timer_.Start(FROM_HERE, kTimeDeltaForRunningExpireWithRemainingWork,
  40. this, &FaviconBackendWrapper::OnExpireTimerFired);
  41. }
  42. void FaviconBackendWrapper::Shutdown() {
  43. // Ensures there isn't a reference to this in the task runner (by way of the
  44. // task the timer posts).
  45. commit_timer_.Stop();
  46. expire_timer_.Stop();
  47. }
  48. void FaviconBackendWrapper::DeleteAndRecreateDatabase() {
  49. Shutdown();
  50. favicon_backend_.reset();
  51. base::DeleteFile(db_path_);
  52. Init(db_path_);
  53. }
  54. std::vector<favicon_base::FaviconRawBitmapResult>
  55. FaviconBackendWrapper::GetFaviconsForUrl(
  56. const GURL& page_url,
  57. const favicon_base::IconTypeSet& icon_types,
  58. const std::vector<int>& desired_sizes) {
  59. if (!favicon_backend_)
  60. return {};
  61. return favicon_backend_->GetFaviconsForUrl(page_url, icon_types,
  62. desired_sizes,
  63. /* fallback_to_host */ false);
  64. }
  65. favicon_base::FaviconRawBitmapResult
  66. FaviconBackendWrapper::GetLargestFaviconForUrl(
  67. const GURL& page_url,
  68. const std::vector<favicon_base::IconTypeSet>& icon_types_list,
  69. int minimum_size_in_pixels) {
  70. if (!favicon_backend_)
  71. return {};
  72. return favicon_backend_->GetLargestFaviconForUrl(page_url, icon_types_list,
  73. minimum_size_in_pixels);
  74. }
  75. void FaviconBackendWrapper::SetFaviconsOutOfDateForPage(const GURL& page_url) {
  76. if (favicon_backend_ &&
  77. favicon_backend_->SetFaviconsOutOfDateForPage(page_url)) {
  78. ScheduleCommit();
  79. }
  80. }
  81. void FaviconBackendWrapper::SetFavicons(const base::flat_set<GURL>& page_urls,
  82. favicon_base::IconType icon_type,
  83. const GURL& icon_url,
  84. const std::vector<SkBitmap>& bitmaps) {
  85. if (favicon_backend_ &&
  86. favicon_backend_
  87. ->SetFavicons(page_urls, icon_type, icon_url, bitmaps,
  88. favicon::FaviconBitmapType::ON_VISIT)
  89. .did_change_database()) {
  90. ScheduleCommit();
  91. }
  92. }
  93. void FaviconBackendWrapper::CloneFaviconMappingsForPages(
  94. const GURL& page_url_to_read,
  95. const favicon_base::IconTypeSet& icon_types,
  96. const base::flat_set<GURL>& page_urls_to_write) {
  97. if (!favicon_backend_)
  98. return;
  99. std::set<GURL> changed_urls = favicon_backend_->CloneFaviconMappingsForPages(
  100. {page_url_to_read}, icon_types, page_urls_to_write);
  101. if (!changed_urls.empty())
  102. ScheduleCommit();
  103. }
  104. std::vector<favicon_base::FaviconRawBitmapResult>
  105. FaviconBackendWrapper::GetFavicon(const GURL& icon_url,
  106. favicon_base::IconType icon_type,
  107. const std::vector<int>& desired_sizes) {
  108. return UpdateFaviconMappingsAndFetch({}, icon_url, icon_type, desired_sizes);
  109. }
  110. std::vector<favicon_base::FaviconRawBitmapResult>
  111. FaviconBackendWrapper::UpdateFaviconMappingsAndFetch(
  112. const base::flat_set<GURL>& page_urls,
  113. const GURL& icon_url,
  114. favicon_base::IconType icon_type,
  115. const std::vector<int>& desired_sizes) {
  116. if (!favicon_backend_)
  117. return {};
  118. auto result = favicon_backend_->UpdateFaviconMappingsAndFetch(
  119. page_urls, icon_url, icon_type, desired_sizes);
  120. if (!result.updated_page_urls.empty())
  121. ScheduleCommit();
  122. return result.bitmap_results;
  123. }
  124. void FaviconBackendWrapper::DeleteFaviconMappings(
  125. const base::flat_set<GURL>& page_urls,
  126. favicon_base::IconType icon_type) {
  127. if (!favicon_backend_)
  128. return;
  129. auto deleted_page_urls =
  130. favicon_backend_->DeleteFaviconMappings(page_urls, icon_type);
  131. if (!deleted_page_urls.empty())
  132. ScheduleCommit();
  133. }
  134. std::vector<GURL> FaviconBackendWrapper::GetCachedRecentRedirectsForPage(
  135. const GURL& page_url) {
  136. // By only returning |page_url| this code won't set the favicon on redirects.
  137. // If that becomes necessary, we would need this class to know about
  138. // redirects. Chrome does this by way of HistoryService remembering redirects
  139. // for recent pages. See |HistoryBackend::recent_redirects_|.
  140. return {page_url};
  141. }
  142. FaviconBackendWrapper::~FaviconBackendWrapper() = default;
  143. void FaviconBackendWrapper::ScheduleCommit() {
  144. if (!commit_timer_.IsRunning()) {
  145. // 10 seconds matches that of HistoryBackend.
  146. commit_timer_.Start(FROM_HERE, base::Seconds(10), this,
  147. &FaviconBackendWrapper::Commit);
  148. }
  149. }
  150. void FaviconBackendWrapper::Commit() {
  151. if (favicon_backend_)
  152. favicon_backend_->Commit();
  153. }
  154. void FaviconBackendWrapper::OnExpireTimerFired() {
  155. if (!favicon_backend_)
  156. return;
  157. // See comments above |kTimeDeltaForRunningExpireNoRemainingWork| for a
  158. // description of this logic.
  159. favicon::FaviconDatabase* db = favicon_backend_->db();
  160. auto icon_ids = db->GetFaviconsLastUpdatedBefore(
  161. base::Time::Now() - kTimeDeltaWhenEntriesAreRemoved,
  162. kMaxNumberOfEntriesToRemoveAtATime);
  163. for (favicon_base::FaviconID icon_id : icon_ids) {
  164. db->DeleteFavicon(icon_id);
  165. db->DeleteIconMappingsForFaviconId(icon_id);
  166. }
  167. if (!icon_ids.empty())
  168. Commit();
  169. const base::TimeDelta delta =
  170. icon_ids.size() == kMaxNumberOfEntriesToRemoveAtATime
  171. ? kTimeDeltaForRunningExpireWithRemainingWork
  172. : kTimeDeltaForRunningExpireNoRemainingWork;
  173. expire_timer_.Start(FROM_HERE, delta, this,
  174. &FaviconBackendWrapper::OnExpireTimerFired);
  175. }
  176. } // namespace weblayer