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