Bug 998191, part 12: Simplify mime_generate_headers by returning msgIStructuredHeaders, r=irving, a=jcranmer
authorJoshua Cranmer <Pidgeot18@gmail.com>
Wed, 07 Jan 2015 15:59:54 -0600
changeset 21607 c6f49a08146ca9de04c2915fc1e46a8b17624a7e
parent 21606 a9e2a1b47cddbd20aee3e6b55969868645b8a846
child 21608 b75f54fd61218a108d3b91bb3db83480daf9ac01
push id1305
push usermbanner@mozilla.com
push dateMon, 23 Feb 2015 19:48:12 +0000
treeherdercomm-beta@3ae4f13858fd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersirving, jcranmer
bugs998191
Bug 998191, part 12: Simplify mime_generate_headers by returning msgIStructuredHeaders, r=irving, a=jcranmer With the conclusion of this patch, we now represent the top-level headers using only nsIMsgCompFields and structured headers where appropriate. Carrying forward CLOSED TREE, needed for changes in part 7.
mailnews/compose/src/nsMsgCompUtils.cpp
mailnews/compose/src/nsMsgCompUtils.h
mailnews/compose/src/nsMsgSend.cpp
--- a/mailnews/compose/src/nsMsgCompUtils.cpp
+++ b/mailnews/compose/src/nsMsgCompUtils.cpp
@@ -235,53 +235,42 @@ nsresult mime_sanity_check_fields (
       bool val = false; \
       fields->Get##method(&val); \
       if (val) \
         draftInfo.AppendLiteral(param "=1"); \
       else \
         draftInfo.AppendLiteral(param "=0"); \
     } while (false)
 
