Skip to content

Commit

Permalink
Exported XHR function. Changed how dispose works for source handlers.
Browse files Browse the repository at this point in the history
  • Loading branch information
heff committed Oct 22, 2014
1 parent 8306866 commit 4a3a12e
Show file tree
Hide file tree
Showing 9 changed files with 194 additions and 110 deletions.
1 change: 1 addition & 0 deletions build/source-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
3 changes: 3 additions & 0 deletions src/js/exports.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
80 changes: 0 additions & 80 deletions src/js/lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
30 changes: 19 additions & 11 deletions src/js/media/html5.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
};

/**
Expand Down
29 changes: 12 additions & 17 deletions src/js/media/media.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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);
};

/**
Expand Down
1 change: 0 additions & 1 deletion src/js/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -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<j.length;i++) {
var techName = vjs.capitalize(j[i]),
Expand Down
8 changes: 7 additions & 1 deletion src/js/tracks.js
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,13 @@ vjs.TextTrack.prototype.load = function(){
// Only load if not loaded yet.
if (this.readyState_ === 0) {
this.readyState_ = 1;
vjs.get(this.src_, vjs.bind(this, this.parseCues), vjs.bind(this, this.onError));
vjs.xhr(this.src_, vjs.bind(function(err, response, responseBody){
if (err) {
return this.onError(err);
}

this.parseCues(responseBody);
}));
}

};
Expand Down
151 changes: 151 additions & 0 deletions src/js/xhr.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/**
* Simple http request for retrieving external files (e.g. text tracks)
*
* ##### Example
*
* // using url string
* videojs.xhr('http://example.com/myfile.vtt', function(error, response, responseBody){});
*
* // or options block
* videojs.xhr({
* uri: 'http://example.com/myfile.vtt',
* method: 'GET',
* responseType: 'text'
* }, function(error, response, responseBody){
* if (error) {
* // log the error
* } else {
* // successful, do something with the response
* }
* });
*
*
* API is modeled after the Raynos/xhr, which we hope to use after
* getting browserify implemented.
* https://github.com/Raynos/xhr/blob/master/index.js
*
* @param {Object|String} options Options block or URL string
* @param {Function} callback The callback function
* @returns {Object} The request
*/
vjs.xhr = function(options, callback){
var XHR, request, urlInfo, winLoc, fileUrl, crossOrigin, abortTimeout, successHandler, errorHandler;

// If options is a string it's the url
if (typeof options === 'string') {
options = {
uri: options
};
}

// Merge with default options
videojs.util.mergeOptions({
method: 'GET',
timeout: 45 * 1000
}, options);

callback = callback || function(){};

successHandler = function(){
window.clearTimeout(abortTimeout);
callback(null, request, request.response || request.responseText);
};

errorHandler = function(err){
window.clearTimeout(abortTimeout);

if (!err || typeof err === 'string') {
err = new Error(err);
}

callback(err, request);
};

XHR = window.XMLHttpRequest;

if (typeof XHR === 'undefined') {
// Shim XMLHttpRequest for older IEs
XHR = 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 XHR();
// Store a reference to the url on the request instance
request.uri = options.uri;

urlInfo = vjs.parseUrl(options.uri);
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);

// XDomainRequest -- Use 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 = successHandler;
request.onerror = errorHandler;
// 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 = function(){};

// XMLHTTPRequest
} else {
fileUrl = (urlInfo.protocol == 'file:' || winLoc.protocol == 'file:');

request.onreadystatechange = function() {
if (request.readyState === 4) {
if (request.timedout) {
return errorHandler('timeout');
}

if (request.status === 200 || fileUrl && request.status === 0) {
successHandler();
} else {
errorHandler();
}
}
};

if (options.timeout) {
abortTimeout = window.setTimeout(function() {
if (request.readyState !== 4) {
request.timedout = true;
request.abort();
}
}, options.timeout);
}
}

// open the connection
try {
// Third arg is async, or ignored by XDomainRequest
request.open(options.method || 'GET', options.uri, true);
} catch(err) {
return errorHandler(err);
}

// withCredentials only supported by XMLHttpRequest2
if(options.withCredentials) {
request.withCredentials = true;
}

if (options.responseType) {
request.responseType = options.responseType;
}

// send the request
try {
request.send();
} catch(err) {
return errorHandler(err);
}

return request;
};
1 change: 1 addition & 0 deletions test/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ module.exports = function(config) {
"../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",
Expand Down

0 comments on commit 4a3a12e

Please sign in to comment.