browser_sanitizeDialog_treeView.js
Go to the documentation of this file.
1 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et: */
3 /* ***** BEGIN LICENSE BLOCK *****
4  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5  *
6  * The contents of this file are subject to the Mozilla Public License Version
7  * 1.1 (the "License"); you may not use this file except in compliance with
8  * the License. You may obtain a copy of the License at
9  * http://www.mozilla.org/MPL/
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  *
16  * The Original Code is sanitize dialog test code.
17  *
18  * The Initial Developer of the Original Code is Mozilla Corp.
19  * Portions created by the Initial Developer are Copyright (C) 2009
20  * the Initial Developer. All Rights Reserved.
21  *
22  * Contributor(s):
23  * Drew Willcoxon <adw@mozilla.com> (Original Author)
24  *
25  * Alternatively, the contents of this file may be used under the terms of
26  * either the GNU General Public License Version 2 or later (the "GPL"), or
27  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28  * in which case the provisions of the GPL or the LGPL are applicable instead
29  * of those above. If you wish to allow use of your version of this file only
30  * under the terms of either the GPL or the LGPL, and not to allow others to
31  * use your version of this file under the terms of the MPL, indicate your
32  * decision by deleting the provisions above and replace them with the notice
33  * and other provisions required by the GPL or the LGPL. If you do not delete
34  * the provisions above, a recipient may use your version of this file under
35  * the terms of any one of the MPL, the GPL or the LGPL.
36  *
37  * ***** END LICENSE BLOCK ***** */
38 
52 Cc["@mozilla.org/moz/jssubscript-loader;1"].
53  getService(Components.interfaces.mozIJSSubScriptLoader).
54  loadSubScript("chrome://mochikit/content/MochiKit/packed.js");
55 
56 Cc["@mozilla.org/moz/jssubscript-loader;1"].
57  getService(Components.interfaces.mozIJSSubScriptLoader).
58  loadSubScript("chrome://browser/content/sanitize.js");
59 
60 const winWatch = Cc["@mozilla.org/embedcomp/window-watcher;1"].
61  getService(Ci.nsIWindowWatcher);
62 const dm = Cc["@mozilla.org/download-manager;1"].
63  getService(Ci.nsIDownloadManager);
64 const bhist = Cc["@mozilla.org/browser/global-history;2"].
65  getService(Ci.nsIBrowserHistory);
66 const formhist = Cc["@mozilla.org/satchel/form-history;1"].
67  getService(Ci.nsIFormHistory2);
68 
69 // Add tests here. Each is a function that's called by doNextTest().
70 var gAllTests = [
71 
75  function () {
76  // Add history (within the past hour) to get some rows in the tree.
77  let uris = [];
78  for (let i = 0; i < 30; i++) {
79  uris.push(addHistoryWithMinutesAgo(i));
80  }
81 
82  // Open the dialog and do our tests.
83  openWindow(function (aWin) {
84  let wh = new WindowHelper(aWin);
85  wh.selectDuration(Sanitizer.TIMESPAN_HOUR);
86  wh.checkGrippy("Grippy should be at last row after selecting HOUR " +
87  "duration",
88  wh.getRowCount() - 1);
89 
90  // Move the grippy around.
91  let row = wh.getGrippyRow();
92  while (row !== 0) {
93  row--;
94  wh.moveGrippyBy(-1);
95  wh.checkGrippy("Grippy should be moved up one row", row);
96  }
97  wh.moveGrippyBy(-1);
98  wh.checkGrippy("Grippy should remain at first row after trying to move " +
99  "it up",
100  0);
101  while (row !== wh.getRowCount() - 1) {
102  row++;
103  wh.moveGrippyBy(1);
104  wh.checkGrippy("Grippy should be moved down one row", row);
105  }
106  wh.moveGrippyBy(1);
107  wh.checkGrippy("Grippy should remain at last row after trying to move " +
108  "it down",
109  wh.getRowCount() - 1);
110 
111  // Cancel the dialog, make sure history visits are not cleared.
112  wh.checkPrefCheckbox("history", false);
113 
114  wh.cancelDialog();
115  ensureHistoryClearedState(uris, false);
116 
117  // OK, done, cleanup after ourselves.
118  blankSlate();
119  ensureHistoryClearedState(uris, true);
120  });
121  },
122 
127  function () {
128  // Add history and downloads (within the past hour).
129  let uris = [];
130  for (let i = 0; i < 30; i++) {
131  uris.push(addHistoryWithMinutesAgo(i));
132  }
133  let downloadIDs = [];
134  for (let i = 0; i < 5; i++) {
135  downloadIDs.push(addDownloadWithMinutesAgo(i));
136  }
137  // Add history and downloads (over an hour ago).
138  let olderURIs = [];
139  for (let i = 0; i < 5; i++) {
140  olderURIs.push(addHistoryWithMinutesAgo(61 + i));
141  }
142  let olderDownloadIDs = [];
143  for (let i = 0; i < 5; i++) {
144  olderDownloadIDs.push(addDownloadWithMinutesAgo(61 + i));
145  }
146  let totalHistoryVisits = uris.length + olderURIs.length;
147 
148  // Open the dialog and do our tests.
149  openWindow(function (aWin) {
150  let wh = new WindowHelper(aWin);
151  wh.selectDuration(Sanitizer.TIMESPAN_HOUR);
152  wh.checkGrippy("Grippy should be at proper row after selecting HOUR " +
153  "duration",
154  uris.length);
155 
156  // Accept the dialog, make sure history visits and downloads within one
157  // hour are cleared.
158  wh.checkPrefCheckbox("history", true);
159  wh.acceptDialog();
160  ensureHistoryClearedState(uris, true);
161  ensureDownloadsClearedState(downloadIDs, true);
162 
163  // Make sure visits and downloads > 1 hour still exist.
164  ensureHistoryClearedState(olderURIs, false);
165  ensureDownloadsClearedState(olderDownloadIDs, false);
166 
167  // OK, done, cleanup after ourselves.
168  blankSlate();
169  ensureHistoryClearedState(olderURIs, true);
170  ensureDownloadsClearedState(olderDownloadIDs, true);
171  });
172  },
173 
178  function () {
179  // Add history, downloads, form entries (within the past hour).
180  let uris = [];
181  for (let i = 0; i < 5; i++) {
182  uris.push(addHistoryWithMinutesAgo(i));
183  }
184  let downloadIDs = [];
185  for (let i = 0; i < 5; i++) {
186  downloadIDs.push(addDownloadWithMinutesAgo(i));
187  }
188  let formEntries = [];
189  for (let i = 0; i < 5; i++) {
190  formEntries.push(addFormEntryWithMinutesAgo(i));
191  }
192 
193  // Open the dialog and do our tests.
194  openWindow(function (aWin) {
195  let wh = new WindowHelper(aWin);
196  wh.selectDuration(Sanitizer.TIMESPAN_HOUR);
197  wh.checkGrippy("Grippy should be at last row after selecting HOUR " +
198  "duration",
199  wh.getRowCount() - 1);
200 
201  // Remove only form entries, leave history (including downloads).
202  wh.checkPrefCheckbox("history", false);
203  wh.checkPrefCheckbox("formdata", true);
204  wh.acceptDialog();
205 
206  // Of the three only form entries should be cleared.
207  ensureHistoryClearedState(uris, false);
208  ensureDownloadsClearedState(downloadIDs, false);
209  ensureFormEntriesClearedState(formEntries, true);
210 
211  // OK, done, cleanup after ourselves.
212  blankSlate();
213  ensureHistoryClearedState(uris, true);
214  ensureDownloadsClearedState(downloadIDs, true);
215  });
216  },
217 
221  function () {
222  // Add history.
223  let uris = [];
224  uris.push(addHistoryWithMinutesAgo(10)); // within past hour
225  uris.push(addHistoryWithMinutesAgo(70)); // within past two hours
226  uris.push(addHistoryWithMinutesAgo(130)); // within past four hours
227  uris.push(addHistoryWithMinutesAgo(250)); // outside past four hours
228 
229  // Open the dialog and do our tests.
230  openWindow(function (aWin) {
231  let wh = new WindowHelper(aWin);
232  wh.selectDuration(Sanitizer.TIMESPAN_EVERYTHING);
233  wh.checkPrefCheckbox("history", true);
234  wh.acceptDialog();
235  ensureHistoryClearedState(uris, true);
236  });
237  }
238 ];
239 
240 // Used as the download database ID for a new download. Incremented for each
241 // new download. See addDownloadWithMinutesAgo().
242 var gDownloadId = 5555551;
243 
244 // Index in gAllTests of the test currently being run. Incremented for each
245 // test run. See doNextTest().
246 var gCurrTest = 0;
247 
248 var now_uSec = Date.now() * 1000;
249 
251 
264 function WindowHelper(aWin) {
265  this.win = aWin;
266 }
267 
268 WindowHelper.prototype = {
272  acceptDialog: function () {
273  is(this.win.document.documentElement.getButton("accept").disabled, false,
274  "Dialog's OK button should not be disabled");
275  this.win.document.documentElement.acceptDialog();
276  },
277 
281  cancelDialog: function () {
282  this.win.document.documentElement.cancelDialog();
283  },
284 
294  checkGrippy: function (aMsg, aExpectedRow) {
295  is(this.getGrippyRow(), aExpectedRow, aMsg);
296  this.checkTreeSelection();
297  this.ensureGrippyIsVisible();
298  },
299 
309  checkPrefCheckbox: function (aPrefName, aCheckState) {
310  var pref = "privacy.cpd." + aPrefName;
311  var cb = this.win.document.querySelectorAll(
312  "#itemList > [preference='" + pref + "']");
313  is(cb.length, 1, "found checkbox for " + pref + " preference");
314  if (cb[0].checked != aCheckState)
315  cb[0].click();
316  },
317 
323  checkTreeSelection: function () {
324  let grippyRow = this.getGrippyRow();
325  let sel = this.getTree().view.selection;
326  if (grippyRow === 0) {
327  is(sel.getRangeCount(), 0,
328  "Grippy row is 0, so no tree selection should exist");
329  }
330  else {
331  is(sel.getRangeCount(), 1,
332  "Grippy row > 0, so only one tree selection range should exist");
333  let min = {};
334  let max = {};
335  sel.getRangeAt(0, min, max);
336  is(min.value, 0, "Tree selection should start at first row");
337  is(max.value, grippyRow - 1,
338  "Tree selection should end at row before grippy");
339  }
340  },
341 
346  ensureGrippyIsVisible: function () {
347  let tbo = this.getTree().treeBoxObject;
348  let firstVis = tbo.getFirstVisibleRow();
349  let lastVis = tbo.getLastVisibleRow();
350  let grippyRow = this.getGrippyRow();
351  ok(firstVis <= grippyRow && grippyRow <= lastVis,
352  "Grippy row should be visible; this inequality should be true: " +
353  firstVis + " <= " + grippyRow + " <= " + lastVis);
354  },
355 
359  getDurationDropdown: function () {
360  return this.win.document.getElementById("sanitizeDurationChoice");
361  },
362 
366  getGrippyRow: function () {
367  return this.win.gContiguousSelectionTreeHelper.getGrippyRow();
368  },
369 
373  getRowCount: function () {
374  return this.getTree().view.rowCount;
375  },
376 
380  getTree: function () {
381  return this.win.gContiguousSelectionTreeHelper.tree;
382  },
383 
388  isWarningPanelVisible: function () {
389  return this.win.document.getElementById("durationDeck").selectedIndex == 1;
390  },
391 
395  isTreeVisible: function () {
396  return this.win.document.getElementById("durationDeck").selectedIndex == 0;
397  },
398 
406  moveGrippyBy: function (aDelta) {
407  if (aDelta === 0)
408  return;
409  let key = aDelta < 0 ? "UP" : "DOWN";
410  let abs = Math.abs(aDelta);
411  let treechildren = this.getTree().treeBoxObject.treeBody;
412  for (let i = 0; i < abs; i++) {
413  EventUtils.sendKey(key, treechildren);
414  }
415  },
416 
423  selectDuration: function (aDurVal) {
424  this.getDurationDropdown().value = aDurVal;
425  if (aDurVal === Sanitizer.TIMESPAN_EVERYTHING) {
426  is(this.isTreeVisible(), false,
427  "Tree should not be visible for TIMESPAN_EVERYTHING");
428  is(this.isWarningPanelVisible(), true,
429  "Warning panel should be visible for TIMESPAN_EVERYTHING");
430  }
431  else {
432  is(this.isTreeVisible(), true,
433  "Tree should be visible for non-TIMESPAN_EVERYTHING");
434  is(this.isWarningPanelVisible(), false,
435  "Warning panel should not be visible for non-TIMESPAN_EVERYTHING");
436  }
437  }
438 };
439 
446 function addDownloadWithMinutesAgo(aMinutesAgo) {
447  let name = "fakefile-" + aMinutesAgo + "-minutes-ago";
448  let data = {
449  id: gDownloadId,
450  name: name,
451  source: "https://bugzilla.mozilla.org/show_bug.cgi?id=480169",
452  target: name,
453  startTime: now_uSec - (aMinutesAgo * 60 * 1000000),
454  endTime: now_uSec - ((aMinutesAgo + 1) *60 * 1000000),
455  state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
456  currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0
457  };
458 
459  let db = dm.DBConnection;
460  let stmt = db.createStatement(
461  "INSERT INTO moz_downloads (id, name, source, target, startTime, endTime, " +
462  "state, currBytes, maxBytes, preferredAction, autoResume) " +
463  "VALUES (:id, :name, :source, :target, :startTime, :endTime, :state, " +
464  ":currBytes, :maxBytes, :preferredAction, :autoResume)");
465  try {
466  for (let prop in data) {
467  stmt.params[prop] = data[prop];
468  }
469  stmt.execute();
470  }
471  finally {
472  stmt.reset();
473  }
474 
475  is(downloadExists(gDownloadId), true,
476  "Sanity check: download " + gDownloadId +
477  " should exist after creating it");
478 
479  return gDownloadId++;
480 }
481 
488 function addFormEntryWithMinutesAgo(aMinutesAgo) {
489  let name = aMinutesAgo + "-minutes-ago";
490  formhist.addEntry(name, "dummy");
491 
492  // Artifically age the entry to the proper vintage.
493  let db = formhist.DBConnection;
494  let timestamp = now_uSec - (aMinutesAgo * 60 * 1000000);
495  db.executeSimpleSQL("UPDATE moz_formhistory SET firstUsed = " +
496  timestamp + " WHERE fieldname = '" + name + "'");
497 
498  is(formhist.nameExists(name), true,
499  "Sanity check: form entry " + name + " should exist after creating it");
500  return name;
501 }
502 
509 function addHistoryWithMinutesAgo(aMinutesAgo) {
510  let pURI = makeURI("http://" + aMinutesAgo + "-minutes-ago.com/");
511  bhist.addPageWithDetails(pURI,
512  aMinutesAgo + " minutes ago",
513  now_uSec - (aMinutesAgo * 60 * 1000 * 1000));
514  is(bhist.isVisited(pURI), true,
515  "Sanity check: history visit " + pURI.spec +
516  " should exist after creating it");
517  return pURI;
518 }
519 
523 function blankSlate() {
524  bhist.removeAllPages();
525  dm.cleanUp();
526  formhist.removeAllEntries();
527 }
528 
536 function downloadExists(aID)
537 {
538  let db = dm.DBConnection;
539  let stmt = db.createStatement(
540  "SELECT * " +
541  "FROM moz_downloads " +
542  "WHERE id = :id"
543  );
544  stmt.params.id = aID;
545  let rows = stmt.step();
546  stmt.finalize();
547  return !!rows;
548 }
549 
554 function doNextTest() {
555  if (gAllTests.length <= gCurrTest) {
556  blankSlate();
557  finish();
558  }
559  else {
560  let ct = gCurrTest;
561  gCurrTest++;
562  gAllTests[ct]();
563  }
564 }
565 
574 function ensureDownloadsClearedState(aDownloadIDs, aShouldBeCleared) {
575  let niceStr = aShouldBeCleared ? "no longer" : "still";
576  aDownloadIDs.forEach(function (id) {
577  is(downloadExists(id), !aShouldBeCleared,
578  "download " + id + " should " + niceStr + " exist");
579  });
580 }
581 
590 function ensureFormEntriesClearedState(aFormEntries, aShouldBeCleared) {
591  let niceStr = aShouldBeCleared ? "no longer" : "still";
592  aFormEntries.forEach(function (entry) {
593  is(formhist.nameExists(entry), !aShouldBeCleared,
594  "form entry " + entry + " should " + niceStr + " exist");
595  });
596 }
597 
606 function ensureHistoryClearedState(aURIs, aShouldBeCleared) {
607  let niceStr = aShouldBeCleared ? "no longer" : "still";
608  aURIs.forEach(function (aURI) {
609  is(bhist.isVisited(aURI), !aShouldBeCleared,
610  "history visit " + aURI.spec + " should " + niceStr + " exist");
611  });
612 }
613 
620 function openWindow(aOnloadCallback) {
621  let windowObserver = {
622  observe: function(aSubject, aTopic, aData) {
623  if (aTopic === "domwindowopened") {
624  winWatch.unregisterNotification(this);
625  let win = aSubject.QueryInterface(Ci.nsIDOMWindow);
626  win.addEventListener("load", function onload(event) {
627  win.removeEventListener("load", onload, false);
628  executeSoon(function () {
629  // Some exceptions that reach here don't reach the test harness, but
630  // ok()/is() do...
631  try {
632  aOnloadCallback(win);
633  doNextTest();
634  }
635  catch (exc) {
636  win.close();
637  ok(false, "Unexpected exception: " + exc + "\n" + exc.stack);
638  finish();
639  }
640  });
641  }, false);
642  }
643  }
644  };
645  winWatch.registerNotification(windowObserver);
646  winWatch.openWindow(null,
647  "chrome://browser/content/sanitize.xul",
648  "Sanitize",
649  "chrome,titlebar,dialog,centerscreen,modal",
650  null);
651 }
652 
654 
655 function test() {
656  blankSlate();
658  // Kick off all the tests in the gAllTests array.
659  doNextTest();
660 }
classDescription entry
Definition: FeedWriter.js:1427
const Cc
window onload
var uris
var pref
Definition: openLocation.js:44
function addFormEntryWithMinutesAgo(aMinutesAgo)
Cc["@mozilla.org/moz/jssubscript-loader;1"] getService(Components.interfaces.mozIJSSubScriptLoader).loadSubScript("chrome const winWatch
var event
function downloadExists(aID)
function doNextTest()
getService(Ci.sbIFaceplateManager)
function addHistoryWithMinutesAgo(aMinutesAgo)
function addDownloadWithMinutesAgo(aMinutesAgo)
function makeURI(aURLSpec, aCharset)
Definition: FeedWriter.js:71
function blankSlate()
waitForExplicitFinish()
function WindowHelper(aWin)
function ensureDownloadsClearedState(aDownloadIDs, aShouldBeCleared)
function ensureFormEntriesClearedState(aFormEntries, aShouldBeCleared)
function openWindow(aOnloadCallback)
return null
Definition: FeedWriter.js:1143
const Ci
function Sanitizer()
Definition: sanitize.js:42
#define min(a, b)
function ensureHistoryClearedState(aURIs, aShouldBeCleared)
observe data
Definition: FeedWriter.js:1329
_getSelectedPageStyle s i
_updateTextAndScrollDataForFrame aData
sbDeviceFirmwareAutoCheckForUpdate prototype observe