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 "imgITools.h" 17 #include "imgIContainer.h" 18 #include "imgLoader.h" 19 20 class nsIPrincipal; 21 22 #include "Database.h" 23 #include "mozilla/storage.h" 24 25 #define ICON_STATUS_UNKNOWN 0 26 #define ICON_STATUS_CHANGED 1 << 0 27 #define ICON_STATUS_SAVED 1 << 1 28 #define ICON_STATUS_ASSOCIATED 1 << 2 29 #define ICON_STATUS_CACHED 1 << 3 30 31 #define TO_CHARBUFFER(_buffer) \ 32 reinterpret_cast<char*>(const_cast<uint8_t*>(_buffer)) 33 #define TO_INTBUFFER(_string) \ 34 reinterpret_cast<uint8_t*>(const_cast<char*>(_string.get())) 35 36 #define PNG_MIME_TYPE "image/png" 37 #define SVG_MIME_TYPE "image/svg+xml" 38 39 /** 40 * The maximum time we will keep a favicon around. We always ask the cache, if 41 * we can, but default to this value if we do not get a time back, or the time 42 * is more in the future than this. 43 * Currently set to one week from now. 44 */ 45 #define MAX_FAVICON_EXPIRATION ((PRTime)7 * 24 * 60 * 60 * PR_USEC_PER_SEC) 46 47 // Whether there are unsupported payloads to convert yet. 48 #define PREF_CONVERT_PAYLOADS "places.favicons.convertPayloads" 49 50 namespace mozilla { 51 namespace places { 52 53 /** 54 * Indicates when a icon should be fetched from network. 55 */ 56 enum AsyncFaviconFetchMode { FETCH_NEVER = 0, FETCH_IF_MISSING, FETCH_ALWAYS }; 57 58 /** 59 * Represents one of the payloads (frames) of an icon entry. 60 */ 61 struct IconPayload { IconPayloadIconPayload62 IconPayload() : id(0), width(0) { 63 data.SetIsVoid(true); 64 mimeType.SetIsVoid(true); 65 } 66 67 int64_t id; 68 uint16_t width; 69 nsCString data; 70 nsCString mimeType; 71 }; 72 73 /** 74 * Represents an icon entry. 75 */ 76 struct IconData { IconDataIconData77 IconData() 78 : expiration(0), 79 fetchMode(FETCH_NEVER), 80 status(ICON_STATUS_UNKNOWN), 81 rootIcon(0) {} 82 83 nsCString spec; 84 nsCString host; 85 PRTime expiration; 86 enum AsyncFaviconFetchMode fetchMode; 87 uint16_t status; // This is a bitset, see ICON_STATUS_* defines above. 88 uint8_t rootIcon; 89 nsTArray<IconPayload> payloads; 90 }; 91 92 /** 93 * Data cache for a page entry. 94 */ 95 struct PageData { PageDataPageData96 PageData() : id(0), placeId(0), canAddToHistory(true) { 97 guid.SetIsVoid(true); 98 } 99 100 int64_t id; // This is the moz_pages_w_icons id. 101 int64_t placeId; // This is the moz_places page id. 102 nsCString spec; 103 nsCString host; 104 nsCString bookmarkedSpec; 105 bool canAddToHistory; // False for disabled history and unsupported schemas. 106 nsCString guid; 107 }; 108 109 /** 110 * Info for a frame. 111 */ 112 struct FrameData { FrameDataFrameData113 FrameData(uint16_t aIndex, uint16_t aWidth) : index(aIndex), width(aWidth) {} 114 115 uint16_t index; 116 uint16_t width; 117 }; 118 119 /** 120 * Async fetches icon from database or network, associates it with the required 121 * page and finally notifies the change. 122 */ 123 class AsyncFetchAndSetIconForPage final : public Runnable, 124 public nsIStreamListener, 125 public nsIInterfaceRequestor, 126 public nsIChannelEventSink, 127 public mozIPlacesPendingOperation { 128 public: 129 NS_DECL_NSIRUNNABLE 130 NS_DECL_NSISTREAMLISTENER 131 NS_DECL_NSIINTERFACEREQUESTOR 132 NS_DECL_NSICHANNELEVENTSINK 133 NS_DECL_NSIREQUESTOBSERVER 134 NS_DECL_MOZIPLACESPENDINGOPERATION 135 NS_DECL_ISUPPORTS_INHERITED 136 137 /** 138 * Constructor. 139 * 140 * @param aIcon 141 * Icon to be fetched and associated. 142 * @param aPage 143 * Page to which associate the icon. 144 * @param aFaviconLoadPrivate 145 * Whether this favicon load is in private browsing. 146 * @param aCallback 147 * Function to be called when the fetch-and-associate process finishes. 148 * @param aLoadingPrincipal 149 * LoadingPrincipal of the icon to be fetched. 150 */ 151 AsyncFetchAndSetIconForPage(IconData& aIcon, PageData& aPage, 152 bool aFaviconLoadPrivate, 153 nsIFaviconDataCallback* aCallback, 154 nsIPrincipal* aLoadingPrincipal, 155 uint64_t aRequestContextID); 156 157 private: 158 nsresult FetchFromNetwork(); ~AsyncFetchAndSetIconForPage()159 virtual ~AsyncFetchAndSetIconForPage() {} 160 161 nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback; 162 IconData mIcon; 163 PageData mPage; 164 const bool mFaviconLoadPrivate; 165 nsMainThreadPtrHandle<nsIPrincipal> mLoadingPrincipal; 166 bool mCanceled; 167 nsCOMPtr<nsIRequest> mRequest; 168 uint64_t mRequestContextID; 169 }; 170 171 /** 172 * Associates the icon to the required page, finally dispatches an event to the 173 * main thread to notify the change to observers. 174 */ 175 class AsyncAssociateIconToPage final : public Runnable { 176 public: 177 NS_DECL_NSIRUNNABLE 178 179 /** 180 * Constructor. 181 * 182 * @param aIcon 183 * Icon to be associated. 184 * @param aPage 185 * Page to which associate the icon. 186 * @param aCallback 187 * Function to be called when the associate process finishes. 188 */ 189 AsyncAssociateIconToPage( 190 const IconData& aIcon, const PageData& aPage, 191 const nsMainThreadPtrHandle<nsIFaviconDataCallback>& aCallback); 192 193 private: 194 nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback; 195 IconData mIcon; 196 PageData mPage; 197 }; 198 199 /** 200 * Asynchronously tries to get the URL of a page's favicon, then notifies the 201 * given observer. 202 */ 203 class AsyncGetFaviconURLForPage final : public Runnable { 204 public: 205 NS_DECL_NSIRUNNABLE 206 207 /** 208 * Constructor. 209 * 210 * @param aPageSpec 211 * URL of the page whose favicon's URL we're fetching 212 * @param aPageHost 213 * Host of the page whose favicon's URL we're fetching 214 * @param aCallback 215 * function to be called once finished 216 * @param aPreferredWidth 217 * The preferred size for the icon 218 */ 219 AsyncGetFaviconURLForPage(const nsACString& aPageSpec, 220 const nsACString& aPageHost, 221 uint16_t aPreferredWidth, 222 nsIFaviconDataCallback* aCallback); 223 224 private: 225 uint16_t mPreferredWidth; 226 nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback; 227 nsCString mPageSpec; 228 nsCString mPageHost; 229 }; 230 231 /** 232 * Asynchronously tries to get the URL and data of a page's favicon, then 233 * notifies the given observer. 234 */ 235 class AsyncGetFaviconDataForPage final : public Runnable { 236 public: 237 NS_DECL_NSIRUNNABLE 238 239 /** 240 * Constructor. 241 * 242 * @param aPageSpec 243 * URL of the page whose favicon URL and data we're fetching 244 * @param aPageHost 245 * Host of the page whose favicon's URL we're fetching 246 * @param aPreferredWidth 247 * The preferred size of the icon. We will try to return an icon close 248 * to this size. 249 * @param aCallback 250 * function to be called once finished 251 */ 252 AsyncGetFaviconDataForPage(const nsACString& aPageSpec, 253 const nsACString& aPageHost, 254 uint16_t aPreferredWidth, 255 nsIFaviconDataCallback* aCallback); 256 257 private: 258 uint16_t mPreferredWidth; 259 nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback; 260 nsCString mPageSpec; 261 nsCString mPageHost; 262 }; 263 264 class AsyncReplaceFaviconData final : public Runnable { 265 public: 266 NS_DECL_NSIRUNNABLE 267 268 explicit AsyncReplaceFaviconData(const IconData& aIcon); 269 270 private: 271 nsresult RemoveIconDataCacheEntry(); 272 273 IconData mIcon; 274 }; 275 276 /** 277 * Notifies the icon change to favicon observers. 278 */ 279 class NotifyIconObservers final : public Runnable { 280 public: 281 NS_DECL_NSIRUNNABLE 282 283 /** 284 * Constructor. 285 * 286 * @param aIcon 287 * Icon information. Can be empty if no icon is associated to the page. 288 * @param aPage 289 * Page to which the icon information applies. 290 * @param aCallback 291 * Function to be notified in all cases. 292 */ 293 NotifyIconObservers( 294 const IconData& aIcon, const PageData& aPage, 295 const nsMainThreadPtrHandle<nsIFaviconDataCallback>& aCallback); 296 297 private: 298 nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback; 299 IconData mIcon; 300 PageData mPage; 301 302 void SendGlobalNotifications(nsIURI* aIconURI); 303 }; 304 305 /** 306 * Fetches and converts unsupported payloads. This is used during the initial 307 * migration of icons from the old to the new store. 308 */ 309 class FetchAndConvertUnsupportedPayloads final : public Runnable { 310 public: 311 NS_DECL_NSIRUNNABLE 312 313 /** 314 * Constructor. 315 * 316 * @param aDBConn 317 * The database connection to use. 318 */ 319 explicit FetchAndConvertUnsupportedPayloads(mozIStorageConnection* aDBConn); 320 321 private: 322 nsresult ConvertPayload(int64_t aId, const nsACString& aMimeType, 323 nsCString& aPayload, int32_t* aWidth); 324 nsresult StorePayload(int64_t aId, int32_t aWidth, const nsCString& aPayload); 325 326 nsCOMPtr<mozIStorageConnection> mDB; 327 }; 328 329 /** 330 * Copies Favicons from one page to another one. 331 */ 332 class AsyncCopyFavicons final : public Runnable { 333 public: 334 NS_DECL_NSIRUNNABLE 335 336 /** 337 * Constructor. 338 * 339 * @param aFromPage 340 * The originating page. 341 * @param aToPage 342 * The destination page. 343 * @param aFaviconLoadPrivate 344 * Whether this favicon load is in private browsing. 345 * @param aCallback 346 * An optional callback to invoke when done. 347 */ 348 AsyncCopyFavicons(PageData& aFromPage, PageData& aToPage, 349 nsIFaviconDataCallback* aCallback); 350 351 private: 352 PageData mFromPage; 353 PageData mToPage; 354 nsMainThreadPtrHandle<nsIFaviconDataCallback> mCallback; 355 }; 356 357 } // namespace places 358 } // namespace mozilla 359