tor-browser

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

commit 27689c413b0b9e5fb1f3c12a0962e2a034ee8fea
parent f6ad3a8d24a95f8bebb1ac58760dc393641abed5
Author: Narcis Beleuzu <nbeleuzu@mozilla.com>
Date:   Fri, 17 Oct 2025 03:56:38 +0300

Revert "Bug 1927289: More strongly enforce WebGL context continuity. r=ahale" for webgl failures on /test_conformance__context__context-lost-restored.html

This reverts commit fe0b47dff33c30892b2ecc7585b4bcc14d2f6094.

Diffstat:
Mdom/canvas/ClientWebGLContext.cpp | 363++++++++++++++++++++++++++++---------------------------------------------------
1 file changed, 126 insertions(+), 237 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; } @@ -801,8 +802,7 @@ ClientWebGLContext::SetDimensions(const int32_t signedWidth, mResetLayer = true; // Always treat this as resize. - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (notLost) { + if (mNotLost) { auto& state = State(); auto curSize = prevRequestedSize; @@ -1012,7 +1012,8 @@ std::unordered_map<GLenum, bool> webgl::MakeIsEnabledMap(const bool webgl2) { uvec2 ClientWebGLContext::DrawingBufferSize() { if (IsContextLost()) return {}; - RefPtr<webgl::NotLostData> notLost(mNotLost); + RefPtr<webgl::NotLostData> notLost( + mNotLost); // Hold a strong-ref to prevent LoseContext=>UAF. auto& state = State(); auto& size = state.mDrawingBufferSize; @@ -1033,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 @@ -1108,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; @@ -1158,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; @@ -1176,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; @@ -1216,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)) { @@ -1262,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(); @@ -1340,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 = {}; @@ -1355,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) { @@ -1372,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( @@ -1433,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(); } @@ -1963,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; @@ -1987,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); @@ -2013,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; @@ -2061,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; @@ -2082,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; @@ -2105,11 +2072,6 @@ Maybe<std::string> ClientWebGLContext::GetString(const GLenum pname) { void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname, JS::MutableHandle<JS::Value> retval, ErrorResult& rv, const bool debug) { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } - retval.set(JS::NullValue()); const FuncScope funcScope(*this, "getParameter"); if (IsContextLost()) return; @@ -2512,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))); @@ -2578,19 +2540,15 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname, void ClientWebGLContext::GetBufferParameter( JSContext* cx, GLenum target, GLenum pname, JS::MutableHandle<JS::Value> retval) const { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } - retval.set(JS::NullValue()); + 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)) { @@ -2621,13 +2579,9 @@ void ClientWebGLContext::GetFramebufferAttachmentParameter( JSContext* const cx, const GLenum target, const GLenum attachment, const GLenum pname, JS::MutableHandle<JS::Value> retval, ErrorResult& rv) const { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } - retval.set(JS::NullValue()); const FuncScope funcScope(*this, "getFramebufferAttachmentParameter"); + if (IsContextLost()) return; const auto& state = State(); @@ -2643,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, @@ -2707,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); @@ -2723,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)) { @@ -2743,13 +2693,9 @@ void ClientWebGLContext::GetRenderbufferParameter( void ClientWebGLContext::GetIndexedParameter( JSContext* cx, GLenum target, GLuint index, JS::MutableHandle<JS::Value> retval, ErrorResult& rv) const { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } - retval.set(JS::NullValue()); const FuncScope funcScope(*this, "getIndexedParameter"); + if (IsContextLost()) return; const auto& state = State(); @@ -2779,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)) { @@ -2815,13 +2761,9 @@ void ClientWebGLContext::GetUniform(JSContext* const cx, const WebGLProgramJS& prog, const WebGLUniformLocationJS& loc, JS::MutableHandle<JS::Value> retval) { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } - retval.set(JS::NullValue()); const FuncScope funcScope(*this, "getUniform"); + if (IsContextLost()) return; if (!prog.ValidateUsable(*this, "prog")) return; if (!loc.ValidateUsable(*this, "loc")) return; @@ -2839,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)) { @@ -2959,15 +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); @@ -3019,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)) { @@ -3150,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(); } @@ -3185,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)) { @@ -3580,10 +3503,8 @@ void ClientWebGLContext::GetBufferSubData(GLenum target, GLintptr srcByteOffset, GLuint dstElemCountOverride) { const FuncScope funcScope(*this, "getBufferSubData"); if (IsContextLost()) return; - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } + const auto notLost = + mNotLost; // Hold a strong-ref to prevent LoseContext=>UAF. if (!ValidateNonNegative("srcByteOffset", srcByteOffset)) return; size_t elemSize = SizeOfViewElem(dstData); @@ -4192,13 +4113,9 @@ void ClientWebGLContext::GenerateMipmap(GLenum texTarget) const { void ClientWebGLContext::GetTexParameter( JSContext* cx, GLenum texTarget, GLenum pname, JS::MutableHandle<JS::Value> retval) const { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } - retval.set(JS::NullValue()); const FuncScope funcScope(*this, "getTexParameter"); + if (IsContextLost()) return; auto& state = State(); auto& texUnit = state.mTexUnits[state.mActiveTexUnit]; @@ -4215,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)) { @@ -4398,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; @@ -4600,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; @@ -4647,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; @@ -4657,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) { @@ -4680,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) { @@ -4689,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) { @@ -4757,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 @@ -4916,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)) { @@ -4942,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)) { @@ -5383,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); @@ -5528,20 +5433,17 @@ void ClientWebGLContext::GetQuery(JSContext* cx, GLenum specificTarget, void ClientWebGLContext::GetQueryParameter( JSContext*, WebGLQueryJS& query, const GLenum pname, JS::MutableHandle<JS::Value> retval) const { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } retval.set(JS::NullValue()); 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)) { @@ -5664,20 +5566,17 @@ void ClientWebGLContext::QueryCounter(WebGLQueryJS& query, void ClientWebGLContext::GetSamplerParameter( JSContext* cx, const WebGLSamplerJS& sampler, const GLenum pname, JS::MutableHandle<JS::Value> retval) const { - RefPtr<webgl::NotLostData> notLost(mNotLost); - if (!notLost) { - return; - } retval.set(JS::NullValue()); 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)) { @@ -5768,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; @@ -5833,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)) { @@ -6055,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)); } @@ -6105,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)) { @@ -6121,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(); @@ -6514,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)); @@ -6530,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)) { @@ -6863,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)) { @@ -6887,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)) {