|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 var rootDir = getRootDirectory(gTestPath); |
|
6 const gTestRoot = rootDir; |
|
7 |
|
8 var gTestBrowser = null; |
|
9 var gNextTest = null; |
|
10 var gNextTestSkip = 0; |
|
11 var gPlayPreviewPluginActualEvents = 0; |
|
12 var gPlayPreviewPluginExpectedEvents = 1; |
|
13 |
|
14 var gPlayPreviewRegistration = null; |
|
15 |
|
16 function registerPlayPreview(mimeType, targetUrl) { |
|
17 |
|
18 function StreamConverterFactory() {} |
|
19 StreamConverterFactory.prototype = { |
|
20 QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]), |
|
21 _targetConstructor: null, |
|
22 |
|
23 register: function register(targetConstructor) { |
|
24 this._targetConstructor = targetConstructor; |
|
25 var proto = targetConstructor.prototype; |
|
26 var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); |
|
27 registrar.registerFactory(proto.classID, proto.classDescription, |
|
28 proto.contractID, this); |
|
29 }, |
|
30 |
|
31 unregister: function unregister() { |
|
32 var proto = this._targetConstructor.prototype; |
|
33 var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); |
|
34 registrar.unregisterFactory(proto.classID, this); |
|
35 this._targetConstructor = null; |
|
36 }, |
|
37 |
|
38 // nsIFactory |
|
39 createInstance: function createInstance(aOuter, iid) { |
|
40 if (aOuter !== null) |
|
41 throw Cr.NS_ERROR_NO_AGGREGATION; |
|
42 return (new (this._targetConstructor)).QueryInterface(iid); |
|
43 }, |
|
44 |
|
45 // nsIFactory |
|
46 lockFactory: function lockFactory(lock) { |
|
47 // No longer used as of gecko 1.7. |
|
48 throw Cr.NS_ERROR_NOT_IMPLEMENTED; |
|
49 } |
|
50 }; |
|
51 |
|
52 function OverlayStreamConverter() {} |
|
53 OverlayStreamConverter.prototype = { |
|
54 QueryInterface: XPCOMUtils.generateQI([ |
|
55 Ci.nsISupports, |
|
56 Ci.nsIStreamConverter, |
|
57 Ci.nsIStreamListener, |
|
58 Ci.nsIRequestObserver |
|
59 ]), |
|
60 |
|
61 classID: Components.ID('{4c6030f7-e20a-264f-0f9b-ada3a9e97384}'), |
|
62 classDescription: 'overlay-test-data Component', |
|
63 contractID: '@mozilla.org/streamconv;1?from=application/x-moz-playpreview&to=*/*', |
|
64 |
|
65 // nsIStreamConverter::convert |
|
66 convert: function(aFromStream, aFromType, aToType, aCtxt) { |
|
67 throw Cr.NS_ERROR_NOT_IMPLEMENTED; |
|
68 }, |
|
69 |
|
70 // nsIStreamConverter::asyncConvertData |
|
71 asyncConvertData: function(aFromType, aToType, aListener, aCtxt) { |
|
72 var isValidRequest = false; |
|
73 try { |
|
74 var request = aCtxt; |
|
75 request.QueryInterface(Ci.nsIChannel); |
|
76 var spec = request.URI.spec; |
|
77 var expectedSpec = 'data:application/x-moz-playpreview;,' + mimeType; |
|
78 isValidRequest = (spec == expectedSpec); |
|
79 } catch (e) { } |
|
80 if (!isValidRequest) |
|
81 throw Cr.NS_ERROR_NOT_IMPLEMENTED; |
|
82 |
|
83 // Store the listener passed to us |
|
84 this.listener = aListener; |
|
85 }, |
|
86 |
|
87 // nsIStreamListener::onDataAvailable |
|
88 onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) { |
|
89 // Do nothing since all the data loading is handled by the viewer. |
|
90 ok(false, "onDataAvailable should not be called"); |
|
91 }, |
|
92 |
|
93 // nsIRequestObserver::onStartRequest |
|
94 onStartRequest: function(aRequest, aContext) { |
|
95 |
|
96 // Setup the request so we can use it below. |
|
97 aRequest.QueryInterface(Ci.nsIChannel); |
|
98 // Cancel the request so the viewer can handle it. |
|
99 aRequest.cancel(Cr.NS_BINDING_ABORTED); |
|
100 |
|
101 // Create a new channel that is viewer loaded as a resource. |
|
102 var ioService = Services.io; |
|
103 var channel = ioService.newChannel(targetUrl, null, null); |
|
104 channel.asyncOpen(this.listener, aContext); |
|
105 }, |
|
106 |
|
107 // nsIRequestObserver::onStopRequest |
|
108 onStopRequest: function(aRequest, aContext, aStatusCode) { |
|
109 // Do nothing. |
|
110 } |
|
111 }; |
|
112 |
|
113 var ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); |
|
114 ph.registerPlayPreviewMimeType(mimeType, true); // ignoring CTP rules |
|
115 |
|
116 var factory = new StreamConverterFactory(); |
|
117 factory.register(OverlayStreamConverter); |
|
118 |
|
119 return (gPlayPreviewRegistration = { |
|
120 unregister: function() { |
|
121 ph.unregisterPlayPreviewMimeType(mimeType); |
|
122 factory.unregister(); |
|
123 gPlayPreviewRegistration = null; |
|
124 } |
|
125 }); |
|
126 } |
|
127 |
|
128 function unregisterPlayPreview() { |
|
129 gPlayPreviewRegistration.unregister(); |
|
130 } |
|
131 |
|
132 Components.utils.import('resource://gre/modules/XPCOMUtils.jsm'); |
|
133 Components.utils.import("resource://gre/modules/Services.jsm"); |
|
134 |
|
135 |
|
136 function test() { |
|
137 waitForExplicitFinish(); |
|
138 registerCleanupFunction(function() { |
|
139 if (gPlayPreviewRegistration) |
|
140 gPlayPreviewRegistration.unregister(); |
|
141 Services.prefs.clearUserPref("plugins.click_to_play"); |
|
142 }); |
|
143 |
|
144 var newTab = gBrowser.addTab(); |
|
145 gBrowser.selectedTab = newTab; |
|
146 gTestBrowser = gBrowser.selectedBrowser; |
|
147 gTestBrowser.addEventListener("load", pageLoad, true); |
|
148 gTestBrowser.addEventListener("PluginBindingAttached", handleBindingAttached, true, true); |
|
149 |
|
150 setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED); |
|
151 registerPlayPreview('application/x-test', 'about:'); |
|
152 prepareTest(test1a, gTestRoot + "plugin_test.html", 1); |
|
153 } |
|
154 |
|
155 function finishTest() { |
|
156 gTestBrowser.removeEventListener("load", pageLoad, true); |
|
157 gTestBrowser.removeEventListener("PluginBindingAttached", handleBindingAttached, true, true); |
|
158 gBrowser.removeCurrentTab(); |
|
159 window.focus(); |
|
160 finish(); |
|
161 } |
|
162 |
|
163 function handleBindingAttached(evt) { |
|
164 if (evt.target instanceof Ci.nsIObjectLoadingContent && |
|
165 evt.target.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW) |
|
166 gPlayPreviewPluginActualEvents++; |
|
167 } |
|
168 |
|
169 function pageLoad() { |
|
170 // The plugin events are async dispatched and can come after the load event |
|
171 // This just allows the events to fire before we then go on to test the states |
|
172 |
|
173 // iframe might triggers load event as well, making sure we skip some to let |
|
174 // all iframes on the page be loaded as well |
|
175 if (gNextTestSkip) { |
|
176 gNextTestSkip--; |
|
177 return; |
|
178 } |
|
179 executeSoon(gNextTest); |
|
180 } |
|
181 |
|
182 function prepareTest(nextTest, url, skip) { |
|
183 gNextTest = nextTest; |
|
184 gNextTestSkip = skip; |
|
185 gTestBrowser.contentWindow.location = url; |
|
186 } |
|
187 |
|
188 // Tests a page with normal play preview registration (1/2) |
|
189 function test1a() { |
|
190 var notificationBox = gBrowser.getNotificationBox(gTestBrowser); |
|
191 ok(!notificationBox.getNotificationWithValue("missing-plugins"), "Test 1a, Should not have displayed the missing plugin notification"); |
|
192 ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 1a, Should not have displayed the blocked plugin notification"); |
|
193 |
|
194 var pluginInfo = getTestPlugin(); |
|
195 ok(pluginInfo, "Should have a test plugin"); |
|
196 |
|
197 var doc = gTestBrowser.contentDocument; |
|
198 var plugin = doc.getElementById("test"); |
|
199 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); |
|
200 is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 1a, plugin fallback type should be PLUGIN_PLAY_PREVIEW"); |
|
201 ok(!objLoadingContent.activated, "Test 1a, Plugin should not be activated"); |
|
202 |
|
203 var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "previewPluginContent"); |
|
204 ok(overlay, "Test 1a, the overlay div is expected"); |
|
205 |
|
206 var iframe = overlay.getElementsByClassName("previewPluginContentFrame")[0]; |
|
207 ok(iframe && iframe.localName == "iframe", "Test 1a, the overlay iframe is expected"); |
|
208 var iframeHref = iframe.contentWindow.location.href; |
|
209 ok(iframeHref == "about:", "Test 1a, the overlay about: content is expected"); |
|
210 |
|
211 var rect = iframe.getBoundingClientRect(); |
|
212 ok(rect.width == 200, "Test 1a, Plugin with id=" + plugin.id + " overlay rect should have 200px width before being replaced by actual plugin"); |
|
213 ok(rect.height == 200, "Test 1a, Plugin with id=" + plugin.id + " overlay rect should have 200px height before being replaced by actual plugin"); |
|
214 |
|
215 var e = overlay.ownerDocument.createEvent("CustomEvent"); |
|
216 e.initCustomEvent("MozPlayPlugin", true, true, null); |
|
217 overlay.dispatchEvent(e); |
|
218 var condition = function() objLoadingContent.activated; |
|
219 waitForCondition(condition, test1b, "Test 1a, Waited too long for plugin to stop play preview"); |
|
220 } |
|
221 |
|
222 // Tests that activating via MozPlayPlugin through the notification works (part 2/2) |
|
223 function test1b() { |
|
224 var plugin = gTestBrowser.contentDocument.getElementById("test"); |
|
225 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); |
|
226 ok(objLoadingContent.activated, "Test 1b, Plugin should be activated"); |
|
227 |
|
228 is(gPlayPreviewPluginActualEvents, gPlayPreviewPluginExpectedEvents, |
|
229 "There should be exactly one PluginPlayPreview event"); |
|
230 |
|
231 unregisterPlayPreview(); |
|
232 |
|
233 prepareTest(test2, gTestRoot + "plugin_test.html"); |
|
234 } |
|
235 |
|
236 // Tests a page with a working plugin in it -- the mime type was just unregistered. |
|
237 function test2() { |
|
238 var plugin = gTestBrowser.contentDocument.getElementById("test"); |
|
239 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); |
|
240 ok(objLoadingContent.activated, "Test 2, Plugin should be activated"); |
|
241 |
|
242 registerPlayPreview('application/x-unknown', 'about:'); |
|
243 |
|
244 prepareTest(test3, gTestRoot + "plugin_test.html"); |
|
245 } |
|
246 |
|
247 // Tests a page with a working plugin in it -- diffent play preview type is reserved. |
|
248 function test3() { |
|
249 var plugin = gTestBrowser.contentDocument.getElementById("test"); |
|
250 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); |
|
251 ok(objLoadingContent.activated, "Test 3, Plugin should be activated"); |
|
252 |
|
253 unregisterPlayPreview(); |
|
254 |
|
255 registerPlayPreview('application/x-test', 'about:'); |
|
256 Services.prefs.setBoolPref("plugins.click_to_play", true); |
|
257 setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY); |
|
258 prepareTest(test4a, gTestRoot + "plugin_test.html", 1); |
|
259 } |
|
260 |
|
261 // Test a fallback to the click-to-play |
|
262 function test4a() { |
|
263 var doc = gTestBrowser.contentDocument; |
|
264 var plugin = doc.getElementById("test"); |
|
265 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); |
|
266 is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 4a, plugin fallback type should be PLUGIN_PLAY_PREVIEW"); |
|
267 ok(!objLoadingContent.activated, "Test 4a, Plugin should not be activated"); |
|
268 |
|
269 var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "previewPluginContent"); |
|
270 ok(overlay, "Test 4a, the overlay div is expected"); |
|
271 |
|
272 var e = overlay.ownerDocument.createEvent("CustomEvent"); |
|
273 e.initCustomEvent("MozPlayPlugin", true, true, true); |
|
274 overlay.dispatchEvent(e); |
|
275 var condition = function() objLoadingContent.pluginFallbackType == Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY; |
|
276 waitForCondition(condition, test4b, "Test 4a, Waited too long for plugin to stop play preview"); |
|
277 } |
|
278 |
|
279 function test4b() { |
|
280 var doc = gTestBrowser.contentDocument; |
|
281 var plugin = doc.getElementById("test"); |
|
282 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); |
|
283 ok(objLoadingContent.pluginFallbackType != Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 4b, plugin fallback type should not be PLUGIN_PLAY_PREVIEW"); |
|
284 ok(!objLoadingContent.activated, "Test 4b, Plugin should not be activated"); |
|
285 |
|
286 prepareTest(test5a, gTestRoot + "plugin_test.html", 1); |
|
287 } |
|
288 |
|
289 // Test a bypass of the click-to-play |
|
290 function test5a() { |
|
291 var doc = gTestBrowser.contentDocument; |
|
292 var plugin = doc.getElementById("test"); |
|
293 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); |
|
294 is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW, "Test 5a, plugin fallback type should be PLUGIN_PLAY_PREVIEW"); |
|
295 ok(!objLoadingContent.activated, "Test 5a, Plugin should not be activated"); |
|
296 |
|
297 var overlay = doc.getAnonymousElementByAttribute(plugin, "class", "previewPluginContent"); |
|
298 ok(overlay, "Test 5a, the overlay div is expected"); |
|
299 |
|
300 var e = overlay.ownerDocument.createEvent("CustomEvent"); |
|
301 e.initCustomEvent("MozPlayPlugin", true, true, false); |
|
302 overlay.dispatchEvent(e); |
|
303 var condition = function() objLoadingContent.activated; |
|
304 waitForCondition(condition, test5b, "Test 5a, Waited too long for plugin to stop play preview"); |
|
305 } |
|
306 |
|
307 function test5b() { |
|
308 var doc = gTestBrowser.contentDocument; |
|
309 var plugin = doc.getElementById("test"); |
|
310 var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); |
|
311 ok(objLoadingContent.activated, "Test 5b, Plugin should be activated"); |
|
312 |
|
313 finishTest(); |
|
314 } |
|
315 |