Bug 542998 - Need option to disable Archiving completely; r=asuth sr=bienvenu ui-r=clarkbw
authorJim <squibblyflabbetydoo@gmail.com>
Wed, 09 Mar 2011 09:24:57 +0000
changeset 7287 0347b42406e647d88d4ebfe55444f2f3c334ddd3
parent 7286 51964922420382df12dc06f04be2af86986d19c8
child 7288 95afb3f1f6c98a114ff39567587267aa353b8100
push idunknown
push userunknown
push dateunknown
reviewersasuth, bienvenu, clarkbw
bugs542998
Bug 542998 - Need option to disable Archiving completely; r=asuth sr=bienvenu ui-r=clarkbw
mail/base/content/mail3PaneWindowCommands.js
mail/base/content/mailWindowOverlay.js
mail/base/content/messageWindow.js
mail/base/content/nsContextMenu.js
mail/base/content/selectionsummaries.js
mail/test/mozmill/folder-display/test-message-commands.js
mailnews/base/public/nsIMsgIdentity.idl
mailnews/base/src/nsMsgAccountManager.cpp
mailnews/base/util/nsMsgIdentity.cpp
mailnews/imap/src/nsImapIncomingServer.cpp
mailnews/mailnews.js
--- a/mail/base/content/mail3PaneWindowCommands.js
+++ b/mail/base/content/mail3PaneWindowCommands.js
@@ -372,26 +372,18 @@ var DefaultController =
       case "cmd_printSetup":
       case "cmd_viewAllHeader":
       case "cmd_viewNormalHeader":
         return true;
       case "cmd_markAsFlagged":
       case "button_file":
       case "cmd_file":
       case "cmd_archive":
-        let selectedMessages = gFolderDisplay.selectedMessages;
-        let archiveKfs =  selectedMessages.length > 0 && selectedMessages[0].folder &&
-           selectedMessages[0].folder.server.archiveKeepFolderStructure;
-        if (!archiveKfs)
-          return gFolderDisplay.selectedCount > 0;
-        // Otherwise, we fall through to checking if we're an archive folder.
       case "button_archive":
-        return gFolderDisplay.selectedCount > 0 && gFolderDisplay.displayedFolder &&
-          !gFolderDisplay.displayedFolder.isSpecialFolder(
-             Components.interfaces.nsMsgFolderFlags.Archive, true);
+        return CanArchiveMsg();
       case "cmd_markAsJunk":
       case "cmd_markAsNotJunk":
         return gFolderDisplay.getCommandStatus(nsMsgViewCommandType.junk);
       case "cmd_recalculateJunkScore":
         // We're going to take a conservative position here, because we really
         // don't want people running junk controls on folders that are not
         // enabled for junk. The junk type picks up possible dummy message headers,
         // while the runJunkControls will prevent running on XF virtual folders.
--- a/mail/base/content/mailWindowOverlay.js
+++ b/mail/base/content/mailWindowOverlay.js
@@ -1523,16 +1523,40 @@ BatchMessageMover.prototype = {
     if (!iid.equals(Components.interfaces.nsIUrlListener) &&
       !iid.equals(Components.interfaces.nsIMsgCopyServiceListener) &&
       !iid.equals(Components.interfaces.nsISupports))
       throw Components.results.NS_ERROR_NO_INTERFACE;
     return this;
   }
 }
 
