Changeset 251746 in webkit


Ignore:
Timestamp:
Oct 29, 2019 5:28:20 PM (4 years ago)
Author:
Chris Dumez
Message:

UserMediaRequest should not prevent entering the back/forward cache
https://bugs.webkit.org/show_bug.cgi?id=203098
<rdar://problem/56716101>

Reviewed by Eric Carlson.

Source/WebCore:

Allow pages to enter the back/forward cache, even if they have a pending
getUserMedia promise. Whenever we get a permission decision from the
UIProcess, we now schedule a task to resolve/reject the promise on the
WindowEventLoop. The WindowEventLoop properly gets suspended while in
the back/forward cache.

Test: http/tests/navigation/page-cache-getUserMedia-pending-promise.html

  • Modules/mediastream/MediaDevices.cpp:

(WebCore::MediaDevices::getUserMedia const):
If the document is not fully active, reject the promise with an InvalidStateError, as per:

  • Modules/mediastream/UserMediaRequest.cpp:

(WebCore::UserMediaRequest::allow):
(WebCore::UserMediaRequest::deny):
(WebCore::UserMediaRequest::shouldPreventEnteringBackForwardCache_DEPRECATED const): Deleted.

  • Modules/mediastream/UserMediaRequest.h:

LayoutTests:

Add layout test coverage.

  • fast/mediastream/MediaDevices-getUserMedia-expected.txt:
  • http/tests/navigation/page-cache-getUserMedia-pending-promise-expected.txt: Added.
  • http/tests/navigation/page-cache-getUserMedia-pending-promise.html: Added.
