Bug 793031 - Open recent file fails if the file doesn't exists anymore. r=robcee
☠☠ backed out by 7703f0ec6770 ☠ ☠
authorJohan Charlez <johan.charlez@gmail.com>
Mon, 01 Oct 2012 13:04:00 +0300
changeset 110259 fd093acb629e09e54af97455911aafc137a8067e
parent 110258 b07f4a276e76b45589b9cd78192c977aea05359e
child 110260 0759a7d8b78bbbd3ba831d237e0b213ca6e40990
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersrobcee
bugs793031
milestone19.0a1
Bug 793031 - Open recent file fails if the file doesn't exists anymore. r=robcee
browser/devtools/scratchpad/scratchpad.js
browser/devtools/scratchpad/test/browser_scratchpad_bug_651942_recent_files.js
browser/locales/en-US/chrome/browser/devtools/scratchpad.properties
--- a/browser/devtools/scratchpad/scratchpad.js
+++ b/browser/devtools/scratchpad/scratchpad.js
@@ -683,16 +683,28 @@ var Scratchpad = {
             file = aFile;
           } else {
             file = Components.classes["@mozilla.org/file/local;1"].
                    createInstance(Components.interfaces.nsILocalFile);
             let filePath = this.getRecentFiles()[aIndex];
             file.initWithPath(filePath);
           }
 
