Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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/. */
5 "use strict";
7 const HTML = "<html>\
8 <body>\
9 <div>foo</div>\
10 <div>and</div>\
11 <textarea>noodles</textarea>\
12 </body>\
13 </html>";
15 const URL = "data:text/html;charset=utf-8," + encodeURIComponent(HTML);
17 const FRAME_HTML = "<iframe src='" + URL + "'><iframe>";
18 const FRAME_URL = "data:text/html;charset=utf-8," + encodeURIComponent(FRAME_HTML);
20 const { defer } = require("sdk/core/promise");
21 const { browserWindows } = require("sdk/windows");
22 const tabs = require("sdk/tabs");
23 const { setTabURL, getActiveTab, getTabContentWindow, closeTab, getTabs,
24 getTabTitle } = require("sdk/tabs/utils");
25 const { getMostRecentBrowserWindow, isFocused } = require("sdk/window/utils");
26 const { open: openNewWindow, close: closeWindow, focus } = require("sdk/window/helpers");
27 const { Loader } = require("sdk/test/loader");
28 const { merge } = require("sdk/util/object");
29 const { isPrivate } = require("sdk/private-browsing");
31 // General purpose utility functions
33 /**
34 * Opens the url given and return a promise, that will be resolved with the
35 * content window when the document is ready.
36 *
37 * I believe this approach could be useful in most of our unit test, that
38 * requires to open a tab and need to access to its content.
39 */
40 function open(url, options) {
41 let { promise, resolve } = defer();
43 if (options && typeof(options) === "object") {
44 openNewWindow("", {
45 features: merge({ toolbar: true }, options)
46 }).then(function(chromeWindow) {
47 if (isPrivate(chromeWindow) !== !!options.private)
48 throw new Error("Window should have Private set to " + !!options.private);
50 let tab = getActiveTab(chromeWindow);
52 tab.linkedBrowser.addEventListener("load", function ready(event) {
53 let { document } = getTabContentWindow(tab);
55 if (document.readyState === "complete" && document.URL === url) {
56 this.removeEventListener(event.type, ready);
58 if (options.title)
59 document.title = options.title;
61 resolve(document.defaultView);
62 }
63 }, true);
65 setTabURL(tab, url);
66 });
68 return promise;
69 };
71 tabs.open({
72 url: url,
73 onReady: function(tab) {
74 // Unfortunately there is no way to get a XUL Tab from SDK Tab on Firefox,
75 // only on Fennec. We should implement `tabNS` also on Firefox in order
76 // to have that.
78 // Here we assuming that the most recent browser window is the one we're
79 // doing the test, and the active tab is the one we just opened.
80 let window = getTabContentWindow(getActiveTab(getMostRecentBrowserWindow()));
82 resolve(window);
83 }
84 });
86 return promise;
87 };
89 /**
90 * Close the Active Tab
91 */
92 function close(window) {
93 let { promise, resolve } = defer();
95 if (window && typeof(window.close) === "function") {
96 closeWindow(window).then(function() resolve());
97 }
98 else {
99 // Here we assuming that the most recent browser window is the one we're
100 // doing the test, and the active tab is the one we just opened.
101 closeTab(getActiveTab(getMostRecentBrowserWindow()));
102 resolve();
103 }
105 return promise;
106 }
108 /**
109 * Reload the window given and return a promise, that will be resolved with the
110 * content window after a small delay.
111 */
112 function reload(window) {
113 let { promise, resolve } = defer();
115 // Here we assuming that the most recent browser window is the one we're
116 // doing the test, and the active tab is the one we just opened.
117 let tab = tabs.activeTab;
119 tab.once("ready", function () {
120 resolve(window);
121 });
123 window.location.reload(true);
125 return promise;
126 }
128 // Selection's unit test utility function
130 /**
131 * Select the first div in the page, adding the range to the selection.
132 */
133 function selectFirstDiv(window) {
134 let div = window.document.querySelector("div");
135 let selection = window.getSelection();
136 let range = window.document.createRange();
138 if (selection.rangeCount > 0)
139 selection.removeAllRanges();
141 range.selectNode(div);
142 selection.addRange(range);
144 return window;
145 }
147 /**
148 * Select all divs in the page, adding the ranges to the selection.
149 */
150 function selectAllDivs(window) {
151 let divs = window.document.getElementsByTagName("div");
152 let selection = window.getSelection();
154 if (selection.rangeCount > 0)
155 selection.removeAllRanges();
157 for (let i = 0; i < divs.length; i++) {
158 let range = window.document.createRange();
160 range.selectNode(divs[i]);
161 selection.addRange(range);
162 }
164 return window;
165 }
167 /**
168 * Select the textarea content
169 */
170 function selectTextarea(window) {
171 let selection = window.getSelection();
172 let textarea = window.document.querySelector("textarea");
174 if (selection.rangeCount > 0)
175 selection.removeAllRanges();
177 textarea.setSelectionRange(0, textarea.value.length);
178 textarea.focus();
180 return window;
181 }
183 /**
184 * Select the content of the first div
185 */
186 function selectContentFirstDiv(window) {
187 let div = window.document.querySelector("div");
188 let selection = window.getSelection();
189 let range = window.document.createRange();
191 if (selection.rangeCount > 0)
192 selection.removeAllRanges();
194 range.selectNodeContents(div);
195 selection.addRange(range);
197 return window;
198 }
200 /**
201 * Dispatch the selection event for the selection listener added by
202 * `nsISelectionPrivate.addSelectionListener`
203 */
204 function dispatchSelectionEvent(window) {
205 // We modify the selection in order to dispatch the selection's event, by
206 // contract the selection by one character. So if the text selected is "foo"
207 // will be "fo".
208 window.getSelection().modify("extend", "backward", "character");
210 return window;
211 }
213 /**
214 * Dispatch the selection event for the selection listener added by
215 * `window.onselect` / `window.addEventListener`
216 */
217 function dispatchOnSelectEvent(window) {
218 let { document } = window;
219 let textarea = document.querySelector("textarea");
220 let event = document.createEvent("UIEvents");
222 event.initUIEvent("select", true, true, window, 1);
224 textarea.dispatchEvent(event);
226 return window;
227 }
229 // Test cases
231 exports["test PWPB Selection Listener"] = function(assert, done) {
232 let loader = Loader(module);
233 let selection = loader.require("sdk/selection");
235 open(URL, {private: true, title: "PWPB Selection Listener"}).
236 then(function(window) {
237 selection.once("select", function() {
238 assert.equal(browserWindows.length, 2, "there should be only two windows open.");
239 assert.equal(getTabs().length, 2, "there should be only two tabs open: '" +
240 getTabs().map(function(tab) getTabTitle(tab)).join("', '") +
241 "'."
242 );
244 // window should be focused, but force the focus anyhow.. see bug 841823
245 focus(window).then(function() {
246 // check state of window
247 assert.ok(isFocused(window), "the window is focused");
248 assert.ok(isPrivate(window), "the window should be a private window");
250 assert.equal(selection.text, "fo");
252 close(window).
253 then(loader.unload).
254 then(done).
255 then(null, assert.fail);
256 });
257 });
258 return window;
259 }).
260 then(selectContentFirstDiv).
261 then(dispatchSelectionEvent).
262 then(null, assert.fail);
263 };
265 exports["test PWPB Textarea OnSelect Listener"] = function(assert, done) {
266 let loader = Loader(module);
267 let selection = loader.require("sdk/selection");
269 open(URL, {private: true, title: "PWPB OnSelect Listener"}).
270 then(function(window) {
271 selection.once("select", function() {
272 assert.equal(browserWindows.length, 2, "there should be only two windows open.");
273 assert.equal(getTabs().length, 2, "there should be only two tabs open: '" +
274 getTabs().map(function(tab) getTabTitle(tab)).join("', '") +
275 "'."
276 );
278 // window should be focused, but force the focus anyhow.. see bug 841823
279 focus(window).then(function() {
280 assert.equal(selection.text, "noodles");
282 close(window).
283 then(loader.unload).
284 then(done).
285 then(null, assert.fail);
286 });
287 });
288 return window;
289 }).
290 then(selectTextarea).
291 then(dispatchOnSelectEvent).
292 then(null, assert.fail);
293 };
295 exports["test PWPB Single DOM Selection"] = function(assert, done) {
296 let loader = Loader(module);
297 let selection = loader.require("sdk/selection");
299 open(URL, {private: true, title: "PWPB Single DOM Selection"}).
300 then(selectFirstDiv).
301 then(focus).then(function() {
302 assert.equal(selection.isContiguous, true,
303 "selection.isContiguous with single DOM Selection works.");
305 assert.equal(selection.text, "foo",
306 "selection.text with single DOM Selection works.");
308 assert.equal(selection.html, "<div>foo</div>",
309 "selection.html with single DOM Selection works.");
311 let selectionCount = 0;
312 for each (let sel in selection) {
313 selectionCount++;
315 assert.equal(sel.text, "foo",
316 "iterable selection.text with single DOM Selection works.");
318 assert.equal(sel.html, "<div>foo</div>",
319 "iterable selection.html with single DOM Selection works.");
320 }
322 assert.equal(selectionCount, 1,
323 "One iterable selection");
324 }).then(close).then(loader.unload).then(done).then(null, assert.fail);
325 }
327 exports["test PWPB Textarea Selection"] = function(assert, done) {
328 let loader = Loader(module);
329 let selection = loader.require("sdk/selection");
331 open(URL, {private: true, title: "PWPB Textarea Listener"}).
332 then(selectTextarea).
333 then(focus).
334 then(function() {
336 assert.equal(selection.isContiguous, true,
337 "selection.isContiguous with Textarea Selection works.");
339 assert.equal(selection.text, "noodles",
340 "selection.text with Textarea Selection works.");
342 assert.strictEqual(selection.html, null,
343 "selection.html with Textarea Selection works.");
345 let selectionCount = 0;
346 for each (let sel in selection) {
347 selectionCount++;
349 assert.equal(sel.text, "noodles",
350 "iterable selection.text with Textarea Selection works.");
352 assert.strictEqual(sel.html, null,
353 "iterable selection.html with Textarea Selection works.");
354 }
356 assert.equal(selectionCount, 1,
357 "One iterable selection");
358 }).then(close).then(loader.unload).then(done).then(null, assert.fail);
359 };
361 exports["test PWPB Set HTML in Multiple DOM Selection"] = function(assert, done) {
362 let loader = Loader(module);
363 let selection = loader.require("sdk/selection");
365 open(URL, {private: true, title: "PWPB Set HTML in Multiple DOM Selection"}).
366 then(selectAllDivs).
367 then(focus).
368 then(function() {
369 let html = "<span>b<b>a</b>r</span>";
371 let expectedText = ["bar", "and"];
372 let expectedHTML = [html, "<div>and</div>"];
374 selection.html = html;
376 assert.equal(selection.text, expectedText[0],
377 "set selection.text with DOM Selection works.");
379 assert.equal(selection.html, expectedHTML[0],
380 "selection.html with DOM Selection works.");
382 let selectionCount = 0;
383 for each (let sel in selection) {
385 assert.equal(sel.text, expectedText[selectionCount],
386 "iterable selection.text with multiple DOM Selection works.");
388 assert.equal(sel.html, expectedHTML[selectionCount],
389 "iterable selection.html with multiple DOM Selection works.");
391 selectionCount++;
392 }
394 assert.equal(selectionCount, 2,
395 "Two iterable selections");
396 }).then(close).then(loader.unload).then(done).then(null, assert.fail);
397 };
399 exports["test PWPB Set Text in Textarea Selection"] = function(assert, done) {
400 let loader = Loader(module);
401 let selection = loader.require("sdk/selection");
403 open(URL, {private: true, title: "test PWPB Set Text in Textarea Selection"}).
404 then(selectTextarea).
405 then(focus).
406 then(function() {
408 let text = "bar";
410 selection.text = text;
412 assert.equal(selection.text, text,
413 "set selection.text with Textarea Selection works.");
415 assert.strictEqual(selection.html, null,
416 "selection.html with Textarea Selection works.");
418 let selectionCount = 0;
419 for each (let sel in selection) {
420 selectionCount++;
422 assert.equal(sel.text, text,
423 "iterable selection.text with Textarea Selection works.");
425 assert.strictEqual(sel.html, null,
426 "iterable selection.html with Textarea Selection works.");
427 }
429 assert.equal(selectionCount, 1,
430 "One iterable selection");
432 }).then(close).then(loader.unload).then(done).then(null, assert.fail);
433 };
435 // If the platform doesn't support the PBPW, we're replacing PBPW tests
436 if (!require("sdk/private-browsing/utils").isWindowPBSupported) {
437 module.exports = {
438 "test PBPW Unsupported": function Unsupported (assert) {
439 assert.pass("Private Window Per Browsing is not supported on this platform.");
440 }
441 }
442 }
444 // If the module doesn't support the app we're being run in, require() will
445 // throw. In that case, remove all tests above from exports, and add one dummy
446 // test that passes.
447 try {
448 require("sdk/selection");
449 }
450 catch (err) {
451 if (!/^Unsupported Application/.test(err.message))
452 throw err;
454 module.exports = {
455 "test Unsupported Application": function Unsupported (assert) {
456 assert.pass(err.message);
457 }
458 }
459 }