Better handle some file sync file access errors

- Catch additional errors on Windows (too-long paths, maybe aliases)
- Fix "Show File" button (which didn't show in some cases, at least on
  Windows)
- Clarify error message
This commit is contained in:
Dan Stillman 2013-04-11 04:28:38 -04:00
parent e716a5367a
commit 2236bab130
5 changed files with 85 additions and 95 deletions

View File

@ -523,54 +523,34 @@ Zotero.File = new function(){
} }
if (e.name == 'NS_ERROR_FILE_ACCESS_DENIED' || e.name == 'NS_ERROR_FILE_IS_LOCKED' if (e.name == 'NS_ERROR_FILE_ACCESS_DENIED' || e.name == 'NS_ERROR_FILE_IS_LOCKED'
// Shows up on some Windows systems // These show up on some Windows systems
|| e.name == 'NS_ERROR_FAILURE') { || e.name == 'NS_ERROR_FAILURE' || e.name == 'NS_ERROR_FILE_NOT_FOUND') {
Zotero.debug(e); Zotero.debug(e);
str = str + " " + Zotero.getString('file.accessError.cannotBe') + " " + opWord + "."; str = str + " " + Zotero.getString('file.accessError.cannotBe') + " " + opWord + ".";
var checkFileWindows = Zotero.getString('file.accessError.message.windows'); var checkFileWindows = Zotero.getString('file.accessError.message.windows');
var checkFileOther = Zotero.getString('file.accessError.message.other'); var checkFileOther = Zotero.getString('file.accessError.message.other');
var msg = str + " " var msg = str + "\n\n"
+ (Zotero.isWin ? checkFileWindows : checkFileOther) + (Zotero.isWin ? checkFileWindows : checkFileOther)
+ "\n\n" + "\n\n"
+ Zotero.getString('file.accessError.restart'); + Zotero.getString('file.accessError.restart');
if (operation == 'create') { var e = new Zotero.Error(
var e = new Zotero.Error( msg,
msg, 0,
0, {
{ dialogButtonText: Zotero.getString('file.accessError.showParentDir'),
dialogButtonText: Zotero.getString('file.accessError.showParentDir'), dialogButtonCallback: function () {
dialogButtonCallback: function () { try {
try { file.parent.QueryInterface(Components.interfaces.nsILocalFile);
file.parent.QueryInterface(Components.interfaces.nsILocalFile).reveal(); file.parent.reveal();
} }
// Unsupported on some platforms // Unsupported on some platforms
catch (e2) { catch (e2) {
Zotero.debug(e2); Zotero.launchFile(file.parent);
}
} }
} }
); }
} );
else {
var e = new Zotero.Error(
msg,
0,
{
dialogButtonText: Zotero.getString('locate.showFile.label'),
dialogButtonCallback: function () {
try {
file.QueryInterface(Components.interfaces.nsILocalFile);
file.reveal();
}
// Unsupported on some platforms
catch (e2) {
Zotero.debug(e2);
}
}
}
);
}
} }
throw (e); throw (e);

View File

@ -1607,18 +1607,18 @@ Zotero.Sync.Storage = new function () {
// Do deletes outside of the enumerator to avoid an access error on Windows // Do deletes outside of the enumerator to avoid an access error on Windows
for each(var file in filesToDelete) { for each(var file in filesToDelete) {
if (file.isFile()) { try {
Zotero.debug("Deleting existing file " + file.leafName); if (file.isFile()) {
try { Zotero.debug("Deleting existing file " + file.leafName);
file.remove(false); file.remove(false);
} }
catch (e) { else if (file.isDirectory()) {
Zotero.File.checkFileAccessError(e, file, 'delete'); Zotero.debug("Deleting existing directory " + file.leafName);
file.remove(true);
} }
} }
else if (file.isDirectory()) { catch (e) {
Zotero.debug("Deleting existing directory " + file.leafName); Zotero.File.checkFileAccessError(e, file, 'delete');
file.remove(true);
} }
} }
} }

View File

