static async probeSupport() {
    const testKeySystems = [
      'org.w3.clearkey',
      'com.widevine.alpha',
      'com.widevine.alpha.experiment', // Widevine L1 in Windows
      'com.microsoft.playready',
      'com.microsoft.playready.hardware',
      'com.microsoft.playready.recommendation',
      'com.microsoft.playready.recommendation.3000',
      'com.microsoft.playready.recommendation.3000.clearlead',
      'com.chromecast.playready',
      'com.apple.fps.1_0',
      'com.apple.fps',
      'com.huawei.wiseplay',
    ];

    if (!shaka.drm.DrmUtils.isBrowserSupported()) {
      const result = {};
      for (const keySystem of testKeySystems) {
        result[keySystem] = null;
      }
      return result;
    }

    const hdcpVersions = [
      '1.0',
      '1.1',
      '1.2',
      '1.3',
      '1.4',
      '2.0',
      '2.1',
      '2.2',
      '2.3',
    ];

    const widevineRobustness = [
      'SW_SECURE_CRYPTO',
      'SW_SECURE_DECODE',
      'HW_SECURE_CRYPTO',
      'HW_SECURE_DECODE',
      'HW_SECURE_ALL',
    ];

    const playreadyRobustness = [
      '150',
      '2000',
      '3000',
    ];

    const testRobustness = {
      'com.widevine.alpha': widevineRobustness,
      'com.widevine.alpha.experiment': widevineRobustness,
      'com.microsoft.playready.recommendation': playreadyRobustness,
    };

    const basicVideoCapabilities = [
      {contentType: 'video/mp4; codecs="avc1.42E01E"'},
      {contentType: 'video/webm; codecs="vp8"'},
    ];

    const basicAudioCapabilities = [
      {contentType: 'audio/mp4; codecs="mp4a.40.2"'},
      {contentType: 'audio/webm; codecs="opus"'},
    ];

    const basicConfigTemplate = {
      videoCapabilities: basicVideoCapabilities,
      audioCapabilities: basicAudioCapabilities,
      initDataTypes: ['cenc', 'sinf', 'skd', 'keyids'],
    };

    const testEncryptionSchemes = [
      null,
      'cenc',
      'cbcs',
      'cbcs-1-9',
    ];

    /** @type {!Map<string, ?shaka.extern.DrmSupportType>} */
    const support = new Map();

    const device = shaka.device.DeviceFactory.getDevice();

    /**
     * @param {string} keySystem
     * @param {MediaKeySystemAccess} access
     * @return {!Promise}
     */
    const processMediaKeySystemAccess = async (keySystem, access) => {
      let mediaKeys;
      try {
        // Workaround: Our automated test lab runs Windows browsers under a
        // headless service.  In this environment, Firefox's CDMs seem to crash
        // when we create the CDM here.
        if (!device.createMediaKeysWhenCheckingSupport()) {
          // Reject this, since it crashes our tests.
          throw new Error('Suppressing Firefox Windows DRM in testing!');
        } else {
          // Otherwise, create the CDM.
          mediaKeys = await access.createMediaKeys();
        }
      } catch (error) {
        // In some cases, we can get a successful access object but fail to
        // create a MediaKeys instance.  When this happens, don't update the
        // support structure.  If a previous test succeeded, we won't overwrite
        // any of the results.
        return;
      }

      // If sessionTypes is missing, assume no support for persistent-license.
      const sessionTypes = access.getConfiguration().sessionTypes;
      let persistentState = sessionTypes ?
          sessionTypes.includes('persistent-license') : false;

      // Tizen 3.0 doesn't support persistent licenses, but reports that it
      // does.  It doesn't fail until you call update() with a license
      // response, which is way too late.
      // This is a work-around for #894.
      if (device.misreportsSupportForPersistentLicenses()) {
        persistentState = false;
      }

      const videoCapabilities = access.getConfiguration().videoCapabilities;
      const audioCapabilities = access.getConfiguration().audioCapabilities;

      let supportValue = {
        persistentState,
        encryptionSchemes: [],
        videoRobustnessLevels: [],
        audioRobustnessLevels: [],
        minHdcpVersions: [],
      };
      if (support.has(keySystem) && support.get(keySystem)) {
        // Update the existing non-null value.
        supportValue = support.get(keySystem);
      } else {
        // Set a new one.
        support.set(keySystem, supportValue);
      }

      // If the returned config doesn't mention encryptionScheme, the field
      // is not supported.  If installed, our polyfills should make sure this
      // doesn't happen.
      const returnedScheme = videoCapabilities[0].encryptionScheme;
      if (returnedScheme &&
          !supportValue.encryptionSchemes.includes(returnedScheme)) {
        supportValue.encryptionSchemes.push(returnedScheme);
      }

      const videoRobustness = videoCapabilities[0].robustness;
      if (videoRobustness &&
          !supportValue.videoRobustnessLevels.includes(videoRobustness)) {
        supportValue.videoRobustnessLevels.push(videoRobustness);
      }

      const audioRobustness = audioCapabilities[0].robustness;
      if (audioRobustness &&
          !supportValue.audioRobustnessLevels.includes(audioRobustness)) {
        supportValue.audioRobustnessLevels.push(audioRobustness);
      }

      if ('getStatusForPolicy' in mediaKeys) {
        const promises = [];
        for (const hdcpVersion of hdcpVersions) {
          if (supportValue.minHdcpVersions.includes(hdcpVersion)) {
            continue;
          }
          promises.push(mediaKeys.getStatusForPolicy({
            minHdcpVersion: hdcpVersion,
          }).then((status) => {
            if (status == 'usable' &&
                !supportValue.minHdcpVersions.includes(hdcpVersion)) {
              supportValue.minHdcpVersions.push(hdcpVersion);
            }
          }));
        }
        await Promise.all(promises);
      }
    };

    const testSystemEme = async (keySystem, encryptionScheme,
        videoRobustness, audioRobustness) => {
      try {
        const basicConfig =
            shaka.util.ObjectUtils.cloneObject(basicConfigTemplate);
        for (const cap of basicConfig.videoCapabilities) {
          cap.encryptionScheme = encryptionScheme;
          cap.robustness = videoRobustness;
        }
        for (const cap of basicConfig.audioCapabilities) {
          cap.encryptionScheme = encryptionScheme;
          cap.robustness = audioRobustness;
        }

        const offlineConfig = shaka.util.ObjectUtils.cloneObject(basicConfig);
        offlineConfig.persistentState = 'required';
        offlineConfig.sessionTypes = ['persistent-license'];

        const configs = [offlineConfig, basicConfig];
        // On some (Android) WebView environments,
        // requestMediaKeySystemAccess will
        // not resolve or reject, at least if RESOURCE_PROTECTED_MEDIA_ID
        // is not set.  This is a workaround for that issue.
        const TIMEOUT_FOR_CHECK_ACCESS_IN_SECONDS = 5;
        let access;
        const device = shaka.device.DeviceFactory.getDevice();
        if (device.getDeviceType() == shaka.device.IDevice.DeviceType.MOBILE) {
          access =
            await shaka.util.Functional.promiseWithTimeout(
                TIMEOUT_FOR_CHECK_ACCESS_IN_SECONDS,
                navigator.requestMediaKeySystemAccess(keySystem, configs),
            );
        } else {
          access =
              await navigator.requestMediaKeySystemAccess(keySystem, configs);
        }
        await processMediaKeySystemAccess(keySystem, access);
      } catch (error) {}  // Ignore errors.
    };

    const testSystemMcap = async (keySystem, encryptionScheme,
        videoRobustness, audioRobustness) => {
      try {
        const decodingConfig = {
          type: 'media-source',
          video: {
            contentType: basicVideoCapabilities[0].contentType,
            width: 640,
            height: 480,
            bitrate: 1,
            framerate: 1,
          },
          audio: {
            contentType: basicAudioCapabilities[0].contentType,
            channels: 2,
            bitrate: 1,
            samplerate: 1,
          },
          keySystemConfiguration: {
            keySystem,
            video: {
              encryptionScheme,
              robustness: videoRobustness,
            },
            audio: {
              encryptionScheme,
              robustness: audioRobustness,
            },
          },
        };
        // On some (Android) WebView environments, decodingInfo will
        // not resolve or reject, at least if RESOURCE_PROTECTED_MEDIA_ID
        // is not set.  This is a workaround for that issue.
        const TIMEOUT_FOR_DECODING_INFO_IN_SECONDS = 5;
        let decodingInfo;
        const device = shaka.device.DeviceFactory.getDevice();
        if (device.getDeviceType() == shaka.device.IDevice.DeviceType.MOBILE) {
          decodingInfo =
            await shaka.util.Functional.promiseWithTimeout(
                TIMEOUT_FOR_DECODING_INFO_IN_SECONDS,
                navigator.mediaCapabilities.decodingInfo(decodingConfig),
            );
        } else {
          decodingInfo =
              await navigator.mediaCapabilities.decodingInfo(decodingConfig);
        }

        const access = decodingInfo.keySystemAccess;
        await processMediaKeySystemAccess(keySystem, access);
      } catch (error) {
        // Ignore errors.
        shaka.log.v2('Failed to probe support for', keySystem, error);
      }
    };

    // Initialize the support structure for each key system.
    for (const keySystem of testKeySystems) {
      support.set(keySystem, null);
    }

    const checkKeySystem = (keySystem) => {
      // Our Polyfill will reject anything apart com.apple.fps key systems.
      // It seems the Safari modern EME API will allow to request a
      // MediaKeySystemAccess for the ClearKey CDM, create and update a key
      // session but playback will never start
      // Safari bug: https://bugs.webkit.org/show_bug.cgi?id=231006
      const device = shaka.device.DeviceFactory.getDevice();
      if (device.getBrowserEngine() ===
          shaka.device.IDevice.BrowserEngine.WEBKIT &&
          shaka.drm.DrmUtils.isClearKeySystem(keySystem)) {
        return false;
      }
      return true;
    };

    // Test each key system and encryption scheme.
    const tests = [];
    for (const encryptionScheme of testEncryptionSchemes) {
      for (const keySystem of testKeySystems) {
        if (!checkKeySystem(keySystem)) {
          continue;
        }
        tests.push(testSystemEme(keySystem, encryptionScheme, '', ''));
        tests.push(testSystemMcap(keySystem, encryptionScheme, '', ''));
      }
    }

    for (const keySystem of testKeySystems) {
      for (const robustness of (testRobustness[keySystem] || [])) {
        if (!checkKeySystem(keySystem)) {
          continue;
        }
        tests.push(testSystemEme(keySystem, null, robustness, ''));
        tests.push(testSystemEme(keySystem, null, '', robustness));
        tests.push(testSystemMcap(keySystem, null, robustness, ''));
        tests.push(testSystemMcap(keySystem, null, '', robustness));
      }
    }

    await Promise.all(tests);
    return shaka.util.MapUtils.asObject(support);
  }
Returns a Promise to a map of EME support for well-known key systems.

@return {!Promise<!Object<string, ?shaka.extern.DrmSupportType>>}