image/decoders/icon/win/nsIconChannel.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  *
     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/. */
     7 #include "mozilla/ArrayUtils.h"
     9 #include "nsIconChannel.h"
    10 #include "nsIIconURI.h"
    11 #include "nsIServiceManager.h"
    12 #include "nsIInterfaceRequestor.h"
    13 #include "nsIInterfaceRequestorUtils.h"
    14 #include "nsXPIDLString.h"
    15 #include "nsReadableUtils.h"
    16 #include "nsMimeTypes.h"
    17 #include "nsMemory.h"
    18 #include "nsIStringStream.h"
    19 #include "nsIURL.h"
    20 #include "nsNetUtil.h"
    21 #include "nsIFile.h"
    22 #include "nsIFileURL.h"
    23 #include "nsIMIMEService.h"
    24 #include "nsCExternalHandlerService.h"
    25 #include "nsDirectoryServiceDefs.h"
    27 #ifdef _WIN32_WINNT
    28 #undef _WIN32_WINNT
    29 #endif
    30 #define _WIN32_WINNT 0x0600
    32 // we need windows.h to read out registry information...
    33 #include <windows.h>
    34 #include <shellapi.h>
    35 #include <shlobj.h>
    36 #include <objbase.h>
    37 #include <wchar.h>
    39 using namespace mozilla;
    41 struct ICONFILEHEADER {
    42   uint16_t ifhReserved;
    43   uint16_t ifhType;
    44   uint16_t ifhCount;
    45 };
    47 struct ICONENTRY {
    48   int8_t ieWidth;
    49   int8_t ieHeight;
    50   uint8_t ieColors;
    51   uint8_t ieReserved;
    52   uint16_t iePlanes;
    53   uint16_t ieBitCount;
    54   uint32_t ieSizeImage;
    55   uint32_t ieFileOffset;
    56 };
    58 // Match stock icons with names
    59 static SHSTOCKICONID GetStockIconIDForName(const nsACString &aStockName)
    60 {
    61   // UAC shield icon
    62   if (aStockName == NS_LITERAL_CSTRING("uac-shield"))
    63     return SIID_SHIELD;
    65   return SIID_INVALID;
    66 }
    68 // nsIconChannel methods
    69 nsIconChannel::nsIconChannel()
    70 {
    71 }
    73 nsIconChannel::~nsIconChannel() 
    74 {}
    76 NS_IMPL_ISUPPORTS(nsIconChannel, 
    77                   nsIChannel, 
    78                   nsIRequest,
    79                   nsIRequestObserver,
    80                   nsIStreamListener)
    82 nsresult nsIconChannel::Init(nsIURI* uri)
    83 {
    84   NS_ASSERTION(uri, "no uri");
    85   mUrl = uri;
    86   mOriginalURI = uri;
    87   nsresult rv;
    88   mPump = do_CreateInstance(NS_INPUTSTREAMPUMP_CONTRACTID, &rv);
    89   return rv;
    90 }
    92 ////////////////////////////////////////////////////////////////////////////////
    93 // nsIRequest methods:
    95 NS_IMETHODIMP nsIconChannel::GetName(nsACString &result)
    96 {
    97   return mUrl->GetSpec(result);
    98 }
   100 NS_IMETHODIMP nsIconChannel::IsPending(bool *result)
   101 {
   102   return mPump->IsPending(result);
   103 }
   105 NS_IMETHODIMP nsIconChannel::GetStatus(nsresult *status)
   106 {
   107   return mPump->GetStatus(status);
   108 }
   110 NS_IMETHODIMP nsIconChannel::Cancel(nsresult status)
   111 {
   112   return mPump->Cancel(status);
   113 }
   115 NS_IMETHODIMP nsIconChannel::Suspend(void)
   116 {
   117   return mPump->Suspend();
   118 }
   120 NS_IMETHODIMP nsIconChannel::Resume(void)
   121 {
   122   return mPump->Resume();
   123 }
   124 NS_IMETHODIMP nsIconChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
   125 {
   126   *aLoadGroup = mLoadGroup;
   127   NS_IF_ADDREF(*aLoadGroup);
   128   return NS_OK;
   129 }
   131 NS_IMETHODIMP nsIconChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
   132 {
   133   mLoadGroup = aLoadGroup;
   134   return NS_OK;
   135 }
   137 NS_IMETHODIMP nsIconChannel::GetLoadFlags(uint32_t *aLoadAttributes)
   138 {
   139   return mPump->GetLoadFlags(aLoadAttributes);
   140 }
   142 NS_IMETHODIMP nsIconChannel::SetLoadFlags(uint32_t aLoadAttributes)
   143 {
   144   return mPump->SetLoadFlags(aLoadAttributes);
   145 }
   147 ////////////////////////////////////////////////////////////////////////////////
   148 // nsIChannel methods:
   150 NS_IMETHODIMP nsIconChannel::GetOriginalURI(nsIURI* *aURI)
   151 {
   152   *aURI = mOriginalURI;
   153   NS_ADDREF(*aURI);
   154   return NS_OK;
   155 }
   157 NS_IMETHODIMP nsIconChannel::SetOriginalURI(nsIURI* aURI)
   158 {
   159   NS_ENSURE_ARG_POINTER(aURI);
   160   mOriginalURI = aURI;
   161   return NS_OK;
   162 }
   164 NS_IMETHODIMP nsIconChannel::GetURI(nsIURI* *aURI)
   165 {
   166   *aURI = mUrl;
   167   NS_IF_ADDREF(*aURI);
   168   return NS_OK;
   169 }
   171 NS_IMETHODIMP
   172 nsIconChannel::Open(nsIInputStream **_retval)
   173 {
   174   return MakeInputStream(_retval, false);
   175 }
   177 nsresult nsIconChannel::ExtractIconInfoFromUrl(nsIFile ** aLocalFile, uint32_t * aDesiredImageSize, nsCString &aContentType, nsCString &aFileExtension)
   178 {
   179   nsresult rv = NS_OK;
   180   nsCOMPtr<nsIMozIconURI> iconURI (do_QueryInterface(mUrl, &rv));
   181   NS_ENSURE_SUCCESS(rv, rv);
   183   iconURI->GetImageSize(aDesiredImageSize);
   184   iconURI->GetContentType(aContentType);
   185   iconURI->GetFileExtension(aFileExtension);
   187   nsCOMPtr<nsIURL> url;
   188   rv = iconURI->GetIconURL(getter_AddRefs(url));
   189   if (NS_FAILED(rv) || !url) return NS_OK;
   191   nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(url, &rv);
   192   if (NS_FAILED(rv) || !fileURL) return NS_OK;
   194   nsCOMPtr<nsIFile> file;
   195   rv = fileURL->GetFile(getter_AddRefs(file));
   196   if (NS_FAILED(rv) || !file) return NS_OK;
   198   return file->Clone(aLocalFile);
   199 }
   201 NS_IMETHODIMP nsIconChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt)
   202 {
   203   nsCOMPtr<nsIInputStream> inStream;
   204   nsresult rv = MakeInputStream(getter_AddRefs(inStream), true);
   205   if (NS_FAILED(rv))
   206     return rv;
   208   // Init our streampump
   209   rv = mPump->Init(inStream, int64_t(-1), int64_t(-1), 0, 0, false);
   210   if (NS_FAILED(rv))
   211     return rv;
   213   rv = mPump->AsyncRead(this, ctxt);
   214   if (NS_SUCCEEDED(rv)) {
   215     // Store our real listener
   216     mListener = aListener;
   217     // Add ourself to the load group, if available
   218     if (mLoadGroup)
   219       mLoadGroup->AddRequest(this, nullptr);
   220   }
   221   return rv;
   222 }
   224 static DWORD GetSpecialFolderIcon(nsIFile* aFile, int aFolder, SHFILEINFOW* aSFI, UINT aInfoFlags)
   225 {
   226   DWORD shellResult = 0;
   228   if (!aFile)
   229     return shellResult;
   231   wchar_t fileNativePath[MAX_PATH];
   232   nsAutoString fileNativePathStr;
   233   aFile->GetPath(fileNativePathStr);
   234   ::GetShortPathNameW(fileNativePathStr.get(), fileNativePath, ArrayLength(fileNativePath));
   236   LPITEMIDLIST idList;
   237   HRESULT hr = ::SHGetSpecialFolderLocation(nullptr, aFolder, &idList);
   238   if (SUCCEEDED(hr)) {
   239     wchar_t specialNativePath[MAX_PATH];
   240     ::SHGetPathFromIDListW(idList, specialNativePath);
   241     ::GetShortPathNameW(specialNativePath, specialNativePath, ArrayLength(specialNativePath));
   243     if (!wcsicmp(fileNativePath, specialNativePath)) {
   244       aInfoFlags |= (SHGFI_PIDL | SHGFI_SYSICONINDEX);
   245       shellResult = ::SHGetFileInfoW((LPCWSTR)(LPCITEMIDLIST)idList, 0, aSFI,
   246                                      sizeof(*aSFI), aInfoFlags);
   247     }
   248   }
   249   CoTaskMemFree(idList);
   250   return shellResult;
   251 }
   253 static UINT GetSizeInfoFlag(uint32_t aDesiredImageSize)
   254 {
   255   UINT infoFlag;
   256   if (aDesiredImageSize > 16)
   257     infoFlag = SHGFI_SHELLICONSIZE;
   258   else
   259     infoFlag = SHGFI_SMALLICON;
   261   return infoFlag;
   262 }
   264 nsresult nsIconChannel::GetHIconFromFile(HICON *hIcon)
   265 {
   266   nsXPIDLCString contentType;
   267   nsCString fileExt;
   268   nsCOMPtr<nsIFile> localFile; // file we want an icon for
   269   uint32_t desiredImageSize;
   270   nsresult rv = ExtractIconInfoFromUrl(getter_AddRefs(localFile), &desiredImageSize, contentType, fileExt);
   271   NS_ENSURE_SUCCESS(rv, rv);
   273   // if the file exists, we are going to use it's real attributes...otherwise we only want to use it for it's extension...
   274   SHFILEINFOW      sfi;
   275   UINT infoFlags = SHGFI_ICON;
   277   bool fileExists = false;
   279   nsAutoString filePath;
   280   CopyASCIItoUTF16(fileExt, filePath);
   281   if (localFile)
   282   {
   283     rv = localFile->Normalize();
   284     NS_ENSURE_SUCCESS(rv, rv);
   286     localFile->GetPath(filePath);
   287     if (filePath.Length() < 2 || filePath[1] != ':')
   288       return NS_ERROR_MALFORMED_URI; // UNC
   290     if (filePath.Last() == ':')
   291       filePath.Append('\\');
   292     else {
   293       localFile->Exists(&fileExists);
   294       if (!fileExists)
   295        localFile->GetLeafName(filePath);
   296     }
   297   }
   299   if (!fileExists)
   300    infoFlags |= SHGFI_USEFILEATTRIBUTES;
   302   infoFlags |= GetSizeInfoFlag(desiredImageSize);
   304   // if we have a content type... then use it! but for existing files, we want
   305   // to show their real icon.
   306   if (!fileExists && !contentType.IsEmpty())
   307   {
   308     nsCOMPtr<nsIMIMEService> mimeService (do_GetService(NS_MIMESERVICE_CONTRACTID, &rv));
   309     NS_ENSURE_SUCCESS(rv, rv);
   311     nsAutoCString defFileExt;
   312     mimeService->GetPrimaryExtension(contentType, fileExt, defFileExt);
   313     // If the mime service does not know about this mime type, we show
   314     // the generic icon.
   315     // In any case, we need to insert a '.' before the extension.
   316     filePath = NS_LITERAL_STRING(".") + NS_ConvertUTF8toUTF16(defFileExt);
   317   }
   319   // Is this the "Desktop" folder?
   320   DWORD shellResult = GetSpecialFolderIcon(localFile, CSIDL_DESKTOP, &sfi, infoFlags);
   321   if (!shellResult) {
   322     // Is this the "My Documents" folder?
   323     shellResult = GetSpecialFolderIcon(localFile, CSIDL_PERSONAL, &sfi, infoFlags);
   324   }
   326   // There are other "Special Folders" and Namespace entities that we are not 
   327   // fetching icons for, see: 
   328   // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/enums/csidl.asp
   329   // If we ever need to get them, code to do so would be inserted here. 
   331   // Not a special folder, or something else failed above.
   332   if (!shellResult)
   333     shellResult = ::SHGetFileInfoW(filePath.get(),
   334                                    FILE_ATTRIBUTE_ARCHIVE, &sfi, sizeof(sfi), infoFlags);
   336   if (shellResult && sfi.hIcon)
   337     *hIcon = sfi.hIcon;
   338   else
   339     rv = NS_ERROR_NOT_AVAILABLE;
   341   return rv;
   342 }
   344 nsresult nsIconChannel::GetStockHIcon(nsIMozIconURI *aIconURI, HICON *hIcon)
   345 {
   346   nsresult rv = NS_OK;
   348   // We can only do this on Vista or above
   349   HMODULE hShellDLL = ::LoadLibraryW(L"shell32.dll");
   350   decltype(SHGetStockIconInfo)* pSHGetStockIconInfo =
   351     (decltype(SHGetStockIconInfo)*) ::GetProcAddress(hShellDLL, "SHGetStockIconInfo");
   353   if (pSHGetStockIconInfo)
   354   {
   355     uint32_t desiredImageSize;
   356     aIconURI->GetImageSize(&desiredImageSize);
   357     nsAutoCString stockIcon;
   358     aIconURI->GetStockIcon(stockIcon);
   360     SHSTOCKICONID stockIconID = GetStockIconIDForName(stockIcon);
   361     if (stockIconID == SIID_INVALID)
   362       return NS_ERROR_NOT_AVAILABLE;
   364     UINT infoFlags = SHGSI_ICON;
   365     infoFlags |= GetSizeInfoFlag(desiredImageSize);
   367     SHSTOCKICONINFO sii = {0};
   368     sii.cbSize = sizeof(sii);
   369     HRESULT hr = pSHGetStockIconInfo(stockIconID, infoFlags, &sii);
   371     if (SUCCEEDED(hr))
   372       *hIcon = sii.hIcon;
   373     else
   374       rv = NS_ERROR_FAILURE;
   375   }
   376   else
   377   {
   378     rv = NS_ERROR_NOT_AVAILABLE;
   379   }
   381   if (hShellDLL)
   382     ::FreeLibrary(hShellDLL);
   384   return rv;
   385 }
   387 // Given a BITMAPINFOHEADER, returns the size of the color table.
   388 static int GetColorTableSize(BITMAPINFOHEADER* aHeader)
   389 {
   390   int colorTableSize = -1;
   392   // http://msdn.microsoft.com/en-us/library/dd183376%28v=VS.85%29.aspx
   393   switch (aHeader->biBitCount) {
   394   case 0:
   395     colorTableSize = 0;
   396     break;
   397   case 1:
   398     colorTableSize = 2 * sizeof(RGBQUAD);
   399     break;
   400   case 4:
   401   case 8:
   402   {
   403     // The maximum possible size for the color table is 2**bpp, so check for
   404     // that and fail if we're not in those bounds
   405     unsigned int maxEntries = 1 << (aHeader->biBitCount);
   406     if (aHeader->biClrUsed > 0 && aHeader->biClrUsed <= maxEntries)
   407       colorTableSize = aHeader->biClrUsed * sizeof(RGBQUAD);
   408     else if (aHeader->biClrUsed == 0)
   409       colorTableSize = maxEntries * sizeof(RGBQUAD);
   410     break;
   411   }
   412   case 16:
   413   case 32:
   414     // If we have BI_BITFIELDS compression, we would normally need 3 DWORDS for
   415     // the bitfields mask which would be stored in the color table; However, 
   416     // we instead force the bitmap to request data of type BI_RGB so the color
   417     // table should be of size 0.  
   418     // Setting aHeader->biCompression = BI_RGB forces the later call to 
   419     // GetDIBits to return to us BI_RGB data.
   420     if (aHeader->biCompression == BI_BITFIELDS) {
   421       aHeader->biCompression = BI_RGB;
   422     }
   423     colorTableSize = 0;
   424     break;
   425   case 24:
   426     colorTableSize = 0;
   427     break;
   428   }
   430   if (colorTableSize < 0)
   431     NS_WARNING("Unable to figure out the color table size for this bitmap");
   433   return colorTableSize;
   434 }
   436 // Given a header and a size, creates a freshly allocated BITMAPINFO structure.
   437 // It is the caller's responsibility to null-check and delete the structure.
   438 static BITMAPINFO* CreateBitmapInfo(BITMAPINFOHEADER* aHeader,
   439                                     size_t aColorTableSize)
   440 {
   441   BITMAPINFO* bmi = (BITMAPINFO*) ::operator new(sizeof(BITMAPINFOHEADER) +
   442                                                  aColorTableSize,
   443                                                  mozilla::fallible_t());
   444   if (bmi) {
   445     memcpy(bmi, aHeader, sizeof(BITMAPINFOHEADER));
   446     memset(bmi->bmiColors, 0, aColorTableSize);
   447   }
   448   return bmi;
   449 }
   451 nsresult nsIconChannel::MakeInputStream(nsIInputStream** _retval, bool nonBlocking)
   452 {
   453   // Check whether the icon requested's a file icon or a stock icon
   454   nsresult rv = NS_ERROR_NOT_AVAILABLE;
   456   // GetDIBits does not exist on windows mobile.
   457   HICON hIcon = nullptr;
   459   nsCOMPtr<nsIMozIconURI> iconURI(do_QueryInterface(mUrl, &rv));
   460   NS_ENSURE_SUCCESS(rv, rv);
   462   nsAutoCString stockIcon;
   463   iconURI->GetStockIcon(stockIcon);
   464   if (!stockIcon.IsEmpty())
   465     rv = GetStockHIcon(iconURI, &hIcon);
   466   else
   467     rv = GetHIconFromFile(&hIcon);
   469   NS_ENSURE_SUCCESS(rv, rv);
   471   if (hIcon)
   472   {
   473     // we got a handle to an icon. Now we want to get a bitmap for the icon using GetIconInfo....
   474     ICONINFO iconInfo;
   475     if (GetIconInfo(hIcon, &iconInfo))
   476     {
   477       // we got the bitmaps, first find out their size
   478       HDC hDC = CreateCompatibleDC(nullptr); // get a device context for the screen.
   479       BITMAPINFOHEADER maskHeader  = {sizeof(BITMAPINFOHEADER)};
   480       BITMAPINFOHEADER colorHeader = {sizeof(BITMAPINFOHEADER)};
   481       int colorTableSize, maskTableSize;
   482       if (GetDIBits(hDC, iconInfo.hbmMask,  0, 0, nullptr, (BITMAPINFO*)&maskHeader,  DIB_RGB_COLORS) &&
   483           GetDIBits(hDC, iconInfo.hbmColor, 0, 0, nullptr, (BITMAPINFO*)&colorHeader, DIB_RGB_COLORS) &&
   484           maskHeader.biHeight == colorHeader.biHeight &&
   485           maskHeader.biWidth  == colorHeader.biWidth  &&
   486           colorHeader.biBitCount > 8 &&
   487           colorHeader.biSizeImage > 0 &&
   488           colorHeader.biWidth >= 0 && colorHeader.biWidth <= 255 &&
   489           colorHeader.biHeight >= 0 && colorHeader.biHeight <= 255 &&
   490           maskHeader.biSizeImage > 0  &&
   491           (colorTableSize = GetColorTableSize(&colorHeader)) >= 0 &&
   492           (maskTableSize  = GetColorTableSize(&maskHeader))  >= 0) {
   493         uint32_t iconSize = sizeof(ICONFILEHEADER) +
   494                             sizeof(ICONENTRY) +
   495                             sizeof(BITMAPINFOHEADER) +
   496                             colorHeader.biSizeImage +
   497                             maskHeader.biSizeImage;
   499         char *buffer = new char[iconSize];
   500         if (!buffer)
   501           rv = NS_ERROR_OUT_OF_MEMORY;
   502         else {
   503           char *whereTo = buffer;
   504           int howMuch;
   506           // the data starts with an icon file header
   507           ICONFILEHEADER iconHeader;
   508           iconHeader.ifhReserved = 0;
   509           iconHeader.ifhType = 1;
   510           iconHeader.ifhCount = 1;
   511           howMuch = sizeof(ICONFILEHEADER);
   512           memcpy(whereTo, &iconHeader, howMuch);
   513           whereTo += howMuch;
   515           // followed by the single icon entry
   516           ICONENTRY iconEntry;
   517           iconEntry.ieWidth = static_cast<int8_t>(colorHeader.biWidth);
   518           iconEntry.ieHeight = static_cast<int8_t>(colorHeader.biHeight);
   519           iconEntry.ieColors = 0;
   520           iconEntry.ieReserved = 0;
   521           iconEntry.iePlanes = 1;
   522           iconEntry.ieBitCount = colorHeader.biBitCount;
   523           iconEntry.ieSizeImage = sizeof(BITMAPINFOHEADER) +
   524                                   colorHeader.biSizeImage +
   525                                   maskHeader.biSizeImage;
   526           iconEntry.ieFileOffset = sizeof(ICONFILEHEADER) + sizeof(ICONENTRY);
   527           howMuch = sizeof(ICONENTRY);
   528           memcpy(whereTo, &iconEntry, howMuch);
   529           whereTo += howMuch;
   531           // followed by the bitmap info header
   532           // (doubling the height because icons have two bitmaps)
   533           colorHeader.biHeight *= 2;
   534           colorHeader.biSizeImage += maskHeader.biSizeImage;
   535           howMuch = sizeof(BITMAPINFOHEADER);
   536           memcpy(whereTo, &colorHeader, howMuch);
   537           whereTo += howMuch;
   538           colorHeader.biHeight /= 2;
   539           colorHeader.biSizeImage -= maskHeader.biSizeImage;
   541           // followed by the XOR bitmap data (colorHeader)
   542           // (you'd expect the color table to come here, but it apparently doesn't)
   543           BITMAPINFO* colorInfo = CreateBitmapInfo(&colorHeader, colorTableSize);
   544           if (colorInfo && GetDIBits(hDC, iconInfo.hbmColor, 0,
   545                                      colorHeader.biHeight, whereTo, colorInfo,
   546                                      DIB_RGB_COLORS)) {
   547             whereTo += colorHeader.biSizeImage;
   549             // and finally the AND bitmap data (maskHeader)
   550             BITMAPINFO* maskInfo = CreateBitmapInfo(&maskHeader, maskTableSize);
   551             if (maskInfo && GetDIBits(hDC, iconInfo.hbmMask, 0,
   552                                       maskHeader.biHeight, whereTo, maskInfo,
   553                                       DIB_RGB_COLORS)) {
   554               // Now, create a pipe and stuff our data into it
   555               nsCOMPtr<nsIInputStream> inStream;
   556               nsCOMPtr<nsIOutputStream> outStream;
   557               rv = NS_NewPipe(getter_AddRefs(inStream), getter_AddRefs(outStream),
   558                               iconSize, iconSize, nonBlocking);
   559               if (NS_SUCCEEDED(rv)) {
   560                 uint32_t written;
   561                 rv = outStream->Write(buffer, iconSize, &written);
   562                 if (NS_SUCCEEDED(rv)) {
   563                   NS_ADDREF(*_retval = inStream);
   564                 }
   565               }
   567             } // if we got bitmap bits
   568             delete maskInfo;
   569           } // if we got mask bits
   570           delete colorInfo;
   571           delete [] buffer;
   572         } // if we allocated the buffer
   573       } // if we got mask size
   575       DeleteDC(hDC);
   576       DeleteObject(iconInfo.hbmColor);
   577       DeleteObject(iconInfo.hbmMask);
   578     } // if we got icon info
   579     DestroyIcon(hIcon);
   580   } // if we got an hIcon
   582   // If we didn't make a stream, then fail.
   583   if (!*_retval && NS_SUCCEEDED(rv))
   584     rv = NS_ERROR_NOT_AVAILABLE;
   585   return rv;
   586 }
   588 NS_IMETHODIMP nsIconChannel::GetContentType(nsACString &aContentType) 
   589 {
   590   aContentType.AssignLiteral(IMAGE_ICO);
   591   return NS_OK;
   592 }
   594 NS_IMETHODIMP
   595 nsIconChannel::SetContentType(const nsACString &aContentType)
   596 {
   597   // It doesn't make sense to set the content-type on this type
   598   // of channel...
   599   return NS_ERROR_FAILURE;
   600 }
   602 NS_IMETHODIMP nsIconChannel::GetContentCharset(nsACString &aContentCharset) 
   603 {
   604   aContentCharset.Truncate();
   605   return NS_OK;
   606 }
   608 NS_IMETHODIMP
   609 nsIconChannel::SetContentCharset(const nsACString &aContentCharset)
   610 {
   611   // It doesn't make sense to set the content-charset on this type
   612   // of channel...
   613   return NS_ERROR_FAILURE;
   614 }
   616 NS_IMETHODIMP
   617 nsIconChannel::GetContentDisposition(uint32_t *aContentDisposition)
   618 {
   619   return NS_ERROR_NOT_AVAILABLE;
   620 }
   622 NS_IMETHODIMP
   623 nsIconChannel::SetContentDisposition(uint32_t aContentDisposition)
   624 {
   625   return NS_ERROR_NOT_AVAILABLE;
   626 }
   628 NS_IMETHODIMP
   629 nsIconChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename)
   630 {
   631   return NS_ERROR_NOT_AVAILABLE;
   632 }
   634 NS_IMETHODIMP
   635 nsIconChannel::SetContentDispositionFilename(const nsAString &aContentDispositionFilename)
   636 {
   637   return NS_ERROR_NOT_AVAILABLE;
   638 }
   640 NS_IMETHODIMP
   641 nsIconChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader)
   642 {
   643   return NS_ERROR_NOT_AVAILABLE;
   644 }
   646 NS_IMETHODIMP nsIconChannel::GetContentLength(int64_t *aContentLength)
   647 {
   648   *aContentLength = mContentLength;
   649   return NS_OK;
   650 }
   652 NS_IMETHODIMP nsIconChannel::SetContentLength(int64_t aContentLength)
   653 {
   654   NS_NOTREACHED("nsIconChannel::SetContentLength");
   655   return NS_ERROR_NOT_IMPLEMENTED;
   656 }
   658 NS_IMETHODIMP nsIconChannel::GetOwner(nsISupports* *aOwner)
   659 {
   660   *aOwner = mOwner.get();
   661   NS_IF_ADDREF(*aOwner);
   662   return NS_OK;
   663 }
   665 NS_IMETHODIMP nsIconChannel::SetOwner(nsISupports* aOwner)
   666 {
   667   mOwner = aOwner;
   668   return NS_OK;
   669 }
   671 NS_IMETHODIMP nsIconChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
   672 {
   673   *aNotificationCallbacks = mCallbacks.get();
   674   NS_IF_ADDREF(*aNotificationCallbacks);
   675   return NS_OK;
   676 }
   678 NS_IMETHODIMP nsIconChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
   679 {
   680   mCallbacks = aNotificationCallbacks;
   681   return NS_OK;
   682 }
   684 NS_IMETHODIMP nsIconChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
   685 {
   686   *aSecurityInfo = nullptr;
   687   return NS_OK;
   688 }
   690 // nsIRequestObserver methods
   691 NS_IMETHODIMP nsIconChannel::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
   692 {
   693   if (mListener)
   694     return mListener->OnStartRequest(this, aContext);
   695   return NS_OK;
   696 }
   698 NS_IMETHODIMP nsIconChannel::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext, nsresult aStatus)
   699 {
   700   if (mListener) {
   701     mListener->OnStopRequest(this, aContext, aStatus);
   702     mListener = nullptr;
   703   }
   705   // Remove from load group
   706   if (mLoadGroup)
   707     mLoadGroup->RemoveRequest(this, nullptr, aStatus);
   709   // Drop notification callbacks to prevent cycles.
   710   mCallbacks = nullptr;
   712   return NS_OK;
   713 }
   715 // nsIStreamListener methods
   716 NS_IMETHODIMP nsIconChannel::OnDataAvailable(nsIRequest* aRequest,
   717                                              nsISupports* aContext,
   718                                              nsIInputStream* aStream,
   719                                              uint64_t aOffset,
   720                                              uint32_t aCount)
   721 {
   722   if (mListener)
   723     return mListener->OnDataAvailable(this, aContext, aStream, aOffset, aCount);
   724   return NS_OK;
   725 }

mercurial