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

Side by Side Diff: chrome/browser/history/history_backend.cc

Issue 10802066: Adds support for saving favicon size into history database. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Changes as requested Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View 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 <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"
26 #include "chrome/browser/favicon/select_favicon_frames.h"
25 #include "chrome/browser/history/history_notifications.h" 27 #include "chrome/browser/history/history_notifications.h"
26 #include "chrome/browser/history/history_publisher.h" 28 #include "chrome/browser/history/history_publisher.h"
27 #include "chrome/browser/history/in_memory_history_backend.h" 29 #include "chrome/browser/history/in_memory_history_backend.h"
28 #include "chrome/browser/history/page_usage_data.h" 30 #include "chrome/browser/history/page_usage_data.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"
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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 id,
1814 int desired_size_in_dip,
1815 ui::ScaleFactor desired_scale_factor) {
1816 if (request->canceled())
1817 return;
1818
1819 std::vector<FaviconID> candidate_favicon_ids;
1820 candidate_favicon_ids.push_back(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(candidate_favicon_ids,
1827 desired_size_in_dip, desired_scale_factors, &favicon_bitmap_results);
1828
1829 IconURLSizesMap icon_url_sizes;
1830 BuildIconURLSizesMap(candidate_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::MergeFavicon(
1848 const GURL& page_url,
1849 const GURL& icon_url,
1850 IconType icon_type,
1851 scoped_refptr<base::RefCountedMemory> bitmap_data,
1852 const gfx::Size& pixel_size) {
1853 if (!thumbnail_db_.get() || !db_.get())
1854 return;
1855
1856 gfx::Size merge_pixel_size;
1857 if (!IsMergeValid(page_url, icon_url, icon_type, pixel_size,
1858 &merge_pixel_size)) {
1859 return;
1860 }
1861
1862 FaviconID favicon_id =
1863 thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type, NULL);
1864 if (favicon_id) {
1865 FaviconBitmapData bitmap_data_element;
1866 bitmap_data_element.bitmap_data = bitmap_data;
1867 bitmap_data_element.pixel_size = merge_pixel_size;
1868 bitmap_data_element.icon_url = icon_url;
1869 std::vector<FaviconBitmapData> favicon_bitmap_data;
1870 favicon_bitmap_data.push_back(bitmap_data_element);
1871 SetFaviconBitmaps(favicon_id, favicon_bitmap_data);
1872 } else {
1873 FaviconSizes favicon_sizes;
1874 favicon_sizes.push_back(merge_pixel_size);
1875 favicon_id = thumbnail_db_->AddFavicon(icon_url,
1876 icon_type,
1877 favicon_sizes,
1878 bitmap_data,
1879 base::Time::Now(),
1880 merge_pixel_size);
1881 IconURLFaviconIDMap icon_url_id_map;
1882 icon_url_id_map[icon_url] = favicon_id;
1883 SetFaviconMappingsForPageAndRedirects(page_url, icon_type,
1884 icon_url_id_map);
1885 }
1886 }
1887
1888 void HistoryBackend::SetFavicons(
1889 const GURL& page_url,
1890 IconType icon_type,
1891 const std::vector<FaviconBitmapData>& favicon_bitmap_data,
1892 const IconURLSizesMap& icon_url_sizes) {
1893 if (!thumbnail_db_.get() || !db_.get())
1894 return;
1895
1896 DCHECK(ValidateSetFaviconsParams(favicon_bitmap_data, icon_url_sizes));
1897
1898 // Build map of FaviconBitmapResults for each icon url.
1899 typedef std::map<GURL, std::vector<FaviconBitmapData> >
1900 BitmapDataByIconURL;
1901 BitmapDataByIconURL grouped_by_icon_url;
1902 for (size_t i = 0; i < favicon_bitmap_data.size(); ++i) {
1903 const GURL& icon_url = favicon_bitmap_data[i].icon_url;
1904 grouped_by_icon_url[icon_url].push_back(favicon_bitmap_data[i]);
1905 }
1906
1907 IconURLFaviconIDMap icon_url_id_map;
1908 for (IconURLSizesMap::const_iterator it = icon_url_sizes.begin();
1909 it != icon_url_sizes.end(); ++it) {
1910 const GURL& icon_url = it->first;
1911 FaviconID icon_id =
1912 thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type, NULL);
1913 if (icon_id)
1914 SetFaviconSizes(icon_id, it->second);
1915 else
1916 icon_id = thumbnail_db_->AddFavicon(icon_url, icon_type, it->second);
1917 icon_url_id_map[icon_url] = icon_id;
1918
1919 BitmapDataByIconURL::iterator grouped_by_icon_url_it =
1920 grouped_by_icon_url.find(icon_url);
1921 if (grouped_by_icon_url_it != grouped_by_icon_url.end())
1922 SetFaviconBitmaps(icon_id, grouped_by_icon_url_it->second);
1923 }
1924
1925 SetFaviconMappingsForPageAndRedirects(page_url, icon_type, icon_url_id_map);
1926 }
1927
1928 void HistoryBackend::SetFaviconsOutOfDateForPage(const GURL& page_url) {
1787 std::vector<IconMapping> icon_mappings; 1929 std::vector<IconMapping> icon_mappings;
1788 1930
1789 if (!thumbnail_db_.get() || 1931 if (!thumbnail_db_.get() ||
1790 !thumbnail_db_->GetIconMappingsForPageURL(page_url, 1932 !thumbnail_db_->GetIconMappingsForPageURL(page_url,
1791 &icon_mappings)) 1933 &icon_mappings))
1792 return; 1934 return;
1793 1935
1794 for (std::vector<IconMapping>::iterator m = icon_mappings.begin(); 1936 for (std::vector<IconMapping>::iterator m = icon_mappings.begin();
1795 m != icon_mappings.end(); ++m) { 1937 m != icon_mappings.end(); ++m) {
1796 thumbnail_db_->SetFaviconOutOfDate(m->icon_id); 1938 thumbnail_db_->SetFaviconOutOfDate(m->icon_id);
1797 } 1939 }
1798 ScheduleCommit(); 1940 ScheduleCommit();
1799 } 1941 }
1800 1942
1801 void HistoryBackend::CloneFavicon(const GURL& old_page_url, 1943 void HistoryBackend::CloneFavicons(const GURL& old_page_url,
1802 const GURL& new_page_url) { 1944 const GURL& new_page_url) {
1803 if (!thumbnail_db_.get()) 1945 if (!thumbnail_db_.get())
1804 return; 1946 return;
1805 1947
1806 // Prevent cross-domain cloning. 1948 // Prevent cross-domain cloning.
1807 if (old_page_url.GetOrigin() != new_page_url.GetOrigin()) 1949 if (old_page_url.GetOrigin() != new_page_url.GetOrigin())
1808 return; 1950 return;
1809 1951
1810 thumbnail_db_->CloneIconMappings(old_page_url, new_page_url); 1952 thumbnail_db_->CloneIconMappings(old_page_url, new_page_url);
1811 ScheduleCommit(); 1953 ScheduleCommit();
1812 } 1954 }
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1870 2012
1871 if (!favicons_changed.empty()) { 2013 if (!favicons_changed.empty()) {
1872 // Send the notification about the changed favicon URLs. 2014 // Send the notification about the changed favicon URLs.
1873 FaviconChangeDetails* changed_details = new FaviconChangeDetails; 2015 FaviconChangeDetails* changed_details = new FaviconChangeDetails;
1874 changed_details->urls.swap(favicons_changed); 2016 changed_details->urls.swap(favicons_changed);
1875 BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, 2017 BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED,
1876 changed_details); 2018 changed_details);
1877 } 2019 }
1878 } 2020 }
1879 2021
1880 void HistoryBackend::UpdateFaviconMappingAndFetchImpl( 2022 void HistoryBackend::UpdateFaviconMappingsAndFetchImpl(
2023 scoped_refptr<GetFaviconRequest> request,
1881 const GURL* page_url, 2024 const GURL* page_url,
1882 const GURL& icon_url, 2025 const std::vector<GURL>& icon_urls,
1883 scoped_refptr<GetFaviconRequest> request, 2026 int icon_types,
1884 int icon_types) { 2027 int desired_size_in_dip,
1885 // Check only a single type was given when the page_url was specified. 2028 const std::vector<ui::ScaleFactor>& desired_scale_factors) {
1886 DCHECK(!page_url || (page_url && (icon_types == FAVICON || 2029 // |icon_types| must be either a single icon type or icon types which are
1887 icon_types == TOUCH_ICON || icon_types == TOUCH_PRECOMPOSED_ICON))); 2030 // equivalent.
1888 2031 DCHECK(icon_types == FAVICON ||
1889 if (request->canceled()) 2032 icon_types == TOUCH_ICON ||
2033 icon_types == TOUCH_PRECOMPOSED_ICON ||
2034 icon_types == (TOUCH_ICON | TOUCH_PRECOMPOSED_ICON));
2035
2036 if (request->canceled() || !thumbnail_db_.get())
1890 return; 2037 return;
1891 2038
1892 std::vector<history::FaviconBitmapResult> favicon_bitmap_results; 2039 std::vector<FaviconID> favicon_ids;
1893 2040 IconURLFaviconIDMap icon_url_id_map;
1894 if (thumbnail_db_.get()) { 2041
1895 IconType icon_type; 2042 // The icon type for which the mappings will the updated and data will be
1896 const FaviconID favicon_id = 2043 // returned.
1897 thumbnail_db_->GetFaviconIDForFaviconURL( 2044 IconType selected_icon_type = INVALID_ICON;
1898 icon_url, icon_types, &icon_type); 2045
2046 for (size_t i = 0; i < icon_urls.size(); ++i) {
2047 const GURL& icon_url = icon_urls[i];
2048 IconType icon_type_out;
2049 const FaviconID favicon_id = thumbnail_db_->GetFaviconIDForFaviconURL(
2050 icon_url, icon_types, &icon_type_out);
2051
1899 if (favicon_id) { 2052 if (favicon_id) {
1900 GetFaviconFromDB(favicon_id, &favicon_bitmap_results); 2053 if (icon_type_out > selected_icon_type) {
1901 2054 selected_icon_type = icon_type_out;
1902 if (page_url) 2055 favicon_ids.clear();
1903 SetFaviconMapping(*page_url, favicon_id, icon_type); 2056 icon_url_id_map.clear();
2057 }
2058 if (icon_type_out == selected_icon_type) {
2059 favicon_ids.push_back(favicon_id);
2060 icon_url_id_map[icon_url] = favicon_id;
2061 }
1904 } 2062 }
1905 // else case, haven't cached entry yet. Caller is responsible for 2063 // else case, haven't cached entry yet. Caller is responsible for
1906 // downloading the favicon and invoking SetFavicon. 2064 // downloading the favicon and invoking SetFavicons.
1907 } 2065 }
1908 // TODO(pkotwicz): Pass map of |icon_url| to the sizes available from the web 2066
1909 // at |icon_url| instead of an empty map. 2067 if (page_url) {
2068 SetFaviconMappingsForPageAndRedirects(*page_url, selected_icon_type,
2069 icon_url_id_map);
2070 }
2071
2072 std::vector<FaviconBitmapResult> favicon_bitmap_results;
2073 IconURLSizesMap icon_url_sizes;
2074 GetFaviconBitmapResultsForBestMatch(favicon_ids, desired_size_in_dip,
2075 desired_scale_factors, &favicon_bitmap_results);
2076 BuildIconURLSizesMap(favicon_ids, &icon_url_sizes);
2077
1910 request->ForwardResult(request->handle(), favicon_bitmap_results, 2078 request->ForwardResult(request->handle(), favicon_bitmap_results,
1911 IconURLSizesMap()); 2079 icon_url_sizes);
1912 } 2080 }
1913 2081
1914 void HistoryBackend::GetFaviconForURL( 2082 bool HistoryBackend::IsMergeValid(const GURL& page_url,
1915 scoped_refptr<GetFaviconRequest> request, 2083 const GURL& icon_url,
2084 IconType icon_type,
2085 const gfx::Size& pixel_size,
2086 gfx::Size* merge_pixel_size) {
2087 // Get FaviconIDs for |page_url| and |icon_type|.
2088 std::vector<IconMapping> icon_mappings;
2089 thumbnail_db_->GetIconMappingsForPageURL(page_url, icon_type,
2090 &icon_mappings);
2091
2092 if (!icon_mappings.empty()) {
2093 // There are already mappings for |page_url|. The merge is invalid if
2094 // |icon_url| is not part of the mappings.
2095 bool found_icon_url = false;
2096 for (size_t i = 0; i < icon_mappings.size(); ++i) {
2097 if (icon_mappings[i].icon_url == icon_url) {
2098 found_icon_url = true;
2099 break;
2100 }
2101 }
2102 if (!found_icon_url)
2103 return false;
2104 }
2105
2106 FaviconID favicon_id =
2107 thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, icon_type, NULL);
2108
2109 if (favicon_id) {
2110 FaviconSizes favicon_sizes;
2111 thumbnail_db_->GetFaviconHeader(favicon_id, NULL, NULL, &favicon_sizes);
2112
2113 // The merge is valid if the favicon sizes for |favicon_id| are unkown.
2114 if (favicon_sizes == GetDefaultFaviconSizes()) {
2115 *merge_pixel_size = gfx::Size();
2116 return true;
2117 }
2118
2119 // The merge is invalid if |pixel_size| is not a subset of the favicon
2120 // sizes of |favicon_id|.
2121 FaviconSizes::iterator favicon_sizes_it = std::find(favicon_sizes.begin(),
2122 favicon_sizes.end(), pixel_size);
2123 if (favicon_sizes_it == favicon_sizes.end())
2124 return false;
2125
2126 *merge_pixel_size = *favicon_sizes_it;
2127 return true;
2128 }
2129
2130 // The merge is valid if the database knows neither |page_url| or |icon_url|.
2131 // Use GetDefaultFaviconSizes() as the complete set of favicon sizes the
2132 // favicon is available from the web are unknown.
2133 *merge_pixel_size = gfx::Size();
2134 return true;
2135 }
2136
2137 void HistoryBackend::SetFaviconBitmaps(
2138 FaviconID icon_id,
2139 const std::vector<FaviconBitmapData>& favicon_bitmap_data) {
2140 std::vector<FaviconBitmapIDSize> bitmap_id_sizes;
2141 thumbnail_db_->GetFaviconBitmapIDSizes(icon_id, &bitmap_id_sizes);
2142
2143 // A nested loop is ok because in practice neither |favicon_bitmap_data| nor
2144 // |bitmap_id_sizes| will have many elements.
2145 for (size_t i = 0; i < favicon_bitmap_data.size(); ++i) {
2146 const FaviconBitmapData& bitmap_data_element = favicon_bitmap_data[i];
2147 FaviconBitmapID bitmap_id = 0;
2148 for (size_t j = 0; j < bitmap_id_sizes.size(); ++j) {
2149 if (bitmap_id_sizes[j].pixel_size == bitmap_data_element.pixel_size) {
2150 bitmap_id = bitmap_id_sizes[j].bitmap_id;
2151 break;
2152 }
2153 }
2154 if (bitmap_id) {
2155 thumbnail_db_->SetFaviconBitmap(bitmap_id,
2156 bitmap_data_element.bitmap_data, base::Time::Now());
2157 } else {
2158 thumbnail_db_->AddFaviconBitmap(icon_id, bitmap_data_element.bitmap_data,
2159 base::Time::Now(), bitmap_data_element.pixel_size);
2160 }
2161 }
2162 }
2163
2164 bool HistoryBackend::ValidateSetFaviconsParams(
2165 const std::vector<FaviconBitmapData>& favicon_bitmap_data,
2166 const IconURLSizesMap& icon_url_sizes) const {
michaelbai 2012/09/04 21:18:53 In Android, there is no url associated with the ic
pkotwicz 2012/09/04 22:40:54 It is still valid for IconURLSizesMap to have a ke
2167 if (icon_url_sizes.size() > kMaxFaviconsPerPage)
2168 return false;
2169
2170 for (IconURLSizesMap::const_iterator it = icon_url_sizes.begin();
2171 it != icon_url_sizes.end(); ++it) {
2172 if (it->second.size() > kMaxFaviconBitmapsPerIconURL)
2173 return false;
2174 }
2175
2176 for (size_t i = 0; i < favicon_bitmap_data.size(); ++i) {
2177 if (!favicon_bitmap_data[i].bitmap_data.get())
2178 return false;
2179
2180 IconURLSizesMap::const_iterator it =
2181 icon_url_sizes.find(favicon_bitmap_data[i].icon_url);
2182 if (it == icon_url_sizes.end())
2183 return false;
2184
2185 const FaviconSizes& favicon_sizes = it->second;
2186 FaviconSizes::const_iterator it2 = std::find(favicon_sizes.begin(),
2187 favicon_sizes.end(), favicon_bitmap_data[i].pixel_size);
2188 if (it2 == favicon_sizes.end())
2189 return false;
2190 }
2191 return true;
2192 }
2193
2194 void HistoryBackend::SetFaviconSizes(
2195 FaviconID icon_id,
2196 const FaviconSizes& favicon_sizes) {
2197 std::vector<FaviconBitmapIDSize> bitmap_id_sizes;
2198 thumbnail_db_->GetFaviconBitmapIDSizes(icon_id, &bitmap_id_sizes);
2199
2200 // Remove bitmaps whose pixel size is not contained in |favicon_sizes|.
2201 for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) {
2202 const gfx::Size& pixel_size = bitmap_id_sizes[i].pixel_size;
2203 FaviconSizes::const_iterator sizes_it = std::find(favicon_sizes.begin(),
2204 favicon_sizes.end(), pixel_size);
2205 if (sizes_it == favicon_sizes.end())
2206 thumbnail_db_->DeleteFaviconBitmap(bitmap_id_sizes[i].bitmap_id);
michaelbai 2012/09/04 21:18:53 Not sure, I fully understand the design here, coul
pkotwicz 2012/09/04 22:40:54 This method will delete any favicon bitmaps whose
2207 }
2208
2209 thumbnail_db_->SetFaviconSizes(icon_id, favicon_sizes);
2210 }
2211
2212 bool HistoryBackend::GetFaviconsFromDB(
1916 const GURL& page_url, 2213 const GURL& page_url,
1917 int icon_types) { 2214 int icon_types,
1918 if (request->canceled()) 2215 int desired_size_in_dip,
1919 return; 2216 const std::vector<ui::ScaleFactor>& desired_scale_factors,
1920 2217 std::vector<FaviconBitmapResult>* favicon_bitmap_results,
1921 std::vector<FaviconBitmapResult> favicon_bitmap_results; 2218 IconURLSizesMap* icon_url_sizes) {
1922 2219 DCHECK(favicon_bitmap_results);
1923 // Get the favicon from DB. 2220 DCHECK(icon_url_sizes);
1924 GetFaviconFromDB(page_url, icon_types, &favicon_bitmap_results); 2221
1925 2222 if (!db_.get() || !thumbnail_db_.get())
1926 // TODO(pkotwicz): Pass map of matched icon URLs for |icon_types| to the 2223 return false;
1927 // sizes that each icon URL is available at from the web instead of an 2224
1928 // empty map. 2225 // Time the query.
1929 request->ForwardResult(request->handle(), favicon_bitmap_results, 2226 TimeTicks beginning_time = TimeTicks::Now();
1930 IconURLSizesMap()); 2227
1931 } 2228 // Get FaviconIDs for |page_url| and one of |icon_types|.
1932 2229 std::vector<IconMapping> icon_mappings;
1933 void HistoryBackend::GetFaviconForID(scoped_refptr<GetFaviconRequest> request, 2230 thumbnail_db_->GetIconMappingsForPageURL(page_url, icon_types,
1934 FaviconID id) { 2231 &icon_mappings);
1935 if (request->canceled()) 2232 std::vector<FaviconID> favicon_ids;
1936 return; 2233 for (size_t i = 0; i < icon_mappings.size(); ++i)
1937 2234 favicon_ids.push_back(icon_mappings[i].icon_id);
1938 std::vector<FaviconBitmapResult> favicon_bitmap_results; 2235
1939 2236 // Populate |favicon_bitmap_results| and |icon_url_sizes|.
1940 // Get the favicon from DB. 2237 bool success =
1941 GetFaviconFromDB(id, &favicon_bitmap_results); 2238 GetFaviconBitmapResultsForBestMatch(favicon_ids,
1942 2239 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 2240 BuildIconURLSizesMap(favicon_ids, icon_url_sizes);
1944 // available from the web instead of an empty map. 2241 UMA_HISTOGRAM_TIMES("History.GetFavIconFromDB", // historical name
1945 request->ForwardResult(request->handle(), favicon_bitmap_results, 2242 TimeTicks::Now() - beginning_time);
1946 IconURLSizesMap()); 2243 return success && !icon_url_sizes->empty();
1947 } 2244 }
1948 2245
1949 void HistoryBackend::SetFavicon( 2246 bool HistoryBackend::GetFaviconBitmapResultsForBestMatch(
2247 const std::vector<FaviconID>& candidate_favicon_ids,
2248 int desired_size_in_dip,
2249 const std::vector<ui::ScaleFactor>& desired_scale_factors,
2250 std::vector<history::FaviconBitmapResult>* favicon_bitmap_results) {
2251 if (candidate_favicon_ids.empty())
2252 return false;
2253
2254 // Find the FaviconID and the FaviconBitmapIDs which best match
2255 // |desired_size_in_dip| and |desired_scale_factors|.
2256 // TODO(pkotwicz): Select bitmap results from multiple favicons once
2257 // content::FaviconStatus supports multiple icon URLs.
2258 FaviconID best_favicon_id = 0;
2259 scoped_ptr<std::vector<FaviconBitmapID> > best_bitmap_ids(NULL);
2260 // Set |highest_score| less than min valid score of 0.
2261 float highest_score = -1.0f;
2262 for (size_t i = 0; i < candidate_favicon_ids.size(); ++i) {
2263 std::vector<FaviconBitmapIDSize> bitmap_id_sizes;
2264 thumbnail_db_->GetFaviconBitmapIDSizes(candidate_favicon_ids[i],
2265 &bitmap_id_sizes);
2266
2267 scoped_ptr<std::vector<FaviconBitmapID> > candidate_bitmap_ids(
2268 new std::vector<FaviconBitmapID>());
2269 float score;
2270 SelectFaviconBitmapIDs(bitmap_id_sizes,
2271 desired_scale_factors,
2272 desired_size_in_dip,
2273 candidate_bitmap_ids.get(),
2274 &score);
2275 if (score > highest_score) {
2276 best_favicon_id = candidate_favicon_ids[i],
2277 best_bitmap_ids.swap(candidate_bitmap_ids);
2278 highest_score = score;
2279 }
2280 }
2281
2282 // Construct FaviconBitmapResults from |best_favicon_id| and
2283 // |best_bitmap_ids|.
2284 GURL icon_url;
2285 IconType icon_type;
2286 if (!thumbnail_db_->GetFaviconHeader(best_favicon_id, &icon_url,
2287 &icon_type, NULL)) {
2288 return false;
2289 }
2290
2291 favicon_bitmap_results->clear();
2292 for (size_t i = 0; i < best_bitmap_ids->size(); ++i) {
2293 base::Time last_updated;
2294 FaviconBitmapResult bitmap_result;
2295 bitmap_result.icon_url = icon_url;
2296 bitmap_result.icon_type = icon_type;
2297 if (!thumbnail_db_->GetFaviconBitmap((*best_bitmap_ids)[i],
2298 &last_updated,
2299 &bitmap_result.bitmap_data,
2300 &bitmap_result.pixel_size)) {
2301 return false;
2302 }
2303
2304 bitmap_result.expired = (Time::Now() - last_updated) >
2305 TimeDelta::FromDays(kFaviconRefetchDays);
2306 if (bitmap_result.is_valid())
2307 favicon_bitmap_results->push_back(bitmap_result);
2308 }
2309 return true;
2310 }
2311
2312 bool HistoryBackend::BuildIconURLSizesMap(
2313 const std::vector<FaviconID>& favicon_ids,
2314 IconURLSizesMap* icon_url_sizes) {
2315 icon_url_sizes->clear();
2316 for (size_t i = 0; i < favicon_ids.size(); ++i) {
2317 GURL icon_url;
2318 FaviconSizes favicon_sizes;
2319 if (!thumbnail_db_->GetFaviconHeader(favicon_ids[i], &icon_url, NULL,
2320 &favicon_sizes)) {
2321 return false;
2322 }
2323 (*icon_url_sizes)[icon_url] = favicon_sizes;
2324 }
2325 return true;
2326 }
2327
2328 void HistoryBackend::SetFaviconMappingsForPageAndRedirects(
1950 const GURL& page_url, 2329 const GURL& page_url,
1951 const GURL& icon_url, 2330 IconType icon_type,
1952 scoped_refptr<base::RefCountedMemory> data, 2331 const IconURLFaviconIDMap& icon_url_id_map) {
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()) 2332 if (!thumbnail_db_.get())
1979 return; 2333 return;
1980 2334
1981 // Find all the pages whose favicons we should set, we want to set it for 2335 // 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. 2336 // all the pages in the redirect chain if it redirected.
1983 history::RedirectList dummy_list; 2337 history::RedirectList dummy_list;
1984 history::RedirectList* redirects; 2338 history::RedirectList* redirects;
1985 RedirectCache::iterator iter = recent_redirects_.Get(page_url); 2339 RedirectCache::iterator iter = recent_redirects_.Get(page_url);
1986 if (iter != recent_redirects_.end()) { 2340 if (iter != recent_redirects_.end()) {
1987 redirects = &iter->second; 2341 redirects = &iter->second;
1988 2342
1989 // This redirect chain should have the destination URL as the last item. 2343 // This redirect chain should have the destination URL as the last item.
1990 DCHECK(!redirects->empty()); 2344 DCHECK(!redirects->empty());
1991 DCHECK(redirects->back() == page_url); 2345 DCHECK(redirects->back() == page_url);
1992 } else { 2346 } else {
1993 // No redirect chain stored, make up one containing the URL we want to we 2347 // No redirect chain stored, make up one containing the URL we want to we
1994 // can use the same logic below. 2348 // can use the same logic below.
1995 dummy_list.push_back(page_url); 2349 dummy_list.push_back(page_url);
1996 redirects = &dummy_list; 2350 redirects = &dummy_list;
1997 } 2351 }
1998 2352
1999 std::set<GURL> favicons_changed; 2353 std::set<GURL> favicons_changed;
2000 2354
2001 // Save page <-> favicon association. 2355 // Save page <-> favicon associations.
2002 for (history::RedirectList::const_iterator i(redirects->begin()); 2356 for (history::RedirectList::const_iterator i(redirects->begin());
2003 i != redirects->end(); ++i) { 2357 i != redirects->end(); ++i) {
2004 FaviconID replaced_id; 2358 if (SetFaviconMappingsForPage(*i, icon_type, icon_url_id_map)) {
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); 2359 favicons_changed.insert(*i);
2015 } 2360 }
2016 } 2361 }
2017 2362
2018 // Send the notification about the changed favicons. 2363 // Send the notification about the changed favicons.
2019 FaviconChangeDetails* changed_details = new FaviconChangeDetails; 2364 FaviconChangeDetails* changed_details = new FaviconChangeDetails;
2020 changed_details->urls.swap(favicons_changed); 2365 changed_details->urls.swap(favicons_changed);
2021 BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED, 2366 BroadcastNotifications(chrome::NOTIFICATION_FAVICON_CHANGED,
2022 changed_details); 2367 changed_details);
2023 2368
2024 ScheduleCommit(); 2369 ScheduleCommit();
2025 } 2370 }
2026 2371
2027 bool HistoryBackend::AddOrUpdateIconMapping(const GURL& page_url, 2372 bool HistoryBackend::SetFaviconMappingsForPage(
2028 FaviconID id, 2373 const GURL& page_url,
2029 IconType icon_type, 2374 IconType icon_type,
2030 FaviconID* replaced_icon) { 2375 const IconURLFaviconIDMap& icon_url_id_map) {
2031 *replaced_icon = 0; 2376 DCHECK_LE(icon_url_id_map.size(), kMaxFaviconsPerPage);
2377 bool mappings_changed = false;
2378
2379 // Two icon types are considered 'equivalent' if one of the icon types is
2380 // ICON_TOUCH and the other is ICON_PRECOMPOSED_TOUCH.
2381 //
2382 // Sets the icon mappings of |page_url| for |icon_type| to the icon URLs
2383 // and favicon ids in |icon_url_id_map|. The mappings from |page_url| for
2384 // any icon URLs not in |icon_url_id_map| are removed.
2385 // The icon mappings of |page_url| for equivalent icon types are removed.
2386 // Remove any favicons which are orphaned as a result of the removal of the
2387 // icon mappings.
2388
2389 IconURLFaviconIDMap icon_mappings_to_add = icon_url_id_map;
2390
2032 std::vector<IconMapping> icon_mappings; 2391 std::vector<IconMapping> icon_mappings;
2033 if (!thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings)) { 2392 thumbnail_db_->GetIconMappingsForPageURL(page_url, &icon_mappings);
2034 // There is no mapping add it directly.
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(); 2393 for (std::vector<IconMapping>::iterator m = icon_mappings.begin();
2047 m != icon_mappings.end(); ++m) { 2394 m != icon_mappings.end(); ++m) {
2048 if (m->icon_id == id) 2395 if ((icon_type == TOUCH_ICON && m->icon_type == TOUCH_PRECOMPOSED_ICON) ||
2049 // The mapping is already there. 2396 (icon_type == TOUCH_PRECOMPOSED_ICON && m->icon_type == TOUCH_ICON) ||
2050 return false; 2397 icon_type == m->icon_type) {
2398 IconURLFaviconIDMap::iterator it =
2399 icon_mappings_to_add.find(m->icon_url);
2400 if (it == icon_mappings_to_add.end()) {
2401 thumbnail_db_->DeleteIconMapping(m->mapping_id);
2402 } else {
2403 FaviconID icon_id = it->second;
2404 icon_mappings_to_add.erase(it);
2405 if (icon_id == m->icon_id) {
2406 // Keep icon mapping.
2407 continue;
2408 }
2051 2409
2052 if ((icon_type == TOUCH_ICON && m->icon_type == TOUCH_PRECOMPOSED_ICON) || 2410 thumbnail_db_->UpdateIconMapping(m->mapping_id, icon_id);
2053 (icon_type == TOUCH_PRECOMPOSED_ICON && m->icon_type == TOUCH_ICON) || 2411 }
2054 (icon_type == m->icon_type)) { 2412 // Removing / updating the icon mapping may have orphaned the associated
2055 thumbnail_db_->UpdateIconMapping(m->mapping_id, id); 2413 // favicon so we must recheck it. This is not super fast, but this case
2056 *replaced_icon = m->icon_id; 2414 // will get triggered rarely, since normally a page will always map to
2057 return true; 2415 // the same favicon IDs. It will mostly happen for favicons we import.
2416 if (!thumbnail_db_->HasMappingFor(m->icon_id))
2417 thumbnail_db_->DeleteFavicon(m->icon_id);
2418 mappings_changed = true;
2058 } 2419 }
2059 } 2420 }
2060 thumbnail_db_->AddIconMapping(page_url, id); 2421
2061 return true; 2422 for (IconURLFaviconIDMap::iterator it = icon_mappings_to_add.begin();
2423 it != icon_mappings_to_add.end(); ++it) {
2424 thumbnail_db_->AddIconMapping(page_url, it->second);
2425 mappings_changed = true;
2426 }
2427 return mappings_changed;
2062 } 2428 }
2063 2429
2064 void HistoryBackend::Commit() { 2430 void HistoryBackend::Commit() {
2065 if (!db_.get()) 2431 if (!db_.get())
2066 return; 2432 return;
2067 2433
2068 // Note that a commit may not actually have been scheduled if a caller 2434 // Note that a commit may not actually have been scheduled if a caller
2069 // explicitly calls this instead of using ScheduleCommit. Likewise, we 2435 // explicitly calls this instead of using ScheduleCommit. Likewise, we
2070 // may reset the flag written by a pending commit. But this is OK! It 2436 // 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 2437 // will merely cause extra commits (which is kind of the idea). We
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
2435 2801
2436 return true; 2802 return true;
2437 } 2803 }
2438 2804
2439 BookmarkService* HistoryBackend::GetBookmarkService() { 2805 BookmarkService* HistoryBackend::GetBookmarkService() {
2440 if (bookmark_service_) 2806 if (bookmark_service_)
2441 bookmark_service_->BlockTillLoaded(); 2807 bookmark_service_->BlockTillLoaded();
2442 return bookmark_service_; 2808 return bookmark_service_;
2443 } 2809 }
2444 2810
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) { 2811 void HistoryBackend::NotifyVisitObservers(const VisitRow& visit) {
2504 BriefVisitInfo info; 2812 BriefVisitInfo info;
2505 info.url_id = visit.url_id; 2813 info.url_id = visit.url_id;
2506 info.time = visit.visit_time; 2814 info.time = visit.visit_time;
2507 info.transition = visit.transition; 2815 info.transition = visit.transition;
2508 // If we don't have a delegate yet during setup or shutdown, we will drop 2816 // If we don't have a delegate yet during setup or shutdown, we will drop
2509 // these notifications. 2817 // these notifications.
2510 if (delegate_.get()) 2818 if (delegate_.get())
2511 delegate_->NotifyVisitDBObserversOnAddVisit(info); 2819 delegate_->NotifyVisitDBObserversOnAddVisit(info);
2512 } 2820 }
2513 2821
2514 } // namespace history 2822 } // namespace history
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698