summaryrefslogtreecommitdiffstats
path: root/toolkit/components/places/tests/unit/test_history_clear.js
blob: 56d34994f7aba274a899d8dc55e44fcc3bbdeaf7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

var mDBConn = DBConn();

function promiseOnClearHistoryObserved() {
  let deferred = Promise.defer();

  let historyObserver = {
    onBeginUpdateBatch: function() {},
    onEndUpdateBatch: function() {},
    onVisit: function() {},
    onTitleChanged: function() {},
    onDeleteURI: function(aURI) {},
    onPageChanged: function() {},
    onDeleteVisits: function() {},

    onClearHistory: function() {
      PlacesUtils.history.removeObserver(this, false);
      deferred.resolve();
    },

    QueryInterface: XPCOMUtils.generateQI([
      Ci.nsINavHistoryObserver,
    ])
  }
  PlacesUtils.history.addObserver(historyObserver, false);
  return deferred.promise;
}

// This global variable is a promise object, initialized in run_test and waited
// upon in the first asynchronous test.  It is resolved when the
// "places-init-complete" notification is received. We cannot initialize it in
// the asynchronous test, because then it's too late to register the observer.
var promiseInit;

function run_test() {
  // places-init-complete is notified after run_test, and it will
  // run a first frecency fix through async statements.
  // To avoid random failures we have to run after all of this.
  promiseInit = promiseTopicObserved(PlacesUtils.TOPIC_INIT_COMPLETE);

  run_next_test();
}

add_task(function* test_history_clear()
{
  yield promiseInit;

  yield PlacesTestUtils.addVisits([
    { uri: uri("http://typed.mozilla.org/"),
      transition: TRANSITION_TYPED },
    { uri: uri("http://link.mozilla.org/"),
      transition: TRANSITION_LINK },
    { uri: uri("http://download.mozilla.org/"),
      transition: TRANSITION_DOWNLOAD },
    { uri: uri("http://redir_temp.mozilla.org/"),
      transition: TRANSITION_REDIRECT_TEMPORARY,
      referrer: "http://link.mozilla.org/"},
    { uri: uri("http://redir_perm.mozilla.org/"),
      transition: TRANSITION_REDIRECT_PERMANENT,
      referrer: "http://link.mozilla.org/"},
  ]);

  // add a place: bookmark
  PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
                                       uri("place:folder=4"),
                                       PlacesUtils.bookmarks.DEFAULT_INDEX,
                                       "shortcut");

  // Add an expire never annotation
  // Actually expire never annotations are removed as soon as a page is removed
  // from the database, so this should act as a normal visit.
  PlacesUtils.annotations.setPageAnnotation(uri("http://download.mozilla.org/"),
                                            "never", "never", 0,
                                            PlacesUtils.annotations.EXPIRE_NEVER);

  // Add a bookmark
  // Bookmarked page should have history cleared and frecency = -1
  PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
                                       uri("http://typed.mozilla.org/"),
                                       PlacesUtils.bookmarks.DEFAULT_INDEX,
                                       "bookmark");

  yield PlacesTestUtils.addVisits([
    { uri: uri("http://typed.mozilla.org/"),
      transition: TRANSITION_BOOKMARK },
    { uri: uri("http://frecency.mozilla.org/"),
      transition: TRANSITION_LINK },
  ]);
  yield PlacesTestUtils.promiseAsyncUpdates();

  // Clear history and wait for the onClearHistory notification.
  let promiseWaitClearHistory = promiseOnClearHistoryObserved();
  PlacesUtils.history.clear();
  yield promiseWaitClearHistory;

  // check browserHistory returns no entries
  do_check_eq(0, PlacesUtils.history.hasHistoryEntries);

  yield promiseTopicObserved(PlacesUtils.TOPIC_EXPIRATION_FINISHED);
  yield PlacesTestUtils.promiseAsyncUpdates();

  // Check that frecency for not cleared items (bookmarks) has been converted
  // to -1.
  stmt = mDBConn.createStatement(
    "SELECT h.id FROM moz_places h WHERE h.frecency > 0 ");
  do_check_false(stmt.executeStep());
  stmt.finalize();

  stmt = mDBConn.createStatement(
    `SELECT h.id FROM moz_places h WHERE h.frecency < 0
       AND EXISTS (SELECT id FROM moz_bookmarks WHERE fk = h.id) LIMIT 1`);
  do_check_true(stmt.executeStep());
  stmt.finalize();

  // Check that all visit_counts have been brought to 0
  stmt = mDBConn.createStatement(
    "SELECT id FROM moz_places WHERE visit_count <> 0 LIMIT 1");
  do_check_false(stmt.executeStep());
  stmt.finalize();

  // Check that history tables are empty
  stmt = mDBConn.createStatement(
    "SELECT * FROM (SELECT id FROM moz_historyvisits LIMIT 1)");
  do_check_false(stmt.executeStep());
  stmt.finalize();

  // Check that all moz_places entries except bookmarks and place: have been removed
  stmt = mDBConn.createStatement(
    `SELECT h.id FROM moz_places h WHERE
       url_hash NOT BETWEEN hash('place', 'prefix_lo') AND hash('place', 'prefix_hi')
       AND NOT EXISTS (SELECT id FROM moz_bookmarks WHERE fk = h.id) LIMIT 1`);
  do_check_false(stmt.executeStep());
  stmt.finalize();

  // Check that we only have favicons for retained places
  stmt = mDBConn.createStatement(
    `SELECT f.id FROM moz_favicons f WHERE NOT EXISTS
       (SELECT id FROM moz_places WHERE favicon_id = f.id) LIMIT 1`);
  do_check_false(stmt.executeStep());
  stmt.finalize();

  // Check that we only have annotations for retained places
  stmt = mDBConn.createStatement(
    `SELECT a.id FROM moz_annos a WHERE NOT EXISTS
       (SELECT id FROM moz_places WHERE id = a.place_id) LIMIT 1`);
  do_check_false(stmt.executeStep());
  stmt.finalize();

  // Check that we only have inputhistory for retained places
  stmt = mDBConn.createStatement(
    `SELECT i.place_id FROM moz_inputhistory i WHERE NOT EXISTS
       (SELECT id FROM moz_places WHERE id = i.place_id) LIMIT 1`);
  do_check_false(stmt.executeStep());
  stmt.finalize();

  // Check that place:uris have frecency 0
  stmt = mDBConn.createStatement(
    `SELECT h.id FROM moz_places h
     WHERE url_hash BETWEEN hash('place', 'prefix_lo')
                        AND hash('place', 'prefix_hi')
       AND h.frecency <> 0 LIMIT 1`);
  do_check_false(stmt.executeStep());
  stmt.finalize();
});