Skip to content

Commit

Permalink
Asynchronously migrate extension data (#1385)
Browse files Browse the repository at this point in the history
* Asynchronously migrate extension data

* Add storage migration warning; Default to unlimited storage

* Bump version to 7.7.6-less-broken

* Skip update if current value is longer

* copying -> migrating for clarity

* Bump version

* Excise misleading comment
  • Loading branch information
hobinjk authored and nightpool committed Aug 13, 2017
1 parent 216a6e9 commit 7a9581c
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 24 deletions.
2 changes: 1 addition & 1 deletion Firefox/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"title": "New XKit",
"name": "new-xkit",
"fullName": "New XKit",
"version": "7.7.6",
"version": "7.7.7",
"description": "Fork of XKit, the Tumblr extension framework",
"main": "./main.js",
"author": "",
Expand Down
46 changes: 37 additions & 9 deletions Firefox/sync-data.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,44 @@
/* globals require, exports */
/* globals require, exports, Promise */
let prefs = require('sdk/preferences/service');
let {setTimeout} = require('sdk/timers');
let prefRoot = 'extensions.xkit7.';

function migratePreference(port, prefKey) {
let name = prefKey.substring(prefRoot.length);
let value = prefs.get(prefKey, null);
let msg = {};
msg[name] = value;
// postMessage doesn't return a promise even though it could :(
port.postMessage(msg);
return new Promise(function(resolve, reject) {
setTimeout(function() {
if (port.error) {
reject(port.error);
} else {
resolve();
}
}, 10);
});
}

function migratePreferences(port, existingKeys) {
if (existingKeys.length === 0) {
return Promise.resolve();
}
let key = existingKeys.pop();
return migratePreference(port, key).then(function() {
return migratePreferences(port, existingKeys);
});
}

exports.setSyncLegacyDataPort = function(port) {

// Get all and broadcast to webext
// Get all and broadcast to webext one at a time
let existingKeys = prefs.keys(prefRoot);
let xkitStorage = {};
for (let properName of existingKeys) {
let name = properName.substring(prefRoot.length);
let value = prefs.get(properName, null);
xkitStorage[name] = value;
}
port.postMessage(xkitStorage);

migratePreferences(port, existingKeys).then(() => {
return port.postMessage({isProperlyMigrated: true});
}).catch(err => {
console.error('preferences not migrated', err);
});
};
46 changes: 34 additions & 12 deletions Firefox/webextension/background.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,43 @@
/* global browser */
/* global browser, Promise */

// From the MDN WebExtensions hybrid addon example

// Ask to the legacy part to dump the needed data and send it back
// to the background page...
var port = browser.runtime.connect({name: "sync-legacy-addon-data"});
port.onMessage.addListener((msg) => {
if (msg) {
browser.storage.local.get('isMigrated').then(function(item) {
if (item.isMigrated) {
console.warn('Skipping migration');
return;
browser.storage.local.get('isProperlyMigrated').then(function(item) {
if (item.isProperlyMigrated) {
console.warn('Skipping migration', item);
return;
}

var port = browser.runtime.connect({name: "sync-legacy-addon-data"});
function onMessage(msg) {
if (!msg) {
return;
}
let setPromises = Object.keys(msg).map(function(key) {
return browser.storage.local.get({key: null}).then(function(msgItem) {
if (typeof(msgItem[key]) === 'string') {
if (msgItem[key].length > msg[key].length) {
// Do not update the storage
return Promise.resolve();
}
}
// The corresponding code in XKit is GM_setValue(name, value) -> set({name: value})
return browser.storage.local.set(msg);
});
});
Promise.all(setPromises).catch(function(err) {
let errorMessage = "XKit failed to migrate your preferences to the new storage system. The migration reported the following error messag: " + err + ". Please restart your browser to try again.";
if (typeof(XKit) === 'undefined') {
alert(errorMessage);
} else {
XKit.window.show("Storage migration in progress", errorMessage, "error", "<div class=\"xkit-button default\">OK</div>");
}
// The corresponding code in XKit is GM_setValue(name, value) -> set({name: value})
msg.isMigrated = true;
console.log('Migrating pref storage', msg);
browser.storage.local.set(msg);
browser.storage.local.set({isProperlyMigrated: false});
port.onMessage.removeListener(onMessage);
});
}

port.onMessage.addListener(onMessage);
});
2 changes: 1 addition & 1 deletion Firefox/webextension/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"manifest_version": 2,
"name": "New XKit",
"permissions": ["*://*/*", "*://*/", "storage", "http://*.tumblr.com/", "https://*.tumblr.com/" ],
"version": "7.7.6",
"version": "7.7.7",
"web_accessible_resources": [ "manifest.json", "editor.js" ],
"background": {
"scripts": ["background.js"]
Expand Down
12 changes: 11 additions & 1 deletion WebExtension/bridge.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ try {
var storage = browser.storage.local;
var storage_loaded = false;
var framework_version = getVersion();
var storage_used = -1;
var storage_used = 0;
var storage_max = -1;
init_bridge();
} catch (e) {
Expand Down Expand Up @@ -90,6 +90,16 @@ function init_bridge() {
});
return;
}
if (typeof(chrome) === 'undefined') {
if (!items.isProperlyMigrated) {
XKit.window.show("Storage migration in progress", "XKit is still busy migrating your preferences from the old storage system to the new one. Please check back in a couple seconds by refreshing the page.", "warning", "<div class=\"xkit-button default\" id=\"xkit-bridge-refresh\">Refresh</div>");
$("#xkit-bridge-refresh").click(function() {
window.location = window.location;
});
return;
}

}
for (var key in items) {
xkit_storage[key] = items[key];
}
Expand Down

0 comments on commit 7a9581c

Please sign in to comment.