dom/indexedDB/AsyncConnectionHelper.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "base/basictypes.h"
michael@0 8
michael@0 9 #include "AsyncConnectionHelper.h"
michael@0 10
michael@0 11 #include "mozilla/dom/quota/QuotaManager.h"
michael@0 12 #include "mozilla/storage.h"
michael@0 13 #include "nsComponentManagerUtils.h"
michael@0 14 #include "nsContentUtils.h"
michael@0 15 #include "nsProxyRelease.h"
michael@0 16 #include "nsThreadUtils.h"
michael@0 17 #include "nsWrapperCacheInlines.h"
michael@0 18
michael@0 19 #include "IDBEvents.h"
michael@0 20 #include "IDBTransaction.h"
michael@0 21 #include "IndexedDatabaseManager.h"
michael@0 22 #include "ProfilerHelpers.h"
michael@0 23 #include "ReportInternalError.h"
michael@0 24 #include "TransactionThreadPool.h"
michael@0 25
michael@0 26 #include "ipc/IndexedDBChild.h"
michael@0 27 #include "ipc/IndexedDBParent.h"
michael@0 28
michael@0 29 using namespace mozilla;
michael@0 30 USING_INDEXEDDB_NAMESPACE
michael@0 31 using mozilla::dom::quota::QuotaManager;
michael@0 32
michael@0 33 namespace {
michael@0 34
michael@0 35 IDBTransaction* gCurrentTransaction = nullptr;
michael@0 36
michael@0 37 const uint32_t kProgressHandlerGranularity = 1000;
michael@0 38
michael@0 39 class MOZ_STACK_CLASS TransactionPoolEventTarget : public StackBasedEventTarget
michael@0 40 {
michael@0 41 public:
michael@0 42 NS_DECL_NSIEVENTTARGET
michael@0 43
michael@0 44 TransactionPoolEventTarget(IDBTransaction* aTransaction)
michael@0 45 : mTransaction(aTransaction)
michael@0 46 { }
michael@0 47
michael@0 48 private:
michael@0 49 IDBTransaction* mTransaction;
michael@0 50 };
michael@0 51
michael@0 52 // This inline is just so that we always clear aBuffers appropriately even if
michael@0 53 // something fails.
michael@0 54 inline
michael@0 55 nsresult
michael@0 56 ConvertCloneReadInfosToArrayInternal(
michael@0 57 JSContext* aCx,
michael@0 58 nsTArray<StructuredCloneReadInfo>& aReadInfos,
michael@0 59 JS::MutableHandle<JS::Value> aResult)
michael@0 60 {
michael@0 61 JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
michael@0 62 if (!array) {
michael@0 63 IDB_WARNING("Failed to make array!");
michael@0 64 return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
michael@0 65 }
michael@0 66
michael@0 67 if (!aReadInfos.IsEmpty()) {
michael@0 68 if (!JS_SetArrayLength(aCx, array, uint32_t(aReadInfos.Length()))) {
michael@0 69 IDB_WARNING("Failed to set array length!");
michael@0 70 return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
michael@0 71 }
michael@0 72
michael@0 73 for (uint32_t index = 0, count = aReadInfos.Length(); index < count;
michael@0 74 index++) {
michael@0 75 StructuredCloneReadInfo& readInfo = aReadInfos[index];
michael@0 76
michael@0 77 JS::Rooted<JS::Value> val(aCx);
michael@0 78 if (!IDBObjectStore::DeserializeValue(aCx, readInfo, &val)) {
michael@0 79 NS_WARNING("Failed to decode!");
michael@0 80 return NS_ERROR_DOM_DATA_CLONE_ERR;
michael@0 81 }
michael@0 82
michael@0 83 if (!JS_SetElement(aCx, array, index, val)) {
michael@0 84 IDB_WARNING("Failed to set array element!");
michael@0 85 return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
michael@0 86 }
michael@0 87 }
michael@0 88 }
michael@0 89
michael@0 90 aResult.setObject(*array);
michael@0 91 return NS_OK;
michael@0 92 }
michael@0 93
michael@0 94 } // anonymous namespace
michael@0 95
michael@0 96 HelperBase::~HelperBase()
michael@0 97 {
michael@0 98 if (!NS_IsMainThread()) {
michael@0 99 IDBRequest* request;
michael@0 100 mRequest.forget(&request);
michael@0 101
michael@0 102 if (request) {
michael@0 103 nsCOMPtr<nsIThread> mainThread;
michael@0 104 NS_GetMainThread(getter_AddRefs(mainThread));
michael@0 105 NS_WARN_IF_FALSE(mainThread, "Couldn't get the main thread!");
michael@0 106
michael@0 107 if (mainThread) {
michael@0 108 NS_ProxyRelease(mainThread, static_cast<EventTarget*>(request));
michael@0 109 }
michael@0 110 }
michael@0 111 }
michael@0 112 }
michael@0 113
michael@0 114 nsresult
michael@0 115 HelperBase::WrapNative(JSContext* aCx,
michael@0 116 nsISupports* aNative,
michael@0 117 JS::MutableHandle<JS::Value> aResult)
michael@0 118 {
michael@0 119 NS_ASSERTION(aCx, "Null context!");
michael@0 120 NS_ASSERTION(aNative, "Null pointer!");
michael@0 121 NS_ASSERTION(aResult.address(), "Null pointer!");
michael@0 122 NS_ASSERTION(mRequest, "Null request!");
michael@0 123
michael@0 124 nsresult rv = nsContentUtils::WrapNative(aCx, aNative, aResult);
michael@0 125 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 126
michael@0 127 return NS_OK;
michael@0 128 }
michael@0 129
michael@0 130 void
michael@0 131 HelperBase::ReleaseMainThreadObjects()
michael@0 132 {
michael@0 133 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 134
michael@0 135 mRequest = nullptr;
michael@0 136 }
michael@0 137
michael@0 138 AsyncConnectionHelper::AsyncConnectionHelper(IDBDatabase* aDatabase,
michael@0 139 IDBRequest* aRequest)
michael@0 140 : HelperBase(aRequest),
michael@0 141 mDatabase(aDatabase),
michael@0 142 mResultCode(NS_OK),
michael@0 143 mDispatched(false)
michael@0 144 {
michael@0 145 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 146 }
michael@0 147
michael@0 148 AsyncConnectionHelper::AsyncConnectionHelper(IDBTransaction* aTransaction,
michael@0 149 IDBRequest* aRequest)
michael@0 150 : HelperBase(aRequest),
michael@0 151 mDatabase(aTransaction->mDatabase),
michael@0 152 mTransaction(aTransaction),
michael@0 153 mResultCode(NS_OK),
michael@0 154 mDispatched(false)
michael@0 155 {
michael@0 156 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 157 }
michael@0 158
michael@0 159 AsyncConnectionHelper::~AsyncConnectionHelper()
michael@0 160 {
michael@0 161 if (!NS_IsMainThread()) {
michael@0 162 IDBDatabase* database;
michael@0 163 mDatabase.forget(&database);
michael@0 164
michael@0 165 IDBTransaction* transaction;
michael@0 166 mTransaction.forget(&transaction);
michael@0 167
michael@0 168 nsCOMPtr<nsIThread> mainThread;
michael@0 169 NS_GetMainThread(getter_AddRefs(mainThread));
michael@0 170 NS_WARN_IF_FALSE(mainThread, "Couldn't get the main thread!");
michael@0 171
michael@0 172 if (mainThread) {
michael@0 173 if (database) {
michael@0 174 NS_ProxyRelease(mainThread, static_cast<IDBWrapperCache*>(database));
michael@0 175 }
michael@0 176 if (transaction) {
michael@0 177 NS_ProxyRelease(mainThread, static_cast<IDBWrapperCache*>(transaction));
michael@0 178 }
michael@0 179 }
michael@0 180 }
michael@0 181
michael@0 182 NS_ASSERTION(!mOldProgressHandler, "Should not have anything here!");
michael@0 183 }
michael@0 184
michael@0 185 NS_IMPL_ISUPPORTS(AsyncConnectionHelper, nsIRunnable,
michael@0 186 mozIStorageProgressHandler)
michael@0 187
michael@0 188 NS_IMETHODIMP
michael@0 189 AsyncConnectionHelper::Run()
michael@0 190 {
michael@0 191 if (NS_IsMainThread()) {
michael@0 192 PROFILER_MAIN_THREAD_LABEL("IndexedDB", "AsyncConnectionHelper::Run");
michael@0 193
michael@0 194 if (mTransaction &&
michael@0 195 mTransaction->IsAborted()) {
michael@0 196 // Always fire a "error" event with ABORT_ERR if the transaction was
michael@0 197 // aborted, even if the request succeeded or failed with another error.
michael@0 198 mResultCode = NS_ERROR_DOM_INDEXEDDB_ABORT_ERR;
michael@0 199 }
michael@0 200
michael@0 201 IDBTransaction* oldTransaction = gCurrentTransaction;
michael@0 202 gCurrentTransaction = mTransaction;
michael@0 203
michael@0 204 ChildProcessSendResult sendResult =
michael@0 205 IndexedDatabaseManager::IsMainProcess() ?
michael@0 206 MaybeSendResponseToChildProcess(mResultCode) :
michael@0 207 Success_NotSent;
michael@0 208
michael@0 209 switch (sendResult) {
michael@0 210 case Success_Sent: {
michael@0 211 if (mRequest) {
michael@0 212 mRequest->NotifyHelperSentResultsToChildProcess(NS_OK);
michael@0 213 }
michael@0 214 break;
michael@0 215 }
michael@0 216
michael@0 217 case Success_NotSent: {
michael@0 218 if (mRequest) {
michael@0 219 nsresult rv = mRequest->NotifyHelperCompleted(this);
michael@0 220 if (NS_SUCCEEDED(mResultCode) && NS_FAILED(rv)) {
michael@0 221 mResultCode = rv;
michael@0 222 }
michael@0 223
michael@0 224 IDB_PROFILER_MARK("IndexedDB Request %llu: Running main thread "
michael@0 225 "response (rv = %lu)",
michael@0 226 "IDBRequest[%llu] MT Done",
michael@0 227 mRequest->GetSerialNumber(), mResultCode);
michael@0 228 }
michael@0 229
michael@0 230 // Call OnError if the database had an error or if the OnSuccess
michael@0 231 // handler has an error.
michael@0 232 if (NS_FAILED(mResultCode) ||
michael@0 233 NS_FAILED((mResultCode = OnSuccess()))) {
michael@0 234 OnError();
michael@0 235 }
michael@0 236 break;
michael@0 237 }
michael@0 238
michael@0 239 case Success_ActorDisconnected: {
michael@0 240 // Nothing needs to be done here.
michael@0 241 break;
michael@0 242 }
michael@0 243
michael@0 244 case Error: {
michael@0 245 IDB_WARNING("MaybeSendResultsToChildProcess failed!");
michael@0 246 mResultCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
michael@0 247 if (mRequest) {
michael@0 248 mRequest->NotifyHelperSentResultsToChildProcess(mResultCode);
michael@0 249 }
michael@0 250 break;
michael@0 251 }
michael@0 252
michael@0 253 default:
michael@0 254 MOZ_CRASH("Unknown value for ChildProcessSendResult!");
michael@0 255 }
michael@0 256
michael@0 257 NS_ASSERTION(gCurrentTransaction == mTransaction, "Should be unchanged!");
michael@0 258 gCurrentTransaction = oldTransaction;
michael@0 259
michael@0 260 if (mDispatched && mTransaction) {
michael@0 261 mTransaction->OnRequestFinished();
michael@0 262 }
michael@0 263
michael@0 264 ReleaseMainThreadObjects();
michael@0 265
michael@0 266 NS_ASSERTION(!(mDatabase || mTransaction || mRequest), "Subclass didn't "
michael@0 267 "call AsyncConnectionHelper::ReleaseMainThreadObjects!");
michael@0 268
michael@0 269 return NS_OK;
michael@0 270 }
michael@0 271
michael@0 272 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 273
michael@0 274 PROFILER_LABEL("IndexedDB", "AsyncConnectionHelper::Run");
michael@0 275
michael@0 276 IDB_PROFILER_MARK_IF(mRequest,
michael@0 277 "IndexedDB Request %llu: Beginning database work",
michael@0 278 "IDBRequest[%llu] DT Start",
michael@0 279 mRequest->GetSerialNumber());
michael@0 280
michael@0 281 nsresult rv = NS_OK;
michael@0 282 nsCOMPtr<mozIStorageConnection> connection;
michael@0 283
michael@0 284 if (mTransaction) {
michael@0 285 rv = mTransaction->GetOrCreateConnection(getter_AddRefs(connection));
michael@0 286 if (NS_SUCCEEDED(rv)) {
michael@0 287 NS_ASSERTION(connection, "This should never be null!");
michael@0 288 }
michael@0 289 }
michael@0 290
michael@0 291 bool setProgressHandler = false;
michael@0 292 if (connection) {
michael@0 293 rv = connection->SetProgressHandler(kProgressHandlerGranularity, this,
michael@0 294 getter_AddRefs(mOldProgressHandler));
michael@0 295 NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "SetProgressHandler failed!");
michael@0 296 if (NS_SUCCEEDED(rv)) {
michael@0 297 setProgressHandler = true;
michael@0 298 }
michael@0 299 }
michael@0 300
michael@0 301 if (NS_SUCCEEDED(rv)) {
michael@0 302 bool hasSavepoint = false;
michael@0 303 if (mDatabase) {
michael@0 304 QuotaManager::SetCurrentWindow(mDatabase->GetOwner());
michael@0 305
michael@0 306 // Make the first savepoint.
michael@0 307 if (mTransaction) {
michael@0 308 if (!(hasSavepoint = mTransaction->StartSavepoint())) {
michael@0 309 NS_WARNING("Failed to make savepoint!");
michael@0 310 }
michael@0 311 }
michael@0 312 }
michael@0 313
michael@0 314 mResultCode = DoDatabaseWork(connection);
michael@0 315
michael@0 316 if (mDatabase) {
michael@0 317 // Release or roll back the savepoint depending on the error code.
michael@0 318 if (hasSavepoint) {
michael@0 319 NS_ASSERTION(mTransaction, "Huh?!");
michael@0 320 if (NS_SUCCEEDED(mResultCode)) {
michael@0 321 mTransaction->ReleaseSavepoint();
michael@0 322 }
michael@0 323 else {
michael@0 324 mTransaction->RollbackSavepoint();
michael@0 325 }
michael@0 326 }
michael@0 327
michael@0 328 // Don't unset this until we're sure that all SQLite activity has
michael@0 329 // completed!
michael@0 330 QuotaManager::SetCurrentWindow(nullptr);
michael@0 331 }
michael@0 332 }
michael@0 333 else {
michael@0 334 // NS_ERROR_NOT_AVAILABLE is our special code for "database is invalidated"
michael@0 335 // and we should fail with RECOVERABLE_ERR.
michael@0 336 if (rv == NS_ERROR_NOT_AVAILABLE) {
michael@0 337 mResultCode = NS_ERROR_DOM_INDEXEDDB_RECOVERABLE_ERR;
michael@0 338 }
michael@0 339 else {
michael@0 340 IDB_REPORT_INTERNAL_ERR();
michael@0 341 mResultCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
michael@0 342 }
michael@0 343 }
michael@0 344
michael@0 345 if (setProgressHandler) {
michael@0 346 nsCOMPtr<mozIStorageProgressHandler> handler;
michael@0 347 rv = connection->RemoveProgressHandler(getter_AddRefs(handler));
michael@0 348 NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "RemoveProgressHandler failed!");
michael@0 349 #ifdef DEBUG
michael@0 350 if (NS_SUCCEEDED(rv)) {
michael@0 351 NS_ASSERTION(SameCOMIdentity(handler, static_cast<nsIRunnable*>(this)),
michael@0 352 "Mismatch!");
michael@0 353 }
michael@0 354 #endif
michael@0 355 }
michael@0 356
michael@0 357 IDB_PROFILER_MARK_IF(mRequest,
michael@0 358 "IndexedDB Request %llu: Finished database work "
michael@0 359 "(rv = %lu)",
michael@0 360 "IDBRequest[%llu] DT Done", mRequest->GetSerialNumber(),
michael@0 361 mResultCode);
michael@0 362
michael@0 363 return NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL);
michael@0 364 }
michael@0 365
michael@0 366 NS_IMETHODIMP
michael@0 367 AsyncConnectionHelper::OnProgress(mozIStorageConnection* aConnection,
michael@0 368 bool* _retval)
michael@0 369 {
michael@0 370 if (mDatabase && mDatabase->IsInvalidated()) {
michael@0 371 // Someone is trying to delete the database file. Exit lightningfast!
michael@0 372 *_retval = true;
michael@0 373 return NS_OK;
michael@0 374 }
michael@0 375
michael@0 376 if (mOldProgressHandler) {
michael@0 377 return mOldProgressHandler->OnProgress(aConnection, _retval);
michael@0 378 }
michael@0 379
michael@0 380 *_retval = false;
michael@0 381 return NS_OK;
michael@0 382 }
michael@0 383
michael@0 384 nsresult
michael@0 385 AsyncConnectionHelper::Dispatch(nsIEventTarget* aTarget)
michael@0 386 {
michael@0 387 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 388
michael@0 389 nsresult rv = Init();
michael@0 390 if (NS_FAILED(rv)) {
michael@0 391 return rv;
michael@0 392 }
michael@0 393
michael@0 394 rv = aTarget->Dispatch(this, NS_DISPATCH_NORMAL);
michael@0 395 NS_ENSURE_SUCCESS(rv, rv);
michael@0 396
michael@0 397 if (mTransaction) {
michael@0 398 mTransaction->OnNewRequest();
michael@0 399 }
michael@0 400
michael@0 401 mDispatched = true;
michael@0 402
michael@0 403 return NS_OK;
michael@0 404 }
michael@0 405
michael@0 406 nsresult
michael@0 407 AsyncConnectionHelper::DispatchToTransactionPool()
michael@0 408 {
michael@0 409 NS_ASSERTION(mTransaction, "Only ok to call this with a transaction!");
michael@0 410 TransactionPoolEventTarget target(mTransaction);
michael@0 411 return Dispatch(&target);
michael@0 412 }
michael@0 413
michael@0 414 // static
michael@0 415 void
michael@0 416 AsyncConnectionHelper::SetCurrentTransaction(IDBTransaction* aTransaction)
michael@0 417 {
michael@0 418 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 419 NS_ASSERTION(!aTransaction || !gCurrentTransaction,
michael@0 420 "Stepping on another transaction!");
michael@0 421
michael@0 422 gCurrentTransaction = aTransaction;
michael@0 423 }
michael@0 424
michael@0 425 // static
michael@0 426 IDBTransaction*
michael@0 427 AsyncConnectionHelper::GetCurrentTransaction()
michael@0 428 {
michael@0 429 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 430
michael@0 431 return gCurrentTransaction;
michael@0 432 }
michael@0 433
michael@0 434 nsresult
michael@0 435 AsyncConnectionHelper::Init()
michael@0 436 {
michael@0 437 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 438
michael@0 439 return NS_OK;
michael@0 440 }
michael@0 441
michael@0 442 already_AddRefed<nsIDOMEvent>
michael@0 443 AsyncConnectionHelper::CreateSuccessEvent(mozilla::dom::EventTarget* aOwner)
michael@0 444 {
michael@0 445 return CreateGenericEvent(mRequest, NS_LITERAL_STRING(SUCCESS_EVT_STR),
michael@0 446 eDoesNotBubble, eNotCancelable);
michael@0 447 }
michael@0 448
michael@0 449 nsresult
michael@0 450 AsyncConnectionHelper::OnSuccess()
michael@0 451 {
michael@0 452 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 453 NS_ASSERTION(mRequest, "Null request!");
michael@0 454
michael@0 455 PROFILER_MAIN_THREAD_LABEL("IndexedDB", "AsyncConnectionHelper::OnSuccess");
michael@0 456
michael@0 457 nsRefPtr<nsIDOMEvent> event = CreateSuccessEvent(mRequest);
michael@0 458 if (!event) {
michael@0 459 IDB_WARNING("Failed to create event!");
michael@0 460 return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
michael@0 461 }
michael@0 462
michael@0 463 bool dummy;
michael@0 464 nsresult rv = mRequest->DispatchEvent(event, &dummy);
michael@0 465 IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
michael@0 466
michael@0 467 WidgetEvent* internalEvent = event->GetInternalNSEvent();
michael@0 468 NS_ASSERTION(internalEvent, "This should never be null!");
michael@0 469
michael@0 470 NS_ASSERTION(!mTransaction ||
michael@0 471 mTransaction->IsOpen() ||
michael@0 472 mTransaction->IsAborted(),
michael@0 473 "How else can this be closed?!");
michael@0 474
michael@0 475 if (internalEvent->mFlags.mExceptionHasBeenRisen &&
michael@0 476 mTransaction &&
michael@0 477 mTransaction->IsOpen()) {
michael@0 478 rv = mTransaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
michael@0 479 NS_ENSURE_SUCCESS(rv, rv);
michael@0 480 }
michael@0 481
michael@0 482 return NS_OK;
michael@0 483 }
michael@0 484
michael@0 485 void
michael@0 486 AsyncConnectionHelper::OnError()
michael@0 487 {
michael@0 488 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 489 NS_ASSERTION(mRequest, "Null request!");
michael@0 490
michael@0 491 PROFILER_MAIN_THREAD_LABEL("IndexedDB", "AsyncConnectionHelper::OnError");
michael@0 492
michael@0 493 // Make an error event and fire it at the target.
michael@0 494 nsRefPtr<nsIDOMEvent> event =
michael@0 495 CreateGenericEvent(mRequest, NS_LITERAL_STRING(ERROR_EVT_STR), eDoesBubble,
michael@0 496 eCancelable);
michael@0 497 if (!event) {
michael@0 498 NS_ERROR("Failed to create event!");
michael@0 499 return;
michael@0 500 }
michael@0 501
michael@0 502 bool doDefault;
michael@0 503 nsresult rv = mRequest->DispatchEvent(event, &doDefault);
michael@0 504 if (NS_SUCCEEDED(rv)) {
michael@0 505 NS_ASSERTION(!mTransaction ||
michael@0 506 mTransaction->IsOpen() ||
michael@0 507 mTransaction->IsAborted(),
michael@0 508 "How else can this be closed?!");
michael@0 509
michael@0 510 WidgetEvent* internalEvent = event->GetInternalNSEvent();
michael@0 511 NS_ASSERTION(internalEvent, "This should never be null!");
michael@0 512
michael@0 513 if (internalEvent->mFlags.mExceptionHasBeenRisen &&
michael@0 514 mTransaction &&
michael@0 515 mTransaction->IsOpen() &&
michael@0 516 NS_FAILED(mTransaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR))) {
michael@0 517 NS_WARNING("Failed to abort transaction!");
michael@0 518 }
michael@0 519
michael@0 520 if (doDefault &&
michael@0 521 mTransaction &&
michael@0 522 mTransaction->IsOpen() &&
michael@0 523 NS_FAILED(mTransaction->Abort(mRequest))) {
michael@0 524 NS_WARNING("Failed to abort transaction!");
michael@0 525 }
michael@0 526 }
michael@0 527 else {
michael@0 528 NS_WARNING("DispatchEvent failed!");
michael@0 529 }
michael@0 530 }
michael@0 531
michael@0 532 nsresult
michael@0 533 AsyncConnectionHelper::GetSuccessResult(JSContext* aCx,
michael@0 534 JS::MutableHandle<JS::Value> aVal)
michael@0 535 {
michael@0 536 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 537
michael@0 538 aVal.setUndefined();
michael@0 539 return NS_OK;
michael@0 540 }
michael@0 541
michael@0 542 void
michael@0 543 AsyncConnectionHelper::ReleaseMainThreadObjects()
michael@0 544 {
michael@0 545 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 546
michael@0 547 mDatabase = nullptr;
michael@0 548 mTransaction = nullptr;
michael@0 549
michael@0 550 HelperBase::ReleaseMainThreadObjects();
michael@0 551 }
michael@0 552
michael@0 553 AsyncConnectionHelper::ChildProcessSendResult
michael@0 554 AsyncConnectionHelper::MaybeSendResponseToChildProcess(nsresult aResultCode)
michael@0 555 {
michael@0 556 NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
michael@0 557 NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 558
michael@0 559 // If there's no request, there could never have been an actor, and so there
michael@0 560 // is nothing to do.
michael@0 561 if (!mRequest) {
michael@0 562 return Success_NotSent;
michael@0 563 }
michael@0 564
michael@0 565 IDBTransaction* trans = GetCurrentTransaction();
michael@0 566 // We may not have a transaction, e.g. for deleteDatabase
michael@0 567 if (!trans) {
michael@0 568 return Success_NotSent;
michael@0 569 }
michael@0 570
michael@0 571 // Are we shutting down the child?
michael@0 572 IndexedDBDatabaseParent* dbActor = trans->Database()->GetActorParent();
michael@0 573 if (dbActor && dbActor->IsDisconnected()) {
michael@0 574 return Success_ActorDisconnected;
michael@0 575 }
michael@0 576
michael@0 577 IndexedDBRequestParentBase* actor = mRequest->GetActorParent();
michael@0 578 if (!actor) {
michael@0 579 return Success_NotSent;
michael@0 580 }
michael@0 581
michael@0 582 IDB_PROFILER_MARK("IndexedDB Request %llu: Sending response to child "
michael@0 583 "process (rv = %lu)",
michael@0 584 "IDBRequest[%llu] MT Done",
michael@0 585 mRequest->GetSerialNumber(), aResultCode);
michael@0 586
michael@0 587 return SendResponseToChildProcess(aResultCode);
michael@0 588 }
michael@0 589
michael@0 590 nsresult
michael@0 591 AsyncConnectionHelper::OnParentProcessRequestComplete(
michael@0 592 const ResponseValue& aResponseValue)
michael@0 593 {
michael@0 594 NS_ASSERTION(!IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
michael@0 595
michael@0 596 if (aResponseValue.type() == ResponseValue::Tnsresult) {
michael@0 597 NS_ASSERTION(NS_FAILED(aResponseValue.get_nsresult()), "Huh?");
michael@0 598 SetError(aResponseValue.get_nsresult());
michael@0 599 }
michael@0 600 else {
michael@0 601 nsresult rv = UnpackResponseFromParentProcess(aResponseValue);
michael@0 602 NS_ENSURE_SUCCESS(rv, rv);
michael@0 603 }
michael@0 604
michael@0 605 return Run();
michael@0 606 }
michael@0 607
michael@0 608 // static
michael@0 609 nsresult
michael@0 610 AsyncConnectionHelper::ConvertToArrayAndCleanup(
michael@0 611 JSContext* aCx,
michael@0 612 nsTArray<StructuredCloneReadInfo>& aReadInfos,
michael@0 613 JS::MutableHandle<JS::Value> aResult)
michael@0 614 {
michael@0 615 NS_ASSERTION(aCx, "Null context!");
michael@0 616 NS_ASSERTION(aResult.address(), "Null pointer!");
michael@0 617
michael@0 618 nsresult rv = ConvertCloneReadInfosToArrayInternal(aCx, aReadInfos, aResult);
michael@0 619
michael@0 620 for (uint32_t index = 0; index < aReadInfos.Length(); index++) {
michael@0 621 aReadInfos[index].mCloneBuffer.clear();
michael@0 622 }
michael@0 623 aReadInfos.Clear();
michael@0 624
michael@0 625 return rv;
michael@0 626 }
michael@0 627
michael@0 628 NS_IMETHODIMP_(MozExternalRefCountType)
michael@0 629 StackBasedEventTarget::AddRef()
michael@0 630 {
michael@0 631 NS_NOTREACHED("Don't call me!");
michael@0 632 return 2;
michael@0 633 }
michael@0 634
michael@0 635 NS_IMETHODIMP_(MozExternalRefCountType)
michael@0 636 StackBasedEventTarget::Release()
michael@0 637 {
michael@0 638 NS_NOTREACHED("Don't call me!");
michael@0 639 return 1;
michael@0 640 }
michael@0 641
michael@0 642 NS_IMETHODIMP
michael@0 643 StackBasedEventTarget::QueryInterface(REFNSIID aIID,
michael@0 644 void** aInstancePtr)
michael@0 645 {
michael@0 646 NS_NOTREACHED("Don't call me!");
michael@0 647 return NS_NOINTERFACE;
michael@0 648 }
michael@0 649
michael@0 650 NS_IMETHODIMP
michael@0 651 ImmediateRunEventTarget::Dispatch(nsIRunnable* aRunnable,
michael@0 652 uint32_t aFlags)
michael@0 653 {
michael@0 654 NS_ASSERTION(aRunnable, "Null pointer!");
michael@0 655
michael@0 656 nsCOMPtr<nsIRunnable> runnable(aRunnable);
michael@0 657 DebugOnly<nsresult> rv =
michael@0 658 runnable->Run();
michael@0 659 MOZ_ASSERT(NS_SUCCEEDED(rv));
michael@0 660 return NS_OK;
michael@0 661 }
michael@0 662
michael@0 663 NS_IMETHODIMP
michael@0 664 ImmediateRunEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread)
michael@0 665 {
michael@0 666 *aIsOnCurrentThread = true;
michael@0 667 return NS_OK;
michael@0 668 }
michael@0 669
michael@0 670 NS_IMETHODIMP
michael@0 671 TransactionPoolEventTarget::Dispatch(nsIRunnable* aRunnable,
michael@0 672 uint32_t aFlags)
michael@0 673 {
michael@0 674 NS_ASSERTION(aRunnable, "Null pointer!");
michael@0 675 NS_ASSERTION(aFlags == NS_DISPATCH_NORMAL, "Unsupported!");
michael@0 676
michael@0 677 TransactionThreadPool* pool = TransactionThreadPool::GetOrCreate();
michael@0 678 NS_ENSURE_TRUE(pool, NS_ERROR_UNEXPECTED);
michael@0 679
michael@0 680 nsresult rv = pool->Dispatch(mTransaction, aRunnable, false, nullptr);
michael@0 681 NS_ENSURE_SUCCESS(rv, rv);
michael@0 682
michael@0 683 return NS_OK;
michael@0 684 }
michael@0 685
michael@0 686 NS_IMETHODIMP
michael@0 687 TransactionPoolEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread)
michael@0 688 {
michael@0 689 *aIsOnCurrentThread = false;
michael@0 690 return NS_OK;
michael@0 691 }
michael@0 692
michael@0 693 NS_IMETHODIMP
michael@0 694 NoDispatchEventTarget::Dispatch(nsIRunnable* aRunnable,
michael@0 695 uint32_t aFlags)
michael@0 696 {
michael@0 697 nsCOMPtr<nsIRunnable> runnable = aRunnable;
michael@0 698 return NS_OK;
michael@0 699 }
michael@0 700
michael@0 701 NS_IMETHODIMP
michael@0 702 NoDispatchEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread)
michael@0 703 {
michael@0 704 *aIsOnCurrentThread = true;
michael@0 705 return NS_OK;
michael@0 706 }

mercurial