tor-browser

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

commit de1557487939cf263648d94bca1a30dd66759edd
parent 105c0ee1489b02f857cb2fbb39533cd86a24d462
Author: Sandor Molnar <smolnar@mozilla.com>
Date:   Wed,  7 Jan 2026 18:48:01 +0200

Revert "Bug 2002144 - Replace New Tab Wallpaper blob URLs with MozNewTabWallpaper protocol handler. r=mconley,home-newtab-reviewers" for causing build bustages @ NeckoParent.cpp

This reverts commit f063a98a3dbb6ade3fc46694c7ac9f9946874612.

Revert "Bug 2002129 - Add unit tests for MozNewTabWallpaperProtocolHandler. r=necko-reviewers,valentin"

This reverts commit cd18695e48ac25a4d6e14b794aac886e52386a2a.

Revert "Bug 1989609 - Create protocol handler to allow New Tabs in containers to use custom wallpapers. r=home-newtab-reviewers,necko-reviewers,mconley,kershaw,ckerschb"

This reverts commit d2fb41d9d1fc48af33430b6965d6c5fc04ad7d72.

Diffstat:
Mbrowser/extensions/newtab/lib/Wallpapers/WallpaperFeed.sys.mjs | 108++++++++++++++++++++++++-------------------------------------------------------
Mbrowser/extensions/newtab/test/xpcshell/test_WallpaperFeed.js | 28++++++++++++----------------
Mcaps/nsScriptSecurityManager.cpp | 3+--
Mnetwerk/base/nsNetUtil.cpp | 10----------
Mnetwerk/build/components.conf | 19-------------------
Mnetwerk/ipc/NeckoParent.cpp | 151------------------------------------------------------------------------------
Mnetwerk/ipc/NeckoParent.h | 18------------------
Mnetwerk/ipc/PNecko.ipdl | 5-----
Dnetwerk/protocol/res/MozNewTabWallpaperProtocolHandler.cpp | 195-------------------------------------------------------------------------------
Dnetwerk/protocol/res/MozNewTabWallpaperProtocolHandler.h | 91-------------------------------------------------------------------------------
Mnetwerk/protocol/res/PageThumbProtocolHandler.cpp | 86++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Mnetwerk/protocol/res/moz.build | 2--
Dnetwerk/test/unit/test_wallpaper_protocol.js | 38--------------------------------------
Mnetwerk/test/unit/xpcshell.toml | 2--
14 files changed, 129 insertions(+), 627 deletions(-)

