tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsIconChannel.cpp (3875B)


      1 /* -*- Mode: C++; tab-width: 20; 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 #include "mozilla/gfx/Swizzle.h"
      7 #include "mozilla/dom/ContentChild.h"
      8 #include "mozilla/NullPrincipal.h"
      9 #include "nsMimeTypes.h"
     10 #include "nsXULAppAPI.h"
     11 #include "AndroidBridge.h"
     12 #include "nsIconChannel.h"
     13 #include "nsIIconURI.h"
     14 #include "nsIStringStream.h"
     15 #include "nsNetUtil.h"
     16 #include "nsComponentManagerUtils.h"
     17 
     18 NS_IMPL_ISUPPORTS(nsIconChannel, nsIRequest, nsIChannel)
     19 
     20 using namespace mozilla;
     21 using mozilla::dom::ContentChild;
     22 
     23 static nsresult GetIconForExtension(const nsACString& aFileExt,
     24                                    uint32_t aIconSize, uint8_t* const aBuf) {
     25  if (!AndroidBridge::Bridge()) {
     26    return NS_ERROR_FAILURE;
     27  }
     28 
     29  AndroidBridge::Bridge()->GetIconForExtension(aFileExt, aIconSize, aBuf);
     30 
     31  return NS_OK;
     32 }
     33 
     34 static nsresult CallRemoteGetIconForExtension(const nsACString& aFileExt,
     35                                              uint32_t aIconSize,
     36                                              uint8_t* const aBuf) {
     37  NS_ENSURE_TRUE(aBuf != nullptr, NS_ERROR_NULL_POINTER);
     38 
     39  // An array has to be used to get data from remote process
     40  nsTArray<uint8_t> bits;
     41  uint32_t bufSize = aIconSize * aIconSize * 4;
     42 
     43  if (!ContentChild::GetSingleton()->SendGetIconForExtension(
     44          PromiseFlatCString(aFileExt), aIconSize, &bits)) {
     45    return NS_ERROR_FAILURE;
     46  }
     47 
     48  NS_ASSERTION(bits.Length() == bufSize, "Pixels array is incomplete");
     49  if (bits.Length() != bufSize) {
     50    return NS_ERROR_FAILURE;
     51  }
     52 
     53  memcpy(aBuf, bits.Elements(), bufSize);
     54 
     55  return NS_OK;
     56 }
     57 
     58 static nsresult moz_icon_to_channel(nsIURI* aURI, nsILoadInfo* aLoadInfo,
     59                                    const nsACString& aFileExt,
     60                                    uint32_t aIconSize, nsIChannel** aChannel) {
     61  NS_ENSURE_TRUE(aIconSize < 256 && aIconSize > 0, NS_ERROR_UNEXPECTED);
     62 
     63  int width = aIconSize;
     64  int height = aIconSize;
     65 
     66  // moz-icon data should have two bytes for the size,
     67  // then the ARGB pixel values with pre-multiplied Alpha
     68  const int channels = 4;
     69  CheckedInt32 buf_size =
     70      4 + channels * CheckedInt32(height) * CheckedInt32(width);
     71  if (!buf_size.isValid()) {
     72    return NS_ERROR_OUT_OF_MEMORY;
     73  }
     74  uint8_t* const buf = (uint8_t*)moz_xmalloc(buf_size.value());
     75  uint8_t* out = buf;
     76 
     77  *(out++) = width;
     78  *(out++) = height;
     79  *(out++) = uint8_t(mozilla::gfx::SurfaceFormat::R8G8B8A8);
     80 
     81  // Set all bits to ensure in nsIconDecoder we color manage and premultiply.
     82  *(out++) = 0xFF;
     83 
     84  nsresult rv;
     85  if (XRE_IsParentProcess()) {
     86    rv = GetIconForExtension(aFileExt, aIconSize, out);
     87  } else {
     88    rv = CallRemoteGetIconForExtension(aFileExt, aIconSize, out);
     89  }
     90  NS_ENSURE_SUCCESS(rv, rv);
     91 
     92  nsCOMPtr<nsIStringInputStream> stream =
     93      do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv);
     94  NS_ENSURE_SUCCESS(rv, rv);
     95 
     96  rv = stream->AdoptData((char*)buf, buf_size.value());
     97  NS_ENSURE_SUCCESS(rv, rv);
     98 
     99  return NS_NewInputStreamChannelInternal(
    100      aChannel, aURI, stream.forget(), nsLiteralCString(IMAGE_ICON_MS),
    101      /* aContentCharset */ ""_ns, aLoadInfo);
    102 }
    103 
    104 nsresult nsIconChannel::Init(nsIURI* aURI, nsILoadInfo* aLoadInfo) {
    105  nsCOMPtr<nsIMozIconURI> iconURI = do_QueryInterface(aURI);
    106  NS_ASSERTION(iconURI, "URI is not an nsIMozIconURI");
    107 
    108  nsAutoCString stockIcon;
    109  iconURI->GetStockIcon(stockIcon);
    110 
    111  uint32_t desiredImageSize;
    112  iconURI->GetImageSize(&desiredImageSize);
    113 
    114  nsAutoCString iconFileExt;
    115  iconURI->GetFileExtension(iconFileExt);
    116 
    117  return moz_icon_to_channel(iconURI, aLoadInfo, iconFileExt, desiredImageSize,
    118                             getter_AddRefs(mRealChannel));
    119 }