tor-browser

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

commit 0b01217aa3c9c6bc7918e9fe9df22022a6c2fbd6
parent c32abaee2e8896ecd62dd065ac6c485520d76d1f
Author: agoloman <agoloman@mozilla.com>
Date:   Wed, 15 Oct 2025 19:05:02 +0300

Revert "Bug 1927289: More strongly enforce WebGL context continuity. r=ahale" for causing bc failures @browser_canvas_randomization.js.

This reverts commit a7b2b6d5206d454b856c570eda5691a02f313b01.

Diffstat:
Mdom/canvas/ClientWebGLContext.cpp | 466+++++++++++++++++++++++++++++--------------------------------------------------
1 file changed, 170 insertions(+), 296 deletions(-)

diff --git a/dom/canvas/ClientWebGLContext.cpp b/dom/canvas/ClientWebGLContext.cpp @@ -276,9 +276,8 @@ void ClientWebGLContext::OnContextLoss( const webgl::ContextLossReason reason) const { JsWarning("WebGL context was lost."); - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (notLost) { - for (const auto& ext : notLost->extensions) { + if (mNotLost) { + for (const auto& ext : mNotLost->extensions) { if (!ext) continue; ext->mContext = nullptr; // Detach. } @@ -422,12 +421,14 @@ template <typename MethodT, typename... Args> void ClientWebGLContext::Run_WithDestArgTypes( std::optional<JS::AutoCheckCannotGC>&& noGc, const MethodT method, const size_t id, const Args&... args) const { + const auto notLost = + mNotLost; // Hold a strong-ref to prevent LoseContext=>UAF. + // `AutoCheckCannotGC` must be reset after the GC data is done being used but // *before* the `notLost` destructor runs, since the latter can GC. const auto cleanup = MakeScopeExit([&]() { noGc.reset(); }); - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { + if (IsContextLost()) { return; } @@ -490,18 +491,12 @@ webgl::SwapChainOptions ClientWebGLContext::PrepareAsyncSwapChainOptions( // Currently remote texture ids should only be set internally. MOZ_ASSERT(!options.remoteTextureOwnerId.IsValid() && !options.remoteTextureId.IsValid()); - - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return options; - } - // Async present only works when out-of-process. It is not supported in WebVR. // Allow it if it is either forced or if the pref is set. if (fb || webvr) { return options; } - if (notLost->inProcess && + if (!IsContextLost() && !mNotLost->inProcess && (options.forceAsyncPresent || StaticPrefs::webgl_out_of_process_async_present())) { if (!mRemoteTextureOwnerId) { @@ -548,18 +543,15 @@ void ClientWebGLContext::EndOfFrame() { Maybe<layers::SurfaceDescriptor> ClientWebGLContext::GetFrontBuffer( WebGLFramebufferJS* const fb, bool vr) { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return {}; - } const FuncScope funcScope(*this, "<GetFrontBuffer>"); + if (IsContextLost()) return {}; - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { return inProcess->GetFrontBuffer(fb ? fb->mId : 0, vr); } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); // Always synchronously get the front buffer if not using a remote texture. @@ -634,23 +626,18 @@ void ClientWebGLContext::ClearVRSwapChain() { Run<RPROC(ClearVRSwapChain)>(); } bool ClientWebGLContext::UpdateWebRenderCanvasData( nsDisplayListBuilder* aBuilder, WebRenderCanvasData* aCanvasData) { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return true; - } - CanvasRenderer* renderer = aCanvasData->GetCanvasRenderer(); - if (!mResetLayer && renderer) { + if (!IsContextLost() && !mResetLayer && renderer) { return true; } const auto& size = DrawingBufferSize(); - if (!renderer && notLost->mCanvasRenderer && - notLost->mCanvasRenderer->GetSize() == gfx::IntSize(size.x, size.y) && - aCanvasData->SetCanvasRenderer(notLost->mCanvasRenderer)) { - notLost->mCanvasRenderer->SetDirty(); + if (!IsContextLost() && !renderer && mNotLost->mCanvasRenderer && + mNotLost->mCanvasRenderer->GetSize() == gfx::IntSize(size.x, size.y) && + aCanvasData->SetCanvasRenderer(mNotLost->mCanvasRenderer)) { + mNotLost->mCanvasRenderer->SetDirty(); mResetLayer = false; return true; } @@ -662,7 +649,7 @@ bool ClientWebGLContext::UpdateWebRenderCanvasData( return false; } - notLost->mCanvasRenderer = renderer; + mNotLost->mCanvasRenderer = renderer; MOZ_ASSERT(renderer); mResetLayer = false; @@ -771,17 +758,12 @@ void ClientWebGLContext::SetUnpackColorSpace( void ClientWebGLContext::GetContextAttributes( dom::Nullable<dom::WebGLContextAttributes>& retval) { retval.SetNull(); - - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } - const FuncScope funcScope(*this, "getContextAttributes"); + if (IsContextLost()) return; dom::WebGLContextAttributes& result = retval.SetValue(); - const auto& options = notLost->info.options; + const auto& options = mNotLost->info.options; result.mAlpha.Construct(options.alpha); result.mDepth = options.depth; @@ -799,17 +781,12 @@ void ClientWebGLContext::GetContextAttributes( NS_IMETHODIMP ClientWebGLContext::SetDimensions(const int32_t signedWidth, const int32_t signedHeight) { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return NS_ERROR_FAILURE; - } - const FuncScope funcScope(*this, "<SetDimensions>"); MOZ_ASSERT(mInitialOptions); if (mLossStatus != webgl::LossStatus::Ready) { // Attempted resize of a lost context. - return NS_ERROR_FAILURE; + return NS_OK; } uvec2 size = {static_cast<uint32_t>(signedWidth), @@ -825,19 +802,29 @@ ClientWebGLContext::SetDimensions(const int32_t signedWidth, mResetLayer = true; // Always treat this as resize. - auto& state = State(); + if (mNotLost) { + auto& state = State(); - auto curSize = prevRequestedSize; - if (state.mDrawingBufferSize) { - curSize = *state.mDrawingBufferSize; + auto curSize = prevRequestedSize; + if (state.mDrawingBufferSize) { + curSize = *state.mDrawingBufferSize; + } + if (size == curSize) return NS_OK; // MUST skip no-op resize + + state.mDrawingBufferSize = Nothing(); + Run<RPROC(Resize)>(size); + + UpdateCanvasParameters(); + MarkCanvasDirty(); + return NS_OK; } - if (size == curSize) return NS_OK; // MUST skip no-op resize - state.mDrawingBufferSize = Nothing(); - Run<RPROC(Resize)>(size); + // - + // Context (re-)creation - UpdateCanvasParameters(); - MarkCanvasDirty(); + if (!CreateHostContext(size)) { + return NS_ERROR_FAILURE; + } return NS_OK; } @@ -860,10 +847,8 @@ static bool IsWebglOutOfProcessEnabled() { } bool ClientWebGLContext::CreateHostContext(const uvec2& requestedSize) { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return false; - } + const auto pNotLost = MakeRefPtr<webgl::NotLostData>(*this); + auto& notLost = *pNotLost; auto res = [&]() -> Result<Ok, std::string> { auto options = *mInitialOptions; @@ -903,8 +888,8 @@ bool ClientWebGLContext::CreateHostContext(const uvec2& requestedSize) { } if (!useOop) { - notLost->inProcess = - HostWebGLContext::Create({this, nullptr}, initDesc, &notLost->info); + notLost.inProcess = + HostWebGLContext::Create({this, nullptr}, initDesc, &notLost.info); return Ok(); } @@ -931,11 +916,11 @@ bool ClientWebGLContext::CreateHostContext(const uvec2& requestedSize) { mFwdTransactionTracker = nullptr; } - if (!outOfProcess->SendInitialize(initDesc, &notLost->info)) { + if (!outOfProcess->SendInitialize(initDesc, &notLost.info)) { return Err("WebGL actor Initialize failed"); } - notLost->outOfProcess = outOfProcess; + notLost.outOfProcess = outOfProcess; reporter.SetSuccessful(); return Ok(); }(); @@ -946,12 +931,13 @@ bool ClientWebGLContext::CreateHostContext(const uvec2& requestedSize) { " (about:config override available:" " webgl.disable-fail-if-major-performance-caveat)"; } - notLost->info.error = str; + notLost.info.error = str; } - if (!notLost->info.error->empty()) { - ThrowEvent_WebGLContextCreationError(notLost->info.error); + if (!notLost.info.error->empty()) { + ThrowEvent_WebGLContextCreationError(notLost.info.error); return false; } + mNotLost = pNotLost; UpdateCanvasParameters(); MarkCanvasDirty(); @@ -1025,10 +1011,9 @@ std::unordered_map<GLenum, bool> webgl::MakeIsEnabledMap(const bool webgl2) { // ------- uvec2 ClientWebGLContext::DrawingBufferSize() { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return {}; - } + if (IsContextLost()) return {}; + RefPtr<webgl::NotLostData> notLost( + mNotLost); // Hold a strong-ref to prevent LoseContext=>UAF. auto& state = State(); auto& size = state.mDrawingBufferSize; @@ -1049,19 +1034,14 @@ uvec2 ClientWebGLContext::DrawingBufferSize() { } void ClientWebGLContext::OnMemoryPressure() { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } + if (IsContextLost()) return; - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { return inProcess->OnMemoryPressure(); } - const auto& child = notLost->outOfProcess; - if (child) { - (void)child->SendOnMemoryPressure(); - } + const auto& child = mNotLost->outOfProcess; + (void)child->SendOnMemoryPressure(); } NS_IMETHODIMP @@ -1124,10 +1104,9 @@ void ClientWebGLContext::DidRefresh() { Run<RPROC(DidRefresh)>(); } already_AddRefed<gfx::SourceSurface> ClientWebGLContext::GetSurfaceSnapshot( gfxAlphaType* const out_alphaType) { const FuncScope funcScope(*this, "<GetSurfaceSnapshot>"); - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return nullptr; - } + if (IsContextLost()) return nullptr; + RefPtr<webgl::NotLostData> notLost( + mNotLost); // Hold a strong-ref to prevent LoseContext=>UAF. auto ret = BackBufferSnapshot(); if (!ret) return nullptr; @@ -1174,10 +1153,9 @@ mozilla::ipc::IProtocol* ClientWebGLContext::SupportsSnapshotExternalCanvas() RefPtr<gfx::SourceSurface> ClientWebGLContext::GetFrontBufferSnapshot( const bool requireAlphaPremult) { const FuncScope funcScope(*this, "<GetSurfaceSnapshot>"); - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return nullptr; - } + if (IsContextLost()) return nullptr; + RefPtr<webgl::NotLostData> notLost( + mNotLost); // Hold a strong-ref to prevent LoseContext=>UAF. const auto& options = notLost->info.options; @@ -1192,7 +1170,7 @@ RefPtr<gfx::SourceSurface> ClientWebGLContext::GetFrontBufferSnapshot( /*zero=*/true)); }; - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { const auto maybeSize = inProcess->FrontBufferSnapshotInto({}); if (!maybeSize) return nullptr; @@ -1232,7 +1210,7 @@ RefPtr<gfx::SourceSurface> ClientWebGLContext::GetFrontBufferSnapshot( } return surf; } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); webgl::FrontBufferSnapshotIpc res; if (!child->SendGetFrontBufferSnapshot(&res)) { @@ -1278,10 +1256,9 @@ RefPtr<gfx::SourceSurface> ClientWebGLContext::GetFrontBufferSnapshot( } RefPtr<gfx::DataSourceSurface> ClientWebGLContext::BackBufferSnapshot() { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return nullptr; - } + if (IsContextLost()) return nullptr; + RefPtr<webgl::NotLostData> notLost( + mNotLost); // Hold a strong-ref to prevent LoseContext=>UAF. const auto& options = notLost->info.options; const auto& state = State(); @@ -1356,11 +1333,6 @@ RefPtr<gfx::DataSourceSurface> ClientWebGLContext::BackBufferSnapshot() { UniquePtr<uint8_t[]> ClientWebGLContext::GetImageBuffer( mozilla::CanvasUtils::ImageExtraction aExtractionBehavior, int32_t* out_format, gfx::IntSize* out_imageSize) { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return nullptr; - } - *out_format = 0; *out_imageSize = {}; @@ -1371,7 +1343,7 @@ UniquePtr<uint8_t[]> ClientWebGLContext::GetImageBuffer( RefPtr<gfx::DataSourceSurface> dataSurface = snapshot->GetDataSurface(); - const auto& premultAlpha = notLost->info.options.premultipliedAlpha; + const auto& premultAlpha = mNotLost->info.options.premultipliedAlpha; *out_imageSize = dataSurface->GetSize(); if (aExtractionBehavior == CanvasUtils::ImageExtraction::Randomize) { @@ -1388,18 +1360,13 @@ ClientWebGLContext::GetInputStream( const char* mimeType, const nsAString& encoderOptions, mozilla::CanvasUtils::ImageExtraction extractionBehavior, const nsACString& randomizationKey, nsIInputStream** out_stream) { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return NS_ERROR_FAILURE; - } - // Use GetSurfaceSnapshot() to make sure that appropriate y-flip gets applied gfxAlphaType any; RefPtr<gfx::SourceSurface> snapshot = GetSurfaceSnapshot(&any); if (!snapshot) return NS_ERROR_FAILURE; RefPtr<gfx::DataSourceSurface> dataSurface = snapshot->GetDataSurface(); - const auto& premultAlpha = notLost->info.options.premultipliedAlpha; + const auto& premultAlpha = mNotLost->info.options.premultipliedAlpha; if (ShouldResistFingerprinting(RFPTarget::CanvasRandomization)) { return gfxUtils::GetInputStreamWithRandomNoise( @@ -1449,24 +1416,21 @@ ClientWebGLContext::CreateOpaqueFramebuffer( auto ret = AsRefPtr(new WebGLFramebufferJS(*this, true)); - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return ret.forget(); - } - - const auto& inProcess = notLost->inProcess; - if (inProcess) { - if (!inProcess->CreateOpaqueFramebuffer(ret->mId, options)) { - ret = nullptr; + if (mNotLost) { + const auto& inProcess = mNotLost->inProcess; + if (inProcess) { + if (!inProcess->CreateOpaqueFramebuffer(ret->mId, options)) { + ret = nullptr; + } + return ret.forget(); } - return ret.forget(); + const auto& child = mNotLost->outOfProcess; + child->FlushPendingCmds(); + bool ok = false; + if (!child->SendCreateOpaqueFramebuffer(ret->mId, options, &ok)) + return nullptr; + if (!ok) return nullptr; } - const auto& child = notLost->outOfProcess; - child->FlushPendingCmds(); - bool ok = false; - if (!child->SendCreateOpaqueFramebuffer(ret->mId, options, &ok)) - return nullptr; - if (!ok) return nullptr; return ret.forget(); } @@ -1979,12 +1943,9 @@ bool ClientWebGLContext::IsVertexArray( void ClientWebGLContext::SetEnabledI(const GLenum cap, const Maybe<GLuint> i, const bool val) const { const FuncScope funcScope(*this, "enable/disable"); - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } + if (IsContextLost()) return; - auto& map = notLost->state.mIsEnabledMap; + auto& map = mNotLost->state.mIsEnabledMap; auto slot = MaybeFind(map, cap); if (i && cap != LOCAL_GL_BLEND) { slot = nullptr; @@ -2003,12 +1964,9 @@ void ClientWebGLContext::SetEnabledI(const GLenum cap, const Maybe<GLuint> i, bool ClientWebGLContext::IsEnabled(const GLenum cap) const { const FuncScope funcScope(*this, "isEnabled"); - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return false; - } + if (IsContextLost()) return false; - const auto& map = notLost->state.mIsEnabledMap; + const auto& map = mNotLost->state.mIsEnabledMap; const auto slot = MaybeFind(map, cap); if (!slot) { EnqueueError_ArgEnum("cap", cap); @@ -2029,10 +1987,9 @@ void ClientWebGLContext::GetInternalformatParameter( JS::MutableHandle<JS::Value> retval, ErrorResult& rv) { const FuncScope funcScope(*this, "getInternalformatParameter"); retval.set(JS::NullValue()); - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } + const auto notLost = + mNotLost; // Hold a strong-ref to prevent LoseContext=>UAF. + if (IsContextLost()) return; const auto& inProcessContext = notLost->inProcess; Maybe<std::vector<int32_t>> maybe; @@ -2077,17 +2034,14 @@ bool ToJSValueOrNull(JSContext* const cx, const RefPtr<T>& ptr, } Maybe<double> ClientWebGLContext::GetNumber(const GLenum pname) { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return Nothing(); - } + MOZ_ASSERT(!IsContextLost()); - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { return inProcess->GetNumber(pname); } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); Maybe<double> ret; @@ -2098,17 +2052,14 @@ Maybe<double> ClientWebGLContext::GetNumber(const GLenum pname) { } Maybe<std::string> ClientWebGLContext::GetString(const GLenum pname) { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return Nothing(); - } + MOZ_ASSERT(!IsContextLost()); - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { return inProcess->GetString(pname); } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); Maybe<std::string> ret; @@ -2122,11 +2073,6 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname, JS::MutableHandle<JS::Value> retval, ErrorResult& rv, const bool debug) { retval.set(JS::NullValue()); - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } - const FuncScope funcScope(*this, "getParameter"); if (IsContextLost()) return; const auto& limits = Limits(); @@ -2528,8 +2474,8 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname, if (maybe) { auto str = std::string{}; if (pname == dom::MOZ_debug_Binding::WSI_INFO) { - const auto& outOfProcess = notLost->outOfProcess; - const auto& inProcess = notLost->inProcess; + const auto& outOfProcess = mNotLost->outOfProcess; + const auto& inProcess = mNotLost->inProcess; str += PrintfStdString("outOfProcess: %s\ninProcess: %s\n", ToChars(bool(outOfProcess)), ToChars(bool(inProcess))); @@ -2595,17 +2541,14 @@ void ClientWebGLContext::GetBufferParameter( JSContext* cx, GLenum target, GLenum pname, JS::MutableHandle<JS::Value> retval) const { retval.set(JS::NullValue()); - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } + if (IsContextLost()) return; const auto maybe = [&]() { - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { return inProcess->GetBufferParameter(target, pname); } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); Maybe<double> ret; if (!child->SendGetBufferParameter(target, pname, &ret)) { @@ -2637,12 +2580,8 @@ void ClientWebGLContext::GetFramebufferAttachmentParameter( const GLenum pname, JS::MutableHandle<JS::Value> retval, ErrorResult& rv) const { retval.set(JS::NullValue()); - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } - const FuncScope funcScope(*this, "getFramebufferAttachmentParameter"); + if (IsContextLost()) return; const auto& state = State(); @@ -2658,12 +2597,12 @@ void ClientWebGLContext::GetFramebufferAttachmentParameter( const auto fnGet = [&](const GLenum pname) { const auto fbId = fb ? fb->mId : 0; - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { return inProcess->GetFramebufferAttachmentParameter(fbId, attachment, pname); } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); Maybe<double> ret; if (!child->SendGetFramebufferAttachmentParameter(fbId, attachment, pname, @@ -2722,12 +2661,8 @@ void ClientWebGLContext::GetRenderbufferParameter( JSContext* cx, GLenum target, GLenum pname, JS::MutableHandle<JS::Value> retval) const { retval.set(JS::NullValue()); - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } - const FuncScope funcScope(*this, "getRenderbufferParameter"); + if (IsContextLost()) return; if (target != LOCAL_GL_RENDERBUFFER) { EnqueueError_ArgEnum("target", target); @@ -2738,11 +2673,11 @@ void ClientWebGLContext::GetRenderbufferParameter( const auto& rb = state.mBoundRb; const auto rbId = rb ? rb->mId : 0; const auto maybe = [&]() { - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { return inProcess->GetRenderbufferParameter(rbId, pname); } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); Maybe<double> ret; if (!child->SendGetRenderbufferParameter(rbId, pname, &ret)) { @@ -2759,12 +2694,8 @@ void ClientWebGLContext::GetIndexedParameter( JSContext* cx, GLenum target, GLuint index, JS::MutableHandle<JS::Value> retval, ErrorResult& rv) const { retval.set(JS::NullValue()); - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } - const FuncScope funcScope(*this, "getIndexedParameter"); + if (IsContextLost()) return; const auto& state = State(); @@ -2794,11 +2725,11 @@ void ClientWebGLContext::GetIndexedParameter( } const auto maybe = [&]() { - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { return inProcess->GetIndexedParameter(target, index); } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); Maybe<double> ret; if (!child->SendGetIndexedParameter(target, index, &ret)) { @@ -2831,12 +2762,8 @@ void ClientWebGLContext::GetUniform(JSContext* const cx, const WebGLUniformLocationJS& loc, JS::MutableHandle<JS::Value> retval) { retval.set(JS::NullValue()); - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } - const FuncScope funcScope(*this, "getUniform"); + if (IsContextLost()) return; if (!prog.ValidateUsable(*this, "prog")) return; if (!loc.ValidateUsable(*this, "loc")) return; @@ -2854,11 +2781,11 @@ void ClientWebGLContext::GetUniform(JSContext* const cx, } const auto res = [&]() { - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { return inProcess->GetUniform(prog.mId, loc.mLocation); } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); webgl::GetUniformData ret; if (!child->SendGetUniform(prog.mId, loc.mLocation, &ret)) { @@ -2974,14 +2901,10 @@ void ClientWebGLContext::GetUniform(JSContext* const cx, already_AddRefed<WebGLShaderPrecisionFormatJS> ClientWebGLContext::GetShaderPrecisionFormat(const GLenum shadertype, const GLenum precisiontype) { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return nullptr; - } - const FuncScope funcScope(*this, "getShaderPrecisionFormat"); + if (IsContextLost()) return nullptr; - const auto& shaderPrecisions = *notLost->info.shaderPrecisions; + const auto& shaderPrecisions = *mNotLost->info.shaderPrecisions; const auto args = webgl::GetShaderPrecisionFormatArgs{shadertype, precisiontype}; const auto found = MaybeFind(shaderPrecisions, args); @@ -3033,16 +2956,13 @@ void ClientWebGLContext::BlendFuncSeparateI(Maybe<GLuint> i, GLenum srcRGB, } GLenum ClientWebGLContext::CheckFramebufferStatus(GLenum target) { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return LOCAL_GL_FRAMEBUFFER_UNSUPPORTED; - } + if (IsContextLost()) return LOCAL_GL_FRAMEBUFFER_UNSUPPORTED; - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { return inProcess->CheckFramebufferStatus(target); } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); GLenum ret = 0; if (!child->SendCheckFramebufferStatus(target, &ret)) { @@ -3164,34 +3084,27 @@ void ClientWebGLContext::DepthRange(GLclampf zNear, GLclampf zFar) { } void ClientWebGLContext::Flush(const bool flushGl) const { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } - const FuncScope funcScope(*this, "flush"); + if (IsContextLost()) return; if (flushGl) { Run<RPROC(Flush)>(); } - if (notLost->inProcess) return; - const auto& child = notLost->outOfProcess; + if (mNotLost->inProcess) return; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); } void ClientWebGLContext::Finish() { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } + if (IsContextLost()) return; - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { inProcess->Finish(); return; } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); (void)child->SendFinish(); } @@ -3199,23 +3112,19 @@ void ClientWebGLContext::Finish() { void ClientWebGLContext::FrontFace(GLenum mode) { Run<RPROC(FrontFace)>(mode); } GLenum ClientWebGLContext::GetError() { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return 0; - } - const FuncScope funcScope(*this, "getError"); if (mNextError) { const auto ret = mNextError; mNextError = 0; return ret; } + if (IsContextLost()) return 0; - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { return inProcess->GetError(); } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); GLenum ret = 0; if (!child->SendGetError(&ret)) { @@ -3592,13 +3501,10 @@ void ClientWebGLContext::GetBufferSubData(GLenum target, GLintptr srcByteOffset, const dom::ArrayBufferView& dstData, GLuint dstElemOffset, GLuint dstElemCountOverride) { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } - const FuncScope funcScope(*this, "getBufferSubData"); - + if (IsContextLost()) return; + const auto notLost = + mNotLost; // Hold a strong-ref to prevent LoseContext=>UAF. if (!ValidateNonNegative("srcByteOffset", srcByteOffset)) return; size_t elemSize = SizeOfViewElem(dstData); @@ -4208,12 +4114,8 @@ void ClientWebGLContext::GetTexParameter( JSContext* cx, GLenum texTarget, GLenum pname, JS::MutableHandle<JS::Value> retval) const { retval.set(JS::NullValue()); - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } - const FuncScope funcScope(*this, "getTexParameter"); + if (IsContextLost()) return; auto& state = State(); auto& texUnit = state.mTexUnits[state.mActiveTexUnit]; @@ -4230,11 +4132,11 @@ void ClientWebGLContext::GetTexParameter( } const auto maybe = [&]() { - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { return inProcess->GetTexParameter(tex->mId, pname); } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); Maybe<double> ret; if (!child->SendGetTexParameter(tex->mId, pname, &ret)) { @@ -4413,12 +4315,8 @@ void ClientWebGLContext::TexImage(uint8_t funcDims, GLenum imageTarget, const Maybe<ivec3>& isize, GLint border, const webgl::PackingInfo& pi, const TexImageSource& src) const { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } - const FuncScope funcScope(*this, "tex(Sub)Image[23]D"); + if (IsContextLost()) return; if (!IsTexTargetForDims(ImageToTexTarget(imageTarget), mIsWebGL2, funcDims)) { EnqueueError_ArgEnum("imageTarget", imageTarget); return; @@ -4615,7 +4513,7 @@ void ClientWebGLContext::TexImage(uint8_t funcDims, GLenum imageTarget, if (desc->sd) { const auto& sd = *(desc->sd); const auto sdType = sd.type(); - const auto& contextInfo = notLost->info; + const auto& contextInfo = mNotLost->info; // TODO (Bug 754256): Figure out the source colorSpace. const auto& webgl = this; @@ -4662,7 +4560,7 @@ void ClientWebGLContext::TexImage(uint8_t funcDims, GLenum imageTarget, } break; case layers::SurfaceDescriptor::TSurfaceDescriptorD3D10: { const auto& sdD3D = sd.get_SurfaceDescriptorD3D10(); - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; MOZ_ASSERT(desc->image); keepAliveImage = desc->image; @@ -4672,7 +4570,7 @@ void ClientWebGLContext::TexImage(uint8_t funcDims, GLenum imageTarget, } } break; case layers::SurfaceDescriptor::TSurfaceDescriptorGPUVideo: { - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; MOZ_ASSERT(desc->image); keepAliveImage = desc->image; if (inProcess) { @@ -4695,7 +4593,7 @@ void ClientWebGLContext::TexImage(uint8_t funcDims, GLenum imageTarget, } } break; case layers::SurfaceDescriptor::TSurfaceDescriptorExternalImage: { - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; MOZ_ASSERT(desc->sourceSurf); keepAliveSurf = desc->sourceSurf; if (inProcess) { @@ -4704,7 +4602,7 @@ void ClientWebGLContext::TexImage(uint8_t funcDims, GLenum imageTarget, } } break; case layers::SurfaceDescriptor::TSurfaceDescriptorCanvasSurface: { - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; MOZ_ASSERT(desc->sourceSurf); keepAliveSurf = desc->sourceSurf; if (inProcess) { @@ -4772,12 +4670,12 @@ void ClientWebGLContext::TexImage(uint8_t funcDims, GLenum imageTarget, CastUvec3(offset), pi, std::move(*desc)); } else { // We can't handle shmems like SurfaceDescriptorBuffer inline, so use ipdl. - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { return inProcess->TexImage(static_cast<uint32_t>(level), respecFormat, CastUvec3(offset), pi, *desc); } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); // The shmem we're handling was only shared from RDD to Content, and @@ -4931,19 +4829,16 @@ void ClientWebGLContext::UseProgram(WebGLProgramJS* const prog) { } void ClientWebGLContext::ValidateProgram(WebGLProgramJS& prog) const { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } const FuncScope funcScope(*this, "validateProgram"); + if (IsContextLost()) return; if (!prog.ValidateUsable(*this, "prog")) return; prog.mLastValidate = [&]() { - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { return inProcess->ValidateProgram(prog.mId); } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); bool ret = {}; if (!child->SendValidateProgram(prog.mId, &ret)) { @@ -4957,15 +4852,11 @@ void ClientWebGLContext::ValidateProgram(WebGLProgramJS& prog) const { Maybe<double> ClientWebGLContext::GetVertexAttribPriv(const GLuint index, const GLenum pname) { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return Nothing(); - } - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { return inProcess->GetVertexAttrib(index, pname); } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); Maybe<double> ret; if (!child->SendGetVertexAttrib(index, pname, &ret)) { @@ -5398,10 +5289,9 @@ void ClientWebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, bool ClientWebGLContext::DoReadPixels(const webgl::ReadPixelsDesc& desc, const Span<uint8_t> dest) const { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return false; - } + const auto notLost = + mNotLost; // Hold a strong-ref to prevent LoseContext=>UAF. + if (!notLost) return false; const auto& inProcess = notLost->inProcess; if (inProcess) { inProcess->ReadPixelsInto(desc, dest); @@ -5544,19 +5434,16 @@ void ClientWebGLContext::GetQueryParameter( JSContext*, WebGLQueryJS& query, const GLenum pname, JS::MutableHandle<JS::Value> retval) const { retval.set(JS::NullValue()); - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } const FuncScope funcScope(*this, "getQueryParameter"); + if (IsContextLost()) return; if (!query.ValidateUsable(*this, "query")) return; auto maybe = [&]() { - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { return inProcess->GetQueryParameter(query.mId, pname); } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); Maybe<double> ret; if (!child->SendGetQueryParameter(query.mId, pname, &ret)) { @@ -5680,19 +5567,16 @@ void ClientWebGLContext::GetSamplerParameter( JSContext* cx, const WebGLSamplerJS& sampler, const GLenum pname, JS::MutableHandle<JS::Value> retval) const { retval.set(JS::NullValue()); - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } const FuncScope funcScope(*this, "getSamplerParameter"); + if (IsContextLost()) return; if (!sampler.ValidateUsable(*this, "sampler")) return; const auto maybe = [&]() { - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { return inProcess->GetSamplerParameter(sampler.mId, pname); } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); Maybe<double> ret; if (!child->SendGetSamplerParameter(sampler.mId, pname, &ret)) { @@ -5783,11 +5667,8 @@ void ClientWebGLContext::GetSyncParameter( GLenum ClientWebGLContext::ClientWaitSync(WebGLSyncJS& sync, const GLbitfield flags, const GLuint64 timeout) const { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return LOCAL_GL_WAIT_FAILED; - } const FuncScope funcScope(*this, "clientWaitSync"); + if (IsContextLost()) return LOCAL_GL_WAIT_FAILED; if (!sync.ValidateUsable(*this, "sync")) return LOCAL_GL_WAIT_FAILED; static constexpr auto VALID_BITS = LOCAL_GL_SYNC_FLUSH_COMMANDS_BIT; @@ -5848,11 +5729,11 @@ GLenum ClientWebGLContext::ClientWaitSync(WebGLSyncJS& sync, // Fine, time to block: const auto ret = [&]() { - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { return inProcess->ClientWaitSync(sync.mId, flags, timeout); } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); GLenum ret = {}; if (!child->SendClientWaitSync(sync.mId, flags, timeout, &ret)) { @@ -6070,7 +5951,7 @@ void ClientWebGLContext::DrawBuffers(const dom::Sequence<GLenum>& buffers) { void ClientWebGLContext::EnqueueErrorImpl(const GLenum error, const nsACString& text) const { - if (IsContextLost()) return; + if (!mNotLost) return; // Ignored if context is lost. AutoEnqueueFlush(); Run<RPROC(GenerateError)>(error, ToString(text)); } @@ -6120,7 +6001,7 @@ void ClientWebGLContext::GetSupportedExtensions( dom::Nullable<nsTArray<nsString>>& retval, const dom::CallerType callerType) const { retval.SetNull(); - if (IsContextLost()) return; + if (!mNotLost) return; auto& retarr = retval.SetValue(); for (const auto i : MakeEnumeratedRange(WebGLExtensionID::Max)) { @@ -6136,7 +6017,7 @@ void ClientWebGLContext::GetSupportedExtensions( void ClientWebGLContext::GetSupportedProfilesASTC( dom::Nullable<nsTArray<nsString>>& retval) const { retval.SetNull(); - if (IsContextLost()) return; + if (!mNotLost) return; const auto& limits = Limits(); auto& retarr = retval.SetValue(); @@ -6529,11 +6410,8 @@ GLint ClientWebGLContext::GetAttribLocation(const WebGLProgramJS& prog, GLint ClientWebGLContext::GetFragDataLocation(const WebGLProgramJS& prog, const nsAString& name) const { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return -1; - } const FuncScope funcScope(*this, "getFragDataLocation"); + if (IsContextLost()) return -1; if (!prog.ValidateUsable(*this, "program")) return -1; const auto nameU8 = ToString(NS_ConvertUTF16toUTF8(name)); @@ -6545,11 +6423,11 @@ GLint ClientWebGLContext::GetFragDataLocation(const WebGLProgramJS& prog, } return [&]() { - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { return inProcess->GetFragDataLocation(prog.mId, nameU8); } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); GLint ret = {}; if (!child->SendGetFragDataLocation(prog.mId, nameU8, &ret)) { @@ -6878,17 +6756,13 @@ void ClientWebGLContext::ShaderSource(WebGLShaderJS& shader, const webgl::CompileResult& ClientWebGLContext::GetCompileResult( const WebGLShaderJS& shader) const { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return shader.mResult; - } if (shader.mResult.pending) { shader.mResult = [&]() { - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { return inProcess->GetCompileResult(shader.mId); } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); webgl::CompileResult ret = {}; if (!child->SendGetCompileResult(shader.mId, &ret)) { @@ -6902,17 +6776,17 @@ const webgl::CompileResult& ClientWebGLContext::GetCompileResult( const webgl::LinkResult& ClientWebGLContext::GetLinkResult( const WebGLProgramJS& prog) const { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return *(prog.mResult); - } if (prog.mResult->pending) { + const auto notLost = + mNotLost; // Hold a strong-ref to prevent LoseContext=>UAF. + if (!notLost) return *(prog.mResult); + *(prog.mResult) = [&]() { - const auto& inProcess = notLost->inProcess; + const auto& inProcess = mNotLost->inProcess; if (inProcess) { return inProcess->GetLinkResult(prog.mId); } - const auto& child = notLost->outOfProcess; + const auto& child = mNotLost->outOfProcess; child->FlushPendingCmds(); webgl::LinkResult ret; if (!child->SendGetLinkResult(prog.mId, &ret)) {