dom/file/ArchiveReader.cpp

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=2 et sw=2 tw=80: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "ArchiveReader.h"
     8 #include "ArchiveRequest.h"
     9 #include "ArchiveEvent.h"
    10 #include "ArchiveZipEvent.h"
    12 #include "nsIURI.h"
    13 #include "nsNetUtil.h"
    15 #include "mozilla/dom/ArchiveReaderBinding.h"
    16 #include "mozilla/dom/BindingDeclarations.h"
    17 #include "mozilla/Preferences.h"
    18 #include "mozilla/dom/EncodingUtils.h"
    20 using namespace mozilla;
    21 using namespace mozilla::dom;
    22 USING_FILE_NAMESPACE
    24 /* static */ already_AddRefed<ArchiveReader>
    25 ArchiveReader::Constructor(const GlobalObject& aGlobal,
    26                            nsIDOMBlob* aBlob,
    27                            const ArchiveReaderOptions& aOptions,
    28                            ErrorResult& aError)
    29 {
    30   MOZ_ASSERT(aBlob);
    32   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
    33   if (!window) {
    34     aError.Throw(NS_ERROR_UNEXPECTED);
    35     return nullptr;
    36   }
    38   nsAutoCString encoding;
    39   if (!EncodingUtils::FindEncodingForLabel(aOptions.mEncoding, encoding) ||
    40       encoding.EqualsLiteral("replacement")) {
    41     aError.ThrowTypeError(MSG_ENCODING_NOT_SUPPORTED, &aOptions.mEncoding);
    42     return nullptr;
    43   }
    45   nsRefPtr<ArchiveReader> reader =
    46     new ArchiveReader(aBlob, window, encoding);
    47   return reader.forget();
    48 }
    50 ArchiveReader::ArchiveReader(nsIDOMBlob* aBlob, nsPIDOMWindow* aWindow,
    51                              const nsACString& aEncoding)
    52   : mBlob(aBlob)
    53   , mWindow(aWindow)
    54   , mStatus(NOT_STARTED)
    55   , mEncoding(aEncoding)
    56 {
    57   MOZ_ASSERT(aBlob);
    58   MOZ_ASSERT(aWindow);
    60   SetIsDOMBinding();
    61 }
    63 ArchiveReader::~ArchiveReader()
    64 {
    65 }
    67 /* virtual */ JSObject*
    68 ArchiveReader::WrapObject(JSContext* aCx)
    69 {
    70   return ArchiveReaderBinding::Wrap(aCx, this);
    71 }
    73 nsresult
    74 ArchiveReader::RegisterRequest(ArchiveRequest* aRequest)
    75 {
    76   switch (mStatus) {
    77     // Append to the list and let's start to work:
    78     case NOT_STARTED:
    79       mRequests.AppendElement(aRequest);
    80       return OpenArchive();
    82     // Just append to the list:
    83     case WORKING:
    84       mRequests.AppendElement(aRequest);
    85       return NS_OK;
    87     // Return data!
    88     case READY:
    89       RequestReady(aRequest);
    90       return NS_OK;
    91   }
    93   NS_ASSERTION(false, "unexpected mStatus value");
    94   return NS_OK;
    95 }
    97 // This returns the input stream
    98 nsresult
    99 ArchiveReader::GetInputStream(nsIInputStream** aInputStream)
   100 {
   101   // Getting the input stream
   102   mBlob->GetInternalStream(aInputStream);
   103   NS_ENSURE_TRUE(*aInputStream, NS_ERROR_UNEXPECTED);
   104   return NS_OK;
   105 }
   107 nsresult
   108 ArchiveReader::GetSize(uint64_t* aSize)
   109 {
   110   nsresult rv = mBlob->GetSize(aSize);
   111   NS_ENSURE_SUCCESS(rv, rv);
   112   return NS_OK;
   113 }
   115 // Here we open the archive:
   116 nsresult
   117 ArchiveReader::OpenArchive()
   118 {
   119   mStatus = WORKING;
   120   nsresult rv;
   122   // Target:
   123   nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
   124   NS_ASSERTION(target, "Must have stream transport service");
   126   // Here a Event to make everything async:
   127   nsRefPtr<ArchiveReaderEvent> event;
   129   /* FIXME: If we want to support more than 1 format we should check the content type here: */
   130   event = new ArchiveReaderZipEvent(this, mEncoding);
   131   rv = target->Dispatch(event, NS_DISPATCH_NORMAL);
   132   NS_ENSURE_SUCCESS(rv, rv);
   134   // In order to be sure that this object exists when the event finishes its task,
   135   // we increase the refcount here:
   136   AddRef();
   138   return NS_OK;
   139 }
   141 // Data received from the dispatched event:
   142 void
   143 ArchiveReader::Ready(nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList,
   144                      nsresult aStatus)
   145 {
   146   mStatus = READY;
   148   // Let's store the values:
   149   mData.fileList = aFileList;
   150   mData.status = aStatus;
   152   // Propagate the results:
   153   for (uint32_t index = 0; index < mRequests.Length(); ++index) {
   154     nsRefPtr<ArchiveRequest> request = mRequests[index];
   155     RequestReady(request);
   156   }
   158   mRequests.Clear();
   160   // The async operation is concluded, we can decrease the reference:
   161   Release();
   162 }
   164 void
   165 ArchiveReader::RequestReady(ArchiveRequest* aRequest)
   166 {
   167   // The request will do the rest:
   168   aRequest->ReaderReady(mData.fileList, mData.status);
   169 }
   171 already_AddRefed<ArchiveRequest>
   172 ArchiveReader::GetFilenames()
   173 {
   174   nsRefPtr<ArchiveRequest> request = GenerateArchiveRequest();
   175   request->OpGetFilenames();
   177   return request.forget();
   178 }
   180 already_AddRefed<ArchiveRequest>
   181 ArchiveReader::GetFile(const nsAString& filename)
   182 {
   183   nsRefPtr<ArchiveRequest> request = GenerateArchiveRequest();
   184   request->OpGetFile(filename);
   186   return request.forget();
   187 }
   189 already_AddRefed<ArchiveRequest>
   190 ArchiveReader::GetFiles()
   191 {
   192   nsRefPtr<ArchiveRequest> request = GenerateArchiveRequest();
   193   request->OpGetFiles();
   195   return request.forget();
   196 }
   198 already_AddRefed<ArchiveRequest>
   199 ArchiveReader::GenerateArchiveRequest()
   200 {
   201   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   202   return ArchiveRequest::Create(mWindow, this);
   203 }
   205 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_4(ArchiveReader,
   206                                         mBlob,
   207                                         mWindow,
   208                                         mData.fileList,
   209                                         mRequests)
   211 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ArchiveReader)
   212   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   213   NS_INTERFACE_MAP_ENTRY(nsISupports)
   214 NS_INTERFACE_MAP_END
   216 NS_IMPL_CYCLE_COLLECTING_ADDREF(ArchiveReader)
   217 NS_IMPL_CYCLE_COLLECTING_RELEASE(ArchiveReader)

mercurial