Bug 520346 - Periodic update check for lightweight themes. r=dtownsend, sr=dveditz

This commit is contained in:
Dão Gottwald 2009-11-17 08:55:47 +01:00
parent 293039d851
commit 4d156fc8b5
5 changed files with 238 additions and 47 deletions

View File

@ -176,6 +176,8 @@ pref("extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.description", "chrome://
pref("xpinstall.whitelist.add", "addons.mozilla.org");
pref("xpinstall.whitelist.add.36", "getpersonas.com");
pref("lightweightThemes.update.enabled", true);
pref("keyword.enabled", true);
pref("keyword.URL", "chrome://browser-region/locale/region.properties");

View File

@ -7250,44 +7250,7 @@ var LightWeightThemeWebInstaller = {
},
_getThemeFromNode: function (node) {
const MANDATORY = ["id", "name", "headerURL"];
const OPTIONAL = ["footerURL", "textcolor", "accentcolor", "iconURL",
"previewURL", "author", "description", "homepageURL"];
try {
var data = JSON.parse(node.getAttribute("data-browsertheme"));
} catch (e) {
return null;
}
if (!data || typeof data != "object")
return null;
for (let prop in data) {
if (!data[prop] ||
typeof data[prop] != "string" ||
MANDATORY.indexOf(prop) == -1 && OPTIONAL.indexOf(prop) == -1) {
delete data[prop];
continue;
}
if (/URL$/.test(prop)) {
try {
data[prop] = makeURLAbsolute(node.baseURI, data[prop]);
if (/^https?:/.test(data[prop]))
continue;
} catch (e) {}
delete data[prop];
}
}
for (let i = 0; i < MANDATORY.length; i++) {
if (!(MANDATORY[i] in data))
return null;
}
return data;
return this._manager.parseTheme(node.getAttribute("data-browsertheme"),
node.baseURI);
}
}

View File

