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 <algorithm> |
7 #include <list> | 8 #include <list> |
8 #include <map> | 9 #include <map> |
9 #include <set> | 10 #include <set> |
10 #include <vector> | 11 #include <vector> |
11 | 12 |
12 #include "base/bind.h" | 13 #include "base/bind.h" |
13 #include "base/compiler_specific.h" | 14 #include "base/compiler_specific.h" |
14 #include "base/file_util.h" | 15 #include "base/file_util.h" |
15 #include "base/memory/scoped_ptr.h" | 16 #include "base/memory/scoped_ptr.h" |
16 #include "base/memory/scoped_vector.h" | 17 #include "base/memory/scoped_vector.h" |
17 #include "base/message_loop.h" | 18 #include "base/message_loop.h" |
18 #include "base/metrics/histogram.h" | 19 #include "base/metrics/histogram.h" |
19 #include "base/string_util.h" | 20 #include "base/string_util.h" |
20 #include "base/time.h" | 21 #include "base/time.h" |
21 #include "base/utf_string_conversions.h" | 22 #include "base/utf_string_conversions.h" |
22 #include "chrome/browser/api/bookmarks/bookmark_service.h" | 23 #include "chrome/browser/api/bookmarks/bookmark_service.h" |
23 #include "chrome/browser/autocomplete/history_url_provider.h" | 24 #include "chrome/browser/autocomplete/history_url_provider.h" |
24 #include "chrome/browser/cancelable_request.h" | 25 #include "chrome/browser/cancelable_request.h" |
25 #include "chrome/browser/history/history_notifications.h" | 26 #include "chrome/browser/history/history_notifications.h" |
26 #include "chrome/browser/history/history_publisher.h" | 27 #include "chrome/browser/history/history_publisher.h" |
27 #include "chrome/browser/history/in_memory_history_backend.h" | 28 #include "chrome/browser/history/in_memory_history_backend.h" |
28 #include "chrome/browser/history/page_usage_data.h" | 29 #include "chrome/browser/history/page_usage_data.h" |
| 30 #include "chrome/browser/history/select_favicon_frames.h" |
29 #include "chrome/browser/history/top_sites.h" | 31 #include "chrome/browser/history/top_sites.h" |
30 #include "chrome/browser/history/visit_filter.h" | 32 #include "chrome/browser/history/visit_filter.h" |
31 #include "chrome/common/chrome_constants.h" | 33 #include "chrome/common/chrome_constants.h" |
32 #include "chrome/common/chrome_notification_types.h" | 34 #include "chrome/common/chrome_notification_types.h" |
33 #include "chrome/common/url_constants.h" | 35 #include "chrome/common/url_constants.h" |
34 #include "content/public/browser/download_persistent_store_info.h" | 36 #include "content/public/browser/download_persistent_store_info.h" |
35 #include "googleurl/src/gurl.h" | 37 #include "googleurl/src/gurl.h" |
36 #include "grit/chromium_strings.h" | 38 #include "grit/chromium_strings.h" |
37 #include "grit/generated_resources.h" | 39 #include "grit/generated_resources.h" |
38 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | 40 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 static const int kSessionCloseTimeWindowSecs = 10; | 89 static const int kSessionCloseTimeWindowSecs = 10; |
88 | 90 |
89 // The maximum number of items we'll allow in the redirect list before | 91 // The maximum number of items we'll allow in the redirect list before |
90 // deleting some. | 92 // deleting some. |
91 static const int kMaxRedirectCount = 32; | 93 static const int kMaxRedirectCount = 32; |
92 | 94 |
93 // The number of days old a history entry can be before it is considered "old" | 95 // The number of days old a history entry can be before it is considered "old" |
94 // and is archived. | 96 // and is archived. |
95 static const int kArchiveDaysThreshold = 90; | 97 static const int kArchiveDaysThreshold = 90; |
96 | 98 |
| 99 // The maximum number of icons URLs per page which can be stored in the |
| 100 // thumbnail database. |
| 101 static const size_t kMaxFaviconsPerPage = 8; |
| 102 |
| 103 // The maximum number of bitmaps for a single icon URL which can be stored in |
| 104 // the thumbnail database. |
| 105 static const size_t kMaxFaviconBitmapsPerIconURL = 8; |
| 106 |
97 // Converts from PageUsageData to MostVisitedURL. |redirects| is a | 107 // Converts from PageUsageData to MostVisitedURL. |redirects| is a |
98 // list of redirects for this URL. Empty list means no redirects. | 108 // list of redirects for this URL. Empty list means no redirects. |
99 MostVisitedURL MakeMostVisitedURL(const PageUsageData& page_data, | 109 MostVisitedURL MakeMostVisitedURL(const PageUsageData& page_data, |
100 const RedirectList& redirects) { | 110 const RedirectList& redirects) { |
101 MostVisitedURL mv; | 111 MostVisitedURL mv; |
102 mv.url = page_data.GetURL(); | 112 mv.url = page_data.GetURL(); |
103 mv.title = page_data.GetTitle(); | 113 mv.title = page_data.GetTitle(); |
104 if (redirects.empty()) { | 114 if (redirects.empty()) { |
105 // Redirects must contain at least the target url. | 115 // Redirects must contain at least the target url. |
106 mv.redirects.push_back(mv.url); | 116 mv.redirects.push_back(mv.url); |
(...skipping 1655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1762 URLID url_id; | 1772 URLID url_id; |
1763 if ((url_id = db_->GetRowForURL(redirects.back(), NULL))) | 1773 if ((url_id = db_->GetRowForURL(redirects.back(), NULL))) |
1764 success = thumbnail_db_->GetPageThumbnail(url_id, data); | 1774 success = thumbnail_db_->GetPageThumbnail(url_id, data); |
1765 } | 1775 } |
1766 } | 1776 } |
1767 } | 1777 } |
1768 | 1778 |
1769 return success; | 1779 return success; |
1770 } | 1780 } |
1771 | 1781 |
1772 void HistoryBackend::GetFavicon(scoped_refptr<GetFaviconRequest> request, | 1782 void HistoryBackend::GetFavicons( |
1773 const GURL& icon_url, | 1783 scoped_refptr<GetFaviconRequest> request, |
1774 int icon_types) { | 1784 const std::vector<GURL>& icon_urls, |
1775 UpdateFaviconMappingAndFetchImpl(NULL, icon_url, request, icon_types); | 1785 int icon_types, |
| 1786 int desired_size_in_dip, |
| 1787 const std::vector<ui::ScaleFactor>& desired_scale_factors) { |
| 1788 UpdateFaviconMappingsAndFetchImpl(request, NULL, icon_urls, icon_types, |
| 1789 desired_size_in_dip, desired_scale_factors); |
1776 } | 1790 } |
1777 | 1791 |
1778 void HistoryBackend::UpdateFaviconMappingAndFetch( | 1792 void HistoryBackend::GetFaviconsForURL( |
1779 scoped_refptr<GetFaviconRequest> request, | 1793 scoped_refptr<GetFaviconRequest> request, |
1780 const GURL& page_url, | 1794 const GURL& page_url, |
1781 const GURL& icon_url, | 1795 int icon_types, |
1782 IconType icon_type) { | 1796 int desired_size_in_dip, |
1783 UpdateFaviconMappingAndFetchImpl(&page_url, icon_url, request, icon_type); | 1797 const std::vector<ui::ScaleFactor>& desired_scale_factors) { |
| 1798 if (request->canceled()) |
| 1799 return; |
| 1800 |
| 1801 std::vector<FaviconBitmapResult> favicon_bitmap_results; |
| 1802 IconURLSizesMap icon_url_sizes; |
| 1803 |
| 1804 // Get results from DB. |
| 1805 GetFaviconsFromDB(page_url, icon_types, desired_size_in_dip, |
| 1806 desired_scale_factors, &favicon_bitmap_results, &icon_url_sizes); |
| 1807 |
| 1808 request->ForwardResult(request->handle(), favicon_bitmap_results, |
| 1809 icon_url_sizes); |
1784 } | 1810 } |
1785 | 1811 |
1786 void HistoryBackend::SetFaviconOutOfDateForPage(const GURL& page_url) { | 1812 void HistoryBackend::GetFaviconForID(scoped_refptr<GetFaviconRequest> request, |
| 1813 FaviconID favicon_id, |
| 1814 int desired_size_in_dip, |
| 1815 ui::ScaleFactor desired_scale_factor) { |
| 1816 if (request->canceled()) |
| 1817 return; |
| 1818 |
| 1819 std::vector<FaviconID> favicon_ids; |
| 1820 favicon_ids.push_back(favicon_id); |
| 1821 std::vector<ui::ScaleFactor> desired_scale_factors; |
| 1822 desired_scale_factors.push_back(desired_scale_factor); |
| 1823 |
| 1824 // Get results from DB. |
| 1825 std::vector<FaviconBitmapResult> favicon_bitmap_results; |
| 1826 GetFaviconBitmapResultsForBestMatch(favicon_ids, desired_size_in_dip, |
| 1827 desired_scale_factors, &favicon_bitmap_results); |
| 1828 |
| 1829 IconURLSizesMap icon_url_sizes; |
| 1830 BuildIconURLSizesMap(favicon_ids, &icon_url_sizes); |
| 1831 |
| 1832 request->ForwardResult(request->handle(), favicon_bitmap_results, |
| 1833 icon_url_sizes); |
| 1834 } |
| 1835 |
| 1836 void HistoryBackend::UpdateFaviconMappingsAndFetch( |
| 1837 scoped_refptr<GetFaviconRequest> request, |
| 1838 const GURL& page_url, |
| 1839 const std::vector<GURL>& icon_urls, |
| 1840 int icon_types, |
| 1841 int desired_size_in_dip, |
| 1842 const std::vector<ui::ScaleFactor>& desired_scale_factors) { |
| 1843 UpdateFaviconMappingsAndFetchImpl(request, &page_url, icon_urls, icon_types, |
| 1844 desired_size_in_dip, desired_scale_factors); |
| 1845 } |
| 1846 |
| 1847 void HistoryBackend::SetFavicons( |
| 1848 const GURL& page_url, |
| 1849 IconType icon_type, |
| 1850 const std::vector<FaviconBitmapData>& favicon_bitmap_data, |
| 1851 const IconURLSizesMap& icon_url_sizes) { |
| 1852 if (!thumbnail_db_.get() || !db_.get()) |
| 1853 return; |
| 1854 |
| 1855 DCHECK(ValidateSetFaviconsParams(favicon_bitmap_data, icon_url_sizes)); |
| 1856 |
| 1857 // Build map of FaviconBitmapData for each icon url. |
| 1858 typedef std::map<GURL, std::vector<FaviconBitmapData> > |
| 1859 BitmapDataByIconURL; |
| 1860 BitmapDataByIconURL grouped_by_icon_url; |
| 1861 for (size_t i = 0; i < favicon_bitmap_data.size(); ++i) { |
| 1862 const GURL& icon_url = favicon_bitmap_data[i].icon_url; |
| 1863 grouped_by_icon_url[icon_url].push_back(favicon_bitmap_data[i]); |
| 1864 } |
| 1865 |
| 1866 std::vector<FaviconID> icon_ids; |
| 1867 for (IconURLSizesMap::const_iterator it = icon_url_sizes.begin(); |
| 1868 it != icon_url_sizes.end(); ++it) { |
| 1869 const GURL& icon_url = it->first; |
| 1870 FaviconID icon_id = |
| 1871 thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type, NULL); |
| 1872 if (icon_id) |
| 1873 SetFaviconSizes(icon_id, it->second); |
| 1874 else |
| 1875 icon_id = thumbnail_db_->AddFavicon(icon_url, icon_type, it->second); |
| 1876 icon_ids.push_back(icon_id); |
| 1877 |
| 1878 BitmapDataByIconURL::iterator grouped_by_icon_url_it = |
| 1879 grouped_by_icon_url.find(icon_url); |
| 1880 if (grouped_by_icon_url_it != grouped_by_icon_url.end()) |
| 1881 SetFaviconBitmaps(icon_id, grouped_by_icon_url_it->second); |
| 1882 } |
| 1883 |
| 1884 SetFaviconMappingsForPageAndRedirects(page_url, icon_type, icon_ids); |
| 1885 } |
| 1886 |
| 1887 void HistoryBackend::SetFaviconsOutOfDateForPage(const GURL& page_url) { |
1787 std::vector<IconMapping> icon_mappings; | 1888 std::vector<IconMapping> icon_mappings; |
1788 | 1889 |
1789 if (!thumbnail_db_.get() || | 1890 if (!thumbnail_db_.get() || |
1790 !thumbnail_db_->GetIconMappingsForPageURL(page_url, | 1891 !thumbnail_db_->GetIconMappingsForPageURL(page_url, |
1791 &icon_mappings)) | 1892 &icon_mappings)) |
1792 return; | 1893 return; |
1793 | 1894 |
1794 for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); | 1895 for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); |
1795 m != icon_mappings.end(); ++m) { | 1896 m != icon_mappings.end(); ++m) { |
1796 thumbnail_db_->SetFaviconOutOfDate(m->icon_id); | 1897 thumbnail_db_->SetFaviconOutOfDate(m->icon_id); |
1797 } | 1898 } |
1798 ScheduleCommit(); | 1899 ScheduleCommit(); |
1799 } | 1900 } |
1800 | 1901 |
1801 void HistoryBackend::CloneFavicon(const GURL& old_page_url, | 1902 void HistoryBackend::CloneFavicons(const GURL& old_page_url, |
1802 const GURL& new_page_url) { | 1903 const GURL& new_page_url) { |
1803 if (!thumbnail_db_.get()) | 1904 if (!thumbnail_db_.get()) |
1804 return; | 1905 return; |
1805 | 1906 |
1806 // Prevent cross-domain cloning. | 1907 // Prevent cross-domain cloning. |
1807 if (old_page_url.GetOrigin() != new_page_url.GetOrigin()) | 1908 if (old_page_url.GetOrigin() != new_page_url.GetOrigin()) |
1808 return; | 1909 return; |
1809 | 1910 |
1810 thumbnail_db_->CloneIconMappings(old_page_url, new_page_url); | 1911 thumbnail_db_->CloneIconMappings(old_page_url, new_page_url); |
1811 ScheduleCommit(); | 1912 ScheduleCommit(); |
1812 } | 1913 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1870 | 1971 |
1871 if (!favicons_changed.empty()) { | 1972 if (!favicons_changed.empty()) { |
1872 // Send the notification about the changed favicon URLs. | 1973 // Send the notification about the changed favicon URLs. |
1873 FaviconChangeDetails* changed_details = new FaviconChangeDetails; | 1974 FaviconChangeDetails* changed_details = new FaviconChangeDetails; |
1874 changed_details->urls.swap(favicons_changed); | 1975 changed_details->urls.swap(favicons_changed); |
1875 BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, | 1976 BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, |
1876 changed_details); | 1977 changed_details); |
1877 } | 1978 } |
1878 } | 1979 } |
1879 | 1980 |
1880 void HistoryBackend::UpdateFaviconMappingAndFetchImpl( | 1981 void HistoryBackend::UpdateFaviconMappingsAndFetchImpl( |
| 1982 scoped_refptr<GetFaviconRequest> request, |
1881 const GURL* page_url, | 1983 const GURL* page_url, |
1882 const GURL& icon_url, | 1984 const std::vector<GURL>& icon_urls, |
1883 scoped_refptr<GetFaviconRequest> request, | 1985 int icon_types, |
1884 int icon_types) { | 1986 int desired_size_in_dip, |
1885 // Check only a single type was given when the page_url was specified. | 1987 const std::vector<ui::ScaleFactor>& desired_scale_factors) { |
1886 DCHECK(!page_url || (page_url && (icon_types == FAVICON || | 1988 // If |page_url| is specified, |icon_types| must be either a single icon |
1887 icon_types == TOUCH_ICON || icon_types == TOUCH_PRECOMPOSED_ICON))); | 1989 // type or icon types which are equivalent. |
1888 | 1990 DCHECK(!page_url || |
1889 if (request->canceled()) | 1991 icon_types == FAVICON || |
| 1992 icon_types == TOUCH_ICON || |
| 1993 icon_types == TOUCH_PRECOMPOSED_ICON || |
| 1994 icon_types == (TOUCH_ICON | TOUCH_PRECOMPOSED_ICON)); |
| 1995 |
| 1996 if (request->canceled() || !thumbnail_db_.get()) |
1890 return; | 1997 return; |
1891 | 1998 |
1892 std::vector<history::FaviconBitmapResult> favicon_bitmap_results; | 1999 std::vector<FaviconID> favicon_ids; |
1893 | 2000 |
1894 if (thumbnail_db_.get()) { | 2001 // The icon type for which the mappings will the updated and data will be |
1895 IconType icon_type; | 2002 // returned. |
1896 const FaviconID favicon_id = | 2003 IconType selected_icon_type = INVALID_ICON; |
1897 thumbnail_db_->GetFaviconIDForFaviconURL( | 2004 |
1898 icon_url, icon_types, &icon_type); | 2005 for (size_t i = 0; i < icon_urls.size(); ++i) { |
| 2006 const GURL& icon_url = icon_urls[i]; |
| 2007 IconType icon_type_out; |
| 2008 const FaviconID favicon_id = thumbnail_db_->GetFaviconIDForFaviconURL( |
| 2009 icon_url, icon_types, &icon_type_out); |
| 2010 |
1899 if (favicon_id) { | 2011 if (favicon_id) { |
1900 GetFaviconFromDB(favicon_id, &favicon_bitmap_results); | 2012 // Return and update icon mappings only for the largest icon type. As |
1901 | 2013 // |icon_urls| is not sorted in terms of icon type, clear |favicon_ids| |
1902 if (page_url) | 2014 // if an |icon_url| with a larger icon type is found. |
1903 SetFaviconMapping(*page_url, favicon_id, icon_type); | 2015 if (icon_type_out > selected_icon_type) { |
1904 } | 2016 selected_icon_type = icon_type_out; |
1905 // else case, haven't cached entry yet. Caller is responsible for | 2017 favicon_ids.clear(); |
1906 // downloading the favicon and invoking SetFavicon. | 2018 } |
1907 } | 2019 if (icon_type_out == selected_icon_type) |
1908 // TODO(pkotwicz): Pass map of |icon_url| to the sizes available from the web | 2020 favicon_ids.push_back(favicon_id); |
1909 // at |icon_url| instead of an empty map. | 2021 } |
| 2022 } |
| 2023 |
| 2024 if (page_url && !favicon_ids.empty()) { |
| 2025 SetFaviconMappingsForPageAndRedirects(*page_url, selected_icon_type, |
| 2026 favicon_ids); |
| 2027 } |
| 2028 |
| 2029 std::vector<FaviconBitmapResult> favicon_bitmap_results; |
| 2030 GetFaviconBitmapResultsForBestMatch(favicon_ids, desired_size_in_dip, |
| 2031 desired_scale_factors, &favicon_bitmap_results); |
| 2032 IconURLSizesMap icon_url_sizes; |
| 2033 BuildIconURLSizesMap(favicon_ids, &icon_url_sizes); |
| 2034 |
1910 request->ForwardResult(request->handle(), favicon_bitmap_results, | 2035 request->ForwardResult(request->handle(), favicon_bitmap_results, |
1911 IconURLSizesMap()); | 2036 icon_url_sizes); |
1912 } | 2037 } |
1913 | 2038 |
1914 void HistoryBackend::GetFaviconForURL( | 2039 void HistoryBackend::SetFaviconBitmaps( |
1915 scoped_refptr<GetFaviconRequest> request, | 2040 FaviconID icon_id, |
| 2041 const std::vector<FaviconBitmapData>& favicon_bitmap_data) { |
| 2042 std::vector<FaviconBitmapIDSize> bitmap_id_sizes; |
| 2043 thumbnail_db_->GetFaviconBitmapIDSizes(icon_id, &bitmap_id_sizes); |
| 2044 |
| 2045 // A nested loop is ok because in practice neither |favicon_bitmap_data| nor |
| 2046 // |bitmap_id_sizes| will have many elements. |
| 2047 for (size_t i = 0; i < favicon_bitmap_data.size(); ++i) { |
| 2048 const FaviconBitmapData& bitmap_data_element = favicon_bitmap_data[i]; |
| 2049 FaviconBitmapID bitmap_id = 0; |
| 2050 for (size_t j = 0; j < bitmap_id_sizes.size(); ++j) { |
| 2051 if (bitmap_id_sizes[j].pixel_size == bitmap_data_element.pixel_size) { |
| 2052 bitmap_id = bitmap_id_sizes[j].bitmap_id; |
| 2053 break; |
| 2054 } |
| 2055 } |
| 2056 if (bitmap_id) { |
| 2057 thumbnail_db_->SetFaviconBitmap(bitmap_id, |
| 2058 bitmap_data_element.bitmap_data, base::Time::Now()); |
| 2059 } else { |
| 2060 thumbnail_db_->AddFaviconBitmap(icon_id, bitmap_data_element.bitmap_data, |
| 2061 base::Time::Now(), bitmap_data_element.pixel_size); |
| 2062 } |
| 2063 } |
| 2064 } |
| 2065 |
| 2066 bool HistoryBackend::ValidateSetFaviconsParams( |
| 2067 const std::vector<FaviconBitmapData>& favicon_bitmap_data, |
| 2068 const IconURLSizesMap& icon_url_sizes) const { |
| 2069 if (icon_url_sizes.size() > kMaxFaviconsPerPage) |
| 2070 return false; |
| 2071 |
| 2072 for (IconURLSizesMap::const_iterator it = icon_url_sizes.begin(); |
| 2073 it != icon_url_sizes.end(); ++it) { |
| 2074 if (it->second.size() > kMaxFaviconBitmapsPerIconURL) |
| 2075 return false; |
| 2076 } |
| 2077 |
| 2078 for (size_t i = 0; i < favicon_bitmap_data.size(); ++i) { |
| 2079 if (!favicon_bitmap_data[i].bitmap_data.get()) |
| 2080 return false; |
| 2081 |
| 2082 IconURLSizesMap::const_iterator it = |
| 2083 icon_url_sizes.find(favicon_bitmap_data[i].icon_url); |
| 2084 if (it == icon_url_sizes.end()) |
| 2085 return false; |
| 2086 |
| 2087 const FaviconSizes& favicon_sizes = it->second; |
| 2088 FaviconSizes::const_iterator it2 = std::find(favicon_sizes.begin(), |
| 2089 favicon_sizes.end(), favicon_bitmap_data[i].pixel_size); |
| 2090 if (it2 == favicon_sizes.end()) |
| 2091 return false; |
| 2092 } |
| 2093 return true; |
| 2094 } |
| 2095 |
| 2096 void HistoryBackend::SetFaviconSizes( |
| 2097 FaviconID icon_id, |
| 2098 const FaviconSizes& favicon_sizes) { |
| 2099 std::vector<FaviconBitmapIDSize> bitmap_id_sizes; |
| 2100 thumbnail_db_->GetFaviconBitmapIDSizes(icon_id, &bitmap_id_sizes); |
| 2101 |
| 2102 // Remove bitmaps whose pixel size is not contained in |favicon_sizes|. |
| 2103 for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) { |
| 2104 const gfx::Size& pixel_size = bitmap_id_sizes[i].pixel_size; |
| 2105 FaviconSizes::const_iterator sizes_it = std::find(favicon_sizes.begin(), |
| 2106 favicon_sizes.end(), pixel_size); |
| 2107 if (sizes_it == favicon_sizes.end()) |
| 2108 thumbnail_db_->DeleteFaviconBitmap(bitmap_id_sizes[i].bitmap_id); |
| 2109 } |
| 2110 |
| 2111 thumbnail_db_->SetFaviconSizes(icon_id, favicon_sizes); |
| 2112 } |
| 2113 |
| 2114 bool HistoryBackend::GetFaviconsFromDB( |
1916 const GURL& page_url, | 2115 const GURL& page_url, |
1917 int icon_types) { | 2116 int icon_types, |
1918 if (request->canceled()) | 2117 int desired_size_in_dip, |
1919 return; | 2118 const std::vector<ui::ScaleFactor>& desired_scale_factors, |
1920 | 2119 std::vector<FaviconBitmapResult>* favicon_bitmap_results, |
1921 std::vector<FaviconBitmapResult> favicon_bitmap_results; | 2120 IconURLSizesMap* icon_url_sizes) { |
1922 | 2121 DCHECK(favicon_bitmap_results); |
1923 // Get the favicon from DB. | 2122 DCHECK(icon_url_sizes); |
1924 GetFaviconFromDB(page_url, icon_types, &favicon_bitmap_results); | 2123 |
1925 | 2124 if (!db_.get() || !thumbnail_db_.get()) |
1926 // TODO(pkotwicz): Pass map of matched icon URLs for |icon_types| to the | 2125 return false; |
1927 // sizes that each icon URL is available at from the web instead of an | 2126 |
1928 // empty map. | 2127 // Time the query. |
1929 request->ForwardResult(request->handle(), favicon_bitmap_results, | 2128 TimeTicks beginning_time = TimeTicks::Now(); |
1930 IconURLSizesMap()); | 2129 |
1931 } | 2130 // Get FaviconIDs for |page_url| and one of |icon_types|. |
1932 | 2131 std::vector<IconMapping> icon_mappings; |
1933 void HistoryBackend::GetFaviconForID(scoped_refptr<GetFaviconRequest> request, | 2132 thumbnail_db_->GetIconMappingsForPageURL(page_url, icon_types, |
1934 FaviconID id) { | 2133 &icon_mappings); |
1935 if (request->canceled()) | 2134 std::vector<FaviconID> favicon_ids; |
1936 return; | 2135 for (size_t i = 0; i < icon_mappings.size(); ++i) |
1937 | 2136 favicon_ids.push_back(icon_mappings[i].icon_id); |
1938 std::vector<FaviconBitmapResult> favicon_bitmap_results; | 2137 |
1939 | 2138 // Populate |favicon_bitmap_results| and |icon_url_sizes|. |
1940 // Get the favicon from DB. | 2139 bool success = |
1941 GetFaviconFromDB(id, &favicon_bitmap_results); | 2140 GetFaviconBitmapResultsForBestMatch(favicon_ids, |
1942 | 2141 desired_size_in_dip, desired_scale_factors, favicon_bitmap_results) && |
1943 // TODO(pkotwicz): Pass map of the matched icon URL to the sizes that it is | 2142 BuildIconURLSizesMap(favicon_ids, icon_url_sizes); |
1944 // available from the web instead of an empty map. | 2143 UMA_HISTOGRAM_TIMES("History.GetFavIconFromDB", // historical name |
1945 request->ForwardResult(request->handle(), favicon_bitmap_results, | 2144 TimeTicks::Now() - beginning_time); |
1946 IconURLSizesMap()); | 2145 return success && !icon_url_sizes->empty(); |
1947 } | 2146 } |
1948 | 2147 |
1949 void HistoryBackend::SetFavicon( | 2148 bool HistoryBackend::GetFaviconBitmapResultsForBestMatch( |
| 2149 const std::vector<FaviconID>& candidate_favicon_ids, |
| 2150 int desired_size_in_dip, |
| 2151 const std::vector<ui::ScaleFactor>& desired_scale_factors, |
| 2152 std::vector<history::FaviconBitmapResult>* favicon_bitmap_results) { |
| 2153 favicon_bitmap_results->clear(); |
| 2154 |
| 2155 if (candidate_favicon_ids.empty()) |
| 2156 return true; |
| 2157 |
| 2158 // Find the FaviconID and the FaviconBitmapIDs which best match |
| 2159 // |desired_size_in_dip| and |desired_scale_factors|. |
| 2160 // TODO(pkotwicz): Select bitmap results from multiple favicons once |
| 2161 // content::FaviconStatus supports multiple icon URLs. |
| 2162 FaviconID best_favicon_id = 0; |
| 2163 std::vector<FaviconBitmapID> best_bitmap_ids; |
| 2164 float highest_score = kSelectFaviconFramesInvalidScore; |
| 2165 for (size_t i = 0; i < candidate_favicon_ids.size(); ++i) { |
| 2166 std::vector<FaviconBitmapIDSize> bitmap_id_sizes; |
| 2167 thumbnail_db_->GetFaviconBitmapIDSizes(candidate_favicon_ids[i], |
| 2168 &bitmap_id_sizes); |
| 2169 |
| 2170 std::vector<FaviconBitmapID> candidate_bitmap_ids; |
| 2171 float score = 0; |
| 2172 SelectFaviconBitmapIDs(bitmap_id_sizes, |
| 2173 desired_scale_factors, |
| 2174 desired_size_in_dip, |
| 2175 &candidate_bitmap_ids, |
| 2176 &score); |
| 2177 if (score > highest_score) { |
| 2178 best_favicon_id = candidate_favicon_ids[i], |
| 2179 best_bitmap_ids.swap(candidate_bitmap_ids); |
| 2180 highest_score = score; |
| 2181 } |
| 2182 } |
| 2183 |
| 2184 // Construct FaviconBitmapResults from |best_favicon_id| and |
| 2185 // |best_bitmap_ids|. |
| 2186 GURL icon_url; |
| 2187 IconType icon_type; |
| 2188 if (!thumbnail_db_->GetFaviconHeader(best_favicon_id, &icon_url, |
| 2189 &icon_type, NULL)) { |
| 2190 return false; |
| 2191 } |
| 2192 |
| 2193 for (size_t i = 0; i < best_bitmap_ids.size(); ++i) { |
| 2194 base::Time last_updated; |
| 2195 FaviconBitmapResult bitmap_result; |
| 2196 bitmap_result.icon_url = icon_url; |
| 2197 bitmap_result.icon_type = icon_type; |
| 2198 if (!thumbnail_db_->GetFaviconBitmap(best_bitmap_ids[i], |
| 2199 &last_updated, |
| 2200 &bitmap_result.bitmap_data, |
| 2201 &bitmap_result.pixel_size)) { |
| 2202 return false; |
| 2203 } |
| 2204 |
| 2205 bitmap_result.expired = (Time::Now() - last_updated) > |
| 2206 TimeDelta::FromDays(kFaviconRefetchDays); |
| 2207 if (bitmap_result.is_valid()) |
| 2208 favicon_bitmap_results->push_back(bitmap_result); |
| 2209 } |
| 2210 return true; |
| 2211 } |
| 2212 |
| 2213 bool HistoryBackend::BuildIconURLSizesMap( |
| 2214 const std::vector<FaviconID>& favicon_ids, |
| 2215 IconURLSizesMap* icon_url_sizes) { |
| 2216 icon_url_sizes->clear(); |
| 2217 for (size_t i = 0; i < favicon_ids.size(); ++i) { |
| 2218 GURL icon_url; |
| 2219 FaviconSizes favicon_sizes; |
| 2220 if (!thumbnail_db_->GetFaviconHeader(favicon_ids[i], &icon_url, NULL, |
| 2221 &favicon_sizes)) { |
| 2222 return false; |
| 2223 } |
| 2224 (*icon_url_sizes)[icon_url] = favicon_sizes; |
| 2225 } |
| 2226 return true; |
| 2227 } |
| 2228 |
| 2229 void HistoryBackend::SetFaviconMappingsForPageAndRedirects( |
1950 const GURL& page_url, | 2230 const GURL& page_url, |
1951 const GURL& icon_url, | 2231 IconType icon_type, |
1952 scoped_refptr<base::RefCountedMemory> data, | 2232 const std::vector<FaviconID>& icon_ids) { |
1953 IconType icon_type) { | |
1954 DCHECK(data.get()); | |
1955 if (!thumbnail_db_.get() || !db_.get()) | |
1956 return; | |
1957 | |
1958 FaviconID id = thumbnail_db_->GetFaviconIDForFaviconURL( | |
1959 icon_url, icon_type, NULL); | |
1960 if (!id) { | |
1961 id = thumbnail_db_->AddFavicon(icon_url, | |
1962 icon_type, | |
1963 GetDefaultFaviconSizes(), | |
1964 data, | |
1965 Time::Now(), | |
1966 gfx::Size()); | |
1967 } else { | |
1968 thumbnail_db_->DeleteFaviconBitmapsForFavicon(id); | |
1969 thumbnail_db_->AddFaviconBitmap(id, data, Time::Now(), gfx::Size()); | |
1970 } | |
1971 | |
1972 SetFaviconMapping(page_url, id, icon_type); | |
1973 } | |
1974 | |
1975 void HistoryBackend::SetFaviconMapping(const GURL& page_url, | |
1976 FaviconID id, | |
1977 IconType icon_type) { | |
1978 if (!thumbnail_db_.get()) | 2233 if (!thumbnail_db_.get()) |
1979 return; | 2234 return; |
1980 | 2235 |
1981 // Find all the pages whose favicons we should set, we want to set it for | 2236 // Find all the pages whose favicons we should set, we want to set it for |
1982 // all the pages in the redirect chain if it redirected. | 2237 // all the pages in the redirect chain if it redirected. |
1983 history::RedirectList dummy_list; | 2238 history::RedirectList dummy_list; |
1984 history::RedirectList* redirects; | 2239 history::RedirectList* redirects; |
1985 RedirectCache::iterator iter = recent_redirects_.Get(page_url); | 2240 RedirectCache::iterator iter = recent_redirects_.Get(page_url); |
1986 if (iter != recent_redirects_.end()) { | 2241 if (iter != recent_redirects_.end()) { |
1987 redirects = &iter->second; | 2242 redirects = &iter->second; |
1988 | 2243 |
1989 // This redirect chain should have the destination URL as the last item. | 2244 // This redirect chain should have the destination URL as the last item. |
1990 DCHECK(!redirects->empty()); | 2245 DCHECK(!redirects->empty()); |
1991 DCHECK(redirects->back() == page_url); | 2246 DCHECK(redirects->back() == page_url); |
1992 } else { | 2247 } else { |
1993 // No redirect chain stored, make up one containing the URL we want to we | 2248 // No redirect chain stored, make up one containing the URL we want to we |
1994 // can use the same logic below. | 2249 // can use the same logic below. |
1995 dummy_list.push_back(page_url); | 2250 dummy_list.push_back(page_url); |
1996 redirects = &dummy_list; | 2251 redirects = &dummy_list; |
1997 } | 2252 } |
1998 | 2253 |
1999 std::set<GURL> favicons_changed; | 2254 std::set<GURL> favicons_changed; |
2000 | 2255 |
2001 // Save page <-> favicon association. | 2256 // Save page <-> favicon associations. |
2002 for (history::RedirectList::const_iterator i(redirects->begin()); | 2257 for (history::RedirectList::const_iterator i(redirects->begin()); |
2003 i != redirects->end(); ++i) { | 2258 i != redirects->end(); ++i) { |
2004 FaviconID replaced_id; | 2259 if (SetFaviconMappingsForPage(*i, icon_type, icon_ids)) |
2005 if (AddOrUpdateIconMapping(*i, id, icon_type, &replaced_id)) { | |
2006 // The page's favicon ID changed. This means that the one we just | |
2007 // changed from could have been orphaned, and we need to re-check it. | |
2008 // This is not super fast, but this case will get triggered rarely, | |
2009 // since normally a page will always map to the same favicon ID. It | |
2010 // will mostly happen for favicons we import. | |
2011 if (replaced_id && !thumbnail_db_->HasMappingFor(replaced_id)) | |
2012 thumbnail_db_->DeleteFavicon(replaced_id); | |
2013 | |
2014 favicons_changed.insert(*i); | 2260 favicons_changed.insert(*i); |
2015 } | |
2016 } | 2261 } |
2017 | 2262 |
2018 // Send the notification about the changed favicons. | 2263 // Send the notification about the changed favicons. |
2019 FaviconChangeDetails* changed_details = new FaviconChangeDetails; | 2264 FaviconChangeDetails* changed_details = new FaviconChangeDetails; |
2020 changed_details->urls.swap(favicons_changed); | 2265 changed_details->urls.swap(favicons_changed); |
2021 BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, | 2266 BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, |
2022 changed_details); | 2267 changed_details); |
2023 | 2268 |
2024 ScheduleCommit(); | 2269 ScheduleCommit(); |
2025 } | 2270 } |
2026 | 2271 |
2027 bool HistoryBackend::AddOrUpdateIconMapping(const GURL& page_url, | 2272 bool HistoryBackend::SetFaviconMappingsForPage( |
2028 FaviconID id, | 2273 const GURL& page_url, |
2029 IconType icon_type, | 2274 IconType icon_type, |
2030 FaviconID* replaced_icon) { | 2275 const std::vector<FaviconID>& icon_ids) { |
2031 *replaced_icon = 0; | 2276 DCHECK_LE(icon_ids.size(), kMaxFaviconsPerPage); |
| 2277 bool mappings_changed = false; |
| 2278 |
| 2279 // Two icon types are considered 'equivalent' if one of the icon types is |
| 2280 // TOUCH_ICON and the other is TOUCH_PRECOMPOSED_ICON. |
| 2281 // |
| 2282 // Sets the icon mappings from |page_url| for |icon_type| to the favicons |
| 2283 // with |icon_ids|. Mappings for |page_url| to favicons of type |icon_type| |
| 2284 // whose FaviconID is not in |icon_ids| are removed. All icon mappings for |
| 2285 // |page_url| to favicons of a type equivalent to |icon_type| are removed. |
| 2286 // Remove any favicons which are orphaned as a result of the removal of the |
| 2287 // icon mappings. |
| 2288 |
| 2289 std::vector<FaviconID> unmapped_icon_ids = icon_ids; |
| 2290 |
2032 std::vector<IconMapping> icon_mappings; | 2291 std::vector<IconMapping> icon_mappings; |
2033 if (!thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings)) { | 2292 thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings); |
2034 // There is no mapping add it directly. | 2293 |
2035 thumbnail_db_->AddIconMapping(page_url, id); | |
2036 return true; | |
2037 } | |
2038 // Iterate all matched icon mappings, | |
2039 // a. If the given icon id and matched icon id are same, return. | |
2040 // b. If the given icon type and matched icon type are same, but icon id | |
2041 // are not, update the IconMapping. | |
2042 // c. If the given icon_type and matched icon type are not same, but | |
2043 // either of them is ICON_TOUCH or ICON_PRECOMPOSED_TOUCH, update the | |
2044 // IconMapping. | |
2045 // d. Otherwise add a icon mapping. | |
2046 for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); | 2294 for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); |
2047 m != icon_mappings.end(); ++m) { | 2295 m != icon_mappings.end(); ++m) { |
2048 if (m->icon_id == id) | 2296 std::vector<FaviconID>::iterator icon_id_it = std::find( |
2049 // The mapping is already there. | 2297 unmapped_icon_ids.begin(), unmapped_icon_ids.end(), m->icon_id); |
2050 return false; | 2298 |
| 2299 // If the icon mapping already exists, avoid removing it and adding it back. |
| 2300 if (icon_id_it != unmapped_icon_ids.end()) { |
| 2301 unmapped_icon_ids.erase(icon_id_it); |
| 2302 continue; |
| 2303 } |
2051 | 2304 |
2052 if ((icon_type == TOUCH_ICON && m->icon_type == TOUCH_PRECOMPOSED_ICON) || | 2305 if ((icon_type == TOUCH_ICON && m->icon_type == TOUCH_PRECOMPOSED_ICON) || |
2053 (icon_type == TOUCH_PRECOMPOSED_ICON && m->icon_type == TOUCH_ICON) || | 2306 (icon_type == TOUCH_PRECOMPOSED_ICON && m->icon_type == TOUCH_ICON) || |
2054 (icon_type == m->icon_type)) { | 2307 (icon_type == m->icon_type)) { |
2055 thumbnail_db_->UpdateIconMapping(m->mapping_id, id); | 2308 thumbnail_db_->DeleteIconMapping(m->mapping_id); |
2056 *replaced_icon = m->icon_id; | 2309 |
2057 return true; | 2310 // Removing the icon mapping may have orphaned the associated favicon so |
| 2311 // we must recheck it. This is not super fast, but this case will get |
| 2312 // triggered rarely, since normally a page will always map to the same |
| 2313 // favicon IDs. It will mostly happen for favicons we import. |
| 2314 if (!thumbnail_db_->HasMappingFor(m->icon_id)) |
| 2315 thumbnail_db_->DeleteFavicon(m->icon_id); |
| 2316 mappings_changed = true; |
2058 } | 2317 } |
2059 } | 2318 } |
2060 thumbnail_db_->AddIconMapping(page_url, id); | 2319 |
2061 return true; | 2320 for (size_t i = 0; i < unmapped_icon_ids.size(); ++i ) { |
| 2321 thumbnail_db_->AddIconMapping(page_url, unmapped_icon_ids[i]); |
| 2322 mappings_changed = true; |
| 2323 } |
| 2324 return mappings_changed; |
2062 } | 2325 } |
2063 | 2326 |
2064 void HistoryBackend::Commit() { | 2327 void HistoryBackend::Commit() { |
2065 if (!db_.get()) | 2328 if (!db_.get()) |
2066 return; | 2329 return; |
2067 | 2330 |
2068 // Note that a commit may not actually have been scheduled if a caller | 2331 // Note that a commit may not actually have been scheduled if a caller |
2069 // explicitly calls this instead of using ScheduleCommit. Likewise, we | 2332 // explicitly calls this instead of using ScheduleCommit. Likewise, we |
2070 // may reset the flag written by a pending commit. But this is OK! It | 2333 // may reset the flag written by a pending commit. But this is OK! It |
2071 // will merely cause extra commits (which is kind of the idea). We | 2334 // 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... |
2435 | 2698 |
2436 return true; | 2699 return true; |
2437 } | 2700 } |
2438 | 2701 |
2439 BookmarkService* HistoryBackend::GetBookmarkService() { | 2702 BookmarkService* HistoryBackend::GetBookmarkService() { |
2440 if (bookmark_service_) | 2703 if (bookmark_service_) |
2441 bookmark_service_->BlockTillLoaded(); | 2704 bookmark_service_->BlockTillLoaded(); |
2442 return bookmark_service_; | 2705 return bookmark_service_; |
2443 } | 2706 } |
2444 | 2707 |
2445 bool HistoryBackend::GetFaviconFromDB( | |
2446 const GURL& page_url, | |
2447 int icon_types, | |
2448 std::vector<FaviconBitmapResult>* favicon_bitmap_results) { | |
2449 DCHECK(favicon_bitmap_results); | |
2450 | |
2451 if (!db_.get() || !thumbnail_db_.get()) | |
2452 return false; | |
2453 | |
2454 bool success = false; | |
2455 // Time the query. | |
2456 TimeTicks beginning_time = TimeTicks::Now(); | |
2457 | |
2458 std::vector<IconMapping> icon_mappings; | |
2459 // Iterate over the known icons looking for one that includes one of the | |
2460 // requested types. | |
2461 if (thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings)) { | |
2462 for (std::vector<IconMapping>::iterator i = icon_mappings.begin(); | |
2463 i != icon_mappings.end(); ++i) { | |
2464 if ((i->icon_type & icon_types) && | |
2465 GetFaviconFromDB(i->icon_id, favicon_bitmap_results)) { | |
2466 success = true; | |
2467 break; | |
2468 } | |
2469 } | |
2470 } | |
2471 UMA_HISTOGRAM_TIMES("History.GetFavIconFromDB", // historical name | |
2472 TimeTicks::Now() - beginning_time); | |
2473 return success; | |
2474 } | |
2475 | |
2476 bool HistoryBackend::GetFaviconFromDB( | |
2477 FaviconID favicon_id, | |
2478 std::vector<history::FaviconBitmapResult>* favicon_bitmap_results) { | |
2479 FaviconBitmapResult bitmap_result; | |
2480 Time last_updated; | |
2481 if (!thumbnail_db_->GetFaviconHeader(favicon_id, | |
2482 &bitmap_result.icon_url, | |
2483 &bitmap_result.icon_type, | |
2484 NULL)) { | |
2485 return false; | |
2486 } | |
2487 | |
2488 std::vector<FaviconBitmap> favicon_bitmaps; | |
2489 thumbnail_db_->GetFaviconBitmaps(favicon_id, &favicon_bitmaps); | |
2490 if (favicon_bitmaps.empty()) | |
2491 return false; | |
2492 | |
2493 bitmap_result.bitmap_data = favicon_bitmaps[0].bitmap_data; | |
2494 bitmap_result.expired = (Time::Now() - favicon_bitmaps[0].last_updated) > | |
2495 TimeDelta::FromDays(kFaviconRefetchDays); | |
2496 | |
2497 favicon_bitmap_results->clear(); | |
2498 if (bitmap_result.is_valid()) | |
2499 favicon_bitmap_results->push_back(bitmap_result); | |
2500 return true; | |
2501 } | |
2502 | |
2503 void HistoryBackend::NotifyVisitObservers(const VisitRow& visit) { | 2708 void HistoryBackend::NotifyVisitObservers(const VisitRow& visit) { |
2504 BriefVisitInfo info; | 2709 BriefVisitInfo info; |
2505 info.url_id = visit.url_id; | 2710 info.url_id = visit.url_id; |
2506 info.time = visit.visit_time; | 2711 info.time = visit.visit_time; |
2507 info.transition = visit.transition; | 2712 info.transition = visit.transition; |
2508 // If we don't have a delegate yet during setup or shutdown, we will drop | 2713 // If we don't have a delegate yet during setup or shutdown, we will drop |
2509 // these notifications. | 2714 // these notifications. |
2510 if (delegate_.get()) | 2715 if (delegate_.get()) |
2511 delegate_->NotifyVisitDBObserversOnAddVisit(info); | 2716 delegate_->NotifyVisitDBObserversOnAddVisit(info); |
2512 } | 2717 } |
2513 | 2718 |
2514 } // namespace history | 2719 } // namespace history |
OLD | NEW |