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

Side by Side 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: Changes as requested by Sky and stevenjb Created 8 years, 4 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/history/history_backend.h" 5 #include "chrome/browser/history/history_backend.h"
6 6
7 #include <list> 7 #include <list>
8 #include <map> 8 #include <map>
9 #include <set> 9 #include <set>
10 #include <vector> 10 #include <vector>
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 static const int kSessionCloseTimeWindowSecs = 10; 87 static const int kSessionCloseTimeWindowSecs = 10;
88 88
89 // The maximum number of items we'll allow in the redirect list before 89 // The maximum number of items we'll allow in the redirect list before
90 // deleting some. 90 // deleting some.
91 static const int kMaxRedirectCount = 32; 91 static const int kMaxRedirectCount = 32;
92 92
93 // The number of days old a history entry can be before it is considered "old" 93 // The number of days old a history entry can be before it is considered "old"
94 // and is archived. 94 // and is archived.
95 static const int kArchiveDaysThreshold = 90; 95 static const int kArchiveDaysThreshold = 90;
96 96
97 // The maximum number of icons URLs per page which can be stored in the
98 // thumbnail database.
99 const size_t kMaxFaviconsPerPage = 8;
100
101 // The maximum number of bitmaps for a single icon URL which can be stored in
102 // the thumbnail database.
103 const size_t kMaxFaviconBitmapsPerIconURL = 8;
104
97 // Converts from PageUsageData to MostVisitedURL. |redirects| is a 105 // Converts from PageUsageData to MostVisitedURL. |redirects| is a
98 // list of redirects for this URL. Empty list means no redirects. 106 // list of redirects for this URL. Empty list means no redirects.
99 MostVisitedURL MakeMostVisitedURL(const PageUsageData& page_data, 107 MostVisitedURL MakeMostVisitedURL(const PageUsageData& page_data,
100 const RedirectList& redirects) { 108 const RedirectList& redirects) {
101 MostVisitedURL mv; 109 MostVisitedURL mv;
102 mv.url = page_data.GetURL(); 110 mv.url = page_data.GetURL();
103 mv.title = page_data.GetTitle(); 111 mv.title = page_data.GetTitle();
104 if (redirects.empty()) { 112 if (redirects.empty()) {
105 // Redirects must contain at least the target url. 113 // Redirects must contain at least the target url.
106 mv.redirects.push_back(mv.url); 114 mv.redirects.push_back(mv.url);
(...skipping 1657 matching lines...) Expand 10 before | Expand all | Expand 10 after
1764 URLID url_id; 1772 URLID url_id;
1765 if ((url_id = db_->GetRowForURL(redirects.back(), NULL))) 1773 if ((url_id = db_->GetRowForURL(redirects.back(), NULL)))
1766 success = thumbnail_db_->GetPageThumbnail(url_id, data); 1774 success = thumbnail_db_->GetPageThumbnail(url_id, data);
1767 } 1775 }
1768 } 1776 }
1769 } 1777 }
1770 1778
1771 return success; 1779 return success;
1772 } 1780 }
1773 1781
1774 void HistoryBackend::GetFavicon(scoped_refptr<GetFaviconRequest> request, 1782 void HistoryBackend::GetFaviconClosestToSize(
1775 const GURL& icon_url, 1783 scoped_refptr<GetFaviconRequest> request,
1776 int icon_types) { 1784 const GURL& icon_url,
1777 UpdateFaviconMappingAndFetchImpl(NULL, icon_url, request, icon_types); 1785 int icon_types,
1786 const gfx::Size& pixel_size) {
1787 std::vector<GURL> icon_urls;
1788 icon_urls.push_back(icon_url);
1789 UpdateFaviconMappingsAndFetchImpl(NULL, icon_urls, request, icon_types,
1790 &pixel_size);
1778 } 1791 }
1779 1792
1780 void HistoryBackend::UpdateFaviconMappingAndFetch( 1793 void HistoryBackend::GetFavicons(scoped_refptr<GetFaviconRequest> request,
1794 const std::vector<GURL>& icon_urls,
1795 int icon_types) {
1796 UpdateFaviconMappingsAndFetchImpl(NULL, icon_urls, request, icon_types, NULL);
1797 }
1798
1799 void HistoryBackend::GetFaviconForURLClosestToSize(
1781 scoped_refptr<GetFaviconRequest> request, 1800 scoped_refptr<GetFaviconRequest> request,
1782 const GURL& page_url, 1801 const GURL& page_url,
1783 const GURL& icon_url, 1802 int icon_types,
1784 IconType icon_type) { 1803 const gfx::Size& pixel_size) {
1785 UpdateFaviconMappingAndFetchImpl(&page_url, icon_url, request, icon_type); 1804 if (request->canceled())
1805 return;
1806
1807 FaviconData favicon_data;
1808
1809 // Get the favicon from DB.
1810 GetFaviconsFromDB(page_url, icon_types, &pixel_size, &favicon_data);
1811
1812 request->ForwardResult(request->handle(), favicon_data);
1786 } 1813 }
1787 1814
1788 void HistoryBackend::SetFaviconOutOfDateForPage(const GURL& page_url) { 1815 void HistoryBackend::GetFaviconsForURL(
1816 scoped_refptr<GetFaviconRequest> request,
1817 const GURL& page_url,
1818 int icon_types) {
1819 if (request->canceled())
1820 return;
1821
1822 FaviconData favicon_data;
1823
1824 // Get the favicons from DB.
1825 GetFaviconsFromDB(page_url, icon_types, NULL, &favicon_data);
1826
1827 request->ForwardResult(request->handle(), favicon_data);
1828 }
1829
1830 void HistoryBackend::UpdateFaviconMappingsAndFetch(
1831 scoped_refptr<GetFaviconRequest> request,
1832 const GURL& page_url,
1833 const std::vector<GURL>& icon_urls,
1834 IconType icon_type) {
1835 UpdateFaviconMappingsAndFetchImpl(&page_url, icon_urls, request, icon_type,
1836 NULL);
1837 }
1838
1839 void HistoryBackend::AddFavicons(
1840 const GURL& page_url,
1841 IconType icon_type,
1842 const std::vector<FaviconDataElement>& elements) {
1843 FaviconData favicon_data;
1844 GetFaviconsFromDB(page_url, icon_type, NULL, &favicon_data);
1845
1846 IconURLSizesMap icon_url_sizes;
1847 if (favicon_data.known_icon) {
1848 icon_url_sizes = favicon_data.icon_url_sizes;
1849 } else {
1850 // The thumbnail database doesn't know about |page_url|. Guess at what
1851 // |icon_url_sizes| should be.
1852 for (size_t i = 0; i < elements.size(); ++i) {
1853 GURL icon_url = elements[i].icon_url;
1854 icon_url_sizes[icon_url].InsertSize(elements[i].pixel_size);
1855 }
1856 }
1857
1858 SetFavicons(page_url, icon_type, elements, icon_url_sizes);
1859 }
1860
1861 void HistoryBackend::SetFaviconsOutOfDateForPage(const GURL& page_url) {
1789 std::vector<IconMapping> icon_mappings; 1862 std::vector<IconMapping> icon_mappings;
1790 1863
1791 if (!thumbnail_db_.get() || 1864 if (!thumbnail_db_.get() ||
1792 !thumbnail_db_->GetIconMappingsForPageURL(page_url, 1865 !thumbnail_db_->GetIconMappingsForPageURL(page_url,
1793 &icon_mappings)) 1866 &icon_mappings))
1794 return; 1867 return;
1795 1868
1796 for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 1869 for (std::vector<IconMapping>::iterator m = icon_mappings.begin();
1797 m != icon_mappings.end(); ++m) { 1870 m != icon_mappings.end(); ++m) {
1798 thumbnail_db_->SetFaviconOutOfDate(m->icon_id); 1871 thumbnail_db_->SetFaviconOutOfDate(m->icon_id);
(...skipping 19 matching lines...) Expand all
1818 if (!db_.get() || !thumbnail_db_.get()) 1891 if (!db_.get() || !thumbnail_db_.get())
1819 return; 1892 return;
1820 1893
1821 Time now = Time::Now(); 1894 Time now = Time::Now();
1822 1895
1823 // Track all URLs that had their favicons set or updated. 1896 // Track all URLs that had their favicons set or updated.
1824 std::set<GURL> favicons_changed; 1897 std::set<GURL> favicons_changed;
1825 1898
1826 for (size_t i = 0; i < favicon_usage.size(); i++) { 1899 for (size_t i = 0; i < favicon_usage.size(); i++) {
1827 FaviconID favicon_id = thumbnail_db_->GetFaviconIDForFaviconURL( 1900 FaviconID favicon_id = thumbnail_db_->GetFaviconIDForFaviconURL(
1828 favicon_usage[i].favicon_url, history::FAVICON, NULL); 1901 favicon_usage[i].favicon_url, history::FAVICON);
1829 if (!favicon_id) { 1902 if (!favicon_id) {
1830 // This favicon doesn't exist yet, so we create it using the given data. 1903 // This favicon doesn't exist yet, so we create it using the given data.
1831 // TODO(pkotwicz): Pass in real pixel size. 1904 // TODO(pkotwicz): Pass in real pixel size.
1832 favicon_id = thumbnail_db_->AddFavicon( 1905 favicon_id = thumbnail_db_->AddFavicon(
1833 favicon_usage[i].favicon_url, 1906 favicon_usage[i].favicon_url,
1834 history::FAVICON, 1907 history::FAVICON,
1835 std::string("0 0"), 1908 std::string("0 0"),
1836 new base::RefCountedBytes(favicon_usage[i].png_data), 1909 new base::RefCountedBytes(favicon_usage[i].png_data),
1837 now, 1910 now,
1838 gfx::Size()); 1911 gfx::Size());
(...skipping 14 matching lines...) Expand all
1853 URLRow url_info(*url); 1926 URLRow url_info(*url);
1854 url_info.set_visit_count(0); 1927 url_info.set_visit_count(0);
1855 url_info.set_typed_count(0); 1928 url_info.set_typed_count(0);
1856 url_info.set_last_visit(base::Time()); 1929 url_info.set_last_visit(base::Time());
1857 url_info.set_hidden(false); 1930 url_info.set_hidden(false);
1858 db_->AddURL(url_info); 1931 db_->AddURL(url_info);
1859 thumbnail_db_->AddIconMapping(*url, favicon_id); 1932 thumbnail_db_->AddIconMapping(*url, favicon_id);
1860 favicons_changed.insert(*url); 1933 favicons_changed.insert(*url);
1861 } 1934 }
1862 } else { 1935 } else {
1863 if (!thumbnail_db_->GetIconMappingForPageURL(*url, FAVICON, NULL)) { 1936 if (!thumbnail_db_->GetIconMappingsForPageURL(*url, FAVICON, NULL)) {
1864 // URL is present in history, update the favicon *only* if it is not 1937 // URL is present in history, update the favicon *only* if it is not
1865 // set already. 1938 // set already.
1866 thumbnail_db_->AddIconMapping(*url, favicon_id); 1939 thumbnail_db_->AddIconMapping(*url, favicon_id);
1867 favicons_changed.insert(*url); 1940 favicons_changed.insert(*url);
1868 } 1941 }
1869 } 1942 }
1870 } 1943 }
1871 } 1944 }
1872 1945
1873 if (!favicons_changed.empty()) { 1946 if (!favicons_changed.empty()) {
1874 // Send the notification about the changed favicon URLs. 1947 // Send the notification about the changed favicon URLs.
1875 FaviconChangeDetails* changed_details = new FaviconChangeDetails; 1948 FaviconChangeDetails* changed_details = new FaviconChangeDetails;
1876 changed_details->urls.swap(favicons_changed); 1949 changed_details->urls.swap(favicons_changed);
1877 BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, 1950 BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED,
1878 changed_details); 1951 changed_details);
1879 } 1952 }
1880 } 1953 }
1881 1954
1882 void HistoryBackend::UpdateFaviconMappingAndFetchImpl( 1955 void HistoryBackend::UpdateFaviconMappingsAndFetchImpl(
1883 const GURL* page_url, 1956 const GURL* page_url,
1884 const GURL& icon_url, 1957 const std::vector<GURL>& icon_urls,
1885 scoped_refptr<GetFaviconRequest> request, 1958 scoped_refptr<GetFaviconRequest> request,
1886 int icon_types) { 1959 int icon_types,
1960 const gfx::Size* desired_pixel_size) {
1887 // Check only a single type was given when the page_url was specified. 1961 // Check only a single type was given when the page_url was specified.
1888 DCHECK(!page_url || (page_url && (icon_types == FAVICON || 1962 DCHECK(!page_url || (page_url && (icon_types == FAVICON ||
1889 icon_types == TOUCH_ICON || icon_types == TOUCH_PRECOMPOSED_ICON))); 1963 icon_types == TOUCH_ICON || icon_types == TOUCH_PRECOMPOSED_ICON)));
1890 1964
1891 if (request->canceled()) 1965 if (request->canceled())
1892 return; 1966 return;
1893 1967
1894 FaviconData favicon; 1968 FaviconData favicon_data;
1895 1969
1970 IconURLFaviconIDMap icon_url_id_map;
1896 if (thumbnail_db_.get()) { 1971 if (thumbnail_db_.get()) {
1897 const FaviconID favicon_id = 1972 for (size_t i = 0; i < icon_urls.size(); ++i) {
1898 thumbnail_db_->GetFaviconIDForFaviconURL( 1973 GURL icon_url = icon_urls[i];
1899 icon_url, icon_types, &favicon.icon_type); 1974 const FaviconID favicon_id =
1900 if (favicon_id) { 1975 thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_types);
1901 scoped_refptr<base::RefCountedMemory> data; 1976 if (favicon_id) {
1902 favicon.known_icon = true; 1977 AddToFaviconData(favicon_id, desired_pixel_size, &favicon_data);
1903 Time last_updated; 1978 icon_url_id_map[icon_url] = favicon_id;
1904 if (thumbnail_db_->GetFavicon(favicon_id, &last_updated, &data,
1905 NULL, NULL)) {
1906 favicon.expired = (Time::Now() - last_updated) >
1907 TimeDelta::FromDays(kFaviconRefetchDays);
1908 favicon.image_data = data;
1909 } 1979 }
1910 1980 // else case, haven't cached entry yet. Caller is responsible for
1911 if (page_url) 1981 // downloading the favicon and invoking SetFavicons.
1912 SetFaviconMapping(*page_url, favicon_id, favicon.icon_type); 1982 }
1913 } 1983 }
1914 // else case, haven't cached entry yet. Caller is responsible for 1984
1915 // downloading the favicon and invoking SetFavicon. 1985 if (page_url) {
1916 } 1986 SetFaviconMappingsForPageAndRedirects(
1917 request->ForwardResult(request->handle(), favicon); 1987 *page_url, favicon_data.icon_type, icon_url_id_map);
1918 } 1988 }
1919 1989
1920 void HistoryBackend::GetFaviconForURL( 1990 request->ForwardResult(request->handle(), favicon_data);
1921 scoped_refptr<GetFaviconRequest> request, 1991 }
1992
1993 void HistoryBackend::SetFavicons(
1922 const GURL& page_url, 1994 const GURL& page_url,
1923 int icon_types) { 1995 IconType icon_type,
1924 if (request->canceled()) 1996 const std::vector<FaviconDataElement>& elements,
1925 return; 1997 const IconURLSizesMap& icon_url_sizes) {
1926
1927 FaviconData favicon;
1928
1929 // Get the favicon from DB.
1930 GetFaviconFromDB(page_url, icon_types, &favicon);
1931
1932 request->ForwardResult(request->handle(), favicon);
1933 }
1934
1935 void HistoryBackend::GetFaviconForID(scoped_refptr<GetFaviconRequest> request,
1936 FaviconID id) {
1937 if (request->canceled())
1938 return;
1939
1940 FaviconData favicon;
1941 GetFaviconFromDB(id, &favicon);
1942 request->ForwardResult(request->handle(), favicon);
1943 }
1944
1945 void HistoryBackend::SetFavicon(
1946 const GURL& page_url,
1947 const GURL& icon_url,
1948 scoped_refptr<base::RefCountedMemory> data,
1949 IconType icon_type) {
1950 DCHECK(data.get());
1951 if (!thumbnail_db_.get() || !db_.get()) 1998 if (!thumbnail_db_.get() || !db_.get())
1952 return; 1999 return;
1953 2000
1954 FaviconID id = thumbnail_db_->GetFaviconIDForFaviconURL( 2001 DCHECK(ValidateSetFaviconsParams(elements, icon_url_sizes));
1955 icon_url, icon_type, NULL); 2002
1956 if (id) { 2003 // Build map of |elements| for icon url.
1957 thumbnail_db_->SetFaviconBitmap(id, data, Time::Now()); 2004 typedef std::map<GURL, std::vector<FaviconDataElement> > ElementsByIconURL;
2005 ElementsByIconURL grouped_by_icon_url;
2006 for (size_t i = 0; i < elements.size(); ++i) {
2007 GURL icon_url = elements[i].icon_url;
stevenjb 2012/08/15 22:59:18 You could use a GURL& or skip local to avoid an ex
2008 grouped_by_icon_url[icon_url].push_back(elements[i]);
2009 }
2010
2011 IconURLFaviconIDMap icon_url_id_map;
2012 for (ElementsByIconURL::iterator it = grouped_by_icon_url.begin();
2013 it != grouped_by_icon_url.end(); ++it) {
2014 GURL icon_url = it->first;
2015 FaviconID icon_id =
2016 thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type);
2017 if (!icon_id)
2018 icon_id = thumbnail_db_->AddFavicon(icon_url, icon_type);
2019 icon_url_id_map[icon_url] = icon_id;
2020
2021 // Update sizes first because it may result in deleting favicon bitmaps.
2022 SetFaviconSizes(icon_id, icon_url_sizes.find(icon_url)->second);
2023 SetFaviconBitmaps(icon_id, it->second);
2024 }
2025
2026 // Update sizes for favicons which have entries in |icon_url_sizes| but not
2027 // in |elements|.
2028 for (IconURLSizesMap::const_iterator it = icon_url_sizes.begin();
2029 it != icon_url_sizes.end(); ++it) {
2030 GURL icon_url = it->first;
2031 if (grouped_by_icon_url.find(icon_url) == grouped_by_icon_url.end()) {
2032 FaviconID icon_id =
2033 thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type);
2034 if (!icon_id)
2035 icon_id = thumbnail_db_->AddFavicon(icon_url, icon_type);
2036 icon_url_id_map[icon_url] = icon_id;
2037 SetFaviconSizes(icon_id, it->second);
2038 }
2039 }
2040
2041 SetFaviconMappingsForPageAndRedirects(page_url, icon_type, icon_url_id_map);
2042 }
2043
2044 void HistoryBackend::SetFaviconBitmaps(
2045 FaviconID icon_id,
2046 const std::vector<FaviconDataElement>& elements) {
2047 std::vector<FaviconBitmapIDSize> bitmap_id_size_listing;
2048 thumbnail_db_->GetFaviconBitmapIDSizeListing(icon_id,
2049 &bitmap_id_size_listing);
2050
2051 // A nested loop is ok because in practice neither |elements| nor
2052 // |bitmap_id_size_listing| will have many elements.
2053 for (size_t i = 0; i < elements.size(); ++i) {
2054 FaviconDataElement element = elements[i];
2055 FaviconBitmapID bitmap_id = 0;
2056 for (size_t j = 0; j < bitmap_id_size_listing.size(); ++j) {
2057 if (bitmap_id_size_listing[j].pixel_size == element.pixel_size) {
2058 bitmap_id = bitmap_id_size_listing[j].bitmap_id;
2059 break;
2060 }
2061 }
2062 if (bitmap_id) {
2063 thumbnail_db_->SetFaviconBitmap(bitmap_id, element.bitmap_data,
2064 base::Time::Now());
2065 } else {
2066 thumbnail_db_->AddFaviconBitmap(icon_id, element.bitmap_data,
2067 base::Time::Now(), element.pixel_size);
2068 }
2069 }
2070 }
2071
2072 bool HistoryBackend::ValidateSetFaviconsParams(
2073 const std::vector<FaviconDataElement>& elements,
2074 const IconURLSizesMap& icon_url_sizes) const {
2075 if (icon_url_sizes.size() > kMaxFaviconsPerPage)
2076 return false;
2077 for (IconURLSizesMap::const_iterator it = icon_url_sizes.begin();
2078 it != icon_url_sizes.end(); ++it) {
2079 if (it->second.num_sizes() > kMaxFaviconBitmapsPerIconURL)
2080 return false;
2081 }
2082
2083 for (size_t i = 0; i < elements.size(); ++i) {
2084 IconURLSizesMap::const_iterator it =
2085 icon_url_sizes.find(elements[i].icon_url);
2086 if (it == icon_url_sizes.end() ||
2087 !it->second.has_size(elements[i].pixel_size) ||
2088 !elements[i].bitmap_data.get())
2089 return false;
2090 }
2091 return true;
2092 }
2093
2094 void HistoryBackend::SetFaviconSizes(
2095 FaviconID icon_id,
2096 const FaviconSizes& sizes) {
2097 std::vector<FaviconBitmapIDSize> bitmap_id_size_listing;
2098 thumbnail_db_->GetFaviconBitmapIDSizeListing(icon_id,
2099 &bitmap_id_size_listing);
2100
2101 // Remove bitmaps whose pixel size is not contained in |sizes|.
2102 for (size_t i = 0; i < bitmap_id_size_listing.size(); ++i) {
2103 gfx::Size pixel_size = bitmap_id_size_listing[i].pixel_size;
2104 if (!sizes.has_size(pixel_size))
2105 thumbnail_db_->DeleteFaviconBitmap(bitmap_id_size_listing[i].bitmap_id);
2106 }
2107
2108 thumbnail_db_->SetFaviconSizes(icon_id, sizes.ToString());
2109 }
2110
2111 bool HistoryBackend::GetFaviconsFromDB(
2112 const GURL& page_url,
2113 int icon_types,
2114 const gfx::Size* desired_pixel_size,
2115 FaviconData* favicon_data) {
2116 DCHECK(favicon_data);
2117
2118 if (!db_.get() || !thumbnail_db_.get())
2119 return false;
2120
2121 // Time the query.
2122 TimeTicks beginning_time = TimeTicks::Now();
2123
2124 bool no_errors = true;
2125 std::vector<IconMapping> icon_mappings;
2126 if (thumbnail_db_->GetIconMappingsForPageURL(page_url, icon_types,
2127 &icon_mappings)) {
2128 for (std::vector<IconMapping>::iterator i = icon_mappings.begin();
2129 i != icon_mappings.end(); ++i) {
2130 if (!AddToFaviconData(i->icon_id, desired_pixel_size, favicon_data)) {
2131 no_errors = false;
2132 break;
2133 }
2134 }
2135 }
2136
2137 UMA_HISTOGRAM_TIMES("History.GetFavIconFromDB", // historical name
2138 TimeTicks::Now() - beginning_time);
2139 return no_errors && !favicon_data->icon_url_sizes.empty();
2140 }
2141
2142 bool HistoryBackend::AddToFaviconData(FaviconID favicon_id,
2143 const gfx::Size* desired_pixel_size,
2144 FaviconData* favicon_data) {
2145 GURL icon_url;
2146 IconType icon_type;
2147 std::string sizes_as_string;
2148
2149 if (!thumbnail_db_->GetFaviconHeader(favicon_id, &icon_url, &icon_type,
2150 &sizes_as_string)) {
2151 return false;
2152 }
2153
2154 favicon_data->known_icon = true;
2155 if (favicon_data->icon_url_sizes.size() == 0) {
2156 favicon_data->icon_type = icon_type;
2157 favicon_data->expired = false;
1958 } else { 2158 } else {
1959 id = thumbnail_db_->AddFavicon(icon_url, 2159 DCHECK_EQ(favicon_data->icon_type, icon_type);
1960 icon_type, 2160 }
1961 "0 0", 2161
1962 data, 2162 favicon_data->icon_url_sizes[icon_url] = FaviconSizes(sizes_as_string);
1963 Time::Now(), 2163
1964 gfx::Size()); 2164 std::vector<FaviconBitmap> favicon_bitmaps;
1965 } 2165 thumbnail_db_->GetFaviconBitmaps(favicon_id, &favicon_bitmaps);
1966 2166 for (size_t i = 0; i < favicon_bitmaps.size(); ++i) {
1967 SetFaviconMapping(page_url, id, icon_type); 2167 FaviconBitmap favicon_bitmap = favicon_bitmaps[i];
1968 } 2168 FaviconDataElement favicon_element;
1969 2169 favicon_element.bitmap_data = favicon_bitmap.bitmap_data;
1970 void HistoryBackend::SetFaviconMapping(const GURL& page_url, 2170 favicon_element.pixel_size = favicon_bitmap.pixel_size;
1971 FaviconID id, 2171 favicon_element.icon_url = icon_url;
1972 IconType icon_type) { 2172 favicon_data->elements.push_back(favicon_element);
2173
2174 favicon_data->expired |= (Time::Now() - favicon_bitmap.last_updated) >
2175 TimeDelta::FromDays(kFaviconRefetchDays);
2176 }
2177
2178 if (desired_pixel_size) {
stevenjb 2012/08/15 22:59:18 Couldn't this just check on desired_pixel_size.IsE
pkotwicz 2012/08/16 02:58:37 I think that it is clearer when desired_pixel_size
stevenjb 2012/08/20 17:20:27 I guess it's a tradeoff between clarity here and c
2179 int closest_index = GetBestElementForSizeIndex(favicon_data->elements,
2180 *desired_pixel_size);
2181 if (closest_index >= 0) {
2182 FaviconDataElement element = favicon_data->elements[closest_index];
2183 favicon_data->elements.clear();
2184 favicon_data->elements.push_back(element);
2185 }
2186 }
2187
2188 return true;
2189 }
2190
2191 int HistoryBackend::GetBestElementForSizeIndex(
2192 const std::vector<FaviconDataElement>& elements,
2193 const gfx::Size& desired_pixel_size) const {
2194 // TODO(pkotwicz): Use smarter selection algorithm.
2195 int closest_element_index = -1;
2196 int smallest_diff = std::numeric_limits<int>::max();
2197 for (size_t i = 0; i < elements.size(); ++i) {
2198 gfx::Size pixel_size = elements[i].pixel_size;
2199 int diff = std::abs(pixel_size.width() - desired_pixel_size.width()) +
2200 std::abs(pixel_size.height() - desired_pixel_size.height());
2201 if (diff < smallest_diff) {
2202 closest_element_index = i;
2203 smallest_diff = diff;
2204 }
2205 if (smallest_diff == 0)
2206 break;
2207 }
2208 return closest_element_index;
2209 }
2210
2211 void HistoryBackend::SetFaviconMappingsForPageAndRedirects(
2212 const GURL& page_url,
2213 IconType icon_type,
2214 const IconURLFaviconIDMap& icon_url_id_map) {
1973 if (!thumbnail_db_.get()) 2215 if (!thumbnail_db_.get())
1974 return; 2216 return;
1975 2217
1976 // Find all the pages whose favicons we should set, we want to set it for 2218 // Find all the pages whose favicons we should set, we want to set it for
1977 // all the pages in the redirect chain if it redirected. 2219 // all the pages in the redirect chain if it redirected.
1978 history::RedirectList dummy_list; 2220 history::RedirectList dummy_list;
1979 history::RedirectList* redirects; 2221 history::RedirectList* redirects;
1980 RedirectCache::iterator iter = recent_redirects_.Get(page_url); 2222 RedirectCache::iterator iter = recent_redirects_.Get(page_url);
1981 if (iter != recent_redirects_.end()) { 2223 if (iter != recent_redirects_.end()) {
1982 redirects = &iter->second; 2224 redirects = &iter->second;
1983 2225
1984 // This redirect chain should have the destination URL as the last item. 2226 // This redirect chain should have the destination URL as the last item.
1985 DCHECK(!redirects->empty()); 2227 DCHECK(!redirects->empty());
1986 DCHECK(redirects->back() == page_url); 2228 DCHECK(redirects->back() == page_url);
1987 } else { 2229 } else {
1988 // No redirect chain stored, make up one containing the URL we want to we 2230 // No redirect chain stored, make up one containing the URL we want to we
1989 // can use the same logic below. 2231 // can use the same logic below.
1990 dummy_list.push_back(page_url); 2232 dummy_list.push_back(page_url);
1991 redirects = &dummy_list; 2233 redirects = &dummy_list;
1992 } 2234 }
1993 2235
1994 std::set<GURL> favicons_changed; 2236 std::set<GURL> favicons_changed;
1995 2237
1996 // Save page <-> favicon association. 2238 // Save page <-> favicon associations.
1997 for (history::RedirectList::const_iterator i(redirects->begin()); 2239 for (history::RedirectList::const_iterator i(redirects->begin());
1998 i != redirects->end(); ++i) { 2240 i != redirects->end(); ++i) {
1999 FaviconID replaced_id; 2241 if (SetFaviconMappingsForPage(*i, icon_type, icon_url_id_map)) {
2000 if (AddOrUpdateIconMapping(*i, id, icon_type, &replaced_id)) {
2001 // The page's favicon ID changed. This means that the one we just
2002 // changed from could have been orphaned, and we need to re-check it.
2003 // This is not super fast, but this case will get triggered rarely,
2004 // since normally a page will always map to the same favicon ID. It
2005 // will mostly happen for favicons we import.
2006 if (replaced_id && !thumbnail_db_->HasMappingFor(replaced_id))
2007 thumbnail_db_->DeleteFavicon(replaced_id);
2008
2009 favicons_changed.insert(*i); 2242 favicons_changed.insert(*i);
2010 } 2243 }
2011 } 2244 }
2012 2245
2013 // Send the notification about the changed favicons. 2246 // Send the notification about the changed favicons.
2014 FaviconChangeDetails* changed_details = new FaviconChangeDetails; 2247 FaviconChangeDetails* changed_details = new FaviconChangeDetails;
2015 changed_details->urls.swap(favicons_changed); 2248 changed_details->urls.swap(favicons_changed);
2016 BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, 2249 BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED,
2017 changed_details); 2250 changed_details);
2018 2251
2019 ScheduleCommit(); 2252 ScheduleCommit();
2020 } 2253 }
2021 2254
2022 bool HistoryBackend::AddOrUpdateIconMapping(const GURL& page_url, 2255 bool HistoryBackend::SetFaviconMappingsForPage(
2023 FaviconID id, 2256 const GURL& page_url,
2024 IconType icon_type, 2257 IconType icon_type,
2025 FaviconID* replaced_icon) { 2258 const IconURLFaviconIDMap& icon_url_id_map) {
2026 *replaced_icon = 0; 2259 DCHECK_LE(icon_url_id_map.size(), kMaxFaviconsPerPage);
2260 bool mappings_changed = false;
2261
2262 IconURLFaviconIDMap icon_mappings_to_add = icon_url_id_map;
2263
2264 // Two icon types are considered 'equivalent' if
2265 // a. The two icon types are equal.
2266 // b. If one of the icon types is ICON_TOUCH and the other is
2267 // ICON_PRECOMPOSED_TOUCH.
2268 //
2269 // For each of the urls in |icon_url_id_map|.
2270 // a. If one of the icon mappings has the same icon url as the url from
2271 // |icon_url_id_map|.
2272 // i. If the matched icon mapping has the same type as the given
2273 // |icon_type|, the icon mapping was previously created.
2274 // ii. If the matched icon mapping has an 'equivalent' icon type to the
2275 // given |icon_type|, update the icon mapping.
2276 // b. Otherwise, add the icon mapping represented by the url.
2277 // c. If there are any icon mappings with an icon_url not in
2278 // |icon_url_id_map| and the mapping type is the same or equivalent to the
2279 // given |icon_type|, remove the mapping.
2280
2027 std::vector<IconMapping> icon_mappings; 2281 std::vector<IconMapping> icon_mappings;
2028 if (!thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings)) { 2282 thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings);
2029 // There is no mapping add it directly.
2030 thumbnail_db_->AddIconMapping(page_url, id);
2031 return true;
2032 }
2033 // Iterate all matched icon mappings,
2034 // a. If the given icon id and matched icon id are same, return.
2035 // b. If the given icon type and matched icon type are same, but icon id
2036 // are not, update the IconMapping.
2037 // c. If the given icon_type and matched icon type are not same, but
2038 // either of them is ICON_TOUCH or ICON_PRECOMPOSED_TOUCH, update the
2039 // IconMapping.
2040 // d. Otherwise add a icon mapping.
2041 for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 2283 for (std::vector<IconMapping>::iterator m = icon_mappings.begin();
2042 m != icon_mappings.end(); ++m) { 2284 m != icon_mappings.end(); ++m) {
2043 if (m->icon_id == id)
2044 // The mapping is already there.
2045 return false;
2046
2047 if ((icon_type == TOUCH_ICON && m->icon_type == TOUCH_PRECOMPOSED_ICON) || 2285 if ((icon_type == TOUCH_ICON && m->icon_type == TOUCH_PRECOMPOSED_ICON) ||
2048 (icon_type == TOUCH_PRECOMPOSED_ICON && m->icon_type == TOUCH_ICON) || 2286 (icon_type == TOUCH_PRECOMPOSED_ICON && m->icon_type == TOUCH_ICON) ||
2049 (icon_type == m->icon_type)) { 2287 (icon_type == m->icon_type)) {
2050 thumbnail_db_->UpdateIconMapping(m->mapping_id, id); 2288 IconURLFaviconIDMap::iterator it =
2051 *replaced_icon = m->icon_id; 2289 icon_mappings_to_add.find(m->icon_url);
2052 return true; 2290 if (it == icon_mappings_to_add.end()) {
2291 thumbnail_db_->DeleteIconMapping(m->mapping_id);
2292 } else {
2293 icon_mappings_to_add.erase(it);
2294 if (icon_type == m->icon_type) {
2295 // The mapping is already there.
2296 continue;
2297 }
2298 thumbnail_db_->UpdateIconMapping(m->mapping_id, it->second);
2299 }
2300 // Removing / updating the icon mapping may have orphaned the associated
2301 // favicon so we must recheck it. This is not super fast, but this case
2302 // will get triggered rarely, since normally a page will always map to
2303 // the same favicon IDs. It will mostly happen for favicons we import.
2304 if (!thumbnail_db_->HasMappingFor(m->icon_id))
2305 thumbnail_db_->DeleteFavicon(m->icon_id);
2306
2307 mappings_changed = true;
2053 } 2308 }
2054 } 2309 }
2055 thumbnail_db_->AddIconMapping(page_url, id); 2310
2056 return true; 2311 for (IconURLFaviconIDMap::iterator it = icon_mappings_to_add.begin();
2312 it != icon_mappings_to_add.end(); ++it) {
2313 thumbnail_db_->AddIconMapping(page_url, it->second);
2314 mappings_changed = true;
2315 }
2316 return mappings_changed;
2057 } 2317 }
2058 2318
2059 void HistoryBackend::Commit() { 2319 void HistoryBackend::Commit() {
2060 if (!db_.get()) 2320 if (!db_.get())
2061 return; 2321 return;
2062 2322
2063 // Note that a commit may not actually have been scheduled if a caller 2323 // Note that a commit may not actually have been scheduled if a caller
2064 // explicitly calls this instead of using ScheduleCommit. Likewise, we 2324 // explicitly calls this instead of using ScheduleCommit. Likewise, we
2065 // may reset the flag written by a pending commit. But this is OK! It 2325 // may reset the flag written by a pending commit. But this is OK! It
2066 // will merely cause extra commits (which is kind of the idea). We 2326 // will merely cause extra commits (which is kind of the idea). We
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
2430 2690
2431 return true; 2691 return true;
2432 } 2692 }
2433 2693
2434 BookmarkService* HistoryBackend::GetBookmarkService() { 2694 BookmarkService* HistoryBackend::GetBookmarkService() {
2435 if (bookmark_service_) 2695 if (bookmark_service_)
2436 bookmark_service_->BlockTillLoaded(); 2696 bookmark_service_->BlockTillLoaded();
2437 return bookmark_service_; 2697 return bookmark_service_;
2438 } 2698 }
2439 2699
2440 bool HistoryBackend::GetFaviconFromDB(
2441 const GURL& page_url,
2442 int icon_types,
2443 FaviconData* favicon) {
2444 DCHECK(favicon);
2445
2446 if (!db_.get() || !thumbnail_db_.get())
2447 return false;
2448
2449 bool success = false;
2450 // Time the query.
2451 TimeTicks beginning_time = TimeTicks::Now();
2452
2453 std::vector<IconMapping> icon_mappings;
2454 // Iterate over the known icons looking for one that includes one of the
2455 // requested types.
2456 if (thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings)) {
2457 for (std::vector<IconMapping>::iterator i = icon_mappings.begin();
2458 i != icon_mappings.end(); ++i) {
2459 if ((i->icon_type & icon_types) &&
2460 GetFaviconFromDB(i->icon_id, favicon)) {
2461 success = true;
2462 break;
2463 }
2464 }
2465 }
2466 UMA_HISTOGRAM_TIMES("History.GetFavIconFromDB", // historical name
2467 TimeTicks::Now() - beginning_time);
2468 return success;
2469 }
2470
2471 bool HistoryBackend::GetFaviconFromDB(FaviconID favicon_id,
2472 FaviconData* favicon) {
2473 Time last_updated;
2474 scoped_refptr<base::RefCountedMemory> data;
2475
2476 if (!thumbnail_db_->GetFavicon(favicon_id, &last_updated, &data,
2477 &favicon->icon_url, &favicon->icon_type))
2478 return false;
2479
2480 favicon->expired = (Time::Now() - last_updated) >
2481 TimeDelta::FromDays(kFaviconRefetchDays);
2482 favicon->known_icon = true;
2483 favicon->image_data = data;
2484 return true;
2485 }
2486
2487 void HistoryBackend::NotifyVisitObservers(const VisitRow& visit) { 2700 void HistoryBackend::NotifyVisitObservers(const VisitRow& visit) {
2488 BriefVisitInfo info; 2701 BriefVisitInfo info;
2489 info.url_id = visit.url_id; 2702 info.url_id = visit.url_id;
2490 info.time = visit.visit_time; 2703 info.time = visit.visit_time;
2491 info.transition = visit.transition; 2704 info.transition = visit.transition;
2492 // If we don't have a delegate yet during setup or shutdown, we will drop 2705 // If we don't have a delegate yet during setup or shutdown, we will drop
2493 // these notifications. 2706 // these notifications.
2494 if (delegate_.get()) 2707 if (delegate_.get())
2495 delegate_->NotifyVisitDBObserversOnAddVisit(info); 2708 delegate_->NotifyVisitDBObserversOnAddVisit(info);
2496 } 2709 }
2497 2710
2498 } // namespace history 2711 } // namespace history
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698