Skip to content

Commit

Permalink
Bug 1888634 - Disallow captureStream with canvas transferred to DOM w…
Browse files Browse the repository at this point in the history
…orker. r=gfx-reviewers,lsalzman

This behaviour has yet to be defined by the spec and/or WPT, see:

w3c/mediacapture-fromelement#65
w3c/mediacapture-extensions#26
web-platform-tests/wpt#21102

Differential Revision: https://phabricator.services.mozilla.com/D207582
  • Loading branch information
aosmond committed Apr 17, 2024
1 parent 989d782 commit 467baa2
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 0 deletions.
15 changes: 15 additions & 0 deletions dom/canvas/OffscreenCanvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,21 @@ UniquePtr<OffscreenCanvasCloneData> OffscreenCanvas::ToCloneData(
return nullptr;
}

// Check if we are using HTMLCanvasElement::captureStream. This is not
// defined by the spec yet, so it is better to fail now than implement
// something not compliant:
// https://github.com/w3c/mediacapture-fromelement/issues/65
// https://github.com/w3c/mediacapture-extensions/pull/26
// https://github.com/web-platform-tests/wpt/issues/21102
if (mDisplay && NS_WARN_IF(mDisplay->UsingElementCaptureStream())) {
ErrorResult rv;
rv.ThrowNotSupportedError(
"Cannot transfer OffscreenCanvas bound to element using "
"captureStream.");
MOZ_ALWAYS_TRUE(rv.MaybeSetPendingException(aCx));
return nullptr;
}

auto cloneData = MakeUnique<OffscreenCanvasCloneData>(
mDisplay, mWidth, mHeight, mCompositorBackendType, mTextureType,
mNeutered, mIsWriteOnly, mExpandedReader);
Expand Down
16 changes: 16 additions & 0 deletions dom/canvas/OffscreenCanvasDisplayHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,22 @@ void OffscreenCanvasDisplayHelper::DestroyCanvas() {
mWorkerRef = nullptr;
}

bool OffscreenCanvasDisplayHelper::CanElementCaptureStream() const {
MutexAutoLock lock(mMutex);
return !!mWorkerRef;
}

bool OffscreenCanvasDisplayHelper::UsingElementCaptureStream() const {
MutexAutoLock lock(mMutex);

if (NS_WARN_IF(!NS_IsMainThread())) {
MOZ_ASSERT_UNREACHABLE("Should not call off main-thread!");
return !!mCanvasElement;
}

return mCanvasElement && mCanvasElement->UsingCaptureStream();
}

CanvasContextType OffscreenCanvasDisplayHelper::GetContextType() const {
MutexAutoLock lock(mMutex);
return mType;
Expand Down
3 changes: 3 additions & 0 deletions dom/canvas/OffscreenCanvasDisplayHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ class OffscreenCanvasDisplayHelper final {
void DestroyCanvas();
void DestroyElement();

bool CanElementCaptureStream() const;
bool UsingElementCaptureStream() const;

already_AddRefed<mozilla::gfx::SourceSurface> GetSurfaceSnapshot();
already_AddRefed<mozilla::layers::Image> GetAsImage();
UniquePtr<uint8_t[]> GetImageBuffer(int32_t* aOutFormat,
Expand Down
14 changes: 14 additions & 0 deletions dom/html/HTMLCanvasElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,20 @@ already_AddRefed<CanvasCaptureMediaStream> HTMLCanvasElement::CaptureStream(
return nullptr;
}

// Check if we transferred the OffscreenCanvas to a DOM worker. This is not
// defined by the spec yet, so it is better to fail now than implement
// something not compliant:
// https://github.com/w3c/mediacapture-fromelement/issues/65
// https://github.com/w3c/mediacapture-extensions/pull/26
// https://github.com/web-platform-tests/wpt/issues/21102
if (mOffscreenDisplay &&
NS_WARN_IF(!mOffscreenDisplay->CanElementCaptureStream())) {
aRv.ThrowNotSupportedError(
"Capture stream not supported when OffscreenCanvas transferred to "
"worker");
return nullptr;
}

auto stream = MakeRefPtr<CanvasCaptureMediaStream>(window, this);

nsCOMPtr<nsIPrincipal> principal = NodePrincipal();
Expand Down
2 changes: 2 additions & 0 deletions dom/html/HTMLCanvasElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,8 @@ class HTMLCanvasElement final : public nsGenericHTMLElement,

layers::ImageContainer* GetImageContainer() const { return mImageContainer; }

bool UsingCaptureStream() const { return !!mRequestedFrameRefreshObserver; }

protected:
bool mResetLayer;
bool mMaybeModified; // we fetched the context, so we may have written to the
Expand Down

0 comments on commit 467baa2

Please sign in to comment.