fune/browser/components/extensions/ext-history.js
Kris Maglione 918ed6c474 Bug 1431533: Part 5a - Auto-rewrite code to use ChromeUtils import methods. r=florian
This was done using the following script:
37e3803c7a/processors/chromeutils-import.jsm

MozReview-Commit-ID: 1Nc3XDu0wGl

--HG--
extra : source : 12fc4dee861c812fd2bd032c63ef17af61800c70
extra : intermediate-source : 34c999fa006bffe8705cf50c54708aa21a962e62
extra : histedit_source : b2be2c5e5d226e6c347312456a6ae339c1e634b0
2018-01-29 15:20:18 -08:00

261 lines
8.7 KiB
JavaScript

/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
// The ext-* files are imported into the same scopes.
/* import-globals-from ext-browserAction.js */
ChromeUtils.defineModuleGetter(this, "PlacesUtils",
"resource://gre/modules/PlacesUtils.jsm");
ChromeUtils.defineModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
var {
normalizeTime,
} = ExtensionUtils;
let nsINavHistoryService = Ci.nsINavHistoryService;
const TRANSITION_TO_TRANSITION_TYPES_MAP = new Map([
["link", nsINavHistoryService.TRANSITION_LINK],
["typed", nsINavHistoryService.TRANSITION_TYPED],
["auto_bookmark", nsINavHistoryService.TRANSITION_BOOKMARK],
["auto_subframe", nsINavHistoryService.TRANSITION_EMBED],
["manual_subframe", nsINavHistoryService.TRANSITION_FRAMED_LINK],
["reload", nsINavHistoryService.TRANSITION_RELOAD],
]);
let TRANSITION_TYPE_TO_TRANSITIONS_MAP = new Map();
for (let [transition, transitionType] of TRANSITION_TO_TRANSITION_TYPES_MAP) {
TRANSITION_TYPE_TO_TRANSITIONS_MAP.set(transitionType, transition);
}
const getTransitionType = transition => {
// cannot set a default value for the transition argument as the framework sets it to null
transition = transition || "link";
let transitionType = TRANSITION_TO_TRANSITION_TYPES_MAP.get(transition);
if (!transitionType) {
throw new Error(`|${transition}| is not a supported transition for history`);
}
return transitionType;
};
const getTransition = transitionType => {
return TRANSITION_TYPE_TO_TRANSITIONS_MAP.get(transitionType) || "link";
};
/*
* Converts a nsINavHistoryResultNode into a HistoryItem
*
* https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsINavHistoryResultNode
*/
const convertNodeToHistoryItem = node => {
return {
id: node.pageGuid,
url: node.uri,
title: node.title,
lastVisitTime: PlacesUtils.toDate(node.time).getTime(),
visitCount: node.accessCount,
};
};
/*
* Converts a nsINavHistoryResultNode into a VisitItem
*
* https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsINavHistoryResultNode
*/
const convertNodeToVisitItem = node => {
return {
id: node.pageGuid,
visitId: String(node.visitId),
visitTime: PlacesUtils.toDate(node.time).getTime(),
referringVisitId: String(node.fromVisitId),
transition: getTransition(node.visitType),
};
};
/*
* Converts a nsINavHistoryContainerResultNode into an array of objects
*
* https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsINavHistoryContainerResultNode
*/
const convertNavHistoryContainerResultNode = (container, converter) => {
let results = [];
container.containerOpen = true;
for (let i = 0; i < container.childCount; i++) {
let node = container.getChild(i);
results.push(converter(node));
}
container.containerOpen = false;
return results;
};
var _observer;
const getHistoryObserver = () => {
if (!_observer) {
_observer = new class extends EventEmitter {
onDeleteURI(uri, guid, reason) {
this.emit("visitRemoved", {allHistory: false, urls: [uri.spec]});
}
onVisits(visits) {
for (let visit of visits) {
let data = {
id: visit.guid,
url: visit.uri.spec,
title: visit.lastKnownTitle || "",
lastVisitTime: visit.time / 1000, // time from Places is microseconds,
visitCount: visit.visitCount,
typedCount: visit.typed,
};
this.emit("visited", data);
}
}
onBeginUpdateBatch() {}
onEndUpdateBatch() {}
onTitleChanged(uri, title) {
this.emit("titleChanged", {url: uri.spec, title: title});
}
onClearHistory() {
this.emit("visitRemoved", {allHistory: true, urls: []});
}
onPageChanged() {}
onFrecencyChanged() {}
onManyFrecenciesChanged() {}
onDeleteVisits(uri, time, guid, reason) {
this.emit("visitRemoved", {allHistory: false, urls: [uri.spec]});
}
}();
PlacesUtils.history.addObserver(_observer);
}
return _observer;
};
this.history = class extends ExtensionAPI {
getAPI(context) {
return {
history: {
addUrl: function(details) {
let transition, date;
try {
transition = getTransitionType(details.transition);
} catch (error) {
return Promise.reject({message: error.message});
}
if (details.visitTime) {
date = normalizeTime(details.visitTime);
}
let pageInfo = {
title: details.title,
url: details.url,
visits: [
{
transition,
date,
},
],
};
try {
return PlacesUtils.history.insert(pageInfo).then(() => undefined);
} catch (error) {
return Promise.reject({message: error.message});
}
},
deleteAll: function() {
return PlacesUtils.history.clear();
},
deleteRange: function(filter) {
let newFilter = {
beginDate: normalizeTime(filter.startTime),
endDate: normalizeTime(filter.endTime),
};
// History.removeVisitsByFilter returns a boolean, but our API should return nothing
return PlacesUtils.history.removeVisitsByFilter(newFilter).then(() => undefined);
},
deleteUrl: function(details) {
let url = details.url;
// History.remove returns a boolean, but our API should return nothing
return PlacesUtils.history.remove(url).then(() => undefined);
},
search: function(query) {
let beginTime = (query.startTime == null) ?
PlacesUtils.toPRTime(Date.now() - 24 * 60 * 60 * 1000) :
PlacesUtils.toPRTime(normalizeTime(query.startTime));
let endTime = (query.endTime == null) ?
Number.MAX_VALUE :
PlacesUtils.toPRTime(normalizeTime(query.endTime));
if (beginTime > endTime) {
return Promise.reject({message: "The startTime cannot be after the endTime"});
}
let options = PlacesUtils.history.getNewQueryOptions();
options.includeHidden = true;
options.sortingMode = options.SORT_BY_DATE_DESCENDING;
options.maxResults = query.maxResults || 100;
let historyQuery = PlacesUtils.history.getNewQuery();
historyQuery.searchTerms = query.text;
historyQuery.beginTime = beginTime;
historyQuery.endTime = endTime;
let queryResult = PlacesUtils.history.executeQuery(historyQuery, options).root;
let results = convertNavHistoryContainerResultNode(queryResult, convertNodeToHistoryItem);
return Promise.resolve(results);
},
getVisits: function(details) {
let url = details.url;
if (!url) {
return Promise.reject({message: "A URL must be provided for getVisits"});
}
let options = PlacesUtils.history.getNewQueryOptions();
options.includeHidden = true;
options.sortingMode = options.SORT_BY_DATE_DESCENDING;
options.resultType = options.RESULTS_AS_VISIT;
let historyQuery = PlacesUtils.history.getNewQuery();
historyQuery.uri = Services.io.newURI(url);
let queryResult = PlacesUtils.history.executeQuery(historyQuery, options).root;
let results = convertNavHistoryContainerResultNode(queryResult, convertNodeToVisitItem);
return Promise.resolve(results);
},
onVisited: new EventManager(context, "history.onVisited", fire => {
let listener = (event, data) => {
fire.sync(data);
};
getHistoryObserver().on("visited", listener);
return () => {
getHistoryObserver().off("visited", listener);
};
}).api(),
onVisitRemoved: new EventManager(context, "history.onVisitRemoved", fire => {
let listener = (event, data) => {
fire.sync(data);
};
getHistoryObserver().on("visitRemoved", listener);
return () => {
getHistoryObserver().off("visitRemoved", listener);
};
}).api(),
onTitleChanged: new EventManager(context, "history.onTitleChanged", fire => {
let listener = (event, data) => {
fire.sync(data);
};
getHistoryObserver().on("titleChanged", listener);
return () => {
getHistoryObserver().off("titleChanged", listener);
};
}).api(),
},
};
}
};