<html>
  <body>
    <script type="text/javascript">
      // Since promises run asynchronously, use the pages title to keep track
      // of the result.
      function setResultInTitle(title) {
        if (title == "" || title == "success" || title == "TypeError" ||
            title == "Unsupported keySystem or supportedConfigurations.") {
          document.title = title;
        } else {
          console.log("Unexpected result: " + title);
          document.title = "unexpected result";
        }
      };

      function capabilitiesToString(array) {
        var result = [];
        array.forEach(function(v) {
          result.push(v.contentType);
        });
        return '[ ' + result.join(', ') + ' ]';
      }

      // Compares 2 arrays of MediaKeySystemMediaCapability, comparing only
      // |contentType|. This assumes the order is the same. Returns "success"
      // if they match, an error message if they don't.
      function verifyCapabilitiesAreEqual(actual, expected) {
        if (actual.length != expected.length)
          return 'mismatched lengths; not all capabilities are supported. Got ' +
              capabilitiesToString(actual) + ', expected ' +
              capabilitiesToString(expected);
        for (var i = 0; i < actual.length; i++) {
          // Only compare |contentType|. Other properties are ignored.
          if (actual[i].contentType !== expected[i].contentType)
            return actual[i].contentType + " does not match " +
                   expected[i].contentType + " at index " + i;
        }
        return "success";
      }

      // Calls navigator.requestMediaKeySystemAccess() using the supplied codec
      // lists, and then verifies the result. Sets page title when done.
      function requestMediaKeySystemAccessAndVerifyConfiguration(
          keySystem, initDataType, audioCapabilities, videoCapabilities,
          sessionType) {
        var configuration = {
            initDataTypes: [initDataType],
            audioCapabilities: [],
            videoCapabilities: [],
            sessionTypes: [sessionType]
        };
        if (audioCapabilities !== null) {
          configuration.audioCapabilities = audioCapabilities;
        }
        if (videoCapabilities !== null) {
          configuration.videoCapabilities = videoCapabilities;
        }
        // This is using promises which will run asynchronously.
        navigator.requestMediaKeySystemAccess(keySystem, [configuration])
            .then(function(response) {
              var allowedConfig = response.getConfiguration();
              if (allowedConfig.initDataTypes.length !== 1) {
                setResultInTitle("initDataType length mismatch");
                return;
              }
              if (allowedConfig.initDataTypes[0] !== initDataType) {
                setResultInTitle("initDataType returned " +
                                 allowedConfig.initDataTypes[0] +
                                 ", expected " + initDataType);
                return;
              }
              if (audioCapabilities !== null) {
                var result =
                    verifyCapabilitiesAreEqual(allowedConfig.audioCapabilities,
                                            configuration.audioCapabilities);
                if (result !== "success") {
                  setResultInTitle(result);
                  return;
                }
              } else if (allowedConfig.audioCapabilities.length > 0) {
                setResultInTitle(
                    'audioCapabilities set when none expected, got ' +
                    capabilitiesToString(allowedConfig.audioCapabilities));
                return;
              }
              if (videoCapabilities !== null) {
                setResultInTitle(
                    verifyCapabilitiesAreEqual(allowedConfig.videoCapabilities,
                                            configuration.videoCapabilities));
                return;
              } else if (allowedConfig.videoCapabilities.length > 0) {
                setResultInTitle(
                    'videoCapabilities set when none expected, got ' +
                    capabilitiesToString(allowedConfig.videoCapabilities));
                return;
              }
              setResultInTitle("success");
            })
            .catch(function(err) {
              setResultInTitle((err.name == 'TypeError') ? err.name : err.message);
            });
      };

      function checkKeySystemWithMediaMimeType(keySystem, initDataType,
          audioCapabilities, videoCapabilities, sessionType) {
        setResultInTitle("");
        requestMediaKeySystemAccessAndVerifyConfiguration(keySystem,
            initDataType, audioCapabilities, videoCapabilities, sessionType);
      };
    </script>
  </body>
</html>
