mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backing out bug 893276 for causing bug 1058840.
This commit is contained in:
parent
e527d34eaf
commit
7a33dc951e
@ -8,16 +8,13 @@ module.metadata = {
|
||||
"stability": "stable"
|
||||
};
|
||||
|
||||
const { Cc, Ci, Cu } = require("chrome");
|
||||
const { Cc, Ci } = require("chrome");
|
||||
const file = require("./io/file");
|
||||
const prefs = require("./preferences/service");
|
||||
const jpSelf = require("./self");
|
||||
const timer = require("./timers");
|
||||
const unload = require("./system/unload");
|
||||
const { emit, on, off } = require("./event/core");
|
||||
const { defer } = require('./core/promise');
|
||||
|
||||
const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
|
||||
|
||||
const WRITE_PERIOD_PREF = "extensions.addon-sdk.simple-storage.writePeriod";
|
||||
const WRITE_PERIOD_DEFAULT = 300000; // 5 minutes
|
||||
@ -38,57 +35,6 @@ Object.defineProperties(exports, {
|
||||
}
|
||||
});
|
||||
|
||||
function getHash(data) {
|
||||
let { promise, resolve } = defer();
|
||||
|
||||
let crypto = Cc["@mozilla.org/security/hash;1"].createInstance(Ci.nsICryptoHash);
|
||||
crypto.init(crypto.MD5);
|
||||
|
||||
let listener = {
|
||||
onStartRequest: function() { },
|
||||
|
||||
onDataAvailable: function(request, context, inputStream, offset, count) {
|
||||
crypto.updateFromStream(inputStream, count);
|
||||
},
|
||||
|
||||
onStopRequest: function(request, context, status) {
|
||||
resolve(crypto.finish(false));
|
||||
}
|
||||
};
|
||||
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
|
||||
createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
let stream = converter.convertToInputStream(data);
|
||||
let pump = Cc["@mozilla.org/network/input-stream-pump;1"].
|
||||
createInstance(Ci.nsIInputStreamPump);
|
||||
pump.init(stream, -1, -1, 0, 0, true);
|
||||
pump.asyncRead(listener, null);
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
function writeData(filename, data) {
|
||||
let { promise, resolve, reject } = defer();
|
||||
|
||||
let stream = file.open(filename, "w");
|
||||
try {
|
||||
stream.writeAsync(data, err => {
|
||||
if (err)
|
||||
reject(err);
|
||||
else
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
catch (err) {
|
||||
// writeAsync closes the stream after it's done, so only close on error.
|
||||
stream.close();
|
||||
reject(err);
|
||||
}
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
// A generic JSON store backed by a file on disk. This should be isolated
|
||||
// enough to move to its own module if need be...
|
||||
function JsonStore(options) {
|
||||
@ -97,9 +43,11 @@ function JsonStore(options) {
|
||||
this.writePeriod = options.writePeriod;
|
||||
this.onOverQuota = options.onOverQuota;
|
||||
this.onWrite = options.onWrite;
|
||||
this.hash = null;
|
||||
|
||||
unload.ensure(this);
|
||||
this.startTimer();
|
||||
|
||||
this.writeTimer = timer.setInterval(this.write.bind(this),
|
||||
this.writePeriod);
|
||||
}
|
||||
|
||||
JsonStore.prototype = {
|
||||
@ -133,18 +81,11 @@ JsonStore.prototype = {
|
||||
undefined;
|
||||
},
|
||||
|
||||
startTimer: function JsonStore_startTimer() {
|
||||
timer.setTimeout(() => {
|
||||
this.write().then(this.startTimer.bind(this));
|
||||
}, this.writePeriod);
|
||||
},
|
||||
|
||||
// Removes the backing file and all empty subdirectories.
|
||||
purge: function JsonStore_purge() {
|
||||
try {
|
||||
// This'll throw if the file doesn't exist.
|
||||
file.remove(this.filename);
|
||||
this.hash = null;
|
||||
let parentPath = this.filename;
|
||||
do {
|
||||
parentPath = file.dirname(parentPath);
|
||||
@ -164,25 +105,31 @@ JsonStore.prototype = {
|
||||
// errors cause tests to fail. Supporting "known" errors in the test
|
||||
// harness appears to be non-trivial. Maybe later.
|
||||
this.root = JSON.parse(str);
|
||||
let self = this;
|
||||
getHash(str).then(hash => this.hash = hash);
|
||||
}
|
||||
catch (err) {
|
||||
this.root = {};
|
||||
this.hash = null;
|
||||
}
|
||||
},
|
||||
|
||||
// If the store is under quota, writes the root to the backing file.
|
||||
// Otherwise quota observers are notified and nothing is written.
|
||||
write: function JsonStore_write() {
|
||||
if (this.quotaUsage > 1)
|
||||
this.onOverQuota(this);
|
||||
else
|
||||
this._write();
|
||||
},
|
||||
|
||||
// Cleans up on unload. If unloading because of uninstall, the store is
|
||||
// purged; otherwise it's written.
|
||||
unload: function JsonStore_unload(reason) {
|
||||
timer.clearTimeout(this.writeTimer);
|
||||
timer.clearInterval(this.writeTimer);
|
||||
this.writeTimer = null;
|
||||
|
||||
if (reason === "uninstall")
|
||||
this.purge();
|
||||
else
|
||||
this.write();
|
||||
this._write();
|
||||
},
|
||||
|
||||
// True if the root is an empty object.
|
||||
@ -201,40 +148,32 @@ JsonStore.prototype = {
|
||||
// Writes the root to the backing file, notifying write observers when
|
||||
// complete. If the store is over quota or if it's empty and the store has
|
||||
// never been written, nothing is written and write observers aren't notified.
|
||||
write: Task.async(function JsonStore_write() {
|
||||
_write: function JsonStore__write() {
|
||||
// Don't write if the root is uninitialized or if the store is empty and the
|
||||
// backing file doesn't yet exist.
|
||||
if (!this.isRootInited || (this._isEmpty && !file.exists(this.filename)))
|
||||
return;
|
||||
|
||||
let data = JSON.stringify(this.root);
|
||||
|
||||
// If the store is over quota, don't write. The current under-quota state
|
||||
// should persist.
|
||||
if ((this.quota > 0) && (data.length > this.quota)) {
|
||||
this.onOverQuota(this);
|
||||
return;
|
||||
}
|
||||
|
||||
// Hash the data to compare it to any previously written data
|
||||
let hash = yield getHash(data);
|
||||
|
||||
if (hash == this.hash)
|
||||
if (this.quotaUsage > 1)
|
||||
return;
|
||||
|
||||
// Finally, write.
|
||||
let stream = file.open(this.filename, "w");
|
||||
try {
|
||||
yield writeData(this.filename, data);
|
||||
|
||||
this.hash = hash;
|
||||
if (this.onWrite)
|
||||
this.onWrite(this);
|
||||
stream.writeAsync(JSON.stringify(this.root), function writeAsync(err) {
|
||||
if (err)
|
||||
console.error("Error writing simple storage file: " + this.filename);
|
||||
else if (this.onWrite)
|
||||
this.onWrite(this);
|
||||
}.bind(this));
|
||||
}
|
||||
catch (err) {
|
||||
console.error("Error writing simple storage file: " + this.filename);
|
||||
console.error(err);
|
||||
// writeAsync closes the stream after it's done, so only close on error.
|
||||
stream.close();
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -6,7 +6,6 @@ const file = require("sdk/io/file");
|
||||
const prefs = require("sdk/preferences/service");
|
||||
|
||||
const QUOTA_PREF = "extensions.addon-sdk.simple-storage.quota";
|
||||
const WRITE_PERIOD_PREF = "extensions.addon-sdk.simple-storage.writePeriod";
|
||||
|
||||
let {Cc,Ci} = require("chrome");
|
||||
|
||||
@ -35,13 +34,12 @@ exports.testSetGet = function (assert, done) {
|
||||
// Load the module again and make sure the value stuck.
|
||||
loader = Loader(module);
|
||||
ss = loader.require("sdk/simple-storage");
|
||||
assert.equal(ss.storage.foo, val, "Value should persist");
|
||||
manager(loader).jsonStore.onWrite = function (storage) {
|
||||
assert.fail("Nothing should be written since `storage` was not changed.");
|
||||
file.remove(storeFilename);
|
||||
done();
|
||||
};
|
||||
assert.equal(ss.storage.foo, val, "Value should persist");
|
||||
loader.unload();
|
||||
file.remove(storeFilename);
|
||||
done();
|
||||
};
|
||||
let val = "foo";
|
||||
ss.storage.foo = val;
|
||||
@ -162,11 +160,10 @@ exports.testQuotaExceededHandle = function (assert, done) {
|
||||
assert.equal(ss.storage.x, 4, "x value should be correct");
|
||||
assert.equal(ss.storage.y, 5, "y value should be correct");
|
||||
manager(loader).jsonStore.onWrite = function (storage) {
|
||||
assert.fail("Nothing should be written since `storage` was not changed.");
|
||||
prefs.reset(QUOTA_PREF);
|
||||
done();
|
||||
};
|
||||
loader.unload();
|
||||
prefs.reset(QUOTA_PREF);
|
||||
done();
|
||||
};
|
||||
loader.unload();
|
||||
});
|
||||
@ -200,9 +197,6 @@ exports.testQuotaExceededNoHandle = function (assert, done) {
|
||||
assert.equal(ss.storage, val,
|
||||
"Over-quota value should not have been written, " +
|
||||
"old value should have persisted: " + ss.storage);
|
||||
manager(loader).jsonStore.onWrite = function (storage) {
|
||||
assert.fail("Nothing should be written since `storage` was not changed.");
|
||||
};
|
||||
loader.unload();
|
||||
prefs.reset(QUOTA_PREF);
|
||||
done();
|
||||
@ -257,184 +251,6 @@ exports.testUninstall = function (assert, done) {
|
||||
loader.unload();
|
||||
};
|
||||
|
||||
exports.testChangeInnerArray = function(assert, done) {
|
||||
prefs.set(WRITE_PERIOD_PREF, 10);
|
||||
|
||||
let expected = {
|
||||
x: [5, 7],
|
||||
y: [7, 28],
|
||||
z: [6, 2]
|
||||
};
|
||||
|
||||
// Load the module, set a value.
|
||||
let loader = Loader(module);
|
||||
let ss = loader.require("sdk/simple-storage");
|
||||
manager(loader).jsonStore.onWrite = function (storage) {
|
||||
assert.ok(file.exists(storeFilename), "Store file should exist");
|
||||
|
||||
// Load the module again and check the result
|
||||
loader = Loader(module);
|
||||
ss = loader.require("sdk/simple-storage");
|
||||
assert.equal(JSON.stringify(ss.storage),
|
||||
JSON.stringify(expected), "Should see the expected object");
|
||||
|
||||
// Add a property
|
||||
ss.storage.x.push(["bar"]);
|
||||
expected.x.push(["bar"]);
|
||||
manager(loader).jsonStore.onWrite = function (storage) {
|
||||
assert.equal(JSON.stringify(ss.storage),
|
||||
JSON.stringify(expected), "Should see the expected object");
|
||||
|
||||
// Modify a property
|
||||
ss.storage.y[0] = 42;
|
||||
expected.y[0] = 42;
|
||||
manager(loader).jsonStore.onWrite = function (storage) {
|
||||
assert.equal(JSON.stringify(ss.storage),
|
||||
JSON.stringify(expected), "Should see the expected object");
|
||||
|
||||
// Delete a property
|
||||
delete ss.storage.z[1];
|
||||
delete expected.z[1];
|
||||
manager(loader).jsonStore.onWrite = function (storage) {
|
||||
assert.equal(JSON.stringify(ss.storage),
|
||||
JSON.stringify(expected), "Should see the expected object");
|
||||
|
||||
// Modify the new inner-object
|
||||
ss.storage.x[2][0] = "baz";
|
||||
expected.x[2][0] = "baz";
|
||||
manager(loader).jsonStore.onWrite = function (storage) {
|
||||
assert.equal(JSON.stringify(ss.storage),
|
||||
JSON.stringify(expected), "Should see the expected object");
|
||||
|
||||
manager(loader).jsonStore.onWrite = function (storage) {
|
||||
assert.fail("Nothing should be written since `storage` was not changed.");
|
||||
};
|
||||
loader.unload();
|
||||
|
||||
// Load the module again and check the result
|
||||
loader = Loader(module);
|
||||
ss = loader.require("sdk/simple-storage");
|
||||
assert.equal(JSON.stringify(ss.storage),
|
||||
JSON.stringify(expected), "Should see the expected object");
|
||||
loader.unload();
|
||||
file.remove(storeFilename);
|
||||
prefs.reset(WRITE_PERIOD_PREF);
|
||||
done();
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ss.storage = {
|
||||
x: [5, 7],
|
||||
y: [7, 28],
|
||||
z: [6, 2]
|
||||
};
|
||||
assert.equal(JSON.stringify(ss.storage),
|
||||
JSON.stringify(expected), "Should see the expected object");
|
||||
|
||||
loader.unload();
|
||||
};
|
||||
|
||||
exports.testChangeInnerObject = function(assert, done) {
|
||||
prefs.set(WRITE_PERIOD_PREF, 10);
|
||||
|
||||
let expected = {
|
||||
x: {
|
||||
a: 5,
|
||||
b: 7
|
||||
},
|
||||
y: {
|
||||
c: 7,
|
||||
d: 28
|
||||
},
|
||||
z: {
|
||||
e: 6,
|
||||
f: 2
|
||||
}
|
||||
};
|
||||
|
||||
// Load the module, set a value.
|
||||
let loader = Loader(module);
|
||||
let ss = loader.require("sdk/simple-storage");
|
||||
manager(loader).jsonStore.onWrite = function (storage) {
|
||||
assert.ok(file.exists(storeFilename), "Store file should exist");
|
||||
|
||||
// Load the module again and check the result
|
||||
loader = Loader(module);
|
||||
ss = loader.require("sdk/simple-storage");
|
||||
assert.equal(JSON.stringify(ss.storage),
|
||||
JSON.stringify(expected), "Should see the expected object");
|
||||
|
||||
// Add a property
|
||||
ss.storage.x.g = {foo: "bar"};
|
||||
expected.x.g = {foo: "bar"};
|
||||
manager(loader).jsonStore.onWrite = function (storage) {
|
||||
assert.equal(JSON.stringify(ss.storage),
|
||||
JSON.stringify(expected), "Should see the expected object");
|
||||
|
||||
// Modify a property
|
||||
ss.storage.y.c = 42;
|
||||
expected.y.c = 42;
|
||||
manager(loader).jsonStore.onWrite = function (storage) {
|
||||
assert.equal(JSON.stringify(ss.storage),
|
||||
JSON.stringify(expected), "Should see the expected object");
|
||||
|
||||
// Delete a property
|
||||
delete ss.storage.z.f;
|
||||
delete expected.z.f;
|
||||
manager(loader).jsonStore.onWrite = function (storage) {
|
||||
assert.equal(JSON.stringify(ss.storage),
|
||||
JSON.stringify(expected), "Should see the expected object");
|
||||
|
||||
// Modify the new inner-object
|
||||
ss.storage.x.g.foo = "baz";
|
||||
expected.x.g.foo = "baz";
|
||||
manager(loader).jsonStore.onWrite = function (storage) {
|
||||
assert.equal(JSON.stringify(ss.storage),
|
||||
JSON.stringify(expected), "Should see the expected object");
|
||||
|
||||
manager(loader).jsonStore.onWrite = function (storage) {
|
||||
assert.fail("Nothing should be written since `storage` was not changed.");
|
||||
};
|
||||
loader.unload();
|
||||
|
||||
// Load the module again and check the result
|
||||
loader = Loader(module);
|
||||
ss = loader.require("sdk/simple-storage");
|
||||
assert.equal(JSON.stringify(ss.storage),
|
||||
JSON.stringify(expected), "Should see the expected object");
|
||||
loader.unload();
|
||||
file.remove(storeFilename);
|
||||
prefs.reset(WRITE_PERIOD_PREF);
|
||||
done();
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ss.storage = {
|
||||
x: {
|
||||
a: 5,
|
||||
b: 7
|
||||
},
|
||||
y: {
|
||||
c: 7,
|
||||
d: 28
|
||||
},
|
||||
z: {
|
||||
e: 6,
|
||||
f: 2
|
||||
}
|
||||
};
|
||||
assert.equal(JSON.stringify(ss.storage),
|
||||
JSON.stringify(expected), "Should see the expected object");
|
||||
|
||||
loader.unload();
|
||||
};
|
||||
|
||||
exports.testSetNoSetRead = function (assert, done) {
|
||||
// Load the module, set a value.
|
||||
let loader = Loader(module);
|
||||
@ -453,13 +269,12 @@ exports.testSetNoSetRead = function (assert, done) {
|
||||
// Load the module a third time and make sure the value stuck.
|
||||
loader = Loader(module);
|
||||
ss = loader.require("sdk/simple-storage");
|
||||
assert.equal(ss.storage.foo, val, "Value should persist");
|
||||
manager(loader).jsonStore.onWrite = function (storage) {
|
||||
assert.fail("Nothing should be written since `storage` was not changed.");
|
||||
file.remove(storeFilename);
|
||||
done();
|
||||
};
|
||||
assert.equal(ss.storage.foo, val, "Value should persist");
|
||||
loader.unload();
|
||||
file.remove(storeFilename);
|
||||
done();
|
||||
};
|
||||
let val = "foo";
|
||||
ss.storage.foo = val;
|
||||
@ -480,13 +295,12 @@ function setGetRoot(assert, done, val, compare) {
|
||||
// Load the module again and make sure the value stuck.
|
||||
loader = Loader(module);
|
||||
ss = loader.require("sdk/simple-storage");
|
||||
assert.ok(compare(ss.storage, val), "Value should persist");
|
||||
manager(loader).jsonStore.onWrite = function (storage) {
|
||||
assert.fail("Nothing should be written since `storage` was not changed.");
|
||||
manager(loader).jsonStore.onWrite = function () {
|
||||
file.remove(storeFilename);
|
||||
done();
|
||||
};
|
||||
assert.ok(compare(ss.storage, val), "Value should persist");
|
||||
loader.unload();
|
||||
file.remove(storeFilename);
|
||||
done();
|
||||
};
|
||||
ss.storage = val;
|
||||
assert.ok(compare(ss.storage, val), "Value read should be value set");
|
||||
|
Loading…
Reference in New Issue
Block a user