diff --git a/chrome/content/zotero/xpcom/zotero.js b/chrome/content/zotero/xpcom/zotero.js index 02c321647b..3b695bdce0 100644 --- a/chrome/content/zotero/xpcom/zotero.js +++ b/chrome/content/zotero/xpcom/zotero.js @@ -292,33 +292,82 @@ Services.scriptloader.loadSubScript("resource://zotero/polyfill.js"); catch (e) { // Zotero dir not found if (e.name == 'NS_ERROR_FILE_NOT_FOUND') { - Zotero.startupError = Zotero.getString('dataDir.notFound'); + let foundInDefault = false; + try { + foundInDefault = (yield OS.File.exists(Zotero.DataDirectory.defaultDir)) + && (yield OS.File.exists( + OS.Path.join( + Zotero.DataDirectory.defaultDir, + Zotero.DataDirectory.getDatabaseFilename() + ) + )); + } + catch (e) { + Zotero.logError(e); + } + + let previousDir = Zotero.Prefs.get('lastDataDir') || Zotero.Prefs.get('dataDir'); + Zotero.startupError = foundInDefault + ? Zotero.getString( + 'dataDir.notFound.defaultFound', + [ + Zotero.clientName, + previousDir, + Zotero.DataDirectory.defaultDir + ] + ) + : Zotero.getString('dataDir.notFound', Zotero.clientName); _startupErrorHandler = function() { var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]. createInstance(Components.interfaces.nsIPromptService); - var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING) - + (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_IS_STRING) - + (ps.BUTTON_POS_2) * (ps.BUTTON_TITLE_IS_STRING); + var buttonFlags = ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING + + ps.BUTTON_POS_1 * ps.BUTTON_TITLE_IS_STRING + + ps.BUTTON_POS_2 * ps.BUTTON_TITLE_IS_STRING; // TEMP: lastDataDir can be removed once old persistent descriptors have been // converted, which they are in getZoteroDirectory() in 5.0 - var previousDir = Zotero.Prefs.get('lastDataDir') || Zotero.Prefs.get('dataDir'); - var index = ps.confirmEx(null, - Zotero.getString('general.error'), - Zotero.startupError + '\n\n' + - Zotero.getString('dataDir.previousDir') + ' ' + previousDir, - buttonFlags, - Zotero.getString('general.quit'), - Zotero.getString('dataDir.useDefaultLocation'), - Zotero.getString('general.locate'), - null, {}); - - // Revert to home directory - if (index == 1) { - Zotero.DataDirectory.choose(true, true); + if (foundInDefault) { + let index = ps.confirmEx(null, + Zotero.getString('general.error'), + Zotero.startupError, + buttonFlags, + Zotero.getString('dataDir.useNewLocation'), + Zotero.getString('general.quit'), + Zotero.getString('general.locate'), + null, {} + ); + // Revert to home directory + if (index == 0) { + Zotero.DataDirectory.set(Zotero.DataDirectory.defaultDir); + Zotero.Utilities.Internal.quit(true); + return; + } + // Locate data directory + else if (index == 2) { + Zotero.DataDirectory.choose(true); + } + } - // Locate data directory - else if (index == 2) { - Zotero.DataDirectory.choose(true); + else { + let index = ps.confirmEx(null, + Zotero.getString('general.error'), + Zotero.startupError + '\n\n' + + Zotero.getString('dataDir.previousDir') + ' ' + previousDir, + buttonFlags, + Zotero.getString('general.quit'), + Zotero.getString('dataDir.useDefaultLocation'), + Zotero.getString('general.locate'), + null, {} + ); + // Revert to home directory + if (index == 1) { + Zotero.DataDirectory.set(Zotero.DataDirectory.defaultDir); + Zotero.Utilities.Internal.quit(true); + return; + } + // Locate data directory + else if (index == 2) { + Zotero.DataDirectory.choose(true); + } } } return; @@ -351,13 +400,7 @@ Services.scriptloader.loadSubScript("resource://zotero/polyfill.js"); Zotero.IPC.init(); } catch (e) { - if (e.name == 'NS_ERROR_FILE_ACCESS_DENIED') { - var msg = Zotero.localeJoin([ - Zotero.getString('startupError.databaseCannotBeOpened'), - Zotero.getString('startupError.checkPermissions') - ]); - Zotero.startupError = msg; - Zotero.logError(e); + if (_checkDataDirAccessError(e)) { return false; } throw (e); @@ -847,20 +890,15 @@ Services.scriptloader.loadSubScript("resource://zotero/polyfill.js"); } } catch (e) { - if (e.name == 'NS_ERROR_FILE_ACCESS_DENIED') { - var msg = Zotero.localeJoin([ - Zotero.getString('startupError.databaseCannotBeOpened'), - Zotero.getString('startupError.checkPermissions') - ]); - Zotero.startupError = msg; - } + if (_checkDataDirAccessError(e)) {} // Storage busy - else if (e.message.endsWith('2153971713')) { + else if (e.message.includes('2153971713')) { Zotero.startupError = Zotero.getString('startupError.databaseInUse') + "\n\n" + Zotero.getString( "startupError.close" + (Zotero.isStandalone ? 'Firefox' : 'Standalone') ); - } else { + } + else { Zotero.startupError = Zotero.getString('startupError') + "\n\n" + (e.stack || e); } @@ -873,6 +911,39 @@ Services.scriptloader.loadSubScript("resource://zotero/polyfill.js"); return true; }); + + function _checkDataDirAccessError(e) { + if (e.name != 'NS_ERROR_FILE_ACCESS_DENIED' && !e.message.includes('2152857621')) { + return false; + } + + var msg = Zotero.getString('dataDir.databaseCannotBeOpened', Zotero.clientName) + + "\n\n" + + Zotero.getString('dataDir.checkPermissions', Zotero.clientName); + // If already using default directory, just show it + if (Zotero.DataDirectory.dir == Zotero.DataDirectory.defaultDir) { + msg += "\n\n" + Zotero.getString('dataDir.location', Zotero.DataDirectory.dir); + } + // Otherwise suggest moving to default, since there's a good chance this is due to security + // software preventing Zotero from accessing the selected directory (particularly if it's + // a Firefox profile) + else { + msg += "\n\n" + + Zotero.getString('dataDir.moveToDefaultLocation', Zotero.clientName) + + "\n\n" + + Zotero.getString( + 'dataDir.migration.failure.full.current', Zotero.DataDirectory.dir + ) + + "\n" + + Zotero.getString( + 'dataDir.migration.failure.full.recommended', Zotero.DataDirectory.defaultDir + ); + } + Zotero.startupError = msg; + return true; + } + + /** * Called when the DB has been released by another Zotero process to perform necessary * initialization steps diff --git a/chrome/locale/en-US/zotero/zotero.properties b/chrome/locale/en-US/zotero/zotero.properties index 124f42bf22..3ed037097d 100644 --- a/chrome/locale/en-US/zotero/zotero.properties +++ b/chrome/locale/en-US/zotero/zotero.properties @@ -119,7 +119,13 @@ attachmentBasePath.clearBasePath.existingAttachments.singular = One existing at attachmentBasePath.clearBasePath.existingAttachments.plural = %S existing attachments within the old base directory will be converted to use absolute paths. attachmentBasePath.clearBasePath.button = Clear Base Directory Setting -dataDir.notFound = The Zotero data directory could not be found. +dataDir.databaseCannotBeOpened = The %S database cannot be opened. +dataDir.checkPermissions = Make sure you have read and write permissions for all files in the %1$S data directory and that security software isn’t preventing %1$S from accessing that directory. +dataDir.moveToDefaultLocation = You may be able to fix this problem by moving the data directory to the new default location in your home directory. %S will automatically detect the new location. +dataDir.location = Data Directory: %S +dataDir.notFound = The %S data directory could not be found. +dataDir.notFound.defaultFound = The %S data directory could not be found at %S, but a data directory was found at %S. Use this directory instead? +dataDir.useNewLocation = Use New Location dataDir.previousDir = Previous directory: dataDir.default = Default (%S) dataDir.useDefaultLocation = Use Default Location @@ -165,8 +171,6 @@ startupError = There was an error starting Zotero. startupError.databaseInUse = Your Zotero database is currently in use. Only one instance of Zotero using the same database may be opened simultaneously at this time. startupError.closeStandalone = If Zotero Standalone is open, please close it and restart Firefox. startupError.closeFirefox = If Firefox with the Zotero extension is open, please close it and restart Zotero Standalone. -startupError.databaseCannotBeOpened = The Zotero database cannot be opened. -startupError.checkPermissions = Make sure you have read and write permissions for all files in the Zotero data directory. startupError.zoteroVersionIsOlder = This version of Zotero is older than the version last used with your database. startupError.incompatibleDBVersion = This %1$S database requires %1$S %2$S or later. startupError.zoteroVersionIsOlder.current = Current version: %S