Bug 1389789 - nsIPgpMimeProxy: Indroduce nsPgpMimeProxy::OutputDecryptedData. r=jorgk
authorPatrick Brunschwig <patrick@enigmail.net>
Wed, 16 Aug 2017 00:52:00 +0200
changeset 29570 37c4745fb9f1849a894f6b643025b9f2611e25cd
parent 29569 d240ea7abfd5454d30fdc64a5dbe9e50ca168e96
child 29571 9ed0ce8f4802dc45629dc19b12b1fbc34f4ecf81
push id378
push userclokep@gmail.com
push dateMon, 13 Nov 2017 18:45:35 +0000
reviewersjorgk
bugs1389789
Bug 1389789 - nsIPgpMimeProxy: Indroduce nsPgpMimeProxy::OutputDecryptedData. r=jorgk
mailnews/mime/cthandlers/pgpmime/nsPgpMimeProxy.cpp
mailnews/mime/public/nsIPgpMimeProxy.idl
--- a/mailnews/mime/cthandlers/pgpmime/nsPgpMimeProxy.cpp
+++ b/mailnews/mime/cthandlers/pgpmime/nsPgpMimeProxy.cpp
@@ -20,16 +20,37 @@
 
 #include "mimecth.h"
 #include "mimemoz2.h"
 #include "nspr.h"
 #include "plstr.h"
 #include "nsIPgpMimeProxy.h"
 #include "nsComponentManagerUtils.h"
 
