From 4a3a12ef5bc6dd2c7e3ccb2ee7affd30acd4c0b7 Mon Sep 17 00:00:00 2001 From: Steve Heffernan Date: Wed, 22 Oct 2014 13:11:29 -0400 Subject: [PATCH] Exported XHR function. Changed how dispose works for source handlers. --- build/source-loader.js | 1 + src/js/exports.js | 3 + src/js/lib.js | 80 ---------------------- src/js/media/html5.js | 30 +++++--- src/js/media/media.js | 29 ++++---- src/js/player.js | 1 - src/js/tracks.js | 8 ++- src/js/xhr.js | 151 +++++++++++++++++++++++++++++++++++++++++ test/karma.conf.js | 1 + 9 files changed, 194 insertions(+), 110 deletions(-) create mode 100644 src/js/xhr.js diff --git a/build/source-loader.js b/build/source-loader.js index 40626c5835..492ff11806 100644 --- a/build/source-loader.js +++ b/build/source-loader.js @@ -19,6 +19,7 @@ var sourceFiles = [ "src/js/core-object.js", "src/js/events.js", "src/js/lib.js", + "src/js/xhr.js", "src/js/util.js", "src/js/component.js", "src/js/button.js", diff --git a/src/js/exports.js b/src/js/exports.js index e80efd4eb6..dd1dc696f6 100644 --- a/src/js/exports.js +++ b/src/js/exports.js @@ -180,3 +180,6 @@ goog.exportSymbol('videojs.createTimeRange', vjs.createTimeRange); goog.exportSymbol('videojs.util', vjs.util); goog.exportProperty(vjs.util, 'mergeOptions', vjs.util.mergeOptions); goog.exportProperty(vjs, 'addLanguage', vjs.addLanguage); + +goog.exportSymbol('videojs.net', vjs.net); +goog.exportProperty(vjs.net, 'get', vjs.net.get); diff --git a/src/js/lib.js b/src/js/lib.js index 1112c10413..71f28330c4 100644 --- a/src/js/lib.js +++ b/src/js/lib.js @@ -613,86 +613,6 @@ vjs.createTimeRange = function(start, end){ }; }; -/** - * Simple http request for retrieving external files (e.g. text tracks) - * @param {String} url URL of resource - * @param {Function} onSuccess Success callback - * @param {Function=} onError Error callback - * @param {Boolean=} withCredentials Flag which allow credentials - * @private - */ -vjs.get = function(url, onSuccess, onError, withCredentials){ - var fileUrl, request, urlInfo, winLoc, crossOrigin; - - onError = onError || function(){}; - - if (typeof XMLHttpRequest === 'undefined') { - // Shim XMLHttpRequest for older IEs - window.XMLHttpRequest = function () { - try { return new window.ActiveXObject('Msxml2.XMLHTTP.6.0'); } catch (e) {} - try { return new window.ActiveXObject('Msxml2.XMLHTTP.3.0'); } catch (f) {} - try { return new window.ActiveXObject('Msxml2.XMLHTTP'); } catch (g) {} - throw new Error('This browser does not support XMLHttpRequest.'); - }; - } - - request = new XMLHttpRequest(); - - urlInfo = vjs.parseUrl(url); - winLoc = window.location; - // check if url is for another domain/origin - // ie8 doesn't know location.origin, so we won't rely on it here - crossOrigin = (urlInfo.protocol + urlInfo.host) !== (winLoc.protocol + winLoc.host); - - // Use XDomainRequest for IE if XMLHTTPRequest2 isn't available - // 'withCredentials' is only available in XMLHTTPRequest2 - // Also XDomainRequest has a lot of gotchas, so only use if cross domain - if(crossOrigin && window.XDomainRequest && !('withCredentials' in request)) { - request = new window.XDomainRequest(); - request.onload = function() { - onSuccess(request.responseText); - }; - request.onerror = onError; - // these blank handlers need to be set to fix ie9 http://cypressnorth.com/programming/internet-explorer-aborting-ajax-requests-fixed/ - request.onprogress = function() {}; - request.ontimeout = onError; - - // XMLHTTPRequest - } else { - fileUrl = (urlInfo.protocol == 'file:' || winLoc.protocol == 'file:'); - - request.onreadystatechange = function() { - if (request.readyState === 4) { - if (request.status === 200 || fileUrl && request.status === 0) { - onSuccess(request.responseText); - } else { - onError(request.responseText); - } - } - }; - } - - // open the connection - try { - // Third arg is async, or ignored by XDomainRequest - request.open('GET', url, true); - // withCredentials only supported by XMLHttpRequest2 - if(withCredentials) { - request.withCredentials = true; - } - } catch(e) { - onError(e); - return; - } - - // send the request - try { - request.send(); - } catch(e) { - onError(e); - } -}; - /** * Add to local storage (may removeable) * @private diff --git a/src/js/media/html5.js b/src/js/media/html5.js index 57f3edde93..83b4f2af29 100644 --- a/src/js/media/html5.js +++ b/src/js/media/html5.js @@ -18,7 +18,7 @@ vjs.Html5 = vjs.MediaTechController.extend({ // set the source if one was provided if (options['source'] && this.el_.currentSrc !== options['source'].src) { - this.el_.src = options['source'].src; + this.setSource(options['source']); } // Determine if native controls should be used @@ -302,18 +302,26 @@ vjs.Html5.nativeSourceHandler = {}; * @return {String} 'probably', 'maybe', or '' (empty string) */ vjs.Html5.nativeSourceHandler.canHandleSource = function(source){ - var can = ''; - - // IE9 on Windows 7 without MediaPlayer throws an error here - // https://github.com/videojs/video.js/issues/519 - try { - can = !!vjs.TEST_VID.canPlayType(source.type); - } catch(e) { - can = ''; + var ext; + + function canPlayType(type){ + // IE9 on Windows 7 without MediaPlayer throws an error here + // https://github.com/videojs/video.js/issues/519 + try { + return !!vjs.TEST_VID.canPlayType(type); + } catch(e) { + return ''; + } } - // TODO: If no type, check the extension - return can; + // If a type was provided we should rely on that + if (source.type) { + return canPlayType(source.type); + } else { + // If no type, fall back to checking 'video/[EXTENSION]' + ext = source.src.match(/\.([^\/\?]+)(\?[^\/]+)?$/i)[1]; + return canPlayType('video/'+ext); + } }; /** diff --git a/src/js/media/media.js b/src/js/media/media.js index 0406cdf995..db9be742c3 100644 --- a/src/js/media/media.js +++ b/src/js/media/media.js @@ -314,8 +314,6 @@ vjs.MediaTechController.withSourceHandlers = function(tech){ tech.selectSourceHandler = function(source){ var handlers = tech.sourceHandlers; - // console.log('here', handlers[0].canHandleSource); - for (var i = 0; i < handlers.length; i++) { can = handlers[i].canHandleSource(source); @@ -327,26 +325,23 @@ vjs.MediaTechController.withSourceHandlers = function(tech){ return null; }; + /** + * Create a function for setting the source using a source object + * and source handlers. + * Should never be called unless a source handler was found. + * @param {Object} source A source object with src and type keys + */ tech.prototype.setSource = function(source){ var sh = tech.selectSourceHandler(source); - this.currentSource_ = source; + // Clean up any existing source handler + if (this.sourceHandler && this.sourceHandler.dispose) { + this.sourceHandler.dispose(); + } - if (sh) { - // Clean up any existing source handler - if (this.sourceHandler && this.sourceHandler.dispose) { - this.sourceHandler.dispose(); - } + this.currentSource_ = source; - this.sourceHandler = sh; - sh.handleSource(source, this); - } else { - // If no source handler was found, attempt the existing one. It could be - // that it's a source object with no type. - // There should be no way to get here without loading an initial handler. - // The tech wouldn't be loaded if a handler wasn't found in canPlaySource. - this.sourceHandler.handleSource(source, this); - } + this.sourceHandler = sh.handleSource(source, this); }; /** diff --git a/src/js/player.js b/src/js/player.js index 6e4e67ff58..8c815b4cc2 100644 --- a/src/js/player.js +++ b/src/js/player.js @@ -1071,7 +1071,6 @@ vjs.Player.prototype.exitFullWindow = function(){ }; vjs.Player.prototype.selectSource = function(sources){ - // Loop through each playback technology in the options order for (var i=0,j=this.options_['techOrder'];i