<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Mute video and audio tracks independently, make sure page state updates correctly.</title>
    <script src="../../resources/testharness.js"></script>
    <script src="../../resources/testharnessreport.js"></script>
    <script>

    if (window.testRunner)
        testRunner.setUserMediaPermission(true);

    function waitForPageStateChange(numberOfTries, originalState, resolve, reject)
    {
        let newState = internals.pageMediaState();
        if (newState != originalState) {
            resolve(newState);
            return;
        }

        if (numberOfTries <= 0) {
            reject('Page state did not change in time.');
            return;
        }

        setTimeout(() => { waitForPageStateChange(--numberOfTries, originalState, resolve, reject); }, 10);
    }

    function testTrack(track, title)
    {
        promise_test((test) => {
            return new Promise((resolve, reject) => {
                let isVideo = track.kind == "video";
                if (window.internals) {
                    assert_false(internals.pageMediaState().includes('HasMutedVideoCaptureDevice'));
                    assert_false(internals.pageMediaState().includes('HasMutedAudioCaptureDevice'));
                }

                track.onunmute = () => reject("Got 'unmute' event unexpectedly!");
                track.onmute = () => {
                    new Promise((innerResolve, innerReject) => {
                        waitForPageStateChange(10, internals.pageMediaState(), innerResolve, innerReject)
                    }).then((pageMediaState) => {

                        track.onunmute = (evt) => {
                            waitForPageStateChange(10, internals.pageMediaState(), resolve, reject)
                        }

                        if (window.internals) {
                            assert_true(pageMediaState.includes(isVideo ? 'HasMutedVideoCaptureDevice' : 'HasMutedAudioCaptureDevice'));
                            assert_false(pageMediaState.includes(isVideo ? 'HasMutedAudioCaptureDevice' : 'HasMutedVideoCaptureDevice'));
                            assert_true(pageMediaState.includes(isVideo ? 'HasActiveAudioCaptureDevice' : 'HasActiveVideoCaptureDevice'));
                            assert_false(pageMediaState.includes(isVideo ? 'HasActiveVideoCaptureDevice' : 'HasActiveAudioCaptureDevice'));
                            internals.setMediaStreamTrackMuted(track, false)
                        }
                    })
                }

                if (window.internals)
                    internals.setMediaStreamTrackMuted(track, true);
                setTimeout(() => reject("Muted state did not change in .5 second"), 500);
            });
        }, title);
    }

    promise_test((test) => {
        return navigator.mediaDevices.getUserMedia({ video: true, audio: true})
            .then((stream) => {
                testTrack(stream.getVideoTracks()[0], "Mute video track only");
                testTrack(stream.getAudioTracks()[0], "Mute audio track only");
            });
    }, "Create stream");


    </script>
</head>
<body>
</body>
</html>