@ -38,8 +38,16 @@ var EXPORTED_SYMBOLS = ["LightweightThemeManager"];
const Cc = Components.classes;
const Ci = Components.interfaces;
const MAX_USED_THEMES_COUNT = 8;
const MAX_PREVIEW_SECONDS = 30;
const MANDATORY = ["id", "name", "headerURL"];
const OPTIONAL = ["footerURL", "textcolor", "accentcolor", "iconURL",
"previewURL", "author", "description", "homepageURL",
"updateURL", "version"];
const PERSIST_ENABLED = true;
const PERSIST_BYPASS_CACHE = false;
const PERSIST_FILES = {
@ -91,7 +99,8 @@ var LightweightThemeManager = {
for (let key in PERSIST_FILES) {
try {
if (data[key] && _prefs.getBoolPref("persisted." + key))
data[key] = _getLocalImageURI(PERSIST_FILES[key]).spec;
data[key] = _getLocalImageURI(PERSIST_FILES[key]).spec
+ "?" + data.id + ";" + _version(data);
} catch (e) {}
}
}
@ -176,12 +185,93 @@ var LightweightThemeManager = {
_previewTimer = null;
_notifyWindows(this.currentThemeForDisplay);
}
},
parseTheme: function (aString, aBaseURI) {
try {
var data = JSON.parse(aString);
} catch (e) {
return null;
}
if (!data || typeof data != "object")
return null;
for (let prop in data) {
if (typeof data[prop] == "string" &&
(data[prop] = data[prop].trim()) &&
(MANDATORY.indexOf(prop) > -1 || OPTIONAL.indexOf(prop) > -1)) {
if (!/URL$/.test(prop))
continue;
try {
data[prop] = _makeURI(data[prop], _makeURI(aBaseURI)).spec;
if (/^https:/.test(data[prop]))
continue;
if (prop != "updateURL" && /^http:/.test(data[prop]))
continue;
} catch (e) {}
}
delete data[prop];
}
for (let i = 0; i < MANDATORY.length; i++) {
if (!(MANDATORY[i] in data))
return null;
}
return data;
},
updateCurrentTheme: function () {
try {
if (!_prefs.getBoolPref("update.enabled"))
return;
} catch (e) {
return;
}
var theme = this.currentTheme;
if (!theme || !theme.updateURL)
return;
var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Ci.nsIXMLHttpRequest);
req.mozBackgroundRequest = true;
req.overrideMimeType("text/plain");
req.open("GET", theme.updateURL, true);
var self = this;
req.onload = function () {
if (req.status != 200)
return;
let newData = self.parseTheme(req.responseText, theme.updateURL);
if (!newData ||
newData.id != theme.id ||
_version(newData) == _version(theme))
return;
var currentTheme = self.currentTheme;
if (currentTheme && currentTheme.id == theme.id)
self.currentTheme = newData;
};
req.send(null);
}
};
function _usedThemesExceptId(aId)
LightweightThemeManager.usedThemes.filter(function (t) t.id != aId);
function _version(aThemeData)
aThemeData.version || "";
function _makeURI(aURL, aBaseURI)
_ioService.newURI(aURL, null, aBaseURI);
function _updateUsedThemes(aList) {
if (aList.length > MAX_USED_THEMES_COUNT)
aList.length = MAX_USED_THEMES_COUNT;
@ -227,7 +317,7 @@ function _getLocalImageURI(localFileName) {
function _persistImage(sourceURL, localFileName, callback) {
var targetURI = _getLocalImageURI(localFileName);
var sourceURI = _ioService.newURI(sourceURL, null, null);
var sourceURI = _makeURI(sourceURL);
var persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
.createInstance(Ci.nsIWebBrowserPersist);

View File

@ -2538,6 +2538,8 @@ ExtensionManager.prototype = {
Ci.nsIExtensionManager.UPDATE_CHECK_NEWVERSION,
new BackgroundUpdateCheckListener(this.datasource),
UPDATE_WHEN_PERIODIC_UPDATE);
LightweightThemeManager.updateCurrentTheme();
},
/**

View File

@ -1,11 +1,16 @@
const MANDATORY = ["id", "name", "headerURL"];
const OPTIONAL = ["footerURL", "textcolor", "accentcolor", "iconURL",
"previewURL", "author", "description", "homepageURL",
"updateURL", "version"];
function dummy(id) {
return {
id: id,
name: Math.random(),
headerURL: "about:blank",
footerURL: "about:blank",
textcolor: Math.random(),
accentcolor: Math.random()
id: id || Math.random().toString(),
name: Math.random().toString(),
headerURL: "http://lwttest.invalid/a.png",
footerURL: "http://lwttest.invalid/b.png",
textcolor: Math.random().toString(),
accentcolor: Math.random().toString()
};
}
@ -113,4 +118,133 @@ function run_test() {
ltm.forgetUsedTheme("x2");
do_check_eq(ltm.usedThemes.length, 0);
do_check_eq(ltm.currentTheme, null);
do_check_eq(ltm.parseTheme("invalid json"), null);
do_check_eq(ltm.parseTheme('"json string"'), null);
function roundtrip(data, secure) {
return ltm.parseTheme(JSON.stringify(data),
"http" + (secure ? "s" : "") + "://lwttest.invalid/");
}
var data = dummy();
do_check_neq(roundtrip(data), null);
data.id = null;
do_check_eq(roundtrip(data), null);
data.id = 1;
do_check_eq(roundtrip(data), null);
data.id = 1.5;
do_check_eq(roundtrip(data), null);
data.id = true;
do_check_eq(roundtrip(data), null);
data.id = {};
do_check_eq(roundtrip(data), null);
data.id = [];
do_check_eq(roundtrip(data), null);
data = dummy();
data.unknownProperty = "Foo";
do_check_eq(typeof roundtrip(data).unknownProperty, "undefined");
data = dummy();
data.unknownURL = "http://lwttest.invalid/";
do_check_eq(typeof roundtrip(data).unknownURL, "undefined");
function roundtripSet(props, modify, test, secure) {
props.forEach(function (prop) {
var data = dummy();
modify(data, prop);
test(roundtrip(data, secure), prop, data);
});
}
roundtripSet(MANDATORY, function (data, prop) {
delete data[prop];
}, function (after) {
do_check_eq(after, null);
});
roundtripSet(OPTIONAL, function (data, prop) {
delete data[prop];
}, function (after) {
do_check_neq(after, null);
});
roundtripSet(MANDATORY, function (data, prop) {
data[prop] = "";
}, function (after) {
do_check_eq(after, null);
});
roundtripSet(OPTIONAL, function (data, prop) {
data[prop] = "";
}, function (after, prop) {
do_check_eq(typeof after[prop], "undefined");
});
roundtripSet(MANDATORY, function (data, prop) {
data[prop] = " ";
}, function (after) {
do_check_eq(after, null);
});
roundtripSet(OPTIONAL, function (data, prop) {
data[prop] = " ";
}, function (after, prop) {
do_check_neq(after, null);
do_check_eq(typeof after[prop], "undefined");
});
function non_urls(props) {
return props.filter(function (prop) !/URL$/.test(prop));
}
function urls(props) {
return props.filter(function (prop) /URL$/.test(prop));
}
roundtripSet(non_urls(MANDATORY.concat(OPTIONAL)), function (data, prop) {
data[prop] = prop;
}, function (after, prop, before) {
do_check_eq(after[prop], before[prop]);
});
roundtripSet(non_urls(MANDATORY.concat(OPTIONAL)), function (data, prop) {
data[prop] = " " + prop + " ";
}, function (after, prop, before) {
do_check_eq(after[prop], before[prop].trim());
});
roundtripSet(urls(MANDATORY.concat(OPTIONAL)), function (data, prop) {
data[prop] = Math.random().toString();
}, function (after, prop, before) {
if (prop == "updateURL")
do_check_eq(typeof after[prop], "undefined");
else
do_check_eq(after[prop], "http://lwttest.invalid/" + before[prop]);
});
roundtripSet(urls(MANDATORY.concat(OPTIONAL)), function (data, prop) {
data[prop] = Math.random().toString();
}, function (after, prop, before) {
do_check_eq(after[prop], "https://lwttest.invalid/" + before[prop]);
}, true);
roundtripSet(urls(MANDATORY.concat(OPTIONAL)), function (data, prop) {
data[prop] = "https://sub.lwttest.invalid/" + Math.random().toString();
}, function (after, prop, before) {
do_check_eq(after[prop], before[prop]);
});
roundtripSet(urls(MANDATORY), function (data, prop) {
data[prop] = "ftp://lwttest.invalid/" + Math.random().toString();
}, function (after) {
do_check_eq(after, null);
});
roundtripSet(urls(OPTIONAL), function (data, prop) {
data[prop] = "ftp://lwttest.invalid/" + Math.random().toString();
}, function (after, prop) {
do_check_eq(typeof after[prop], "undefined");
});
}