diff --git a/browser/extensions/newtab/lib/Wallpapers/WallpaperFeed.sys.mjs b/browser/extensions/newtab/lib/Wallpapers/WallpaperFeed.sys.mjs @@ -2,8 +2,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs"; - const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { BasePromiseWorker: "resource://gre/modules/PromiseWorker.sys.mjs", @@ -39,22 +37,12 @@ const RS_FALLBACK_BASE_URL = export class WallpaperFeed { #customBackgroundObjectURL = null; - // @backward-compat { version 148 } This newtab train-hop compatibility - // shim can be removed once Firefox 148 makes it to the release channel. - #usesProtocolHandler = - Services.vc.compare(AppConstants.MOZ_APP_VERSION, "148.0a1") >= 0; - constructor() { this.loaded = false; this.wallpaperClient = null; this._onSync = this.onSync.bind(this); } - // Constructs a moz-newtab-wallpaper:// URI for the given wallpaper UUID. - getWallpaperURL(uuid) { - return `moz-newtab-wallpaper://${uuid}`; - } - /** * This thin wrapper around global.fetch makes it easier for us to write * automated tests that simulate responses from this fetch. @@ -111,15 +99,6 @@ export class WallpaperFeed { } async updateWallpapers(isStartup = false) { - // @backward-compat { version 148 } This newtab train-hop compatibility - // shim can be removed once Firefox 148 makes it to the release channel. - if (!this.#usesProtocolHandler) { - if (this.#customBackgroundObjectURL) { - URL.revokeObjectURL(this.#customBackgroundObjectURL); - this.#customBackgroundObjectURL = null; - } - } - let uuid = Services.prefs.getStringPref( PREF_WALLPAPERS_CUSTOM_WALLPAPER_UUID, "" @@ -130,43 +109,35 @@ export class WallpaperFeed { "" ); + if (this.#customBackgroundObjectURL) { + URL.revokeObjectURL(this.#customBackgroundObjectURL); + this.#customBackgroundObjectURL = null; + } + if (uuid && selectedWallpaper === "custom") { - // @backward-compat { version 148 } This newtab train-hop compatibility - // shim can be removed once Firefox 148 makes it to the release channel. - if (this.#usesProtocolHandler) { - const wallpaperURI = this.getWallpaperURL(uuid); + const wallpaperDir = PathUtils.join(PathUtils.profileDir, "wallpaper"); + const filePath = PathUtils.join(wallpaperDir, uuid); + + try { + let testFile = await IOUtils.getFile(filePath); + + if (!testFile) { + throw new Error("File does not exist"); + } + + let imageFile = await File.createFromNsIFile(testFile); + this.#customBackgroundObjectURL = URL.createObjectURL(imageFile); this.store.dispatch( ac.BroadcastToContent({ type: at.WALLPAPERS_CUSTOM_SET, - data: wallpaperURI, + data: this.#customBackgroundObjectURL, }) ); - } else { - const wallpaperDir = PathUtils.join(PathUtils.profileDir, "wallpaper"); - const filePath = PathUtils.join(wallpaperDir, uuid); - - try { - let testFile = await IOUtils.getFile(filePath); - - if (!testFile) { - throw new Error("File does not exist"); - } - - let imageFile = await File.createFromNsIFile(testFile); - this.#customBackgroundObjectURL = URL.createObjectURL(imageFile); - - this.store.dispatch( - ac.BroadcastToContent({ - type: at.WALLPAPERS_CUSTOM_SET, - data: this.#customBackgroundObjectURL, - }) - ); - } catch (error) { - console.warn(`Wallpaper file not found: ${error.message}`); - Services.prefs.clearUserPref(PREF_WALLPAPERS_CUSTOM_WALLPAPER_UUID); - return; - } + } catch (error) { + console.warn(`Wallpaper file not found: ${error.message}`); + Services.prefs.clearUserPref(PREF_WALLPAPERS_CUSTOM_WALLPAPER_UUID); + return; } } else { this.store.dispatch( @@ -310,32 +281,19 @@ export class WallpaperFeed { await IOUtils.write(filePath, uint8Array, { tmpPath: `${filePath}.tmp` }); - // @backward-compat { version 148 } This newtab train-hop compatibility - // shim can be removed once Firefox 148 makes it to the release channel. - if (this.#usesProtocolHandler) { - const wallpaperURI = this.getWallpaperURL(uuid); - - this.store.dispatch( - ac.BroadcastToContent({ - type: at.WALLPAPERS_CUSTOM_SET, - data: wallpaperURI, - }) - ); - } else { - if (this.#customBackgroundObjectURL) { - URL.revokeObjectURL(this.#customBackgroundObjectURL); - this.#customBackgroundObjectURL = null; - } + if (this.#customBackgroundObjectURL) { + URL.revokeObjectURL(this.#customBackgroundObjectURL); + this.#customBackgroundObjectURL = null; + } - this.#customBackgroundObjectURL = URL.createObjectURL(file); + this.#customBackgroundObjectURL = URL.createObjectURL(file); - this.store.dispatch( - ac.BroadcastToContent({ - type: at.WALLPAPERS_CUSTOM_SET, - data: this.#customBackgroundObjectURL, - }) - ); - } + this.store.dispatch( + ac.BroadcastToContent({ + type: at.WALLPAPERS_CUSTOM_SET, + data: this.#customBackgroundObjectURL, + }) + ); this.store.dispatch( ac.SetPref("newtabWallpapers.customWallpaper.theme", wallpaperTheme) diff --git a/browser/extensions/newtab/test/xpcshell/test_WallpaperFeed.js b/browser/extensions/newtab/test/xpcshell/test_WallpaperFeed.js @@ -202,10 +202,10 @@ add_task(async function test_Wallpaper_Upload() { }); /** - * Tests that the parent process sends down a moz-newtab-wallpaper:// protocol URI - * to newtab to render as the background. + * Tests that the parent process sends down a consistent object URL to newtab to + * render as the background. */ -add_task(async function test_Wallpaper_protocolURI() { +add_task(async function test_Wallpaper_objectURI() { let sandbox = sinon.createSandbox(); let feed = getWallpaperFeedForTest(sandbox); @@ -243,26 +243,22 @@ add_task(async function test_Wallpaper_protocolURI() { feed.store.dispatch.calledWith( actionCreators.BroadcastToContent({ type: actionTypes.WALLPAPERS_CUSTOM_SET, - data: sandbox.match("moz-newtab-wallpaper://"), + data: sandbox.match("blob:null/"), }) - ), - "Should dispatch WALLPAPERS_CUSTOM_SET with moz-newtab-wallpaper:// URI" + ) ); - // Verify the protocol URI uses the correct scheme and gets stored in state + // Now ensure that a consistent object URL gets returned for each subsequent + // request for a wallpaper by checking to see that it exists in the state + // object. This URL is non-deterministic, but we can pull it out from what was + // just passed to the store dispatch method. const [action] = feed.store.dispatch.getCall(0).args; - const wallpaperURI = action.data; - - Assert.ok( - wallpaperURI.startsWith("moz-newtab-wallpaper://"), - "Wallpaper URI should use moz-newtab-wallpaper:// protocol" - ); - + const wallpaperURL = action.data; const state = reducers.Wallpapers(null, action); Assert.equal( state.uploadedWallpaper, - wallpaperURI, - "Should have updated the state to include the protocol URI" + wallpaperURL, + "Should have updated the state to include the object URL" ); // Cleanup files diff --git a/caps/nsScriptSecurityManager.cpp b/caps/nsScriptSecurityManager.cpp @@ -1073,8 +1073,7 @@ nsresult nsScriptSecurityManager::CheckLoadURIFlags( } } } else if (targetScheme.EqualsLiteral("moz-page-thumb") || - targetScheme.EqualsLiteral("page-icon") || - targetScheme.EqualsLiteral("moz-newtab-wallpaper")) { + targetScheme.EqualsLiteral("page-icon")) { if (XRE_IsParentProcess()) { return NS_OK; } diff --git a/netwerk/base/nsNetUtil.cpp b/netwerk/base/nsNetUtil.cpp @@ -107,7 +107,6 @@ #include "mozilla/net/CookieJarSettings.h" #include "mozilla/net/MozSrcProtocolHandler.h" #include "mozilla/net/ExtensionProtocolHandler.h" -#include "mozilla/net/MozNewTabWallpaperProtocolHandler.h" #include "mozilla/net/PageThumbProtocolHandler.h" #include "mozilla/net/SFVService.h" #include "nsICookieService.h" @@ -1994,15 +1993,6 @@ nsresult NS_NewURI(nsIURI** aURI, const nsACString& aSpec, return handler->NewURI(aSpec, aCharset, aBaseURI, aURI); } - if (scheme.EqualsLiteral("moz-newtab-wallpaper")) { - RefPtr<mozilla::net::MozNewTabWallpaperProtocolHandler> handler = - mozilla::net::MozNewTabWallpaperProtocolHandler::GetSingleton(); - if (!handler) { - return NS_ERROR_NOT_AVAILABLE; - } - return handler->NewURI(aSpec, aCharset, aBaseURI, aURI); - } - if (scheme.EqualsLiteral("about")) { return nsAboutProtocolHandler::CreateNewURI(aSpec, aCharset, aBaseURI, aURI); diff --git a/netwerk/build/components.conf b/netwerk/build/components.conf @@ -435,25 +435,6 @@ Classes = [ }, }, { - 'cid': '{64095195-aa8a-4d17-8ec8-c470d85b609b}', - 'contract_ids': ['@mozilla.org/network/protocol;1?name=moz-newtab-wallpaper'], - 'singleton': True, - 'type': 'mozilla::net::MozNewTabWallpaperProtocolHandler', - 'headers': ['mozilla/net/MozNewTabWallpaperProtocolHandler.h'], - 'constructor': 'mozilla::net::MozNewTabWallpaperProtocolHandler::GetSingleton', - 'protocol_config': { - 'scheme': 'moz-newtab-wallpaper', - 'flags': [ - 'URI_STD', - 'URI_IS_UI_RESOURCE', - 'URI_IS_LOCAL_RESOURCE', - 'URI_NORELATIVE', - 'URI_NOAUTH', - ], - 'default_port': -1, - }, - }, - { 'cid': '{1423e739-782c-4081-b5d8-fe6fba68c0ef}', 'contract_ids': ['@mozilla.org/network/protocol;1?name=moz-safe-about'], 'singleton': True, diff --git a/netwerk/ipc/NeckoParent.cpp b/netwerk/ipc/NeckoParent.cpp @@ -13,7 +13,6 @@ #include "mozilla/ipc/IPCStreamUtils.h" #include "mozilla/net/ExtensionProtocolHandler.h" #include "mozilla/net/PageThumbProtocolHandler.h" -#include "mozilla/net/MozNewTabWallpaperProtocolHandler.h" #include "mozilla/net/NeckoParent.h" #include "mozilla/net/HttpChannelParent.h" #include "mozilla/net/CookieServiceParent.h" @@ -802,52 +801,6 @@ mozilla::ipc::IPCResult NeckoParent::RecvGetPageThumbStream( return IPC_OK(); } -mozilla::ipc::IPCResult NeckoParent::RecvGetMozNewTabWallpaperStream( - nsIURI* aURI, const LoadInfoArgs& aLoadInfoArgs, - GetMozNewTabWallpaperStreamResolver&& aResolver) { - // Only the privileged about content process is allowed to access - // things over the moz-newtab-wallpaper protocol. Any other content process - // that tries to send this should have been blocked via the - // ScriptSecurityManager, but if somehow the process has been tricked into - // sending this message, we send IPC_FAIL in order to crash that - // likely-compromised content process. - if (static_cast<ContentParent*>(Manager())->GetRemoteType() != - PRIVILEGEDABOUT_REMOTE_TYPE) { - return IPC_FAIL(this, "Wrong process type"); - } - - RefPtr<net::MozNewTabWallpaperProtocolHandler> ph( - net::MozNewTabWallpaperProtocolHandler::GetSingleton()); - MOZ_ASSERT(ph); - - // Ask the MozNewTabWallpaperProtocolHandler to give us a new input stream for - // this URI. The request comes from a MozNewTabWallpaperProtocolHandler in the - // child process, but is not guaranteed to be a valid moz-newtab-wallpaper - // URI, and not guaranteed to represent a resource that the child should be - // allowed to access. The MozNewTabWallpaperProtocolHandler is responsible for - // validating the request. - nsCOMPtr<nsIInputStream> inputStream; - bool terminateSender = true; - auto inputStreamPromise = ph->NewStream(aURI, &terminateSender); - - if (terminateSender) { - return IPC_FAIL(this, "Malformed moz-newtab-wallpaper request"); - } - - inputStreamPromise->Then( - GetMainThreadSerialEventTarget(), __func__, - [aResolver](const RemoteStreamInfo& aInfo) { aResolver(Some(aInfo)); }, - [aResolver](nsresult aRv) { - // If NewStream failed, we send back an invalid stream to the child so - // it can handle the error. MozPromise rejection is reserved for channel - // errors/disconnects. - (void)NS_WARN_IF(NS_FAILED(aRv)); - aResolver(Nothing()); - }); - - return IPC_OK(); -} - mozilla::ipc::IPCResult NeckoParent::RecvGetPageIconStream( nsIURI* aURI, const LoadInfoArgs& aLoadInfoArgs, GetPageIconStreamResolver&& aResolver) { @@ -900,109 +853,5 @@ mozilla::ipc::IPCResult NeckoParent::RecvGetPageIconStream( #endif } -/* static */ -RefPtr<RemoteStreamPromise> NeckoParent::CreateRemoteStreamForResolvedURI( - nsIURI* aChildURI, const nsACString& aResolvedSpec, - const nsACString& aDefaultMimeType) { - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(XRE_IsParentProcess()); - - nsresult rv; - - nsAutoCString resolvedScheme; - rv = net_ExtractURLScheme(aResolvedSpec, resolvedScheme); - if (NS_FAILED(rv) || !resolvedScheme.EqualsLiteral("file")) { - return RemoteStreamPromise::CreateAndReject(NS_ERROR_UNEXPECTED, __func__); - } - - MOZ_ASSERT(resolvedScheme.EqualsLiteral("file"), - "CreateRemoteStreamForResolvedURI requires file:// URI"); - - nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv); - if (NS_FAILED(rv)) { - return RemoteStreamPromise::CreateAndReject(rv, __func__); - } - - nsCOMPtr<nsIURI> resolvedURI; - rv = ioService->NewURI(aResolvedSpec, nullptr, nullptr, - getter_AddRefs(resolvedURI)); - if (NS_FAILED(rv)) { - return RemoteStreamPromise::CreateAndReject(rv, __func__); - } - - // Load local file resources for internal protocol handlers (moz-page-thumb, - // moz-newtab-wallpaper). resolvedURI must be file:// scheme pointing to the - // profile directory. Callers validate the original URI scheme/host and use - // internal path resolution (PageThumbsStorageService, profile/wallpaper/) - // before calling this method. - nsCOMPtr<nsIChannel> channel; - nsCOMPtr<nsIPrincipal> nullPrincipal = - NullPrincipal::CreateWithoutOriginAttributes(); - rv = NS_NewChannel(getter_AddRefs(channel), resolvedURI, nullPrincipal, - nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL, - nsIContentPolicy::TYPE_IMAGE); - if (NS_FAILED(rv)) { - return RemoteStreamPromise::CreateAndReject(rv, __func__); - } - - auto promiseHolder = MakeUnique<MozPromiseHolder<RemoteStreamPromise>>(); - RefPtr<RemoteStreamPromise> promise = promiseHolder->Ensure(__func__); - - nsCOMPtr<nsIMIMEService> mime = do_GetService("@mozilla.org/mime;1", &rv); - if (NS_FAILED(rv)) { - return RemoteStreamPromise::CreateAndReject(rv, __func__); - } - - nsAutoCString contentType; - rv = mime->GetTypeFromURI(aChildURI, contentType); - if (NS_FAILED(rv)) { - if (!aDefaultMimeType.IsEmpty()) { - contentType = aDefaultMimeType; - } else { - return RemoteStreamPromise::CreateAndReject(rv, __func__); - } - } - - rv = NS_DispatchBackgroundTask( - NS_NewRunnableFunction( - "NeckoParent::CreateRemoteStreamForResolvedURI", - [contentType, channel, holder = std::move(promiseHolder)]() { - nsresult rv; - - nsCOMPtr<nsIFileChannel> fileChannel = - do_QueryInterface(channel, &rv); - if (NS_FAILED(rv)) { - holder->Reject(rv, __func__); - return; - } - - nsCOMPtr<nsIFile> requestedFile; - rv = fileChannel->GetFile(getter_AddRefs(requestedFile)); - if (NS_FAILED(rv)) { - holder->Reject(rv, __func__); - return; - } - - nsCOMPtr<nsIInputStream> inputStream; - rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), - requestedFile, PR_RDONLY, -1); - if (NS_FAILED(rv)) { - holder->Reject(rv, __func__); - return; - } - - RemoteStreamInfo info(inputStream, contentType, -1); - - holder->Resolve(std::move(info), __func__); - }), - NS_DISPATCH_EVENT_MAY_BLOCK); - - if (NS_FAILED(rv)) { - return RemoteStreamPromise::CreateAndReject(rv, __func__); - } - - return promise; -} - } // namespace net } // namespace mozilla diff --git a/netwerk/ipc/NeckoParent.h b/netwerk/ipc/NeckoParent.h @@ -8,7 +8,6 @@ #include "mozilla/BasePrincipal.h" #include "mozilla/net/PNeckoParent.h" #include "mozilla/net/NeckoCommon.h" -#include "mozilla/MozPromise.h" #include "nsIAuthPrompt2.h" #include "nsNetUtil.h" @@ -18,10 +17,6 @@ namespace mozilla { namespace net { -class RemoteStreamInfo; -using RemoteStreamPromise = - mozilla::MozPromise<RemoteStreamInfo, nsresult, false>; - // Used to override channel Private Browsing status if needed. enum PBOverrideStatus { kPBOverride_Unset = 0, @@ -60,14 +55,6 @@ class NeckoParent : public PNeckoParent { return PNeckoParent::RecvPCookieServiceConstructor(aActor); } - /* - * Helper method to create a remote stream from a resolved file URI. - * Shared by PageThumbProtocolHandler and MozNewTabWallpaperProtocolHandler. - */ - static RefPtr<RemoteStreamPromise> CreateRemoteStreamForResolvedURI( - nsIURI* aChildURI, const nsACString& aResolvedSpec, - const nsACString& aDefaultMimeType); - protected: virtual ~NeckoParent() = default; @@ -209,11 +196,6 @@ class NeckoParent : public PNeckoParent { nsIURI* aURI, const LoadInfoArgs& aLoadInfoArgs, GetPageIconStreamResolver&& aResolve); - /* New Tab wallpaper remote resource loading */ - mozilla::ipc::IPCResult RecvGetMozNewTabWallpaperStream( - nsIURI* aURI, const LoadInfoArgs& aLoadInfoArgs, - GetMozNewTabWallpaperStreamResolver&& aResolve); - mozilla::ipc::IPCResult RecvInitSocketProcessBridge( InitSocketProcessBridgeResolver&& aResolver); mozilla::ipc::IPCResult RecvResetSocketProcessBridge(); diff --git a/netwerk/ipc/PNecko.ipdl b/netwerk/ipc/PNecko.ipdl @@ -158,11 +158,6 @@ parent: async GetPageThumbStream(nullable nsIURI uri, LoadInfoArgs loadInfo) returns (RemoteStreamInfo? info); async GetPageIconStream(nullable nsIURI uri, LoadInfoArgs loadInfo) returns (RemoteStreamInfo? info); - /** - * New Tab wallpaper remote resource loading - */ - async GetMozNewTabWallpaperStream(nullable nsIURI uri, LoadInfoArgs loadInfo) returns (RemoteStreamInfo? info); - child: async SpeculativeConnectRequest(); diff --git a/netwerk/protocol/res/MozNewTabWallpaperProtocolHandler.cpp b/netwerk/protocol/res/MozNewTabWallpaperProtocolHandler.cpp @@ -1,195 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "MozNewTabWallpaperProtocolHandler.h" - -#include "mozilla/ClearOnShutdown.h" -#include "mozilla/net/NeckoParent.h" -#include "nsContentUtils.h" -#include "nsIFile.h" -#include "nsIFileChannel.h" -#include "nsIFileURL.h" -#include "nsIMIMEService.h" -#include "nsDirectoryServiceUtils.h" -#include "nsAppDirectoryServiceDefs.h" -#include "nsNetUtil.h" -#include "nsURLHelper.h" -#include "prio.h" -#include "SimpleChannel.h" - -#define NEWTAB_WALLPAPER_SCHEME "moz-newtab-wallpaper" - -namespace mozilla { -namespace net { - -StaticRefPtr<MozNewTabWallpaperProtocolHandler> - MozNewTabWallpaperProtocolHandler::sSingleton; - -NS_IMPL_QUERY_INTERFACE(MozNewTabWallpaperProtocolHandler, - nsISubstitutingProtocolHandler, nsIProtocolHandler, - nsISupportsWeakReference) -NS_IMPL_ADDREF_INHERITED(MozNewTabWallpaperProtocolHandler, - SubstitutingProtocolHandler) -NS_IMPL_RELEASE_INHERITED(MozNewTabWallpaperProtocolHandler, - SubstitutingProtocolHandler) - -already_AddRefed<MozNewTabWallpaperProtocolHandler> -MozNewTabWallpaperProtocolHandler::GetSingleton() { - if (!sSingleton) { - sSingleton = new MozNewTabWallpaperProtocolHandler(); - ClearOnShutdown(&sSingleton); - } - - return do_AddRef(sSingleton); -} - -// A moz-newtab-wallpaper URI is only loadable by chrome pages in the parent -// process, or privileged content running in the privileged about content -// process. -MozNewTabWallpaperProtocolHandler::MozNewTabWallpaperProtocolHandler() - : SubstitutingProtocolHandler(NEWTAB_WALLPAPER_SCHEME) {} - -RefPtr<RemoteStreamPromise> MozNewTabWallpaperProtocolHandler::NewStream( - nsIURI* aChildURI, bool* aTerminateSender) { - MOZ_ASSERT(!IsNeckoChild()); - MOZ_ASSERT(NS_IsMainThread()); - - if (!aChildURI || !aTerminateSender) { - return RemoteStreamPromise::CreateAndReject(NS_ERROR_INVALID_ARG, __func__); - } - - *aTerminateSender = true; - nsresult rv; - - bool isWallpaperScheme = false; - if (NS_FAILED( - aChildURI->SchemeIs(NEWTAB_WALLPAPER_SCHEME, &isWallpaperScheme)) || - !isWallpaperScheme) { - return RemoteStreamPromise::CreateAndReject(NS_ERROR_UNKNOWN_PROTOCOL, - __func__); - } - - nsAutoCString host; - if (NS_FAILED(aChildURI->GetAsciiHost(host)) || host.IsEmpty()) { - return RemoteStreamPromise::CreateAndReject(NS_ERROR_UNEXPECTED, __func__); - } - - *aTerminateSender = false; - - nsAutoCString resolvedSpec; - rv = ResolveURI(aChildURI, resolvedSpec); - if (NS_FAILED(rv)) { - return RemoteStreamPromise::CreateAndReject(rv, __func__); - } - - return mozilla::net::NeckoParent::CreateRemoteStreamForResolvedURI( - aChildURI, resolvedSpec, "image/jpeg"_ns); -} - -bool MozNewTabWallpaperProtocolHandler::ResolveSpecialCases( - const nsACString& aHost, const nsACString& aPath, - const nsACString& aPathname, nsACString& aResult) { - if (aHost.IsEmpty()) { - return false; - } - - if (IsNeckoChild()) { - // Child process: return placeholder file:// URI for - // SubstitutingProtocolHandler. SubstituteChannel will replace with a remote - // channel that proxies the load to the parent process. - aResult.Assign("file://"); - aResult.Append(aHost); - return true; - } else { - // Parent process: resolve to profile/wallpaper/{host} directory. - nsCOMPtr<nsIFile> file; - nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, - getter_AddRefs(file)); - if (NS_FAILED(rv)) { - return false; - } - - rv = file->AppendNative("wallpaper"_ns); - if (NS_FAILED(rv)) { - return false; - } - - rv = file->AppendNative(nsCString(aHost)); - if (NS_FAILED(rv)) { - return false; - } - - nsCOMPtr<nsIURI> uri; - rv = NS_NewFileURI(getter_AddRefs(uri), file); - if (NS_FAILED(rv)) { - return false; - } - - return NS_SUCCEEDED(uri->GetSpec(aResult)); - } -} - -nsresult MozNewTabWallpaperProtocolHandler::SubstituteChannel( - nsIURI* aURI, nsILoadInfo* aLoadInfo, nsIChannel** aRetVal) { - // Check if URI resolves to a file URI. - nsAutoCString resolvedSpec; - MOZ_TRY(ResolveURI(aURI, resolvedSpec)); - - nsAutoCString scheme; - MOZ_TRY(net_ExtractURLScheme(resolvedSpec, scheme)); - - if (!scheme.EqualsLiteral("file")) { - NS_WARNING("moz-newtab-wallpaper URIs should only resolve to file URIs."); - return NS_ERROR_NO_INTERFACE; - } - - if (IsNeckoChild()) { - MOZ_TRY(SubstituteRemoteChannel(aURI, aLoadInfo, aRetVal)); - } - - return NS_OK; -} - -Result<Ok, nsresult> MozNewTabWallpaperProtocolHandler::SubstituteRemoteChannel( - nsIURI* aURI, nsILoadInfo* aLoadInfo, nsIChannel** aRetVal) { - MOZ_ASSERT(IsNeckoChild()); - MOZ_TRY(aURI ? NS_OK : NS_ERROR_INVALID_ARG); - MOZ_TRY(aLoadInfo ? NS_OK : NS_ERROR_INVALID_ARG); - -#ifdef DEBUG - nsAutoCString resolvedSpec; - MOZ_TRY(ResolveURI(aURI, resolvedSpec)); - - nsAutoCString scheme; - MOZ_TRY(net_ExtractURLScheme(resolvedSpec, scheme)); - - MOZ_ASSERT(scheme.EqualsLiteral("file")); -#endif /* DEBUG */ - - RefPtr<RemoteStreamGetter> streamGetter = - new RemoteStreamGetter(aURI, aLoadInfo); - - NewSimpleChannel(aURI, aLoadInfo, streamGetter, aRetVal); - return Ok(); -} - -// static -void MozNewTabWallpaperProtocolHandler::NewSimpleChannel( - nsIURI* aURI, nsILoadInfo* aLoadinfo, RemoteStreamGetter* aStreamGetter, - nsIChannel** aRetVal) { - nsCOMPtr<nsIChannel> channel = NS_NewSimpleChannel( - aURI, aLoadinfo, aStreamGetter, - [](nsIStreamListener* listener, nsIChannel* simpleChannel, - RemoteStreamGetter* getter) -> RequestOrReason { - return getter->GetAsync(listener, simpleChannel, - &NeckoChild::SendGetMozNewTabWallpaperStream); - }); - - channel.swap(*aRetVal); -} - -} // namespace net -} // namespace mozilla diff --git a/netwerk/protocol/res/MozNewTabWallpaperProtocolHandler.h b/netwerk/protocol/res/MozNewTabWallpaperProtocolHandler.h @@ -1,91 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef MozNewTabWallpaperProtocolHandler_h___ -#define MozNewTabWallpaperProtocolHandler_h___ - -#include "mozilla/Result.h" -#include "mozilla/MozPromise.h" -#include "mozilla/net/RemoteStreamGetter.h" -#include "SubstitutingProtocolHandler.h" -#include "nsIInputStream.h" -#include "nsWeakReference.h" - -namespace mozilla { -namespace net { - -class RemoteStreamGetter; - -class MozNewTabWallpaperProtocolHandler final - : public nsISubstitutingProtocolHandler, - public SubstitutingProtocolHandler, - public nsSupportsWeakReference { - public: - NS_DECL_ISUPPORTS_INHERITED - NS_FORWARD_NSIPROTOCOLHANDLER(SubstitutingProtocolHandler::) - NS_FORWARD_NSISUBSTITUTINGPROTOCOLHANDLER(SubstitutingProtocolHandler::) - - static already_AddRefed<MozNewTabWallpaperProtocolHandler> GetSingleton(); - - /** - * Obtains an input stream for a user-uploaded New Tab wallpaper. - * - * @param aChildURI moz-newtab-wallpaper URI from child process - * @param aTerminateSender set to true if URI is invalid (terminates child) - * @return RemoteStreamPromise resolving to RemoteStreamInfo on success or - * nsresult on failure - */ - RefPtr<RemoteStreamPromise> NewStream(nsIURI* aChildURI, - bool* aTerminateSender); - - protected: - ~MozNewTabWallpaperProtocolHandler() = default; - - private: - explicit MozNewTabWallpaperProtocolHandler(); - - [[nodiscard]] bool ResolveSpecialCases(const nsACString& aHost, - const nsACString& aPath, - const nsACString& aPathname, - nsACString& aResult) override; - - /** - * Substitutes the channel with a remote channel in child process. - * - * @param aURI the moz-newtab-wallpaper URI - * @param aLoadInfo the loadinfo for the request - * @param aRetVal in/out channel param for the substituted channel - * @return NS_OK on success or NS_ERROR_NO_INTERFACE if URI doesn't - * resolve to file:// - */ - [[nodiscard]] virtual nsresult SubstituteChannel( - nsIURI* aURI, nsILoadInfo* aLoadInfo, nsIChannel** aRetVal) override; - - /** - * Replaces the channel with one that proxies the load to parent process. - * - * @param aURI the moz-newtab-wallpaper URI - * @param aLoadInfo the loadinfo for the request - * @param aRetVal in/out channel param for the substituted remote channel - * @return NS_OK if successful, otherwise an error - */ - Result<Ok, nsresult> SubstituteRemoteChannel(nsIURI* aURI, - nsILoadInfo* aLoadInfo, - nsIChannel** aRetVal); - - // To allow parent IPDL actors to invoke methods on this handler when - // handling moz-newtab-wallpaper requests from the child. - static StaticRefPtr<MozNewTabWallpaperProtocolHandler> sSingleton; - - // Gets a SimpleChannel that wraps the provided channel. - static void NewSimpleChannel(nsIURI* aURI, nsILoadInfo* aLoadinfo, - RemoteStreamGetter* aStreamGetter, - nsIChannel** aRetVal); -}; - -} // namespace net -} // namespace mozilla - -#endif /* MozNewTabWallpaperProtocolHandler_h___ */ diff --git a/netwerk/protocol/res/PageThumbProtocolHandler.cpp b/netwerk/protocol/res/PageThumbProtocolHandler.cpp @@ -11,7 +11,6 @@ #include "mozilla/ipc/URIParams.h" #include "mozilla/ipc/URIUtils.h" #include "mozilla/net/NeckoChild.h" -#include "mozilla/net/NeckoParent.h" #include "mozilla/RefPtr.h" #include "mozilla/ResultExtensions.h" #include "mozilla/Try.h" @@ -120,8 +119,89 @@ RefPtr<RemoteStreamPromise> PageThumbProtocolHandler::NewStream( return RemoteStreamPromise::CreateAndReject(rv, __func__); } - return mozilla::net::NeckoParent::CreateRemoteStreamForResolvedURI( - aChildURI, resolvedSpec, ""_ns); + nsAutoCString resolvedScheme; + rv = net_ExtractURLScheme(resolvedSpec, resolvedScheme); + if (NS_FAILED(rv) || !resolvedScheme.EqualsLiteral("file")) { + return RemoteStreamPromise::CreateAndReject(NS_ERROR_UNEXPECTED, __func__); + } + + nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv); + if (NS_FAILED(rv)) { + return RemoteStreamPromise::CreateAndReject(rv, __func__); + } + + nsCOMPtr<nsIURI> resolvedURI; + rv = ioService->NewURI(resolvedSpec, nullptr, nullptr, + getter_AddRefs(resolvedURI)); + if (NS_FAILED(rv)) { + return RemoteStreamPromise::CreateAndReject(rv, __func__); + } + + // We use the system principal to get a file channel for the request, + // but only after we've checked (above) that the child URI is of + // moz-page-thumb scheme and that the URI host matches PAGE_THUMB_HOST. + nsCOMPtr<nsIChannel> channel; + rv = NS_NewChannel(getter_AddRefs(channel), resolvedURI, + nsContentUtils::GetSystemPrincipal(), + nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL, + nsIContentPolicy::TYPE_OTHER); + if (NS_FAILED(rv)) { + return RemoteStreamPromise::CreateAndReject(rv, __func__); + } + + auto promiseHolder = MakeUnique<MozPromiseHolder<RemoteStreamPromise>>(); + RefPtr<RemoteStreamPromise> promise = promiseHolder->Ensure(__func__); + + nsCOMPtr<nsIMIMEService> mime = do_GetService("@mozilla.org/mime;1", &rv); + if (NS_FAILED(rv)) { + return RemoteStreamPromise::CreateAndReject(rv, __func__); + } + + nsAutoCString contentType; + rv = mime->GetTypeFromURI(aChildURI, contentType); + if (NS_FAILED(rv)) { + return RemoteStreamPromise::CreateAndReject(rv, __func__); + } + + rv = NS_DispatchBackgroundTask( + NS_NewRunnableFunction( + "PageThumbProtocolHandler::NewStream", + [contentType, channel, holder = std::move(promiseHolder)]() { + nsresult rv; + + nsCOMPtr<nsIFileChannel> fileChannel = + do_QueryInterface(channel, &rv); + if (NS_FAILED(rv)) { + holder->Reject(rv, __func__); + return; + } + + nsCOMPtr<nsIFile> requestedFile; + rv = fileChannel->GetFile(getter_AddRefs(requestedFile)); + if (NS_FAILED(rv)) { + holder->Reject(rv, __func__); + return; + } + + nsCOMPtr<nsIInputStream> inputStream; + rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), + requestedFile, PR_RDONLY, -1); + if (NS_FAILED(rv)) { + holder->Reject(rv, __func__); + return; + } + + RemoteStreamInfo info(inputStream, contentType, -1); + + holder->Resolve(std::move(info), __func__); + }), + NS_DISPATCH_EVENT_MAY_BLOCK); + + if (NS_FAILED(rv)) { + return RemoteStreamPromise::CreateAndReject(rv, __func__); + } + + return promise; } bool PageThumbProtocolHandler::ResolveSpecialCases(const nsACString& aHost, diff --git a/netwerk/protocol/res/moz.build b/netwerk/protocol/res/moz.build @@ -13,7 +13,6 @@ XPIDL_MODULE = "necko_res" EXPORTS.mozilla.net += [ "ExtensionProtocolHandler.h", - "MozNewTabWallpaperProtocolHandler.h", "MozSrcProtocolHandler.h", "PageThumbProtocolHandler.h", "RemoteStreamGetter.h", @@ -28,7 +27,6 @@ EXPORTS += [ UNIFIED_SOURCES += [ "ExtensionProtocolHandler.cpp", - "MozNewTabWallpaperProtocolHandler.cpp", "MozSrcProtocolHandler.cpp", "nsResProtocolHandler.cpp", "PageThumbProtocolHandler.cpp", diff --git a/netwerk/test/unit/test_wallpaper_protocol.js b/netwerk/test/unit/test_wallpaper_protocol.js @@ -1,38 +0,0 @@ -"use strict"; - -// Need profile so that the protocol handler can resolve the path to the underlying file -do_get_profile(); - -function run_test() { - // Check the protocol handler implements the correct interfaces - let handler = Services.io.getProtocolHandler("moz-newtab-wallpaper"); - ok( - handler instanceof Ci.nsIProtocolHandler, - "moz-newtab-wallpaper handler provides nsIProtocolHandler interface" - ); - ok( - handler instanceof Ci.nsISubstitutingProtocolHandler, - "moz-newtab-wallpaper handler provides nsISubstitutingProtocolHandler interface" - ); - - // Create a dummy loadinfo which we can hand to newChannel - let dummyURI = Services.io.newURI("https://www.example.com/"); - let dummyChannel = NetUtil.newChannel({ - uri: dummyURI, - loadUsingSystemPrincipal: true, - }); - let dummyLoadInfo = dummyChannel.loadInfo; - - // Test that empty host fails - let emptyHost = Services.io.newURI("moz-newtab-wallpaper://"); - Assert.throws( - () => handler.newChannel(emptyHost, dummyLoadInfo), - /NS_ERROR/i, - "moz-newtab-wallpaper URI with empty host must not resolve" - ); - - // Test that valid host creates a channel (even if file doesn't exist yet) - let validURI = Services.io.newURI("moz-newtab-wallpaper://wallpaper.jpg"); - let channel = handler.newChannel(validURI, dummyLoadInfo); - ok(channel, "moz-newtab-wallpaper URI with valid host creates a channel"); -} diff --git a/netwerk/test/unit/xpcshell.toml b/netwerk/test/unit/xpcshell.toml @@ -1586,8 +1586,6 @@ run-sequentially = ["true"] # node server exceptions dont replay well ["test_verify_traffic.js"] -["test_wallpaper_protocol.js"] - ["test_websocket_500k.js"] skip-if = [ "verify",