2c6ddb6e by David LaPalomento

Use common implementations of xhr and resolveUrl

Expose the XHR and URL resolution utility methods on videojs.hls so they can be shared between the playlist loader and the core plugin. Narrow the scope of the settings variable to be correctly tied to a single instance of the plugin.
1 parent 1cf4604e
...@@ -5,102 +5,8 @@ ...@@ -5,102 +5,8 @@
5 (function(window, videojs) { 5 (function(window, videojs) {
6 'use strict'; 6 'use strict';
7 var 7 var
8 8 resolveUrl = videojs.hls.resolveUrl,
9 /* XXX COPIED REMOVE ME */ 9 xhr = videojs.hls.xhr,
10 /**
11 * Constructs a new URI by interpreting a path relative to another
12 * URI.
13 * @param basePath {string} a relative or absolute URI
14 * @param path {string} a path part to combine with the base
15 * @return {string} a URI that is equivalent to composing `base`
16 * with `path`
17 * @see http://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue
18 */
19 resolveUrl = function(basePath, path) {
20 // use the base element to get the browser to handle URI resolution
21 var
22 oldBase = document.querySelector('base'),
23 docHead = document.querySelector('head'),
24 a = document.createElement('a'),
25 base = oldBase,
26 oldHref,
27 result;
28
29 // prep the document
30 if (oldBase) {
31 oldHref = oldBase.href;
32 } else {
33 base = docHead.appendChild(document.createElement('base'));
34 }
35
36 base.href = basePath;
37 a.href = path;
38 result = a.href;
39
40 // clean up
41 if (oldBase) {
42 oldBase.href = oldHref;
43 } else {
44 docHead.removeChild(base);
45 }
46 return result;
47 },
48
49 /* XXX COPIED REMOVE ME */
50 /**
51 * Creates and sends an XMLHttpRequest.
52 * @param options {string | object} if this argument is a string, it
53 * is intrepreted as a URL and a simple GET request is
54 * inititated. If it is an object, it should contain a `url`
55 * property that indicates the URL to request and optionally a
56 * `method` which is the type of HTTP request to send.
57 * @param callback (optional) {function} a function to call when the
58 * request completes. If the request was not successful, the first
59 * argument will be falsey.
60 * @return {object} the XMLHttpRequest that was initiated.
61 */
62 xhr = function(url, callback) {
63 var
64 options = {
65 method: 'GET'
66 },
67 request;
68
69 if (typeof callback !== 'function') {
70 callback = function() {};
71 }
72
73 if (typeof url === 'object') {
74 options = videojs.util.mergeOptions(options, url);
75 url = options.url;
76 }
77
78 request = new window.XMLHttpRequest();
79 request.open(options.method, url);
80
81 if (options.responseType) {
82 request.responseType = options.responseType;
83 }
84 if (options.withCredentials) {
85 request.withCredentials = true;
86 }
87
88 request.onreadystatechange = function() {
89 // wait until the request completes
90 if (this.readyState !== 4) {
91 return;
92 }
93
94 // request error
95 if (this.status >= 400 || this.status === 0) {
96 return callback.call(this, true, url);
97 }
98
99 return callback.call(this, false, url);
100 };
101 request.send(null);
102 return request;
103 },
104 10
105 /** 11 /**
106 * Returns a new master playlist that is the result of merging an 12 * Returns a new master playlist that is the result of merging an
...@@ -147,7 +53,7 @@ ...@@ -147,7 +53,7 @@
147 media, 53 media,
148 request, 54 request,
149 55
150 haveMetadata = function(error, url) { 56 haveMetadata = function(error, xhr, url) {
151 var parser, refreshDelay, update; 57 var parser, refreshDelay, update;
152 58
153 // any in-flight request is now finished 59 // any in-flight request is now finished
...@@ -155,9 +61,9 @@ ...@@ -155,9 +61,9 @@
155 61
156 if (error) { 62 if (error) {
157 loader.error = { 63 loader.error = {
158 status: this.status, 64 status: xhr.status,
159 message: 'HLS playlist request error at URL: ' + url, 65 message: 'HLS playlist request error at URL: ' + url,
160 code: (this.status >= 500) ? 4 : 2 66 code: (xhr.status >= 500) ? 4 : 2
161 }; 67 };
162 return loader.trigger('error'); 68 return loader.trigger('error');
163 } 69 }
...@@ -165,7 +71,7 @@ ...@@ -165,7 +71,7 @@
165 loader.state = 'HAVE_METADATA'; 71 loader.state = 'HAVE_METADATA';
166 72
167 parser = new videojs.m3u8.Parser(); 73 parser = new videojs.m3u8.Parser();
168 parser.push(this.responseText); 74 parser.push(xhr.responseText);
169 parser.manifest.uri = url; 75 parser.manifest.uri = url;
170 76
171 // merge this playlist into the master 77 // merge this playlist into the master
...@@ -235,7 +141,7 @@ ...@@ -235,7 +141,7 @@
235 141
236 // request the new playlist 142 // request the new playlist
237 request = xhr(resolveUrl(loader.master.uri, playlist.uri), function(error) { 143 request = xhr(resolveUrl(loader.master.uri, playlist.uri), function(error) {
238 haveMetadata.call(this, error, playlist.uri); 144 haveMetadata(error, this, playlist.uri);
239 }); 145 });
240 }; 146 };
241 147
...@@ -249,7 +155,7 @@ ...@@ -249,7 +155,7 @@
249 loader.state = 'HAVE_CURRENT_METADATA'; 155 loader.state = 'HAVE_CURRENT_METADATA';
250 request = xhr(resolveUrl(loader.master.uri, loader.media().uri), 156 request = xhr(resolveUrl(loader.master.uri, loader.media().uri),
251 function(error) { 157 function(error) {
252 haveMetadata.call(this, error, loader.media().uri); 158 haveMetadata(error, this, loader.media().uri);
253 }); 159 });
254 }); 160 });
255 161
...@@ -286,8 +192,8 @@ ...@@ -286,8 +192,8 @@
286 request = xhr(resolveUrl(srcUrl, parser.manifest.playlists[0].uri), 192 request = xhr(resolveUrl(srcUrl, parser.manifest.playlists[0].uri),
287 function(error) { 193 function(error) {
288 // pass along the URL specified in the master playlist 194 // pass along the URL specified in the master playlist
289 haveMetadata.call(this, 195 haveMetadata(error,
290 error, 196 this,
291 parser.manifest.playlists[0].uri); 197 parser.manifest.playlists[0].uri);
292 }); 198 });
293 return loader.trigger('loadedplaylist'); 199 return loader.trigger('loadedplaylist');
...@@ -302,7 +208,7 @@ ...@@ -302,7 +208,7 @@
302 }] 208 }]
303 }; 209 };
304 loader.master.playlists[srcUrl] = loader.master.playlists[0]; 210 loader.master.playlists[srcUrl] = loader.master.playlists[0];
305 return haveMetadata.call(this, null, srcUrl); 211 return haveMetadata(null, this, srcUrl);
306 }); 212 });
307 }; 213 };
308 PlaylistLoader.prototype = new videojs.hls.Stream(); 214 PlaylistLoader.prototype = new videojs.hls.Stream();
......
...@@ -32,8 +32,6 @@ videojs.hls = { ...@@ -32,8 +32,6 @@ videojs.hls = {
32 32
33 var 33 var
34 34
35 settings,
36
37 // the desired length of video to maintain in the buffer, in seconds 35 // the desired length of video to maintain in the buffer, in seconds
38 goalBufferLength = 5, 36 goalBufferLength = 5,
39 37
...@@ -109,7 +107,7 @@ var ...@@ -109,7 +107,7 @@ var
109 * argument will be falsey. 107 * argument will be falsey.
110 * @return {object} the XMLHttpRequest that was initiated. 108 * @return {object} the XMLHttpRequest that was initiated.
111 */ 109 */
112 xhr = function(url, callback) { 110 xhr = videojs.hls.xhr = function(url, callback) {
113 var 111 var
114 options = { 112 options = {
115 method: 'GET' 113 method: 'GET'
...@@ -131,7 +129,7 @@ var ...@@ -131,7 +129,7 @@ var
131 if (options.responseType) { 129 if (options.responseType) {
132 request.responseType = options.responseType; 130 request.responseType = options.responseType;
133 } 131 }
134 if (settings.withCredentials) { 132 if (options.withCredentials) {
135 request.withCredentials = true; 133 request.withCredentials = true;
136 } 134 }
137 135
...@@ -253,7 +251,7 @@ var ...@@ -253,7 +251,7 @@ var
253 * with `path` 251 * with `path`
254 * @see http://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue 252 * @see http://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue
255 */ 253 */
256 resolveUrl = function(basePath, path) { 254 resolveUrl = videojs.hls.resolveUrl = function(basePath, path) {
257 // use the base element to get the browser to handle URI resolution 255 // use the base element to get the browser to handle URI resolution
258 var 256 var
259 oldBase = document.querySelector('base'), 257 oldBase = document.querySelector('base'),
...@@ -296,6 +294,7 @@ var ...@@ -296,6 +294,7 @@ var
296 294
297 playlistXhr, 295 playlistXhr,
298 segmentXhr, 296 segmentXhr,
297 settings,
299 loadedPlaylist, 298 loadedPlaylist,
300 fillBuffer, 299 fillBuffer,
301 updateCurrentPlaylist, 300 updateCurrentPlaylist,
...@@ -425,7 +424,10 @@ var ...@@ -425,7 +424,10 @@ var
425 if (playlistXhr) { 424 if (playlistXhr) {
426 playlistXhr.abort(); 425 playlistXhr.abort();
427 } 426 }
428 playlistXhr = xhr(resolveUrl(srcUrl, playlist.uri), loadedPlaylist); 427 playlistXhr = xhr({
428 url: resolveUrl(srcUrl, playlist.uri),
429 withCredentials: settings.withCredentials
430 }, loadedPlaylist);
429 } else { 431 } else {
430 player.hls.mediaIndex = 432 player.hls.mediaIndex =
431 translateMediaIndex(player.hls.mediaIndex, 433 translateMediaIndex(player.hls.mediaIndex,
...@@ -654,7 +656,8 @@ var ...@@ -654,7 +656,8 @@ var
654 // request the next segment 656 // request the next segment
655 segmentXhr = xhr({ 657 segmentXhr = xhr({
656 url: segmentUri, 658 url: segmentUri,
657 responseType: 'arraybuffer' 659 responseType: 'arraybuffer',
660 withCredentials: settings.withCredentials
658 }, function(error, url) { 661 }, function(error, url) {
659 // the segment request is no longer outstanding 662 // the segment request is no longer outstanding
660 segmentXhr = null; 663 segmentXhr = null;
...@@ -723,14 +726,20 @@ var ...@@ -723,14 +726,20 @@ var
723 sourceBuffer.appendBuffer(segmentParser.getFlvHeader()); 726 sourceBuffer.appendBuffer(segmentParser.getFlvHeader());
724 727
725 player.hls.mediaIndex = 0; 728 player.hls.mediaIndex = 0;
726 xhr(srcUrl, function(error, url) { 729 xhr({
730 url: srcUrl,
731 withCredentials: settings.withCredentials
732 }, function(error, url) {
727 var uri, parser = new videojs.m3u8.Parser(); 733 var uri, parser = new videojs.m3u8.Parser();
728 parser.push(this.responseText); 734 parser.push(this.responseText);
729 735
730 // master playlists 736 // master playlists
731 if (parser.manifest.playlists) { 737 if (parser.manifest.playlists) {
732 player.hls.master = parser.manifest; 738 player.hls.master = parser.manifest;
733 playlistXhr = xhr(resolveUrl(url, parser.manifest.playlists[0].uri), loadedPlaylist); 739 playlistXhr = xhr({
740 url: resolveUrl(url, parser.manifest.playlists[0].uri),
741 withCredentials: settings.withCredentials
742 }, loadedPlaylist);
734 return player.trigger('loadedmanifest'); 743 return player.trigger('loadedmanifest');
735 } else { 744 } else {
736 // infer a master playlist if a media playlist is loaded directly 745 // infer a master playlist if a media playlist is loaded directly
......