+/**
+ * Checks if the selected messages can be archived. This depends on what folder
+ * they're in and whether archiving is enabled for that identity.
+ *
+ * @return true if all selected messages can be archived, false otherwise
+ */
+function CanArchiveMsg()
+{
+  if (gFolderDisplay.selectedCount == 0)
+    return false;
+  if (!gFolderDisplay.displayedFolder ||
+      gFolderDisplay.displayedFolder.isSpecialFolder(
+        Components.interfaces.nsMsgFolderFlags.Archive, true))
+    return false;
+  return gFolderDisplay.selectedMessages.every(function(msg) {
+      return getIdentityForHeader(msg).archiveEnabled;
+    });
+}
+
+/**
+ * Archives the selected messages
+ *
+ * @param event the event that caused us to call this function
+ */
 function MsgArchiveSelectedMessages(event)
 {
   let batchMover = new BatchMessageMover();
   batchMover.archiveMessages(gFolderDisplay.selectedMessages);
 }
 
 function MsgForwardMessage(event)
 {
--- a/mail/base/content/messageWindow.js
+++ b/mail/base/content/messageWindow.js
@@ -822,20 +822,17 @@ var MessageWindowController =
       case "cmd_markAsJunk":
       case "cmd_markAsNotJunk":
         return gFolderDisplay.getCommandStatus(nsMsgViewCommandType.junk);
       case "cmd_recalculateJunkScore":
         return gFolderDisplay.selectedMessage &&
                gFolderDisplay.getCommandStatus(nsMsgViewCommandType.runJunkControls);
       case "cmd_archive":
       case "button_archive":
-        var folder = gFolderDisplay.displayedFolder;
-        return folder &&
-          !folder.isSpecialFolder(Components.interfaces.nsMsgFolderFlags.Archive,
-                                  true);
+        return CanArchiveMsg();
       case "cmd_reply":
       case "button_reply":
       case "cmd_replyall":
       case "button_replyall":
         return gFolderDisplay.selectedMessage && IsReplyEnabled();
       case "cmd_replylist":
       case "button_replylist":
         return gFolderDisplay.selectedMessage && IsReplyListEnabled();
--- a/mail/base/content/nsContextMenu.js
+++ b/mail/base/content/nsContextMenu.js
@@ -278,18 +278,20 @@ nsContextMenu.prototype = {
                   this.numSelectedMessages > 1 && this.inThreadPane &&
                   !this.hideMailItems);
 
     this.setSingleSelection("mailContext-copyMessageUrl", this.isNewsgroup);
 
     let msgModifyItems = this.numSelectedMessages > 0 && !this.hideMailItems &&
       !this.onPlayableMedia &&
       !(this.numSelectedMessages == 1 && gMessageDisplay.isDummy);
+    let canArchive = CanArchiveMsg();
 
-    this.showItem("mailContext-archive", canMove && msgModifyItems);
+    this.showItem("mailContext-archive", canMove && msgModifyItems &&
+                                         canArchive);
 
     // Set up the move menu. We can't move from newsgroups.
     this.showItem("mailContext-moveMenu",
                   msgModifyItems && !this.isNewsgroup);
 
     // disable move if we can't delete message(s) from this folder
     this.enableItem("mailContext-moveMenu", canMove && !this.onPlayableMedia);
 
--- a/mail/base/content/selectionsummaries.js
+++ b/mail/base/content/selectionsummaries.js
@@ -257,16 +257,20 @@ MultiMessageSummary.prototype = {
     _mm_addClass(heading, "info");
 
     let messagesTitle =
       PluralForm.get(numThreads, gSelectionSummaryStrings["NConversations"])
                 .replace("#1", numThreads);
 
     heading.textContent = messagesTitle;
 
+    // enable/disable the archive button as appropriate
+    let archiveBtn = htmlpane.contentDocument.getElementById('archive');
+    archiveBtn.collapsed = !CanArchiveMsg();
+
     // clear the messages list
     let messagesElt = htmlpane.contentDocument.getElementById('messagelist');
     while (messagesElt.firstChild)
       messagesElt.removeChild(messagesElt.firstChild);
 
     const MAX_MESSAGES = 100;
     const SNIPPET_LENGTH = 300;
     let count = 0;
@@ -547,16 +551,20 @@ ThreadSummary.prototype = {
     let numMessages = this._msgHdrs.length;
     let subject = (firstMsgHdr.mime2DecodedSubject || gSelectionSummaryStrings["noSubject"])
        + " "
        + PluralForm.get(numMessages, gSelectionSummaryStrings["Nmessages"]).replace('#1', numMessages);
     let heading = htmlpane.contentDocument.getElementById('heading');
     heading.setAttribute("class", "heading");
     heading.textContent = subject;
 
+    // enable/disable the archive button as appropriate
+    let archiveBtn = htmlpane.contentDocument.getElementById('archive');
+    archiveBtn.collapsed = !CanArchiveMsg();
+
     let messagesElt = htmlpane.contentDocument.getElementById('messagelist');
     while (messagesElt.firstChild)
       messagesElt.removeChild(messagesElt.firstChild);
 
     let headerParser = Components.classes["@mozilla.org/messenger/headerparser;1"]
                                     .getService(Components.interfaces.nsIMsgHeaderParser);
     let count = 0;
     const MAX_THREADS = 100;
--- a/mail/test/mozmill/folder-display/test-message-commands.js
+++ b/mail/test/mozmill/folder-display/test-message-commands.js
@@ -84,17 +84,16 @@ function check_read_status(messages, rea
                 ", expected " + read_str(read));
 }
 
 /**
  * Ensures that the mark read/unread menu items are enabled/disabled properly
  * @param canMarkRead true if the mark read item should be enabled
  * @param canMarkUnread true if the mark unread item should be enabled
  */
-
 function check_read_menuitems(index, canMarkRead, canMarkUnread) {
   right_click_on_row(index);
   mc.click_menus_in_sequence(mc.e("mailContext"), [{id: "mailContext-mark"}]);
 
   let readEnabled = !mc.e("mailContext-markRead").disabled;
   let unreadEnabled = !mc.e("mailContext-markUnread").disabled;
 
   // Close both the mark submenu and the main context menu
@@ -105,16 +104,22 @@ function check_read_menuitems(index, can
               "Mark read menu item " + (canMarkRead ? "dis" : "en") +
               "abled when it shouldn't be!");
 
   assert_true(unreadEnabled == canMarkUnread,
               "Mark unread menu item " + (canMarkUnread ? "dis" : "en") +
               "abled when it shouldn't be!");
 }
 
+function enable_archiving(enabled) {
+  Cc["@mozilla.org/preferences-service;1"]
+   .getService(Ci.nsIPrefService).getBranch(null)
+   .setBoolPref("mail.identity.default.archive_enabled", enabled);
+}
+
 // XXX Disabled due to issues with running these tests on tinderbox
 /*
 function test_mark_one_read() {
   be_in_folder(unreadFolder);
   let curMessage = select_click_row(0);
 
   curMessage.markRead(false);
   mc.keypress(null, "m", {});
@@ -260,16 +265,17 @@ function yearly_archive(keep_structure) 
               "Message should have been archived to " + firstArchiveUri + ", but it isn't present there");
   be_in_folder(lastArchiveFolder);
 
   assert_true(mc.dbView.getMsgHdrAt(0).messageId == lastMsgHdrMsgId,
               "Message should have been archived to " + lastArchiveUri + ", but it isn't present there");
 }
 
 function test_monthly_archive() {
+  enable_archiving(true);
   monthly_archive(false);
 }
 
 function monthly_archive(keep_structure) {
   be_in_folder(archiveSrcFolder);
   let identity = acctMgr.getFirstIdentityForServer(mc.folderDisplay.view.dbView
                                                    .getMsgHdrAt(0).folder.server);
   identity.archiveGranularity = Ci.nsIMsgIdentity.perMonthArchiveFolders;
@@ -308,29 +314,56 @@ function monthly_archive(keep_structure)
               firstMsgYear + "/" + firstMonthFolderName + "/Archives, but it isn't present there");
   be_in_folder(lastArchiveFolder);
   assert_true(mc.dbView.getMsgHdrAt(0).messageId == lastMsgHdrMsgId,
               "Message should have been archived to Local Folders/" +
               lastMsgYear + "/" + lastMonthFolderName + "/Archives, but it isn't present there");
 }
 
 function test_folder_structure_archiving() {
+  enable_archiving(true);
   Cc["@mozilla.org/preferences-service;1"]
    .getService(Ci.nsIPrefService).getBranch(null)
    .setBoolPref("mail.identity.default.archive_keep_folder_structure", true);
   monthly_archive(true);
   yearly_archive(true);
 }
 
 function test_selection_after_archive() {
+  enable_archiving(true);
   be_in_folder(archiveSrcFolder);
   let identity = acctMgr.getFirstIdentityForServer(mc.folderDisplay.view.dbView
                                                    .getMsgHdrAt(0).folder.server);
   identity.archiveGranularity = Ci.nsIMsgIdentity.perMonthArchiveFolders;
   // We had a bug where we would always select the 0th message after an
   // archive, so test that we'll actually select the next remaining message
   // by archiving rows 1 & 2 and verifying that the 3rd message gets selected.
   let hdrToSelect = select_click_row(3);
   select_click_row(1);
   select_control_click_row(2);
   archive_selected_messages();
   assert_selected_and_displayed(hdrToSelect);
 }
+
+function test_disabled_archive() {
+  enable_archiving(false);
+  be_in_folder(archiveSrcFolder);
+
+  // test single message
+  let current = select_click_row(0);
+  mc.keypress(null, "a", {});
+  assert_selected_and_displayed(current);
+
+  assert_true(mc.e("hdrArchiveButton").disabled,
+              "Archive button should be disabled when archiving is disabled!");
+
+  // test message summaries
+  select_click_row(0);
+  current = select_shift_click_row(2);
+  mc.keypress(null, "a", {});
+  assert_selected_and_displayed(current);
+
+  let htmlframe = mc.e("multimessage");
+  let archiveBtn = htmlframe.contentDocument.getElementById("archive");
+  assert_true(archiveBtn.collapsed,
+              "Multi-message archive button should be disabled when " +
+              "archiving is disabled!");
+}
--- a/mailnews/base/public/nsIMsgIdentity.idl
+++ b/mailnews/base/public/nsIMsgIdentity.idl
@@ -40,17 +40,17 @@
 #include "nsILocalFile.idl"
 
 /**
  * This interface contains all the personal outgoing mail information
  * for a given person.
  * Each identity is identified by a key, which is the <id> string in
  * the identity preferences, such as in mail.identity.<id>.replyTo.
  */
-[scriptable, uuid(5e68bec0-aa51-11df-94e2-0800200c9a66)]
+[scriptable, uuid(98897ee8-42ac-11e0-94df-080027eef196)]
 interface nsIMsgIdentity : nsISupports {
   /**
    * Internal preferences ID.
    */
   attribute ACString key;
 
   /**
    * Overriding display name for this identity. If this pref is not set
@@ -183,16 +183,17 @@ interface nsIMsgIdentity : nsISupports {
    * @{
    * URIs for the special folders (drafts, templates, archive)
    */
   attribute ACString draftFolder;
   attribute ACString archiveFolder;
   attribute ACString stationeryFolder;
   /** @} */
 
+  attribute boolean archiveEnabled;
   /**
    * @{
    * This attribute and constants control the granularity of sub-folders of the
    * Archives folder - either messages go in the single archive folder, or a
    * yearly archive folder, or in a monthly archive folder with a yearly
    * parent folder. If the server doesn't support folders that both contain
    * messages and have sub-folders, we will ignore this setting.
    */
--- a/mailnews/base/src/nsMsgAccountManager.cpp
+++ b/mailnews/base/src/nsMsgAccountManager.cpp
@@ -1529,17 +1529,27 @@ nsMsgAccountManager::SetSpecialFolders()
       if (!folderUri.IsEmpty() && NS_SUCCEEDED(rdf->GetResource(folderUri, getter_AddRefs(res))))
       {
         folder = do_QueryInterface(res, &rv);
         nsCOMPtr <nsIMsgFolder> parent;
         if (folder && NS_SUCCEEDED(rv))
         {
           rv = folder->GetParent(getter_AddRefs(parent));
           if (NS_SUCCEEDED(rv) && parent)
-            rv = folder->SetFlag(nsMsgFolderFlags::Archive);
+          {
+            PRBool archiveEnabled;
+            thisIdentity->GetArchiveEnabled(&archiveEnabled);
+            if (archiveEnabled)
+              rv = folder->SetFlag(nsMsgFolderFlags::Archive);
+            else
+            {
+              printf("Clearing archive flag\n");
+              rv = folder->ClearFlag(nsMsgFolderFlags::Archive);
+            }
+          }
         }
       }
       thisIdentity->GetStationeryFolder(folderUri);
       if (!folderUri.IsEmpty() && NS_SUCCEEDED(rdf->GetResource(folderUri, getter_AddRefs(res))))
       {
         folder = do_QueryInterface(res, &rv);
         if (folder && NS_SUCCEEDED(rv))
         {
--- a/mailnews/base/util/nsMsgIdentity.cpp
+++ b/mailnews/base/util/nsMsgIdentity.cpp
@@ -268,16 +268,17 @@ nsMsgIdentity::SetDoBccList(const nsACSt
 {
   return SetCharAttribute("doBccList", aValue);
 }
 
 NS_IMPL_FOLDERPREF_STR(DraftFolder, "draft_folder", "Drafts", nsMsgFolderFlags::Drafts)
 NS_IMPL_FOLDERPREF_STR(ArchiveFolder, "archive_folder", "Archives", nsMsgFolderFlags::Archive)
 NS_IMPL_FOLDERPREF_STR(StationeryFolder, "stationery_folder", "Templates", nsMsgFolderFlags::Templates)
 
+NS_IMPL_IDPREF_BOOL(ArchiveEnabled, "archive_enabled")
 NS_IMPL_IDPREF_INT(ArchiveGranularity, "archive_granularity")
 NS_IMPL_IDPREF_BOOL(ArchiveKeepFolderStructure, "archive_keep_folder_structure")
 
 NS_IMPL_IDPREF_BOOL(ShowSaveMsgDlg, "showSaveMsgDlg")
 NS_IMPL_IDPREF_STR (DirectoryServer, "directoryServer")
 NS_IMPL_IDPREF_BOOL(OverrideGlobalPref, "overrideGlobal_Pref")
 NS_IMPL_IDPREF_BOOL(AutocompleteToMyDomain, "autocompleteToMyDomain")
 
--- a/mailnews/imap/src/nsImapIncomingServer.cpp
+++ b/mailnews/imap/src/nsImapIncomingServer.cpp
@@ -1471,22 +1471,27 @@ NS_IMETHODIMP nsImapIncomingServer::Disc
       }
       identity->GetDraftFolder(folderUri);
       if (CheckSpecialFolder(rdf, folderUri, nsMsgFolderFlags::Drafts,
                              existingUri))
       {
         identity->SetDraftFolder(existingUri);
         identity->SetDraftsFolderPickerMode(NS_LITERAL_CSTRING("1"));
       }
-      identity->GetArchiveFolder(folderUri);
-      if (CheckSpecialFolder(rdf, folderUri, nsMsgFolderFlags::Archive,
-                             existingUri))
+      PRBool archiveEnabled;
+      identity->GetArchiveEnabled(&archiveEnabled);
+      if (archiveEnabled)
       {
-        identity->SetArchiveFolder(existingUri);
-        identity->SetArchivesFolderPickerMode(NS_LITERAL_CSTRING("1"));
+        identity->GetArchiveFolder(folderUri);
+        if (CheckSpecialFolder(rdf, folderUri, nsMsgFolderFlags::Archive,
+                               existingUri))
+        {
+          identity->SetArchiveFolder(existingUri);
+          identity->SetArchivesFolderPickerMode(NS_LITERAL_CSTRING("1"));
+        }
       }
       identity->GetStationeryFolder(folderUri);
       nsCOMPtr<nsIRDFResource> res;
       if (!folderUri.IsEmpty() && NS_SUCCEEDED(rdf->GetResource(folderUri, getter_AddRefs(res))))
       {
         nsCOMPtr<nsIMsgFolder> folder(do_QueryInterface(res, &rv));
         if (NS_SUCCEEDED(rv))
           rv = folder->SetFlag(nsMsgFolderFlags::Templates);
--- a/mailnews/mailnews.js
+++ b/mailnews/mailnews.js
@@ -348,16 +348,17 @@ pref("mailnews.account_central_page.url"
 /* default prefs for Mozilla 5.0 */
 pref("mail.identity.default.compose_html", true);
 pref("mail.identity.default.valid", true);
 pref("mail.identity.default.fcc", true);
 pref("mail.identity.default.fcc_folder", "mailbox://nobody@Local%20Folders/Sent");
 pref("mail.identity.default.fcc_reply_follows_parent", false);
 pref("mail.identity.default.autocompleteToMyDomain", false);
 
+pref("mail.identity.default.archive_enabled", true);
 // archive into 0: single folder, 1: yearly folder, 2: year/year-month folder
 pref("mail.identity.default.archive_granularity", 1);
 pref("mail.identity.default.archive_keep_folder_structure", false);
 
 // keep these defaults for backwards compatibility and migration
 
 // but .doBcc and .doBccList are the right ones from now on.
 pref("mail.identity.default.bcc_self", false);