Source: lib/net/data_uri_plugin.js

  1. /*! @license
  2. * Shaka Player
  3. * Copyright 2016 Google LLC
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. goog.provide('shaka.net.DataUriPlugin');
  7. goog.require('shaka.log');
  8. goog.require('shaka.net.NetworkingEngine');
  9. goog.require('shaka.util.AbortableOperation');
  10. goog.require('shaka.util.Error');
  11. goog.require('shaka.util.StringUtils');
  12. goog.require('shaka.util.Uint8ArrayUtils');
  13. /**
  14. * @summary A networking plugin to handle data URIs.
  15. * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/data_URIs
  16. * @export
  17. */
  18. shaka.net.DataUriPlugin = class {
  19. /**
  20. * @param {string} uri
  21. * @param {shaka.extern.Request} request
  22. * @param {shaka.net.NetworkingEngine.RequestType} requestType
  23. * @param {shaka.extern.ProgressUpdated} progressUpdated Called when a
  24. * progress event happened.
  25. * @return {!shaka.extern.IAbortableOperation.<shaka.extern.Response>}
  26. * @export
  27. */
  28. static parse(uri, request, requestType, progressUpdated) {
  29. try {
  30. const parsed = shaka.net.DataUriPlugin.parseRaw(uri);
  31. /** @type {shaka.extern.Response} */
  32. const response = {
  33. uri: uri,
  34. originalUri: uri,
  35. data: parsed.data,
  36. headers: {
  37. 'content-type': parsed.contentType,
  38. },
  39. originalRequest: request,
  40. };
  41. return shaka.util.AbortableOperation.completed(response);
  42. } catch (error) {
  43. return shaka.util.AbortableOperation.failed(error);
  44. }
  45. }
  46. /**
  47. * @param {string} uri
  48. * @return {{data: BufferSource, contentType: string}}
  49. */
  50. static parseRaw(uri) {
  51. // Extract the scheme.
  52. const parts = uri.split(':');
  53. if (parts.length < 2 || parts[0] != 'data') {
  54. shaka.log.error('Bad data URI, failed to parse scheme');
  55. throw new shaka.util.Error(
  56. shaka.util.Error.Severity.CRITICAL,
  57. shaka.util.Error.Category.NETWORK,
  58. shaka.util.Error.Code.MALFORMED_DATA_URI,
  59. uri);
  60. }
  61. const path = parts.slice(1).join(':');
  62. // Extract the encoding and MIME type (required but can be empty).
  63. const infoAndData = path.split(',');
  64. if (infoAndData.length < 2) {
  65. shaka.log.error('Bad data URI, failed to extract encoding and MIME type');
  66. throw new shaka.util.Error(
  67. shaka.util.Error.Severity.CRITICAL,
  68. shaka.util.Error.Category.NETWORK,
  69. shaka.util.Error.Code.MALFORMED_DATA_URI,
  70. uri);
  71. }
  72. const info = infoAndData[0];
  73. const dataStr = window.decodeURIComponent(infoAndData.slice(1).join(','));
  74. // The MIME type is always the first thing in the semicolon-separated list
  75. // of type parameters. It may be blank.
  76. const typeInfoList = info.split(';');
  77. const contentType = typeInfoList[0];
  78. // Check for base64 encoding, which is always the last in the
  79. // semicolon-separated list if present.
  80. let base64Encoded = false;
  81. if (typeInfoList.length > 1 &&
  82. typeInfoList[typeInfoList.length - 1] == 'base64') {
  83. base64Encoded = true;
  84. typeInfoList.pop();
  85. }
  86. // Convert the data.
  87. /** @type {BufferSource} */
  88. let data;
  89. if (base64Encoded) {
  90. data = shaka.util.Uint8ArrayUtils.fromBase64(dataStr);
  91. } else {
  92. data = shaka.util.StringUtils.toUTF8(dataStr);
  93. }
  94. return {data: data, contentType};
  95. }
  96. };
  97. shaka.net.NetworkingEngine.registerScheme(
  98. 'data', shaka.net.DataUriPlugin.parse);