Skip to content

Commit

Permalink
[v5] Fix CommonMediaResponse.resourceTiming info (#4367)
Browse files Browse the repository at this point in the history
* Fix CommonMediaResponse.resourceTiming info in case PerformanceResourceTiming is not usable (due to cross-origin restrictions)
  • Loading branch information
bbert committed Jan 24, 2024
1 parent 14a0d33 commit 894d80a
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 49 deletions.
46 changes: 5 additions & 41 deletions src/streaming/models/ThroughputModel.js
Expand Up @@ -185,20 +185,14 @@ function ThroughputModel(config) {
* @private
*/
function _calculateThroughputValuesForXhr(httpRequest, latencyInMs) {
let resourceTimingValues = null;
let downloadedBytes = NaN;
let downloadTimeInMs = NaN;
let deriveThroughputViaResourceTimingApi = false;


if (settings.get().streaming.abr.throughput.useResourceTimingApi) {
resourceTimingValues = _deriveDownloadValuesFromResourceTimingApi(httpRequest)
}

// Calculate the throughput using the ResourceTimingAPI if we got useful values
if (resourceTimingValues && !isNaN(resourceTimingValues.downloadedBytes) && !isNaN(resourceTimingValues.downloadTimeInMs)) {
downloadTimeInMs = resourceTimingValues.downloadTimeInMs;
downloadedBytes = resourceTimingValues.downloadedBytes;
// Calculate the throughput using the ResourceTimingAPI if available
if (settings.get().streaming.abr.throughput.useResourceTimingApi && httpRequest._resourceTimingValues) {
downloadedBytes = httpRequest._resourceTimingValues.transferSize;
downloadTimeInMs = httpRequest._resourceTimingValues.responseEnd - httpRequest._resourceTimingValues.responseStart;
deriveThroughputViaResourceTimingApi = true;
}

Expand Down Expand Up @@ -231,36 +225,6 @@ function ThroughputModel(config) {
};
}

/**
* Calculate the downloaded bytes and the download times using the resource timing API
* @param httpRequest
* @returns {{downloadTimeInMs: (*|number|NaN), downloadedBytes: (*|number|NaN)}}
* @private
*/
function _deriveDownloadValuesFromResourceTimingApi(httpRequest) {
let downloadedBytes = NaN;
let downloadTimeInMs = NaN;

if (_areResourceTimingValuesUsable(httpRequest)) {
downloadedBytes = httpRequest._resourceTimingValues.transferSize;
downloadTimeInMs = httpRequest._resourceTimingValues.responseEnd - httpRequest._resourceTimingValues.responseStart;
}

return { downloadedBytes, downloadTimeInMs }
}

/**
* Checks if we got useful ResourceTimingAPI values
* @param httpRequest
* @param {boolean} ignoreTransferSize
* @returns {null|*|boolean}
* @private
*/
function _areResourceTimingValuesUsable(httpRequest, ignoreTransferSize = false) {
return settings.get().streaming.abr.throughput.useResourceTimingApi && httpRequest._resourceTimingValues && !isNaN(httpRequest._resourceTimingValues.responseStart) && httpRequest._resourceTimingValues.responseStart > 0
&& !isNaN(httpRequest._resourceTimingValues.responseEnd) && httpRequest._resourceTimingValues.responseEnd > 0 && ((!isNaN(httpRequest._resourceTimingValues.transferSize) && httpRequest._resourceTimingValues.transferSize > 0) || ignoreTransferSize)
}

/**
* Return the current estimated bandwidth based on NetworkInformation.downlink if the API is available
* @returns {*|number}
Expand All @@ -285,7 +249,7 @@ function ThroughputModel(config) {
*/
function _isCachedResponse(mediaType, cacheReferenceTime, httpRequest) {

if (_areResourceTimingValuesUsable(httpRequest, true)) {
if (settings.get().streaming.abr.throughput.useResourceTimingApi && httpRequest._resourceTimingValues) {
return httpRequest._resourceTimingValues.transferSize === 0 && httpRequest._resourceTimingValues.decodedBodySize > 0
}

Expand Down
34 changes: 26 additions & 8 deletions src/streaming/net/HTTPLoader.js
Expand Up @@ -490,16 +490,34 @@ function HTTPLoader(cfg) {
i += 1;
}

// Check if PerformanceResourceTiming values are usable
// Note: to allow seeing cross-origin timing information, the Timing-Allow-Origin HTTP response header needs to be set
// See https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming#cross-origin_timing_information
if (!_areResourceTimingValuesUsable(resource)) {
return;
}

httpRequest.customData.request.resourceTimingValues = resource;

// Use Resource Timing info when available for CommonMediaResponse
if (resource) {
httpResponse.resourceTiming.startTime = resource.startTime;
httpResponse.resourceTiming.encodedBodySize = resource.encodedBodySize;
httpResponse.resourceTiming.responseStart = resource.startTime;
httpResponse.resourceTiming.responseEnd = resource.responseEnd;
httpResponse.resourceTiming.duration = resource.duration;
}
// Update CommonMediaResponse Resource Timing info
httpResponse.resourceTiming.startTime = resource.startTime;
httpResponse.resourceTiming.encodedBodySize = resource.encodedBodySize;
httpResponse.resourceTiming.responseStart = resource.startTime;
httpResponse.resourceTiming.responseEnd = resource.responseEnd;
httpResponse.resourceTiming.duration = resource.duration;
}

/**
* Checks if we got usable ResourceTimingAPI values
* @param httpRequest
* @returns {boolean}
* @private
*/
function _areResourceTimingValuesUsable(resource) {
return resource &&
!isNaN(resource.responseStart) && resource.responseStart > 0 &&
!isNaN(resource.responseEnd) && resource.responseEnd > 0 &&
!isNaN(resource.transferSize) && resource.transferSize > 0
}

/**
Expand Down

0 comments on commit 894d80a

Please sign in to comment.