Changeset 280676 in webkit
- Timestamp:
- Aug 4, 2021, 7:46:31 PM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
-
ChangeLog (modified) (1 diff)
-
Modules/mediacontrols/MediaControlsHost.cpp (modified) (8 diffs)
-
Modules/mediacontrols/MediaControlsHost.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r280671 r280676 1 2021-08-04 Devin Rousso <drousso@apple.com> 2 3 REGRESSION (r280374): ASSERTION FAILED: Completion handler should not be called more than once under WebCore::MediaControlsContextMenuProvider::contextMenuItemSelected 4 https://bugs.webkit.org/show_bug.cgi?id=228725 5 <rdar://problem/81437221> 6 7 Reviewed by Eric Carlson. 8 9 The contextmenu system used by (modern) media controls are a bit wonky in that it has to 10 support both macOS and iOS, which use wildly different mechanisms. The former has distinct 11 methods for handling when a contextmenu item is selected vs when the menu is dismissed (at 12 least as of r280374). The latter has a single method that handles both. Additionally, the 13 (modern) media controls JS expects the following from `showMediaControlsContextMenu`: 14 1. `showMediaControlsContextMenu` will only `return true` if the contextmenu will be shown 15 2. the callback provided to `showMediaControlsContextMenu` will always/only be invoked when 16 the contextmenu is dismissed (regardless of whether an item is selected) 17 3. if an item is selected, the logic for that will be handled by the `MediaControlsHost` 18 This patch primarily addresses #2, but also slightly adjusts the code to fix #1. It does #1 19 by moving the call that saves the callback further down. On iOS, #2 already works. On macOS, 20 it does #2 by changing from `CompletionHandler` to `Function`, allowing it to be called more 21 than once, with the understanding that the JS callback will not be invoked more than once. 22 This way, macOS can match the behavior of iOS by eagerly invoking the JS callback when a 23 contextmenu item is selected without waiting for the menu to actually dismiss, while still 24 handling the contextmenu being dismissed without an item being selected (and also not having 25 to worry about whether the `CompletionHandler` has already been invoked). 26 27 * Modules/mediacontrols/MediaControlsHost.h: 28 * Modules/mediacontrols/MediaControlsHost.cpp: 29 (WebCore::MediaControlsContextMenuProvider::create): 30 (WebCore::MediaControlsContextMenuProvider::MediaControlsContextMenuProvider): 31 (WebCore::MediaControlsContextMenuProvider::didDismissContextMenu): 32 (WebCore::MediaControlsContextMenuProvider::contextMenuCleared): 33 (WebCore::MediaControlsHost::showMediaControlsContextMenu): 34 1 35 2021-08-04 Dana Estra <destra@apple.com> 2 36 -
trunk/Source/WebCore/Modules/mediacontrols/MediaControlsHost.cpp
r280374 r280676 62 62 #include "VoidCallback.h" 63 63 #include <JavaScriptCore/JSCJSValueInlines.h> 64 #include <wtf/ CompletionHandler.h>64 #include <wtf/Function.h> 65 65 #include <wtf/JSONValues.h> 66 66 #include <wtf/Scope.h> … … 366 366 class MediaControlsContextMenuProvider final : public ContextMenuProvider { 367 367 public: 368 static Ref<MediaControlsContextMenuProvider> create(Vector<ContextMenuItem>&& items, CompletionHandler<void(uint64_t)>&& callback)368 static Ref<MediaControlsContextMenuProvider> create(Vector<ContextMenuItem>&& items, Function<void(uint64_t)>&& callback) 369 369 { 370 370 return adoptRef(*new MediaControlsContextMenuProvider(WTFMove(items), WTFMove(callback))); … … 372 372 373 373 private: 374 MediaControlsContextMenuProvider(Vector<ContextMenuItem>&& items, CompletionHandler<void(uint64_t)>&& callback)374 MediaControlsContextMenuProvider(Vector<ContextMenuItem>&& items, Function<void(uint64_t)>&& callback) 375 375 : m_items(WTFMove(items)) 376 376 , m_callback(WTFMove(callback)) … … 391 391 void didDismissContextMenu() override 392 392 { 393 if (m_callback) 393 if (!m_didDismiss) { 394 m_didDismiss = true; 394 395 m_callback(ContextMenuItemTagNoAction); 396 } 395 397 } 396 398 … … 402 404 void contextMenuCleared() override 403 405 { 404 if (m_callback) 405 m_callback(ContextMenuItemTagNoAction); 406 didDismissContextMenu(); 406 407 m_items.clear(); 407 408 } … … 413 414 414 415 Vector<ContextMenuItem> m_items; 415 CompletionHandler<void(uint64_t)> m_callback; 416 Function<void(uint64_t)> m_callback; 417 bool m_didDismiss { false }; 416 418 }; 417 419 … … 464 466 if (m_showMediaControlsContextMenuCallback) 465 467 return false; 466 467 m_showMediaControlsContextMenuCallback = WTFMove(callback);468 469 auto invokeCallbackAtScopeExit = makeScopeExit([&, protectedThis = makeRef(*this)] {470 if (m_showMediaControlsContextMenuCallback)471 std::exchange(m_showMediaControlsContextMenuCallback, nullptr)->handleEvent();472 });473 468 474 469 if (!m_mediaElement) … … 656 651 ASSERT(!idMap.isEmpty()); 657 652 658 auto handleItemSelected = [weakMediaElement = makeWeakPtr(mediaElement), idMap = WTFMove(idMap), invokeCallbackAtScopeExit = WTFMove(invokeCallbackAtScopeExit)] (MenuItemIdentifier selectedItemID) { 653 m_showMediaControlsContextMenuCallback = WTFMove(callback); 654 655 auto handleItemSelected = [weakThis = makeWeakPtr(this), idMap = WTFMove(idMap)] (MenuItemIdentifier selectedItemID) { 656 if (!weakThis) 657 return; 658 Ref strongThis = *weakThis; 659 660 auto invokeCallbackAtScopeExit = makeScopeExit([strongThis] { 661 if (auto showMediaControlsContextMenuCallback = std::exchange(strongThis->m_showMediaControlsContextMenuCallback, nullptr)) 662 showMediaControlsContextMenuCallback->handleEvent(); 663 }); 664 659 665 if (selectedItemID == invalidMenuItemIdentifier) 660 666 return; 661 667 662 if (! weakMediaElement)668 if (!strongThis->m_mediaElement) 663 669 return; 664 665 auto& mediaElement = *weakMediaElement; 670 auto& mediaElement = *strongThis->m_mediaElement; 666 671 667 672 UserGestureIndicator gestureIndicator(ProcessingUserGesture, &mediaElement.document()); -
trunk/Source/WebCore/Modules/mediacontrols/MediaControlsHost.h
r279309 r280676 46 46 class VoidCallback; 47 47 48 class MediaControlsHost : public RefCounted<MediaControlsHost> {48 class MediaControlsHost final : public RefCounted<MediaControlsHost>, public CanMakeWeakPtr<MediaControlsHost> { 49 49 WTF_MAKE_FAST_ALLOCATED(MediaControlsHost); 50 50 public:
Note:
See TracChangeset
for help on using the changeset viewer.