From 2236bab130344fe154b1e7bb0d3408515631de9f Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Thu, 11 Apr 2013 04:28:38 -0400 Subject: [PATCH] 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 --- chrome/content/zotero/xpcom/file.js | 56 +++++++------------- chrome/content/zotero/xpcom/storage.js | 16 +++--- chrome/content/zotero/xpcom/zotero.js | 53 ++++++++++++++++++ chrome/content/zotero/zoteroPane.js | 53 ++---------------- chrome/locale/en-US/zotero/zotero.properties | 2 +- 5 files changed, 85 insertions(+), 95 deletions(-) diff --git a/chrome/content/zotero/xpcom/file.js b/chrome/content/zotero/xpcom/file.js index 57688d467f..7383d4572f 100644 --- a/chrome/content/zotero/xpcom/file.js +++ b/chrome/content/zotero/xpcom/file.js @@ -523,54 +523,34 @@ Zotero.File = new function(){ } if (e.name == 'NS_ERROR_FILE_ACCESS_DENIED' || e.name == 'NS_ERROR_FILE_IS_LOCKED' - // Shows up on some Windows systems - || e.name == 'NS_ERROR_FAILURE') { + // These show up on some Windows systems + || e.name == 'NS_ERROR_FAILURE' || e.name == 'NS_ERROR_FILE_NOT_FOUND') { Zotero.debug(e); str = str + " " + Zotero.getString('file.accessError.cannotBe') + " " + opWord + "."; var checkFileWindows = Zotero.getString('file.accessError.message.windows'); var checkFileOther = Zotero.getString('file.accessError.message.other'); - var msg = str + " " + var msg = str + "\n\n" + (Zotero.isWin ? checkFileWindows : checkFileOther) + "\n\n" + Zotero.getString('file.accessError.restart'); - if (operation == 'create') { - var e = new Zotero.Error( - msg, - 0, - { - dialogButtonText: Zotero.getString('file.accessError.showParentDir'), - dialogButtonCallback: function () { - try { - file.parent.QueryInterface(Components.interfaces.nsILocalFile).reveal(); - } - // Unsupported on some platforms - catch (e2) { - Zotero.debug(e2); - } + var e = new Zotero.Error( + msg, + 0, + { + dialogButtonText: Zotero.getString('file.accessError.showParentDir'), + dialogButtonCallback: function () { + try { + file.parent.QueryInterface(Components.interfaces.nsILocalFile); + file.parent.reveal(); + } + // Unsupported on some platforms + catch (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); diff --git a/chrome/content/zotero/xpcom/storage.js b/chrome/content/zotero/xpcom/storage.js index b0e9d55c33..45d8ef3652 100644 --- a/chrome/content/zotero/xpcom/storage.js +++ b/chrome/content/zotero/xpcom/storage.js @@ -1607,18 +1607,18 @@ Zotero.Sync.Storage = new function () { // Do deletes outside of the enumerator to avoid an access error on Windows for each(var file in filesToDelete) { - if (file.isFile()) { - Zotero.debug("Deleting existing file " + file.leafName); - try { + try { + if (file.isFile()) { + Zotero.debug("Deleting existing file " + file.leafName); file.remove(false); } - catch (e) { - Zotero.File.checkFileAccessError(e, file, 'delete'); + else if (file.isDirectory()) { + Zotero.debug("Deleting existing directory " + file.leafName); + file.remove(true); } } - else if (file.isDirectory()) { - Zotero.debug("Deleting existing directory " + file.leafName); - file.remove(true); + catch (e) { + Zotero.File.checkFileAccessError(e, file, 'delete'); } } } diff --git a/chrome/content/zotero/xpcom/zotero.js b/chrome/content/zotero/xpcom/zotero.js index db14c0acf0..cbcce63834 100644 --- a/chrome/content/zotero/xpcom/zotero.js +++ b/chrome/content/zotero/xpcom/zotero.js @@ -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 * @@ -1854,6 +1906,7 @@ Components.utils.import("resource://gre/modules/Services.jsm"); Zotero.Items.reloadAll(); } + /** * Brings Zotero Standalone to the foreground */ diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js index b4e0417b8d..c962838847 100644 --- a/chrome/content/zotero/zoteroPane.js +++ b/chrome/content/zotero/zoteroPane.js @@ -3464,7 +3464,7 @@ var ZoteroPane = new function() this.loadURI(url, event); } else { - this.launchFile(file); + Zotero.launchFile(file); } } else { @@ -3507,54 +3507,11 @@ var ZoteroPane = new function() /** - * Launch a file, the best way we can + * @deprecated */ 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); - } - } + Zotero.debug("ZoteroPane.launchFile() is deprecated -- use Zotero.launchFile()", 2); + Zotero.launchFile(file); } @@ -3626,7 +3583,7 @@ var ZoteroPane = new function() // On platforms that don't support nsILocalFile.reveal() (e.g. Linux), // launch the parent directory var parent = file.parent.QueryInterface(Components.interfaces.nsILocalFile); - this.launchFile(parent); + Zotero.launchFile(parent); } } else { diff --git a/chrome/locale/en-US/zotero/zotero.properties b/chrome/locale/en-US/zotero/zotero.properties index 71ca50c46b..9820cae9df 100644 --- a/chrome/locale/en-US/zotero/zotero.properties +++ b/chrome/locale/en-US/zotero/zotero.properties @@ -903,7 +903,7 @@ file.accessError.cannotBe = cannot be file.accessError.created = created file.accessError.updated = updated 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.restart = Restarting your computer or disabling security software may also help. file.accessError.showParentDir = Show Parent Directory