зеркало из https://github.com/mozilla/gecko-dev.git
Bug 341341 - automatically update installed microsummary generators. r=myk
This commit is contained in:
Родитель
3cedd5720a
Коммит
f822bfeed5
|
@ -239,6 +239,10 @@ pref("browser.search.update.log", false);
|
|||
// Check whether we need to perform engine updates every 6 hours
|
||||
pref("browser.search.updateinterval", 6);
|
||||
|
||||
// Whether or not microsummary and generator updates are enabled
|
||||
pref("browser.microsummary.enabled", true);
|
||||
pref("browser.microsummary.updateGenerators", true);
|
||||
|
||||
// enable search suggestions by default
|
||||
pref("browser.search.suggest.enabled", true);
|
||||
|
||||
|
|
|
@ -53,6 +53,8 @@ const NS_ERROR_DOM_BAD_URI = NS_ERROR_MODULE_DOM + 1012;
|
|||
|
||||
// How often to check for microsummaries that need updating, in milliseconds.
|
||||
const CHECK_INTERVAL = 15 * 1000; // 15 seconds
|
||||
// How often to check for generator updates, in seconds
|
||||
const GENERATOR_INTERVAL = 7 * 86400; // 1 week
|
||||
|
||||
const MICSUM_NS = new Namespace("http://www.mozilla.org/microsummaries/0.1");
|
||||
const XSLT_NS = new Namespace("http://www.w3.org/1999/XSL/Transform");
|
||||
|
@ -166,7 +168,7 @@ MicrosummaryService.prototype = {
|
|||
break;
|
||||
case "nsPref:changed":
|
||||
if (data == "enabled")
|
||||
this._initTimer();
|
||||
this._initTimers();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
@ -174,11 +176,11 @@ MicrosummaryService.prototype = {
|
|||
_init: function MSS__init() {
|
||||
this._obs.addObserver(this, "xpcom-shutdown", true);
|
||||
this._branch.addObserver("", this, true);
|
||||
this._initTimer();
|
||||
this._initTimers();
|
||||
this._cacheLocalGenerators();
|
||||
},
|
||||
|
||||
_initTimer: function MSS__initTimer() {
|
||||
_initTimers: function MSS__initTimers() {
|
||||
if (this._timer)
|
||||
this._timer.cancel();
|
||||
|
||||
|
@ -194,6 +196,18 @@ MicrosummaryService.prototype = {
|
|||
this._timer.initWithCallback(callback,
|
||||
CHECK_INTERVAL,
|
||||
this._timer.TYPE_REPEATING_SLACK);
|
||||
|
||||
// Setup a cross-session timer to periodically check for generator updates.
|
||||
var updateManager = Cc["@mozilla.org/updates/timer-manager;1"].
|
||||
getService(Ci.nsIUpdateTimerManager);
|
||||
var interval = getPref("browser.microsummary.generatorUpdateInterval",
|
||||
GENERATOR_INTERVAL);
|
||||
var updateCallback = {
|
||||
_svc: this,
|
||||
notify: function(timer) { this._svc._updateGenerators() }
|
||||
};
|
||||
updateManager.registerTimer("microsummary-generator-update-timer",
|
||||
updateCallback, interval);
|
||||
},
|
||||
|
||||
_destroy: function MSS__destroy() {
|
||||
|
@ -229,6 +243,16 @@ MicrosummaryService.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
_updateGenerators: function MSS__updateGenerators() {
|
||||
var generators = this._localGenerators;
|
||||
var update = getPref("browser.microsummary.updateGenerators", true);
|
||||
if (!generators || !update)
|
||||
return;
|
||||
|
||||
for (let uri in generators)
|
||||
generators[uri].update();
|
||||
},
|
||||
|
||||
_updateMicrosummary: function MSS__updateMicrosummary(bookmarkID, microsummary) {
|
||||
var title = this._getTitle(bookmarkID);
|
||||
|
||||
|
@ -325,12 +349,6 @@ MicrosummaryService.prototype = {
|
|||
if (!resource.isXML)
|
||||
throw(resource.uri.spec + " microsummary generator loaded, but not XML");
|
||||
|
||||
// Fix the generator's ID if it was installed before we started using URNs
|
||||
// to uniquely identify generators.
|
||||
// XXX This code can go away after Fx2 beta2, when enough users will have
|
||||
// upgraded from earlier versions to make bug 346822 no longer significant.
|
||||
this._fixGeneratorID(resource.content, resource.uri);
|
||||
|
||||
var generator = new MicrosummaryGenerator(null, resource.uri);
|
||||
generator.initFromXML(resource.content);
|
||||
|
||||
|
@ -345,52 +363,6 @@ MicrosummaryService.prototype = {
|
|||
" ID: " + generator.uri.spec);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fix the ID of a local generator that was installed before we started
|
||||
* using URNs to uniquely identify local generators.
|
||||
*
|
||||
* @param xmlDefinition
|
||||
* an nsIDOMDocument XML document defining the generator
|
||||
* @param localURI
|
||||
* an nsIURI file URI to the generator's local file
|
||||
*
|
||||
*/
|
||||
_fixGeneratorID: function MSS__fixGeneratorID(xmlDefinition, localURI) {
|
||||
var generatorNode = xmlDefinition.getElementsByTagNameNS(MICSUM_NS, "generator")[0];
|
||||
|
||||
if (!generatorNode)
|
||||
return;
|
||||
|
||||
// Don't fix generators that have already been fixed or were installed
|
||||
// after we switched to identifying generators by URN.
|
||||
if (generatorNode.hasAttribute("uri"))
|
||||
return;
|
||||
|
||||
// Don't fix generators that don't have any ID at all (we fall back to
|
||||
// the local URI in these cases, which is useful for developers during
|
||||
// the process of developing generators).
|
||||
if (!generatorNode.hasAttribute("sourceURI"))
|
||||
return;
|
||||
|
||||
var oldURI = generatorNode.getAttribute("sourceURI");
|
||||
var newURI = "urn:source:" + oldURI;
|
||||
|
||||
LOG("fixing generator with old-style ID\n" +
|
||||
" old ID: " + oldURI + "\n" +
|
||||
" new ID: " + newURI);
|
||||
|
||||
// Update the XML definition to reflect the change.
|
||||
generatorNode.setAttribute("uri", newURI);
|
||||
|
||||
// Save the updated XML definition to the local file.
|
||||
var file = localURI.QueryInterface(Ci.nsIFileURL).file.clone();
|
||||
this._saveGeneratorXML(xmlDefinition, file);
|
||||
|
||||
// Update bookmarks in the bookmarks datastore that are using
|
||||
// this microsummary generator to reflect the change.
|
||||
this._changeField(FIELD_MICSUM_GEN_URI, oldURI, newURI);
|
||||
},
|
||||
|
||||
// nsIMicrosummaryService
|
||||
|
||||
/**
|
||||
|
@ -458,29 +430,24 @@ MicrosummaryService.prototype = {
|
|||
var generator = this._localGenerators[generatorID];
|
||||
|
||||
var topic;
|
||||
var file;
|
||||
if (generator) {
|
||||
// This generator is already installed. Save it in the existing file
|
||||
// (i.e. update the existing generator with the newly downloaded XML).
|
||||
file = generator.localURI.QueryInterface(Ci.nsIFileURL).file.clone();
|
||||
if (generator)
|
||||
topic = "microsummary-generator-updated";
|
||||
}
|
||||
else {
|
||||
// This generator is not already installed. Save it as a new file.
|
||||
topic = "microsummary-generator-installed";
|
||||
var generatorName = rootNode.getAttribute("name");
|
||||
var fileName = sanitizeName(generatorName) + ".xml";
|
||||
file = this._dirs.get("UsrMicsumGens", Ci.nsIFile);
|
||||
var file = this._dirs.get("UsrMicsumGens", Ci.nsIFile);
|
||||
file.append(fileName);
|
||||
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, PERMS_FILE);
|
||||
generator = new MicrosummaryGenerator(null, this._ios.newFileURI(file));
|
||||
this._localGenerators[generatorID] = generator;
|
||||
topic = "microsummary-generator-installed";
|
||||
}
|
||||
|
||||
// Initialize (or reinitialize) the generator from its XML definition,
|
||||
// the save the definition to the generator's file.
|
||||
generator.initFromXML(xmlDefinition);
|
||||
this._saveGeneratorXML(xmlDefinition, file);
|
||||
generator.saveXMLToFile(xmlDefinition);
|
||||
|
||||
LOG("installed generator " + generatorID);
|
||||
|
||||
|
@ -489,37 +456,6 @@ MicrosummaryService.prototype = {
|
|||
return generator;
|
||||
},
|
||||
|
||||
/**
|
||||
* Save a generator's XML definition to a local file.
|
||||
*
|
||||
* @param xmlDefinition
|
||||
* an nsIDOMDocument XML document defining the generator
|
||||
* @param file
|
||||
* an nsIFile file representing the generator's local file
|
||||
*
|
||||
*/
|
||||
_saveGeneratorXML: function MSS_saveGeneratorXML(xmlDefinition, file) {
|
||||
LOG("saving definition to " + file.path);
|
||||
|
||||
// Write the generator XML to the local file.
|
||||
var outputStream = Cc["@mozilla.org/network/safe-file-output-stream;1"].
|
||||
createInstance(Ci.nsIFileOutputStream);
|
||||
var localFile = file.QueryInterface(Ci.nsILocalFile);
|
||||
outputStream.init(localFile, (MODE_WRONLY | MODE_TRUNCATE | MODE_CREATE),
|
||||
PERMS_FILE, 0);
|
||||
var serializer = Cc["@mozilla.org/xmlextras/xmlserializer;1"].
|
||||
createInstance(Ci.nsIDOMSerializer);
|
||||
serializer.serializeToStream(xmlDefinition, outputStream, null);
|
||||
if (outputStream instanceof Ci.nsISafeOutputStream) {
|
||||
try { outputStream.finish() }
|
||||
catch (e) { outputStream.close() }
|
||||
}
|
||||
else
|
||||
outputStream.close();
|
||||
},
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the set of microsummaries available for a given page. The set
|
||||
* might change after this method returns, since this method will trigger
|
||||
|
@ -1327,11 +1263,10 @@ MicrosummaryGenerator.prototype = {
|
|||
|
||||
this._name = generatorNode.getAttribute("name");
|
||||
|
||||
// If this is a local generator (i.e. it has a local URI), then we have
|
||||
// to retrieve its URI from the "uri" attribute of its generator tag.
|
||||
if (this.localURI && generatorNode.hasAttribute("uri")) {
|
||||
// We have to retrieve the URI from local generators via the "uri" attribute
|
||||
// of its generator tag.
|
||||
if (this.localURI && generatorNode.hasAttribute("uri"))
|
||||
this._uri = this._ios.newURI(generatorNode.getAttribute("uri"), null, null);
|
||||
}
|
||||
|
||||
function getFirstChildByTagName(tagName, parentNode, namespace) {
|
||||
var nodeList = parentNode.getElementsByTagNameNS(namespace, tagName);
|
||||
|
@ -1461,6 +1396,100 @@ MicrosummaryGenerator.prototype = {
|
|||
// XXX When we support HTML microsummaries we'll need to do something
|
||||
// more sophisticated than just returning the text content of the fragment.
|
||||
return fragment.textContent;
|
||||
},
|
||||
|
||||
saveXMLToFile: function MSD_saveXMLToFile(xmlDefinition) {
|
||||
var file = this.localURI.QueryInterface(Ci.nsIFileURL).file.clone();
|
||||
|
||||
LOG("saving definition to " + file.path);
|
||||
|
||||
// Write the generator XML to the local file.
|
||||
var outputStream = Cc["@mozilla.org/network/safe-file-output-stream;1"].
|
||||
createInstance(Ci.nsIFileOutputStream);
|
||||
var localFile = file.QueryInterface(Ci.nsILocalFile);
|
||||
outputStream.init(localFile, (MODE_WRONLY | MODE_TRUNCATE | MODE_CREATE),
|
||||
PERMS_FILE, 0);
|
||||
var serializer = Cc["@mozilla.org/xmlextras/xmlserializer;1"].
|
||||
createInstance(Ci.nsIDOMSerializer);
|
||||
serializer.serializeToStream(xmlDefinition, outputStream, null);
|
||||
if (outputStream instanceof Ci.nsISafeOutputStream) {
|
||||
try { outputStream.finish() }
|
||||
catch (e) { outputStream.close() }
|
||||
}
|
||||
else
|
||||
outputStream.close();
|
||||
},
|
||||
|
||||
update: function MSD_update() {
|
||||
// Update this generator if it was downloaded from a remote source and has
|
||||
// been modified since we last downloaded it.
|
||||
var genURI = this.uri;
|
||||
if (genURI && /^urn:source:/i.test(genURI.spec)) {
|
||||
let genURL = genURI.spec.replace(/^urn:source:/, "");
|
||||
genURI = this._ios.newURI(genURL, null, null);
|
||||
}
|
||||
|
||||
// Only continue if we have a valid remote URI
|
||||
if (!genURI || !/^https?/.test(genURI.scheme)) {
|
||||
LOG("generator did not have valid URI; skipping update: " + genURI.spec);
|
||||
return;
|
||||
}
|
||||
|
||||
// We use a HEAD request to check if the generator has been modified since
|
||||
// the last time we downloaded it. If it has, we move to _performUpdate() to
|
||||
// actually download and save the new generator.
|
||||
var t = this;
|
||||
var loadCallback = function(resource) {
|
||||
if (resource.status != 304)
|
||||
t._performUpdate(genURI);
|
||||
else
|
||||
LOG("generator is already up to date: " + genURI.spec);
|
||||
resource.destroy();
|
||||
};
|
||||
var errorCallback = function(resource) {
|
||||
resource.destroy();
|
||||
};
|
||||
|
||||
var file = this.localURI.QueryInterface(Ci.nsIFileURL).file.clone();
|
||||
var lastmod = new Date(file.lastModifiedTime);
|
||||
LOG("updating generator: " + genURI.spec);
|
||||
var resource = new MicrosummaryResource(genURI);
|
||||
resource.lastMod = lastmod.toUTCString();
|
||||
resource.method = "HEAD";
|
||||
resource.load(loadCallback, errorCallback);
|
||||
},
|
||||
|
||||
_performUpdate: function MSD__performUpdate(uri) {
|
||||
var t = this;
|
||||
var loadCallback = function(resource) {
|
||||
try { t._handleUpdateLoad(resource) }
|
||||
finally { resource.destroy() }
|
||||
};
|
||||
var errorCallback = function(resource) {
|
||||
resource.destroy();
|
||||
};
|
||||
|
||||
var resource = new MicrosummaryResource(uri);
|
||||
resource.load(loadCallback, errorCallback);
|
||||
},
|
||||
|
||||
_handleUpdateLoad: function MSD__handleUpdateLoad(resource) {
|
||||
if (!resource.isXML)
|
||||
throw("update failed, downloaded resource is not XML: " + this.uri.spec);
|
||||
|
||||
// Preserve the generator's ID.
|
||||
// XXX Check for redirects and update the URI if it changes.
|
||||
var generatorID = this.uri.spec;
|
||||
resource.content.documentElement.setAttribute("uri", generatorID);
|
||||
|
||||
// Reinitialize this generator with the newly downloaded XML and save to disk.
|
||||
this.initFromXML(resource.content);
|
||||
this.saveXMLToFile(resource.content);
|
||||
|
||||
// Let observers know we've updated this generator
|
||||
var obs = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
obs.notifyObservers(this, "microsummary-generator-updated", null);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1687,6 +1716,7 @@ function MicrosummaryResource(uri) {
|
|||
this.__authFailed = false;
|
||||
this._status = null;
|
||||
this._method = "GET";
|
||||
this._lastMod = null;
|
||||
|
||||
// A function to call when we finish loading/parsing the resource.
|
||||
this._loadCallback = null;
|
||||
|
@ -1728,6 +1758,9 @@ MicrosummaryResource.prototype = {
|
|||
get method() { return this._method },
|
||||
set method(aMethod) { this._method = aMethod },
|
||||
|
||||
get lastMod() { return this._lastMod },
|
||||
set lastMod(aMod) { this._lastMod = aMod },
|
||||
|
||||
// Implement notification callback interfaces so we can suppress UI
|
||||
// and abort loads for bad SSL certs and HTTP authorization requests.
|
||||
|
||||
|
@ -1998,6 +2031,8 @@ MicrosummaryResource.prototype = {
|
|||
request = request.QueryInterface(Ci.nsIXMLHttpRequest);
|
||||
request.open(this.method, this.uri.spec, true);
|
||||
request.setRequestHeader("X-Moz", "microsummary");
|
||||
if (this.lastMod)
|
||||
request.setRequestHeader("If-Modified-Since", this.lastMod);
|
||||
|
||||
// Register ourselves as a listener for notification callbacks so we
|
||||
// can handle authorization requests and SSL issues like cert mismatches.
|
||||
|
|
Загрузка…
Ссылка в новой задаче