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 }