dom/file/FileHelper.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.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set ts=2 et sw=2 tw=80: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "FileHelper.h"
michael@0 8
michael@0 9 #include "nsIFileStorage.h"
michael@0 10
michael@0 11 #include "nsError.h"
michael@0 12 #include "nsProxyRelease.h"
michael@0 13
michael@0 14 #include "FileHandle.h"
michael@0 15 #include "FileRequest.h"
michael@0 16 #include "FileService.h"
michael@0 17 #include "nsIRequest.h"
michael@0 18 #include "nsThreadUtils.h"
michael@0 19
michael@0 20 USING_FILE_NAMESPACE
michael@0 21
michael@0 22 namespace {
michael@0 23
michael@0 24 LockedFile* gCurrentLockedFile = nullptr;
michael@0 25
michael@0 26 } // anonymous namespace
michael@0 27
michael@0 28 FileHelper::FileHelper(LockedFile* aLockedFile,
michael@0 29 FileRequest* aFileRequest)
michael@0 30 : mFileStorage(aLockedFile->mFileHandle->mFileStorage),
michael@0 31 mLockedFile(aLockedFile),
michael@0 32 mFileRequest(aFileRequest),
michael@0 33 mResultCode(NS_OK),
michael@0 34 mFinished(false)
michael@0 35 {
michael@0 36 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 37 }
michael@0 38
michael@0 39 FileHelper::~FileHelper()
michael@0 40 {
michael@0 41 NS_ASSERTION(!mFileStorage && !mLockedFile && !mFileRequest && !mListener &&
michael@0 42 !mRequest, "Should have cleared this!");
michael@0 43 }
michael@0 44
michael@0 45 NS_IMPL_ISUPPORTS(FileHelper, nsIRequestObserver)
michael@0 46
michael@0 47 nsresult
michael@0 48 FileHelper::Enqueue()
michael@0 49 {
michael@0 50 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 51
michael@0 52 FileService* service = FileService::GetOrCreate();
michael@0 53 NS_ENSURE_TRUE(service, NS_ERROR_FAILURE);
michael@0 54
michael@0 55 nsresult rv = service->Enqueue(mLockedFile, this);
michael@0 56 NS_ENSURE_SUCCESS(rv, rv);
michael@0 57
michael@0 58 if (mLockedFile) {
michael@0 59 mLockedFile->OnNewRequest();
michael@0 60 }
michael@0 61
michael@0 62 return NS_OK;
michael@0 63 }
michael@0 64
michael@0 65 nsresult
michael@0 66 FileHelper::AsyncRun(FileHelperListener* aListener)
michael@0 67 {
michael@0 68 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 69
michael@0 70 // Assign the listener early, so we can use it synchronously if the code
michael@0 71 // below fails.
michael@0 72 mListener = aListener;
michael@0 73
michael@0 74 nsresult rv;
michael@0 75
michael@0 76 nsCOMPtr<nsISupports> stream;
michael@0 77 if (mLockedFile->mRequestMode == LockedFile::PARALLEL) {
michael@0 78 rv = mLockedFile->CreateParallelStream(getter_AddRefs(stream));
michael@0 79 }
michael@0 80 else {
michael@0 81 rv = mLockedFile->GetOrCreateStream(getter_AddRefs(stream));
michael@0 82 }
michael@0 83
michael@0 84 if (NS_SUCCEEDED(rv)) {
michael@0 85 NS_ASSERTION(stream, "This should never be null!");
michael@0 86
michael@0 87 rv = DoAsyncRun(stream);
michael@0 88 }
michael@0 89
michael@0 90 if (NS_FAILED(rv)) {
michael@0 91 mResultCode = NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
michael@0 92 Finish();
michael@0 93 }
michael@0 94
michael@0 95 return NS_OK;
michael@0 96 }
michael@0 97
michael@0 98 NS_IMETHODIMP
michael@0 99 FileHelper::OnStartRequest(nsIRequest* aRequest, nsISupports* aCtxt)
michael@0 100 {
michael@0 101 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 102
michael@0 103 return NS_OK;
michael@0 104 }
michael@0 105
michael@0 106 NS_IMETHODIMP
michael@0 107 FileHelper::OnStopRequest(nsIRequest* aRequest, nsISupports* aCtxt,
michael@0 108 nsresult aStatus)
michael@0 109 {
michael@0 110 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 111
michael@0 112 if (NS_FAILED(aStatus)) {
michael@0 113 if (aStatus == NS_ERROR_FILE_NO_DEVICE_SPACE) {
michael@0 114 mResultCode = NS_ERROR_DOM_FILEHANDLE_QUOTA_ERR;
michael@0 115 }
michael@0 116 else {
michael@0 117 mResultCode = NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
michael@0 118 }
michael@0 119 }
michael@0 120
michael@0 121 Finish();
michael@0 122
michael@0 123 return NS_OK;
michael@0 124 }
michael@0 125
michael@0 126 void
michael@0 127 FileHelper::OnStreamProgress(uint64_t aProgress, uint64_t aProgressMax)
michael@0 128 {
michael@0 129 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 130
michael@0 131 if (mLockedFile->IsAborted()) {
michael@0 132 NS_ASSERTION(mRequest, "Should have a request!\n");
michael@0 133
michael@0 134 nsresult rv = mRequest->Cancel(NS_BINDING_ABORTED);
michael@0 135 if (NS_FAILED(rv)) {
michael@0 136 NS_WARNING("Failed to cancel the request!");
michael@0 137 }
michael@0 138
michael@0 139 return;
michael@0 140 }
michael@0 141
michael@0 142 if (mFileRequest) {
michael@0 143 mFileRequest->OnProgress(aProgress, aProgressMax);
michael@0 144 }
michael@0 145 }
michael@0 146
michael@0 147 // static
michael@0 148 LockedFile*
michael@0 149 FileHelper::GetCurrentLockedFile()
michael@0 150 {
michael@0 151 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 152
michael@0 153 return gCurrentLockedFile;
michael@0 154 }
michael@0 155
michael@0 156 nsresult
michael@0 157 FileHelper::GetSuccessResult(JSContext* aCx,
michael@0 158 JS::MutableHandle<JS::Value> aVal)
michael@0 159 {
michael@0 160 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 161
michael@0 162 aVal.setUndefined();
michael@0 163 return NS_OK;
michael@0 164 }
michael@0 165
michael@0 166 void
michael@0 167 FileHelper::ReleaseObjects()
michael@0 168 {
michael@0 169 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 170
michael@0 171 mFileStorage = nullptr;
michael@0 172 mLockedFile = nullptr;
michael@0 173 mFileRequest = nullptr;
michael@0 174 mListener = nullptr;
michael@0 175 mRequest = nullptr;
michael@0 176 }
michael@0 177
michael@0 178 void
michael@0 179 FileHelper::Finish()
michael@0 180 {
michael@0 181 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 182
michael@0 183 if (mFinished) {
michael@0 184 return;
michael@0 185 }
michael@0 186
michael@0 187 mFinished = true;
michael@0 188
michael@0 189 if (mLockedFile->IsAborted()) {
michael@0 190 // Always fire a "error" event with ABORT_ERR if the transaction was
michael@0 191 // aborted, even if the request succeeded or failed with another error.
michael@0 192 mResultCode = NS_ERROR_DOM_FILEHANDLE_ABORT_ERR;
michael@0 193 }
michael@0 194
michael@0 195 LockedFile* oldLockedFile = gCurrentLockedFile;
michael@0 196 gCurrentLockedFile = mLockedFile;
michael@0 197
michael@0 198 if (mFileRequest) {
michael@0 199 nsresult rv = mFileRequest->NotifyHelperCompleted(this);
michael@0 200 if (NS_SUCCEEDED(mResultCode) && NS_FAILED(rv)) {
michael@0 201 mResultCode = rv;
michael@0 202 }
michael@0 203 }
michael@0 204
michael@0 205 NS_ASSERTION(gCurrentLockedFile == mLockedFile, "Should be unchanged!");
michael@0 206 gCurrentLockedFile = oldLockedFile;
michael@0 207
michael@0 208 mLockedFile->OnRequestFinished();
michael@0 209
michael@0 210 mListener->OnFileHelperComplete(this);
michael@0 211
michael@0 212 ReleaseObjects();
michael@0 213
michael@0 214 NS_ASSERTION(!(mFileStorage || mLockedFile || mFileRequest || mListener ||
michael@0 215 mRequest), "Subclass didn't call FileHelper::ReleaseObjects!");
michael@0 216
michael@0 217 }
michael@0 218
michael@0 219 void
michael@0 220 FileHelper::OnStreamClose()
michael@0 221 {
michael@0 222 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 223 Finish();
michael@0 224 }
michael@0 225
michael@0 226 void
michael@0 227 FileHelper::OnStreamDestroy()
michael@0 228 {
michael@0 229 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 230 Finish();
michael@0 231 }

mercurial