-char *
-mime_generate_headers (nsMsgCompFields *fields,
-                       const char *charset,
-                       nsMsgDeliverMode deliver_mode, nsIPrompt * aPrompt, nsresult *status)
+nsresult mime_generate_headers(nsIMsgCompFields *fields,
+                               nsMsgDeliverMode deliver_mode,
+                               msgIWritableStructuredHeaders *finalHeaders)
 {
-  nsresult rv;
-  *status = NS_OK;
+  nsresult rv = NS_OK;
 
   nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
-  if (NS_FAILED(rv)) {
-    *status = rv;
-    return nullptr;
-  }
+  NS_ENSURE_SUCCESS(rv, rv);
 
   bool isDraft =
     deliver_mode == nsIMsgSend::nsMsgSaveAsDraft ||
     deliver_mode == nsIMsgSend::nsMsgSaveAsTemplate ||
     deliver_mode == nsIMsgSend::nsMsgQueueForLater ||
     deliver_mode == nsIMsgSend::nsMsgDeliverBackground;
 
   bool hasDisclosedRecipient = false;
 
-  NS_ASSERTION (fields, "null fields");
-  if (!fields) {
-    *status = NS_ERROR_NULL_POINTER;
-    return nullptr;
-  }
+  MOZ_ASSERT(fields, "null fields");
+  NS_ENSURE_ARG_POINTER(fields);
 
   nsCOMArray<msgIAddressObject> from;
   fields->GetAddressingHeader("From", from, true);
 
-  // Make a new block of headers to store the usable headers in, and copy all
-  // headers from the original compose field.
-  nsCOMPtr<msgIWritableStructuredHeaders> finalHeaders =
-    do_CreateInstance(NS_ISTRUCTUREDHEADERS_CONTRACTID);
+  // Copy all headers from the original compose field.
   rv = finalHeaders->AddAllHeaders(fields);
-  MOZ_ASSERT(NS_SUCCEEDED(rv), "This shouldn't fail");
+  NS_ENSURE_SUCCESS(rv, rv);
 
   bool hasMessageId = false;
   if (NS_SUCCEEDED(fields->HasHeader("Message-ID", &hasMessageId)) &&
       hasMessageId)
   {
     /* MDN request header requires to have MessageID header presented
     * in the message in order to
     * coorelate the MDN reports to the original message. Here will be
@@ -380,45 +369,37 @@ mime_generate_headers (nsMsgCompFields *
   if (!newsgroups.IsEmpty())
   {
     // Since the newsgroup header can contain data in the form of:
     // "news://news.mozilla.org/netscape.test,news://news.mozilla.org/netscape.junk"
     // we need to turn that into: "netscape.test,netscape.junk"
     // (XXX: can it really?)
     nsCOMPtr<nsINntpService> nntpService =
       do_GetService("@mozilla.org/messenger/nntpservice;1", &rv);
-    if (NS_FAILED(rv) || !nntpService)
-    {
-      *status = NS_ERROR_FAILURE;
-      return nullptr;
-    }
+    NS_ENSURE_SUCCESS(rv, rv);
 
     nsCString newsgroupsHeaderVal;
     nsCString newshostHeaderVal;
     rv = nntpService->GenerateNewsHeaderValsForPosting(newsgroups,
       getter_Copies(newsgroupsHeaderVal), getter_Copies(newshostHeaderVal));
-    if (NS_FAILED(rv))
-    {
-      *status = rv;
-      return nullptr;
-    }
-    finalHeaders->SetRawHeader("Newsgroups", newsgroupsHeaderVal, charset);
+    NS_ENSURE_SUCCESS(rv, rv);
+    finalHeaders->SetRawHeader("Newsgroups", newsgroupsHeaderVal, nullptr);
 
     // If we are here, we are NOT going to send this now. (i.e. it is a Draft,
     // Send Later file, etc...). Because of that, we need to store what the user
     // typed in on the original composition window for use later when rebuilding
     // the headers
     if (deliver_mode != nsIMsgSend::nsMsgDeliverNow &&
         deliver_mode != nsIMsgSend::nsMsgSendUnsent)
     {
       // This is going to be saved for later, that means we should just store
       // what the user typed into the "Newsgroup" line in the HEADER_X_MOZILLA_NEWSHOST
       // header for later use by "Send Unsent Messages", "Drafts" or "Templates"
       finalHeaders->SetRawHeader(HEADER_X_MOZILLA_NEWSHOST, newshostHeaderVal,
-        charset);
+        nullptr);
     }
 
     // Newsgroups are a recipient...
     hasDisclosedRecipient = true;
   }
 
   nsCOMArray<msgIAddressObject> recipients;
   finalHeaders->GetAddressingHeader("To", recipients);
@@ -521,20 +502,17 @@ mime_generate_headers (nsMsgCompFields *
     }
     // The In-Reply-To header is the last entry in the references header...
     int32_t bracket = references.RFind("<");
     if (bracket >= 0)
       finalHeaders->SetRawHeader("In-Reply-To", Substring(references, bracket),
         nullptr);
   }
 
-  // Convert the blocks of headers into a single string for emission.
-  nsCString headerText;
-  finalHeaders->BuildMimeText(headerText);
-  return ToNewCString(headerText);
+  return NS_OK;
 }
 
 #undef APPEND_BOOL // X-Mozilla-Draft-Info helper macro
 
 static void
 GenerateGlobalRandomBytes(unsigned char *buf, int32_t len)
 {
   static bool      firstTime = true;
--- a/mailnews/compose/src/nsMsgCompUtils.h
+++ b/mailnews/compose/src/nsMsgCompUtils.h
@@ -64,20 +64,19 @@ nsresult    mime_sanity_check_fields (
                             const char *fcc,
                             const char *newsgroups,
                             const char *followup_to,
                             const char * /*subject*/,
                             const char * /*references*/,
                             const char * /*organization*/,
                             const char * /*other_random_headers*/);
 
-char        *mime_generate_headers (nsMsgCompFields *fields,
-                                    const char *charset,
-                                    nsMsgDeliverMode deliver_mode,
-                                    nsIPrompt * aPrompt, nsresult *status);
+nsresult mime_generate_headers(nsIMsgCompFields *fields,
+                               nsMsgDeliverMode deliver_mode,
+                               msgIWritableStructuredHeaders *headers);
 
 char        *mime_make_separator(const char *prefix);
 char        *mime_gen_content_id(uint32_t aPartNum, const char *aEmailAddress);
 
 char        *mime_generate_attachment_headers (
                            const char *type,
                            const char *type_param,
                            const char *encoding,
--- a/mailnews/compose/src/nsMsgSend.cpp
+++ b/mailnews/compose/src/nsMsgSend.cpp
@@ -421,24 +421,19 @@ void nsMsgComposeAndSend::GenerateMessag
    encoded as appropriate.
  */
 NS_IMETHODIMP
 nsMsgComposeAndSend::GatherMimeAttachments()
 {
   bool shouldDeleteDeliveryState = true;
   nsresult status;
   uint32_t    i;
-  char *headers = 0;
   PRFileDesc  *in_file = 0;
-  bool multipart_p = false;
-  bool plaintext_is_mainbody_p = false; // only using text converted from HTML?
   char *buffer = 0;
-  char *buffer_tail = 0;
   nsString msg;
-  bool tonews;
   bool body_is_us_ascii = true;
 
   nsMsgSendPart* toppart = nullptr;      // The very top most container of the message
                       // that we are going to send.
 
   nsMsgSendPart* mainbody = nullptr;     // The leaf node that contains the text of the
                       // message we're going to contain.
 
@@ -461,28 +456,16 @@ nsMsgComposeAndSend::GatherMimeAttachmen
 
   nsCOMPtr<nsIPrompt> promptObject; // only used if we have to show an alert here....
   GetDefaultPrompt(getter_AddRefs(promptObject));
 
   char *hdrs = 0;
   bool maincontainerISrelatedpart = false;
   const char * toppart_type = nullptr;
 
-  // If we have any attachments, we generate multipart.
-  multipart_p = (m_attachment_count > 0);
-
-  // to news is true if we have a m_field and we have a Newsgroup and it is not empty
-  tonews = false;
-  if (mCompFields)
-  {
-    const char* pstrzNewsgroup = mCompFields->GetNewsgroups();
-    if (pstrzNewsgroup && *pstrzNewsgroup)
-      tonews = true;
-  }
-
   status = m_status;
   if (NS_FAILED(status))
     goto FAIL;
 
   if (!m_attachment1_type) {
     m_attachment1_type = PL_strdup(TEXT_PLAIN);
     if (!m_attachment1_type)
       goto FAILMEM;
@@ -567,18 +550,16 @@ nsMsgComposeAndSend::GatherMimeAttachmen
       return NS_OK;
   }
 
   /* Kludge to avoid having to allocate memory on the toy computers... */
   buffer = mime_get_stream_write_buffer();
   if (! buffer)
     goto FAILMEM;
 
-  buffer_tail = buffer;
-
   NS_ASSERTION (m_attachment_pending_count == 0, "m_attachment_pending_count != 0");
 
   mComposeBundle->GetStringFromName(MOZ_UTF16("assemblingMessage"),
                                     getter_Copies(msg));
   SetStatusMessage( msg );
 
   /* First, open the message file.
   */
@@ -739,18 +720,16 @@ nsMsgComposeAndSend::GatherMimeAttachmen
       PR_FREEIF(m_attachment1_type);
       m_attachment1_type = PL_strdup(TEXT_PLAIN);
       if (!m_attachment1_type)
         goto FAILMEM;
 
       /* Override attachment1_encoding here. */
       PR_FREEIF(m_attachment1_encoding);
       m_attachment1_encoding = ToNewCString(m_plaintext->m_encoding);
-
-      plaintext_is_mainbody_p = true; // converted plaintext is mainbody
     }
   }
 
   // check if we need to encapsulate the message in a multipart/mixed or multipart/digest
   if (m_attachment_count > multipartRelatedCount)
   {
     toppart = new nsMsgSendPart(this);
     if (!toppart)
@@ -773,48 +752,45 @@ nsMsgComposeAndSend::GatherMimeAttachmen
   toppart_type = toppart->GetType(); // GetType return directly the member variable, don't free it!
   if (!m_crypto_closure && toppart_type && !PL_strncasecmp(toppart_type, "multipart/", 10))
   {
     status = toppart->SetBuffer(MIME_MULTIPART_BLURB);
     if (NS_FAILED(status))
       goto FAIL;
   }
 
-   /* Write out the message headers.
-   */
-  headers = mime_generate_headers (mCompFields, mCompFields->GetCharacterSet(),
-                                   m_deliver_mode, promptObject, &status);
-  if (NS_FAILED(status))
-    goto FAIL;
-
-  if (!headers)
-    goto FAILMEM;
-
-  //
-  // If we converted HTML into plaintext, the plaintext part (plainpart)
-  // already has its content-type and content-transfer-encoding
-  // ("other") headers set.
-  //
-  // In the specific case where such a plaintext part is the
-  // top level message part (iff an HTML message is being sent
-  // as text only and no other attachments exist) we want to
-  // preserve the original plainpart headers, since they
-  // contain accurate transfer encoding and Mac type/creator
-  // information.
-  //
-  // So, in the above case we append the main message headers,
-  // otherwise we overwrite whatever headers may have existed.
-  //
-  /* reordering of headers will happen in nsMsgSendPart::Write */
-  if ((plainpart) && (plainpart == toppart))
-    status = toppart->AppendOtherHeaders(headers);
-  else
-    status = toppart->SetOtherHeaders(headers);
-  PR_Free(headers);
-  headers = nullptr;
+  {
+    nsCOMPtr<msgIWritableStructuredHeaders> outputHeaders =
+      do_CreateInstance(NS_ISTRUCTUREDHEADERS_CONTRACTID);
+    status = mime_generate_headers(mCompFields, m_deliver_mode, outputHeaders);
+    if (NS_FAILED(status))
+      goto FAIL;
+
+    // Convert the blocks of headers into a single string for emission.
+    nsAutoCString headers;
+    outputHeaders->BuildMimeText(headers);
+
+    // If we converted HTML into plaintext, the plaintext part (plainpart)
+    // already has its content-type and content-transfer-encoding ("other")
+    // headers set.
+    //
+    // In the specific case where such a plaintext part is the top-level message
+    // part (iff an HTML message is being sent as text only and no other
+    // attachments exist) we want to preserve the original plainpart headers,
+    // since they contain accurate transfer encoding and Mac type/creator
+    // information.
+    //
+    // So, in the above case we append the main message headers, otherwise we
+    // overwrite whatever headers may have existed.
+    if (plainpart && plainpart == toppart)
+      status = toppart->AppendOtherHeaders(headers.get());
+    else
+      status = toppart->SetOtherHeaders(headers.get());
+  }
+
   if (NS_FAILED(status))
     goto FAIL;
 
   // Set up the first part (user-typed.)  For now, do it even if the first
   // part is empty; we need to add things to skip it if this part is empty.
 
   // Set up encoder for the first part (message body.)
   //
@@ -872,17 +848,16 @@ nsMsgComposeAndSend::GatherMimeAttachmen
   if (m_attachment_count > 0)
   {
     // Kludge to avoid having to allocate memory on the toy computers...
     if (! mime_mailto_stream_read_buffer)
       mime_mailto_stream_read_buffer = (char *) PR_Malloc (MIME_BUFFER_SIZE);
     buffer = mime_mailto_stream_read_buffer;
     if (! buffer)
       goto FAILMEM;
-    buffer_tail = buffer;
 
     // Gather all of the attachments for this message that are NOT
     // part of an enclosed MHTML message!
     for (i = 0; i < m_attachment_count; i++)
     {
       nsMsgAttachmentHandler *ma = m_attachments[i];
       if (!ma->mMHTMLPart)
         PreProcessPart(ma, toppart);
@@ -1001,17 +976,16 @@ FAILMEM:
 
 FAIL:
   if (toppart)
     delete toppart;
   toppart = nullptr;
   mainbody = nullptr;
   maincontainer = nullptr;
 
-  PR_FREEIF(headers);
   if (in_file)
   {
     PR_Close (in_file);
     in_file = nullptr;
   }
 
   if (shouldDeleteDeliveryState)
   {