1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/file/ArchiveReader.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,217 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.8 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "ArchiveReader.h" 1.11 +#include "ArchiveRequest.h" 1.12 +#include "ArchiveEvent.h" 1.13 +#include "ArchiveZipEvent.h" 1.14 + 1.15 +#include "nsIURI.h" 1.16 +#include "nsNetUtil.h" 1.17 + 1.18 +#include "mozilla/dom/ArchiveReaderBinding.h" 1.19 +#include "mozilla/dom/BindingDeclarations.h" 1.20 +#include "mozilla/Preferences.h" 1.21 +#include "mozilla/dom/EncodingUtils.h" 1.22 + 1.23 +using namespace mozilla; 1.24 +using namespace mozilla::dom; 1.25 +USING_FILE_NAMESPACE 1.26 + 1.27 +/* static */ already_AddRefed<ArchiveReader> 1.28 +ArchiveReader::Constructor(const GlobalObject& aGlobal, 1.29 + nsIDOMBlob* aBlob, 1.30 + const ArchiveReaderOptions& aOptions, 1.31 + ErrorResult& aError) 1.32 +{ 1.33 + MOZ_ASSERT(aBlob); 1.34 + 1.35 + nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports()); 1.36 + if (!window) { 1.37 + aError.Throw(NS_ERROR_UNEXPECTED); 1.38 + return nullptr; 1.39 + } 1.40 + 1.41 + nsAutoCString encoding; 1.42 + if (!EncodingUtils::FindEncodingForLabel(aOptions.mEncoding, encoding) || 1.43 + encoding.EqualsLiteral("replacement")) { 1.44 + aError.ThrowTypeError(MSG_ENCODING_NOT_SUPPORTED, &aOptions.mEncoding); 1.45 + return nullptr; 1.46 + } 1.47 + 1.48 + nsRefPtr<ArchiveReader> reader = 1.49 + new ArchiveReader(aBlob, window, encoding); 1.50 + return reader.forget(); 1.51 +} 1.52 + 1.53 +ArchiveReader::ArchiveReader(nsIDOMBlob* aBlob, nsPIDOMWindow* aWindow, 1.54 + const nsACString& aEncoding) 1.55 + : mBlob(aBlob) 1.56 + , mWindow(aWindow) 1.57 + , mStatus(NOT_STARTED) 1.58 + , mEncoding(aEncoding) 1.59 +{ 1.60 + MOZ_ASSERT(aBlob); 1.61 + MOZ_ASSERT(aWindow); 1.62 + 1.63 + SetIsDOMBinding(); 1.64 +} 1.65 + 1.66 +ArchiveReader::~ArchiveReader() 1.67 +{ 1.68 +} 1.69 + 1.70 +/* virtual */ JSObject* 1.71 +ArchiveReader::WrapObject(JSContext* aCx) 1.72 +{ 1.73 + return ArchiveReaderBinding::Wrap(aCx, this); 1.74 +} 1.75 + 1.76 +nsresult 1.77 +ArchiveReader::RegisterRequest(ArchiveRequest* aRequest) 1.78 +{ 1.79 + switch (mStatus) { 1.80 + // Append to the list and let's start to work: 1.81 + case NOT_STARTED: 1.82 + mRequests.AppendElement(aRequest); 1.83 + return OpenArchive(); 1.84 + 1.85 + // Just append to the list: 1.86 + case WORKING: 1.87 + mRequests.AppendElement(aRequest); 1.88 + return NS_OK; 1.89 + 1.90 + // Return data! 1.91 + case READY: 1.92 + RequestReady(aRequest); 1.93 + return NS_OK; 1.94 + } 1.95 + 1.96 + NS_ASSERTION(false, "unexpected mStatus value"); 1.97 + return NS_OK; 1.98 +} 1.99 + 1.100 +// This returns the input stream 1.101 +nsresult 1.102 +ArchiveReader::GetInputStream(nsIInputStream** aInputStream) 1.103 +{ 1.104 + // Getting the input stream 1.105 + mBlob->GetInternalStream(aInputStream); 1.106 + NS_ENSURE_TRUE(*aInputStream, NS_ERROR_UNEXPECTED); 1.107 + return NS_OK; 1.108 +} 1.109 + 1.110 +nsresult 1.111 +ArchiveReader::GetSize(uint64_t* aSize) 1.112 +{ 1.113 + nsresult rv = mBlob->GetSize(aSize); 1.114 + NS_ENSURE_SUCCESS(rv, rv); 1.115 + return NS_OK; 1.116 +} 1.117 + 1.118 +// Here we open the archive: 1.119 +nsresult 1.120 +ArchiveReader::OpenArchive() 1.121 +{ 1.122 + mStatus = WORKING; 1.123 + nsresult rv; 1.124 + 1.125 + // Target: 1.126 + nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID); 1.127 + NS_ASSERTION(target, "Must have stream transport service"); 1.128 + 1.129 + // Here a Event to make everything async: 1.130 + nsRefPtr<ArchiveReaderEvent> event; 1.131 + 1.132 + /* FIXME: If we want to support more than 1 format we should check the content type here: */ 1.133 + event = new ArchiveReaderZipEvent(this, mEncoding); 1.134 + rv = target->Dispatch(event, NS_DISPATCH_NORMAL); 1.135 + NS_ENSURE_SUCCESS(rv, rv); 1.136 + 1.137 + // In order to be sure that this object exists when the event finishes its task, 1.138 + // we increase the refcount here: 1.139 + AddRef(); 1.140 + 1.141 + return NS_OK; 1.142 +} 1.143 + 1.144 +// Data received from the dispatched event: 1.145 +void 1.146 +ArchiveReader::Ready(nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList, 1.147 + nsresult aStatus) 1.148 +{ 1.149 + mStatus = READY; 1.150 + 1.151 + // Let's store the values: 1.152 + mData.fileList = aFileList; 1.153 + mData.status = aStatus; 1.154 + 1.155 + // Propagate the results: 1.156 + for (uint32_t index = 0; index < mRequests.Length(); ++index) { 1.157 + nsRefPtr<ArchiveRequest> request = mRequests[index]; 1.158 + RequestReady(request); 1.159 + } 1.160 + 1.161 + mRequests.Clear(); 1.162 + 1.163 + // The async operation is concluded, we can decrease the reference: 1.164 + Release(); 1.165 +} 1.166 + 1.167 +void 1.168 +ArchiveReader::RequestReady(ArchiveRequest* aRequest) 1.169 +{ 1.170 + // The request will do the rest: 1.171 + aRequest->ReaderReady(mData.fileList, mData.status); 1.172 +} 1.173 + 1.174 +already_AddRefed<ArchiveRequest> 1.175 +ArchiveReader::GetFilenames() 1.176 +{ 1.177 + nsRefPtr<ArchiveRequest> request = GenerateArchiveRequest(); 1.178 + request->OpGetFilenames(); 1.179 + 1.180 + return request.forget(); 1.181 +} 1.182 + 1.183 +already_AddRefed<ArchiveRequest> 1.184 +ArchiveReader::GetFile(const nsAString& filename) 1.185 +{ 1.186 + nsRefPtr<ArchiveRequest> request = GenerateArchiveRequest(); 1.187 + request->OpGetFile(filename); 1.188 + 1.189 + return request.forget(); 1.190 +} 1.191 + 1.192 +already_AddRefed<ArchiveRequest> 1.193 +ArchiveReader::GetFiles() 1.194 +{ 1.195 + nsRefPtr<ArchiveRequest> request = GenerateArchiveRequest(); 1.196 + request->OpGetFiles(); 1.197 + 1.198 + return request.forget(); 1.199 +} 1.200 + 1.201 +already_AddRefed<ArchiveRequest> 1.202 +ArchiveReader::GenerateArchiveRequest() 1.203 +{ 1.204 + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); 1.205 + return ArchiveRequest::Create(mWindow, this); 1.206 +} 1.207 + 1.208 +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_4(ArchiveReader, 1.209 + mBlob, 1.210 + mWindow, 1.211 + mData.fileList, 1.212 + mRequests) 1.213 + 1.214 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ArchiveReader) 1.215 + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY 1.216 + NS_INTERFACE_MAP_ENTRY(nsISupports) 1.217 +NS_INTERFACE_MAP_END 1.218 + 1.219 +NS_IMPL_CYCLE_COLLECTING_ADDREF(ArchiveReader) 1.220 +NS_IMPL_CYCLE_COLLECTING_RELEASE(ArchiveReader)