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:
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, ¬Lost->info);
+ notLost.inProcess =
+ HostWebGLContext::Create({this, nullptr}, initDesc, ¬Lost.info);
return Ok();
}
@@ -931,11 +916,11 @@ bool ClientWebGLContext::CreateHostContext(const uvec2& requestedSize) {
mFwdTransactionTracker = nullptr;
}
- if (!outOfProcess->SendInitialize(initDesc, ¬Lost->info)) {
+ if (!outOfProcess->SendInitialize(initDesc, ¬Lost.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)) {