1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef nsFaviconService_h_
7 #define nsFaviconService_h_
8 
9 #include "nsIFaviconService.h"
10 #include "mozIAsyncFavicons.h"
11 
12 #include "nsCOMPtr.h"
13 #include "nsString.h"
14 #include "nsDataHashtable.h"
15 #include "nsServiceManagerUtils.h"
16 #include "nsTHashtable.h"
17 #include "nsToolkitCompsCID.h"
18 #include "nsURIHashKey.h"
19 #include "nsINamed.h"
20 #include "nsITimer.h"
21 #include "Database.h"
22 #include "imgITools.h"
23 #include "mozilla/storage.h"
24 #include "mozilla/Attributes.h"
25 
26 #include "FaviconHelpers.h"
27 
28 // The target dimension in pixels for favicons we store, in reverse order.
29 static uint16_t sFaviconSizes[8] = {256, 192, 144, 96, 64, 48, 32, 16};
30 
31 // forward class definitions
32 class mozIStorageStatementCallback;
33 
34 class UnassociatedIconHashKey : public nsURIHashKey {
35  public:
UnassociatedIconHashKey(const nsIURI * aURI)36   explicit UnassociatedIconHashKey(const nsIURI* aURI) : nsURIHashKey(aURI) {}
UnassociatedIconHashKey(const UnassociatedIconHashKey & aOther)37   UnassociatedIconHashKey(const UnassociatedIconHashKey& aOther)
38       : nsURIHashKey(aOther) {
39     NS_NOTREACHED("Do not call me!");
40   }
41   mozilla::places::IconData iconData;
42   PRTime created;
43 };
44 
45 class nsFaviconService final : public nsIFaviconService,
46                                public mozIAsyncFavicons,
47                                public nsITimerCallback,
48                                public nsINamed {
49  public:
50   nsFaviconService();
51 
52   /**
53    * Obtains the service's object.
54    */
55   static already_AddRefed<nsFaviconService> GetSingleton();
56 
57   /**
58    * Initializes the service's object.  This should only be called once.
59    */
60   nsresult Init();
61 
62   /**
63    * Returns a cached pointer to the favicon service for consumers in the
64    * places directory.
65    */
GetFaviconService()66   static nsFaviconService* GetFaviconService() {
67     if (!gFaviconService) {
68       nsCOMPtr<nsIFaviconService> serv =
69           do_GetService(NS_FAVICONSERVICE_CONTRACTID);
70       NS_ENSURE_TRUE(serv, nullptr);
71       NS_ASSERTION(gFaviconService, "Should have static instance pointer now");
72     }
73     return gFaviconService;
74   }
75 
76   /**
77    * Fetch and migrate favicons from an unsupported payload to a supported one.
78    */
79   static void ConvertUnsupportedPayloads(mozIStorageConnection* aDBConn);
80 
81   // addition to API for strings to prevent excessive parsing of URIs
82   nsresult GetFaviconLinkForIconString(const nsCString& aIcon,
83                                        nsIURI** aOutput);
84 
85   nsresult OptimizeIconSizes(mozilla::places::IconData& aIcon);
86 
87   /**
88    * Obtains the favicon data asynchronously.
89    *
90    * @param aFaviconSpec
91    *        The spec of the URI representing the favicon we are looking for.
92    * @param aCallback
93    *        The callback where results or errors will be dispatch to.  In the
94    *        returned result, the favicon binary data will be at index 0, and the
95    *        mime type will be at index 1.
96    */
97   nsresult GetFaviconDataAsync(const nsCString& aFaviconSpec,
98                                mozIStorageStatementCallback* aCallback);
99 
100   /**
101    * Call to send out favicon changed notifications. Should only be called
102    * when there is data loaded for the favicon.
103    * @param aPageURI
104    *        The URI of the page to notify about.
105    * @param aFaviconURI
106    *        The moz-anno:favicon URI of the icon.
107    * @param aGUID
108    *        The unique ID associated with the page.
109    */
110   void SendFaviconNotifications(nsIURI* aPageURI, nsIURI* aFaviconURI,
111                                 const nsACString& aGUID);
112 
113   static mozilla::Atomic<int64_t> sLastInsertedIconId;
114   static void StoreLastInsertedId(const nsACString& aTable,
115                                   const int64_t aLastInsertedId);
116 
117   NS_DECL_ISUPPORTS
118   NS_DECL_NSIFAVICONSERVICE
119   NS_DECL_MOZIASYNCFAVICONS
120   NS_DECL_NSITIMERCALLBACK
121   NS_DECL_NSINAMED
122 
123  private:
GetImgTools()124   imgITools* GetImgTools() {
125     if (!mImgTools) {
126       mImgTools = do_CreateInstance("@mozilla.org/image/tools;1");
127     }
128     return mImgTools;
129   }
130 
131   ~nsFaviconService();
132 
133   RefPtr<mozilla::places::Database> mDB;
134 
135   nsCOMPtr<nsITimer> mExpireUnassociatedIconsTimer;
136   nsCOMPtr<imgITools> mImgTools;
137 
138   static nsFaviconService* gFaviconService;
139 
140   /**
141    * A cached URI for the default icon. We return this a lot, and don't want to
142    * re-parse and normalize our unchanging string many times.  Important: do
143    * not return this directly; use Clone() since callers may change the object
144    * they get back. May be null, in which case it needs initialization.
145    */
146   nsCOMPtr<nsIURI> mDefaultIcon;
147 
148   uint32_t mFailedFaviconSerial;
149   nsDataHashtable<nsCStringHashKey, uint32_t> mFailedFavicons;
150 
151   // This class needs access to the icons cache.
152   friend class mozilla::places::AsyncReplaceFaviconData;
153   nsTHashtable<UnassociatedIconHashKey> mUnassociatedIcons;
154 
155   uint16_t mDefaultIconURIPreferredSize;
156 };
157 
158 #define FAVICON_ANNOTATION_NAME "favicon"
159 
160 #endif  // nsFaviconService_h_
161