⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 236465 in webkit


Ignore:
Timestamp:
Sep 25, 2018, 11:37:29 AM (8 years ago)
Author:
eric.carlson@apple.com
Message:

[MediaStream] Update constraints supported by getDisplayMedia
​https://bugs.webkit.org/show_bug.cgi?id=189930

Reviewed by Youenn Fablet.

Source/WebCore:

No new tests, updated http/tests/media/media-stream/get-display-media-prompt.html.

  • Modules/mediastream/MediaDevices.cpp:

(WebCore::MediaDevices::getDisplayMedia const): Ignore audio constraints.

  • Modules/mediastream/UserMediaRequest.cpp:

(WebCore::hasInvalidGetDisplayMediaConstraint): Check for invalid constraints.
(WebCore::UserMediaRequest::start): Check for invalid constraints.
(WebCore::UserMediaRequest::deny): Support new error.

  • Modules/mediastream/UserMediaRequest.h:
  • platform/mediastream/RealtimeMediaSourceCenter.cpp:

(WebCore::RealtimeMediaSourceCenter::validateRequestConstraints):

LayoutTests:

  • http/tests/media/media-stream/get-display-media-prompt-expected.txt:
  • http/tests/media/media-stream/get-display-media-prompt.html:
Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r236461 r236465  
     12018-09-25  Eric Carlson  <eric.carlson@apple.com>
     2
     3        [MediaStream] Update constraints supported by getDisplayMedia
     4        https://bugs.webkit.org/show_bug.cgi?id=189930
     5
     6        Reviewed by Youenn Fablet.
     7
     8        * http/tests/media/media-stream/get-display-media-prompt-expected.txt:
     9        * http/tests/media/media-stream/get-display-media-prompt.html:
     10
    1112018-09-25  Ryan Haddad  <ryanhaddad@apple.com>
    212
  • trunk/LayoutTests/http/tests/media/media-stream/get-display-media-prompt-expected.txt

    r226412 r236465  
    66PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 0
    77
    8 ** Request an audio-only stream, the user should be prompted **
    9 PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 1
    10 PASS stream.getAudioTracks().length is 1
    11 PASS stream.getVideoTracks().length is 0
     8** Request an audio-only stream, the user should not be prompted **
     9PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 0
     10PASS stream is undefined.
     11PASS err instanceof Error  is true
     12PASS err.name is "TypeError"
    1213
    1314** Request an video-only stream, the user should be prompted **
     15PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 1
     16PASS stream.getAudioTracks().length is 0
     17PASS stream.getVideoTracks().length is 1
     18
     19** Request a stream with audio and video, the user should be prompted but no audio track should be created **
    1420PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 2
    1521PASS stream.getAudioTracks().length is 0
    1622PASS stream.getVideoTracks().length is 1
    1723
    18 ** Request a stream with audio and video, the user should be prompted **
     24** Request a stream with 'max' constraints, the user should not be prompted **
     25PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 2
     26PASS stream is undefined.
     27PASS err instanceof Error  is true
     28PASS err.name is "TypeError"
     29
     30** Request a stream with 'min' constraints, the user should not be prompted **
     31PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 2
     32PASS stream is undefined.
     33PASS err instanceof Error  is true
     34PASS err.name is "TypeError"
     35
     36** Request a stream with 'advanced' constraints, the user should not be prompted **
     37PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 2
     38PASS stream is undefined.
     39PASS err instanceof Error  is true
     40PASS err.name is "TypeError"
     41
     42** Request a stream with valid constraints, the user should be prompted **
    1943PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 3
    20 PASS stream.getAudioTracks().length is 1
     44PASS stream.getAudioTracks().length is 0
    2145PASS stream.getVideoTracks().length is 1
    2246
    23 ** Request a stream with invalid constraints, the user should not be prompted **
    24 PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 3
    25 PASS stream is null
    26 PASS err instanceof Error  is true
    27 PASS err.name is "InvalidAccessError"
     47** Request a stream with an exact audio constraint, it should be ignored **
     48PASS numberOfTimesGetUserMediaPromptHasBeenCalled() is 4
     49PASS stream.getAudioTracks().length is 0
     50PASS stream.getVideoTracks().length is 1
    2851
    2952PASS successfullyParsed is true
  • trunk/LayoutTests/http/tests/media/media-stream/get-display-media-prompt.html

    r226412 r236465  
    1919   
    2020    async function promptForAudioOnly() {
    21         debug("<br>** Request an audio-only stream, the user should be prompted **");
    22         stream = await navigator.mediaDevices.getDisplayMedia({ audio: true });
    23         shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "1");
    24         shouldBe("stream.getAudioTracks().length", "1");
    25         shouldBe("stream.getVideoTracks().length", "0");
     21        debug("<br>** Request an audio-only stream, the user should not be prompted **");
     22        stream = await navigator.mediaDevices.getDisplayMedia({ audio: true })
     23            .catch((e) => { err = e; });
     24        shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "0");
     25        shouldBeUndefined("stream");
     26        shouldBeTrue("err instanceof Error ");
     27        shouldBeEqualToString("err.name", "TypeError");
    2628    }
    2729
    … …  
    2931        debug("<br>** Request an video-only stream, the user should be prompted **");
    3032        stream = await navigator.mediaDevices.getDisplayMedia({ video: true });
    31         shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "2");
     33        shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "1");
    3234        shouldBe("stream.getAudioTracks().length", "0");
    3335        shouldBe("stream.getVideoTracks().length", "1");
    … …  
    3537
    3638    async function promptForAudioAndVideo() {
    37         debug("<br>** Request a stream with audio and video, the user should be prompted **");
     39        debug("<br>** Request a stream with audio and video, the user should be prompted but no audio track should be created **");
    3840        stream = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: true });
    39         shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "3");
    40         shouldBe("stream.getAudioTracks().length", "1");
     41        shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "2");
     42        shouldBe("stream.getAudioTracks().length", "0");
    4143        shouldBe("stream.getVideoTracks().length", "1");
    4244    }
    4345   
    44     async function promptWithMediaTrackConstraints() {
    45         debug("<br>** Request a stream with invalid constraints, the user should not be prompted **");
     46    async function promptWithExactVideoConstraints() {
     47        debug("<br>** Request a stream with 'max' constraints, the user should not be prompted **");
     48
    4649        stream = null;
    47         try {
    48             stream = await navigator.mediaDevices.getDisplayMedia({ video: {width: {exact: 640}, height: {exact: 480}} });
    49         } catch (e) {
    50             err = e;
    51         }
     50        stream = await navigator.mediaDevices.getDisplayMedia({ video: {width: {exact: 640}, height: {exact: 480}} })
     51            .catch((e) => { err = e; });
     52       
     53        shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "2");
     54        shouldBeUndefined("stream");
     55        shouldBeTrue("err instanceof Error ");
     56        shouldBeEqualToString("err.name", "TypeError");
     57    }
     58
     59    async function promptWithMinVideoConstraints() {
     60        debug("<br>** Request a stream with 'min' constraints, the user should not be prompted **");
     61
     62        stream = null;
     63        stream = await navigator.mediaDevices.getDisplayMedia({ video: {width: {min: 640}, height: {min: 480}} })
     64            .catch((e) => { err = e; });
     65        shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "2");
     66        shouldBeUndefined("stream");
     67        shouldBeTrue("err instanceof Error ");
     68        shouldBeEqualToString("err.name", "TypeError");
     69    }
     70
     71    async function promptWithAdvancedVideoConstraints() {
     72        debug("<br>** Request a stream with 'advanced' constraints, the user should not be prompted **");
     73
     74        stream = null;
     75        stream = await navigator.mediaDevices.getDisplayMedia({ video: { width: 640, height: 480, advanced: [ { width: 1920, height: 1280 } ] } })
     76            .catch((e) => { err = e; });
     77        shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "2");
     78        shouldBeUndefined("stream");
     79        shouldBeTrue("err instanceof Error ");
     80        shouldBeEqualToString("err.name", "TypeError");
     81    }
     82
     83    async function promptWithValidVideoConstraints() {
     84        debug("<br>** Request a stream with valid constraints, the user should be prompted **");
     85
     86        stream = null;
     87        stream = await navigator.mediaDevices.getDisplayMedia({ video: {width: 640, height: 480} })
     88            .catch((e) => { err = e; });
    5289       
    5390        shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "3");
    54         shouldBeNull("stream");
    55         shouldBeTrue("err instanceof Error ");
    56         shouldBeEqualToString("err.name", "InvalidAccessError");
     91        shouldBe("stream.getAudioTracks().length", "0");
     92        shouldBe("stream.getVideoTracks().length", "1");
    5793    }
    5894
     95    async function promptWithInvalidAudioConstraint() {
     96        debug("<br>** Request a stream with an exact audio constraint, it should be ignored **");
     97
     98        stream = null;
     99        stream = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: { volume: { exact: 0.5 } } });
     100        shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "4");
     101        shouldBe("stream.getAudioTracks().length", "0");
     102        shouldBe("stream.getVideoTracks().length", "1");
     103    }
     104   
    59105    (async function() {
    60106        description('Test basic getDisplayMedia prompting behavior');
    … …  
    69115        await promptForVideoOnly();
    70116        await promptForAudioAndVideo();
    71         await promptWithMediaTrackConstraints();
     117        await promptWithExactVideoConstraints();
     118        await promptWithMinVideoConstraints();
     119        await promptWithAdvancedVideoConstraints();
     120        await promptWithValidVideoConstraints();
     121        await promptWithInvalidAudioConstraint();
    72122
    73123        debug("");
  • trunk/Source/WebCore/ChangeLog

    r236462 r236465  
     12018-09-25  Eric Carlson  <eric.carlson@apple.com>
     2
     3        [MediaStream] Update constraints supported by getDisplayMedia
     4        https://bugs.webkit.org/show_bug.cgi?id=189930
     5
     6        Reviewed by Youenn Fablet.
     7
     8        No new tests, updated http/tests/media/media-stream/get-display-media-prompt.html.
     9
     10        * Modules/mediastream/MediaDevices.cpp:
     11        (WebCore::MediaDevices::getDisplayMedia const): Ignore audio constraints.
     12
     13        * Modules/mediastream/UserMediaRequest.cpp:
     14        (WebCore::hasInvalidGetDisplayMediaConstraint): Check for invalid constraints.
     15        (WebCore::UserMediaRequest::start): Check for invalid constraints.
     16        (WebCore::UserMediaRequest::deny): Support new error.
     17        * Modules/mediastream/UserMediaRequest.h:
     18
     19        * platform/mediastream/RealtimeMediaSourceCenter.cpp:
     20        (WebCore::RealtimeMediaSourceCenter::validateRequestConstraints):
     21
    1222018-09-25  Xabier Rodriguez Calvar  <calvaris@igalia.com>
    223
  • trunk/Source/WebCore/Modules/mediastream/MediaDevices.cpp

    r235438 r236465  
    121121        return Exception { InvalidStateError };
    122122
    123     auto request = UserMediaRequest::create(*document, { MediaStreamRequest::Type::DisplayMedia, createMediaConstraints(constraints.audio), createMediaConstraints(constraints.video) }, WTFMove(promise));
     123    auto request = UserMediaRequest::create(*document, { MediaStreamRequest::Type::DisplayMedia, { }, createMediaConstraints(constraints.video) }, WTFMove(promise));
    124124    if (request)
    125125        request->start();
  • trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.cpp

    r236422 r236465  
    157157}
    158158
     159static bool hasInvalidGetDisplayMediaConstraint(const MediaConstraints& constraints)
     160{
     161    // https://w3c.github.io/mediacapture-screen-share/#navigator-additions
     162    // 1. Let constraints be the method's first argument.
     163    // 2. For each member present in constraints whose value, value, is a dictionary, run the following steps:
     164    //     1. If value contains a member named advanced, return a promise rejected with a newly created TypeError.
     165    //     2. If value contains a member which in turn is a dictionary containing a member named either min or
     166    //        exact, return a promise rejected with a newly created TypeError.
     167    if (!constraints.isValid)
     168        return false;
     169
     170    if (!constraints.advancedConstraints.isEmpty())
     171        return true;
     172
     173    bool invalid = false;
     174    constraints.mandatoryConstraints.filter([&invalid] (const MediaConstraint& constraint) mutable {
     175        switch (constraint.constraintType()) {
     176        case MediaConstraintType::Width:
     177        case MediaConstraintType::Height: {
     178            auto& intConstraint = downcast<IntConstraint>(constraint);
     179            int value;
     180            invalid = intConstraint.getExact(value) || intConstraint.getMin(value);
     181            break;
     182        }
     183
     184        case MediaConstraintType::AspectRatio:
     185        case MediaConstraintType::FrameRate: {
     186            auto& doubleConstraint = downcast<DoubleConstraint>(constraint);
     187            double value;
     188            invalid = doubleConstraint.getExact(value) || doubleConstraint.getMin(value);
     189            break;
     190        }
     191
     192        case MediaConstraintType::DisplaySurface:
     193        case MediaConstraintType::LogicalSurface: {
     194            auto& boolConstraint = downcast<BooleanConstraint>(constraint);
     195            bool value;
     196            invalid = boolConstraint.getExact(value);
     197            break;
     198        }
     199
     200        case MediaConstraintType::FacingMode:
     201        case MediaConstraintType::DeviceId:
     202        case MediaConstraintType::GroupId: {
     203            auto& stringConstraint = downcast<StringConstraint>(constraint);
     204            Vector<String> values;
     205            invalid = stringConstraint.getExact(values);
     206            break;
     207        }
     208
     209        case MediaConstraintType::SampleRate:
     210        case MediaConstraintType::SampleSize:
     211        case MediaConstraintType::Volume:
     212        case MediaConstraintType::EchoCancellation:
     213            // Ignored.
     214            break;
     215
     216        case MediaConstraintType::Unknown:
     217            ASSERT_NOT_REACHED();
     218            break;
     219        }
     220
     221        return invalid;
     222    });
     223
     224    return invalid;
     225}
     226
    159227void UserMediaRequest::start()
    160228{
    … …  
    166234
    167235    if (m_request.type == MediaStreamRequest::Type::DisplayMedia) {
    168         // https://w3c.github.io/mediacapture-screen-share/#constraints
    169         // 5.2 Constraining Display Surface Selection
    170         // The getDisplayMedia function does not permit the use of constraints for selection of a source as described
    171         // in the getUserMedia() algorithm. Prior to invoking the getUserMedia() algorithm, if either of the video
    172         // and audio attributes are set to a MediaTrackConstraints value (as opposed to being absent or set to a
    173         // Boolean value), reject the promise with a InvalidAccessError and abort.
    174         if (m_request.videoConstraints.isValid && !(m_request.videoConstraints.mandatoryConstraints.isEmpty() && m_request.videoConstraints.advancedConstraints.isEmpty())) {
    175             deny(MediaAccessDenialReason::InvalidAccess);
    176             return;
    177         }
    178 
    179         if (m_request.audioConstraints.isValid && !(m_request.audioConstraints.mandatoryConstraints.isEmpty() && m_request.audioConstraints.advancedConstraints.isEmpty())) {
    180             deny(MediaAccessDenialReason::InvalidAccess);
     236        if (hasInvalidGetDisplayMediaConstraint(m_request.videoConstraints)) {
     237            deny(MediaAccessDenialReason::IllegalConstraint);
    181238            return;
    182239        }
    … …  
    266323    ExceptionCode code;
    267324    switch (reason) {
     325    case MediaAccessDenialReason::IllegalConstraint:
     326        RELEASE_LOG(MediaStream, "UserMediaRequest::deny - invalid constraints");
     327        code = TypeError;
     328        break;
    268329    case MediaAccessDenialReason::NoConstraints:
    269330        RELEASE_LOG(MediaStream, "UserMediaRequest::deny - no constraints");
  • trunk/Source/WebCore/Modules/mediastream/UserMediaRequest.h

    r233425 r236465  
    5757    WEBCORE_EXPORT void allow(CaptureDevice&& audioDevice, CaptureDevice&& videoDevice, String&& deviceIdentifierHashSalt);
    5858
    59     enum MediaAccessDenialReason { NoConstraints, UserMediaDisabled, NoCaptureDevices, InvalidConstraint, HardwareError, PermissionDenied, InvalidAccess, OtherFailure };
     59    enum MediaAccessDenialReason { NoConstraints, UserMediaDisabled, NoCaptureDevices, InvalidConstraint, HardwareError, PermissionDenied, InvalidAccess, IllegalConstraint, OtherFailure };
    6060    WEBCORE_EXPORT void deny(MediaAccessDenialReason, const String& errorMessage = emptyString());
    6161
  • trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp

    r235086 r236465  
    208208}
    209209
     210void RealtimeMediaSourceCenter::getDisplayMediaDevices(const MediaStreamRequest& request, Vector<DeviceInfo>& diaplayDeviceInfo, String& firstInvalidConstraint)
     211{
     212    if (!request.videoConstraints.isValid)
     213        return;
     214
     215    String invalidConstraint;
     216    for (auto& device : displayCaptureDeviceManager().captureDevices()) {
     217        if (!device.enabled())
     218            return;
     219
     220        auto sourceOrError = videoFactory().createVideoCaptureSource(device, { });
     221        if (sourceOrError && sourceOrError.captureSource->supportsConstraints(request.videoConstraints, invalidConstraint))
     222            diaplayDeviceInfo.append({sourceOrError.captureSource->fitnessScore(), device});
     223
     224        if (!invalidConstraint.isEmpty() && firstInvalidConstraint.isEmpty())
     225            firstInvalidConstraint = invalidConstraint;
     226    }
     227}
     228
     229void RealtimeMediaSourceCenter::getUserMediaDevices(const MediaStreamRequest& request, Vector<DeviceInfo>& audioDeviceInfo, Vector<DeviceInfo>& videoDeviceInfo, String& firstInvalidConstraint)
     230{
     231    String invalidConstraint;
     232    if (request.audioConstraints.isValid) {
     233        for (auto& device : audioCaptureDeviceManager().captureDevices()) {
     234            if (!device.enabled())
     235                continue;
     236
     237            auto sourceOrError = audioFactory().createAudioCaptureSource(device, { });
     238            if (sourceOrError && sourceOrError.captureSource->supportsConstraints(request.audioConstraints, invalidConstraint))
     239                audioDeviceInfo.append({sourceOrError.captureSource->fitnessScore(), device});
     240
     241            if (!invalidConstraint.isEmpty() && firstInvalidConstraint.isEmpty())
     242                firstInvalidConstraint = invalidConstraint;
     243        }
     244    }
     245
     246    if (request.videoConstraints.isValid) {
     247        for (auto& device : videoCaptureDeviceManager().captureDevices()) {
     248            if (!device.enabled())
     249                continue;
     250
     251            auto sourceOrError = videoFactory().createVideoCaptureSource(device, { });
     252            if (sourceOrError && sourceOrError.captureSource->supportsConstraints(request.videoConstraints, invalidConstraint))
     253                videoDeviceInfo.append({sourceOrError.captureSource->fitnessScore(), device});
     254
     255            if (!invalidConstraint.isEmpty() && firstInvalidConstraint.isEmpty())
     256                firstInvalidConstraint = invalidConstraint;
     257        }
     258    }
     259}
     260
    210261void RealtimeMediaSourceCenter::validateRequestConstraints(ValidConstraintsHandler&& validHandler, InvalidConstraintsHandler&& invalidHandler, const MediaStreamRequest& request, String&& deviceIdentifierHashSalt)
    211262{
    212     struct DeviceInfo {
    213         unsigned fitnessScore;
    214         CaptureDevice device;
    215     };
    216 
    217263    struct {
    218264        bool operator()(const DeviceInfo& a, const DeviceInfo& b)
    … …  
    224270    Vector<DeviceInfo> audioDeviceInfo;
    225271    Vector<DeviceInfo> videoDeviceInfo;
    226 
    227272    String firstInvalidConstraint;
    228     for (auto& device : getMediaStreamDevices()) {
    229         if (!device.enabled())
    230             continue;
    231 
    232         String invalidConstraint;
    233         CaptureSourceOrError sourceOrError;
    234         switch (device.type()) {
    235         case CaptureDevice::DeviceType::Camera: {
    236             if (request.type != MediaStreamRequest::Type::UserMedia || !request.videoConstraints.isValid)
    237                 continue;
    238 
    239             auto sourceOrError = videoFactory().createVideoCaptureSource(device, { });
    240             if (sourceOrError && sourceOrError.captureSource->supportsConstraints(request.videoConstraints, invalidConstraint))
    241                 videoDeviceInfo.append({sourceOrError.captureSource->fitnessScore(), device});
    242             break;
    243         }
    244         case CaptureDevice::DeviceType::Microphone:
    245             if (request.audioConstraints.isValid) {
    246                 auto sourceOrError = audioFactory().createAudioCaptureSource(device, { });
    247                 if (sourceOrError && sourceOrError.captureSource->supportsConstraints(request.audioConstraints, invalidConstraint))
    248                     audioDeviceInfo.append({sourceOrError.captureSource->fitnessScore(), device});
    249             }
    250             break;
    251         case CaptureDevice::DeviceType::Screen:
    252         case CaptureDevice::DeviceType::Application:
    253         case CaptureDevice::DeviceType::Window:
    254         case CaptureDevice::DeviceType::Browser: {
    255             if (request.type != MediaStreamRequest::Type::DisplayMedia)
    256                 continue;
    257             ASSERT(request.audioConstraints.mandatoryConstraints.isEmpty());
    258             ASSERT(request.videoConstraints.advancedConstraints.isEmpty());
    259             if (!request.videoConstraints.isValid || !request.videoConstraints.advancedConstraints.isEmpty() || !request.videoConstraints.mandatoryConstraints.isEmpty())
    260                 continue;
    261 
    262             auto sourceOrError = videoFactory().createVideoCaptureSource(device, { });
    263             if (sourceOrError && sourceOrError.captureSource->supportsConstraints(request.videoConstraints, invalidConstraint))
    264                 videoDeviceInfo.append({sourceOrError.captureSource->fitnessScore(), device});
    265             break;
    266         }
    267         case CaptureDevice::DeviceType::Unknown:
    268             ASSERT_NOT_REACHED();
    269             break;
    270         }
    271 
    272         if (!invalidConstraint.isEmpty() && firstInvalidConstraint.isEmpty())
    273             firstInvalidConstraint = invalidConstraint;
    274     }
     273
     274    if (request.type == MediaStreamRequest::Type::DisplayMedia)
     275        getDisplayMediaDevices(request, videoDeviceInfo, firstInvalidConstraint);
     276    else
     277        getUserMediaDevices(request, audioDeviceInfo, videoDeviceInfo, firstInvalidConstraint);
    275278
    276279    if ((request.audioConstraints.isValid && audioDeviceInfo.isEmpty()) || (request.videoConstraints.isValid && videoDeviceInfo.isEmpty())) {
  • trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h

    r235086 r236465  
    101101    CaptureDeviceManager* m_videoCaptureDeviceManager { nullptr };
    102102
     103private:
     104    struct DeviceInfo {
     105        unsigned fitnessScore;
     106        CaptureDevice device;
     107    };
     108
     109    void getDisplayMediaDevices(const MediaStreamRequest&, Vector<DeviceInfo>&, String&);
     110    void getUserMediaDevices(const MediaStreamRequest&, Vector<DeviceInfo>& audioDevices, Vector<DeviceInfo>& videoDevices, String&);
     111
    103112    WTF::Function<void()> m_deviceChangedObserver;
    104113};
Note: See TracChangeset for help on using the changeset viewer.