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/* This is a JavaScript module (JSM) to be imported via 6 * Components.utils.import() and acts as a singleton. Only the following 7 * listed symbols will exposed on import, and only when and where imported. 8 */ 9 10var EXPORTED_SYMBOLS = ["HistoryEntry", "DumpHistory"]; 11 12const { PlacesUtils } = ChromeUtils.import( 13 "resource://gre/modules/PlacesUtils.jsm" 14); 15const { PlacesSyncUtils } = ChromeUtils.import( 16 "resource://gre/modules/PlacesSyncUtils.jsm" 17); 18const { Logger } = ChromeUtils.import("resource://tps/logger.jsm"); 19 20var DumpHistory = async function TPS_History__DumpHistory() { 21 let query = PlacesUtils.history.getNewQuery(); 22 let options = PlacesUtils.history.getNewQueryOptions(); 23 let root = PlacesUtils.history.executeQuery(query, options).root; 24 root.containerOpen = true; 25 Logger.logInfo("\n\ndumping history\n", true); 26 for (var i = 0; i < root.childCount; i++) { 27 let node = root.getChild(i); 28 let uri = node.uri; 29 let guid = await PlacesSyncUtils.history 30 .fetchGuidForURL(uri) 31 .catch(() => "?".repeat(12)); 32 let curvisits = await PlacesSyncUtils.history.fetchVisitsForURL(uri); 33 for (var visit of curvisits) { 34 Logger.logInfo( 35 `GUID: ${guid}, URI: ${uri}, type=${visit.type}, date=${visit.date}`, 36 true 37 ); 38 } 39 } 40 root.containerOpen = false; 41 Logger.logInfo("\nend history dump\n", true); 42}; 43 44/** 45 * HistoryEntry object 46 * 47 * Contains methods for manipulating browser history entries. 48 */ 49var HistoryEntry = { 50 /** 51 * Add 52 * 53 * Adds visits for a uri to the history database. Throws on error. 54 * 55 * @param item An object representing one or more visits to a specific uri 56 * @param usSinceEpoch The number of microseconds from Epoch to 57 * the time the current Crossweave run was started 58 * @return nothing 59 */ 60 async Add(item, msSinceEpoch) { 61 Logger.AssertTrue( 62 "visits" in item && "uri" in item, 63 "History entry in test file must have both 'visits' " + 64 "and 'uri' properties" 65 ); 66 let place = { 67 url: item.uri, 68 visits: [], 69 }; 70 for (let visit of item.visits) { 71 let date = new Date( 72 Math.round(msSinceEpoch + visit.date * 60 * 60 * 1000) 73 ); 74 place.visits.push({ date, transition: visit.type }); 75 } 76 if ("title" in item) { 77 place.title = item.title; 78 } 79 return PlacesUtils.history.insert(place); 80 }, 81 82 /** 83 * Find 84 * 85 * Finds visits for a uri to the history database. Throws on error. 86 * 87 * @param item An object representing one or more visits to a specific uri 88 * @param usSinceEpoch The number of microseconds from Epoch to 89 * the time the current Crossweave run was started 90 * @return true if all the visits for the uri are found, otherwise false 91 */ 92 async Find(item, msSinceEpoch) { 93 Logger.AssertTrue( 94 "visits" in item && "uri" in item, 95 "History entry in test file must have both 'visits' " + 96 "and 'uri' properties" 97 ); 98 let curvisits = await PlacesSyncUtils.history.fetchVisitsForURL(item.uri); 99 for (let visit of curvisits) { 100 for (let itemvisit of item.visits) { 101 // Note: in microseconds. 102 let expectedDate = 103 itemvisit.date * 60 * 60 * 1000 * 1000 + msSinceEpoch * 1000; 104 if (visit.type == itemvisit.type) { 105 if (itemvisit.date === undefined || visit.date == expectedDate) { 106 itemvisit.found = true; 107 } 108 } 109 } 110 } 111 112 let all_items_found = true; 113 for (let itemvisit of item.visits) { 114 all_items_found = all_items_found && "found" in itemvisit; 115 Logger.logInfo( 116 `History entry for ${item.uri}, type: ${itemvisit.type}, date: ${itemvisit.date}` + 117 `(${itemvisit.date * 118 60 * 119 60 * 120 1000 * 121 1000}), found = ${!!itemvisit.found}` 122 ); 123 } 124 return all_items_found; 125 }, 126 127 /** 128 * Delete 129 * 130 * Removes visits from the history database. Throws on error. 131 * 132 * @param item An object representing items to delete 133 * @param usSinceEpoch The number of microseconds from Epoch to 134 * the time the current Crossweave run was started 135 * @return nothing 136 */ 137 async Delete(item, msSinceEpoch) { 138 if ("uri" in item) { 139 let removedAny = await PlacesUtils.history.remove(item.uri); 140 if (!removedAny) { 141 Logger.log("Warning: Removed 0 history visits for uri " + item.uri); 142 } 143 } else if ("host" in item) { 144 await PlacesUtils.history.removeByFilter({ host: item.host }); 145 } else if ("begin" in item && "end" in item) { 146 let filter = { 147 beginDate: new Date(msSinceEpoch + item.begin * 60 * 60 * 1000), 148 endDate: new Date(msSinceEpoch + item.end * 60 * 60 * 1000), 149 }; 150 let removedAny = await PlacesUtils.history.removeVisitsByFilter(filter); 151 if (!removedAny) { 152 Logger.log( 153 "Warning: Removed 0 history visits with " + 154 JSON.stringify({ item, filter }) 155 ); 156 } 157 } else { 158 Logger.AssertTrue( 159 false, 160 "invalid entry in delete history " + JSON.stringify(item) 161 ); 162 } 163 }, 164}; 165