Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1457)

Unified Diff: chrome/browser/history/history_backend.cc

Issue 10802066: Adds support for saving favicon size into history database. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/history/history_backend.h ('k') | chrome/browser/history/history_backend_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/history/history_backend.cc
diff --git a/chrome/browser/history/history_backend.cc b/chrome/browser/history/history_backend.cc
index 3c1ecfd67d3f1908ffdfc3cd3305e8fc19d4bbce..6e29984aa42d0d88eeeff59cf691bf31535bc51f 100644
--- a/chrome/browser/history/history_backend.cc
+++ b/chrome/browser/history/history_backend.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/history/history_backend.h"
+#include <algorithm>
#include <list>
#include <map>
#include <set>
@@ -26,6 +27,7 @@
#include "chrome/browser/history/history_publisher.h"
#include "chrome/browser/history/in_memory_history_backend.h"
#include "chrome/browser/history/page_usage_data.h"
+#include "chrome/browser/history/select_favicon_frames.h"
#include "chrome/browser/history/top_sites.h"
#include "chrome/browser/history/visit_filter.h"
#include "chrome/common/chrome_constants.h"
@@ -94,6 +96,14 @@ static const int kMaxRedirectCount = 32;
// and is archived.
static const int kArchiveDaysThreshold = 90;
+// The maximum number of icons URLs per page which can be stored in the
+// thumbnail database.
+static const size_t kMaxFaviconsPerPage = 8;
+
+// The maximum number of bitmaps for a single icon URL which can be stored in
+// the thumbnail database.
+static const size_t kMaxFaviconBitmapsPerIconURL = 8;
+
// Converts from PageUsageData to MostVisitedURL. |redirects| is a
// list of redirects for this URL. Empty list means no redirects.
MostVisitedURL MakeMostVisitedURL(const PageUsageData& page_data,
@@ -1769,21 +1779,112 @@ bool HistoryBackend::GetThumbnailFromOlderRedirect(
return success;
}
-void HistoryBackend::GetFavicon(scoped_refptr<GetFaviconRequest> request,
- const GURL& icon_url,
- int icon_types) {
- UpdateFaviconMappingAndFetchImpl(NULL, icon_url, request, icon_types);
+void HistoryBackend::GetFavicons(
+ scoped_refptr<GetFaviconRequest> request,
+ const std::vector<GURL>& icon_urls,
+ int icon_types,
+ int desired_size_in_dip,
+ const std::vector<ui::ScaleFactor>& desired_scale_factors) {
+ UpdateFaviconMappingsAndFetchImpl(request, NULL, icon_urls, icon_types,
+ desired_size_in_dip, desired_scale_factors);
+}
+
+void HistoryBackend::GetFaviconsForURL(
+ scoped_refptr<GetFaviconRequest> request,
+ const GURL& page_url,
+ int icon_types,
+ int desired_size_in_dip,
+ const std::vector<ui::ScaleFactor>& desired_scale_factors) {
+ if (request->canceled())
+ return;
+
+ std::vector<FaviconBitmapResult> favicon_bitmap_results;
+ IconURLSizesMap icon_url_sizes;
+
+ // Get results from DB.
+ GetFaviconsFromDB(page_url, icon_types, desired_size_in_dip,
+ desired_scale_factors, &favicon_bitmap_results, &icon_url_sizes);
+
+ request->ForwardResult(request->handle(), favicon_bitmap_results,
+ icon_url_sizes);
+}
+
+void HistoryBackend::GetFaviconForID(scoped_refptr<GetFaviconRequest> request,
+ FaviconID favicon_id,
+ int desired_size_in_dip,
+ ui::ScaleFactor desired_scale_factor) {
+ if (request->canceled())
+ return;
+
+ std::vector<FaviconID> favicon_ids;
+ favicon_ids.push_back(favicon_id);
+ std::vector<ui::ScaleFactor> desired_scale_factors;
+ desired_scale_factors.push_back(desired_scale_factor);
+
+ // Get results from DB.
+ std::vector<FaviconBitmapResult> favicon_bitmap_results;
+ GetFaviconBitmapResultsForBestMatch(favicon_ids, desired_size_in_dip,
+ desired_scale_factors, &favicon_bitmap_results);
+
+ IconURLSizesMap icon_url_sizes;
+ BuildIconURLSizesMap(favicon_ids, &icon_url_sizes);
+
+ request->ForwardResult(request->handle(), favicon_bitmap_results,
+ icon_url_sizes);
}
-void HistoryBackend::UpdateFaviconMappingAndFetch(
+void HistoryBackend::UpdateFaviconMappingsAndFetch(
scoped_refptr<GetFaviconRequest> request,
const GURL& page_url,
- const GURL& icon_url,
- IconType icon_type) {
- UpdateFaviconMappingAndFetchImpl(&page_url, icon_url, request, icon_type);
+ const std::vector<GURL>& icon_urls,
+ int icon_types,
+ int desired_size_in_dip,
+ const std::vector<ui::ScaleFactor>& desired_scale_factors) {
+ UpdateFaviconMappingsAndFetchImpl(request, &page_url, icon_urls, icon_types,
+ desired_size_in_dip, desired_scale_factors);
}
-void HistoryBackend::SetFaviconOutOfDateForPage(const GURL& page_url) {
+void HistoryBackend::SetFavicons(
+ const GURL& page_url,
+ IconType icon_type,
+ const std::vector<FaviconBitmapData>& favicon_bitmap_data,
+ const IconURLSizesMap& icon_url_sizes) {
+ if (!thumbnail_db_.get() || !db_.get())
+ return;
+
+ DCHECK(ValidateSetFaviconsParams(favicon_bitmap_data, icon_url_sizes));
+
+ // Build map of FaviconBitmapData for each icon url.
+ typedef std::map<GURL, std::vector<FaviconBitmapData> >
+ BitmapDataByIconURL;
+ BitmapDataByIconURL grouped_by_icon_url;
+ for (size_t i = 0; i < favicon_bitmap_data.size(); ++i) {
+ const GURL& icon_url = favicon_bitmap_data[i].icon_url;
+ grouped_by_icon_url[icon_url].push_back(favicon_bitmap_data[i]);
+ }
+
+ std::vector<FaviconID> icon_ids;
+ for (IconURLSizesMap::const_iterator it = icon_url_sizes.begin();
+ it != icon_url_sizes.end(); ++it) {
+ const GURL& icon_url = it->first;
+ FaviconID icon_id =
+ thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type, NULL);
+ if (icon_id)
+ SetFaviconSizes(icon_id, it->second);
+ else
+ icon_id = thumbnail_db_->AddFavicon(icon_url, icon_type, it->second);
+ icon_ids.push_back(icon_id);
+
+ BitmapDataByIconURL::iterator grouped_by_icon_url_it =
+ grouped_by_icon_url.find(icon_url);
+ if (grouped_by_icon_url_it != grouped_by_icon_url.end())
+ SetFaviconBitmaps(icon_id, grouped_by_icon_url_it->second);
+ }
+
+ SetFaviconMappingsForPageAndRedirects(page_url, icon_type, icon_ids);
+}
+
+void HistoryBackend::SetFaviconsOutOfDateForPage(const GURL& page_url) {
std::vector<IconMapping> icon_mappings;
if (!thumbnail_db_.get() ||
@@ -1798,8 +1899,8 @@ void HistoryBackend::SetFaviconOutOfDateForPage(const GURL& page_url) {
ScheduleCommit();
}
-void HistoryBackend::CloneFavicon(const GURL& old_page_url,
- const GURL& new_page_url) {
+void HistoryBackend::CloneFavicons(const GURL& old_page_url,
+ const GURL& new_page_url) {
if (!thumbnail_db_.get())
return;
@@ -1877,104 +1978,258 @@ void HistoryBackend::SetImportedFavicons(
}
}
-void HistoryBackend::UpdateFaviconMappingAndFetchImpl(
- const GURL* page_url,
- const GURL& icon_url,
+void HistoryBackend::UpdateFaviconMappingsAndFetchImpl(
scoped_refptr<GetFaviconRequest> request,
- int icon_types) {
- // Check only a single type was given when the page_url was specified.
- DCHECK(!page_url || (page_url && (icon_types == FAVICON ||
- icon_types == TOUCH_ICON || icon_types == TOUCH_PRECOMPOSED_ICON)));
-
- if (request->canceled())
+ const GURL* page_url,
+ const std::vector<GURL>& icon_urls,
+ int icon_types,
+ int desired_size_in_dip,
+ const std::vector<ui::ScaleFactor>& desired_scale_factors) {
+ // If |page_url| is specified, |icon_types| must be either a single icon
+ // type or icon types which are equivalent.
+ DCHECK(!page_url ||
+ icon_types == FAVICON ||
+ icon_types == TOUCH_ICON ||
+ icon_types == TOUCH_PRECOMPOSED_ICON ||
+ icon_types == (TOUCH_ICON | TOUCH_PRECOMPOSED_ICON));
+
+ if (request->canceled() || !thumbnail_db_.get())
return;
- std::vector<history::FaviconBitmapResult> favicon_bitmap_results;
+ std::vector<FaviconID> favicon_ids;
- if (thumbnail_db_.get()) {
- IconType icon_type;
- const FaviconID favicon_id =
- thumbnail_db_->GetFaviconIDForFaviconURL(
- icon_url, icon_types, &icon_type);
- if (favicon_id) {
- GetFaviconFromDB(favicon_id, &favicon_bitmap_results);
+ // The icon type for which the mappings will the updated and data will be
+ // returned.
+ IconType selected_icon_type = INVALID_ICON;
+
+ for (size_t i = 0; i < icon_urls.size(); ++i) {
+ const GURL& icon_url = icon_urls[i];
+ IconType icon_type_out;
+ const FaviconID favicon_id = thumbnail_db_->GetFaviconIDForFaviconURL(
+ icon_url, icon_types, &icon_type_out);
- if (page_url)
- SetFaviconMapping(*page_url, favicon_id, icon_type);
+ if (favicon_id) {
+ // Return and update icon mappings only for the largest icon type. As
+ // |icon_urls| is not sorted in terms of icon type, clear |favicon_ids|
+ // if an |icon_url| with a larger icon type is found.
+ if (icon_type_out > selected_icon_type) {
+ selected_icon_type = icon_type_out;
+ favicon_ids.clear();
+ }
+ if (icon_type_out == selected_icon_type)
+ favicon_ids.push_back(favicon_id);
}
- // else case, haven't cached entry yet. Caller is responsible for
- // downloading the favicon and invoking SetFavicon.
}
- // TODO(pkotwicz): Pass map of |icon_url| to the sizes available from the web
- // at |icon_url| instead of an empty map.
- request->ForwardResult(request->handle(), favicon_bitmap_results,
- IconURLSizesMap());
-}
-void HistoryBackend::GetFaviconForURL(
- scoped_refptr<GetFaviconRequest> request,
- const GURL& page_url,
- int icon_types) {
- if (request->canceled())
- return;
+ if (page_url && !favicon_ids.empty()) {
+ SetFaviconMappingsForPageAndRedirects(*page_url, selected_icon_type,
+ favicon_ids);
+ }
std::vector<FaviconBitmapResult> favicon_bitmap_results;
+ GetFaviconBitmapResultsForBestMatch(favicon_ids, desired_size_in_dip,
+ desired_scale_factors, &favicon_bitmap_results);
+ IconURLSizesMap icon_url_sizes;
+ BuildIconURLSizesMap(favicon_ids, &icon_url_sizes);
- // Get the favicon from DB.
- GetFaviconFromDB(page_url, icon_types, &favicon_bitmap_results);
-
- // TODO(pkotwicz): Pass map of matched icon URLs for |icon_types| to the
- // sizes that each icon URL is available at from the web instead of an
- // empty map.
request->ForwardResult(request->handle(), favicon_bitmap_results,
- IconURLSizesMap());
+ icon_url_sizes);
+}
+
+void HistoryBackend::SetFaviconBitmaps(
+ FaviconID icon_id,
+ const std::vector<FaviconBitmapData>& favicon_bitmap_data) {
+ std::vector<FaviconBitmapIDSize> bitmap_id_sizes;
+ thumbnail_db_->GetFaviconBitmapIDSizes(icon_id, &bitmap_id_sizes);
+
+ // A nested loop is ok because in practice neither |favicon_bitmap_data| nor
+ // |bitmap_id_sizes| will have many elements.
+ for (size_t i = 0; i < favicon_bitmap_data.size(); ++i) {
+ const FaviconBitmapData& bitmap_data_element = favicon_bitmap_data[i];
+ FaviconBitmapID bitmap_id = 0;
+ for (size_t j = 0; j < bitmap_id_sizes.size(); ++j) {
+ if (bitmap_id_sizes[j].pixel_size == bitmap_data_element.pixel_size) {
+ bitmap_id = bitmap_id_sizes[j].bitmap_id;
+ break;
+ }
+ }
+ if (bitmap_id) {
+ thumbnail_db_->SetFaviconBitmap(bitmap_id,
+ bitmap_data_element.bitmap_data, base::Time::Now());
+ } else {
+ thumbnail_db_->AddFaviconBitmap(icon_id, bitmap_data_element.bitmap_data,
+ base::Time::Now(), bitmap_data_element.pixel_size);
+ }
+ }
}
-void HistoryBackend::GetFaviconForID(scoped_refptr<GetFaviconRequest> request,
- FaviconID id) {
- if (request->canceled())
- return;
+bool HistoryBackend::ValidateSetFaviconsParams(
+ const std::vector<FaviconBitmapData>& favicon_bitmap_data,
+ const IconURLSizesMap& icon_url_sizes) const {
+ if (icon_url_sizes.size() > kMaxFaviconsPerPage)
+ return false;
- std::vector<FaviconBitmapResult> favicon_bitmap_results;
+ for (IconURLSizesMap::const_iterator it = icon_url_sizes.begin();
+ it != icon_url_sizes.end(); ++it) {
+ if (it->second.size() > kMaxFaviconBitmapsPerIconURL)
+ return false;
+ }
- // Get the favicon from DB.
- GetFaviconFromDB(id, &favicon_bitmap_results);
+ for (size_t i = 0; i < favicon_bitmap_data.size(); ++i) {
+ if (!favicon_bitmap_data[i].bitmap_data.get())
+ return false;
- // TODO(pkotwicz): Pass map of the matched icon URL to the sizes that it is
- // available from the web instead of an empty map.
- request->ForwardResult(request->handle(), favicon_bitmap_results,
- IconURLSizesMap());
+ IconURLSizesMap::const_iterator it =
+ icon_url_sizes.find(favicon_bitmap_data[i].icon_url);
+ if (it == icon_url_sizes.end())
+ return false;
+
+ const FaviconSizes& favicon_sizes = it->second;
+ FaviconSizes::const_iterator it2 = std::find(favicon_sizes.begin(),
+ favicon_sizes.end(), favicon_bitmap_data[i].pixel_size);
+ if (it2 == favicon_sizes.end())
+ return false;
+ }
+ return true;
+}
+
+void HistoryBackend::SetFaviconSizes(
+ FaviconID icon_id,
+ const FaviconSizes& favicon_sizes) {
+ std::vector<FaviconBitmapIDSize> bitmap_id_sizes;
+ thumbnail_db_->GetFaviconBitmapIDSizes(icon_id, &bitmap_id_sizes);
+
+ // Remove bitmaps whose pixel size is not contained in |favicon_sizes|.
+ for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) {
+ const gfx::Size& pixel_size = bitmap_id_sizes[i].pixel_size;
+ FaviconSizes::const_iterator sizes_it = std::find(favicon_sizes.begin(),
+ favicon_sizes.end(), pixel_size);
+ if (sizes_it == favicon_sizes.end())
+ thumbnail_db_->DeleteFaviconBitmap(bitmap_id_sizes[i].bitmap_id);
+ }
+
+ thumbnail_db_->SetFaviconSizes(icon_id, favicon_sizes);
}
-void HistoryBackend::SetFavicon(
+bool HistoryBackend::GetFaviconsFromDB(
const GURL& page_url,
- const GURL& icon_url,
- scoped_refptr<base::RefCountedMemory> data,
- IconType icon_type) {
- DCHECK(data.get());
- if (!thumbnail_db_.get() || !db_.get())
- return;
+ int icon_types,
+ int desired_size_in_dip,
+ const std::vector<ui::ScaleFactor>& desired_scale_factors,
+ std::vector<FaviconBitmapResult>* favicon_bitmap_results,
+ IconURLSizesMap* icon_url_sizes) {
+ DCHECK(favicon_bitmap_results);
+ DCHECK(icon_url_sizes);
- FaviconID id = thumbnail_db_->GetFaviconIDForFaviconURL(
- icon_url, icon_type, NULL);
- if (!id) {
- id = thumbnail_db_->AddFavicon(icon_url,
- icon_type,
- GetDefaultFaviconSizes(),
- data,
- Time::Now(),
- gfx::Size());
- } else {
- thumbnail_db_->DeleteFaviconBitmapsForFavicon(id);
- thumbnail_db_->AddFaviconBitmap(id, data, Time::Now(), gfx::Size());
+ if (!db_.get() || !thumbnail_db_.get())
+ return false;
+
+ // Time the query.
+ TimeTicks beginning_time = TimeTicks::Now();
+
+ // Get FaviconIDs for |page_url| and one of |icon_types|.
+ std::vector<IconMapping> icon_mappings;
+ thumbnail_db_->GetIconMappingsForPageURL(page_url, icon_types,
+ &icon_mappings);
+ std::vector<FaviconID> favicon_ids;
+ for (size_t i = 0; i < icon_mappings.size(); ++i)
+ favicon_ids.push_back(icon_mappings[i].icon_id);
+
+ // Populate |favicon_bitmap_results| and |icon_url_sizes|.
+ bool success =
+ GetFaviconBitmapResultsForBestMatch(favicon_ids,
+ desired_size_in_dip, desired_scale_factors, favicon_bitmap_results) &&
+ BuildIconURLSizesMap(favicon_ids, icon_url_sizes);
+ UMA_HISTOGRAM_TIMES("History.GetFavIconFromDB", // historical name
+ TimeTicks::Now() - beginning_time);
+ return success && !icon_url_sizes->empty();
+}
+
+bool HistoryBackend::GetFaviconBitmapResultsForBestMatch(
+ const std::vector<FaviconID>& candidate_favicon_ids,
+ int desired_size_in_dip,
+ const std::vector<ui::ScaleFactor>& desired_scale_factors,
+ std::vector<history::FaviconBitmapResult>* favicon_bitmap_results) {
+ favicon_bitmap_results->clear();
+
+ if (candidate_favicon_ids.empty())
+ return true;
+
+ // Find the FaviconID and the FaviconBitmapIDs which best match
+ // |desired_size_in_dip| and |desired_scale_factors|.
+ // TODO(pkotwicz): Select bitmap results from multiple favicons once
+ // content::FaviconStatus supports multiple icon URLs.
+ FaviconID best_favicon_id = 0;
+ std::vector<FaviconBitmapID> best_bitmap_ids;
+ float highest_score = kSelectFaviconFramesInvalidScore;
+ for (size_t i = 0; i < candidate_favicon_ids.size(); ++i) {
+ std::vector<FaviconBitmapIDSize> bitmap_id_sizes;
+ thumbnail_db_->GetFaviconBitmapIDSizes(candidate_favicon_ids[i],
+ &bitmap_id_sizes);
+
+ std::vector<FaviconBitmapID> candidate_bitmap_ids;
+ float score = 0;
+ SelectFaviconBitmapIDs(bitmap_id_sizes,
+ desired_scale_factors,
+ desired_size_in_dip,
+ &candidate_bitmap_ids,
+ &score);
+ if (score > highest_score) {
+ best_favicon_id = candidate_favicon_ids[i],
+ best_bitmap_ids.swap(candidate_bitmap_ids);
+ highest_score = score;
+ }
+ }
+
+ // Construct FaviconBitmapResults from |best_favicon_id| and
+ // |best_bitmap_ids|.
+ GURL icon_url;
+ IconType icon_type;
+ if (!thumbnail_db_->GetFaviconHeader(best_favicon_id, &icon_url,
+ &icon_type, NULL)) {
+ return false;
}
- SetFaviconMapping(page_url, id, icon_type);
+ for (size_t i = 0; i < best_bitmap_ids.size(); ++i) {
+ base::Time last_updated;
+ FaviconBitmapResult bitmap_result;
+ bitmap_result.icon_url = icon_url;
+ bitmap_result.icon_type = icon_type;
+ if (!thumbnail_db_->GetFaviconBitmap(best_bitmap_ids[i],
+ &last_updated,
+ &bitmap_result.bitmap_data,
+ &bitmap_result.pixel_size)) {
+ return false;
+ }
+
+ bitmap_result.expired = (Time::Now() - last_updated) >
+ TimeDelta::FromDays(kFaviconRefetchDays);
+ if (bitmap_result.is_valid())
+ favicon_bitmap_results->push_back(bitmap_result);
+ }
+ return true;
}
-void HistoryBackend::SetFaviconMapping(const GURL& page_url,
- FaviconID id,
- IconType icon_type) {
+bool HistoryBackend::BuildIconURLSizesMap(
+ const std::vector<FaviconID>& favicon_ids,
+ IconURLSizesMap* icon_url_sizes) {
+ icon_url_sizes->clear();
+ for (size_t i = 0; i < favicon_ids.size(); ++i) {
+ GURL icon_url;
+ FaviconSizes favicon_sizes;
+ if (!thumbnail_db_->GetFaviconHeader(favicon_ids[i], &icon_url, NULL,
+ &favicon_sizes)) {
+ return false;
+ }
+ (*icon_url_sizes)[icon_url] = favicon_sizes;
+ }
+ return true;
+}
+
+void HistoryBackend::SetFaviconMappingsForPageAndRedirects(
+ const GURL& page_url,
+ IconType icon_type,
+ const std::vector<FaviconID>& icon_ids) {
if (!thumbnail_db_.get())
return;
@@ -1998,21 +2253,11 @@ void HistoryBackend::SetFaviconMapping(const GURL& page_url,
std::set<GURL> favicons_changed;
- // Save page <-> favicon association.
+ // Save page <-> favicon associations.
for (history::RedirectList::const_iterator i(redirects->begin());
i != redirects->end(); ++i) {
- FaviconID replaced_id;
- if (AddOrUpdateIconMapping(*i, id, icon_type, &replaced_id)) {
- // The page's favicon ID changed. This means that the one we just
- // changed from could have been orphaned, and we need to re-check it.
- // This is not super fast, but this case will get triggered rarely,
- // since normally a page will always map to the same favicon ID. It
- // will mostly happen for favicons we import.
- if (replaced_id && !thumbnail_db_->HasMappingFor(replaced_id))
- thumbnail_db_->DeleteFavicon(replaced_id);
-
+ if (SetFaviconMappingsForPage(*i, icon_type, icon_ids))
favicons_changed.insert(*i);
- }
}
// Send the notification about the changed favicons.
@@ -2024,41 +2269,59 @@ void HistoryBackend::SetFaviconMapping(const GURL& page_url,
ScheduleCommit();
}
-bool HistoryBackend::AddOrUpdateIconMapping(const GURL& page_url,
- FaviconID id,
- IconType icon_type,
- FaviconID* replaced_icon) {
- *replaced_icon = 0;
+bool HistoryBackend::SetFaviconMappingsForPage(
+ const GURL& page_url,
+ IconType icon_type,
+ const std::vector<FaviconID>& icon_ids) {
+ DCHECK_LE(icon_ids.size(), kMaxFaviconsPerPage);
+ bool mappings_changed = false;
+
+ // Two icon types are considered 'equivalent' if one of the icon types is
+ // TOUCH_ICON and the other is TOUCH_PRECOMPOSED_ICON.
+ //
+ // Sets the icon mappings from |page_url| for |icon_type| to the favicons
+ // with |icon_ids|. Mappings for |page_url| to favicons of type |icon_type|
+ // whose FaviconID is not in |icon_ids| are removed. All icon mappings for
+ // |page_url| to favicons of a type equivalent to |icon_type| are removed.
+ // Remove any favicons which are orphaned as a result of the removal of the
+ // icon mappings.
+
+ std::vector<FaviconID> unmapped_icon_ids = icon_ids;
+
std::vector<IconMapping> icon_mappings;
- if (!thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings)) {
- // There is no mapping add it directly.
- thumbnail_db_->AddIconMapping(page_url, id);
- return true;
- }
- // Iterate all matched icon mappings,
- // a. If the given icon id and matched icon id are same, return.
- // b. If the given icon type and matched icon type are same, but icon id
- // are not, update the IconMapping.
- // c. If the given icon_type and matched icon type are not same, but
- // either of them is ICON_TOUCH or ICON_PRECOMPOSED_TOUCH, update the
- // IconMapping.
- // d. Otherwise add a icon mapping.
+ thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings);
+
for (std::vector<IconMapping>::iterator m = icon_mappings.begin();
m != icon_mappings.end(); ++m) {
- if (m->icon_id == id)
- // The mapping is already there.
- return false;
+ std::vector<FaviconID>::iterator icon_id_it = std::find(
+ unmapped_icon_ids.begin(), unmapped_icon_ids.end(), m->icon_id);
+
+ // If the icon mapping already exists, avoid removing it and adding it back.
+ if (icon_id_it != unmapped_icon_ids.end()) {
+ unmapped_icon_ids.erase(icon_id_it);
+ continue;
+ }
if ((icon_type == TOUCH_ICON && m->icon_type == TOUCH_PRECOMPOSED_ICON) ||
(icon_type == TOUCH_PRECOMPOSED_ICON && m->icon_type == TOUCH_ICON) ||
(icon_type == m->icon_type)) {
- thumbnail_db_->UpdateIconMapping(m->mapping_id, id);
- *replaced_icon = m->icon_id;
- return true;
+ thumbnail_db_->DeleteIconMapping(m->mapping_id);
+
+ // Removing the icon mapping may have orphaned the associated favicon so
+ // we must recheck it. This is not super fast, but this case will get
+ // triggered rarely, since normally a page will always map to the same
+ // favicon IDs. It will mostly happen for favicons we import.
+ if (!thumbnail_db_->HasMappingFor(m->icon_id))
+ thumbnail_db_->DeleteFavicon(m->icon_id);
+ mappings_changed = true;
}
}
- thumbnail_db_->AddIconMapping(page_url, id);
- return true;
+
+ for (size_t i = 0; i < unmapped_icon_ids.size(); ++i ) {
+ thumbnail_db_->AddIconMapping(page_url, unmapped_icon_ids[i]);
+ mappings_changed = true;
+ }
+ return mappings_changed;
}
void HistoryBackend::Commit() {
@@ -2442,64 +2705,6 @@ BookmarkService* HistoryBackend::GetBookmarkService() {
return bookmark_service_;
}
-bool HistoryBackend::GetFaviconFromDB(
- const GURL& page_url,
- int icon_types,
- std::vector<FaviconBitmapResult>* favicon_bitmap_results) {
- DCHECK(favicon_bitmap_results);
-
- if (!db_.get() || !thumbnail_db_.get())
- return false;
-
- bool success = false;
- // Time the query.
- TimeTicks beginning_time = TimeTicks::Now();
-
- std::vector<IconMapping> icon_mappings;
- // Iterate over the known icons looking for one that includes one of the
- // requested types.
- if (thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings)) {
- for (std::vector<IconMapping>::iterator i = icon_mappings.begin();
- i != icon_mappings.end(); ++i) {
- if ((i->icon_type & icon_types) &&
- GetFaviconFromDB(i->icon_id, favicon_bitmap_results)) {
- success = true;
- break;
- }
- }
- }
- UMA_HISTOGRAM_TIMES("History.GetFavIconFromDB", // historical name
- TimeTicks::Now() - beginning_time);
- return success;
-}
-
-bool HistoryBackend::GetFaviconFromDB(
- FaviconID favicon_id,
- std::vector<history::FaviconBitmapResult>* favicon_bitmap_results) {
- FaviconBitmapResult bitmap_result;
- Time last_updated;
- if (!thumbnail_db_->GetFaviconHeader(favicon_id,
- &bitmap_result.icon_url,
- &bitmap_result.icon_type,
- NULL)) {
- return false;
- }
-
- std::vector<FaviconBitmap> favicon_bitmaps;
- thumbnail_db_->GetFaviconBitmaps(favicon_id, &favicon_bitmaps);
- if (favicon_bitmaps.empty())
- return false;
-
- bitmap_result.bitmap_data = favicon_bitmaps[0].bitmap_data;
- bitmap_result.expired = (Time::Now() - favicon_bitmaps[0].last_updated) >
- TimeDelta::FromDays(kFaviconRefetchDays);
-
- favicon_bitmap_results->clear();
- if (bitmap_result.is_valid())
- favicon_bitmap_results->push_back(bitmap_result);
- return true;
-}
-
void HistoryBackend::NotifyVisitObservers(const VisitRow& visit) {
BriefVisitInfo info;
info.url_id = visit.url_id;
« no previous file with comments | « chrome/browser/history/history_backend.h ('k') | chrome/browser/history/history_backend_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698