Location:
trunk
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r251745 r251746  
     12019-10-29  Chris Dumez  <cdumez@apple.com>
     2
     3        UserMediaRequest should not prevent entering the back/forward cache
     4        https://bugs.webkit.org/show_bug.cgi?id=203098
     5        <rdar://problem/56716101>
     6
     7        Reviewed by Eric Carlson.
     8
     9        Add layout test coverage.
     10
     11        * fast/mediastream/MediaDevices-getUserMedia-expected.txt:
     12        * http/tests/navigation/page-cache-getUserMedia-pending-promise-expected.txt: Added.
     13        * http/tests/navigation/page-cache-getUserMedia-pending-promise.html: Added.
     14
    1152019-10-29  Peng Liu  <peng.liu6@apple.com>
    216
  • trunk/LayoutTests/fast/mediastream/MediaDevices-getUserMedia-expected.txt

    r217081 r251746  
    77
    88PASS navigator.mediaDevices.getUserMedia({audio:true}).then(gotStream1); did not throw exception.
     9PASS navigator.mediaDevices.getUserMedia.apply(undefined) rejected with error: TypeError: Can only call MediaDevices.getUserMedia on instances of MediaDevices
    910PASS navigator.mediaDevices.getUserMedia() rejected with error: TypeError: Type error
    1011PASS navigator.mediaDevices.getUserMedia({}) rejected with error: TypeError: Type error
    11 PASS navigator.mediaDevices.getUserMedia.apply(undefined) rejected with error: TypeError: Can only call MediaDevices.getUserMedia on instances of MediaDevices
    1212PASS Stream 1 generated.
    1313PASS stream.getAudioTracks().length is 1
  • trunk/LayoutTests/platform/mac-wk1/TestExpectations

    r251733 r251746  
    6060http/tests/ssl/media-stream
    6161inspector/page/overrideSetting-MockCaptureDevicesEnabled.html [ Skip ]
     62http/tests/navigation/page-cache-getUserMedia-pending-promise.html [ Skip ]
    6263
    6364# Datalist is unsupported in WK1
  • trunk/LayoutTests/platform/win/TestExpectations

    r251708 r251746  
    867867imported/w3c/web-platform-tests/mediacapture-streams [ Skip ]
    868868http/tests/media/media-stream [ Skip ]
     869http/tests/navigation/page-cache-getUserMedia-pending-promise.html [ Skip ]
    869870
    870871# needs enhanced eventSender.contextMenu() return value
  • trunk/Source/WebCore/ChangeLog

    r251745 r251746  
     12019-10-29  Chris Dumez  <cdumez@apple.com>
     2
     3        UserMediaRequest should not prevent entering the back/forward cache
     4        https://bugs.webkit.org/show_bug.cgi?id=203098
     5        <rdar://problem/56716101>
     6
     7        Reviewed by Eric Carlson.
     8
     9        Allow pages to enter the back/forward cache, even if they have a pending
     10        getUserMedia promise. Whenever we get a permission decision from the
     11        UIProcess, we now schedule a task to resolve/reject the promise on the
     12        WindowEventLoop. The WindowEventLoop properly gets suspended while in
     13        the back/forward cache.
     14
     15        Test: http/tests/navigation/page-cache-getUserMedia-pending-promise.html
     16
     17        * Modules/mediastream/MediaDevices.cpp:
     18        (WebCore::MediaDevices::getUserMedia const):
     19        If the document is not fully active, reject the promise with an InvalidStateError, as per:
     20        - https://w3c.github.io/mediacapture-main/#dom-mediadevices-getusermedia (Step 4)
     21
     22        * Modules/mediastream/UserMediaRequest.cpp:
     23        (WebCore::UserMediaRequest::allow):
     24        (WebCore::UserMediaRequest::deny):
     25        (WebCore::UserMediaRequest::shouldPreventEnteringBackForwardCache_DEPRECATED const): Deleted.
     26        * Modules/mediastream/UserMediaRequest.h:
     27
    1282019-10-29  Peng Liu  <peng.liu6@apple.com>
    229
  • trunk/Source/WebCore/Modules/mediastream/MediaDevices.cpp

    r251712 r251746  
    108108{
    109109    auto* document = this->document();
    110     if (!document)
    111         return;
     110    if (!document || !document->isFullyActive()) {
     111        promise.reject(Exception { InvalidStateError, "Document is not fully active"_s });
     112        return;
     113    }
    112114
    113115    auto audioConstraints = createMediaConstraints(constraints.audio);
  • trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp

    r251244 r251746  
    4848#include "Settings.h"
    4949#include "UserMediaController.h"
     50#include "WindowEventLoop.h"
    5051#include <wtf/Scope.h>
    5152
     
    230231{
    231232    RELEASE_LOG(MediaStream, "UserMediaRequest::allow %s %s", audioDevice ? audioDevice.persistentId().utf8().data() : "", videoDevice ? videoDevice.persistentId().utf8().data() : "");
    232 
    233     auto callback = [this, protector = makePendingActivity(*this), completionHandler = WTFMove(completionHandler)](RefPtr<MediaStreamPrivate>&& privateStream) mutable {
    234         auto scopeExit = makeScopeExit([completionHandler = WTFMove(completionHandler)]() mutable {
    235             completionHandler();
    236         });
    237         if (isContextStopped())
     233    auto* document = this->document();
     234    if (!document)
     235        return completionHandler();
     236
     237    document->eventLoop().queueTask(TaskSource::UserInteraction, *document, [this, protectedThis = makeRef(*this), audioDevice = WTFMove(audioDevice), videoDevice = WTFMove(videoDevice), deviceIdentifierHashSalt = WTFMove(deviceIdentifierHashSalt), completionHandler = WTFMove(completionHandler)]() mutable {
     238        auto callback = [this, protector = makePendingActivity(*this), completionHandler = WTFMove(completionHandler)](RefPtr<MediaStreamPrivate>&& privateStream) mutable {
     239            auto scopeExit = makeScopeExit([completionHandler = WTFMove(completionHandler)]() mutable {
     240                completionHandler();
     241            });
     242            if (isContextStopped())
     243                return;
     244
     245            if (!privateStream) {
     246                RELEASE_LOG(MediaStream, "UserMediaRequest::allow failed to create media stream!");
     247                deny(MediaAccessDenialReason::HardwareError);
     248                return;
     249            }
     250
     251            auto& document = downcast<Document>(*m_scriptExecutionContext);
     252            privateStream->monitorOrientation(document.orientationNotifier());
     253
     254            auto stream = MediaStream::create(document, privateStream.releaseNonNull());
     255            stream->startProducingData();
     256
     257            if (!isMediaStreamCorrectlyStarted(stream)) {
     258                deny(MediaAccessDenialReason::HardwareError);
     259                return;
     260            }
     261
     262            ASSERT(document.isCapturing());
     263            stream->document()->setHasCaptureMediaStreamTrack();
     264            m_promise->resolve(WTFMove(stream));
     265        };
     266
     267        auto& document = downcast<Document>(*scriptExecutionContext());
     268        document.setDeviceIDHashSalt(deviceIdentifierHashSalt);
     269
     270        RealtimeMediaSourceCenter::singleton().createMediaStream(document.logger(), WTFMove(callback), WTFMove(deviceIdentifierHashSalt), WTFMove(audioDevice), WTFMove(videoDevice), m_request);
     271
     272        if (!m_scriptExecutionContext)
    238273            return;
    239274
    240         if (!privateStream) {
    241             RELEASE_LOG(MediaStream, "UserMediaRequest::allow failed to create media stream!");
    242             deny(MediaAccessDenialReason::HardwareError);
    243             return;
    244         }
    245 
    246         auto& document = downcast<Document>(*m_scriptExecutionContext);
    247         privateStream->monitorOrientation(document.orientationNotifier());
    248 
    249         auto stream = MediaStream::create(document, privateStream.releaseNonNull());
    250         stream->startProducingData();
    251 
    252         if (!isMediaStreamCorrectlyStarted(stream)) {
    253             deny(MediaAccessDenialReason::HardwareError);
    254             return;
    255         }
    256 
    257         ASSERT(document.isCapturing());
    258         stream->document()->setHasCaptureMediaStreamTrack();
    259         m_promise->resolve(WTFMove(stream));
    260     };
    261 
    262     auto& document = downcast<Document>(*scriptExecutionContext());
    263     document.setDeviceIDHashSalt(deviceIdentifierHashSalt);
    264 
    265     RealtimeMediaSourceCenter::singleton().createMediaStream(document.logger(), WTFMove(callback), WTFMove(deviceIdentifierHashSalt), WTFMove(audioDevice), WTFMove(videoDevice), m_request);
    266 
    267     if (!m_scriptExecutionContext)
    268         return;
    269 
    270275#if ENABLE(WEB_RTC)
    271     if (auto* page = document.page())
    272         page->rtcController().disableICECandidateFilteringForDocument(document);
     276        if (auto* page = document.page())
     277            page->rtcController().disableICECandidateFilteringForDocument(document);
    273278#endif
     279    });
    274280}
    275281
     
    319325    }
    320326
    321     if (!message.isEmpty())
    322         m_promise->reject(code, message);
    323     else
    324         m_promise->reject(code);
     327    document()->eventLoop().queueTask(TaskSource::UserInteraction, *document(), [this, protectedThis = makeRef(*this), code, message]() mutable {
     328        if (!message.isEmpty())
     329            m_promise->reject(code, message);
     330        else
     331            m_promise->reject(code);
     332    });
    325333}
    326334
     
    335343{
    336344    return "UserMediaRequest";
    337 }
    338 
    339 // FIXME: This should never prevent entering the back/forward cache.
    340 bool UserMediaRequest::shouldPreventEnteringBackForwardCache_DEPRECATED() const
    341 {
    342     return hasPendingActivity();
    343345}
    344346
  • trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.h

    r251244 r251746  
    8686    void stop() final;
    8787    const char* activeDOMObjectName() const final;
    88     bool shouldPreventEnteringBackForwardCache_DEPRECATED() const final;
    8988
    9089    void mediaStreamDidFail(RealtimeMediaSource::Type);
Note: See TracChangeset for help on using the changeset viewer.