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

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: 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::GetFavicons(scoped_refptr<GetFaviconRequest> request,
1775 const GURL& icon_url, 1783 const std::vector<GURL>& icon_urls,
1776 int icon_types) { 1784 int icon_types) {
1777 UpdateFaviconMappingAndFetchImpl(NULL, icon_url, request, icon_types); 1785 UpdateFaviconMappingsAndFetchImpl(NULL, icon_urls, request, icon_types);
1778 } 1786 }
1779 1787
1780 void HistoryBackend::UpdateFaviconMappingAndFetch( 1788 void HistoryBackend::GetFaviconsForURL(
1781 scoped_refptr<GetFaviconRequest> request, 1789 scoped_refptr<GetFaviconRequest> request,
1782 const GURL& page_url, 1790 const GURL& page_url,
1783 const GURL& icon_url, 1791 int icon_types) {
1784 IconType icon_type) { 1792 if (request->canceled())
1785 UpdateFaviconMappingAndFetchImpl(&page_url, icon_url, request, icon_type); 1793 return;
1794
1795 FaviconData favicon_data;
1796
1797 // Get the favicons from DB.
1798 GetFaviconsFromDB(page_url, icon_types, &favicon_data);
1799
1800 request->ForwardResult(request->handle(), favicon_data);
1786 } 1801 }
1787 1802
1788 void HistoryBackend::SetFaviconOutOfDateForPage(const GURL& page_url) { 1803 void HistoryBackend::UpdateFaviconMappingsAndFetch(
1804 scoped_refptr<GetFaviconRequest> request,
1805 const GURL& page_url,
1806 const std::vector<GURL>& icon_urls,
1807 IconType icon_type) {
1808 UpdateFaviconMappingsAndFetchImpl(&page_url, icon_urls, request, icon_type);
1809 }
1810
1811 void HistoryBackend::AddFavicons(
1812 const GURL& page_url,
1813 IconType icon_type,
1814 const std::vector<FaviconDataElement>& elements) {
1815 FaviconData favicon_data;
1816 GetFaviconsFromDB(page_url, icon_type, &favicon_data);
1817
1818 IconURLSizesMap icon_url_sizes;
1819 if (favicon_data.known_icon) {
1820 icon_url_sizes = favicon_data.icon_url_sizes;
1821 } else {
1822 // The thumbnail database doesn't know about |page_url|. Guess at what
1823 // |icon_url_sizes| should be.
1824 for (size_t i = 0; i < elements.size(); ++i) {
1825 const GURL& icon_url = elements[i].icon_url;
1826 icon_url_sizes[icon_url].InsertSize(elements[i].pixel_size);
1827 }
1828 }
1829
1830 SetFavicons(page_url, icon_type, elements, icon_url_sizes);
1831 }
1832
1833 void HistoryBackend::SetFaviconsOutOfDateForPage(const GURL& page_url) {
1789 std::vector<IconMapping> icon_mappings; 1834 std::vector<IconMapping> icon_mappings;
1790 1835
1791 if (!thumbnail_db_.get() || 1836 if (!thumbnail_db_.get() ||
1792 !thumbnail_db_->GetIconMappingsForPageURL(page_url, 1837 !thumbnail_db_->GetIconMappingsForPageURL(page_url,
1793 &icon_mappings)) 1838 &icon_mappings))
1794 return; 1839 return;
1795 1840
1796 for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 1841 for (std::vector<IconMapping>::iterator m = icon_mappings.begin();
1797 m != icon_mappings.end(); ++m) { 1842 m != icon_mappings.end(); ++m) {
1798 thumbnail_db_->SetFaviconOutOfDate(m->icon_id); 1843 thumbnail_db_->SetFaviconOutOfDate(m->icon_id);
1799 } 1844 }
1800 ScheduleCommit(); 1845 ScheduleCommit();
1801 } 1846 }
1802 1847
1803 void HistoryBackend::CloneFavicon(const GURL& old_page_url, 1848 void HistoryBackend::CloneFavicons(const GURL& old_page_url,
1804 const GURL& new_page_url) { 1849 const GURL& new_page_url) {
1805 if (!thumbnail_db_.get()) 1850 if (!thumbnail_db_.get())
1806 return; 1851 return;
1807 1852
1808 // Prevent cross-domain cloning. 1853 // Prevent cross-domain cloning.
1809 if (old_page_url.GetOrigin() != new_page_url.GetOrigin()) 1854 if (old_page_url.GetOrigin() != new_page_url.GetOrigin())
1810 return; 1855 return;
1811 1856
1812 thumbnail_db_->CloneIconMapping(old_page_url, new_page_url); 1857 thumbnail_db_->CloneIconMappings(old_page_url, new_page_url);
1813 ScheduleCommit(); 1858 ScheduleCommit();
1814 } 1859 }
1815 1860
1816 void HistoryBackend::SetImportedFavicons( 1861 void HistoryBackend::SetImportedFavicons(
1817 const std::vector<ImportedFaviconUsage>& favicon_usage) { 1862 const std::vector<ImportedFaviconUsage>& favicon_usage) {
1818 if (!db_.get() || !thumbnail_db_.get()) 1863 if (!db_.get() || !thumbnail_db_.get())
1819 return; 1864 return;
1820 1865
1821 Time now = Time::Now(); 1866 Time now = Time::Now();
1822 1867
1823 // Track all URLs that had their favicons set or updated. 1868 // Track all URLs that had their favicons set or updated.
1824 std::set<GURL> favicons_changed; 1869 std::set<GURL> favicons_changed;
1825 1870
1826 for (size_t i = 0; i < favicon_usage.size(); i++) { 1871 for (size_t i = 0; i < favicon_usage.size(); i++) {
1827 FaviconID favicon_id = thumbnail_db_->GetFaviconIDForFaviconURL( 1872 FaviconID favicon_id = thumbnail_db_->GetFaviconIDForFaviconURL(
1828 favicon_usage[i].favicon_url, history::FAVICON, NULL); 1873 favicon_usage[i].favicon_url, history::FAVICON);
1829 if (!favicon_id) { 1874 if (!favicon_id) {
1830 // This favicon doesn't exist yet, so we create it using the given data. 1875 // This favicon doesn't exist yet, so we create it using the given data.
1831 // TODO(pkotwicz): Pass in real pixel size. 1876 // TODO(pkotwicz): Pass in real pixel size.
1832 favicon_id = thumbnail_db_->AddFavicon( 1877 favicon_id = thumbnail_db_->AddFavicon(
1833 favicon_usage[i].favicon_url, 1878 favicon_usage[i].favicon_url,
1834 history::FAVICON, 1879 history::FAVICON,
1835 std::string("0 0"), 1880 std::string("0 0"),
1836 new base::RefCountedBytes(favicon_usage[i].png_data), 1881 new base::RefCountedBytes(favicon_usage[i].png_data),
1837 now, 1882 now,
1838 gfx::Size()); 1883 gfx::Size());
(...skipping 14 matching lines...) Expand all
1853 URLRow url_info(*url); 1898 URLRow url_info(*url);
1854 url_info.set_visit_count(0); 1899 url_info.set_visit_count(0);
1855 url_info.set_typed_count(0); 1900 url_info.set_typed_count(0);
1856 url_info.set_last_visit(base::Time()); 1901 url_info.set_last_visit(base::Time());
1857 url_info.set_hidden(false); 1902 url_info.set_hidden(false);
1858 db_->AddURL(url_info); 1903 db_->AddURL(url_info);
1859 thumbnail_db_->AddIconMapping(*url, favicon_id); 1904 thumbnail_db_->AddIconMapping(*url, favicon_id);
1860 favicons_changed.insert(*url); 1905 favicons_changed.insert(*url);
1861 } 1906 }
1862 } else { 1907 } else {
1863 if (!thumbnail_db_->GetIconMappingForPageURL(*url, FAVICON, NULL)) { 1908 if (!thumbnail_db_->GetIconMappingsForPageURL(*url, FAVICON, NULL)) {
1864 // URL is present in history, update the favicon *only* if it is not 1909 // URL is present in history, update the favicon *only* if it is not
1865 // set already. 1910 // set already.
1866 thumbnail_db_->AddIconMapping(*url, favicon_id); 1911 thumbnail_db_->AddIconMapping(*url, favicon_id);
1867 favicons_changed.insert(*url); 1912 favicons_changed.insert(*url);
1868 } 1913 }
1869 } 1914 }
1870 } 1915 }
1871 } 1916 }
1872 1917
1873 if (!favicons_changed.empty()) { 1918 if (!favicons_changed.empty()) {
1874 // Send the notification about the changed favicon URLs. 1919 // Send the notification about the changed favicon URLs.
1875 FaviconChangeDetails* changed_details = new FaviconChangeDetails; 1920 FaviconChangeDetails* changed_details = new FaviconChangeDetails;
1876 changed_details->urls.swap(favicons_changed); 1921 changed_details->urls.swap(favicons_changed);
1877 BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, 1922 BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED,
1878 changed_details); 1923 changed_details);
1879 } 1924 }
1880 } 1925 }
1881 1926
1882 void HistoryBackend::UpdateFaviconMappingAndFetchImpl( 1927 void HistoryBackend::UpdateFaviconMappingsAndFetchImpl(
1883 const GURL* page_url, 1928 const GURL* page_url,
1884 const GURL& icon_url, 1929 const std::vector<GURL>& icon_urls,
1885 scoped_refptr<GetFaviconRequest> request, 1930 scoped_refptr<GetFaviconRequest> request,
1886 int icon_types) { 1931 int icon_types) {
1887 // Check only a single type was given when the page_url was specified. 1932 // Check only a single type was given when the page_url was specified.
1888 DCHECK(!page_url || (page_url && (icon_types == FAVICON || 1933 DCHECK(!page_url || (page_url && (icon_types == FAVICON ||
1889 icon_types == TOUCH_ICON || icon_types == TOUCH_PRECOMPOSED_ICON))); 1934 icon_types == TOUCH_ICON || icon_types == TOUCH_PRECOMPOSED_ICON)));
1890 1935
1891 if (request->canceled()) 1936 if (request->canceled())
1892 return; 1937 return;
1893 1938
1894 FaviconData favicon; 1939 FaviconData favicon_data;
1895 1940 IconURLFaviconIDMap icon_url_id_map;
1896 if (thumbnail_db_.get()) { 1941 if (thumbnail_db_.get()) {
1897 const FaviconID favicon_id = 1942 for (size_t i = 0; i < icon_urls.size(); ++i) {
1898 thumbnail_db_->GetFaviconIDForFaviconURL( 1943 const GURL& icon_url = icon_urls[i];
1899 icon_url, icon_types, &favicon.icon_type); 1944 const FaviconID favicon_id =
1900 if (favicon_id) { 1945 thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_types);
1901 scoped_refptr<base::RefCountedMemory> data; 1946 if (favicon_id) {
1902 favicon.known_icon = true; 1947 AddToFaviconData(favicon_id, &favicon_data);
1903 Time last_updated; 1948 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 } 1949 }
1910 1950 // else case, haven't cached entry yet. Caller is responsible for
1911 if (page_url) 1951 // downloading the favicon and invoking SetFavicons.
1912 SetFaviconMapping(*page_url, favicon_id, favicon.icon_type); 1952 }
1913 } 1953 }
1914 // else case, haven't cached entry yet. Caller is responsible for 1954
1915 // downloading the favicon and invoking SetFavicon. 1955 if (page_url) {
1916 } 1956 SetFaviconMappingsForPageAndRedirects(
1917 request->ForwardResult(request->handle(), favicon); 1957 *page_url, favicon_data.icon_type, icon_url_id_map);
1918 } 1958 }
1919 1959 request->ForwardResult(request->handle(), favicon_data);
1920 void HistoryBackend::GetFaviconForURL( 1960 }
1921 scoped_refptr<GetFaviconRequest> request, 1961
1962 void HistoryBackend::SetFavicons(
1922 const GURL& page_url, 1963 const GURL& page_url,
1923 int icon_types) { 1964 IconType icon_type,
1924 if (request->canceled()) 1965 const std::vector<FaviconDataElement>& elements,
1925 return; 1966 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()) 1967 if (!thumbnail_db_.get() || !db_.get())
1952 return; 1968 return;
1953 1969
1954 FaviconID id = thumbnail_db_->GetFaviconIDForFaviconURL( 1970 DCHECK(ValidateSetFaviconsParams(elements, icon_url_sizes));
1955 icon_url, icon_type, NULL); 1971
1956 if (id) 1972 // Build map of |elements| for icon url.
1957 thumbnail_db_->DeleteFaviconBitmapsForFavicon(id); 1973 typedef std::map<GURL, std::vector<FaviconDataElement> > ElementsByIconURL;
1958 1974 ElementsByIconURL grouped_by_icon_url;
1959 id = thumbnail_db_->AddFavicon(icon_url, 1975 for (size_t i = 0; i < elements.size(); ++i) {
1960 icon_type, 1976 const GURL& icon_url = elements[i].icon_url;
1961 "0 0", 1977 grouped_by_icon_url[icon_url].push_back(elements[i]);
1962 data, 1978 }
1963 Time::Now(), 1979
1964 gfx::Size()); 1980 IconURLFaviconIDMap icon_url_id_map;
1965 1981 for (ElementsByIconURL::iterator it = grouped_by_icon_url.begin();
1966 SetFaviconMapping(page_url, id, icon_type); 1982 it != grouped_by_icon_url.end(); ++it) {
1967 } 1983 const GURL& icon_url = it->first;
1968 1984 FaviconID icon_id =
1969 void HistoryBackend::SetFaviconMapping(const GURL& page_url, 1985 thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type);
1970 FaviconID id, 1986 if (!icon_id)
1971 IconType icon_type) { 1987 icon_id = thumbnail_db_->AddFavicon(icon_url, icon_type);
1988 icon_url_id_map[icon_url] = icon_id;
1989
1990 // Update sizes first because it may result in deleting favicon bitmaps.
1991 SetFaviconSizes(icon_id, icon_url_sizes.find(icon_url)->second);
1992 SetFaviconBitmaps(icon_id, it->second);
1993 }
1994
1995 // Update sizes for favicons which have entries in |icon_url_sizes| but not
1996 // in |elements|.
1997 for (IconURLSizesMap::const_iterator it = icon_url_sizes.begin();
1998 it != icon_url_sizes.end(); ++it) {
1999 const GURL& icon_url = it->first;
2000 if (grouped_by_icon_url.find(icon_url) == grouped_by_icon_url.end()) {
2001 FaviconID icon_id =
2002 thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type);
2003 if (!icon_id)
2004 icon_id = thumbnail_db_->AddFavicon(icon_url, icon_type);
2005 icon_url_id_map[icon_url] = icon_id;
2006 SetFaviconSizes(icon_id, it->second);
2007 }
2008 }
2009
2010 SetFaviconMappingsForPageAndRedirects(page_url, icon_type, icon_url_id_map);
2011 }
2012
2013 void HistoryBackend::SetFaviconBitmaps(
2014 FaviconID icon_id,
2015 const std::vector<FaviconDataElement>& elements) {
2016 std::vector<FaviconBitmapIDSize> bitmap_id_size_listing;
2017 thumbnail_db_->GetFaviconBitmapIDSizeListing(icon_id,
2018 &bitmap_id_size_listing);
2019
2020 // A nested loop is ok because in practice neither |elements| nor
2021 // |bitmap_id_size_listing| will have many elements.
2022 for (size_t i = 0; i < elements.size(); ++i) {
2023 const FaviconDataElement& element = elements[i];
2024 FaviconBitmapID bitmap_id = 0;
2025 for (size_t j = 0; j < bitmap_id_size_listing.size(); ++j) {
2026 if (bitmap_id_size_listing[j].pixel_size == element.pixel_size) {
2027 bitmap_id = bitmap_id_size_listing[j].bitmap_id;
2028 break;
2029 }
2030 }
2031 if (bitmap_id) {
2032 thumbnail_db_->SetFaviconBitmap(bitmap_id, element.bitmap_data,
2033 base::Time::Now());
2034 } else {
2035 thumbnail_db_->AddFaviconBitmap(icon_id, element.bitmap_data,
2036 base::Time::Now(), element.pixel_size);
2037 }
2038 }
2039 }
2040
2041 bool HistoryBackend::ValidateSetFaviconsParams(
2042 const std::vector<FaviconDataElement>& elements,
2043 const IconURLSizesMap& icon_url_sizes) const {
2044 if (single_favicon_bitmap_per_icon_type_) {
2045 if (icon_url_sizes.size() != elements.size())
2046 return false;
2047
2048 if (icon_url_sizes.size() > 1)
2049 return false;
2050
2051 if (icon_url_sizes.size() == 1) {
2052 const FaviconSizes& sizes = icon_url_sizes.begin()->second;
2053 if (!sizes.num_sizes() != 1 || !sizes.has_size(gfx::Size()))
2054 return false;
2055 }
2056 } else {
2057 if (icon_url_sizes.size() > kMaxFaviconsPerPage)
2058 return false;
2059 for (IconURLSizesMap::const_iterator it = icon_url_sizes.begin();
2060 it != icon_url_sizes.end(); ++it) {
2061 if (it->second.num_sizes() > kMaxFaviconBitmapsPerIconURL)
2062 return false;
2063 }
2064 }
2065
2066 for (size_t i = 0; i < elements.size(); ++i) {
2067 IconURLSizesMap::const_iterator it =
2068 icon_url_sizes.find(elements[i].icon_url);
2069 if (it == icon_url_sizes.end() ||
2070 !it->second.has_size(elements[i].pixel_size) ||
2071 !elements[i].bitmap_data.get())
2072 return false;
2073 }
2074
2075 return true;
2076 }
2077
2078 void HistoryBackend::SetFaviconSizes(
2079 FaviconID icon_id,
2080 const FaviconSizes& sizes) {
2081 std::vector<FaviconBitmapIDSize> bitmap_id_size_listing;
2082 thumbnail_db_->GetFaviconBitmapIDSizeListing(icon_id,
2083 &bitmap_id_size_listing);
2084
2085 // Remove bitmaps whose pixel size is not contained in |sizes|.
2086 for (size_t i = 0; i < bitmap_id_size_listing.size(); ++i) {
2087 const gfx::Size& pixel_size = bitmap_id_size_listing[i].pixel_size;
2088 if (!sizes.has_size(pixel_size))
2089 thumbnail_db_->DeleteFaviconBitmap(bitmap_id_size_listing[i].bitmap_id);
2090 }
2091
2092 thumbnail_db_->SetFaviconSizes(icon_id, sizes.ToString());
2093 }
2094
2095 bool HistoryBackend::GetFaviconsFromDB(
2096 const GURL& page_url,
2097 int icon_types,
2098 FaviconData* favicon_data) {
2099 DCHECK(favicon_data);
2100
2101 if (!db_.get() || !thumbnail_db_.get())
2102 return false;
2103
2104 // Time the query.
2105 TimeTicks beginning_time = TimeTicks::Now();
2106
2107 bool no_errors = true;
2108 std::vector<IconMapping> icon_mappings;
2109 if (thumbnail_db_->GetIconMappingsForPageURL(page_url, icon_types,
2110 &icon_mappings)) {
2111 for (std::vector<IconMapping>::iterator i = icon_mappings.begin();
2112 i != icon_mappings.end(); ++i) {
2113 if (!AddToFaviconData(i->icon_id, favicon_data)) {
2114 no_errors = false;
2115 break;
2116 }
2117 }
2118 }
2119
2120 UMA_HISTOGRAM_TIMES("History.GetFavIconFromDB", // historical name
2121 TimeTicks::Now() - beginning_time);
2122 return no_errors && !favicon_data->icon_url_sizes.empty();
2123 }
2124
2125 bool HistoryBackend::AddToFaviconData(FaviconID favicon_id,
2126 FaviconData* favicon_data) {
2127 GURL icon_url;
2128 IconType icon_type;
2129 std::string sizes_as_string;
2130
2131 if (!thumbnail_db_->GetFaviconHeader(favicon_id, &icon_url, &icon_type,
2132 &sizes_as_string)) {
2133 return false;
2134 }
2135
2136 favicon_data->known_icon = true;
2137 if (favicon_data->icon_url_sizes.size() == 0) {
sky 2012/08/21 20:16:56 !empty Why does this method care about the icon_u
2138 favicon_data->icon_type = icon_type;
2139 favicon_data->expired = false;
2140 } else {
2141 DCHECK_EQ(favicon_data->icon_type, icon_type);
2142 }
2143
2144 favicon_data->icon_url_sizes[icon_url] = FaviconSizes(sizes_as_string);
2145
2146 std::vector<FaviconBitmap> favicon_bitmaps;
2147 thumbnail_db_->GetFaviconBitmaps(favicon_id, &favicon_bitmaps);
2148 for (size_t i = 0; i < favicon_bitmaps.size(); ++i) {
2149 const FaviconBitmap& favicon_bitmap = favicon_bitmaps[i];
2150 FaviconDataElement favicon_element;
2151 favicon_element.bitmap_data = favicon_bitmap.bitmap_data;
2152 favicon_element.pixel_size = favicon_bitmap.pixel_size;
2153 favicon_element.icon_url = icon_url;
2154 favicon_data->elements.push_back(favicon_element);
2155
2156 // Expired is true if at least one favicon bitmap is expired.ww
2157 favicon_data->expired |= (Time::Now() - favicon_bitmap.last_updated) >
2158 TimeDelta::FromDays(kFaviconRefetchDays);
2159 }
2160
2161 return true;
2162 }
2163
2164 void HistoryBackend::SetFaviconMappingsForPageAndRedirects(
2165 const GURL& page_url,
2166 IconType icon_type,
2167 const IconURLFaviconIDMap& icon_url_id_map) {
1972 if (!thumbnail_db_.get()) 2168 if (!thumbnail_db_.get())
1973 return; 2169 return;
1974 2170
1975 // Find all the pages whose favicons we should set, we want to set it for 2171 // Find all the pages whose favicons we should set, we want to set it for
1976 // all the pages in the redirect chain if it redirected. 2172 // all the pages in the redirect chain if it redirected.
1977 history::RedirectList dummy_list; 2173 history::RedirectList dummy_list;
1978 history::RedirectList* redirects; 2174 history::RedirectList* redirects;
1979 RedirectCache::iterator iter = recent_redirects_.Get(page_url); 2175 RedirectCache::iterator iter = recent_redirects_.Get(page_url);
1980 if (iter != recent_redirects_.end()) { 2176 if (iter != recent_redirects_.end()) {
1981 redirects = &iter->second; 2177 redirects = &iter->second;
1982 2178
1983 // This redirect chain should have the destination URL as the last item. 2179 // This redirect chain should have the destination URL as the last item.
1984 DCHECK(!redirects->empty()); 2180 DCHECK(!redirects->empty());
1985 DCHECK(redirects->back() == page_url); 2181 DCHECK(redirects->back() == page_url);
1986 } else { 2182 } else {
1987 // No redirect chain stored, make up one containing the URL we want to we 2183 // No redirect chain stored, make up one containing the URL we want to we
1988 // can use the same logic below. 2184 // can use the same logic below.
1989 dummy_list.push_back(page_url); 2185 dummy_list.push_back(page_url);
1990 redirects = &dummy_list; 2186 redirects = &dummy_list;
1991 } 2187 }
1992 2188
1993 std::set<GURL> favicons_changed; 2189 std::set<GURL> favicons_changed;
1994 2190
1995 // Save page <-> favicon association. 2191 // Save page <-> favicon associations.
1996 for (history::RedirectList::const_iterator i(redirects->begin()); 2192 for (history::RedirectList::const_iterator i(redirects->begin());
1997 i != redirects->end(); ++i) { 2193 i != redirects->end(); ++i) {
1998 FaviconID replaced_id; 2194 if (SetFaviconMappingsForPage(*i, icon_type, icon_url_id_map)) {
1999 if (AddOrUpdateIconMapping(*i, id, icon_type, &replaced_id)) {
2000 // The page's favicon ID changed. This means that the one we just
2001 // changed from could have been orphaned, and we need to re-check it.
2002 // This is not super fast, but this case will get triggered rarely,
2003 // since normally a page will always map to the same favicon ID. It
2004 // will mostly happen for favicons we import.
2005 if (replaced_id && !thumbnail_db_->HasMappingFor(replaced_id))
2006 thumbnail_db_->DeleteFavicon(replaced_id);
2007
2008 favicons_changed.insert(*i); 2195 favicons_changed.insert(*i);
2009 } 2196 }
2010 } 2197 }
2011 2198
2012 // Send the notification about the changed favicons. 2199 // Send the notification about the changed favicons.
2013 FaviconChangeDetails* changed_details = new FaviconChangeDetails; 2200 FaviconChangeDetails* changed_details = new FaviconChangeDetails;
2014 changed_details->urls.swap(favicons_changed); 2201 changed_details->urls.swap(favicons_changed);
2015 BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, 2202 BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED,
2016 changed_details); 2203 changed_details);
2017 2204
2018 ScheduleCommit(); 2205 ScheduleCommit();
2019 } 2206 }
2020 2207
2021 bool HistoryBackend::AddOrUpdateIconMapping(const GURL& page_url, 2208 bool HistoryBackend::SetFaviconMappingsForPage(
2022 FaviconID id, 2209 const GURL& page_url,
2023 IconType icon_type, 2210 IconType icon_type,
2024 FaviconID* replaced_icon) { 2211 const IconURLFaviconIDMap& icon_url_id_map) {
2025 *replaced_icon = 0; 2212 DCHECK_LE(icon_url_id_map.size(), kMaxFaviconsPerPage);
2213 bool mappings_changed = false;
2214
2215 IconURLFaviconIDMap icon_mappings_to_add = icon_url_id_map;
2216
2217 // Two icon types are considered 'equivalent' if
2218 // a. The two icon types are equal.
2219 // b. If one of the icon types is ICON_TOUCH and the other is
2220 // ICON_PRECOMPOSED_TOUCH.
2221 //
2222 // For each of the urls in |icon_url_id_map|.
2223 // a. If one of the icon mappings has the same icon url as the url from
2224 // |icon_url_id_map|.
2225 // i. If the matched icon mapping has the same type as the given
2226 // |icon_type|, the icon mapping was previously created.
2227 // ii. If the matched icon mapping has an 'equivalent' icon type to the
2228 // given |icon_type|, update the icon mapping.
2229 // b. Otherwise, add the icon mapping represented by the url.
2230 // c. If there are any icon mappings with an icon_url not in
2231 // |icon_url_id_map| and the mapping type is the same or equivalent to the
2232 // given |icon_type|, remove the mapping.
2233
2026 std::vector<IconMapping> icon_mappings; 2234 std::vector<IconMapping> icon_mappings;
2027 if (!thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings)) { 2235 thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings);
2028 // There is no mapping add it directly.
2029 thumbnail_db_->AddIconMapping(page_url, id);
2030 return true;
2031 }
2032 // Iterate all matched icon mappings,
2033 // a. If the given icon id and matched icon id are same, return.
2034 // b. If the given icon type and matched icon type are same, but icon id
2035 // are not, update the IconMapping.
2036 // c. If the given icon_type and matched icon type are not same, but
2037 // either of them is ICON_TOUCH or ICON_PRECOMPOSED_TOUCH, update the
2038 // IconMapping.
2039 // d. Otherwise add a icon mapping.
2040 for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 2236 for (std::vector<IconMapping>::iterator m = icon_mappings.begin();
2041 m != icon_mappings.end(); ++m) { 2237 m != icon_mappings.end(); ++m) {
2042 if (m->icon_id == id)
2043 // The mapping is already there.
2044 return false;
2045
2046 if ((icon_type == TOUCH_ICON && m->icon_type == TOUCH_PRECOMPOSED_ICON) || 2238 if ((icon_type == TOUCH_ICON && m->icon_type == TOUCH_PRECOMPOSED_ICON) ||
2047 (icon_type == TOUCH_PRECOMPOSED_ICON && m->icon_type == TOUCH_ICON) || 2239 (icon_type == TOUCH_PRECOMPOSED_ICON && m->icon_type == TOUCH_ICON) ||
2048 (icon_type == m->icon_type)) { 2240 (icon_type == m->icon_type)) {
2049 thumbnail_db_->UpdateIconMapping(m->mapping_id, id); 2241 IconURLFaviconIDMap::iterator it =
2050 *replaced_icon = m->icon_id; 2242 icon_mappings_to_add.find(m->icon_url);
2051 return true; 2243 if (it == icon_mappings_to_add.end()) {
2244 thumbnail_db_->DeleteIconMapping(m->mapping_id);
2245 } else {
2246 icon_mappings_to_add.erase(it);
2247 if (icon_type == m->icon_type) {
2248 // The mapping is already there.
2249 continue;
2250 }
2251 thumbnail_db_->UpdateIconMapping(m->mapping_id, it->second);
2252 }
2253 // Removing / updating the icon mapping may have orphaned the associated
2254 // favicon so we must recheck it. This is not super fast, but this case
2255 // will get triggered rarely, since normally a page will always map to
2256 // the same favicon IDs. It will mostly happen for favicons we import.
2257 if (!thumbnail_db_->HasMappingFor(m->icon_id))
2258 thumbnail_db_->DeleteFavicon(m->icon_id);
2259
2260 mappings_changed = true;
2052 } 2261 }
2053 } 2262 }
2054 thumbnail_db_->AddIconMapping(page_url, id); 2263
2055 return true; 2264 for (IconURLFaviconIDMap::iterator it = icon_mappings_to_add.begin();
2265 it != icon_mappings_to_add.end(); ++it) {
2266 thumbnail_db_->AddIconMapping(page_url, it->second);
2267 mappings_changed = true;
2268 }
2269 return mappings_changed;
2056 } 2270 }
2057 2271
2058 void HistoryBackend::Commit() { 2272 void HistoryBackend::Commit() {
2059 if (!db_.get()) 2273 if (!db_.get())
2060 return; 2274 return;
2061 2275
2062 // Note that a commit may not actually have been scheduled if a caller 2276 // Note that a commit may not actually have been scheduled if a caller
2063 // explicitly calls this instead of using ScheduleCommit. Likewise, we 2277 // explicitly calls this instead of using ScheduleCommit. Likewise, we
2064 // may reset the flag written by a pending commit. But this is OK! It 2278 // may reset the flag written by a pending commit. But this is OK! It
2065 // will merely cause extra commits (which is kind of the idea). We 2279 // will merely cause extra commits (which is kind of the idea). We
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
2429 2643
2430 return true; 2644 return true;
2431 } 2645 }
2432 2646
2433 BookmarkService* HistoryBackend::GetBookmarkService() { 2647 BookmarkService* HistoryBackend::GetBookmarkService() {
2434 if (bookmark_service_) 2648 if (bookmark_service_)
2435 bookmark_service_->BlockTillLoaded(); 2649 bookmark_service_->BlockTillLoaded();
2436 return bookmark_service_; 2650 return bookmark_service_;
2437 } 2651 }
2438 2652
2439 bool HistoryBackend::GetFaviconFromDB(
2440 const GURL& page_url,
2441 int icon_types,
2442 FaviconData* favicon) {
2443 DCHECK(favicon);
2444
2445 if (!db_.get() || !thumbnail_db_.get())
2446 return false;
2447
2448 bool success = false;
2449 // Time the query.
2450 TimeTicks beginning_time = TimeTicks::Now();
2451
2452 std::vector<IconMapping> icon_mappings;
2453 // Iterate over the known icons looking for one that includes one of the
2454 // requested types.
2455 if (thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings)) {
2456 for (std::vector<IconMapping>::iterator i = icon_mappings.begin();
2457 i != icon_mappings.end(); ++i) {
2458 if ((i->icon_type & icon_types) &&
2459 GetFaviconFromDB(i->icon_id, favicon)) {
2460 success = true;
2461 break;
2462 }
2463 }
2464 }
2465 UMA_HISTOGRAM_TIMES("History.GetFavIconFromDB", // historical name
2466 TimeTicks::Now() - beginning_time);
2467 return success;
2468 }
2469
2470 bool HistoryBackend::GetFaviconFromDB(FaviconID favicon_id,
2471 FaviconData* favicon) {
2472 Time last_updated;
2473 scoped_refptr<base::RefCountedMemory> data;
2474
2475 if (!thumbnail_db_->GetFavicon(favicon_id, &last_updated, &data,
2476 &favicon->icon_url, &favicon->icon_type))
2477 return false;
2478
2479 favicon->expired = (Time::Now() - last_updated) >
2480 TimeDelta::FromDays(kFaviconRefetchDays);
2481 favicon->known_icon = true;
2482 favicon->image_data = data;
2483 return true;
2484 }
2485
2486 void HistoryBackend::NotifyVisitObservers(const VisitRow& visit) { 2653 void HistoryBackend::NotifyVisitObservers(const VisitRow& visit) {
2487 BriefVisitInfo info; 2654 BriefVisitInfo info;
2488 info.url_id = visit.url_id; 2655 info.url_id = visit.url_id;
2489 info.time = visit.visit_time; 2656 info.time = visit.visit_time;
2490 info.transition = visit.transition; 2657 info.transition = visit.transition;
2491 // If we don't have a delegate yet during setup or shutdown, we will drop 2658 // If we don't have a delegate yet during setup or shutdown, we will drop
2492 // these notifications. 2659 // these notifications.
2493 if (delegate_.get()) 2660 if (delegate_.get())
2494 delegate_->NotifyVisitDBObserversOnAddVisit(info); 2661 delegate_->NotifyVisitDBObserversOnAddVisit(info);
2495 } 2662 }
2496 2663
2497 } // namespace history 2664 } // namespace history
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698