1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #pragma once
8 
9 #include "nsIFaviconService.h"
10 #include "nsIChannelEventSink.h"
11 #include "nsIInterfaceRequestor.h"
12 #include "nsIStreamListener.h"
13 #include "mozIPlacesPendingOperation.h"
14 #include "nsThreadUtils.h"
15 #include "nsProxyRelease.h"
16 #include "imgLoader.h"
17 
18 class nsIPrincipal;
19 
20 #include "Database.h"
21 #include "mozilla/storage.h"
22 
23 #define ICON_STATUS_UNKNOWN 0
24 #define ICON_STATUS_CHANGED 1 << 0
25 #define ICON_STATUS_SAVED 1 << 1
26 #define ICON_STATUS_ASSOCIATED 1 << 2
27 #define ICON_STATUS_CACHED 1 << 3
28 
29 #define TO_CHARBUFFER(_buffer) \
30   reinterpret_cast<char*>(const_cast<uint8_t*>(_buffer))
31 #define TO_INTBUFFER(_string) \
32   reinterpret_cast<uint8_t*>(const_cast<char*>(_string.get()))
33 
34 #define PNG_MIME_TYPE "image/png"
35 #define SVG_MIME_TYPE "image/svg+xml"
36 
37 // Always ensure a minimum expiration time, so icons are not already expired
38 // on addition.
39 #define MIN_FAVICON_EXPIRATION ((PRTime)1 * 24 * 60 * 60 * PR_USEC_PER_SEC)
40 // The maximum time we will keep a favicon around.  We always ask the cache
41 // first and default to this value if we can't get a time, or the time we get
42 // is far in the future.
43 #define MAX_FAVICON_EXPIRATION ((PRTime)7 * 24 * 60 * 60 * PR_USEC_PER_SEC)
44 
45 namespace mozilla {
46 namespace places {
47 
48 /**
49  * Indicates when a icon should be fetched from network.
50  */
51 enum AsyncFaviconFetchMode { FETCH_NEVER = 0, FETCH_IF_MISSING, FETCH_ALWAYS };
52 
53 /**
54  * Represents one of the payloads (frames) of an icon entry.
55  */
56 struct IconPayload {
IconPayloadIconPayload57   IconPayload() : id(0), width(0) {
58     data.SetIsVoid(true);
59     mimeType.SetIsVoid(true);
60   }
61 
62   int64_t id;
63   uint16_t width;
64   nsCString data;
65   nsCString mimeType;
66 };
67 
68 /**
69  * Represents an icon entry.
70  */
71 struct IconData {
IconDataIconData72   IconData()
73       : expiration(0),
74         fetchMode(FETCH_NEVER),
75         status(ICON_STATUS_UNKNOWN),
76         rootIcon(0) {}
77 
78   nsCString spec;
79   nsCString host;
80   PRTime expiration;
81   enum AsyncFaviconFetchMode fetchMode;
82   uint16_t status;  // This is a bitset, see ICON_STATUS_* defines above.
83   uint8_t rootIcon;
84   CopyableTArray<IconPayload> payloads;
85 };
86 
87 /**
88  * Data cache for a page entry.
89  */
90 struct PageData {
PageDataPageData91   PageData() : id(0), placeId(0), canAddToHistory(true) {
92     guid.SetIsVoid(true);
93   }
94 
95   int64_t id;       // This is the moz_pages_w_icons id.
96   int64_t placeId;  // This is the moz_places page id.
97   nsCString spec;
98   nsCString host;
99   nsCString bookmarkedSpec;
100   bool canAddToHistory;  // False for disabled history and unsupported schemas.
101   nsCString guid;
102 };
103 
104 /**
105  * Info for a frame.
106  */
107 struct FrameData {
FrameDataFrameData108   FrameData(uint16_t aIndex, uint16_t aWidth) : index(aIndex), width(aWidth) {}
109 
110   uint16_t index;
111   uint16_t width;
112 };
113 
114 /**
115  * Async fetches icon from database or network, associates it with the required
116  * page and finally notifies the change.
117  */
118 class AsyncFetchAndSetIconForPage final : public Runnable,
119                                           public nsIStreamListener,
120                                           public nsIInterfaceRequestor,
121                                           public nsIChannelEventSink,
122                                           public mozIPlacesPendingOperation {
123  public:
124   NS_DECL_NSIRUNNABLE
125   NS_DECL_NSISTREAMLISTENER
126   NS_DECL_NSIINTERFACEREQUESTOR
127   NS_DECL_NSICHANNELEVENTSINK
128   NS_DECL_NSIREQUESTOBSERVER
129   NS_DECL_MOZIPLACESPENDINGOPERATION
130   NS_DECL_ISUPPORTS_INHERITED
131 
132   /**
133    * Constructor.
134    *
135    * @param aIcon
136    *        Icon to be fetched and associated.
137    * @param aPage
138    *        Page to which associate the icon.
139    * @param aFaviconLoadPrivate
140    *        Whether this favicon load is in private browsing.
141    * @param aCallback
142    *        Function to be called when the fetch-and-associate process finishes.
143    * @param aLoadingPrincipal
144    *        LoadingPrincipal of the icon to be fetched.
145    */
146   AsyncFetchAndSetIconForPage(IconData& aIcon, PageData& aPage,
147                               bool aFaviconLoadPrivate,
148                               nsIFaviconDataCallback* aCallback,
149                               nsIPrincipal* aLoadingPrincipal,
150                               uint64_t aRequestContextID);
151 
152  private:
153   nsresult FetchFromNetwork();
154   virtual ~AsyncFetchAndSetIconForPage() = default;
155 
156   nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback;
157   IconData mIcon;
158   PageData mPage;
159   const bool mFaviconLoadPrivate;
160   nsMainThreadPtrHandle<nsIPrincipal> mLoadingPrincipal;
161   bool mCanceled;
162   nsCOMPtr<nsIRequest> mRequest;
163   uint64_t mRequestContextID;
164 };
165 
166 /**
167  * Associates the icon to the required page, finally dispatches an event to the
168  * main thread to notify the change to observers.
169  */
170 class AsyncAssociateIconToPage final : public Runnable {
171  public:
172   NS_DECL_NSIRUNNABLE
173 
174   /**
175    * Constructor.
176    *
177    * @param aIcon
178    *        Icon to be associated.
179    * @param aPage
180    *        Page to which associate the icon.
181    * @param aCallback
182    *        Function to be called when the associate process finishes.
183    */
184   AsyncAssociateIconToPage(
185       const IconData& aIcon, const PageData& aPage,
186       const nsMainThreadPtrHandle<nsIFaviconDataCallback>& aCallback);
187 
188  private:
189   nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback;
190   IconData mIcon;
191   PageData mPage;
192 };
193 
194 /**
195  * Asynchronously tries to get the URL of a page's favicon, then notifies the
196  * given observer.
197  */
198 class AsyncGetFaviconURLForPage final : public Runnable {
199  public:
200   NS_DECL_NSIRUNNABLE
201 
202   /**
203    * Constructor.
204    *
205    * @param aPageSpec
206    *        URL of the page whose favicon's URL we're fetching
207    * @param aPageHost
208    *        Host of the page whose favicon's URL we're fetching
209    * @param aCallback
210    *        function to be called once finished
211    * @param aPreferredWidth
212    *        The preferred size for the icon
213    */
214   AsyncGetFaviconURLForPage(const nsACString& aPageSpec,
215                             const nsACString& aPageHost,
216                             uint16_t aPreferredWidth,
217                             nsIFaviconDataCallback* aCallback);
218 
219  private:
220   uint16_t mPreferredWidth;
221   nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback;
222   nsCString mPageSpec;
223   nsCString mPageHost;
224 };
225 
226 /**
227  * Asynchronously tries to get the URL and data of a page's favicon, then
228  * notifies the given observer.
229  */
230 class AsyncGetFaviconDataForPage final : public Runnable {
231  public:
232   NS_DECL_NSIRUNNABLE
233 
234   /**
235    * Constructor.
236    *
237    * @param aPageSpec
238    *        URL of the page whose favicon URL and data we're fetching
239    * @param aPageHost
240    *        Host of the page whose favicon's URL we're fetching
241    * @param aPreferredWidth
242    *        The preferred size of the icon.  We will try to return an icon close
243    *        to this size.
244    * @param aCallback
245    *        function to be called once finished
246    */
247   AsyncGetFaviconDataForPage(const nsACString& aPageSpec,
248                              const nsACString& aPageHost,
249                              uint16_t aPreferredWidth,
250                              nsIFaviconDataCallback* aCallback);
251 
252  private:
253   uint16_t mPreferredWidth;
254   nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback;
255   nsCString mPageSpec;
256   nsCString mPageHost;
257 };
258 
259 class AsyncReplaceFaviconData final : public Runnable {
260  public:
261   NS_DECL_NSIRUNNABLE
262 
263   explicit AsyncReplaceFaviconData(const IconData& aIcon);
264 
265  private:
266   nsresult RemoveIconDataCacheEntry();
267 
268   IconData mIcon;
269 };
270 
271 /**
272  * Notifies the icon change to favicon observers.
273  */
274 class NotifyIconObservers final : public Runnable {
275  public:
276   NS_DECL_NSIRUNNABLE
277 
278   /**
279    * Constructor.
280    *
281    * @param aIcon
282    *        Icon information. Can be empty if no icon is associated to the page.
283    * @param aPage
284    *        Page to which the icon information applies.
285    * @param aCallback
286    *        Function to be notified in all cases.
287    */
288   NotifyIconObservers(
289       const IconData& aIcon, const PageData& aPage,
290       const nsMainThreadPtrHandle<nsIFaviconDataCallback>& aCallback);
291 
292  private:
293   nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback;
294   IconData mIcon;
295   PageData mPage;
296 };
297 
298 /**
299  * Copies Favicons from one page to another one.
300  */
301 class AsyncCopyFavicons final : public Runnable {
302  public:
303   NS_DECL_NSIRUNNABLE
304 
305   /**
306    * Constructor.
307    *
308    * @param aFromPage
309    *        The originating page.
310    * @param aToPage
311    *        The destination page.
312    * @param aFaviconLoadPrivate
313    *        Whether this favicon load is in private browsing.
314    * @param aCallback
315    *        An optional callback to invoke when done.
316    */
317   AsyncCopyFavicons(PageData& aFromPage, PageData& aToPage,
318                     nsIFaviconDataCallback* aCallback);
319 
320  private:
321   PageData mFromPage;
322   PageData mToPage;
323   nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback;
324 };
325 
326 }  // namespace places
327 }  // namespace mozilla
328