OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |