Bug 1431194 - avoid timeouts when clearing prefs set via pushPrefEnv;r=jmaher

MozReview-Commit-ID: 1EYsxYnj2GE

--HG--
extra : rebase_source : dfa5d822e46387d9d473b5b744289f15f4410dbe
This commit is contained in:
Julian Descottes 2018-01-17 21:51:54 +01:00
Родитель fc2ae75233
Коммит 8aa7939bd1
2 изменённых файлов: 57 добавлений и 6 удалений

Просмотреть файл

@ -21,6 +21,7 @@ function starttest() {
SpecialPowers.setIntPref("test.int", 1);
}
SpecialPowers.setCharPref("test.char", 'test');
SpecialPowers.setBoolPref("test.cleanup", false);
setTimeout(test1, 0, 0);
}
@ -200,9 +201,29 @@ function test11(aCount) {
SpecialPowers.getCharPref('test.char');
setTimeout(test11, 0, ++aCount);
} catch(e) {
SimpleTest.finish();
test12();
}
}
function test12() {
// Set test.cleanup to true via pushPrefEnv, while its default value is false.
SpecialPowers.pushPrefEnv({"set": [["test.cleanup", true]]}, () => {
// Update the preference manually back to its original value.
SpecialPowers.setBoolPref("test.cleanup", false);
setTimeout(test13, 0);
});
}
function test13() {
// Try to flush preferences. Since test.cleanup has manually been set to false, there
// will not be any visible update. Check that the flush does not timeout.
SpecialPowers.flushPrefEnv(() => {
ok(true, 'flushPrefEnv did not time out');
is(SpecialPowers.getBoolPref('test.cleanup'), false, 'test.cleanup should be false');
SimpleTest.finish();
});
}
// todo - test non-changing values, test complex values, test mixing of pushprefEnv 'set' and 'clear'
// When bug 776424 gets fixed, getPref doesn't throw anymore, so this test would have to be changed accordingly
</script>

Просмотреть файл

@ -1191,6 +1191,22 @@ SpecialPowersAPI.prototype = {
});
},
_isPrefActionNeeded(prefAction) {
if (prefAction.action === "clear") {
return Services.prefs.prefHasUserValue(prefAction.name);
} else if (prefAction.action === "set") {
try {
let currentValue = this._getPref(prefAction.name, prefAction.type, {});
return currentValue != prefAction.value;
} catch (e) {
// If the preference is not defined yet, setting the value will have an effect.
return true;
}
}
// Only "clear" and "set" actions are supported.
return false;
},
/*
Iterate through one atomic set of pref actions and perform sets/clears as appropriate.
All actions performed must modify the relevant pref.
@ -1206,19 +1222,33 @@ SpecialPowersAPI.prototype = {
var pendingActions = transaction[0];
var callback = transaction[1];
var lastPref = pendingActions[pendingActions.length - 1];
// Filter out all the pending actions that will not have any effect.
pendingActions = pendingActions.filter(action => {
return this._isPrefActionNeeded(action);
});
var pb = Services.prefs;
var self = this;
pb.addObserver(lastPref.name, function prefObs(subject, topic, data) {
pb.removeObserver(lastPref.name, prefObs);
let onPrefActionsApplied = function() {
self._setTimeout(callback);
self._setTimeout(function() {
self._applyingPrefs = false;
// Now apply any prefs that may have been queued while we were applying
self._applyPrefs();
});
};
// If no valid action remains, call onPrefActionsApplied directly and bail out.
if (pendingActions.length === 0) {
onPrefActionsApplied();
return;
}
var lastPref = pendingActions[pendingActions.length - 1];
var pb = Services.prefs;
pb.addObserver(lastPref.name, function prefObs(subject, topic, data) {
pb.removeObserver(lastPref.name, prefObs);
onPrefActionsApplied();
});
for (var idx in pendingActions) {