summaryrefslogtreecommitdiffstats
path: root/toolkit/components/places/FaviconHelpers.h
blob: ba3407722c9c85150165f726903e617192715561 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#pragma once

#include "nsIFaviconService.h"
#include "nsIChannelEventSink.h"
#include "nsIInterfaceRequestor.h"
#include "nsIStreamListener.h"
#include "mozIPlacesPendingOperation.h"
#include "nsThreadUtils.h"
#include "nsProxyRelease.h"
#include "imgLoader.h"

class nsIPrincipal;

#include "Database.h"
#include "mozilla/storage.h"

#define ICON_STATUS_UNKNOWN 0
#define ICON_STATUS_CHANGED 1 << 0
#define ICON_STATUS_SAVED 1 << 1
#define ICON_STATUS_ASSOCIATED 1 << 2
#define ICON_STATUS_CACHED 1 << 3

#define TO_CHARBUFFER(_buffer) \
  reinterpret_cast<char*>(const_cast<uint8_t*>(_buffer))
#define TO_INTBUFFER(_string) \
  reinterpret_cast<uint8_t*>(const_cast<char*>(_string.get()))

#define PNG_MIME_TYPE "image/png"
#define SVG_MIME_TYPE "image/svg+xml"

// Always ensure a minimum expiration time, so icons are not already expired
// on addition.
#define MIN_FAVICON_EXPIRATION ((PRTime)1 * 24 * 60 * 60 * PR_USEC_PER_SEC)
// The maximum time we will keep a favicon around.  We always ask the cache
// first and default to this value if we can't get a time, or the time we get
// is far in the future.
#define MAX_FAVICON_EXPIRATION ((PRTime)7 * 24 * 60 * 60 * PR_USEC_PER_SEC)

namespace mozilla {
namespace places {

/**
 * Indicates when a icon should be fetched from network.
 */
enum AsyncFaviconFetchMode { FETCH_NEVER = 0, FETCH_IF_MISSING, FETCH_ALWAYS };

/**
 * Represents one of the payloads (frames) of an icon entry.
 */
struct IconPayload {
  IconPayload() : id(0), width(0) {
    data.SetIsVoid(true);
    mimeType.SetIsVoid(true);
  }

  int64_t id;
  uint16_t width;
  nsCString data;
  nsCString mimeType;
};

/**
 * Represents an icon entry.
 */
struct IconData {
  IconData()
      : expiration(0),
        fetchMode(FETCH_NEVER),
        status(ICON_STATUS_UNKNOWN),
        rootIcon(0) {}

  nsCString spec;
  nsCString host;
  PRTime expiration;
  enum AsyncFaviconFetchMode fetchMode;
  uint16_t status;  // This is a bitset, see ICON_STATUS_* defines above.
  uint8_t rootIcon;
  CopyableTArray<IconPayload> payloads;
};

/**
 * Data cache for a page entry.
 */
struct PageData {
  PageData() : id(0), placeId(0), canAddToHistory(true) {
    guid.SetIsVoid(true);
  }

  int64_t id;       // This is the moz_pages_w_icons id.
  int64_t placeId;  // This is the moz_places page id.
  nsCString spec;
  nsCString host;
  nsCString bookmarkedSpec;
  bool canAddToHistory;  // False for disabled history and unsupported schemas.
  nsCString guid;
};

/**
 * Info for a frame.
 */
struct FrameData {
  FrameData(uint16_t aIndex, uint16_t aWidth) : index(aIndex), width(aWidth) {}

  uint16_t index;
  uint16_t width;
};

/**
 * Async fetches icon from database or network, associates it with the required
 * page and finally notifies the change.
 */
class AsyncFetchAndSetIconForPage final : public Runnable,
                                          public nsIStreamListener,
                                          public nsIInterfaceRequestor,
                                          public nsIChannelEventSink,
                                          public mozIPlacesPendingOperation {
 public:
  NS_DECL_NSIRUNNABLE
  NS_DECL_NSISTREAMLISTENER
  NS_DECL_NSIINTERFACEREQUESTOR
  NS_DECL_NSICHANNELEVENTSINK
  NS_DECL_NSIREQUESTOBSERVER
  NS_DECL_MOZIPLACESPENDINGOPERATION
  NS_DECL_ISUPPORTS_INHERITED

  /**
   * Constructor.
   *
   * @param aIcon
   *        Icon to be fetched and associated.
   * @param aPage
   *        Page to which associate the icon.
   * @param aFaviconLoadPrivate
   *        Whether this favicon load is in private browsing.
   * @param aCallback
   *        Function to be called when the fetch-and-associate process finishes.
   * @param aLoadingPrincipal
   *        LoadingPrincipal of the icon to be fetched.
   */
  AsyncFetchAndSetIconForPage(IconData& aIcon, PageData& aPage,
                              bool aFaviconLoadPrivate,
                              nsIFaviconDataCallback* aCallback,
                              nsIPrincipal* aLoadingPrincipal,
                              uint64_t aRequestContextID);

 private:
  nsresult FetchFromNetwork();
  virtual ~AsyncFetchAndSetIconForPage() = default;

  nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback;
  IconData mIcon;
  PageData mPage;
  const bool mFaviconLoadPrivate;
  nsMainThreadPtrHandle<nsIPrincipal> mLoadingPrincipal;
  bool mCanceled;
  nsCOMPtr<nsIRequest> mRequest;
  uint64_t mRequestContextID;
};

/**
 * Associates the icon to the required page, finally dispatches an event to the
 * main thread to notify the change to observers.
 */
class AsyncAssociateIconToPage final : public Runnable {
 public:
  NS_DECL_NSIRUNNABLE