@ -1146,6 +1146,58 @@ Components.utils.import("resource://gre/modules/Services.jsm");
} }
/**
* Launch a file, the best way we can
*/
this.launchFile = function (file) {
try {
file.launch();
}
catch (e) {
Zotero.debug("launch() not supported -- trying fallback executable");
try {
if (Zotero.isWin) {
var pref = "fallbackLauncher.windows";
}
else {
var pref = "fallbackLauncher.unix";
}
var path = Zotero.Prefs.get(pref);
var exec = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
exec.initWithPath(path);
if (!exec.exists()) {
throw (path + " does not exist");
}
var proc = Components.classes["@mozilla.org/process/util;1"]
.createInstance(Components.interfaces.nsIProcess);
proc.init(exec);
var args = [file.path];
proc.runw(true, args, args.length);
}
catch (e) {
Zotero.debug(e);
Zotero.debug("Launching via executable failed -- passing to loadUrl()");
// If nsILocalFile.launch() isn't available and the fallback
// executable doesn't exist, we just let the Firefox external
// helper app window handle it
var nsIFPH = Components.classes["@mozilla.org/network/protocol;1?name=file"]
.getService(Components.interfaces.nsIFileProtocolHandler);
var uri = nsIFPH.newFileURI(file);
var nsIEPS = Components.classes["@mozilla.org/uriloader/external-protocol-service;1"].
getService(Components.interfaces.nsIExternalProtocolService);
nsIEPS.loadUrl(uri);
}
}
}
/* /*
* Debug logging function * Debug logging function
* *
@ -1854,6 +1906,7 @@ Components.utils.import("resource://gre/modules/Services.jsm");
Zotero.Items.reloadAll(); Zotero.Items.reloadAll();
} }
/** /**
* Brings Zotero Standalone to the foreground * Brings Zotero Standalone to the foreground
*/ */

View File

@ -3464,7 +3464,7 @@ var ZoteroPane = new function()
this.loadURI(url, event); this.loadURI(url, event);
} }
else { else {
this.launchFile(file); Zotero.launchFile(file);
} }
} }
else { else {
@ -3507,54 +3507,11 @@ var ZoteroPane = new function()
/** /**
* Launch a file, the best way we can * @deprecated
*/ */
this.launchFile = function (file) { this.launchFile = function (file) {
try { Zotero.debug("ZoteroPane.launchFile() is deprecated -- use Zotero.launchFile()", 2);
file.launch(); Zotero.launchFile(file);
}
catch (e) {
Zotero.debug("launch() not supported -- trying fallback executable");
try {
if (Zotero.isWin) {
var pref = "fallbackLauncher.windows";
}
else {
var pref = "fallbackLauncher.unix";
}
var path = Zotero.Prefs.get(pref);
var exec = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
exec.initWithPath(path);
if (!exec.exists()) {
throw (path + " does not exist");
}
var proc = Components.classes["@mozilla.org/process/util;1"]
.createInstance(Components.interfaces.nsIProcess);
proc.init(exec);
var args = [file.path];
proc.runw(true, args, args.length);
}
catch (e) {
Zotero.debug(e);
Zotero.debug("Launching via executable failed -- passing to loadUrl()");
// If nsILocalFile.launch() isn't available and the fallback
// executable doesn't exist, we just let the Firefox external
// helper app window handle it
var nsIFPH = Components.classes["@mozilla.org/network/protocol;1?name=file"]
.getService(Components.interfaces.nsIFileProtocolHandler);
var uri = nsIFPH.newFileURI(file);
var nsIEPS = Components.classes["@mozilla.org/uriloader/external-protocol-service;1"].
getService(Components.interfaces.nsIExternalProtocolService);
nsIEPS.loadUrl(uri);
}
}
} }
@ -3626,7 +3583,7 @@ var ZoteroPane = new function()
// On platforms that don't support nsILocalFile.reveal() (e.g. Linux), // On platforms that don't support nsILocalFile.reveal() (e.g. Linux),
// launch the parent directory // launch the parent directory
var parent = file.parent.QueryInterface(Components.interfaces.nsILocalFile); var parent = file.parent.QueryInterface(Components.interfaces.nsILocalFile);
this.launchFile(parent); Zotero.launchFile(parent);
} }
} }
else { else {

View File

@ -903,7 +903,7 @@ file.accessError.cannotBe = cannot be
file.accessError.created = created file.accessError.created = created
file.accessError.updated = updated file.accessError.updated = updated
file.accessError.deleted = deleted file.accessError.deleted = deleted
file.accessError.message.windows = Check that the file is not currently in use and that it is not marked as read-only. To check all files in your Zotero data directory, right-click on the 'zotero' directory, click Properties, clear the Read-Only checkbox, and apply the change to all folders and files in the directory. file.accessError.message.windows = Check that the file is not currently in use, that its permissions allow write access, and that it has a valid filename.
file.accessError.message.other = Check that the file is not currently in use and that its permissions allow write access. file.accessError.message.other = Check that the file is not currently in use and that its permissions allow write access.
file.accessError.restart = Restarting your computer or disabling security software may also help. file.accessError.restart = Restarting your computer or disabling security software may also help.
file.accessError.showParentDir = Show Parent Directory file.accessError.showParentDir = Show Parent Directory