+/**
+ * Overall description
+ * ===================
+ *
+ * There are three components involved here: MIME, a proxy object (nsPgpMimeProxy)
+ * and Enigmail (or any other add-on that registered a decryption object with
+ * "@mozilla.org/mime/pgp-mime-js-decrypt;1").
+ *
+ * MIME creates and initialises the proxy object in nsPgpMimeProxy::Init(). This
+ * creates a decryption object, for example EnigmailMimeDecrypt. When MIME wants to
+ * decode something, it calls the Write() method of the proxy, which in turn calls
+ * OnDataAvailable() on the decryptor. The decryptor optains the encrypted data
+ * form the proxy via the proxy's Read() method. The decryptor decrypts the data and
+ * passes the result back to the proxy, using the OutputDecryptedData() method
+ * or by passing a stream to the proxy's OnDataAvailable() method, in which
+ * the proxy will read from that stream.
+ * The proxy knows how to interface with MIME and passes the data on using
+ * some function pointers it got given via nsPgpMimeProxy::SetMimeCallback().
+ */
+
+
 #define MIME_SUPERCLASS mimeEncryptedClass
 MimeDefClass(MimeEncryptedPgp, MimeEncryptedPgpClass,
              mimeEncryptedPgpClass, &MIME_SUPERCLASS);
 
 #define kCharMax 1024
 
 extern "C" MimeObjectClass *
 MIME_PgpMimeCreateContentTypeHandlerClass(
@@ -148,16 +169,17 @@ MimePgpe_init(MimeObject *obj,
   MimePgpeData* data = new MimePgpeData();
   NS_ENSURE_TRUE(data, nullptr);
 
   data->self = obj;
   data->output_fn = output_fn;
   data->output_closure = output_closure;
   data->mimeDecrypt = nullptr;
 
+  // Create proxy object.
   nsresult rv;
   data->mimeDecrypt = do_CreateInstance(NS_PGPMIMEPROXY_CONTRACTID, &rv);
   if (NS_FAILED(rv))
     return data;
 
   char *ct = MimeHeaders_get(obj->headers, HEADER_CONTENT_TYPE, false, false);
 
   rv = (ct ? data->mimeDecrypt->SetContentType(nsDependentCString(ct))
@@ -176,16 +198,17 @@ MimePgpe_init(MimeObject *obj,
 
   mime_stream_data *msd = (mime_stream_data *) (data->self->options->stream_closure);
   nsIChannel *channel = msd->channel;
 
   nsCOMPtr<nsIURI> uri;
   if (channel)
     channel->GetURI(getter_AddRefs(uri));
 
+  // Initialise proxy object with MIME's output function, object and URI.
   if (NS_FAILED(data->mimeDecrypt->SetMimeCallback(output_fn, output_closure, uri)))
     return nullptr;
 
   return data;
 }
 
 static int
 MimePgpe_write(const char *buf, int32_t buf_size, void *output_closure)
@@ -315,51 +338,54 @@ nsPgpMimeProxy::SetMimeCallback(MimeDeco
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPgpMimeProxy::Init()
 {
   mByteBuf.Truncate();
 
+  // Create add-on supplied decrytion object.
   nsresult rv;
-  nsCOMPtr<nsIPrefBranch> pbi(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
-  if (NS_FAILED(rv))
-    return rv;
-
   mDecryptor = do_CreateInstance(PGPMIME_JS_DECRYPTOR_CONTRACTID, &rv);
   if (NS_FAILED(rv))
     mDecryptor = nullptr;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPgpMimeProxy::Write(const char *buf, uint32_t buf_size)
 {
   NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
 
   mByteBuf.Assign(buf, buf_size);
   mStreamOffset = 0;
 
+  // Pass data to the decrytion object for decryption.
+  // The result is returned via OutputDecryptedData().
   if (mDecryptor)
     return mDecryptor->OnDataAvailable((nsIRequest*) this, nullptr, (nsIInputStream*) this,
                                       0, buf_size);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPgpMimeProxy::Finish() {
   NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
 
   if (mDecryptor) {
     return mDecryptor->OnStopRequest((nsIRequest*) this, nullptr, NS_OK);
   }
   else {
+
+    if (!mOutputFun)
+      return NS_ERROR_FAILURE;
+
     nsCString temp;
     temp.Append("Content-Type: text/html\r\nCharset: UTF-8\r\n\r\n<html><body>");
     temp.Append("<BR><text=\"#000000\" bgcolor=\"#FFFFFF\" link=\"#FF0000\" vlink=\"#800080\" alink=\"#0000FF\">");
     temp.Append("<center><table BORDER=1 ><tr><td><CENTER>");
 
     nsCString tString;
     PgpMimeGetNeedsAddonString(tString);
     temp.Append(tString);
@@ -419,16 +445,41 @@ nsPgpMimeProxy::GetMimePart(nsACString &
 
 NS_IMETHODIMP
 nsPgpMimeProxy::SetMimePart(const nsACString &aMimePart)
 {
   mMimePart = aMimePart;
   return NS_OK;
 }
 
+/**
+ * This method is called by the add-on-supplied decryption object.
+ * It passes the decrypted data back to the proxy which calls the
+ * output function is was initialised with.
+ */
+NS_IMETHODIMP
+nsPgpMimeProxy::OutputDecryptedData(const char *buf, uint32_t buf_size)
+{
+  NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+
+  NS_ENSURE_ARG(buf);
+
+  if (!mOutputFun)
+    return NS_ERROR_FAILURE;
+
+  int status = mOutputFun(buf, buf_size, mOutputClosure);
+  if (status < 0) {
+    PR_SetError(status, 0);
+    mOutputFun = nullptr;
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // nsIRequest methods
 ///////////////////////////////////////////////////////////////////////////////
 
 NS_IMETHODIMP
 nsPgpMimeProxy::GetName(nsACString &result)
 {
   result = "pgpmimeproxy";
@@ -523,18 +574,17 @@ nsPgpMimeProxy::Available(uint64_t* _ret
 
   *_retval = (mByteBuf.Length() > mStreamOffset) ?
               mByteBuf.Length() - mStreamOffset : 0;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsPgpMimeProxy::Read(char* buf, uint32_t count,
-                         uint32_t *readCount)
+nsPgpMimeProxy::Read(char* buf, uint32_t count, uint32_t *readCount)
 {
   NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
 
   if (!buf || !readCount)
     return NS_ERROR_NULL_POINTER;
 
   int32_t avail = (mByteBuf.Length() > mStreamOffset) ?
                    mByteBuf.Length() - mStreamOffset : 0;
@@ -548,18 +598,18 @@ nsPgpMimeProxy::Read(char* buf, uint32_t
 
   mStreamOffset += *readCount;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPgpMimeProxy::ReadSegments(nsWriteSegmentFun writer,
-                          void * aClosure, uint32_t count,
-                          uint32_t *readCount)
+                             void * aClosure, uint32_t count,
+                             uint32_t *readCount)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 nsPgpMimeProxy::IsNonBlocking(bool *aNonBlocking)
 {
   NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
@@ -602,18 +652,20 @@ nsPgpMimeProxy::OnStopRequest(nsIRequest
 
 NS_IMETHODIMP
 nsPgpMimeProxy::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
                               nsIInputStream *aInputStream,
                               uint64_t aSourceOffset,
                               uint32_t aLength)
 {
   NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+  NS_ENSURE_ARG(aInputStream);
 
-  NS_ENSURE_ARG(aInputStream);
+  if (!mOutputFun)
+    return NS_ERROR_FAILURE;
 
   char buf[kCharMax];
   uint32_t readCount, readMax;
 
   while (aLength > 0) {
     readMax = (aLength < kCharMax) ? aLength : kCharMax;
 
     nsresult rv;
--- a/mailnews/mime/public/nsIPgpMimeProxy.idl
+++ b/mailnews/mime/public/nsIPgpMimeProxy.idl
@@ -7,28 +7,28 @@
 
 %{C++
 typedef int (*MimeDecodeCallbackFun)(const char *buf, int32_t buf_size, void *output_closure);
 
 #define NS_PGPMIMEPROXY_CLASSNAME "PGP/Mime Decryption"
 #define NS_PGPMIMEPROXY_CONTRACTID "@mozilla.org/mime/pgp-mime-decrypt;1"
 
 #define NS_PGPMIMEPROXY_CID                     \
-{ /* 6b7e094f-536b-40dc-b3a4-e3d729205ce1 */      \
-   0x6b7e094f, 0x536b, 0x40dc,                    \
-{0xb3, 0xa4, 0xe3, 0xd7, 0x29, 0x20, 0x5c, 0xe1 } }
+{ /* 815c4fbe-0e7c-45b6-8324-f7044c7252ac */    \
+   0x815c4fbe, 0x0e7c, 0x45b6,                  \
+{0x83, 0x24, 0xf0, 0x04, 0x4C, 0x72, 0x52, 0xac } }
 %}
 
 native MimeDecodeCallbackFun(MimeDecodeCallbackFun);
 
 /**
  * nsIPgpMimeProxy is a proxy for a (JS-)addon for OpenPGP/MIME decryption
  */
 
-[scriptable, uuid(6b7e094f-536b-40dc-b3a4-e3d729205ce1)]
+[scriptable, uuid(815c4fbe-0e7c-45b6-8324-f7044c7252ac)]
 interface nsIPgpMimeProxy : nsIStreamListener
 {
   /**
    * set the decoder callback into mimelib
    */
   [noscript] void setMimeCallback(in MimeDecodeCallbackFun outputFun,
                                   in voidPtr outputClosure,
                                   in nsIURI myUri);
@@ -58,12 +58,17 @@ interface nsIPgpMimeProxy : nsIStreamLis
 
   /**
    * The particular part number of the multipart object we are working on. The
    * numbering is the same as in URLs that use the form "...?part=1.1.2".
    *
    * The value stored in mimePart is only the number, e.g. "1" or "1.1.2"
    */
   attribute ACString mimePart;
+
+  /**
+   * Pass the decrypted data back from the decryptor and onto to libMime.
+   */
+  void outputDecryptedData(in string buf, in unsigned long count);
 };
 
 
 ///////////////////////////////////////////////////////////////////////////////