diff --git a/www/js/app.js b/www/js/app.js index e8610f60..f9c7f762 100644 --- a/www/js/app.js +++ b/www/js/app.js @@ -26,8 +26,8 @@ // This uses require.js to structure javascript: // http://requirejs.org/docs/api.html#define -define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'cache', 'images', 'cookies', 'q', 'transformStyles', 'kiwixServe'], - function ($, zimArchiveLoader, uiUtil, util, cache, images, cookies, Q, transformStyles, kiwixServe) { +define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'cache', 'images', 'settingsStore', 'q', 'transformStyles', 'kiwixServe'], + function ($, zimArchiveLoader, uiUtil, util, cache, images, settingsStore, Q, transformStyles, kiwixServe) { /** * The delay (in milliseconds) between two "keepalive" messages @@ -52,7 +52,9 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'cache', 'images', 'cook 'type': '' // The type of the search: 'basic'|'full' (set automatically in search algorithm) }; - // A parameter to determine the Settings Store API in use + // A parameter to determine the Settings Store API in use (we need to nullify before testing) + // because params.storeType is also set in a preliminary way in init.js + params['storeType'] = null; params['storeType'] = settingsStore.getBestAvailableStorageAPI(); // Unique identifier of the article expected to be displayed @@ -347,7 +349,7 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'cache', 'images', 'cook params.lastPageHTML = ""; if (typeof Storage !== "undefined") { try { - localStorage.setItem('lastPageHTML', ""); + localStorage.setItem(params.keyPrefix + 'lastPageHTML', ""); } catch (err) { console.log("localStorage not supported: " + err); } @@ -1238,7 +1240,7 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'cache', 'images', 'cook //Clear localStorage if (typeof Storage !== "undefined") { try { - localStorage.setItem('lastPageHTML', ""); + localStorage.setItem(params.keyPrefix + 'lastPageHTML', ""); localStorage.clear(); } catch (err) { console.log("localStorage not supported: " + err); @@ -2728,7 +2730,7 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'cache', 'images', 'cook if (params.rememberLastPage && (typeof Storage !== "undefined") && dirEntry.namespace + '/' + dirEntry.url == lastPage) { if (!params.lastPageHTML) { try { - params.lastPageHTML = localStorage.getItem('lastPageHTML'); + params.lastPageHTML = localStorage.getItem(params.keyPrefix + 'lastPageHTML'); } catch (err) { console.log("localStorage not supported: " + err); } @@ -2994,8 +2996,8 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'cache', 'images', 'cook //Store current document's raw HTML in localStorage for fast restart try { // Ensure we don't go over quota - localStorage.removeItem('lastPageHTML'); - localStorage.setItem('lastPageHTML', htmlArticle); + localStorage.removeItem(params.keyPrefix + 'lastPageHTML'); + localStorage.setItem(params.keyPrefix + 'lastPageHTML', htmlArticle); } catch (err) { if (/quota\s*exceeded/i.test(err.message)) { // Note that Edge gives a quotaExceeded message when running from localhost even if the quota isn't exceeded diff --git a/www/js/init.js b/www/js/init.js index c44ce53b..0dd4b360 100644 --- a/www/js/init.js +++ b/www/js/init.js @@ -57,6 +57,7 @@ params['cachedStartPage'] = false; //If you have cached the start page for quick params['kiwixDownloadLink'] = "https://download.kiwix.org/zim/"; //Include final slash params['storeType'] = checkCookies(); +params['keyPrefix'] = 'kiwixjs-'; // Prefix to use for localStorage keys params['maxResults'] = ~~(getCookie('maxResults') || 25); //Number of search results to display params['relativeFontSize'] = ~~(getCookie('relativeFontSize') || 100); //Sets the initial font size for articles (as a percentage) - user can adjust using zoom buttons params['relativeUIFontSize'] = ~~(getCookie('relativeUIFontSize') || 100); //Sets the initial font size for UI (as a percentage) - user can adjust using slider in Config @@ -102,16 +103,14 @@ params['PWAInstalled'] = decodeURIComponent(getCookie('PWAInstalled')); params.pagesLoaded = 0; // Page counter used to show PWA Install Prompt only after user has played with the app for a while //Prevent app boot loop with problematic pages that cause an app crash -if (getCookie('lastPageLoad') == 'failed') { +if (getCookie('lastPageLoad') === 'failed') { params.lastPageVisit = ""; } else { //Cookie will signal failure until article is fully loaded - if (typeof window.fs === 'undefined') { + if (params.storeType === 'cookie') { document.cookie = 'lastPageLoad=failed;expires=Fri, 31 Dec 9999 23:59:59 GMT'; - } else { - if (typeof localStorage !== 'undefined') { - localStorage.setItem('lastPageLoad', 'failed'); - } + } else if (params.storeType === 'local_storage') { + localStorage.setItem(params.keyPrefix + 'lastPageLoad', 'failed'); } } @@ -236,26 +235,24 @@ function installApp(e) { window.addEventListener('appinstalled', function(e) { params.PWAInstalled = params.version; - document.cookie = 'PWAInstalled=' + encodeURIComponent(params.PWAInstalled) + ';expires=Fri, 31 Dec 9999 23:59:59 GMT'; + if (params.storeType === 'cookie') { + document.cookie = 'PWAInstalled=' + encodeURIComponent(params.PWAInstalled) + ';expires=Fri, 31 Dec 9999 23:59:59 GMT'; + } else if (params.storeType === 'local_storage') { + localStorage.setItem(params.keyPrefix + 'PWAInstalled', params.PWAInstalled); + } }); function getCookie(name) { var result; - if (params.storeType == 'cookie') { + if (params.storeType === 'cookie') { var regexp = new RegExp('(?:^|;)\\s*' + name + '=([^;]+)(?:;|$)'); result = document.cookie.match(regexp); result = result && result.length > 1 ? result[1] : null; - } else { - // We're in an electron app that may not be able to access cookies, so use localStorage instead - if (typeof Storage !== 'undefined') { - try { - result = localStorage.getItem(name); - } catch (err) { - console.log("localStorage not supported: " + err); - } - } + } else if (params.storeType === 'local_storage') { + // Use localStorage instead + result = localStorage.getItem(params.keyPrefix + name); } - return result === null || result == "undefined" ? null : result == "true" ? true : result == "false" ? false : result; + return result === null || result === "undefined" ? null : result === "true" ? true : result === "false" ? false : result; } function checkCookies() { @@ -268,16 +265,14 @@ function checkCookies() { kiwixCookie = !/kiwixCookie=working/i.test(document.cookie); } document.cookie = 'kiwixCookie=;expires=Thu, 01 Jan 1970 00:00:00 GMT'; - if (!kiwixCookie) { - // Cookies appear to be blocked, so test for localStorage support - var result = false; - try { - result = 'localStorage' in window && window['localStorage'] !== null; - } catch (e) { - console.log('LocalStorage is not supported!'); - } - if (result) storeType = 'local_storage'; + // Test for localStorage support + var result = false; + try { + result = 'localStorage' in window && window['localStorage'] !== null; + } catch (e) { + console.log('LocalStorage is not supported!'); } + if (result) storeType = 'local_storage'; console.log('Test1: storeType: ' + storeType); return storeType; } diff --git a/www/js/lib/cache.js b/www/js/lib/cache.js index a147f9ff..70e2ec61 100644 --- a/www/js/lib/cache.js +++ b/www/js/lib/cache.js @@ -21,7 +21,7 @@ */ 'use strict'; -define(['q', 'uiUtil'], function(Q, uiUtil) { +define(['q', 'settingsStore', 'uiUtil'], function(Q, settingsStore, uiUtil) { var CACHE_NAME = 'kiwixjs-assetCache'; // Set the database or cache name here var objStore = 'Assets'; // Name of the object store @@ -268,27 +268,26 @@ define(['q', 'uiUtil'], function(Q, uiUtil) { */ function setArticle(zimFile, article, content, callback) { // Prevent storage if user has deselected the option in Configuration - if (/rememberLastPage=false\b/i.test(document.cookie)) { + if (!params.rememberLastPage) { callback(-1); return; } - document.cookie = zimFile + '=' + encodeURIComponent(article) + ';expires=Fri, 31 Dec 9999 23:59:59 GMT'; + settingsStore.setItem(zimFile, article, Infinity); setItem(zimFile, content, function(response) { callback(response); }); } /** - * Retrieves article contents from cache only if the article's key has been stored in cookie - * (since checking the cookie is synchronous, it prevents unnecessary async cache lookups) + * Retrieves article contents from cache only if the article's key has been stored in settings store + * (since checking the store is synchronous, it prevents unnecessary async cache lookups) * * @param {String} zimFile The filename (or name of first file in set) of the ZIM archive * @param {String} article The URL of the article to be retrieved (including namespace) * @param {Function} callback The function to call with the result */ function getArticle(zimFile, article, callback) { - var encodedTitle = encodeURIComponent(article); - if (~document.cookie.indexOf(zimFile + '=' + encodedTitle)) { + if (settingsStore.getItem(zimFile) === article) { getItem(zimFile, callback); } else { callback(false); @@ -305,7 +304,7 @@ define(['q', 'uiUtil'], function(Q, uiUtil) { function setItem(key, contents, callback) { // Prevent use of storage if user has deselected the option in Configuration // or if the asset is of the wrong type - if (/useCache=false\b/i.test(document.cookie) || !regexpKeyTypes.test(key)) { + if (params.useCache === false || !regexpKeyTypes.test(key)) { callback(-1); return; } @@ -412,7 +411,7 @@ define(['q', 'uiUtil'], function(Q, uiUtil) { if (!/\.css$|\.js$/.test(key)) { document.getElementById('cachingAssets').style.display = 'none'; document.getElementById('searchingArticles').style.display = 'block'; - } else if (/useCache=true\b/i.test(document.cookie)) { + } else if (params.useCache !== false) { var shortTitle = key.replace(/[^/]+\//g, '').substring(0, 18); document.getElementById('cachingAssets').innerHTML = 'Getting ' + shortTitle + '...'; document.getElementById('cachingAssets').style.display = 'block'; diff --git a/www/js/lib/settingsStore.js b/www/js/lib/settingsStore.js index bc076c3d..e3ae4914 100644 --- a/www/js/lib/settingsStore.js +++ b/www/js/lib/settingsStore.js @@ -35,7 +35,7 @@ define([], function () { var regexpCookieKeysToMigrate = new RegExp([ 'lastContentInjectionMode', 'lastSelectedArchivePath', 'imageDisplay', 'useMathJax', 'version', 'lastSelectedArchive', 'listOfArchives', 'lastPageVisit', 'cssUITheme', 'cssTheme', 'cssSource', 'removePageMaxWidth', 'hideActiveContentWarning', - 'allowHTMLExtraction' + 'allowHTMLExtraction', 'PWAInstalled', 'lastPageLoad', 'hideToolbars', 'showFileSelectors', 'cssCache' ].join('|')); /** @@ -43,7 +43,7 @@ define([], function () { * potential collision of key names with localStorage keys used by code inside ZIM archives * @type {String} */ - const keyPrefix = 'kiwixjs-'; + const keyPrefix = params.keyPrefix || 'kiwixjs-'; // Tests for available Storage APIs (document.cookie or localStorage) and returns the best available of these function getBestAvailableStorageAPI() {