Bug 1119529 always add copied file messages to the db, r=neil, a=rkent
authorR Kent James <rkent@caspia.com>
Sun, 22 Feb 2015 13:26:53 -0800
changeset 25743 e830770c8cd4079db9f4032cdd46f6e3b6c8fa0c
parent 25740 658baa0ae1f5af9014643db1b52640b9c84f5172
child 25744 8c85927c474b15c93493fb89ff5879240eb8a5bf
push id1850
push userclokep@gmail.com
push dateWed, 08 Mar 2017 19:29:12 +0000
treeherdercomm-esr52@028df196b2d9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersneil, rkent
bugs1119529
Bug 1119529 always add copied file messages to the db, r=neil, a=rkent * try: -u all -t none
mailnews/imap/src/nsImapMailFolder.cpp
mailnews/imap/src/nsImapMailFolder.h
--- a/mailnews/imap/src/nsImapMailFolder.cpp
+++ b/mailnews/imap/src/nsImapMailFolder.cpp
@@ -8291,133 +8291,159 @@ nsImapMailFolder::InitCopyState(nsISuppo
 }
 
 nsresult
 nsImapMailFolder::CopyFileToOfflineStore(nsIFile *srcFile, nsMsgKey msgKey)
 {
   nsresult rv = GetDatabase();
   NS_ENSURE_SUCCESS(rv, rv);
 
+  bool storeOffline = (mFlags & nsMsgFolderFlags::Offline) && !WeAreOffline();
+
   if (msgKey == nsMsgKey_None)
+  {
+    // To support send filters, we need to store the message in the database when
+    // it is copied to the FCC folder. In that case, we know the UID of the
+    // message and therefore have the correct msgKey. In other cases, where
+    // we don't need the offline message copied, don't add to db.
+    if (!storeOffline)
+      return NS_OK;
+
     mDatabase->GetNextFakeOfflineMsgKey(&msgKey);
-
+  }
+
+  nsCOMPtr<nsIMsgDBHdr> fakeHdr;
+  rv = mDatabase->CreateNewHdr(msgKey, getter_AddRefs(fakeHdr));
+  NS_ENSURE_SUCCESS(rv, rv);
+  fakeHdr->SetUint32Property("pseudoHdr", 1);
+
+  // Should we add this to the offline store?
+  nsCOMPtr<nsIOutputStream> offlineStore;
+  if (storeOffline)
+  {
+    rv = GetOfflineStoreOutputStream(fakeHdr, getter_AddRefs(offlineStore));
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  // We set an offline kMoveResult because in any case we want to update this
+  // msgHdr with one downloaded from the server, with possible additional
+  // headers added.
   nsCOMPtr<nsIMsgOfflineImapOperation> op;
   rv = mDatabase->GetOfflineOpForKey(msgKey, true, getter_AddRefs(op));
   if (NS_SUCCEEDED(rv) && op)
   {
     nsCString destFolderUri;
     GetURI(destFolderUri);
     op->SetOperation(nsIMsgOfflineImapOperation::kMoveResult);
     op->SetDestinationFolderURI(destFolderUri.get());
-    nsCOMPtr<nsIMsgDBHdr> fakeHdr;
-    nsCOMPtr<nsIOutputStream> offlineStore;
-    rv = mDatabase->CreateNewHdr(msgKey, getter_AddRefs(fakeHdr));
-    NS_ENSURE_SUCCESS(rv, rv);
-    rv = GetOfflineStoreOutputStream(fakeHdr, getter_AddRefs(offlineStore));
     SetFlag(nsMsgFolderFlags::OfflineEvents);
-
-    if (NS_SUCCEEDED(rv) && offlineStore)
-    {
-      int64_t curOfflineStorePos = 0;
-      nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(offlineStore);
-      if (seekable)
-        seekable->Tell(&curOfflineStorePos);
-      else
-      {
-        NS_ERROR("needs to be a random store!");
-        return NS_ERROR_FAILURE;
-      }
-
-      nsCOMPtr<nsIInputStream> inputStream;
-      nsCOMPtr<nsIMsgParseMailMsgState> msgParser =
-        do_CreateInstance(NS_PARSEMAILMSGSTATE_CONTRACTID, &rv);
-      msgParser->SetMailDB(mDatabase);
-
-      // Tell the parser to use the offset that will be in the dest stream, not the
-      //  temp file.
-      uint64_t offset;
-      fakeHdr->GetMessageOffset(&offset);
-      // This will fail for > 4GB mbox folders, see bug 793865
-      msgParser->SetEnvelopePos((uint32_t) offset);
-
-      rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), srcFile);
-      if (NS_SUCCEEDED(rv) && inputStream)
+  }
+
+  nsCOMPtr<nsIInputStream> inputStream;
+  nsCOMPtr<nsIMsgParseMailMsgState> msgParser =
+    do_CreateInstance(NS_PARSEMAILMSGSTATE_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+  msgParser->SetMailDB(mDatabase);
+
+  uint64_t offset = 0;
+  if (offlineStore)
+  {
+    // Tell the parser to use the offset that will be in the dest stream,
+    //   not the temp file.
+    fakeHdr->GetMessageOffset(&offset);
+  }
+  // This will fail for > 4GB mbox folders, see bug 793865
+  msgParser->SetEnvelopePos((uint32_t) offset);
+
+  rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), srcFile);
+  if (NS_SUCCEEDED(rv) && inputStream)
+  {
+    // Now, parse the temp file to (optionally) copy to
+    // the offline store for the cur folder.
+    int32_t inputBufferSize = 10240;
+    nsMsgLineStreamBuffer *inputStreamBuffer =
+      new nsMsgLineStreamBuffer(inputBufferSize, true, false);
+    int64_t fileSize;
+    srcFile->GetFileSize(&fileSize);
+    uint32_t bytesWritten;
+    rv = NS_OK;
+    msgParser->SetState(nsIMsgParseMailMsgState::ParseHeadersState);
+    msgParser->SetNewMsgHdr(fakeHdr);
+    bool needMoreData = false;
+    char * newLine = nullptr;
+    uint32_t numBytesInLine = 0;
+    if (offlineStore)
+    {
+      const char *envelope = "From " CRLF;
+      offlineStore->Write(envelope, strlen(envelope), &bytesWritten);
+      fileSize += bytesWritten;
+    }
+    do
+    {
+      newLine = inputStreamBuffer->ReadNextLine(inputStream, numBytesInLine, needMoreData);
+      if (newLine)
       {
-        // now, copy the temp file to the offline store for the cur folder.
-        int32_t inputBufferSize = 10240;
-        nsMsgLineStreamBuffer *inputStreamBuffer =
-          new nsMsgLineStreamBuffer(inputBufferSize, true, false);
-        int64_t fileSize;
-        srcFile->GetFileSize(&fileSize);
-        uint32_t bytesWritten;
-        rv = NS_OK;
-        msgParser->SetState(nsIMsgParseMailMsgState::ParseHeadersState);
-        msgParser->SetNewMsgHdr(fakeHdr);
-        bool needMoreData = false;
-        char * newLine = nullptr;
-        uint32_t numBytesInLine = 0;
-        const char *envelope = "From " CRLF;
-        offlineStore->Write(envelope, strlen(envelope), &bytesWritten);
-        fileSize += bytesWritten;
-        do
-        {
-          newLine = inputStreamBuffer->ReadNextLine(inputStream, numBytesInLine, needMoreData);
-          if (newLine)
-          {
-            msgParser->ParseAFolderLine(newLine, numBytesInLine);
-            rv = offlineStore->Write(newLine, numBytesInLine, &bytesWritten);
-            NS_Free(newLine);
-          }
-        } while (newLine);
-
-        msgParser->FinishHeader();
-        uint32_t resultFlags;
-        fakeHdr->OrFlags(nsMsgMessageFlags::Offline | nsMsgMessageFlags::Read, &resultFlags);
-        fakeHdr->SetOfflineMessageSize(fileSize);
-        fakeHdr->SetUint32Property("pseudoHdr", 1);
-        mDatabase->AddNewHdrToDB(fakeHdr, true /* notify */);
-        SetFlag(nsMsgFolderFlags::OfflineEvents);
-
-        // Call FinishNewMessage before setting pending attributes, as in
-        //   maildir it copies from tmp to cur and may change the storeToken
-        //   to get a unique filename.
-        nsCOMPtr<nsIMsgPluggableStore> msgStore;
-        GetMsgStore(getter_AddRefs(msgStore));
-        if (msgStore)
-          msgStore->FinishNewMessage(offlineStore, fakeHdr);
-
-        nsCOMPtr<nsIMutableArray> messages(do_CreateInstance(NS_ARRAY_CONTRACTID, &rv));
+        msgParser->ParseAFolderLine(newLine, numBytesInLine);
+        if (offlineStore)
+          rv = offlineStore->Write(newLine, numBytesInLine, &bytesWritten);
+
+        NS_Free(newLine);
         NS_ENSURE_SUCCESS(rv, rv);
-        messages->AppendElement(fakeHdr, false);
-
-        SetPendingAttributes(messages, false);
-        // Gloda needs this notification to index the fake message.
-        nsCOMPtr<nsIMsgFolderNotificationService>
-          notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
-        if (notifier)
-          notifier->NotifyMsgsClassified(messages, false, false);
-        inputStream->Close();
-        inputStream = nullptr;
-        delete inputStreamBuffer;
       }
-      offlineStore->Close();
-    }
-  }
+    } while (newLine);
+
+    msgParser->FinishHeader();
+    uint32_t resultFlags;
+    if (offlineStore)
+      fakeHdr->OrFlags(nsMsgMessageFlags::Offline | nsMsgMessageFlags::Read, &resultFlags);
+    else
+      fakeHdr->OrFlags(nsMsgMessageFlags::Read, &resultFlags);
+    if (offlineStore)          
+      fakeHdr->SetOfflineMessageSize(fileSize);
+    mDatabase->AddNewHdrToDB(fakeHdr, true /* notify */);
+
+    // Call FinishNewMessage before setting pending attributes, as in
+    //   maildir it copies from tmp to cur and may change the storeToken
+    //   to get a unique filename.
+    if (offlineStore)
+    {
+      nsCOMPtr<nsIMsgPluggableStore> msgStore;
+      GetMsgStore(getter_AddRefs(msgStore));
+      if (msgStore)
+        msgStore->FinishNewMessage(offlineStore, fakeHdr);
+    }
+
+    nsCOMPtr<nsIMutableArray> messages(do_CreateInstance(NS_ARRAY_CONTRACTID, &rv));
+    NS_ENSURE_SUCCESS(rv, rv);
+    messages->AppendElement(fakeHdr, false);
+
+    SetPendingAttributes(messages, false);
+    // Gloda needs this notification to index the fake message.
+    nsCOMPtr<nsIMsgFolderNotificationService>
+      notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
+    if (notifier)
+      notifier->NotifyMsgsClassified(messages, false, false);
+    inputStream->Close();
+    inputStream = nullptr;
+    delete inputStreamBuffer;
+  }
+  if (offlineStore)
+    offlineStore->Close();
   return rv;
 }
 
 nsresult
 nsImapMailFolder::OnCopyCompleted(nsISupports *srcSupport, nsresult rv)
 {
   // if it's a file, and the copy succeeded, then fcc the offline
   // store, and add a kMoveResult offline op.
   if (NS_SUCCEEDED(rv) && m_copyState)
   {
     nsCOMPtr<nsIFile> srcFile(do_QueryInterface(srcSupport));
-    if (srcFile && (mFlags & nsMsgFolderFlags::Offline) && !WeAreOffline())
+    if (srcFile)
       (void) CopyFileToOfflineStore(srcFile, m_copyState->m_appendUID);
   }
   m_copyState = nullptr;
   nsresult result;
   nsCOMPtr<nsIMsgCopyService> copyService = do_GetService(NS_MSGCOPYSERVICE_CONTRACTID, &result);
   NS_ENSURE_SUCCESS(result, result);
   return copyService->NotifyCompletion(srcSupport, this, rv);
 }