  /**
   * Constructor.
   *
   * @param aIcon
   *        Icon to be associated.
   * @param aPage
   *        Page to which associate the icon.
   * @param aCallback
   *        Function to be called when the associate process finishes.
   */
  AsyncAssociateIconToPage(
      const IconData& aIcon, const PageData& aPage,
      const nsMainThreadPtrHandle<nsIFaviconDataCallback>& aCallback);

 private:
  nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback;
  IconData mIcon;
  PageData mPage;
};

/**
 * Asynchronously tries to get the URL of a page's favicon, then notifies the
 * given observer.
 */
class AsyncGetFaviconURLForPage final : public Runnable {
 public:
  NS_DECL_NSIRUNNABLE

  /**
   * Constructor.
   *
   * @param aPageSpec
   *        URL of the page whose favicon's URL we're fetching
   * @param aPageHost
   *        Host of the page whose favicon's URL we're fetching
   * @param aCallback
   *        function to be called once finished
   * @param aPreferredWidth
   *        The preferred size for the icon
   */
  AsyncGetFaviconURLForPage(const nsACString& aPageSpec,
                            const nsACString& aPageHost,
                            uint16_t aPreferredWidth,
                            nsIFaviconDataCallback* aCallback);

 private:
  uint16_t mPreferredWidth;
  nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback;
  nsCString mPageSpec;
  nsCString mPageHost;
};

/**
 * Asynchronously tries to get the URL and data of a page's favicon, then
 * notifies the given observer.
 */
class AsyncGetFaviconDataForPage final : public Runnable {
 public:
  NS_DECL_NSIRUNNABLE

  /**
   * Constructor.
   *
   * @param aPageSpec
   *        URL of the page whose favicon URL and data we're fetching
   * @param aPageHost
   *        Host of the page whose favicon's URL we're fetching
   * @param aPreferredWidth
   *        The preferred size of the icon.  We will try to return an icon close
   *        to this size.
   * @param aCallback
   *        function to be called once finished
   */
  AsyncGetFaviconDataForPage(const nsACString& aPageSpec,
                             const nsACString& aPageHost,
                             uint16_t aPreferredWidth,
                             nsIFaviconDataCallback* aCallback);

 private:
  uint16_t mPreferredWidth;
  nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback;
  nsCString mPageSpec;
  nsCString mPageHost;
};

class AsyncReplaceFaviconData final : public Runnable {
 public:
  NS_DECL_NSIRUNNABLE

  explicit AsyncReplaceFaviconData(const IconData& aIcon);

 private:
  nsresult RemoveIconDataCacheEntry();

  IconData mIcon;
};

/**
 * Notifies the icon change to favicon observers.
 */
class NotifyIconObservers final : public Runnable {
 public:
  NS_DECL_NSIRUNNABLE

  /**
   * Constructor.
   *
   * @param aIcon
   *        Icon information. Can be empty if no icon is associated to the page.
   * @param aPage
   *        Page to which the icon information applies.
   * @param aCallback
   *        Function to be notified in all cases.
   */
  NotifyIconObservers(
      const IconData& aIcon, const PageData& aPage,
      const nsMainThreadPtrHandle<nsIFaviconDataCallback>& aCallback);

 private:
  nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback;
  IconData mIcon;
  PageData mPage;
};

/**
 * Copies Favicons from one page to another one.
 */
class AsyncCopyFavicons final : public Runnable {
 public:
  NS_DECL_NSIRUNNABLE

  /**
   * Constructor.
   *
   * @param aFromPage
   *        The originating page.
   * @param aToPage
   *        The destination page.
   * @param aFaviconLoadPrivate
   *        Whether this favicon load is in private browsing.
   * @param aCallback
   *        An optional callback to invoke when done.
   */
  AsyncCopyFavicons(PageData& aFromPage, PageData& aToPage,
                    nsIFaviconDataCallback* aCallback);

 private:
  PageData mFromPage;
  PageData mToPage;
  nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback;
};

}  // namespace places
}  // namespace mozilla