diff --git a/extensions/chromium/options/migration.js b/extensions/chromium/options/migration.js new file mode 100644 index 000000000..6d9f4c514 --- /dev/null +++ b/extensions/chromium/options/migration.js @@ -0,0 +1,69 @@ +/* +Copyright 2016 Mozilla Foundation + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +/* globals chrome */ + +(function() { + 'use strict'; + var storageLocal = chrome.storage.local; + var storageSync = chrome.storage.sync; + + if (!storageSync) { + // No sync storage area - nothing to migrate to. + return; + } + + getStorageNames(function(storageKeys) { + storageLocal.get(storageKeys, function(values) { + if (!values || !Object.keys(values).length) { + // No local storage - nothing to migrate. + return; + } + migrateToSyncStorage(values); + }); + }); + + function getStorageNames(callback) { + var x = new XMLHttpRequest(); + var schema_location = chrome.runtime.getManifest().storage.managed_schema; + x.open('get', chrome.runtime.getURL(schema_location)); + x.onload = function() { + var storageKeys = Object.keys(x.response.properties); + callback(storageKeys); + }; + x.responseType = 'json'; + x.send(); + } + + // Save |values| to storage.sync and delete the values with that key from + // storage.local. + function migrateToSyncStorage(values) { + storageSync.set(values, function() { + if (chrome.runtime.lastError) { + console.error('Failed to migrate settings due to an error: ' + + chrome.runtime.lastError.message); + return; + } + // Migration successful. Delete local settings. + storageLocal.remove(Object.keys(values), function() { + // In theory remove() could fail (e.g. if the browser's storage + // backend is corrupt), but since storageSync.set succeeded, consider + // the migration successful. + console.log( + 'Successfully migrated preferences from local to sync storage.'); + }); + }); + } +})(); diff --git a/extensions/chromium/options/options.js b/extensions/chromium/options/options.js index 1d8ec12d8..46b02bb8a 100644 --- a/extensions/chromium/options/options.js +++ b/extensions/chromium/options/options.js @@ -16,9 +16,15 @@ limitations under the License. /* globals chrome, Promise */ 'use strict'; +var storageAreaName = chrome.storage.sync ? 'sync' : 'local'; +var storageArea = chrome.storage[storageAreaName]; Promise.all([ new Promise(function getManagedPrefs(resolve) { + if (!chrome.storage.managed) { + resolve({}); + return; + } // Get preferences as set by the system administrator. chrome.storage.managed.get(null, function(prefs) { // Managed storage may be disabled, e.g. in Opera. @@ -26,7 +32,7 @@ Promise.all([ }); }), new Promise(function getUserPrefs(resolve) { - chrome.storage.local.get(null, function(prefs) { + storageArea.get(null, function(prefs) { resolve(prefs || {}); }); }), @@ -93,7 +99,7 @@ Promise.all([ // Reset button to restore default settings. document.getElementById('reset-button').onclick = function() { userPrefs = {}; - chrome.storage.local.remove(prefNames, function() { + storageArea.remove(prefNames, function() { renderedPrefNames.forEach(function(prefName) { renderPreferenceFunctions[prefName](getPrefValue(prefName)); }); @@ -102,7 +108,7 @@ Promise.all([ // Automatically update the UI when the preferences were changed elsewhere. chrome.storage.onChanged.addListener(function(changes, areaName) { - var prefs = areaName === 'local' ? userPrefs : + var prefs = areaName === storageAreaName ? userPrefs : areaName === 'managed' ? managedPrefs : null; if (prefs) { renderedPrefNames.forEach(function(prefName) { @@ -136,7 +142,7 @@ function renderBooleanPref(shortDescription, description, prefName) { checkbox.onchange = function() { var pref = {}; pref[prefName] = this.checked; - chrome.storage.local.set(pref); + storageArea.set(pref); }; wrapper.querySelector('span').textContent = shortDescription; document.getElementById('settings-boxes').appendChild(wrapper); @@ -151,7 +157,7 @@ function renderDefaultZoomValue(shortDescription) { var wrapper = importTemplate('defaultZoomValue-template'); var select = wrapper.querySelector('select'); select.onchange = function() { - chrome.storage.local.set({ + storageArea.set({ defaultZoomValue: this.value }); }; @@ -180,7 +186,7 @@ function renderSidebarViewOnLoad(shortDescription) { var wrapper = importTemplate('sidebarViewOnLoad-template'); var select = wrapper.querySelector('select'); select.onchange = function() { - chrome.storage.local.set({ + storageArea.set({ sidebarViewOnLoad: parseInt(this.value) }); }; @@ -197,7 +203,7 @@ function renderExternalLinkTarget(shortDescription) { var wrapper = importTemplate('externalLinkTarget-template'); var select = wrapper.querySelector('select'); select.onchange = function() { - chrome.storage.local.set({ + storageArea.set({ externalLinkTarget: parseInt(this.value) }); }; diff --git a/extensions/chromium/pdfHandler.html b/extensions/chromium/pdfHandler.html index fa4f2246f..e412ca1ae 100644 --- a/extensions/chromium/pdfHandler.html +++ b/extensions/chromium/pdfHandler.html @@ -15,6 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. --> + diff --git a/web/chromecom.js b/web/chromecom.js index 46ae1b3cc..275c49070 100644 --- a/web/chromecom.js +++ b/web/chromecom.js @@ -297,17 +297,22 @@ } } + // chrome.storage.sync is not supported in every Chromium-derivate. + // Note: The background page takes care of migrating values from + // chrome.storage.local to chrome.storage.sync when needed. + var storageArea = chrome.storage.sync || chrome.storage.local; + Preferences._writeToStorage = function (prefObj) { return new Promise(function (resolve) { if (prefObj === Preferences.defaults) { var keysToRemove = Object.keys(Preferences.defaults); // If the storage is reset, remove the keys so that the values from // managed storage are applied again. - chrome.storage.local.remove(keysToRemove, function() { + storageArea.remove(keysToRemove, function() { resolve(); }); } else { - chrome.storage.local.set(prefObj, function() { + storageArea.set(prefObj, function() { resolve(); }); } @@ -331,7 +336,7 @@ // Managed storage not supported, e.g. in Opera. defaultPrefs = Preferences.defaults; } - chrome.storage.local.get(defaultPrefs, function(readPrefs) { + storageArea.get(defaultPrefs, function(readPrefs) { resolve(readPrefs); }); }