--- a/mailnews/imap/src/nsImapMailFolder.h
+++ b/mailnews/imap/src/nsImapMailFolder.h
@@ -360,16 +360,24 @@ protected:
   nsresult NotifyMessageFlagsFromHdr(nsIMsgDBHdr *dbHdr, nsMsgKey msgKey,
                                      uint32_t flags);
 
   nsresult SetupHeaderParseStream(uint32_t size, const nsACString& content_type, nsIMailboxSpec *boxSpec);
   nsresult  ParseAdoptedHeaderLine(const char *messageLine, nsMsgKey msgKey);
   nsresult  NormalEndHeaderParseStream(nsIImapProtocol *aProtocol, nsIImapUrl *imapUrl);
 
   void EndOfflineDownload();
+
+  /**
+   * At the end of a file-to-folder copy operation, copy the file to the
+   * offline store and/or add to the message database, (if needed).
+   *
+   * @param srcFile       file containing the message key
+   * @param msgKey        key to use for the new messages
+   */   
   nsresult CopyFileToOfflineStore(nsIFile *srcFile, nsMsgKey msgKey);
 
   nsresult MarkMessagesImapDeleted(nsTArray<nsMsgKey> *keyArray, bool deleted, nsIMsgDatabase *db);
 
   // Notifies imap autosync that it should update this folder when it
   // gets a chance.
   void NotifyHasPendingMsgs();
   void UpdatePendingCounts();