- add third_party src.
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / LayoutTests / http / tests / media / media-source / mediasource-util.js
1 (function(window) {
2     // Set the testharness.js timeout to 120 seconds so that it is higher than
3     // the LayoutTest timeout. This prevents testharness.js from prematurely
4     // terminating tests and allows the LayoutTest runner to control when to
5     // timeout the test.
6     // FIXME: Change this to use explicit_timeout instead once /resources/testharness.js
7     //        is updated to a more recent version.
8     setup({ timeout: 120000 });
9
10     EventExpectationsManager = function(test)
11     {
12         this.test_ = test;
13         this.eventTargetList_ = [];
14         this.waitCallbacks_ = [];
15     };
16
17     EventExpectationsManager.prototype.expectEvent = function(object, eventName, description)
18     {
19         var eventInfo = { 'target': object, 'type': eventName, 'description': description};
20         var expectations = this.getExpectations_(object);
21         expectations.push(eventInfo);
22
23         var t = this;
24         var waitHandler = this.test_.step_func(function() { t.handleWaitCallback_(); });
25         var eventHandler = this.test_.step_func(function(event)
26         {
27             object.removeEventListener(eventName, eventHandler);
28             var expected = expectations[0];
29             assert_equals(event.target, expected.target, "Event target match.");
30             assert_equals(event.type, expected.type, "Event types match.");
31             assert_equals(eventInfo.description, expected.description, "Descriptions match for '" +  event.type + "'.");
32
33             expectations.shift(1);
34             if (t.waitCallbacks_.length > 0)
35                 setTimeout(waitHandler, 0);
36         });
37         object.addEventListener(eventName, eventHandler);
38     };
39
40     EventExpectationsManager.prototype.waitForExpectedEvents = function(callback)
41     {
42         this.waitCallbacks_.push(callback);
43         setTimeout(this.handleWaitCallback_.bind(this), 0);
44     };
45
46     EventExpectationsManager.prototype.expectingEvents = function()
47     {
48         for (var i = 0; i < this.eventTargetList_.length; ++i) {
49             if (this.eventTargetList_[i].expectations.length > 0) {
50                 return true;
51             }
52         }
53         return false;
54     }
55
56     EventExpectationsManager.prototype.handleWaitCallback_ = function()
57     {
58         if (this.waitCallbacks_.length == 0 || this.expectingEvents())
59             return;
60         var callback = this.waitCallbacks_.shift(1);
61         callback();
62     };
63
64     EventExpectationsManager.prototype.getExpectations_ = function(target)
65     {
66         for (var i = 0; i < this.eventTargetList_.length; ++i) {
67             var info = this.eventTargetList_[i];
68             if (info.target == target) {
69                 return info.expectations;
70             }
71         }
72         var expectations = [];
73         this.eventTargetList_.push({ 'target': target, 'expectations': expectations });
74         return expectations;
75     };
76
77     function loadData_(test, url, callback, isBinary)
78     {
79         var request = new XMLHttpRequest();
80         request.open("GET", url, true);
81         if (isBinary) {
82             request.responseType = 'arraybuffer';
83         }
84         request.onload = test.step_func(function(event)
85         {
86             if (request.status != 200) {
87                 assert_unreached("Unexpected status code : " + request.status);
88                 return;
89             }
90             var response = request.response;
91             if (isBinary) {
92                 response = new Uint8Array(response);
93             }
94             callback(response);
95         });
96         request.onerror = test.step_func(function(event)
97         {
98             assert_unreached("Unexpected error");
99         });
100         request.send();
101     }
102
103     function openMediaSource_(test, mediaTag, callback)
104     {
105         var mediaSource = new MediaSource();
106         var mediaSourceURL = URL.createObjectURL(mediaSource);
107
108         var eventHandler = test.step_func(onSourceOpen);
109         function onSourceOpen(event)
110         {
111             mediaSource.removeEventListener('sourceopen', eventHandler);
112             URL.revokeObjectURL(mediaSourceURL);
113             callback(mediaSource);
114         }
115
116         mediaSource.addEventListener('sourceopen', eventHandler);
117         mediaTag.src = mediaSourceURL;
118     }
119
120     var MediaSourceUtil = {};
121
122     MediaSourceUtil.loadTextData = function(test, url, callback)
123     {
124         loadData_(test, url, callback, false);
125     };
126
127     MediaSourceUtil.loadBinaryData = function(test, url, callback)
128     {
129         loadData_(test, url, callback, true);
130     };
131
132     MediaSourceUtil.fetchManifestAndData = function(test, manifestFilename, callback)
133     {
134         var baseURL = '/media/resources/media-source/';
135         var manifestURL = baseURL + manifestFilename;
136         MediaSourceUtil.loadTextData(test, manifestURL, function(manifestText)
137         {
138             var manifest = JSON.parse(manifestText);
139
140             assert_true(MediaSource.isTypeSupported(manifest.type), manifest.type + " is supported.");
141
142             var mediaURL = baseURL + manifest.url;
143             MediaSourceUtil.loadBinaryData(test, mediaURL, function(mediaData)
144             {
145                 callback(manifest.type, mediaData);
146             });
147         });
148     };
149
150     MediaSourceUtil.extractSegmentData = function(mediaData, info)
151     {
152         var start = info.offset;
153         var end = start + info.size;
154         return mediaData.subarray(start, end);
155     }
156
157     MediaSourceUtil.getMediaDataForPlaybackTime = function(mediaData, segmentInfo, playbackTimeToAdd)
158     {
159         assert_less_than_equal(playbackTimeToAdd, segmentInfo.duration);
160         var mediaInfo = segmentInfo.media;
161         var start = mediaInfo[0].offset;
162         var numBytes = 0;
163         var segmentIndex = 0;
164         while (segmentIndex < mediaInfo.length && mediaInfo[segmentIndex].timecode <= playbackTimeToAdd)
165         {
166           numBytes += mediaInfo[segmentIndex].size;
167           ++segmentIndex;
168         }
169         return mediaData.subarray(start, numBytes + start);
170     }
171
172     function getFirstSupportedType(typeList)
173     {
174         for (var i = 0; i < typeList.length; ++i) {
175             if (MediaSource.isTypeSupported(typeList[i]))
176                 return typeList[i];
177         }
178         return "";
179     }
180
181     var audioOnlyTypes = ['audio/webm;codecs="vorbis"', 'audio/mp4;codecs="mp4a.40.2"'];
182     var videoOnlyTypes = ['video/webm;codecs="vp8"', 'video/mp4;codecs="avc1.4D4001"'];
183     var audioVideoTypes = ['video/webm;codecs="vp8,vorbis"', 'video/mp4;codecs="mp4a.40.2"'];
184     MediaSourceUtil.AUDIO_ONLY_TYPE = getFirstSupportedType(audioOnlyTypes);
185     MediaSourceUtil.VIDEO_ONLY_TYPE = getFirstSupportedType(videoOnlyTypes);
186     MediaSourceUtil.AUDIO_VIDEO_TYPE = getFirstSupportedType(audioVideoTypes);
187
188     // TODO: Add wrapper object to MediaSourceUtil that binds loaded mediaData to its
189     // associated segmentInfo.
190
191     function addExtraTestMethods(test)
192     {
193         test.failOnEvent = function(object, eventName)
194         {
195             object.addEventListener(eventName, test.step_func(function(event)
196             {
197                 assert_unreached("Unexpected event '" + eventName + "'");
198             }));
199         };
200
201         test.endOnEvent = function(object, eventName)
202         {
203             object.addEventListener(eventName, test.step_func(function(event) { test.done(); }));
204         };
205
206         test.eventExpectations_ = new EventExpectationsManager(test);
207         test.expectEvent = function(object, eventName, description)
208         {
209             test.eventExpectations_.expectEvent(object, eventName, description);
210         };
211
212         test.waitForExpectedEvents = function(callback)
213         {
214             test.eventExpectations_.waitForExpectedEvents(callback);
215         };
216
217         test.waitForCurrentTimeChange = function(mediaElement, callback)
218         {
219             var initialTime = mediaElement.currentTime;
220
221             var onTimeUpdate = test.step_func(function()
222             {
223                 if (mediaElement.currentTime != initialTime) {
224                     mediaElement.removeEventListener('timeupdate', onTimeUpdate);
225                     callback();
226                 }
227             });
228
229             mediaElement.addEventListener('timeupdate', onTimeUpdate);
230         }
231
232         var oldTestDone = test.done.bind(test);
233         test.done = function()
234         {
235             if (test.status == test.PASS) {
236                 assert_false(test.eventExpectations_.expectingEvents(), "No pending event expectations.");
237             }
238             oldTestDone();
239         };
240     };
241
242     window['MediaSourceUtil'] = MediaSourceUtil;
243     window['media_test'] = function(testFunction, description, options)
244     {
245         options = options || {};
246         return async_test(function(test)
247         {
248             addExtraTestMethods(test);
249             testFunction(test);
250         }, description, options);
251     };
252     window['mediasource_test'] = function(testFunction, description, options)
253     {
254         return media_test(function(test)
255         {
256             var mediaTag = document.createElement("video");
257             document.body.appendChild(mediaTag);
258
259             // Overload done() so that element added to the document can be removed.
260             test.removeMediaElement_ = true;
261             var oldTestDone = test.done.bind(test);
262             test.done = function()
263             {
264                 if (test.removeMediaElement_) {
265                     document.body.removeChild(mediaTag);
266                     test.removeMediaElement_ = false;
267                 }
268                 oldTestDone();
269             };
270
271             openMediaSource_(test, mediaTag, function(mediaSource)
272             {
273                 testFunction(test, mediaTag, mediaSource);
274             });
275         }, description, options);
276     };
277
278     window['mediasource_testafterdataloaded'] = function(testFunction, description, options)
279     {
280         mediasource_test(function(test, mediaElement, mediaSource)
281         {
282             var segmentInfo = WebMSegmentInfo.testWebM;
283             test.failOnEvent(mediaElement, 'error');
284
285             var sourceBuffer = mediaSource.addSourceBuffer(segmentInfo.type);
286             MediaSourceUtil.loadBinaryData(test, segmentInfo.url, function(mediaData)
287             {
288                 testFunction(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData);
289             });
290         }, description, options);
291     }
292
293     function timeRangesToString(ranges)
294     {
295         var s = "{";
296         for (var i = 0; i < ranges.length; ++i) {
297             s += " [" + ranges.start(i).toFixed(3) + ", " + ranges.end(i).toFixed(3) + ")";
298         }
299         return s + " }";
300     }
301
302     window['assertBufferedEquals'] = function(obj, expected, description)
303     {
304         var actual = timeRangesToString(obj.buffered);
305         assert_equals(actual, expected, description);
306     };
307
308 })(window);