Skip to content

Commit

Permalink
[Cocoa] Cancel pending getDisplayMedia prompt when page is reloaded
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=260795
rdar://114563662

Reviewed by Youenn Fablet.

If the page is reloaded while the system prompt window/screen picker is active, cancel
the picker instead waiting for the ScreenCaptureKitSharingSessionManager watchdog timer
to go off and cancel it.

* Source/WebCore/platform/mediastream/mac/ScreenCaptureKitSharingSessionManager.h:
* Source/WebCore/platform/mediastream/mac/ScreenCaptureKitSharingSessionManager.mm:
(WebCore::ScreenCaptureKitSharingSessionManager::cancelGetDisplayMediaPrompt):
* Source/WebKit/GPUProcess/GPUProcess.cpp:
(WebKit::GPUProcess::cancelGetDisplayMediaPrompt):
* Source/WebKit/GPUProcess/GPUProcess.h:
* Source/WebKit/GPUProcess/GPUProcess.messages.in:
* Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp:
(WebKit::GPUProcessProxy::cancelGetDisplayMediaPrompt):
* Source/WebKit/UIProcess/GPU/GPUProcessProxy.h:
* Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
(WebKit::UserMediaPermissionRequestManagerProxy::resetAccess):
* Source/WebKit/UIProcess/UserMediaPermissionRequestProxy.h:
* Source/WebKit/UIProcess/mac/DisplayCaptureSessionManager.h:
* Source/WebKit/UIProcess/mac/DisplayCaptureSessionManager.mm:
(WebKit::DisplayCaptureSessionManager::cancelGetDisplayMediaPrompt):
* Source/WebKit/UIProcess/mac/UserMediaPermissionRequestProxyMac.h:
* Source/WebKit/UIProcess/mac/UserMediaPermissionRequestProxyMac.mm:
(WebKit::UserMediaPermissionRequestProxyMac::invalidate):
(WebKit::UserMediaPermissionRequestProxyMac::promptForGetDisplayMedia):

Canonical link: https://commits.webkit.org/274439@main
  • Loading branch information
eric-carlson committed Feb 11, 2024
1 parent 537043c commit 80f25d4
Show file tree
Hide file tree
Showing 13 changed files with 69 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ class ScreenCaptureKitSharingSessionManager : public CanMakeWeakPtr<ScreenCaptur
void cancelPendingSessionForDevice(const CaptureDevice&);

WEBCORE_EXPORT void promptForGetDisplayMedia(DisplayCapturePromptType, CompletionHandler<void(std::optional<CaptureDevice>)>&&);
WEBCORE_EXPORT void cancelGetDisplayMediaPrompt();

private:
void cleanupAllSessions();
Expand All @@ -119,7 +120,6 @@ class ScreenCaptureKitSharingSessionManager : public CanMakeWeakPtr<ScreenCaptur
WeakPtr<ScreenCaptureSessionSource> findActiveSource(SCContentSharingSession*);

Vector<WeakPtr<ScreenCaptureSessionSource>> m_activeSources;
Vector<std::tuple<RetainPtr<SCContentFilter>, RetainPtr<SCContentSharingSession>>> m_pendingSessions;

RetainPtr<SCContentSharingSession> m_pendingSession;
RetainPtr<SCContentFilter> m_pendingContentFilter;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,12 @@ - (void)stopObservingPicker:(SCContentSharingPicker *)picker
}
}

void ScreenCaptureKitSharingSessionManager::cancelGetDisplayMediaPrompt()
{
if (promptingInProgress())
cancelPicking();
}

