Source: lib/offline/offline_manifest_parser.js

  1. /**
  2. * @license
  3. * Copyright 2016 Google Inc.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. goog.provide('shaka.offline.OfflineManifestParser');
  18. goog.require('goog.asserts');
  19. goog.require('shaka.log');
  20. goog.require('shaka.media.ManifestParser');
  21. goog.require('shaka.media.PresentationTimeline');
  22. goog.require('shaka.offline.OfflineUtils');
  23. goog.require('shaka.util.Error');
  24. /**
  25. * Creates a new offline manifest parser.
  26. * @struct
  27. * @constructor
  28. * @implements {shakaExtern.ManifestParser}
  29. */
  30. shaka.offline.OfflineManifestParser = function() {
  31. /** @private {number} */
  32. this.manifestId_ = -1;
  33. };
  34. /** @override */
  35. shaka.offline.OfflineManifestParser.prototype.configure = function(config) {
  36. // No-op
  37. };
  38. /** @override */
  39. shaka.offline.OfflineManifestParser.prototype.start =
  40. function(uri, playerInterface) {
  41. var parts = /^offline:([0-9]+)$/.exec(uri);
  42. if (!parts) {
  43. return Promise.reject(new shaka.util.Error(
  44. shaka.util.Error.Severity.CRITICAL,
  45. shaka.util.Error.Category.NETWORK,
  46. shaka.util.Error.Code.MALFORMED_OFFLINE_URI, uri));
  47. }
  48. var manifestId = Number(parts[1]);
  49. var storageEngine = shaka.offline.OfflineUtils.createStorageEngine();
  50. this.manifestId_ = manifestId;
  51. if (!storageEngine) {
  52. return Promise.reject(new shaka.util.Error(
  53. shaka.util.Error.Severity.CRITICAL,
  54. shaka.util.Error.Category.STORAGE,
  55. shaka.util.Error.Code.STORAGE_NOT_SUPPORTED));
  56. }
  57. return storageEngine.init(shaka.offline.OfflineUtils.DB_SCHEME)
  58. .then(function() { return storageEngine.get('manifest', manifestId); })
  59. .then(function(manifest) {
  60. if (!manifest) {
  61. throw new shaka.util.Error(
  62. shaka.util.Error.Severity.CRITICAL,
  63. shaka.util.Error.Category.STORAGE,
  64. shaka.util.Error.Code.REQUESTED_ITEM_NOT_FOUND, manifestId);
  65. }
  66. var OfflineManifestParser = shaka.offline.OfflineManifestParser;
  67. return OfflineManifestParser.reconstructManifest(manifest);
  68. })
  69. .then(
  70. function(ret) {
  71. return storageEngine.destroy().then(function() { return ret; });
  72. },
  73. function(err) {
  74. return storageEngine.destroy().then(function() { throw err; });
  75. });
  76. };
  77. /** @override */
  78. shaka.offline.OfflineManifestParser.prototype.stop = function() {
  79. return Promise.resolve();
  80. };
  81. /** @override */
  82. shaka.offline.OfflineManifestParser.prototype.update = function() {
  83. // No-op
  84. };
  85. /** @override */
  86. shaka.offline.OfflineManifestParser.prototype.onExpirationUpdated = function(
  87. sessionId, expiration) {
  88. var storageEngine = shaka.offline.OfflineUtils.createStorageEngine();
  89. goog.asserts.assert(storageEngine, 'Must support offline storage');
  90. storageEngine.init(shaka.offline.OfflineUtils.DB_SCHEME)
  91. .then(function() {
  92. return storageEngine.get('manifest', this.manifestId_);
  93. }.bind(this))
  94. .then(function(manifest) {
  95. if (!manifest) {
  96. // Manifest was deleted, ignore update.
  97. return;
  98. }
  99. if (manifest.sessionIds.indexOf(sessionId) < 0) {
  100. shaka.log.debug('Ignoring updated expiration for unknown session');
  101. return;
  102. }
  103. if (manifest.expiration == undefined ||
  104. manifest.expiration > expiration) {
  105. shaka.log.debug('Updating expiration for stored content');
  106. manifest.expiration = expiration;
  107. return storageEngine.insert('manifest', manifest);
  108. }
  109. })
  110. .catch(function(error) {
  111. shaka.log.error('Error updating offline manifest expiration', error);
  112. })
  113. .then(function() {
  114. return storageEngine.destroy();
  115. });
  116. };
  117. /**
  118. * Reconstructs a manifest object from the given database manifest.
  119. *
  120. * @param {shakaExtern.ManifestDB} manifest
  121. * @return {shakaExtern.Manifest}
  122. */
  123. shaka.offline.OfflineManifestParser.reconstructManifest = function(manifest) {
  124. var timeline = new shaka.media.PresentationTimeline(null, 0);
  125. timeline.setDuration(manifest.duration);
  126. var drmInfos = manifest.drmInfo ? [manifest.drmInfo] : [];
  127. return {
  128. presentationTimeline: timeline,
  129. minBufferTime: 10,
  130. offlineSessionIds: manifest.sessionIds,
  131. periods: manifest.periods.map(function(period) {
  132. return shaka.offline.OfflineUtils.reconstructPeriod(period,
  133. drmInfos,
  134. timeline);
  135. })
  136. };
  137. };
  138. shaka.media.ManifestParser.registerParserByMime(
  139. 'application/x-offline-manifest', shaka.offline.OfflineManifestParser);