tor-browser

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

MozNewTabWallpaperProtocolHandler.cpp (6131B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      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 file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "MozNewTabWallpaperProtocolHandler.h"
      8 
      9 #include "mozilla/ClearOnShutdown.h"
     10 #include "mozilla/net/NeckoParent.h"
     11 #include "nsContentUtils.h"
     12 #include "nsIFile.h"
     13 #include "nsIFileChannel.h"
     14 #include "nsIFileURL.h"
     15 #include "nsIMIMEService.h"
     16 #include "nsDirectoryServiceUtils.h"
     17 #include "nsAppDirectoryServiceDefs.h"
     18 #include "nsNetUtil.h"
     19 #include "nsURLHelper.h"
     20 #include "prio.h"
     21 #include "SimpleChannel.h"
     22 
     23 #define NEWTAB_WALLPAPER_SCHEME "moz-newtab-wallpaper"
     24 
     25 namespace mozilla {
     26 namespace net {
     27 
     28 StaticRefPtr<MozNewTabWallpaperProtocolHandler>
     29    MozNewTabWallpaperProtocolHandler::sSingleton;
     30 
     31 NS_IMPL_QUERY_INTERFACE(MozNewTabWallpaperProtocolHandler,
     32                        nsISubstitutingProtocolHandler, nsIProtocolHandler,
     33                        nsISupportsWeakReference)
     34 NS_IMPL_ADDREF_INHERITED(MozNewTabWallpaperProtocolHandler,
     35                         SubstitutingProtocolHandler)
     36 NS_IMPL_RELEASE_INHERITED(MozNewTabWallpaperProtocolHandler,
     37                          SubstitutingProtocolHandler)
     38 
     39 already_AddRefed<MozNewTabWallpaperProtocolHandler>
     40 MozNewTabWallpaperProtocolHandler::GetSingleton() {
     41  if (!sSingleton) {
     42    sSingleton = new MozNewTabWallpaperProtocolHandler();
     43    ClearOnShutdown(&sSingleton);
     44  }
     45 
     46  return do_AddRef(sSingleton);
     47 }
     48 
     49 // A moz-newtab-wallpaper URI is only loadable by chrome pages in the parent
     50 // process, or privileged content running in the privileged about content
     51 // process.
     52 MozNewTabWallpaperProtocolHandler::MozNewTabWallpaperProtocolHandler()
     53    : SubstitutingProtocolHandler(NEWTAB_WALLPAPER_SCHEME) {}
     54 
     55 RefPtr<RemoteStreamPromise> MozNewTabWallpaperProtocolHandler::NewStream(
     56    nsIURI* aChildURI, bool* aTerminateSender) {
     57  MOZ_ASSERT(!IsNeckoChild());
     58  MOZ_ASSERT(NS_IsMainThread());
     59 
     60  if (!aChildURI || !aTerminateSender) {
     61    return RemoteStreamPromise::CreateAndReject(NS_ERROR_INVALID_ARG, __func__);
     62  }
     63 
     64  *aTerminateSender = true;
     65  nsresult rv;
     66 
     67  bool isWallpaperScheme = false;
     68  if (NS_FAILED(
     69          aChildURI->SchemeIs(NEWTAB_WALLPAPER_SCHEME, &isWallpaperScheme)) ||
     70      !isWallpaperScheme) {
     71    return RemoteStreamPromise::CreateAndReject(NS_ERROR_UNKNOWN_PROTOCOL,
     72                                                __func__);
     73  }
     74 
     75  nsAutoCString host;
     76  if (NS_FAILED(aChildURI->GetAsciiHost(host)) || host.IsEmpty()) {
     77    return RemoteStreamPromise::CreateAndReject(NS_ERROR_UNEXPECTED, __func__);
     78  }
     79 
     80  *aTerminateSender = false;
     81 
     82  nsAutoCString resolvedSpec;
     83  rv = ResolveURI(aChildURI, resolvedSpec);
     84  if (NS_FAILED(rv)) {
     85    return RemoteStreamPromise::CreateAndReject(rv, __func__);
     86  }
     87 
     88  return mozilla::net::NeckoParent::CreateRemoteStreamForResolvedURI(
     89      aChildURI, resolvedSpec, "image/jpeg"_ns);
     90 }
     91 
     92 bool MozNewTabWallpaperProtocolHandler::ResolveSpecialCases(
     93    const nsACString& aHost, const nsACString& aPath,
     94    const nsACString& aPathname, nsACString& aResult) {
     95  if (aHost.IsEmpty()) {
     96    return false;
     97  }
     98 
     99  if (IsNeckoChild()) {
    100    // Child process: return placeholder file:// URI for
    101    // SubstitutingProtocolHandler. SubstituteChannel will replace with a remote
    102    // channel that proxies the load to the parent process.
    103    aResult.Assign("file://");
    104    aResult.Append(aHost);
    105    return true;
    106  } else {
    107    // Parent process: resolve to profile/wallpaper/{host} directory.
    108    nsCOMPtr<nsIFile> file;
    109    nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
    110                                         getter_AddRefs(file));
    111    if (NS_FAILED(rv)) {
    112      return false;
    113    }
    114 
    115    rv = file->AppendNative("wallpaper"_ns);
    116    if (NS_FAILED(rv)) {
    117      return false;
    118    }
    119 
    120    rv = file->AppendNative(nsCString(aHost));
    121    if (NS_FAILED(rv)) {
    122      return false;
    123    }
    124 
    125    nsCOMPtr<nsIURI> uri;
    126    rv = NS_NewFileURI(getter_AddRefs(uri), file);
    127    if (NS_FAILED(rv)) {
    128      return false;
    129    }
    130 
    131    return NS_SUCCEEDED(uri->GetSpec(aResult));
    132  }
    133 }
    134 
    135 nsresult MozNewTabWallpaperProtocolHandler::SubstituteChannel(
    136    nsIURI* aURI, nsILoadInfo* aLoadInfo, nsIChannel** aRetVal) {
    137  // Check if URI resolves to a file URI.
    138  nsAutoCString resolvedSpec;
    139  MOZ_TRY(ResolveURI(aURI, resolvedSpec));
    140 
    141  nsAutoCString scheme;
    142  MOZ_TRY(net_ExtractURLScheme(resolvedSpec, scheme));
    143 
    144  if (!scheme.EqualsLiteral("file")) {
    145    NS_WARNING("moz-newtab-wallpaper URIs should only resolve to file URIs.");
    146    return NS_ERROR_NO_INTERFACE;
    147  }
    148 
    149  if (IsNeckoChild()) {
    150    MOZ_TRY(SubstituteRemoteChannel(aURI, aLoadInfo, aRetVal));
    151  }
    152 
    153  return NS_OK;
    154 }
    155 
    156 Result<Ok, nsresult> MozNewTabWallpaperProtocolHandler::SubstituteRemoteChannel(
    157    nsIURI* aURI, nsILoadInfo* aLoadInfo, nsIChannel** aRetVal) {
    158  MOZ_ASSERT(IsNeckoChild());
    159  MOZ_TRY(aURI ? NS_OK : NS_ERROR_INVALID_ARG);
    160  MOZ_TRY(aLoadInfo ? NS_OK : NS_ERROR_INVALID_ARG);
    161 
    162 #ifdef DEBUG
    163  nsAutoCString resolvedSpec;
    164  MOZ_TRY(ResolveURI(aURI, resolvedSpec));
    165 
    166  nsAutoCString scheme;
    167  MOZ_TRY(net_ExtractURLScheme(resolvedSpec, scheme));
    168 
    169  MOZ_ASSERT(scheme.EqualsLiteral("file"));
    170 #endif /* DEBUG */
    171 
    172  RefPtr<RemoteStreamGetter> streamGetter =
    173      new RemoteStreamGetter(aURI, aLoadInfo);
    174 
    175  NewSimpleChannel(aURI, aLoadInfo, streamGetter, aRetVal);
    176  return Ok();
    177 }
    178 
    179 // static
    180 void MozNewTabWallpaperProtocolHandler::NewSimpleChannel(
    181    nsIURI* aURI, nsILoadInfo* aLoadinfo, RemoteStreamGetter* aStreamGetter,
    182    nsIChannel** aRetVal) {
    183  nsCOMPtr<nsIChannel> channel = NS_NewSimpleChannel(
    184      aURI, aLoadinfo, aStreamGetter,
    185      [](nsIStreamListener* listener, nsIChannel* simpleChannel,
    186         RemoteStreamGetter* getter) -> RequestOrReason {
    187        return getter->GetAsync(listener, simpleChannel,
    188                                &NeckoChild::SendGetMozNewTabWallpaperStream);
    189      });
    190 
    191  channel.swap(*aRetVal);
    192 }
    193 
    194 }  // namespace net
    195 }  // namespace mozilla