void ScreenCaptureKitSharingSessionManager::cancelPicking()
{
ASSERT(isMainThread());
Expand Down
6 changes: 6 additions & 0 deletions Source/WebKit/GPUProcess/GPUProcess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,12 @@ void GPUProcess::promptForGetDisplayMedia(WebCore::DisplayCapturePromptType type
{
WebCore::ScreenCaptureKitSharingSessionManager::singleton().promptForGetDisplayMedia(type, WTFMove(completionHandler));
}

void GPUProcess::cancelGetDisplayMediaPrompt()
{
WebCore::ScreenCaptureKitSharingSessionManager::singleton().cancelGetDisplayMediaPrompt();
}

#endif // HAVE(SCREEN_CAPTURE_KIT)

#if PLATFORM(MAC)
Expand Down
1 change: 1 addition & 0 deletions Source/WebKit/GPUProcess/GPUProcess.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ class GPUProcess : public AuxiliaryProcess, public ThreadSafeRefCounted<GPUProce
#endif
#if HAVE(SCREEN_CAPTURE_KIT)
void promptForGetDisplayMedia(WebCore::DisplayCapturePromptType, CompletionHandler<void(std::optional<WebCore::CaptureDevice>)>&&);
void cancelGetDisplayMediaPrompt();
#endif
#if PLATFORM(MAC)
void displayConfigurationChanged(CGDirectDisplayID, CGDisplayChangeSummaryFlags);
Expand Down
1 change: 1 addition & 0 deletions Source/WebKit/GPUProcess/GPUProcess.messages.in
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ messages -> GPUProcess LegacyReceiver {

#if HAVE(SCREEN_CAPTURE_KIT)
PromptForGetDisplayMedia(enum:uint8_t WebCore::DisplayCapturePromptType type) -> (std::optional<WebCore::CaptureDevice> device)
CancelGetDisplayMediaPrompt()
#endif

#if ENABLE(VIDEO)
Expand Down
5 changes: 5 additions & 0 deletions Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,11 @@ void GPUProcessProxy::promptForGetDisplayMedia(WebCore::DisplayCapturePromptType
{
sendWithAsyncReply(Messages::GPUProcess::PromptForGetDisplayMedia { type }, WTFMove(completionHandler));
}

void GPUProcessProxy::cancelGetDisplayMediaPrompt()
{
send(Messages::GPUProcess::CancelGetDisplayMediaPrompt { }, 0);
}
#endif

void GPUProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOptions)
Expand Down
1 change: 1 addition & 0 deletions Source/WebKit/UIProcess/GPU/GPUProcessProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class GPUProcessProxy final : public AuxiliaryProcessProxy {

#if HAVE(SCREEN_CAPTURE_KIT)
void promptForGetDisplayMedia(WebCore::DisplayCapturePromptType, CompletionHandler<void(std::optional<WebCore::CaptureDevice>)>&&);
void cancelGetDisplayMediaPrompt();
#endif

void removeSession(PAL::SessionID);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,11 @@ void UserMediaPermissionRequestManagerProxy::resetAccess(std::optional<FrameIden
{
ALWAYS_LOG(LOGIDENTIFIER, frameID ? frameID->object().toUInt64() : 0);

if (m_currentUserMediaRequest && (!frameID || m_currentUserMediaRequest->frameID() == *frameID)) {
m_currentUserMediaRequest->invalidate();
m_currentUserMediaRequest = nullptr;
}

if (frameID) {
m_grantedRequests.removeAllMatching([frameID](const auto& grantedRequest) {
return grantedRequest->mainFrameID() == frameID;
Expand Down
2 changes: 1 addition & 1 deletion Source/WebKit/UIProcess/UserMediaPermissionRequestProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class UserMediaPermissionRequestProxy : public API::ObjectImpl<API::Object::Type
enum class UserMediaAccessDenialReason { NoConstraints, UserMediaDisabled, NoCaptureDevices, InvalidConstraint, HardwareError, PermissionDenied, OtherFailure };
void deny(UserMediaAccessDenialReason = UserMediaAccessDenialReason::UserMediaDisabled);

void invalidate();
virtual void invalidate();
bool isPending() const { return m_manager; }

bool requiresAudioCapture() const { return m_eligibleAudioDevices.size(); }
Expand Down
1 change: 1 addition & 0 deletions Source/WebKit/UIProcess/mac/DisplayCaptureSessionManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class DisplayCaptureSessionManager {
~DisplayCaptureSessionManager();

void promptForGetDisplayMedia(UserMediaPermissionRequestProxy::UserMediaDisplayCapturePromptType, WebPageProxy&, const WebCore::SecurityOriginData&, CompletionHandler<void(std::optional<WebCore::CaptureDevice>)>&&);
void cancelGetDisplayMediaPrompt(WebPageProxy&);
bool canRequestDisplayCapturePermission();
void setIndexOfDeviceSelectedForTesting(std::optional<unsigned> index) { m_indexOfDeviceSelectedForTesting = index; }

Expand Down
21 changes: 21 additions & 0 deletions Source/WebKit/UIProcess/mac/DisplayCaptureSessionManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,27 @@
#endif
}

void DisplayCaptureSessionManager::cancelGetDisplayMediaPrompt(WebPageProxy& page)
{
#if HAVE(SCREEN_CAPTURE_KIT)
ASSERT(isAvailable());

if (!isAvailable() || !WebCore::ScreenCaptureKitSharingSessionManager::isAvailable())
return;

if (!page.preferences().useGPUProcessForDisplayCapture()) {
WebCore::ScreenCaptureKitSharingSessionManager::singleton().cancelGetDisplayMediaPrompt();
return;
}

auto gpuProcess = page.process().processPool().gpuProcess();
if (!gpuProcess)
return;

gpuProcess->cancelGetDisplayMediaPrompt();
#endif
}

} // namespace WebKit

#endif // PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,14 @@ class UserMediaPermissionRequestProxyMac final : public UserMediaPermissionReque

UserMediaPermissionRequestProxyMac(UserMediaPermissionRequestManagerProxy&, WebCore::UserMediaRequestIdentifier, WebCore::FrameIdentifier mainFrameID, WebCore::FrameIdentifier, Ref<WebCore::SecurityOrigin>&& userMediaDocumentOrigin, Ref<WebCore::SecurityOrigin>&& topLevelDocumentOrigin, Vector<WebCore::CaptureDevice>&& audioDevices, Vector<WebCore::CaptureDevice>&& videoDevices, WebCore::MediaStreamRequest&&, CompletionHandler<void(bool)>&&);

private:
void promptForGetDisplayMedia(UserMediaDisplayCapturePromptType) final;
bool canRequestDisplayCapturePermission() final;
void invalidate() final;

#if ENABLE(MEDIA_STREAM)
bool m_hasPendingGetDispayMediaPrompt { false };
#endif
};


Expand Down
14 changes: 14 additions & 0 deletions Source/WebKit/UIProcess/mac/UserMediaPermissionRequestProxyMac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,28 @@
{
}

void UserMediaPermissionRequestProxyMac::invalidate()
{
#if ENABLE(MEDIA_STREAM)
if (m_hasPendingGetDispayMediaPrompt) {
DisplayCaptureSessionManager::singleton().cancelGetDisplayMediaPrompt(Ref { manager()->page() });
m_hasPendingGetDispayMediaPrompt = false;
}
#endif
UserMediaPermissionRequestProxy::invalidate();
}

void UserMediaPermissionRequestProxyMac::promptForGetDisplayMedia(UserMediaDisplayCapturePromptType promptType)
{
#if ENABLE(MEDIA_STREAM)
if (!manager())
return;

m_hasPendingGetDispayMediaPrompt = true;
DisplayCaptureSessionManager::singleton().promptForGetDisplayMedia(promptType, Ref { manager()->page() }, topLevelDocumentSecurityOrigin().data(), [protectedThis = Ref { *this }](std::optional<CaptureDevice> device) mutable {

protectedThis->m_hasPendingGetDispayMediaPrompt = false;

if (!device) {
protectedThis->deny(UserMediaPermissionRequestProxy::UserMediaAccessDenialReason::PermissionDenied);
return;
Expand Down

0 comments on commit 80f25d4

Please sign in to comment.