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.

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 16, 2024
1 parent a62a8fc commit 73aa2d6
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:/w3c/mediacapture-fromelement/issues/65
// https:/w3c/mediacapture-extensions/pull/26
// https:/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:/w3c/mediacapture-fromelement/issues/65
// https:/w3c/mediacapture-extensions/pull/26
// https:/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 73aa2d6

Please sign in to comment.