diff --git a/chrome/content/zotero/xpcom/dataDirectory.js b/chrome/content/zotero/xpcom/dataDirectory.js index 12f22b6ef2..7f47816f5f 100644 --- a/chrome/content/zotero/xpcom/dataDirectory.js +++ b/chrome/content/zotero/xpcom/dataDirectory.js @@ -177,26 +177,18 @@ Zotero.DataDirectory = { // New installation of 5.0+ with no data directory specified, so check all the places the data // could be else { - let useProfile = false; - let useFirefoxProfile = false; - let useFirefoxProfileCustom = false; - let dataDirNamedAfterProfile = false; - dataDir = this.defaultDir; - Zotero.fxProfileAccessError = false; - // If there's already a profile pointing to the default location, use a different // data directory named after the profile, as long as one either doesn't exist yet or // one does and it contains a database try { - if (((await Zotero.Profile.findOtherProfilesUsingDataDirectory(dataDir, false))).length) { + if (((await Zotero.Profile.findOtherProfilesUsingDataDirectory(dataDir))).length) { let profileName = PathUtils.filename(Zotero.Profile.dir).match(/[^.]+\.(.+)/)[1]; let newDataDir = this.defaultDir + ' ' + profileName; if (!((await OS.File.exists(newDataDir))) || ((await OS.File.exists(OS.Path.join(newDataDir, dbFilename))))) { dataDir = newDataDir; - dataDirNamedAfterProfile = true; } } } @@ -216,15 +208,13 @@ Zotero.DataDirectory = { return dataDir; } - // Check for /zotero/zotero.sqlite - let profileSubdirModTime; + // Check for /zotero/zotero.sqlite (Zotero Standalone <5.0) try { let dir = OS.Path.join(Zotero.Profile.dir, this.legacyDirName); let dbFile = OS.Path.join(dir, dbFilename); - profileSubdirModTime = new Date(((await IOUtils.stat(dbFile))).lastModified); - Zotero.debug(`Database found at ${dbFile}, last modified ${profileSubdirModTime}`); + let mtime = new Date(((await IOUtils.stat(dbFile))).lastModified); + Zotero.debug(`Database found at ${dbFile}, last modified ${mtime}`); dataDir = dir; - useProfile = true; } catch (e) { if (e.name != 'NotFoundError') { @@ -232,122 +222,6 @@ Zotero.DataDirectory = { } } - // - // Check Firefox directory - // - if (!dataDirNamedAfterProfile) { - // Get default profile in Firefox dir - let defProfile; - let profilesDir = Zotero.Profile.getOtherAppProfilesDir(); - let profilesParent = profilesDir ? PathUtils.parent(profilesDir) : null; - if (profilesParent) { - Zotero.debug("Looking for Firefox profile in " + profilesParent); - try { - defProfile = await Zotero.Profile.getDefaultInProfilesDir(profilesParent); - } - catch (e) { - Zotero.debug("An error occurred locating the Firefox profile; " - + "not attempting to migrate from Zotero for Firefox"); - Zotero.logError(e); - Zotero.fxProfileAccessError = true; - } - } - if (defProfile) { - let profileDir = defProfile[0]; - Zotero.debug("Found default profile at " + profileDir); - - // Read in prefs - let prefsFile = OS.Path.join(profileDir, "prefs.js"); - if (await OS.File.exists(prefsFile)) { - let prefs = await Zotero.Profile.readPrefsFromFile(prefsFile); - - // Check for data dir pref - if (prefs['extensions.zotero.dataDir'] && prefs['extensions.zotero.useDataDir']) { - Zotero.debug(`Found custom dataDir of ${prefs['extensions.zotero.dataDir']}`); - let nsIFile; - try { - nsIFile = Components.classes["@mozilla.org/file/local;1"] - .createInstance(Components.interfaces.nsIFile); - nsIFile.persistentDescriptor = prefs['extensions.zotero.dataDir']; - } - catch (e) { - Zotero.logError(e); - if (!useProfile) { - let msg = "Persistent descriptor in extensions.zotero.dataDir " - + "did not resolve"; - Zotero.debug(msg, 1); - throw new DOMException(msg, 'NotFoundError'); - } - } - try { - let dbFile = OS.Path.join(nsIFile.path, dbFilename); - let mtime = new Date(((await IOUtils.stat(dbFile))).lastModified); - Zotero.debug(`Database found at ${dbFile}, last modified ${mtime}`); - // If custom location has a newer DB, use that - if (!useProfile || mtime > profileSubdirModTime) { - dataDir = nsIFile.path; - useFirefoxProfileCustom = true; - useProfile = false; - } - } - catch (e) { - Zotero.logError(e); - // If we have a DB in the Zotero profile and get an error trying to - // access the custom location in Firefox, use the Zotero profile, since - // there's at least some chance it's right. Otherwise, throw an error. - if (!useProfile) { - // The error message normally gets the path from the pref, but - // we got it from the prefs file, so include it here - e.dataDir = nsIFile.path; - throw e; - } - Zotero.fxProfileAccessError = true; - } - } - // If no custom dir specified, check for a subdirectory - else { - try { - let dir = OS.Path.join(profileDir, this.legacyDirName); - let dbFile = OS.Path.join(dir, dbFilename); - let mtime = new Date(((await IOUtils.stat(dbFile))).lastModified); - Zotero.debug(`Database found at ${dbFile}, last modified ${mtime}`); - // If newer than Zotero profile directory, use this one - if (!useProfile || mtime > profileSubdirModTime) { - dataDir = dir; - useFirefoxProfile = true; - useProfile = false; - } - } - // Legacy subdirectory doesn't exist or there was a problem accessing it, so - // just fall through to default location - catch (e) { - if (e.name != 'NotFoundError') { - Zotero.logError(e); - Zotero.fxProfileAccessError = true; - } - } - } - - // If using data directory from Zotero for Firefox, transfer those prefs, because - // the fact that that DB was more recent and wasn't set in the Zotero profile prefs - // means that they were using Firefox. - if (useFirefoxProfile || useFirefoxProfileCustom) { - for (let key in prefs) { - if (key.substr(0, ZOTERO_CONFIG.PREF_BRANCH.length) === ZOTERO_CONFIG.PREF_BRANCH - && key !== "extensions.zotero.firstRun2") { - Zotero.Prefs.set(key.substr(ZOTERO_CONFIG.PREF_BRANCH.length), prefs[key]); - } - } - - // If data directory setting was transferred, use that - if (Zotero.Prefs.get('useDataDir')) { - return this.init(); - } - } - } - } - } - this.set(dataDir); } @@ -720,110 +594,6 @@ Zotero.DataDirectory = { }, - // TODO: Remove after 5.0 upgrades - checkForLostLegacy: async function () { - var currentDir = this.dir; - if (currentDir != this.defaultDir) return; - if (Zotero.Prefs.get('ignoreLegacyDataDir.auto') || Zotero.Prefs.get('ignoreLegacyDataDir.explicit')) return; - try { - let profilesDir = Zotero.Profile.getOtherAppProfilesDir(); - let profilesParent = profilesDir ? PathUtils.parent(profilesDir) : null; - if (!profilesParent) { - return; - } - Zotero.debug("Looking for Firefox profile in " + profilesParent); - - // get default profile - var defProfile; - try { - defProfile = await Zotero.Profile.getDefaultInProfilesDir(profilesParent); - } - catch (e) { - Zotero.logError(e); - return; - } - if (!defProfile) { - return; - } - let profileDir = defProfile[0]; - Zotero.debug("Found default profile at " + profileDir); - - let dir; - let mtime; - try { - dir = OS.Path.join(profileDir, this.legacyDirName); - let dbFile = OS.Path.join(dir, this.getDatabaseFilename()); - let info = await IOUtils.stat(dbFile); - if (info.size < 1200000) { - Zotero.debug(`Legacy database is ${info.size} bytes -- ignoring`); - Zotero.Prefs.set('ignoreLegacyDataDir.auto', true); - return; - } - mtime = new Date(info.lastModified); - if (mtime < new Date(2017, 6, 1)) { - Zotero.debug(`Legacy database was last modified on ${mtime.toString()} -- ignoring`); - Zotero.Prefs.set('ignoreLegacyDataDir.auto', true); - return; - } - Zotero.debug(`Legacy database found at ${dbFile}, last modified ${mtime}`); - } - catch (e) { - Zotero.Prefs.set('ignoreLegacyDataDir.auto', true); - if (e.name == 'NotFoundError') { - return; - } - throw e; - } - - let ps = Services.prompt; - let buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING) - + (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL) - + (ps.BUTTON_POS_2) * (ps.BUTTON_TITLE_IS_STRING); - let dontAskAgain = {}; - let index = ps.confirmEx(null, - "Other Data Directory Found", - "Zotero found a previous data directory within your Firefox profile, " - + `last modified on ${mtime.toLocaleDateString()}. ` - + "If items or files are missing from Zotero that were present in Zotero for Firefox, " - + "your previous data directory may not have been properly migrated to the new default location " - + `in ${this.defaultDir}.\n\n` - + `Do you wish to continue using the current data directory or switch to the previous one?\n\n` - + `If you switch, your current data directory will be moved to ${this.defaultDir + '-Old'}, ` - + `and the previous directory will be migrated to ${this.defaultDir}.`, - buttonFlags, - "Use Current Directory", - null, - "Switch to Previous Directory", - "Don\u0027t ask me again", - dontAskAgain - ); - if (index == 1) { - return; - } - if (dontAskAgain.value) { - Zotero.Prefs.set('ignoreLegacyDataDir.explicit', true); - } - if (index == 0) { - return; - } - - // Switch to previous directory - this.set(dir); - // Set a marker to rename the current ~/Zotero directory - try { - await Zotero.File.putContentsAsync(OS.Path.join(this.defaultDir, 'move-to-old'), ''); - } - catch (e) { - Zotero.logError(e); - } - Zotero.Utilities.Internal.quit(true); - } - catch (e) { - Zotero.logError(e); - } - }, - - /** * Determine if current data directory is in a legacy location */ diff --git a/chrome/content/zotero/xpcom/profile.js b/chrome/content/zotero/xpcom/profile.js index 0fddf82973..f589ad552c 100644 --- a/chrome/content/zotero/xpcom/profile.js +++ b/chrome/content/zotero/xpcom/profile.js @@ -91,47 +91,19 @@ Zotero.Profile = { /** - * Get the path to the Firefox Profiles directory, which may or may not exist - * - * @return {String|null} - Path, or null if none due to filesystem location - */ - getOtherAppProfilesDir: function () { - var dir = PathUtils.parent(PathUtils.parent(PathUtils.parent(this.dir))); - if (dir === '' || dir == '.') { - return null; - } - - if (Zotero.isWin) { - dir = OS.Path.join(PathUtils.parent(dir), "Mozilla", "Firefox"); - } - else if (Zotero.isMac) { - dir = OS.Path.join(dir, "Firefox"); - } - else { - dir = OS.Path.join(dir, ".mozilla", "firefox"); - } - - return OS.Path.join(dir, "Profiles"); - }, - - - /** - * Find other profile directories (for this app or the other app) using the given data directory + * Find other Zotero profile directories using the given data directory * * @param {String} dataDir - * @param {Boolean} [includeOtherApps=false] - Check Firefox profiles * @return {String[]} */ - findOtherProfilesUsingDataDirectory: async function (dataDir, includeOtherApps = true) { - let otherAppProfiles = includeOtherApps ? await this._findOtherAppProfiles() : []; - let otherProfiles = (await this._findOtherProfiles()).concat(otherAppProfiles); + findOtherProfilesUsingDataDirectory: async function (dataDir) { + let otherProfiles = await this._findOtherProfiles(); - // First get profiles pointing at this directory for (let i = 0; i < otherProfiles.length; i++) { let dir = otherProfiles[i]; let prefs = await Zotero.File.getContentsAsync(OS.Path.join(dir, "prefs.js")); prefs = prefs.trim().split(/(?:\r\n|\r|\n)/); - + let keep = prefs.some(line => line.includes("extensions.zotero.useDataDir") && line.includes("true")) && prefs.some(line => line.match(/extensions\.zotero\.(lastD|d)ataDir/) && line.includes(dataDir)); if (!keep) { @@ -140,15 +112,6 @@ Zotero.Profile = { } } - // If the parent of the source directory is a profile directory from the other app, add that - // to the list, which addresses the situation where the source directory is a custom - // location for the current profile but is a default in the other app (meaning it wouldn't - // be added above). - let dataDirParent = PathUtils.parent(dataDir); - if (otherAppProfiles.includes(dataDirParent) && !otherProfiles.includes(dataDirParent)) { - otherProfiles.push(dataDirParent); - } - if (otherProfiles.length) { Zotero.debug("Found other profiles pointing to " + dataDir); Zotero.debug(otherProfiles); @@ -191,82 +154,6 @@ Zotero.Profile = { }, - /** - * @return {Boolean} - True if accessible or skipped, false if not - */ - checkFirefoxProfileAccess: async function () { - try { - let profilesDir = Zotero.Profile.getOtherAppProfilesDir(); - if (!profilesDir) { - return true; - } - let profilesParent = PathUtils.parent(profilesDir); - Zotero.debug("Looking for Firefox profile in " + profilesParent); - let defProfile = await this.getDefaultInProfilesDir(profilesParent); - if (defProfile) { - let profileDir = defProfile[0]; - Zotero.debug("Found default profile at " + profileDir); - let prefsFile = OS.Path.join(profileDir, "prefs.js"); - await Zotero.File.getContentsAsync(prefsFile); - let dir = OS.Path.join(profileDir, Zotero.DataDirectory.legacyDirName); - Zotero.debug("Checking for 'zotero' subdirectory"); - if ((await OS.File.stat(dir)).isDir) { - let dbFilename = Zotero.DataDirectory.getDatabaseFilename(); - let dbFile = OS.Path.join(dir, dbFilename); - Zotero.debug("Checking database access within 'zotero' subdirectory"); - (await OS.File.stat(dbFile)).lastModificationDate; - } - else { - Zotero.debug("'zotero' is not a directory!"); - } - } - else { - Zotero.debug("No default profile found"); - } - } - catch (e) { - if (e.name == 'NotFoundError' || (e instanceof OS.File.Error && e.becauseNoSuchFile)) { - return true; - } - Zotero.debug(e, 2) - return false - } - return true; - }, - - - readPrefsFromFile: async function (prefsFile) { - var sandbox = new Components.utils.Sandbox("http://www.example.com/"); - Components.utils.evalInSandbox( - "var prefs = {};"+ - "function user_pref(key, val) {"+ - "prefs[key] = val;"+ - "}" - , sandbox); - - (await Zotero.File.getContentsAsync(prefsFile)) - .split(/\n/) - .filter((line) => { - // Strip comments - return !line.startsWith('#') - // Only process lines in our pref branch - && line.includes(ZOTERO_CONFIG.PREF_BRANCH); - }) - // Process each line individually - .forEach((line) => { - try { - Zotero.debug("Processing " + line); - Components.utils.evalInSandbox(line, sandbox); - } - catch (e) { - Zotero.logError("Error processing prefs line: " + line); - } - }); - - return sandbox.prefs; - }, - - // // Private methods // @@ -293,7 +180,7 @@ Zotero.Profile = { /** - * Find other profile directories for this app (Firefox or Zotero) + * Find other Zotero profile directories * * @return {Promise} - Array of paths */ @@ -301,16 +188,5 @@ Zotero.Profile = { var profileDir = this.dir; var profilesDir = this.getProfilesDir(); return (await this._getProfilesInDir(profilesDir)).filter(dir => dir != profileDir); - }, - - - /** - * Find profile directories for the other app (Firefox or Zotero) - * - * @return {Promise} - Array of paths - */ - _findOtherAppProfiles: async function () { - var dir = this.getOtherAppProfilesDir(); - return dir && (await OS.File.exists(dir)) ? this._getProfilesInDir(dir) : []; } }; diff --git a/chrome/content/zotero/xpcom/zotero.js b/chrome/content/zotero/xpcom/zotero.js index bfa53f5de4..e6c17ba7b8 100644 --- a/chrome/content/zotero/xpcom/zotero.js +++ b/chrome/content/zotero/xpcom/zotero.js @@ -373,11 +373,6 @@ const { CommandLineOptions } = ChromeUtils.importESModule("chrome://zotero/conte if (this.skipLoading) { return; } - - await Zotero.DataDirectory.checkForLostLegacy(); - if (this.restarting) { - return; - } } // Make sure data directory isn't in Dropbox, etc. diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js index 412e75d0fc..1b973ceb3e 100644 --- a/chrome/content/zotero/zoteroPane.js +++ b/chrome/content/zotero/zoteroPane.js @@ -807,55 +807,6 @@ var ZoteroPane = new function () { searchBar.searchTextbox.select(); }, 1); - // - // TEMP: Remove after people are no longer upgrading from Zotero for Firefox - // - var showFxProfileWarning = false; - var pref = 'firstRun.skipFirefoxProfileAccessCheck'; - if (Zotero.fxProfileAccessError != undefined && Zotero.fxProfileAccessError) { - showFxProfileWarning = true; - } - else if (!Zotero.Prefs.get(pref)) { - showFxProfileWarning = !await Zotero.Profile.checkFirefoxProfileAccess(); - } - if (showFxProfileWarning) { - Zotero.uiReadyPromise.then(async function () { - await Zotero.Promise.delay(2000); - - var ps = Services.prompt; - var buttonFlags = ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING - + ps.BUTTON_POS_1 * ps.BUTTON_TITLE_IS_STRING; - var text = "Zotero was unable to access your Firefox profile to check for " - + "existing Zotero data.\n\n" - + "If you’ve upgraded from Zotero 4.0 for Firefox and don’t see the data " - + "you expect, it may be located elsewhere on your computer. " - + "Click “More Information” for help restoring your previous data.\n\n" - + "If you’re new to Zotero, you can ignore this message."; - var url = 'https://www.zotero.org/support/kb/data_missing_after_zotero_5_upgrade'; - var dontShowAgain = {}; - let index = ps.confirmEx(null, - Zotero.getString('general.warning'), - text, - buttonFlags, - Zotero.getString('general.moreInformation'), - "Ignore", - null, - Zotero.getString('general.dontShowAgain'), - dontShowAgain - ); - if (dontShowAgain.value) { - Zotero.Prefs.set(pref, true) - } - if (index == 0) { - this.loadURI(url); - } - }.bind(this)); - } - // Once we successfully find it once, don't bother checking again - else { - Zotero.Prefs.set(pref, true); - } - if (Zotero.proxyFailure) { try { Zotero.Sync.Runner.updateIcons(Zotero.proxyFailure); @@ -880,9 +831,6 @@ var ZoteroPane = new function () { else if (Zotero.Sync.Server.manualSyncRequired) { Zotero.debug('Manual sync required -- skipping auto-sync', 4); } - else if (showFxProfileWarning) { - Zotero.debug('Firefox profile access error -- skipping initial auto-sync', 4); - } else { startupSync = true; Zotero.Sync.Runner.sync({ diff --git a/test/tests/profileTest.js b/test/tests/profileTest.js index 0d30884528..63d4901a7d 100644 --- a/test/tests/profileTest.js +++ b/test/tests/profileTest.js @@ -79,8 +79,12 @@ user_pref("loop.copy.ticket", 196); await Zotero.File.putContentsAsync(prefsFile2, contents2); await Zotero.File.putContentsAsync(prefsFile3, contents3); - var stub = sinon.stub(Zotero.Profile, "getOtherAppProfilesDir") - .returns(OS.Path.join(tmpDir, "Profiles")); + var stub = sinon.stub(Zotero.Profile, "_findOtherProfiles") + .returns([ + OS.Path.join(tmpDir, "Profiles", profile1), + OS.Path.join(tmpDir, "Profiles", profile2), + OS.Path.join(tmpDir, "Profiles", profile3) + ]); var dirs = await Zotero.Profile.findOtherProfilesUsingDataDirectory(dataDir); @@ -89,37 +93,6 @@ user_pref("loop.copy.ticket", 196); assert.sameMembers(dirs, [OS.Path.join(tmpDir, "Profiles", profile2)]); assert.lengthOf(dirs, 1); }); - - - it("should find other-app profile with directory as a legacy default location", async function () { - let contents1 = `user_pref("extensions.lastAppVersion", "49.0"); -user_pref("extensions.shownSelectionUI", true); -user_pref("extensions.ui.locale.hidden", true); -user_pref("loop.copy.ticket", 196); -`; - let contents2 = `user_pref("extensions.lastAppVersion", "50.0"); -user_pref("extensions.shownSelectionUI", true); -user_pref("extensions.ui.locale.hidden", true); -user_pref("loop.copy.ticket", 196); -`; - - let prefsFile1 = OS.Path.join(tmpDir, "Profiles", profile1, "prefs.js"); - let prefsFile2 = OS.Path.join(tmpDir, "Profiles", profile2, "prefs.js"); - await Zotero.File.putContentsAsync(prefsFile1, contents1); - await Zotero.File.putContentsAsync(prefsFile2, contents2); - - var stub = sinon.stub(Zotero.Profile, "getOtherAppProfilesDir") - .returns(OS.Path.join(tmpDir, "Profiles")); - - var dirs = await Zotero.Profile.findOtherProfilesUsingDataDirectory( - OS.Path.join(OS.Path.dirname(prefsFile1), Zotero.DataDirectory.legacyDirName) - ); - - stub.restore(); - - assert.sameMembers(dirs, [OS.Path.join(tmpDir, "Profiles", profile1)]); - assert.lengthOf(dirs, 1); - }); });