123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "ActorsChild.h"
- #include "BackgroundChildImpl.h"
- #include "IDBDatabase.h"
- #include "IDBEvents.h"
- #include "IDBFactory.h"
- #include "IDBIndex.h"
- #include "IDBMutableFile.h"
- #include "IDBObjectStore.h"
- #include "IDBMutableFile.h"
- #include "IDBRequest.h"
- #include "IDBTransaction.h"
- #include "IndexedDatabase.h"
- #include "IndexedDatabaseInlines.h"
- #include "mozilla/BasicEvents.h"
- #include "mozilla/Maybe.h"
- #include "mozilla/TypeTraits.h"
- #include "mozilla/dom/Element.h"
- #include "mozilla/dom/PermissionMessageUtils.h"
- #include "mozilla/dom/TabChild.h"
- #include "mozilla/dom/indexedDB/PBackgroundIDBDatabaseFileChild.h"
- #include "mozilla/dom/indexedDB/PIndexedDBPermissionRequestChild.h"
- #include "mozilla/dom/ipc/BlobChild.h"
- #include "mozilla/ipc/BackgroundUtils.h"
- #include "nsCOMPtr.h"
- #include "nsContentUtils.h"
- #include "nsIBFCacheEntry.h"
- #include "nsIDocument.h"
- #include "nsIDOMEvent.h"
- #include "nsIEventTarget.h"
- #include "nsIFileStreams.h"
- #include "nsNetCID.h"
- #include "nsPIDOMWindow.h"
- #include "nsThreadUtils.h"
- #include "nsTraceRefcnt.h"
- #include "PermissionRequestBase.h"
- #include "ProfilerHelpers.h"
- #include "ReportInternalError.h"
- #include "WorkerPrivate.h"
- #include "WorkerRunnable.h"
- #ifdef DEBUG
- #include "IndexedDatabaseManager.h"
- #endif
- #define GC_ON_IPC_MESSAGES 0
- #if defined(DEBUG) || GC_ON_IPC_MESSAGES
- #include "js/GCAPI.h"
- #include "nsJSEnvironment.h"
- #define BUILD_GC_ON_IPC_MESSAGES
- #endif // DEBUG || GC_ON_IPC_MESSAGES
- namespace mozilla {
- using ipc::PrincipalInfo;
- namespace dom {
- using namespace workers;
- namespace indexedDB {
- /*******************************************************************************
- * ThreadLocal
- ******************************************************************************/
- ThreadLocal::ThreadLocal(const nsID& aBackgroundChildLoggingId)
- : mLoggingInfo(aBackgroundChildLoggingId, 1, -1, 1)
- , mCurrentTransaction(0)
- #ifdef DEBUG
- , mOwningThread(PR_GetCurrentThread())
- #endif
- {
- MOZ_ASSERT(mOwningThread);
- MOZ_COUNT_CTOR(mozilla::dom::indexedDB::ThreadLocal);
- // NSID_LENGTH counts the null terminator, SetLength() does not.
- mLoggingIdString.SetLength(NSID_LENGTH - 1);
- aBackgroundChildLoggingId.ToProvidedString(
- *reinterpret_cast<char(*)[NSID_LENGTH]>(mLoggingIdString.BeginWriting()));
- }
- ThreadLocal::~ThreadLocal()
- {
- MOZ_COUNT_DTOR(mozilla::dom::indexedDB::ThreadLocal);
- }
- #ifdef DEBUG
- void
- ThreadLocal::AssertIsOnOwningThread() const
- {
- MOZ_ASSERT(PR_GetCurrentThread() == mOwningThread);
- }
- #endif // DEBUG
- /*******************************************************************************
- * Helpers
- ******************************************************************************/
- namespace {
- void
- MaybeCollectGarbageOnIPCMessage()
- {
- #ifdef BUILD_GC_ON_IPC_MESSAGES
- static const bool kCollectGarbageOnIPCMessages =
- #if GC_ON_IPC_MESSAGES
- true;
- #else
- false;
- #endif // GC_ON_IPC_MESSAGES
- if (!kCollectGarbageOnIPCMessages) {
- return;
- }
- static bool haveWarnedAboutGC = false;
- static bool haveWarnedAboutNonMainThread = false;
- if (!haveWarnedAboutGC) {
- haveWarnedAboutGC = true;
- NS_WARNING("IndexedDB child actor GC debugging enabled!");
- }
- if (!NS_IsMainThread()) {
- if (!haveWarnedAboutNonMainThread) {
- haveWarnedAboutNonMainThread = true;
- NS_WARNING("Don't know how to GC on a non-main thread yet.");
- }
- return;
- }
- nsJSContext::GarbageCollectNow(JS::gcreason::DOM_IPC);
- nsJSContext::CycleCollectNow();
- #endif // BUILD_GC_ON_IPC_MESSAGES
- }
- class MOZ_STACK_CLASS AutoSetCurrentTransaction final
- {
- typedef mozilla::ipc::BackgroundChildImpl BackgroundChildImpl;
- IDBTransaction* const mTransaction;
- IDBTransaction* mPreviousTransaction;
- ThreadLocal* mThreadLocal;
- public:
- explicit AutoSetCurrentTransaction(IDBTransaction* aTransaction)
- : mTransaction(aTransaction)
- , mPreviousTransaction(nullptr)
- , mThreadLocal(nullptr)
- {
- if (aTransaction) {
- BackgroundChildImpl::ThreadLocal* threadLocal =
- BackgroundChildImpl::GetThreadLocalForCurrentThread();
- MOZ_ASSERT(threadLocal);
- // Hang onto this for resetting later.
- mThreadLocal = threadLocal->mIndexedDBThreadLocal;
- MOZ_ASSERT(mThreadLocal);
- // Save the current value.
- mPreviousTransaction = mThreadLocal->GetCurrentTransaction();
- // Set the new value.
- mThreadLocal->SetCurrentTransaction(aTransaction);
- }
- }
- ~AutoSetCurrentTransaction()
- {
- MOZ_ASSERT_IF(mThreadLocal, mTransaction);
- MOZ_ASSERT_IF(mThreadLocal,
- mThreadLocal->GetCurrentTransaction() == mTransaction);
- if (mThreadLocal) {
- // Reset old value.
- mThreadLocal->SetCurrentTransaction(mPreviousTransaction);
- }
- }
- IDBTransaction*
- Transaction() const
- {
- return mTransaction;
- }
- };
- class MOZ_STACK_CLASS ResultHelper final
- : public IDBRequest::ResultCallback
- {
- IDBRequest* mRequest;
- AutoSetCurrentTransaction mAutoTransaction;
- union
- {
- IDBDatabase* mDatabase;
- IDBCursor* mCursor;
- IDBMutableFile* mMutableFile;
- StructuredCloneReadInfo* mStructuredClone;
- const nsTArray<StructuredCloneReadInfo>* mStructuredCloneArray;
- const Key* mKey;
- const nsTArray<Key>* mKeyArray;
- const JS::Value* mJSVal;
- const JS::Handle<JS::Value>* mJSValHandle;
- } mResult;
- enum
- {
- ResultTypeDatabase,
- ResultTypeCursor,
- ResultTypeMutableFile,
- ResultTypeStructuredClone,
- ResultTypeStructuredCloneArray,
- ResultTypeKey,
- ResultTypeKeyArray,
- ResultTypeJSVal,
- ResultTypeJSValHandle,
- } mResultType;
- public:
- ResultHelper(IDBRequest* aRequest,
- IDBTransaction* aTransaction,
- IDBDatabase* aResult)
- : mRequest(aRequest)
- , mAutoTransaction(aTransaction)
- , mResultType(ResultTypeDatabase)
- {
- MOZ_ASSERT(aRequest);
- MOZ_ASSERT(aResult);
- mResult.mDatabase = aResult;
- }
- ResultHelper(IDBRequest* aRequest,
- IDBTransaction* aTransaction,
- IDBCursor* aResult)
- : mRequest(aRequest)
- , mAutoTransaction(aTransaction)
- , mResultType(ResultTypeCursor)
- {
- MOZ_ASSERT(aRequest);
- mResult.mCursor = aResult;
- }
- ResultHelper(IDBRequest* aRequest,
- IDBTransaction* aTransaction,
- IDBMutableFile* aResult)
- : mRequest(aRequest)
- , mAutoTransaction(aTransaction)
- , mResultType(ResultTypeMutableFile)
- {
- MOZ_ASSERT(aRequest);
- mResult.mMutableFile = aResult;
- }
- ResultHelper(IDBRequest* aRequest,
- IDBTransaction* aTransaction,
- StructuredCloneReadInfo* aResult)
- : mRequest(aRequest)
- , mAutoTransaction(aTransaction)
- , mResultType(ResultTypeStructuredClone)
- {
- MOZ_ASSERT(aRequest);
- MOZ_ASSERT(aResult);
- mResult.mStructuredClone = aResult;
- }
- ResultHelper(IDBRequest* aRequest,
- IDBTransaction* aTransaction,
- const nsTArray<StructuredCloneReadInfo>* aResult)
- : mRequest(aRequest)
- , mAutoTransaction(aTransaction)
- , mResultType(ResultTypeStructuredCloneArray)
- {
- MOZ_ASSERT(aRequest);
- MOZ_ASSERT(aResult);
- mResult.mStructuredCloneArray = aResult;
- }
- ResultHelper(IDBRequest* aRequest,
- IDBTransaction* aTransaction,
- const Key* aResult)
- : mRequest(aRequest)
- , mAutoTransaction(aTransaction)
- , mResultType(ResultTypeKey)
- {
- MOZ_ASSERT(aRequest);
- MOZ_ASSERT(aResult);
- mResult.mKey = aResult;
- }
- ResultHelper(IDBRequest* aRequest,
- IDBTransaction* aTransaction,
- const nsTArray<Key>* aResult)
- : mRequest(aRequest)
- , mAutoTransaction(aTransaction)
- , mResultType(ResultTypeKeyArray)
- {
- MOZ_ASSERT(aRequest);
- MOZ_ASSERT(aResult);
- mResult.mKeyArray = aResult;
- }
- ResultHelper(IDBRequest* aRequest,
- IDBTransaction* aTransaction,
- const JS::Value* aResult)
- : mRequest(aRequest)
- , mAutoTransaction(aTransaction)
- , mResultType(ResultTypeJSVal)
- {
- MOZ_ASSERT(aRequest);
- MOZ_ASSERT(!aResult->isGCThing());
- mResult.mJSVal = aResult;
- }
- ResultHelper(IDBRequest* aRequest,
- IDBTransaction* aTransaction,
- const JS::Handle<JS::Value>* aResult)
- : mRequest(aRequest)
- , mAutoTransaction(aTransaction)
- , mResultType(ResultTypeJSValHandle)
- {
- MOZ_ASSERT(aRequest);
- mResult.mJSValHandle = aResult;
- }
- IDBRequest*
- Request() const
- {
- return mRequest;
- }
- IDBTransaction*
- Transaction() const
- {
- return mAutoTransaction.Transaction();
- }
- virtual nsresult
- GetResult(JSContext* aCx, JS::MutableHandle<JS::Value> aResult) override
- {
- MOZ_ASSERT(aCx);
- MOZ_ASSERT(mRequest);
- switch (mResultType) {
- case ResultTypeDatabase:
- return GetResult(aCx, mResult.mDatabase, aResult);
- case ResultTypeCursor:
- return GetResult(aCx, mResult.mCursor, aResult);
- case ResultTypeMutableFile:
- return GetResult(aCx, mResult.mMutableFile, aResult);
- case ResultTypeStructuredClone:
- return GetResult(aCx, mResult.mStructuredClone, aResult);
- case ResultTypeStructuredCloneArray:
- return GetResult(aCx, mResult.mStructuredCloneArray, aResult);
- case ResultTypeKey:
- return GetResult(aCx, mResult.mKey, aResult);
- case ResultTypeKeyArray:
- return GetResult(aCx, mResult.mKeyArray, aResult);
- case ResultTypeJSVal:
- aResult.set(*mResult.mJSVal);
- return NS_OK;
- case ResultTypeJSValHandle:
- aResult.set(*mResult.mJSValHandle);
- return NS_OK;
- default:
- MOZ_CRASH("Unknown result type!");
- }
- MOZ_CRASH("Should never get here!");
- }
- private:
- template <class T>
- typename EnableIf<IsSame<T, IDBDatabase>::value ||
- IsSame<T, IDBCursor>::value ||
- IsSame<T, IDBMutableFile>::value,
- nsresult>::Type
- GetResult(JSContext* aCx,
- T* aDOMObject,
- JS::MutableHandle<JS::Value> aResult)
- {
- if (!aDOMObject) {
- aResult.setNull();
- return NS_OK;
- }
- bool ok = GetOrCreateDOMReflector(aCx, aDOMObject, aResult);
- if (NS_WARN_IF(!ok)) {
- IDB_REPORT_INTERNAL_ERR();
- return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
- }
- return NS_OK;
- }
- nsresult
- GetResult(JSContext* aCx,
- StructuredCloneReadInfo* aCloneInfo,
- JS::MutableHandle<JS::Value> aResult)
- {
- bool ok = IDBObjectStore::DeserializeValue(aCx, *aCloneInfo, aResult);
- if (NS_WARN_IF(!ok)) {
- return NS_ERROR_DOM_DATA_CLONE_ERR;
- }
- return NS_OK;
- }
- nsresult
- GetResult(JSContext* aCx,
- const nsTArray<StructuredCloneReadInfo>* aCloneInfos,
- JS::MutableHandle<JS::Value> aResult)
- {
- JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
- if (NS_WARN_IF(!array)) {
- IDB_REPORT_INTERNAL_ERR();
- return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
- }
- if (!aCloneInfos->IsEmpty()) {
- const uint32_t count = aCloneInfos->Length();
- if (NS_WARN_IF(!JS_SetArrayLength(aCx, array, count))) {
- IDB_REPORT_INTERNAL_ERR();
- return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
- }
- for (uint32_t index = 0; index < count; index++) {
- auto& cloneInfo =
- const_cast<StructuredCloneReadInfo&>(aCloneInfos->ElementAt(index));
- JS::Rooted<JS::Value> value(aCx);
- nsresult rv = GetResult(aCx, &cloneInfo, &value);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- if (NS_WARN_IF(!JS_DefineElement(aCx, array, index, value,
- JSPROP_ENUMERATE))) {
- IDB_REPORT_INTERNAL_ERR();
- return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
- }
- }
- }
- aResult.setObject(*array);
- return NS_OK;
- }
- nsresult
- GetResult(JSContext* aCx,
- const Key* aKey,
- JS::MutableHandle<JS::Value> aResult)
- {
- nsresult rv = aKey->ToJSVal(aCx, aResult);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- return NS_OK;
- }
- nsresult
- GetResult(JSContext* aCx,
- const nsTArray<Key>* aKeys,
- JS::MutableHandle<JS::Value> aResult)
- {
- JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0));
- if (NS_WARN_IF(!array)) {
- IDB_REPORT_INTERNAL_ERR();
- return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
- }
- if (!aKeys->IsEmpty()) {
- const uint32_t count = aKeys->Length();
- if (NS_WARN_IF(!JS_SetArrayLength(aCx, array, count))) {
- IDB_REPORT_INTERNAL_ERR();
- return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
- }
- for (uint32_t index = 0; index < count; index++) {
- const Key& key = aKeys->ElementAt(index);
- MOZ_ASSERT(!key.IsUnset());
- JS::Rooted<JS::Value> value(aCx);
- nsresult rv = GetResult(aCx, &key, &value);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- if (NS_WARN_IF(!JS_DefineElement(aCx, array, index, value,
- JSPROP_ENUMERATE))) {
- IDB_REPORT_INTERNAL_ERR();
- return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
- }
- }
- }
- aResult.setObject(*array);
- return NS_OK;
- }
- };
- class PermissionRequestMainProcessHelper final
- : public PermissionRequestBase
- {
- BackgroundFactoryRequestChild* mActor;
- RefPtr<IDBFactory> mFactory;
- public:
- PermissionRequestMainProcessHelper(BackgroundFactoryRequestChild* aActor,
- IDBFactory* aFactory,
- Element* aOwnerElement,
- nsIPrincipal* aPrincipal)
- : PermissionRequestBase(aOwnerElement, aPrincipal)
- , mActor(aActor)
- , mFactory(aFactory)
- {
- MOZ_ASSERT(aActor);
- MOZ_ASSERT(aFactory);
- aActor->AssertIsOnOwningThread();
- }
- protected:
- ~PermissionRequestMainProcessHelper()
- { }
- private:
- virtual void
- OnPromptComplete(PermissionValue aPermissionValue) override;
- };
- class PermissionRequestChildProcessActor final
- : public PIndexedDBPermissionRequestChild
- {
- BackgroundFactoryRequestChild* mActor;
- RefPtr<IDBFactory> mFactory;
- public:
- PermissionRequestChildProcessActor(BackgroundFactoryRequestChild* aActor,
- IDBFactory* aFactory)
- : mActor(aActor)
- , mFactory(aFactory)
- {
- MOZ_ASSERT(aActor);
- MOZ_ASSERT(aFactory);
- aActor->AssertIsOnOwningThread();
- }
- protected:
- ~PermissionRequestChildProcessActor()
- { }
- virtual bool
- Recv__delete__(const uint32_t& aPermission) override;
- };
- void
- DeserializeStructuredCloneFiles(
- IDBDatabase* aDatabase,
- const nsTArray<SerializedStructuredCloneFile>& aSerializedFiles,
- const nsTArray<RefPtr<JS::WasmModule>>* aModuleSet,
- nsTArray<StructuredCloneFile>& aFiles)
- {
- MOZ_ASSERT_IF(aModuleSet, !aModuleSet->IsEmpty());
- MOZ_ASSERT(aFiles.IsEmpty());
- if (!aSerializedFiles.IsEmpty()) {
- uint32_t moduleIndex = 0;
- const uint32_t count = aSerializedFiles.Length();
- aFiles.SetCapacity(count);
- for (uint32_t index = 0; index < count; index++) {
- const SerializedStructuredCloneFile& serializedFile =
- aSerializedFiles[index];
- const BlobOrMutableFile& blobOrMutableFile = serializedFile.file();
- switch (serializedFile.type()) {
- case StructuredCloneFile::eBlob: {
- MOZ_ASSERT(blobOrMutableFile.type() == BlobOrMutableFile::TPBlobChild);
- auto* actor =
- static_cast<BlobChild*>(blobOrMutableFile.get_PBlobChild());
- RefPtr<BlobImpl> blobImpl = actor->GetBlobImpl();
- MOZ_ASSERT(blobImpl);
- RefPtr<Blob> blob = Blob::Create(aDatabase->GetOwner(), blobImpl);
- aDatabase->NoteReceivedBlob(blob);
- StructuredCloneFile* file = aFiles.AppendElement();
- MOZ_ASSERT(file);
- file->mType = StructuredCloneFile::eBlob;
- file->mBlob.swap(blob);
- break;
- }
- case StructuredCloneFile::eMutableFile: {
- MOZ_ASSERT(blobOrMutableFile.type() == BlobOrMutableFile::Tnull_t ||
- blobOrMutableFile.type() ==
- BlobOrMutableFile::TPBackgroundMutableFileChild);
- switch (blobOrMutableFile.type()) {
- case BlobOrMutableFile::Tnull_t: {
- StructuredCloneFile* file = aFiles.AppendElement();
- MOZ_ASSERT(file);
- file->mType = StructuredCloneFile::eMutableFile;
- break;
- }
- case BlobOrMutableFile::TPBackgroundMutableFileChild: {
- auto* actor =
- static_cast<BackgroundMutableFileChild*>(
- blobOrMutableFile.get_PBackgroundMutableFileChild());
- MOZ_ASSERT(actor);
- actor->EnsureDOMObject();
- auto* mutableFile =
- static_cast<IDBMutableFile*>(actor->GetDOMObject());
- MOZ_ASSERT(mutableFile);
- StructuredCloneFile* file = aFiles.AppendElement();
- MOZ_ASSERT(file);
- file->mType = StructuredCloneFile::eMutableFile;
- file->mMutableFile = mutableFile;
- actor->ReleaseDOMObject();
- break;
- }
- default:
- MOZ_CRASH("Should never get here!");
- }
- break;
- }
- case StructuredCloneFile::eStructuredClone: {
- StructuredCloneFile* file = aFiles.AppendElement();
- MOZ_ASSERT(file);
- file->mType = StructuredCloneFile::eStructuredClone;
- break;
- }
- case StructuredCloneFile::eWasmBytecode:
- case StructuredCloneFile::eWasmCompiled: {
- if (aModuleSet) {
- MOZ_ASSERT(blobOrMutableFile.type() == BlobOrMutableFile::Tnull_t);
- StructuredCloneFile* file = aFiles.AppendElement();
- MOZ_ASSERT(file);
- file->mType = serializedFile.type();
- MOZ_ASSERT(moduleIndex < aModuleSet->Length());
- file->mWasmModule = aModuleSet->ElementAt(moduleIndex);
- if (serializedFile.type() == StructuredCloneFile::eWasmCompiled) {
- moduleIndex++;
- }
- break;
- }
- MOZ_ASSERT(blobOrMutableFile.type() ==
- BlobOrMutableFile::TPBlobChild);
- auto* actor =
- static_cast<BlobChild*>(blobOrMutableFile.get_PBlobChild());
- RefPtr<BlobImpl> blobImpl = actor->GetBlobImpl();
- MOZ_ASSERT(blobImpl);
- RefPtr<Blob> blob = Blob::Create(aDatabase->GetOwner(), blobImpl);
- aDatabase->NoteReceivedBlob(blob);
- StructuredCloneFile* file = aFiles.AppendElement();
- MOZ_ASSERT(file);
- file->mType = serializedFile.type();
- file->mBlob.swap(blob);
- break;
- }
- default:
- MOZ_CRASH("Should never get here!");
- }
- }
- }
- }
- void
- DispatchErrorEvent(IDBRequest* aRequest,
- nsresult aErrorCode,
- IDBTransaction* aTransaction = nullptr,
- nsIDOMEvent* aEvent = nullptr)
- {
- MOZ_ASSERT(aRequest);
- aRequest->AssertIsOnOwningThread();
- MOZ_ASSERT(NS_FAILED(aErrorCode));
- MOZ_ASSERT(NS_ERROR_GET_MODULE(aErrorCode) == NS_ERROR_MODULE_DOM_INDEXEDDB);
- PROFILER_LABEL("IndexedDB",
- "DispatchErrorEvent",
- js::ProfileEntry::Category::STORAGE);
- RefPtr<IDBRequest> request = aRequest;
- RefPtr<IDBTransaction> transaction = aTransaction;
- request->SetError(aErrorCode);
- nsCOMPtr<nsIDOMEvent> errorEvent;
- if (!aEvent) {
- // Make an error event and fire it at the target.
- errorEvent = CreateGenericEvent(request,
- nsDependentString(kErrorEventType),
- eDoesBubble,
- eCancelable);
- MOZ_ASSERT(errorEvent);
- aEvent = errorEvent;
- }
- Maybe<AutoSetCurrentTransaction> asct;
- if (aTransaction) {
- asct.emplace(aTransaction);
- }
- if (transaction) {
- IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: "
- "Firing %s event with error 0x%x",
- "IndexedDB %s: C T[%lld] R[%llu]: %s (0x%x)",
- IDB_LOG_ID_STRING(),
- transaction->LoggingSerialNumber(),
- request->LoggingSerialNumber(),
- IDB_LOG_STRINGIFY(aEvent, kErrorEventType),
- aErrorCode);
- } else {
- IDB_LOG_MARK("IndexedDB %s: Child Request[%llu]: "
- "Firing %s event with error 0x%x",
- "IndexedDB %s: C R[%llu]: %s (0x%x)",
- IDB_LOG_ID_STRING(),
- request->LoggingSerialNumber(),
- IDB_LOG_STRINGIFY(aEvent, kErrorEventType),
- aErrorCode);
- }
- bool doDefault;
- nsresult rv = request->DispatchEvent(aEvent, &doDefault);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return;
- }
- MOZ_ASSERT(!transaction || transaction->IsOpen() || transaction->IsAborted());
- // Do not abort the transaction here if this request is failed due to the
- // abortion of its transaction to ensure that the correct error cause of
- // the abort event be set in IDBTransaction::FireCompleteOrAbortEvents() later.
- if (transaction && transaction->IsOpen() &&
- aErrorCode != NS_ERROR_DOM_INDEXEDDB_ABORT_ERR) {
- WidgetEvent* internalEvent = aEvent->WidgetEventPtr();
- MOZ_ASSERT(internalEvent);
- if (internalEvent->mFlags.mExceptionWasRaised) {
- transaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
- } else if (doDefault) {
- transaction->Abort(request);
- }
- }
- }
- void
- DispatchSuccessEvent(ResultHelper* aResultHelper,
- nsIDOMEvent* aEvent = nullptr)
- {
- MOZ_ASSERT(aResultHelper);
- PROFILER_LABEL("IndexedDB",
- "DispatchSuccessEvent",
- js::ProfileEntry::Category::STORAGE);
- RefPtr<IDBRequest> request = aResultHelper->Request();
- MOZ_ASSERT(request);
- request->AssertIsOnOwningThread();
- RefPtr<IDBTransaction> transaction = aResultHelper->Transaction();
- if (transaction && transaction->IsAborted()) {
- DispatchErrorEvent(request, transaction->AbortCode(), transaction);
- return;
- }
- nsCOMPtr<nsIDOMEvent> successEvent;
- if (!aEvent) {
- successEvent = CreateGenericEvent(request,
- nsDependentString(kSuccessEventType),
- eDoesNotBubble,
- eNotCancelable);
- MOZ_ASSERT(successEvent);
- aEvent = successEvent;
- }
- request->SetResultCallback(aResultHelper);
- MOZ_ASSERT(aEvent);
- MOZ_ASSERT_IF(transaction, transaction->IsOpen());
- if (transaction) {
- IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: "
- "Firing %s event",
- "IndexedDB %s: C T[%lld] R[%llu]: %s",
- IDB_LOG_ID_STRING(),
- transaction->LoggingSerialNumber(),
- request->LoggingSerialNumber(),
- IDB_LOG_STRINGIFY(aEvent, kSuccessEventType));
- } else {
- IDB_LOG_MARK("IndexedDB %s: Child Request[%llu]: Firing %s event",
- "IndexedDB %s: C R[%llu]: %s",
- IDB_LOG_ID_STRING(),
- request->LoggingSerialNumber(),
- IDB_LOG_STRINGIFY(aEvent, kSuccessEventType));
- }
- bool dummy;
- nsresult rv = request->DispatchEvent(aEvent, &dummy);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return;
- }
- MOZ_ASSERT_IF(transaction,
- transaction->IsOpen() || transaction->IsAborted());
- WidgetEvent* internalEvent = aEvent->WidgetEventPtr();
- MOZ_ASSERT(internalEvent);
- if (transaction &&
- transaction->IsOpen() &&
- internalEvent->mFlags.mExceptionWasRaised) {
- transaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
- }
- }
- PRFileDesc*
- GetFileDescriptorFromStream(nsIInputStream* aStream)
- {
- MOZ_ASSERT(aStream);
- nsCOMPtr<nsIFileMetadata> fileMetadata = do_QueryInterface(aStream);
- if (NS_WARN_IF(!fileMetadata)) {
- return nullptr;
- }
- PRFileDesc* fileDesc;
- nsresult rv = fileMetadata->GetFileDescriptor(&fileDesc);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return nullptr;
- }
- MOZ_ASSERT(fileDesc);
- return fileDesc;
- }
- class WorkerPermissionChallenge;
- // This class calles WorkerPermissionChallenge::OperationCompleted() in the
- // worker thread.
- class WorkerPermissionOperationCompleted final : public WorkerControlRunnable
- {
- RefPtr<WorkerPermissionChallenge> mChallenge;
- public:
- WorkerPermissionOperationCompleted(WorkerPrivate* aWorkerPrivate,
- WorkerPermissionChallenge* aChallenge)
- : WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount)
- , mChallenge(aChallenge)
- {
- MOZ_ASSERT(NS_IsMainThread());
- }
- virtual bool
- WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override;
- };
- // This class used to do prompting in the main thread and main process.
- class WorkerPermissionRequest final : public PermissionRequestBase
- {
- RefPtr<WorkerPermissionChallenge> mChallenge;
- public:
- WorkerPermissionRequest(Element* aElement,
- nsIPrincipal* aPrincipal,
- WorkerPermissionChallenge* aChallenge)
- : PermissionRequestBase(aElement, aPrincipal)
- , mChallenge(aChallenge)
- {
- MOZ_ASSERT(XRE_IsParentProcess());
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(aChallenge);
- }
- private:
- ~WorkerPermissionRequest()
- {
- MOZ_ASSERT(NS_IsMainThread());
- }
- virtual void
- OnPromptComplete(PermissionValue aPermissionValue) override;
- };
- // This class is used in the main thread of all child processes.
- class WorkerPermissionRequestChildProcessActor final
- : public PIndexedDBPermissionRequestChild
- {
- RefPtr<WorkerPermissionChallenge> mChallenge;
- public:
- explicit WorkerPermissionRequestChildProcessActor(
- WorkerPermissionChallenge* aChallenge)
- : mChallenge(aChallenge)
- {
- MOZ_ASSERT(!XRE_IsParentProcess());
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(aChallenge);
- }
- protected:
- ~WorkerPermissionRequestChildProcessActor()
- {}
- virtual bool
- Recv__delete__(const uint32_t& aPermission) override;
- };
- class WorkerPermissionChallenge final : public Runnable
- {
- public:
- WorkerPermissionChallenge(WorkerPrivate* aWorkerPrivate,
- BackgroundFactoryRequestChild* aActor,
- IDBFactory* aFactory,
- const PrincipalInfo& aPrincipalInfo)
- : mWorkerPrivate(aWorkerPrivate)
- , mActor(aActor)
- , mFactory(aFactory)
- , mPrincipalInfo(aPrincipalInfo)
- {
- MOZ_ASSERT(mWorkerPrivate);
- MOZ_ASSERT(aActor);
- MOZ_ASSERT(aFactory);
- mWorkerPrivate->AssertIsOnWorkerThread();
- }
- bool
- Dispatch()
- {
- mWorkerPrivate->AssertIsOnWorkerThread();
- if (NS_WARN_IF(!mWorkerPrivate->ModifyBusyCountFromWorker(true))) {
- return false;
- }
- if (NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(this)))) {
- mWorkerPrivate->ModifyBusyCountFromWorker(false);
- return false;
- }
- return true;
- }
- NS_IMETHOD
- Run() override
- {
- bool completed = RunInternal();
- if (completed) {
- OperationCompleted();
- }
- return NS_OK;
- }
- void
- OperationCompleted()
- {
- if (NS_IsMainThread()) {
- RefPtr<WorkerPermissionOperationCompleted> runnable =
- new WorkerPermissionOperationCompleted(mWorkerPrivate, this);
- MOZ_ALWAYS_TRUE(runnable->Dispatch());
- return;
- }
- MOZ_ASSERT(mActor);
- mActor->AssertIsOnOwningThread();
- MaybeCollectGarbageOnIPCMessage();
- RefPtr<IDBFactory> factory;
- mFactory.swap(factory);
- mActor->SendPermissionRetry();
- mActor = nullptr;
- mWorkerPrivate->AssertIsOnWorkerThread();
- mWorkerPrivate->ModifyBusyCountFromWorker(false);
- }
- private:
- bool
- RunInternal()
- {
- MOZ_ASSERT(NS_IsMainThread());
- // Walk up to our containing page
- WorkerPrivate* wp = mWorkerPrivate;
- while (wp->GetParent()) {
- wp = wp->GetParent();
- }
- nsPIDOMWindowInner* window = wp->GetWindow();
- if (!window) {
- return true;
- }
- nsresult rv;
- nsCOMPtr<nsIPrincipal> principal =
- mozilla::ipc::PrincipalInfoToPrincipal(mPrincipalInfo, &rv);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return true;
- }
- if (XRE_IsParentProcess()) {
- nsCOMPtr<Element> ownerElement =
- do_QueryInterface(window->GetChromeEventHandler());
- if (NS_WARN_IF(!ownerElement)) {
- return true;
- }
- RefPtr<WorkerPermissionRequest> helper =
- new WorkerPermissionRequest(ownerElement, principal, this);
- PermissionRequestBase::PermissionValue permission;
- if (NS_WARN_IF(NS_FAILED(helper->PromptIfNeeded(&permission)))) {
- return true;
- }
- MOZ_ASSERT(permission == PermissionRequestBase::kPermissionAllowed ||
- permission == PermissionRequestBase::kPermissionDenied ||
- permission == PermissionRequestBase::kPermissionPrompt);
- return permission != PermissionRequestBase::kPermissionPrompt;
- }
- TabChild* tabChild = TabChild::GetFrom(window);
- MOZ_ASSERT(tabChild);
- IPC::Principal ipcPrincipal(principal);
- auto* actor = new WorkerPermissionRequestChildProcessActor(this);
- tabChild->SendPIndexedDBPermissionRequestConstructor(actor, ipcPrincipal);
- return false;
- }
- private:
- WorkerPrivate* mWorkerPrivate;
- BackgroundFactoryRequestChild* mActor;
- RefPtr<IDBFactory> mFactory;
- PrincipalInfo mPrincipalInfo;
- };
- void
- WorkerPermissionRequest::OnPromptComplete(PermissionValue aPermissionValue)
- {
- MOZ_ASSERT(NS_IsMainThread());
- mChallenge->OperationCompleted();
- }
- bool
- WorkerPermissionOperationCompleted::WorkerRun(JSContext* aCx,
- WorkerPrivate* aWorkerPrivate)
- {
- aWorkerPrivate->AssertIsOnWorkerThread();
- mChallenge->OperationCompleted();
- return true;
- }
- bool
- WorkerPermissionRequestChildProcessActor::Recv__delete__(
- const uint32_t& /* aPermission */)
- {
- MOZ_ASSERT(NS_IsMainThread());
- mChallenge->OperationCompleted();
- return true;
- }
- } // namespace
- /*******************************************************************************
- * Actor class declarations
- ******************************************************************************/
- // CancelableRunnable is used to make workers happy.
- class BackgroundRequestChild::PreprocessHelper final
- : public CancelableRunnable
- {
- typedef std::pair<nsCOMPtr<nsIInputStream>,
- nsCOMPtr<nsIInputStream>> StreamPair;
- nsCOMPtr<nsIEventTarget> mOwningThread;
- nsTArray<StreamPair> mStreamPairs;
- nsTArray<RefPtr<JS::WasmModule>> mModuleSet;
- BackgroundRequestChild* mActor;
- uint32_t mModuleSetIndex;
- nsresult mResultCode;
- public:
- PreprocessHelper(uint32_t aModuleSetIndex, BackgroundRequestChild* aActor)
- : mOwningThread(NS_GetCurrentThread())
- , mActor(aActor)
- , mModuleSetIndex(aModuleSetIndex)
- , mResultCode(NS_OK)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(aActor);
- aActor->AssertIsOnOwningThread();
- }
- bool
- IsOnOwningThread() const
- {
- MOZ_ASSERT(mOwningThread);
- bool current;
- return NS_SUCCEEDED(mOwningThread->IsOnCurrentThread(¤t)) && current;
- }
- void
- AssertIsOnOwningThread() const
- {
- MOZ_ASSERT(IsOnOwningThread());
- }
- void
- ClearActor()
- {
- AssertIsOnOwningThread();
- mActor = nullptr;
- }
- nsresult
- Init(const nsTArray<StructuredCloneFile>& aFiles);
- nsresult
- Dispatch();
- private:
- ~PreprocessHelper()
- { }
- void
- RunOnOwningThread();
- nsresult
- RunOnStreamTransportThread();
- NS_DECL_NSIRUNNABLE
- virtual nsresult
- Cancel() override;
- };
- /*******************************************************************************
- * Local class implementations
- ******************************************************************************/
- void
- PermissionRequestMainProcessHelper::OnPromptComplete(
- PermissionValue aPermissionValue)
- {
- MOZ_ASSERT(mActor);
- mActor->AssertIsOnOwningThread();
- MaybeCollectGarbageOnIPCMessage();
- mActor->SendPermissionRetry();
- mActor = nullptr;
- mFactory = nullptr;
- }
- bool
- PermissionRequestChildProcessActor::Recv__delete__(
- const uint32_t& /* aPermission */)
- {
- MOZ_ASSERT(mActor);
- mActor->AssertIsOnOwningThread();
- MOZ_ASSERT(mFactory);
- MaybeCollectGarbageOnIPCMessage();
- RefPtr<IDBFactory> factory;
- mFactory.swap(factory);
- mActor->SendPermissionRetry();
- mActor = nullptr;
- return true;
- }
- /*******************************************************************************
- * BackgroundRequestChildBase
- ******************************************************************************/
- BackgroundRequestChildBase::BackgroundRequestChildBase(IDBRequest* aRequest)
- : mRequest(aRequest)
- {
- MOZ_ASSERT(aRequest);
- aRequest->AssertIsOnOwningThread();
- MOZ_COUNT_CTOR(indexedDB::BackgroundRequestChildBase);
- }
- BackgroundRequestChildBase::~BackgroundRequestChildBase()
- {
- AssertIsOnOwningThread();
- MOZ_COUNT_DTOR(indexedDB::BackgroundRequestChildBase);
- }
- #ifdef DEBUG
- void
- BackgroundRequestChildBase::AssertIsOnOwningThread() const
- {
- MOZ_ASSERT(mRequest);
- mRequest->AssertIsOnOwningThread();
- }
- #endif // DEBUG
- /*******************************************************************************
- * BackgroundFactoryChild
- ******************************************************************************/
- BackgroundFactoryChild::BackgroundFactoryChild(IDBFactory* aFactory)
- : mFactory(aFactory)
- #ifdef DEBUG
- , mOwningThread(NS_GetCurrentThread())
- #endif
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(aFactory);
- aFactory->AssertIsOnOwningThread();
- MOZ_COUNT_CTOR(indexedDB::BackgroundFactoryChild);
- }
- BackgroundFactoryChild::~BackgroundFactoryChild()
- {
- MOZ_COUNT_DTOR(indexedDB::BackgroundFactoryChild);
- }
- #ifdef DEBUG
- void
- BackgroundFactoryChild::AssertIsOnOwningThread() const
- {
- MOZ_ASSERT(mOwningThread);
- bool current;
- MOZ_ASSERT(NS_SUCCEEDED(mOwningThread->IsOnCurrentThread(¤t)));
- MOZ_ASSERT(current);
- }
- nsIEventTarget*
- BackgroundFactoryChild::OwningThread() const
- {
- MOZ_ASSERT(mOwningThread);
- return mOwningThread;
- }
- #endif // DEBUG
- void
- BackgroundFactoryChild::SendDeleteMeInternal()
- {
- AssertIsOnOwningThread();
- if (mFactory) {
- mFactory->ClearBackgroundActor();
- mFactory = nullptr;
- MOZ_ALWAYS_TRUE(PBackgroundIDBFactoryChild::SendDeleteMe());
- }
- }
- void
- BackgroundFactoryChild::ActorDestroy(ActorDestroyReason aWhy)
- {
- AssertIsOnOwningThread();
- MaybeCollectGarbageOnIPCMessage();
- if (mFactory) {
- mFactory->ClearBackgroundActor();
- #ifdef DEBUG
- mFactory = nullptr;
- #endif
- }
- }
- PBackgroundIDBFactoryRequestChild*
- BackgroundFactoryChild::AllocPBackgroundIDBFactoryRequestChild(
- const FactoryRequestParams& aParams)
- {
- MOZ_CRASH("PBackgroundIDBFactoryRequestChild actors should be manually "
- "constructed!");
- }
- bool
- BackgroundFactoryChild::DeallocPBackgroundIDBFactoryRequestChild(
- PBackgroundIDBFactoryRequestChild* aActor)
- {
- MOZ_ASSERT(aActor);
- delete static_cast<BackgroundFactoryRequestChild*>(aActor);
- return true;
- }
- PBackgroundIDBDatabaseChild*
- BackgroundFactoryChild::AllocPBackgroundIDBDatabaseChild(
- const DatabaseSpec& aSpec,
- PBackgroundIDBFactoryRequestChild* aRequest)
- {
- AssertIsOnOwningThread();
- auto request = static_cast<BackgroundFactoryRequestChild*>(aRequest);
- MOZ_ASSERT(request);
- return new BackgroundDatabaseChild(aSpec, request);
- }
- bool
- BackgroundFactoryChild::DeallocPBackgroundIDBDatabaseChild(
- PBackgroundIDBDatabaseChild* aActor)
- {
- MOZ_ASSERT(aActor);
- delete static_cast<BackgroundDatabaseChild*>(aActor);
- return true;
- }
- /*******************************************************************************
- * BackgroundFactoryRequestChild
- ******************************************************************************/
- BackgroundFactoryRequestChild::BackgroundFactoryRequestChild(
- IDBFactory* aFactory,
- IDBOpenDBRequest* aOpenRequest,
- bool aIsDeleteOp,
- uint64_t aRequestedVersion)
- : BackgroundRequestChildBase(aOpenRequest)
- , mFactory(aFactory)
- , mRequestedVersion(aRequestedVersion)
- , mIsDeleteOp(aIsDeleteOp)
- {
- // Can't assert owning thread here because IPDL has not yet set our manager!
- MOZ_ASSERT(aFactory);
- aFactory->AssertIsOnOwningThread();
- MOZ_ASSERT(aOpenRequest);
- MOZ_COUNT_CTOR(indexedDB::BackgroundFactoryRequestChild);
- }
- BackgroundFactoryRequestChild::~BackgroundFactoryRequestChild()
- {
- MOZ_COUNT_DTOR(indexedDB::BackgroundFactoryRequestChild);
- }
- IDBOpenDBRequest*
- BackgroundFactoryRequestChild::GetOpenDBRequest() const
- {
- AssertIsOnOwningThread();
- return static_cast<IDBOpenDBRequest*>(mRequest.get());
- }
- bool
- BackgroundFactoryRequestChild::HandleResponse(nsresult aResponse)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(NS_FAILED(aResponse));
- MOZ_ASSERT(NS_ERROR_GET_MODULE(aResponse) == NS_ERROR_MODULE_DOM_INDEXEDDB);
- mRequest->Reset();
- DispatchErrorEvent(mRequest, aResponse);
- return true;
- }
- bool
- BackgroundFactoryRequestChild::HandleResponse(
- const OpenDatabaseRequestResponse& aResponse)
- {
- AssertIsOnOwningThread();
- mRequest->Reset();
- auto databaseActor =
- static_cast<BackgroundDatabaseChild*>(aResponse.databaseChild());
- MOZ_ASSERT(databaseActor);
- IDBDatabase* database = databaseActor->GetDOMObject();
- if (!database) {
- databaseActor->EnsureDOMObject();
- database = databaseActor->GetDOMObject();
- MOZ_ASSERT(database);
- MOZ_ASSERT(!database->IsClosed());
- }
- if (database->IsClosed()) {
- // If the database was closed already, which is only possible if we fired an
- // "upgradeneeded" event, then we shouldn't fire a "success" event here.
- // Instead we fire an error event with AbortErr.
- DispatchErrorEvent(mRequest, NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
- } else {
- ResultHelper helper(mRequest, nullptr, database);
- DispatchSuccessEvent(&helper);
- }
- databaseActor->ReleaseDOMObject();
- return true;
- }
- bool
- BackgroundFactoryRequestChild::HandleResponse(
- const DeleteDatabaseRequestResponse& aResponse)
- {
- AssertIsOnOwningThread();
- ResultHelper helper(mRequest, nullptr, &JS::UndefinedHandleValue);
- nsCOMPtr<nsIDOMEvent> successEvent =
- IDBVersionChangeEvent::Create(mRequest,
- nsDependentString(kSuccessEventType),
- aResponse.previousVersion());
- MOZ_ASSERT(successEvent);
- DispatchSuccessEvent(&helper, successEvent);
- return true;
- }
- void
- BackgroundFactoryRequestChild::ActorDestroy(ActorDestroyReason aWhy)
- {
- AssertIsOnOwningThread();
- MaybeCollectGarbageOnIPCMessage();
- if (aWhy != Deletion) {
- IDBOpenDBRequest* openRequest = GetOpenDBRequest();
- if (openRequest) {
- openRequest->NoteComplete();
- }
- }
- }
- bool
- BackgroundFactoryRequestChild::Recv__delete__(
- const FactoryRequestResponse& aResponse)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(mRequest);
- MaybeCollectGarbageOnIPCMessage();
- bool result;
- switch (aResponse.type()) {
- case FactoryRequestResponse::Tnsresult:
- result = HandleResponse(aResponse.get_nsresult());
- break;
- case FactoryRequestResponse::TOpenDatabaseRequestResponse:
- result = HandleResponse(aResponse.get_OpenDatabaseRequestResponse());
- break;
- case FactoryRequestResponse::TDeleteDatabaseRequestResponse:
- result = HandleResponse(aResponse.get_DeleteDatabaseRequestResponse());
- break;
- default:
- MOZ_CRASH("Unknown response type!");
- }
- IDBOpenDBRequest* request = GetOpenDBRequest();
- MOZ_ASSERT(request);
- request->NoteComplete();
- if (NS_WARN_IF(!result)) {
- return false;
- }
- return true;
- }
- bool
- BackgroundFactoryRequestChild::RecvPermissionChallenge(
- const PrincipalInfo& aPrincipalInfo)
- {
- AssertIsOnOwningThread();
- MaybeCollectGarbageOnIPCMessage();
- if (!NS_IsMainThread()) {
- WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
- MOZ_ASSERT(workerPrivate);
- workerPrivate->AssertIsOnWorkerThread();
- RefPtr<WorkerPermissionChallenge> challenge =
- new WorkerPermissionChallenge(workerPrivate, this, mFactory,
- aPrincipalInfo);
- return challenge->Dispatch();
- }
- nsresult rv;
- nsCOMPtr<nsIPrincipal> principal =
- mozilla::ipc::PrincipalInfoToPrincipal(aPrincipalInfo, &rv);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return false;
- }
- if (XRE_IsParentProcess()) {
- nsCOMPtr<nsPIDOMWindowInner> window = mFactory->GetParentObject();
- MOZ_ASSERT(window);
- nsCOMPtr<Element> ownerElement =
- do_QueryInterface(window->GetChromeEventHandler());
- if (NS_WARN_IF(!ownerElement)) {
- // If this fails, the page was navigated. Fail the permission check by
- // forcing an immediate retry.
- return SendPermissionRetry();
- }
- RefPtr<PermissionRequestMainProcessHelper> helper =
- new PermissionRequestMainProcessHelper(this, mFactory, ownerElement, principal);
- PermissionRequestBase::PermissionValue permission;
- if (NS_WARN_IF(NS_FAILED(helper->PromptIfNeeded(&permission)))) {
- return false;
- }
- MOZ_ASSERT(permission == PermissionRequestBase::kPermissionAllowed ||
- permission == PermissionRequestBase::kPermissionDenied ||
- permission == PermissionRequestBase::kPermissionPrompt);
- if (permission != PermissionRequestBase::kPermissionPrompt) {
- SendPermissionRetry();
- }
- return true;
- }
- RefPtr<TabChild> tabChild = mFactory->GetTabChild();
- MOZ_ASSERT(tabChild);
- IPC::Principal ipcPrincipal(principal);
- auto* actor = new PermissionRequestChildProcessActor(this, mFactory);
- tabChild->SendPIndexedDBPermissionRequestConstructor(actor, ipcPrincipal);
- return true;
- }
- bool
- BackgroundFactoryRequestChild::RecvBlocked(const uint64_t& aCurrentVersion)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(mRequest);
- MaybeCollectGarbageOnIPCMessage();
- const nsDependentString type(kBlockedEventType);
- nsCOMPtr<nsIDOMEvent> blockedEvent;
- if (mIsDeleteOp) {
- blockedEvent =
- IDBVersionChangeEvent::Create(mRequest, type, aCurrentVersion);
- MOZ_ASSERT(blockedEvent);
- } else {
- blockedEvent =
- IDBVersionChangeEvent::Create(mRequest,
- type,
- aCurrentVersion,
- mRequestedVersion);
- MOZ_ASSERT(blockedEvent);
- }
- RefPtr<IDBRequest> kungFuDeathGrip = mRequest;
- IDB_LOG_MARK("IndexedDB %s: Child Request[%llu]: Firing \"blocked\" event",
- "IndexedDB %s: C R[%llu]: \"blocked\"",
- IDB_LOG_ID_STRING(),
- kungFuDeathGrip->LoggingSerialNumber());
- bool dummy;
- if (NS_FAILED(kungFuDeathGrip->DispatchEvent(blockedEvent, &dummy))) {
- NS_WARNING("Failed to dispatch event!");
- }
- return true;
- }
- /*******************************************************************************
- * BackgroundDatabaseChild
- ******************************************************************************/
- BackgroundDatabaseChild::BackgroundDatabaseChild(
- const DatabaseSpec& aSpec,
- BackgroundFactoryRequestChild* aOpenRequestActor)
- : mSpec(new DatabaseSpec(aSpec))
- , mOpenRequestActor(aOpenRequestActor)
- , mDatabase(nullptr)
- {
- // Can't assert owning thread here because IPDL has not yet set our manager!
- MOZ_ASSERT(aOpenRequestActor);
- MOZ_COUNT_CTOR(indexedDB::BackgroundDatabaseChild);
- }
- BackgroundDatabaseChild::~BackgroundDatabaseChild()
- {
- MOZ_COUNT_DTOR(indexedDB::BackgroundDatabaseChild);
- }
- void
- BackgroundDatabaseChild::SendDeleteMeInternal()
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(!mTemporaryStrongDatabase);
- MOZ_ASSERT(!mOpenRequestActor);
- if (mDatabase) {
- mDatabase->ClearBackgroundActor();
- mDatabase = nullptr;
- MOZ_ALWAYS_TRUE(PBackgroundIDBDatabaseChild::SendDeleteMe());
- }
- }
- void
- BackgroundDatabaseChild::EnsureDOMObject()
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(mOpenRequestActor);
- if (mTemporaryStrongDatabase) {
- MOZ_ASSERT(!mSpec);
- return;
- }
- MOZ_ASSERT(mSpec);
- auto request = mOpenRequestActor->GetOpenDBRequest();
- MOZ_ASSERT(request);
- auto factory =
- static_cast<BackgroundFactoryChild*>(Manager())->GetDOMObject();
- MOZ_ASSERT(factory);
- mTemporaryStrongDatabase =
- IDBDatabase::Create(request, factory, this, mSpec);
- MOZ_ASSERT(mTemporaryStrongDatabase);
- mTemporaryStrongDatabase->AssertIsOnOwningThread();
- mDatabase = mTemporaryStrongDatabase;
- mSpec.forget();
- }
- void
- BackgroundDatabaseChild::ReleaseDOMObject()
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(mTemporaryStrongDatabase);
- mTemporaryStrongDatabase->AssertIsOnOwningThread();
- MOZ_ASSERT(mOpenRequestActor);
- MOZ_ASSERT(mDatabase == mTemporaryStrongDatabase);
- mOpenRequestActor = nullptr;
- // This may be the final reference to the IDBDatabase object so we may end up
- // calling SendDeleteMeInternal() here. Make sure everything is cleaned up
- // properly before proceeding.
- mTemporaryStrongDatabase = nullptr;
- }
- void
- BackgroundDatabaseChild::ActorDestroy(ActorDestroyReason aWhy)
- {
- AssertIsOnOwningThread();
- MaybeCollectGarbageOnIPCMessage();
- if (mDatabase) {
- mDatabase->ClearBackgroundActor();
- #ifdef DEBUG
- mDatabase = nullptr;
- #endif
- }
- }
- PBackgroundIDBDatabaseFileChild*
- BackgroundDatabaseChild::AllocPBackgroundIDBDatabaseFileChild(
- PBlobChild* aBlobChild)
- {
- MOZ_CRASH("PBackgroundIDBFileChild actors should be manually constructed!");
- }
- bool
- BackgroundDatabaseChild::DeallocPBackgroundIDBDatabaseFileChild(
- PBackgroundIDBDatabaseFileChild* aActor)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(aActor);
- delete aActor;
- return true;
- }
- PBackgroundIDBDatabaseRequestChild*
- BackgroundDatabaseChild::AllocPBackgroundIDBDatabaseRequestChild(
- const DatabaseRequestParams& aParams)
- {
- MOZ_CRASH("PBackgroundIDBDatabaseRequestChild actors should be manually "
- "constructed!");
- }
- bool
- BackgroundDatabaseChild::DeallocPBackgroundIDBDatabaseRequestChild(
- PBackgroundIDBDatabaseRequestChild* aActor)
- {
- MOZ_ASSERT(aActor);
- delete static_cast<BackgroundDatabaseRequestChild*>(aActor);
- return true;
- }
- PBackgroundIDBTransactionChild*
- BackgroundDatabaseChild::AllocPBackgroundIDBTransactionChild(
- const nsTArray<nsString>& aObjectStoreNames,
- const Mode& aMode)
- {
- MOZ_CRASH("PBackgroundIDBTransactionChild actors should be manually "
- "constructed!");
- }
- bool
- BackgroundDatabaseChild::DeallocPBackgroundIDBTransactionChild(
- PBackgroundIDBTransactionChild* aActor)
- {
- MOZ_ASSERT(aActor);
- delete static_cast<BackgroundTransactionChild*>(aActor);
- return true;
- }
- PBackgroundIDBVersionChangeTransactionChild*
- BackgroundDatabaseChild::AllocPBackgroundIDBVersionChangeTransactionChild(
- const uint64_t& aCurrentVersion,
- const uint64_t& aRequestedVersion,
- const int64_t& aNextObjectStoreId,
- const int64_t& aNextIndexId)
- {
- AssertIsOnOwningThread();
- IDBOpenDBRequest* request = mOpenRequestActor->GetOpenDBRequest();
- MOZ_ASSERT(request);
- return new BackgroundVersionChangeTransactionChild(request);
- }
- bool
- BackgroundDatabaseChild::RecvPBackgroundIDBVersionChangeTransactionConstructor(
- PBackgroundIDBVersionChangeTransactionChild* aActor,
- const uint64_t& aCurrentVersion,
- const uint64_t& aRequestedVersion,
- const int64_t& aNextObjectStoreId,
- const int64_t& aNextIndexId)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(aActor);
- MOZ_ASSERT(mOpenRequestActor);
- MaybeCollectGarbageOnIPCMessage();
- EnsureDOMObject();
- auto* actor = static_cast<BackgroundVersionChangeTransactionChild*>(aActor);
- RefPtr<IDBOpenDBRequest> request = mOpenRequestActor->GetOpenDBRequest();
- MOZ_ASSERT(request);
- RefPtr<IDBTransaction> transaction =
- IDBTransaction::CreateVersionChange(mDatabase,
- actor,
- request,
- aNextObjectStoreId,
- aNextIndexId);
- if (NS_WARN_IF(!transaction)) {
- // This can happen if we receive events after a worker has begun its
- // shutdown process.
- MOZ_ASSERT(!NS_IsMainThread());
- // Report this to the console.
- IDB_REPORT_INTERNAL_ERR();
- MOZ_ALWAYS_TRUE(aActor->SendDeleteMe());
- return true;
- }
- transaction->AssertIsOnOwningThread();
- actor->SetDOMTransaction(transaction);
- mDatabase->EnterSetVersionTransaction(aRequestedVersion);
- request->SetTransaction(transaction);
- nsCOMPtr<nsIDOMEvent> upgradeNeededEvent =
- IDBVersionChangeEvent::Create(request,
- nsDependentString(kUpgradeNeededEventType),
- aCurrentVersion,
- aRequestedVersion);
- MOZ_ASSERT(upgradeNeededEvent);
- ResultHelper helper(request, transaction, mDatabase);
- DispatchSuccessEvent(&helper, upgradeNeededEvent);
- return true;
- }
- bool
- BackgroundDatabaseChild::DeallocPBackgroundIDBVersionChangeTransactionChild(
- PBackgroundIDBVersionChangeTransactionChild* aActor)
- {
- MOZ_ASSERT(aActor);
- delete static_cast<BackgroundVersionChangeTransactionChild*>(aActor);
- return true;
- }
- PBackgroundMutableFileChild*
- BackgroundDatabaseChild::AllocPBackgroundMutableFileChild(const nsString& aName,
- const nsString& aType)
- {
- AssertIsOnOwningThread();
- #ifdef DEBUG
- nsCOMPtr<nsIThread> owningThread = do_QueryInterface(OwningThread());
- PRThread* owningPRThread;
- owningThread->GetPRThread(&owningPRThread);
- #endif
- return new BackgroundMutableFileChild(DEBUGONLY(owningPRThread,)
- aName,
- aType);
- }
- bool
- BackgroundDatabaseChild::DeallocPBackgroundMutableFileChild(
- PBackgroundMutableFileChild* aActor)
- {
- MOZ_ASSERT(aActor);
- delete static_cast<BackgroundMutableFileChild*>(aActor);
- return true;
- }
- bool
- BackgroundDatabaseChild::RecvVersionChange(const uint64_t& aOldVersion,
- const NullableVersion& aNewVersion)
- {
- AssertIsOnOwningThread();
- MaybeCollectGarbageOnIPCMessage();
- if (!mDatabase || mDatabase->IsClosed()) {
- return true;
- }
- RefPtr<IDBDatabase> kungFuDeathGrip = mDatabase;
- // Handle bfcache'd windows.
- if (nsPIDOMWindowInner* owner = kungFuDeathGrip->GetOwner()) {
- // The database must be closed if the window is already frozen.
- bool shouldAbortAndClose = owner->IsFrozen();
- // Anything in the bfcache has to be evicted and then we have to close the
- // database also.
- if (nsCOMPtr<nsIDocument> doc = owner->GetExtantDoc()) {
- if (nsCOMPtr<nsIBFCacheEntry> bfCacheEntry = doc->GetBFCacheEntry()) {
- bfCacheEntry->RemoveFromBFCacheSync();
- shouldAbortAndClose = true;
- }
- }
- if (shouldAbortAndClose) {
- // Invalidate() doesn't close the database in the parent, so we have
- // to call Close() and AbortTransactions() manually.
- kungFuDeathGrip->AbortTransactions(/* aShouldWarn */ false);
- kungFuDeathGrip->Close();
- return true;
- }
- }
- // Otherwise fire a versionchange event.
- const nsDependentString type(kVersionChangeEventType);
- nsCOMPtr<nsIDOMEvent> versionChangeEvent;
- switch (aNewVersion.type()) {
- case NullableVersion::Tnull_t:
- versionChangeEvent =
- IDBVersionChangeEvent::Create(kungFuDeathGrip, type, aOldVersion);
- MOZ_ASSERT(versionChangeEvent);
- break;
- case NullableVersion::Tuint64_t:
- versionChangeEvent =
- IDBVersionChangeEvent::Create(kungFuDeathGrip,
- type,
- aOldVersion,
- aNewVersion.get_uint64_t());
- MOZ_ASSERT(versionChangeEvent);
- break;
- default:
- MOZ_CRASH("Should never get here!");
- }
- IDB_LOG_MARK("IndexedDB %s: Child : Firing \"versionchange\" event",
- "IndexedDB %s: C: IDBDatabase \"versionchange\" event",
- IDB_LOG_ID_STRING());
- bool dummy;
- if (NS_FAILED(kungFuDeathGrip->DispatchEvent(versionChangeEvent, &dummy))) {
- NS_WARNING("Failed to dispatch event!");
- }
- if (!kungFuDeathGrip->IsClosed()) {
- SendBlocked();
- }
- return true;
- }
- bool
- BackgroundDatabaseChild::RecvInvalidate()
- {
- AssertIsOnOwningThread();
- MaybeCollectGarbageOnIPCMessage();
- if (mDatabase) {
- mDatabase->Invalidate();
- }
- return true;
- }
- bool
- BackgroundDatabaseChild::RecvCloseAfterInvalidationComplete()
- {
- AssertIsOnOwningThread();
- MaybeCollectGarbageOnIPCMessage();
- if (mDatabase) {
- mDatabase->DispatchTrustedEvent(nsDependentString(kCloseEventType));
- }
- return true;
- }
- /*******************************************************************************
- * BackgroundDatabaseRequestChild
- ******************************************************************************/
- BackgroundDatabaseRequestChild::BackgroundDatabaseRequestChild(
- IDBDatabase* aDatabase,
- IDBRequest* aRequest)
- : BackgroundRequestChildBase(aRequest)
- , mDatabase(aDatabase)
- {
- // Can't assert owning thread here because IPDL has not yet set our manager!
- MOZ_ASSERT(aDatabase);
- aDatabase->AssertIsOnOwningThread();
- MOZ_ASSERT(aRequest);
- MOZ_COUNT_CTOR(indexedDB::BackgroundDatabaseRequestChild);
- }
- BackgroundDatabaseRequestChild::~BackgroundDatabaseRequestChild()
- {
- MOZ_COUNT_DTOR(indexedDB::BackgroundDatabaseRequestChild);
- }
- bool
- BackgroundDatabaseRequestChild::HandleResponse(nsresult aResponse)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(NS_FAILED(aResponse));
- MOZ_ASSERT(NS_ERROR_GET_MODULE(aResponse) == NS_ERROR_MODULE_DOM_INDEXEDDB);
- mRequest->Reset();
- DispatchErrorEvent(mRequest, aResponse);
- return true;
- }
- bool
- BackgroundDatabaseRequestChild::HandleResponse(
- const CreateFileRequestResponse& aResponse)
- {
- AssertIsOnOwningThread();
- mRequest->Reset();
- auto mutableFileActor =
- static_cast<BackgroundMutableFileChild*>(aResponse.mutableFileChild());
- MOZ_ASSERT(mutableFileActor);
- mutableFileActor->EnsureDOMObject();
- auto mutableFile =
- static_cast<IDBMutableFile*>(mutableFileActor->GetDOMObject());
- MOZ_ASSERT(mutableFile);
- ResultHelper helper(mRequest, nullptr, mutableFile);
- DispatchSuccessEvent(&helper);
- mutableFileActor->ReleaseDOMObject();
- return true;
- }
- bool
- BackgroundDatabaseRequestChild::Recv__delete__(
- const DatabaseRequestResponse& aResponse)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(mRequest);
- switch (aResponse.type()) {
- case DatabaseRequestResponse::Tnsresult:
- return HandleResponse(aResponse.get_nsresult());
- case DatabaseRequestResponse::TCreateFileRequestResponse:
- return HandleResponse(aResponse.get_CreateFileRequestResponse());
- default:
- MOZ_CRASH("Unknown response type!");
- }
- MOZ_CRASH("Should never get here!");
- }
- /*******************************************************************************
- * BackgroundTransactionBase
- ******************************************************************************/
- BackgroundTransactionBase::BackgroundTransactionBase()
- : mTransaction(nullptr)
- {
- MOZ_COUNT_CTOR(indexedDB::BackgroundTransactionBase);
- }
- BackgroundTransactionBase::BackgroundTransactionBase(
- IDBTransaction* aTransaction)
- : mTemporaryStrongTransaction(aTransaction)
- , mTransaction(aTransaction)
- {
- MOZ_ASSERT(aTransaction);
- aTransaction->AssertIsOnOwningThread();
- MOZ_COUNT_CTOR(indexedDB::BackgroundTransactionBase);
- }
- BackgroundTransactionBase::~BackgroundTransactionBase()
- {
- MOZ_COUNT_DTOR(indexedDB::BackgroundTransactionBase);
- }
- #ifdef DEBUG
- void
- BackgroundTransactionBase::AssertIsOnOwningThread() const
- {
- MOZ_ASSERT(mTransaction);
- mTransaction->AssertIsOnOwningThread();
- }
- #endif // DEBUG
- void
- BackgroundTransactionBase::NoteActorDestroyed()
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT_IF(mTemporaryStrongTransaction, mTransaction);
- if (mTransaction) {
- mTransaction->ClearBackgroundActor();
- // Normally this would be DEBUG-only but NoteActorDestroyed is also called
- // from SendDeleteMeInternal. In that case we're going to receive an actual
- // ActorDestroy call later and we don't want to touch a dead object.
- mTemporaryStrongTransaction = nullptr;
- mTransaction = nullptr;
- }
- }
- void
- BackgroundTransactionBase::SetDOMTransaction(IDBTransaction* aTransaction)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(aTransaction);
- aTransaction->AssertIsOnOwningThread();
- MOZ_ASSERT(!mTemporaryStrongTransaction);
- MOZ_ASSERT(!mTransaction);
- mTemporaryStrongTransaction = aTransaction;
- mTransaction = aTransaction;
- }
- void
- BackgroundTransactionBase::NoteComplete()
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT_IF(mTransaction, mTemporaryStrongTransaction);
- mTemporaryStrongTransaction = nullptr;
- }
- /*******************************************************************************
- * BackgroundTransactionChild
- ******************************************************************************/
- BackgroundTransactionChild::BackgroundTransactionChild(
- IDBTransaction* aTransaction)
- : BackgroundTransactionBase(aTransaction)
- {
- MOZ_ASSERT(aTransaction);
- aTransaction->AssertIsOnOwningThread();
- MOZ_COUNT_CTOR(indexedDB::BackgroundTransactionChild);
- }
- BackgroundTransactionChild::~BackgroundTransactionChild()
- {
- MOZ_COUNT_DTOR(indexedDB::BackgroundTransactionChild);
- }
- #ifdef DEBUG
- void
- BackgroundTransactionChild::AssertIsOnOwningThread() const
- {
- static_cast<BackgroundDatabaseChild*>(Manager())->AssertIsOnOwningThread();
- }
- #endif // DEBUG
- void
- BackgroundTransactionChild::SendDeleteMeInternal()
- {
- AssertIsOnOwningThread();
- if (mTransaction) {
- NoteActorDestroyed();
- MOZ_ALWAYS_TRUE(PBackgroundIDBTransactionChild::SendDeleteMe());
- }
- }
- void
- BackgroundTransactionChild::ActorDestroy(ActorDestroyReason aWhy)
- {
- AssertIsOnOwningThread();
- MaybeCollectGarbageOnIPCMessage();
- NoteActorDestroyed();
- }
- bool
- BackgroundTransactionChild::RecvComplete(const nsresult& aResult)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(mTransaction);
- MaybeCollectGarbageOnIPCMessage();
- mTransaction->FireCompleteOrAbortEvents(aResult);
- NoteComplete();
- return true;
- }
- PBackgroundIDBRequestChild*
- BackgroundTransactionChild::AllocPBackgroundIDBRequestChild(
- const RequestParams& aParams)
- {
- MOZ_CRASH("PBackgroundIDBRequestChild actors should be manually "
- "constructed!");
- }
- bool
- BackgroundTransactionChild::DeallocPBackgroundIDBRequestChild(
- PBackgroundIDBRequestChild* aActor)
- {
- MOZ_ASSERT(aActor);
- delete static_cast<BackgroundRequestChild*>(aActor);
- return true;
- }
- PBackgroundIDBCursorChild*
- BackgroundTransactionChild::AllocPBackgroundIDBCursorChild(
- const OpenCursorParams& aParams)
- {
- AssertIsOnOwningThread();
- MOZ_CRASH("PBackgroundIDBCursorChild actors should be manually constructed!");
- }
- bool
- BackgroundTransactionChild::DeallocPBackgroundIDBCursorChild(
- PBackgroundIDBCursorChild* aActor)
- {
- MOZ_ASSERT(aActor);
- delete static_cast<BackgroundCursorChild*>(aActor);
- return true;
- }
- /*******************************************************************************
- * BackgroundVersionChangeTransactionChild
- ******************************************************************************/
- BackgroundVersionChangeTransactionChild::
- BackgroundVersionChangeTransactionChild(IDBOpenDBRequest* aOpenDBRequest)
- : mOpenDBRequest(aOpenDBRequest)
- {
- MOZ_ASSERT(aOpenDBRequest);
- aOpenDBRequest->AssertIsOnOwningThread();
- MOZ_COUNT_CTOR(indexedDB::BackgroundVersionChangeTransactionChild);
- }
- BackgroundVersionChangeTransactionChild::
- ~BackgroundVersionChangeTransactionChild()
- {
- AssertIsOnOwningThread();
- MOZ_COUNT_DTOR(indexedDB::BackgroundVersionChangeTransactionChild);
- }
- #ifdef DEBUG
- void
- BackgroundVersionChangeTransactionChild::AssertIsOnOwningThread() const
- {
- static_cast<BackgroundDatabaseChild*>(Manager())->AssertIsOnOwningThread();
- }
- #endif // DEBUG
- void
- BackgroundVersionChangeTransactionChild::SendDeleteMeInternal(
- bool aFailedConstructor)
- {
- AssertIsOnOwningThread();
- if (mTransaction || aFailedConstructor) {
- NoteActorDestroyed();
- MOZ_ALWAYS_TRUE(PBackgroundIDBVersionChangeTransactionChild::
- SendDeleteMe());
- }
- }
- void
- BackgroundVersionChangeTransactionChild::ActorDestroy(ActorDestroyReason aWhy)
- {
- AssertIsOnOwningThread();
- MaybeCollectGarbageOnIPCMessage();
- mOpenDBRequest = nullptr;
- NoteActorDestroyed();
- }
- bool
- BackgroundVersionChangeTransactionChild::RecvComplete(const nsresult& aResult)
- {
- AssertIsOnOwningThread();
- MaybeCollectGarbageOnIPCMessage();
- if (!mTransaction) {
- return true;
- }
- MOZ_ASSERT(mOpenDBRequest);
- IDBDatabase* database = mTransaction->Database();
- MOZ_ASSERT(database);
- database->ExitSetVersionTransaction();
- if (NS_FAILED(aResult)) {
- database->Close();
- }
- RefPtr<IDBOpenDBRequest> request = mOpenDBRequest;
- MOZ_ASSERT(request);
- mTransaction->FireCompleteOrAbortEvents(aResult);
- request->SetTransaction(nullptr);
- request = nullptr;
- mOpenDBRequest = nullptr;
- NoteComplete();
- return true;
- }
- PBackgroundIDBRequestChild*
- BackgroundVersionChangeTransactionChild::AllocPBackgroundIDBRequestChild(
- const RequestParams& aParams)
- {
- MOZ_CRASH("PBackgroundIDBRequestChild actors should be manually "
- "constructed!");
- }
- bool
- BackgroundVersionChangeTransactionChild::DeallocPBackgroundIDBRequestChild(
- PBackgroundIDBRequestChild* aActor)
- {
- MOZ_ASSERT(aActor);
- delete static_cast<BackgroundRequestChild*>(aActor);
- return true;
- }
- PBackgroundIDBCursorChild*
- BackgroundVersionChangeTransactionChild::AllocPBackgroundIDBCursorChild(
- const OpenCursorParams& aParams)
- {
- AssertIsOnOwningThread();
- MOZ_CRASH("PBackgroundIDBCursorChild actors should be manually constructed!");
- }
- bool
- BackgroundVersionChangeTransactionChild::DeallocPBackgroundIDBCursorChild(
- PBackgroundIDBCursorChild* aActor)
- {
- MOZ_ASSERT(aActor);
- delete static_cast<BackgroundCursorChild*>(aActor);
- return true;
- }
- /*******************************************************************************
- * BackgroundMutableFileChild
- ******************************************************************************/
- BackgroundMutableFileChild::BackgroundMutableFileChild(
- DEBUGONLY(PRThread* aOwningThread,)
- const nsAString& aName,
- const nsAString& aType)
- : BackgroundMutableFileChildBase(DEBUGONLY(aOwningThread))
- , mName(aName)
- , mType(aType)
- {
- // Can't assert owning thread here because IPDL has not yet set our manager!
- MOZ_COUNT_CTOR(indexedDB::BackgroundMutableFileChild);
- }
- BackgroundMutableFileChild::~BackgroundMutableFileChild()
- {
- MOZ_COUNT_DTOR(indexedDB::BackgroundMutableFileChild);
- }
- already_AddRefed<MutableFileBase>
- BackgroundMutableFileChild::CreateMutableFile()
- {
- auto database =
- static_cast<BackgroundDatabaseChild*>(Manager())->GetDOMObject();
- MOZ_ASSERT(database);
- RefPtr<IDBMutableFile> mutableFile =
- new IDBMutableFile(database, this, mName, mType);
- return mutableFile.forget();
- }
- /*******************************************************************************
- * BackgroundRequestChild
- ******************************************************************************/
- BackgroundRequestChild::BackgroundRequestChild(IDBRequest* aRequest)
- : BackgroundRequestChildBase(aRequest)
- , mTransaction(aRequest->GetTransaction())
- , mRunningPreprocessHelpers(0)
- , mCurrentModuleSetIndex(0)
- , mPreprocessResultCode(NS_OK)
- , mGetAll(false)
- {
- MOZ_ASSERT(mTransaction);
- mTransaction->AssertIsOnOwningThread();
- MOZ_COUNT_CTOR(indexedDB::BackgroundRequestChild);
- }
- BackgroundRequestChild::~BackgroundRequestChild()
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(!mTransaction);
- MOZ_COUNT_DTOR(indexedDB::BackgroundRequestChild);
- }
- void
- BackgroundRequestChild::MaybeSendContinue()
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(mRunningPreprocessHelpers > 0);
- if (--mRunningPreprocessHelpers == 0) {
- PreprocessResponse response;
- if (NS_SUCCEEDED(mPreprocessResultCode)) {
- if (mGetAll) {
- response = ObjectStoreGetAllPreprocessResponse();
- } else {
- response = ObjectStoreGetPreprocessResponse();
- }
- } else {
- response = mPreprocessResultCode;
- }
- MOZ_ALWAYS_TRUE(SendContinue(response));
- }
- }
- void
- BackgroundRequestChild::OnPreprocessFinished(
- uint32_t aModuleSetIndex,
- nsTArray<RefPtr<JS::WasmModule>>& aModuleSet)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(aModuleSetIndex < mPreprocessHelpers.Length());
- MOZ_ASSERT(!aModuleSet.IsEmpty());
- MOZ_ASSERT(mPreprocessHelpers[aModuleSetIndex]);
- MOZ_ASSERT(mModuleSets[aModuleSetIndex].IsEmpty());
- mModuleSets[aModuleSetIndex].SwapElements(aModuleSet);
- MaybeSendContinue();
- mPreprocessHelpers[aModuleSetIndex] = nullptr;
- }
- void
- BackgroundRequestChild::OnPreprocessFailed(uint32_t aModuleSetIndex,
- nsresult aErrorCode)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(aModuleSetIndex < mPreprocessHelpers.Length());
- MOZ_ASSERT(NS_FAILED(aErrorCode));
- MOZ_ASSERT(mPreprocessHelpers[aModuleSetIndex]);
- MOZ_ASSERT(mModuleSets[aModuleSetIndex].IsEmpty());
- if (NS_SUCCEEDED(mPreprocessResultCode)) {
- mPreprocessResultCode = aErrorCode;
- }
- MaybeSendContinue();
- mPreprocessHelpers[aModuleSetIndex] = nullptr;
- }
- const nsTArray<RefPtr<JS::WasmModule>>*
- BackgroundRequestChild::GetNextModuleSet(const StructuredCloneReadInfo& aInfo)
- {
- if (!aInfo.mHasPreprocessInfo) {
- return nullptr;
- }
- MOZ_ASSERT(mCurrentModuleSetIndex < mModuleSets.Length());
- MOZ_ASSERT(!mModuleSets[mCurrentModuleSetIndex].IsEmpty());
- return &mModuleSets[mCurrentModuleSetIndex++];
- }
- void
- BackgroundRequestChild::HandleResponse(nsresult aResponse)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(NS_FAILED(aResponse));
- MOZ_ASSERT(NS_ERROR_GET_MODULE(aResponse) == NS_ERROR_MODULE_DOM_INDEXEDDB);
- MOZ_ASSERT(mTransaction);
- DispatchErrorEvent(mRequest, aResponse, mTransaction);
- }
- void
- BackgroundRequestChild::HandleResponse(const Key& aResponse)
- {
- AssertIsOnOwningThread();
- ResultHelper helper(mRequest, mTransaction, &aResponse);
- DispatchSuccessEvent(&helper);
- }
- void
- BackgroundRequestChild::HandleResponse(const nsTArray<Key>& aResponse)
- {
- AssertIsOnOwningThread();
- ResultHelper helper(mRequest, mTransaction, &aResponse);
- DispatchSuccessEvent(&helper);
- }
- void
- BackgroundRequestChild::HandleResponse(
- const SerializedStructuredCloneReadInfo& aResponse)
- {
- AssertIsOnOwningThread();
- // XXX Fix this somehow...
- auto& serializedCloneInfo =
- const_cast<SerializedStructuredCloneReadInfo&>(aResponse);
- StructuredCloneReadInfo cloneReadInfo(Move(serializedCloneInfo));
- DeserializeStructuredCloneFiles(mTransaction->Database(),
- aResponse.files(),
- GetNextModuleSet(cloneReadInfo),
- cloneReadInfo.mFiles);
- ResultHelper helper(mRequest, mTransaction, &cloneReadInfo);
- DispatchSuccessEvent(&helper);
- }
- void
- BackgroundRequestChild::HandleResponse(
- const nsTArray<SerializedStructuredCloneReadInfo>& aResponse)
- {
- AssertIsOnOwningThread();
- nsTArray<StructuredCloneReadInfo> cloneReadInfos;
- if (!aResponse.IsEmpty()) {
- const uint32_t count = aResponse.Length();
- cloneReadInfos.SetCapacity(count);
- IDBDatabase* database = mTransaction->Database();
- for (uint32_t index = 0; index < count; index++) {
- // XXX Fix this somehow...
- auto& serializedCloneInfo =
- const_cast<SerializedStructuredCloneReadInfo&>(aResponse[index]);
- StructuredCloneReadInfo* cloneReadInfo = cloneReadInfos.AppendElement();
- // Move relevant data into the cloneReadInfo
- *cloneReadInfo = Move(serializedCloneInfo);
- // Get the files
- nsTArray<StructuredCloneFile> files;
- DeserializeStructuredCloneFiles(database,
- serializedCloneInfo.files(),
- GetNextModuleSet(*cloneReadInfo),
- files);
- cloneReadInfo->mFiles = Move(files);
- }
- }
- ResultHelper helper(mRequest, mTransaction, &cloneReadInfos);
- DispatchSuccessEvent(&helper);
- }
- void
- BackgroundRequestChild::HandleResponse(JS::Handle<JS::Value> aResponse)
- {
- AssertIsOnOwningThread();
- ResultHelper helper(mRequest, mTransaction, &aResponse);
- DispatchSuccessEvent(&helper);
- }
- void
- BackgroundRequestChild::HandleResponse(uint64_t aResponse)
- {
- AssertIsOnOwningThread();
- JS::Value response(JS::NumberValue(aResponse));
- ResultHelper helper(mRequest, mTransaction, &response);
- DispatchSuccessEvent(&helper);
- }
- nsresult
- BackgroundRequestChild::HandlePreprocess(
- const WasmModulePreprocessInfo& aPreprocessInfo)
- {
- AssertIsOnOwningThread();
- IDBDatabase* database = mTransaction->Database();
- mPreprocessHelpers.SetLength(1);
- nsTArray<StructuredCloneFile> files;
- DeserializeStructuredCloneFiles(database,
- aPreprocessInfo.files(),
- nullptr,
- files);
- RefPtr<PreprocessHelper>& preprocessHelper = mPreprocessHelpers[0];
- preprocessHelper = new PreprocessHelper(0, this);
- nsresult rv = preprocessHelper->Init(files);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- rv = preprocessHelper->Dispatch();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- mRunningPreprocessHelpers++;
- mModuleSets.SetLength(1);
- return NS_OK;
- }
- nsresult
- BackgroundRequestChild::HandlePreprocess(
- const nsTArray<WasmModulePreprocessInfo>& aPreprocessInfos)
- {
- AssertIsOnOwningThread();
- IDBDatabase* database = mTransaction->Database();
- uint32_t count = aPreprocessInfos.Length();
- mPreprocessHelpers.SetLength(count);
- // TODO: Since we use the stream transport service, this can spawn 25 threads
- // and has the potential to cause some annoying browser hiccups.
- // Consider using a single thread or a very small threadpool.
- for (uint32_t index = 0; index < count; index++) {
- const WasmModulePreprocessInfo& preprocessInfo = aPreprocessInfos[index];
- nsTArray<StructuredCloneFile> files;
- DeserializeStructuredCloneFiles(database,
- preprocessInfo.files(),
- nullptr,
- files);
- RefPtr<PreprocessHelper>& preprocessHelper = mPreprocessHelpers[index];
- preprocessHelper = new PreprocessHelper(index, this);
- nsresult rv = preprocessHelper->Init(files);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- rv = preprocessHelper->Dispatch();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- mRunningPreprocessHelpers++;
- }
- mModuleSets.SetLength(count);
- mGetAll = true;
- return NS_OK;
- }
- void
- BackgroundRequestChild::ActorDestroy(ActorDestroyReason aWhy)
- {
- AssertIsOnOwningThread();
- MaybeCollectGarbageOnIPCMessage();
- for (uint32_t count = mPreprocessHelpers.Length(), index = 0;
- index < count;
- index++) {
- RefPtr<PreprocessHelper>& preprocessHelper = mPreprocessHelpers[index];
- if (preprocessHelper) {
- preprocessHelper->ClearActor();
- preprocessHelper = nullptr;
- }
- }
- if (mTransaction) {
- mTransaction->AssertIsOnOwningThread();
- mTransaction->OnRequestFinished(/* aActorDestroyedNormally */
- aWhy == Deletion);
- #ifdef DEBUG
- mTransaction = nullptr;
- #endif
- }
- }
- bool
- BackgroundRequestChild::Recv__delete__(const RequestResponse& aResponse)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(mRequest);
- MOZ_ASSERT(mTransaction);
- MaybeCollectGarbageOnIPCMessage();
- if (mTransaction->IsAborted()) {
- // Always fire an "error" event with ABORT_ERR if the transaction was
- // aborted, even if the request succeeded or failed with another error.
- HandleResponse(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
- } else {
- switch (aResponse.type()) {
- case RequestResponse::Tnsresult:
- HandleResponse(aResponse.get_nsresult());
- break;
- case RequestResponse::TObjectStoreAddResponse:
- HandleResponse(aResponse.get_ObjectStoreAddResponse().key());
- break;
- case RequestResponse::TObjectStorePutResponse:
- HandleResponse(aResponse.get_ObjectStorePutResponse().key());
- break;
- case RequestResponse::TObjectStoreGetResponse:
- HandleResponse(aResponse.get_ObjectStoreGetResponse().cloneInfo());
- break;
- case RequestResponse::TObjectStoreGetKeyResponse:
- HandleResponse(aResponse.get_ObjectStoreGetKeyResponse().key());
- break;
- case RequestResponse::TObjectStoreGetAllResponse:
- HandleResponse(aResponse.get_ObjectStoreGetAllResponse().cloneInfos());
- break;
- case RequestResponse::TObjectStoreGetAllKeysResponse:
- HandleResponse(aResponse.get_ObjectStoreGetAllKeysResponse().keys());
- break;
- case RequestResponse::TObjectStoreDeleteResponse:
- HandleResponse(JS::UndefinedHandleValue);
- break;
- case RequestResponse::TObjectStoreClearResponse:
- HandleResponse(JS::UndefinedHandleValue);
- break;
- case RequestResponse::TObjectStoreCountResponse:
- HandleResponse(aResponse.get_ObjectStoreCountResponse().count());
- break;
- case RequestResponse::TIndexGetResponse:
- HandleResponse(aResponse.get_IndexGetResponse().cloneInfo());
- break;
- case RequestResponse::TIndexGetKeyResponse:
- HandleResponse(aResponse.get_IndexGetKeyResponse().key());
- break;
- case RequestResponse::TIndexGetAllResponse:
- HandleResponse(aResponse.get_IndexGetAllResponse().cloneInfos());
- break;
- case RequestResponse::TIndexGetAllKeysResponse:
- HandleResponse(aResponse.get_IndexGetAllKeysResponse().keys());
- break;
- case RequestResponse::TIndexCountResponse:
- HandleResponse(aResponse.get_IndexCountResponse().count());
- break;
- default:
- MOZ_CRASH("Unknown response type!");
- }
- }
- mTransaction->OnRequestFinished(/* aActorDestroyedNormally */ true);
- // Null this out so that we don't try to call OnRequestFinished() again in
- // ActorDestroy.
- mTransaction = nullptr;
- return true;
- }
- bool
- BackgroundRequestChild::RecvPreprocess(const PreprocessParams& aParams)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(mTransaction);
- MaybeCollectGarbageOnIPCMessage();
- nsresult rv;
- switch (aParams.type()) {
- case PreprocessParams::TObjectStoreGetPreprocessParams: {
- ObjectStoreGetPreprocessParams params =
- aParams.get_ObjectStoreGetPreprocessParams();
- rv = HandlePreprocess(params.preprocessInfo());
- break;
- }
- case PreprocessParams::TObjectStoreGetAllPreprocessParams: {
- ObjectStoreGetAllPreprocessParams params =
- aParams.get_ObjectStoreGetAllPreprocessParams();
- rv = HandlePreprocess(params.preprocessInfos());
- break;
- }
- default:
- MOZ_CRASH("Unknown params type!");
- }
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return SendContinue(rv);
- }
- return true;
- }
- nsresult
- BackgroundRequestChild::
- PreprocessHelper::Init(const nsTArray<StructuredCloneFile>& aFiles)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(!aFiles.IsEmpty());
- uint32_t count = aFiles.Length();
- // We should receive even number of files.
- MOZ_ASSERT(count % 2 == 0);
- // Let's process it as pairs.
- count = count / 2;
- nsTArray<StreamPair> streamPairs;
- for (uint32_t index = 0; index < count; index++) {
- uint32_t bytecodeIndex = index * 2;
- uint32_t compiledIndex = bytecodeIndex + 1;
- const StructuredCloneFile& bytecodeFile = aFiles[bytecodeIndex];
- const StructuredCloneFile& compiledFile = aFiles[compiledIndex];
- MOZ_ASSERT(bytecodeFile.mType == StructuredCloneFile::eWasmBytecode);
- MOZ_ASSERT(bytecodeFile.mBlob);
- MOZ_ASSERT(compiledFile.mType == StructuredCloneFile::eWasmCompiled);
- MOZ_ASSERT(compiledFile.mBlob);
- ErrorResult errorResult;
- nsCOMPtr<nsIInputStream> bytecodeStream;
- bytecodeFile.mBlob->GetInternalStream(getter_AddRefs(bytecodeStream),
- errorResult);
- if (NS_WARN_IF(errorResult.Failed())) {
- return errorResult.StealNSResult();
- }
- nsCOMPtr<nsIInputStream> compiledStream;
- compiledFile.mBlob->GetInternalStream(getter_AddRefs(compiledStream),
- errorResult);
- if (NS_WARN_IF(errorResult.Failed())) {
- return errorResult.StealNSResult();
- }
- streamPairs.AppendElement(StreamPair(bytecodeStream, compiledStream));
- }
- mStreamPairs = Move(streamPairs);
- return NS_OK;
- }
- nsresult
- BackgroundRequestChild::
- PreprocessHelper::Dispatch()
- {
- AssertIsOnOwningThread();
- // The stream transport service is used for asynchronous processing. It has
- // a threadpool with a high cap of 25 threads. Fortunately, the service can
- // be used on workers too.
- nsCOMPtr<nsIEventTarget> target =
- do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
- MOZ_ASSERT(target);
- nsresult rv = target->Dispatch(this, NS_DISPATCH_NORMAL);
- if (NS_WARN_IF(NS_FAILED(rv))) {
- return rv;
- }
- return NS_OK;
- }
- void
- BackgroundRequestChild::
- PreprocessHelper::RunOnOwningThread()
- {
- AssertIsOnOwningThread();
- if (mActor) {
- if (NS_SUCCEEDED(mResultCode)) {
- mActor->OnPreprocessFinished(mModuleSetIndex, mModuleSet);
- MOZ_ASSERT(mModuleSet.IsEmpty());
- } else {
- mActor->OnPreprocessFailed(mModuleSetIndex, mResultCode);
- }
- }
- }
- nsresult
- BackgroundRequestChild::
- PreprocessHelper::RunOnStreamTransportThread()
- {
- MOZ_ASSERT(!IsOnOwningThread());
- MOZ_ASSERT(!mStreamPairs.IsEmpty());
- MOZ_ASSERT(mModuleSet.IsEmpty());
- const uint32_t count = mStreamPairs.Length();
- for (uint32_t index = 0; index < count; index++) {
- const StreamPair& streamPair = mStreamPairs[index];
- const nsCOMPtr<nsIInputStream>& bytecodeStream = streamPair.first;
- MOZ_ASSERT(bytecodeStream);
- PRFileDesc* bytecodeFileDesc = GetFileDescriptorFromStream(bytecodeStream);
- if (NS_WARN_IF(!bytecodeFileDesc)) {
- return NS_ERROR_FAILURE;
- }
- const nsCOMPtr<nsIInputStream>& compiledStream = streamPair.second;
- MOZ_ASSERT(compiledStream);
- PRFileDesc* compiledFileDesc = GetFileDescriptorFromStream(compiledStream);
- if (NS_WARN_IF(!compiledFileDesc)) {
- return NS_ERROR_FAILURE;
- }
- JS::BuildIdCharVector buildId;
- bool ok = GetBuildId(&buildId);
- if (NS_WARN_IF(!ok)) {
- return NS_ERROR_FAILURE;
- }
- RefPtr<JS::WasmModule> module = JS::DeserializeWasmModule(bytecodeFileDesc,
- compiledFileDesc,
- Move(buildId),
- nullptr,
- 0,
- 0);
- if (NS_WARN_IF(!module)) {
- return NS_ERROR_FAILURE;
- }
- mModuleSet.AppendElement(module);
- }
- mStreamPairs.Clear();
- return NS_OK;
- }
- NS_IMETHODIMP
- BackgroundRequestChild::
- PreprocessHelper::Run()
- {
- if (IsOnOwningThread()) {
- RunOnOwningThread();
- } else {
- nsresult rv = RunOnStreamTransportThread();
- if (NS_WARN_IF(NS_FAILED(rv))) {
- MOZ_ASSERT(mResultCode == NS_OK);
- mResultCode = rv;
- }
- MOZ_ALWAYS_SUCCEEDS(mOwningThread->Dispatch(this, NS_DISPATCH_NORMAL));
- }
- return NS_OK;
- }
- nsresult
- BackgroundRequestChild::
- PreprocessHelper::Cancel()
- {
- return NS_OK;
- }
- /*******************************************************************************
- * BackgroundCursorChild
- ******************************************************************************/
- // Does not need to be threadsafe since this only runs on one thread, but
- // inheriting from CancelableRunnable is easy.
- class BackgroundCursorChild::DelayedActionRunnable final
- : public CancelableRunnable
- {
- using ActionFunc = void (BackgroundCursorChild::*)();
- BackgroundCursorChild* mActor;
- RefPtr<IDBRequest> mRequest;
- ActionFunc mActionFunc;
- public:
- explicit
- DelayedActionRunnable(BackgroundCursorChild* aActor, ActionFunc aActionFunc)
- : mActor(aActor)
- , mRequest(aActor->mRequest)
- , mActionFunc(aActionFunc)
- {
- MOZ_ASSERT(aActor);
- aActor->AssertIsOnOwningThread();
- MOZ_ASSERT(mRequest);
- MOZ_ASSERT(mActionFunc);
- }
- private:
- ~DelayedActionRunnable()
- { }
- NS_DECL_NSIRUNNABLE
- nsresult Cancel() override;
- };
- BackgroundCursorChild::BackgroundCursorChild(IDBRequest* aRequest,
- IDBObjectStore* aObjectStore,
- Direction aDirection)
- : mRequest(aRequest)
- , mTransaction(aRequest->GetTransaction())
- , mObjectStore(aObjectStore)
- , mIndex(nullptr)
- , mCursor(nullptr)
- , mStrongRequest(aRequest)
- , mDirection(aDirection)
- {
- MOZ_ASSERT(aObjectStore);
- aObjectStore->AssertIsOnOwningThread();
- MOZ_ASSERT(mTransaction);
- MOZ_COUNT_CTOR(indexedDB::BackgroundCursorChild);
- #ifdef DEBUG
- mOwningThread = PR_GetCurrentThread();
- MOZ_ASSERT(mOwningThread);
- #endif
- }
- BackgroundCursorChild::BackgroundCursorChild(IDBRequest* aRequest,
- IDBIndex* aIndex,
- Direction aDirection)
- : mRequest(aRequest)
- , mTransaction(aRequest->GetTransaction())
- , mObjectStore(nullptr)
- , mIndex(aIndex)
- , mCursor(nullptr)
- , mStrongRequest(aRequest)
- , mDirection(aDirection)
- {
- MOZ_ASSERT(aIndex);
- aIndex->AssertIsOnOwningThread();
- MOZ_ASSERT(mTransaction);
- MOZ_COUNT_CTOR(indexedDB::BackgroundCursorChild);
- #ifdef DEBUG
- mOwningThread = PR_GetCurrentThread();
- MOZ_ASSERT(mOwningThread);
- #endif
- }
- BackgroundCursorChild::~BackgroundCursorChild()
- {
- MOZ_COUNT_DTOR(indexedDB::BackgroundCursorChild);
- }
- #ifdef DEBUG
- void
- BackgroundCursorChild::AssertIsOnOwningThread() const
- {
- MOZ_ASSERT(mOwningThread == PR_GetCurrentThread());
- }
- #endif // DEBUG
- void
- BackgroundCursorChild::SendContinueInternal(const CursorRequestParams& aParams)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(mRequest);
- MOZ_ASSERT(mTransaction);
- MOZ_ASSERT(mCursor);
- MOZ_ASSERT(!mStrongRequest);
- MOZ_ASSERT(!mStrongCursor);
- // Make sure all our DOM objects stay alive.
- mStrongCursor = mCursor;
- MOZ_ASSERT(mRequest->ReadyState() == IDBRequestReadyState::Done);
- mRequest->Reset();
- mTransaction->OnNewRequest();
- MOZ_ALWAYS_TRUE(PBackgroundIDBCursorChild::SendContinue(aParams));
- }
- void
- BackgroundCursorChild::SendDeleteMeInternal()
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(!mStrongRequest);
- MOZ_ASSERT(!mStrongCursor);
- mRequest = nullptr;
- mTransaction = nullptr;
- mObjectStore = nullptr;
- mIndex = nullptr;
- if (mCursor) {
- mCursor->ClearBackgroundActor();
- mCursor = nullptr;
- MOZ_ALWAYS_TRUE(PBackgroundIDBCursorChild::SendDeleteMe());
- }
- }
- void
- BackgroundCursorChild::HandleResponse(nsresult aResponse)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(NS_FAILED(aResponse));
- MOZ_ASSERT(NS_ERROR_GET_MODULE(aResponse) == NS_ERROR_MODULE_DOM_INDEXEDDB);
- MOZ_ASSERT(mRequest);
- MOZ_ASSERT(mTransaction);
- MOZ_ASSERT(!mStrongRequest);
- MOZ_ASSERT(!mStrongCursor);
- DispatchErrorEvent(mRequest, aResponse, mTransaction);
- }
- void
- BackgroundCursorChild::HandleResponse(const void_t& aResponse)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(mRequest);
- MOZ_ASSERT(mTransaction);
- MOZ_ASSERT(!mStrongRequest);
- MOZ_ASSERT(!mStrongCursor);
- if (mCursor) {
- mCursor->Reset();
- }
- ResultHelper helper(mRequest, mTransaction, &JS::NullHandleValue);
- DispatchSuccessEvent(&helper);
- if (!mCursor) {
- nsCOMPtr<nsIRunnable> deleteRunnable = new DelayedActionRunnable(
- this, &BackgroundCursorChild::SendDeleteMeInternal);
- MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(deleteRunnable));
- }
- }
- void
- BackgroundCursorChild::HandleResponse(
- const nsTArray<ObjectStoreCursorResponse>& aResponses)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(mRequest);
- MOZ_ASSERT(mTransaction);
- MOZ_ASSERT(mObjectStore);
- MOZ_ASSERT(!mStrongRequest);
- MOZ_ASSERT(!mStrongCursor);
- MOZ_ASSERT(aResponses.Length() == 1);
- // XXX Fix this somehow...
- auto& responses =
- const_cast<nsTArray<ObjectStoreCursorResponse>&>(aResponses);
- // If a new cursor is created, we need to keep a reference to it until the
- // ResultHelper creates a DOM Binding.
- RefPtr<IDBCursor> newCursor;
- for (ObjectStoreCursorResponse& response : responses) {
- StructuredCloneReadInfo cloneReadInfo(Move(response.cloneInfo()));
- cloneReadInfo.mDatabase = mTransaction->Database();
- DeserializeStructuredCloneFiles(mTransaction->Database(),
- response.cloneInfo().files(),
- nullptr,
- cloneReadInfo.mFiles);
- if (mCursor) {
- mCursor->Reset(Move(response.key()), Move(cloneReadInfo));
- } else {
- newCursor = IDBCursor::Create(this,
- Move(response.key()),
- Move(cloneReadInfo));
- mCursor = newCursor;
- }
- }
- ResultHelper helper(mRequest, mTransaction, mCursor);
- DispatchSuccessEvent(&helper);
- }
- void
- BackgroundCursorChild::HandleResponse(
- const ObjectStoreKeyCursorResponse& aResponse)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(mRequest);
- MOZ_ASSERT(mTransaction);
- MOZ_ASSERT(mObjectStore);
- MOZ_ASSERT(!mStrongRequest);
- MOZ_ASSERT(!mStrongCursor);
- // XXX Fix this somehow...
- auto& response = const_cast<ObjectStoreKeyCursorResponse&>(aResponse);
- RefPtr<IDBCursor> newCursor;
- if (mCursor) {
- mCursor->Reset(Move(response.key()));
- } else {
- newCursor = IDBCursor::Create(this, Move(response.key()));
- mCursor = newCursor;
- }
- ResultHelper helper(mRequest, mTransaction, mCursor);
- DispatchSuccessEvent(&helper);
- }
- void
- BackgroundCursorChild::HandleResponse(const IndexCursorResponse& aResponse)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(mRequest);
- MOZ_ASSERT(mTransaction);
- MOZ_ASSERT(mIndex);
- MOZ_ASSERT(!mStrongRequest);
- MOZ_ASSERT(!mStrongCursor);
- // XXX Fix this somehow...
- auto& response = const_cast<IndexCursorResponse&>(aResponse);
- StructuredCloneReadInfo cloneReadInfo(Move(response.cloneInfo()));
- cloneReadInfo.mDatabase = mTransaction->Database();
- DeserializeStructuredCloneFiles(mTransaction->Database(),
- aResponse.cloneInfo().files(),
- nullptr,
- cloneReadInfo.mFiles);
- RefPtr<IDBCursor> newCursor;
- if (mCursor) {
- mCursor->Reset(Move(response.key()),
- Move(response.sortKey()),
- Move(response.objectKey()),
- Move(cloneReadInfo));
- } else {
- newCursor = IDBCursor::Create(this,
- Move(response.key()),
- Move(response.sortKey()),
- Move(response.objectKey()),
- Move(cloneReadInfo));
- mCursor = newCursor;
- }
- ResultHelper helper(mRequest, mTransaction, mCursor);
- DispatchSuccessEvent(&helper);
- }
- void
- BackgroundCursorChild::HandleResponse(const IndexKeyCursorResponse& aResponse)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(mRequest);
- MOZ_ASSERT(mTransaction);
- MOZ_ASSERT(mIndex);
- MOZ_ASSERT(!mStrongRequest);
- MOZ_ASSERT(!mStrongCursor);
- // XXX Fix this somehow...
- auto& response = const_cast<IndexKeyCursorResponse&>(aResponse);
- RefPtr<IDBCursor> newCursor;
- if (mCursor) {
- mCursor->Reset(Move(response.key()),
- Move(response.sortKey()),
- Move(response.objectKey()));
- } else {
- newCursor = IDBCursor::Create(this,
- Move(response.key()),
- Move(response.sortKey()),
- Move(response.objectKey()));
- mCursor = newCursor;
- }
- ResultHelper helper(mRequest, mTransaction, mCursor);
- DispatchSuccessEvent(&helper);
- }
- void
- BackgroundCursorChild::ActorDestroy(ActorDestroyReason aWhy)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT_IF(aWhy == Deletion, !mStrongRequest);
- MOZ_ASSERT_IF(aWhy == Deletion, !mStrongCursor);
- MaybeCollectGarbageOnIPCMessage();
- if (mStrongRequest && !mStrongCursor && mTransaction) {
- mTransaction->OnRequestFinished(/* aActorDestroyedNormally */
- aWhy == Deletion);
- }
- if (mCursor) {
- mCursor->ClearBackgroundActor();
- #ifdef DEBUG
- mCursor = nullptr;
- #endif
- }
- #ifdef DEBUG
- mRequest = nullptr;
- mTransaction = nullptr;
- mObjectStore = nullptr;
- mIndex = nullptr;
- #endif
- }
- bool
- BackgroundCursorChild::RecvResponse(const CursorResponse& aResponse)
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(aResponse.type() != CursorResponse::T__None);
- MOZ_ASSERT(mRequest);
- MOZ_ASSERT(mTransaction);
- MOZ_ASSERT_IF(mCursor, mStrongCursor);
- MOZ_ASSERT_IF(!mCursor, mStrongRequest);
- MaybeCollectGarbageOnIPCMessage();
- RefPtr<IDBRequest> request;
- mStrongRequest.swap(request);
- RefPtr<IDBCursor> cursor;
- mStrongCursor.swap(cursor);
-
- RefPtr<IDBTransaction> transaction = mTransaction;
- switch (aResponse.type()) {
- case CursorResponse::Tnsresult:
- HandleResponse(aResponse.get_nsresult());
- break;
- case CursorResponse::Tvoid_t:
- HandleResponse(aResponse.get_void_t());
- break;
- case CursorResponse::TArrayOfObjectStoreCursorResponse:
- HandleResponse(aResponse.get_ArrayOfObjectStoreCursorResponse());
- break;
- case CursorResponse::TObjectStoreKeyCursorResponse:
- HandleResponse(aResponse.get_ObjectStoreKeyCursorResponse());
- break;
- case CursorResponse::TIndexCursorResponse:
- HandleResponse(aResponse.get_IndexCursorResponse());
- break;
- case CursorResponse::TIndexKeyCursorResponse:
- HandleResponse(aResponse.get_IndexKeyCursorResponse());
- break;
- default:
- MOZ_CRASH("Should never get here!");
- }
- transaction->OnRequestFinished(/* aActorDestroyedNormally */ true);
- return true;
- }
- NS_IMETHODIMP
- BackgroundCursorChild::
- DelayedActionRunnable::Run()
- {
- MOZ_ASSERT(mActor);
- mActor->AssertIsOnOwningThread();
- MOZ_ASSERT(mRequest);
- MOZ_ASSERT(mActionFunc);
- (mActor->*mActionFunc)();
- mActor = nullptr;
- mRequest = nullptr;
- return NS_OK;
- }
- nsresult
- BackgroundCursorChild::
- DelayedActionRunnable::Cancel()
- {
- if (NS_WARN_IF(!mActor)) {
- return NS_ERROR_UNEXPECTED;
- }
- // This must always run to clean up our state.
- Run();
- return NS_OK;
- }
- /*******************************************************************************
- * BackgroundUtilsChild
- ******************************************************************************/
- BackgroundUtilsChild::BackgroundUtilsChild(IndexedDatabaseManager* aManager)
- : mManager(aManager)
- #ifdef DEBUG
- , mOwningThread(NS_GetCurrentThread())
- #endif
- {
- AssertIsOnOwningThread();
- MOZ_ASSERT(aManager);
- MOZ_COUNT_CTOR(indexedDB::BackgroundUtilsChild);
- }
- BackgroundUtilsChild::~BackgroundUtilsChild()
- {
- MOZ_COUNT_DTOR(indexedDB::BackgroundUtilsChild);
- }
- #ifdef DEBUG
- void
- BackgroundUtilsChild::AssertIsOnOwningThread() const
- {
- MOZ_ASSERT(mOwningThread);
- bool current;
- MOZ_ASSERT(NS_SUCCEEDED(mOwningThread->IsOnCurrentThread(¤t)));
- MOZ_ASSERT(current);
- }
- #endif // DEBUG
- void
- BackgroundUtilsChild::SendDeleteMeInternal()
- {
- AssertIsOnOwningThread();
- if (mManager) {
- mManager->ClearBackgroundActor();
- mManager = nullptr;
- MOZ_ALWAYS_TRUE(PBackgroundIndexedDBUtilsChild::SendDeleteMe());
- }
- }
- void
- BackgroundUtilsChild::ActorDestroy(ActorDestroyReason aWhy)
- {
- AssertIsOnOwningThread();
- if (mManager) {
- mManager->ClearBackgroundActor();
- #ifdef DEBUG
- mManager = nullptr;
- #endif
- }
- }
- } // namespace indexedDB
- } // namespace dom
- } // namespace mozilla
|