+          if (!file.exists()) {
+            this.notificationBox.appendNotification(
+              this.strings.GetStringFromName("fileNoLongerExists.notification"),
+              "file-no-longer-exists",
+              null,
+              this.notificationBox.PRIORITY_WARNING_HIGH,
+              null);
+
+            this.clearFiles(aIndex, 1);
+            return;
+          }
+
           this.setFilename(file.path);
           this.importFromFile(file, false);
           this.setRecentFile(file);
         }
       }.bind(this));
     }.bind(this);
 
     if (aIndex > -1) {
@@ -825,16 +837,33 @@ var Scratchpad = {
                               this.strings.
                               GetStringFromName("clearRecentMenuItems.label"));
       clearItems.setAttribute("command", "sp-cmd-clearRecentFiles");
       recentFilesPopup.appendChild(clearItems);
     }
   },
 
   /**
+   * Clear a range of files from the list.
+   *
+   * @param integer aIndex
+   *        Index of file in menu to remove.
+   * @param integer aLength
+   *        Number of files from the index 'aIndex' to remove.
+   */
+  clearFiles: function SP_clearFile(aIndex, aLength)
+  {
+    let filePaths = this.getRecentFiles();
+    let branch = Services.prefs.
+                 getBranch("devtools.scratchpad.");
+    filePaths.splice(aIndex, aLength);
+    branch.setCharPref("recentFilePaths", JSON.stringify(filePaths));
+  },
+
+  /**
    * Clear all recent files.
    */
   clearRecentFiles: function SP_clearRecentFiles()
   {
     Services.prefs.clearUserPref("devtools.scratchpad.recentFilePaths");
   },
 
   /**
@@ -854,21 +883,18 @@ var Scratchpad = {
           this.populateRecentFilesMenu();
         }
 
         menu.removeAttribute("hidden");
       }
 
       let filePaths = this.getRecentFiles();
       if (maxRecent < filePaths.length) {
-        let branch = Services.prefs.
-                     getBranch("devtools.scratchpad.");
         let diff = filePaths.length - maxRecent;
-        filePaths.splice(0, diff);
-        branch.setCharPref("recentFilePaths", JSON.stringify(filePaths));
+        this.clearFiles(0, diff);
       }
     }
   },
   /**
    * Save the textbox content to the currently open file.
    *
    * @param function aCallback
    *        Optional function you want to call when file is saved
--- a/browser/devtools/scratchpad/test/browser_scratchpad_bug_651942_recent_files.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_bug_651942_recent_files.js
@@ -96,45 +96,71 @@ function testOpenOldestRecent()
 // The "devtools.scratchpad.recentFilesMax"-preference was set to zero (0).
 // This should disable the "Open Recent"-menu by hiding it (this should not
 // remove any files from the list). Test to see if it's been hidden.
 function testHideMenu()
 {
   let menu = gScratchpadWindow.document.getElementById("sp-open_recent-menu");
   ok(menu.hasAttribute("hidden"), "The menu was hidden successfully.");
 
-  Services.prefs.setIntPref("devtools.scratchpad.recentFilesMax", 1);
+  Services.prefs.setIntPref("devtools.scratchpad.recentFilesMax", 2);
 }
 
 // We have set the recentFilesMax-pref to one (1), this enables the feature,
 // removes the two oldest files, rebuilds the menu and removes the
 // "hidden"-attribute from it. Test to see if this works.
 function testChangedMaxRecent()
 {
   let menu = gScratchpadWindow.document.getElementById("sp-open_recent-menu");
   ok(!menu.hasAttribute("hidden"), "The menu is visible. \\o/");
 
   lists.recentFiles04 = gScratchpad.getRecentFiles();
 
-  is(lists.recentFiles04.length, 1,
+  is(lists.recentFiles04.length, 2,
      "Two recent files were successfully removed from the 'recent files'-list");
 
   let doc = gScratchpadWindow.document;
   let popup = doc.getElementById("sp-menu-open_recentPopup");
 
   let menuitemLabel = popup.children[0].getAttribute("label");
   let correctMenuItem = false;
   if (menuitemLabel === lists.recentFiles03[2] &&
-      menuitemLabel === lists.recentFiles04[0]) {
+      menuitemLabel === lists.recentFiles04[1]) {
     correctMenuItem = true;
   }
 
   is(correctMenuItem, true,
      "Two recent files were successfully removed from the 'Open Recent'-menu");
 
+  // We now remove one file from the harddrive and use the recent-menuitem for
+  // it to make sure the user is notified that the file no longer exists.
+  // This is tested in testOpenDeletedFile().
+  gFile02.remove(false);
+  gFile02 = null;
+  gScratchpad.openFile(1);
+}
+
+// By now we should have two recent files stored in the list but one of the
+// files should be missing on the harddrive.
+function testOpenDeletedFile() {
+  let doc = gScratchpadWindow.document;
+  let popup = doc.getElementById("sp-menu-open_recentPopup");
+
+  is(gScratchpad.getRecentFiles().length, 1,
+     "The missing file was successfully removed from the list.");
+  // The number of recent files stored, plus the separator and the
+  // clearRecentMenuItems-item.
+  is(popup.children.length, 3,
+     "The missing file was successfully removed from the menu.");
+  ok(gScratchpad.notificationBox.currentNotification,
+     "The notification was successfully displayed.");
+  is(gScratchpad.notificationBox.currentNotification.label,
+     gScratchpad.strings.GetStringFromName("fileNoLongerExists.notification"),
+     "The notification label is correct.");
+
   gScratchpad.clearRecentFiles();
 }
 
 // We have cleared the last file. Test to see if the last file was removed,
 // the menu is empty and was disabled successfully.
 function testClearedAll()
 {
   let doc = gScratchpadWindow.document;
@@ -255,16 +281,20 @@ var PreferenceObserver = {
         testHideMenu();
         break;
       case 6:
         this.timesFired = 7;
         testChangedMaxRecent();
         break;
       case 7:
         this.timesFired = 8;
+        testOpenDeletedFile();
+        break;
+      case 8:
+        this.timesFired = 9;
         testClearedAll();
         break;
     }
   },
 
   uninit: function PO_uninit () {
     this.branch.removeObserver("", this);
   }
@@ -272,18 +302,17 @@ var PreferenceObserver = {
 
 function test()
 {
   waitForExplicitFinish();
 
   registerCleanupFunction(function () {
     gFile01.remove(false);
     gFile01 = null;
-    gFile02.remove(false);
-    gFile02 = null;
+    // gFile02 was removed earlier.
     gFile03.remove(false);
     gFile03 = null;
     gFile04.remove(false);
     gFile04 = null;
     lists.recentFiles01 = null;
     lists.recentFiles02 = null;
     lists.recentFiles03 = null;
     lists.recentFiles04 = null;
--- a/browser/locales/en-US/chrome/browser/devtools/scratchpad.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/scratchpad.properties
@@ -73,8 +73,12 @@ scratchpadIntro1=/*\n * This is a JavaSc
 
 # LOCALIZATION NOTE  (notification.browserContext): This is the message displayed
 # over the top of the editor when the user has switched to browser context.
 browserContext.notification=This scratchpad executes in the Browser context.
 
 # LOCALIZATION NOTE (help.openDocumentationPage): This returns a localized link with
 # documentation for Scratchpad on MDN.
 help.openDocumentationPage=https://developer.mozilla.org/en/Tools/Scratchpad
+
+# LOCALIZATION NOTE (fileExists.notification): This is the message displayed
+# over the top of the the editor when a file does not exist.
+fileNoLongerExists.notification=This file no longer exists.