зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1648141
- IPCBlobInputStream to RemoteLazyInputStream - part 5 - thread, r=smaug
Differential Revision: https://phabricator.services.mozilla.com/D80928
This commit is contained in:
Родитель
5fc1253731
Коммит
c6e87ab4b6
|
@ -22,7 +22,6 @@ Compositor
|
|||
Cookie
|
||||
CrashRep Inject
|
||||
DDMediaLogs
|
||||
DOM File
|
||||
DOMCacheThread
|
||||
DataChannel IO
|
||||
DataStorage
|
||||
|
@ -64,6 +63,7 @@ ProcessHangMon
|
|||
ProfSymbolTable
|
||||
ProfilerChild
|
||||
ProxyResolution
|
||||
RemoteLzyStream
|
||||
RWLockTester
|
||||
RacingServMan
|
||||
RemVidChild
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include "TemporaryFileBlobImpl.h"
|
||||
|
||||
#include "IPCBlobInputStreamThread.h"
|
||||
#include "RemoteLazyInputStreamThread.h"
|
||||
#include "nsFileStreams.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIFileStreams.h"
|
||||
|
@ -76,9 +76,9 @@ class TemporaryFileInputStream final : public nsFileInputStream {
|
|||
}
|
||||
|
||||
~TemporaryFileInputStream() {
|
||||
// Let's delete the file on the IPCBlob Thread.
|
||||
RefPtr<IPCBlobInputStreamThread> thread =
|
||||
IPCBlobInputStreamThread::GetOrCreate();
|
||||
// Let's delete the file on the RemoteLazyInputStream Thread.
|
||||
RefPtr<RemoteLazyInputStreamThread> thread =
|
||||
RemoteLazyInputStreamThread::GetOrCreate();
|
||||
if (NS_WARN_IF(!thread)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include "mozilla/net/SocketProcessParent.h"
|
||||
#include "mozilla/SlicedInputStream.h"
|
||||
#include "mozilla/NonBlockingAsyncInputStream.h"
|
||||
#include "IPCBlobInputStreamThread.h"
|
||||
#include "nsIAsyncInputStream.h"
|
||||
#include "nsIAsyncOutputStream.h"
|
||||
#include "nsIPipe.h"
|
||||
|
@ -19,6 +18,7 @@
|
|||
#include "nsStreamUtils.h"
|
||||
#include "nsStringStream.h"
|
||||
#include "RemoteLazyInputStreamStorage.h"
|
||||
#include "RemoteLazyInputStreamThread.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -804,8 +804,8 @@ nsresult IPCBlobInputStream::EnsureAsyncRemoteStream(
|
|||
return rv;
|
||||
}
|
||||
|
||||
RefPtr<IPCBlobInputStreamThread> thread =
|
||||
IPCBlobInputStreamThread::GetOrCreate();
|
||||
RefPtr<RemoteLazyInputStreamThread> thread =
|
||||
RemoteLazyInputStreamThread::GetOrCreate();
|
||||
if (NS_WARN_IF(!thread)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
|
@ -137,8 +137,8 @@
|
|||
* method will be forwarded to the 'real' stream ones. This means that the
|
||||
* reading will be available.
|
||||
*
|
||||
* DOM-File Thread
|
||||
* ~~~~~~~~~~~~~~~
|
||||
* RemoteLazyInputStream Thread
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* RemoteLazyInputStreamChild actor can be created in any thread (sort of) and
|
||||
* their top-level IPDL protocol is PBackground. These actors are wrapped by 1
|
||||
|
@ -164,10 +164,10 @@
|
|||
* 1. If RemoteLazyInputStreamChild actor is not already owned by DOM-File
|
||||
* thread, it calls Send__delete__ in order to inform the parent side that we
|
||||
* don't need this IPC channel on the current thread.
|
||||
* 2. A new RemoteLazyInputStreamChild is created. IPCBlobInputStreamThread is
|
||||
* used to assign this actor to the DOM-File thread.
|
||||
* IPCBlobInputStreamThread::GetOrCreate() creates the DOM-File thread if it
|
||||
* doesn't exist yet. Pending operations and IPCBlobInputStreams are moved
|
||||
* 2. A new RemoteLazyInputStreamChild is created. RemoteLazyInputStreamThread
|
||||
* is used to assign this actor to the DOM-File thread.
|
||||
* RemoteLazyInputStreamThread::GetOrCreate() creates the DOM-File thread if
|
||||
* it doesn't exist yet. Pending operations and IPCBlobInputStreams are moved
|
||||
* onto the new actor.
|
||||
* 3. RemoteLazyInputStreamParent::Recv__delete__ is called on the parent side
|
||||
* and the parent actor is deleted. Doing this we don't remove the UUID from
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "RemoteLazyInputStreamChild.h"
|
||||
#include "IPCBlobInputStreamThread.h"
|
||||
#include "RemoteLazyInputStreamThread.h"
|
||||
|
||||
#include "mozilla/ipc/IPCStreamUtils.h"
|
||||
#include "mozilla/dom/WorkerCommon.h"
|
||||
|
@ -205,14 +205,14 @@ RemoteLazyInputStreamChild::CreateStream() {
|
|||
// The stream is active but maybe it is not running in the DOM-File thread.
|
||||
// We should migrate it there.
|
||||
if (mState == eActive &&
|
||||
!IPCBlobInputStreamThread::IsOnFileEventTarget(mOwningEventTarget)) {
|
||||
!RemoteLazyInputStreamThread::IsOnFileEventTarget(mOwningEventTarget)) {
|
||||
MOZ_ASSERT(mStreams.IsEmpty());
|
||||
|
||||
shouldMigrate = true;
|
||||
mState = eActiveMigrating;
|
||||
|
||||
RefPtr<IPCBlobInputStreamThread> thread =
|
||||
IPCBlobInputStreamThread::GetOrCreate();
|
||||
RefPtr<RemoteLazyInputStreamThread> thread =
|
||||
RemoteLazyInputStreamThread::GetOrCreate();
|
||||
MOZ_ASSERT(thread, "We cannot continue without DOMFile thread.");
|
||||
|
||||
// Create a new actor object to connect to the target thread.
|
||||
|
@ -412,7 +412,8 @@ void RemoteLazyInputStreamChild::Migrated() {
|
|||
mWorkerRef = nullptr;
|
||||
|
||||
mOwningEventTarget = GetCurrentSerialEventTarget();
|
||||
MOZ_ASSERT(IPCBlobInputStreamThread::IsOnFileEventTarget(mOwningEventTarget));
|
||||
MOZ_ASSERT(
|
||||
RemoteLazyInputStreamThread::IsOnFileEventTarget(mOwningEventTarget));
|
||||
|
||||
// Maybe we have no reasons to keep this actor alive.
|
||||
if (mStreams.IsEmpty()) {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* 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 "IPCBlobInputStreamThread.h"
|
||||
#include "RemoteLazyInputStreamThread.h"
|
||||
|
||||
#include "mozilla/SchedulerGroup.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
|
@ -21,8 +21,8 @@ namespace dom {
|
|||
|
||||
namespace {
|
||||
|
||||
StaticMutex gIPCBlobThreadMutex;
|
||||
StaticRefPtr<IPCBlobInputStreamThread> gIPCBlobThread;
|
||||
StaticMutex gRemoteLazyThreadMutex;
|
||||
StaticRefPtr<RemoteLazyInputStreamThread> gRemoteLazyThread;
|
||||
bool gShutdownHasStarted = false;
|
||||
|
||||
class ThreadInitializeRunnable final : public Runnable {
|
||||
|
@ -31,9 +31,9 @@ class ThreadInitializeRunnable final : public Runnable {
|
|||
|
||||
NS_IMETHOD
|
||||
Run() override {
|
||||
mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
|
||||
MOZ_ASSERT(gIPCBlobThread);
|
||||
gIPCBlobThread->InitializeOnMainThread();
|
||||
mozilla::StaticMutexAutoLock lock(gRemoteLazyThreadMutex);
|
||||
MOZ_ASSERT(gRemoteLazyThread);
|
||||
gRemoteLazyThread->InitializeOnMainThread();
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
@ -72,10 +72,10 @@ class MigrateActorRunnable final : public Runnable {
|
|||
|
||||
} // namespace
|
||||
|
||||
NS_IMPL_ISUPPORTS(IPCBlobInputStreamThread, nsIObserver, nsIEventTarget)
|
||||
NS_IMPL_ISUPPORTS(RemoteLazyInputStreamThread, nsIObserver, nsIEventTarget)
|
||||
|
||||
/* static */
|
||||
bool IPCBlobInputStreamThread::IsOnFileEventTarget(
|
||||
bool RemoteLazyInputStreamThread::IsOnFileEventTarget(
|
||||
nsIEventTarget* aEventTarget) {
|
||||
MOZ_ASSERT(aEventTarget);
|
||||
|
||||
|
@ -86,42 +86,42 @@ bool IPCBlobInputStreamThread::IsOnFileEventTarget(
|
|||
return true;
|
||||
}
|
||||
|
||||
mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
|
||||
return gIPCBlobThread && aEventTarget == gIPCBlobThread->mThread;
|
||||
mozilla::StaticMutexAutoLock lock(gRemoteLazyThreadMutex);
|
||||
return gRemoteLazyThread && aEventTarget == gRemoteLazyThread->mThread;
|
||||
}
|
||||
|
||||
/* static */
|
||||
IPCBlobInputStreamThread* IPCBlobInputStreamThread::Get() {
|
||||
mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
|
||||
RemoteLazyInputStreamThread* RemoteLazyInputStreamThread::Get() {
|
||||
mozilla::StaticMutexAutoLock lock(gRemoteLazyThreadMutex);
|
||||
|
||||
if (gShutdownHasStarted) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return gIPCBlobThread;
|
||||
return gRemoteLazyThread;
|
||||
}
|
||||
|
||||
/* static */
|
||||
IPCBlobInputStreamThread* IPCBlobInputStreamThread::GetOrCreate() {
|
||||
mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
|
||||
RemoteLazyInputStreamThread* RemoteLazyInputStreamThread::GetOrCreate() {
|
||||
mozilla::StaticMutexAutoLock lock(gRemoteLazyThreadMutex);
|
||||
|
||||
if (gShutdownHasStarted) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!gIPCBlobThread) {
|
||||
gIPCBlobThread = new IPCBlobInputStreamThread();
|
||||
if (!gIPCBlobThread->Initialize()) {
|
||||
if (!gRemoteLazyThread) {
|
||||
gRemoteLazyThread = new RemoteLazyInputStreamThread();
|
||||
if (!gRemoteLazyThread->Initialize()) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return gIPCBlobThread;
|
||||
return gRemoteLazyThread;
|
||||
}
|
||||
|
||||
bool IPCBlobInputStreamThread::Initialize() {
|
||||
bool RemoteLazyInputStreamThread::Initialize() {
|
||||
nsCOMPtr<nsIThread> thread;
|
||||
nsresult rv = NS_NewNamedThread("DOM File", getter_AddRefs(thread));
|
||||
nsresult rv = NS_NewNamedThread("RemoteLzyStream", getter_AddRefs(thread));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ bool IPCBlobInputStreamThread::Initialize() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void IPCBlobInputStreamThread::InitializeOnMainThread() {
|
||||
void RemoteLazyInputStreamThread::InitializeOnMainThread() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
|
@ -162,11 +162,11 @@ void IPCBlobInputStreamThread::InitializeOnMainThread() {
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
IPCBlobInputStreamThread::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
const char16_t* aData) {
|
||||
RemoteLazyInputStreamThread::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
const char16_t* aData) {
|
||||
MOZ_ASSERT(!strcmp(aTopic, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID));
|
||||
|
||||
mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
|
||||
mozilla::StaticMutexAutoLock lock(gRemoteLazyThreadMutex);
|
||||
|
||||
if (mThread) {
|
||||
mThread->Shutdown();
|
||||
|
@ -174,16 +174,16 @@ IPCBlobInputStreamThread::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
}
|
||||
|
||||
gShutdownHasStarted = true;
|
||||
gIPCBlobThread = nullptr;
|
||||
gRemoteLazyThread = nullptr;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void IPCBlobInputStreamThread::MigrateActor(
|
||||
void RemoteLazyInputStreamThread::MigrateActor(
|
||||
RemoteLazyInputStreamChild* aActor) {
|
||||
MOZ_ASSERT(aActor->State() == RemoteLazyInputStreamChild::eInactiveMigrating);
|
||||
|
||||
mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
|
||||
mozilla::StaticMutexAutoLock lock(gRemoteLazyThreadMutex);
|
||||
|
||||
if (gShutdownHasStarted) {
|
||||
return;
|
||||
|
@ -198,7 +198,7 @@ void IPCBlobInputStreamThread::MigrateActor(
|
|||
MigrateActorInternal(aActor);
|
||||
}
|
||||
|
||||
void IPCBlobInputStreamThread::MigrateActorInternal(
|
||||
void RemoteLazyInputStreamThread::MigrateActorInternal(
|
||||
RemoteLazyInputStreamChild* aActor) {
|
||||
RefPtr<Runnable> runnable = new MigrateActorRunnable(aActor);
|
||||
mThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
||||
|
@ -207,21 +207,21 @@ void IPCBlobInputStreamThread::MigrateActorInternal(
|
|||
// nsIEventTarget
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
IPCBlobInputStreamThread::IsOnCurrentThreadInfallible() {
|
||||
RemoteLazyInputStreamThread::IsOnCurrentThreadInfallible() {
|
||||
return mThread->IsOnCurrentThread();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
IPCBlobInputStreamThread::IsOnCurrentThread(bool* aRetval) {
|
||||
RemoteLazyInputStreamThread::IsOnCurrentThread(bool* aRetval) {
|
||||
return mThread->IsOnCurrentThread(aRetval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
IPCBlobInputStreamThread::Dispatch(already_AddRefed<nsIRunnable> aRunnable,
|
||||
uint32_t aFlags) {
|
||||
RemoteLazyInputStreamThread::Dispatch(already_AddRefed<nsIRunnable> aRunnable,
|
||||
uint32_t aFlags) {
|
||||
nsCOMPtr<nsIRunnable> runnable(aRunnable);
|
||||
|
||||
mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
|
||||
mozilla::StaticMutexAutoLock lock(gRemoteLazyThreadMutex);
|
||||
|
||||
if (gShutdownHasStarted) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
@ -231,25 +231,25 @@ IPCBlobInputStreamThread::Dispatch(already_AddRefed<nsIRunnable> aRunnable,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
IPCBlobInputStreamThread::DispatchFromScript(nsIRunnable* aRunnable,
|
||||
uint32_t aFlags) {
|
||||
RemoteLazyInputStreamThread::DispatchFromScript(nsIRunnable* aRunnable,
|
||||
uint32_t aFlags) {
|
||||
nsCOMPtr<nsIRunnable> runnable(aRunnable);
|
||||
return Dispatch(runnable.forget(), aFlags);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
IPCBlobInputStreamThread::DelayedDispatch(already_AddRefed<nsIRunnable>,
|
||||
uint32_t) {
|
||||
RemoteLazyInputStreamThread::DelayedDispatch(already_AddRefed<nsIRunnable>,
|
||||
uint32_t) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
bool IsOnDOMFileThread() {
|
||||
mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
|
||||
mozilla::StaticMutexAutoLock lock(gRemoteLazyThreadMutex);
|
||||
|
||||
MOZ_ASSERT(!gShutdownHasStarted);
|
||||
MOZ_ASSERT(gIPCBlobThread);
|
||||
MOZ_ASSERT(gRemoteLazyThread);
|
||||
|
||||
return gIPCBlobThread->IsOnCurrentThreadInfallible();
|
||||
return gRemoteLazyThread->IsOnCurrentThreadInfallible();
|
||||
}
|
||||
|
||||
void AssertIsOnDOMFileThread() { MOZ_ASSERT(IsOnDOMFileThread()); }
|
|
@ -4,8 +4,8 @@
|
|||
* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_IPCBlobInputStreamThread_h
|
||||
#define mozilla_dom_IPCBlobInputStreamThread_h
|
||||
#ifndef mozilla_dom_RemoteLazyInputStreamThread_h
|
||||
#define mozilla_dom_RemoteLazyInputStreamThread_h
|
||||
|
||||
#include "mozilla/dom/RemoteLazyInputStreamChild.h"
|
||||
#include "nsIEventTarget.h"
|
||||
|
@ -19,8 +19,8 @@ namespace dom {
|
|||
|
||||
class RemoteLazyInputStreamChild;
|
||||
|
||||
class IPCBlobInputStreamThread final : public nsIObserver,
|
||||
public nsIEventTarget {
|
||||
class RemoteLazyInputStreamThread final : public nsIObserver,
|
||||
public nsIEventTarget {
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
@ -28,9 +28,9 @@ class IPCBlobInputStreamThread final : public nsIObserver,
|
|||
|
||||
static bool IsOnFileEventTarget(nsIEventTarget* aEventTarget);
|
||||
|
||||
static IPCBlobInputStreamThread* Get();
|
||||
static RemoteLazyInputStreamThread* Get();
|
||||
|
||||
static IPCBlobInputStreamThread* GetOrCreate();
|
||||
static RemoteLazyInputStreamThread* GetOrCreate();
|
||||
|
||||
void MigrateActor(RemoteLazyInputStreamChild* aActor);
|
||||
|
||||
|
@ -39,7 +39,7 @@ class IPCBlobInputStreamThread final : public nsIObserver,
|
|||
void InitializeOnMainThread();
|
||||
|
||||
private:
|
||||
~IPCBlobInputStreamThread() = default;
|
||||
~RemoteLazyInputStreamThread() = default;
|
||||
|
||||
void MigrateActorInternal(RemoteLazyInputStreamChild* aActor);
|
||||
|
||||
|
@ -57,4 +57,4 @@ void AssertIsOnDOMFileThread();
|
|||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_IPCBlobInputStreamThread_h
|
||||
#endif // mozilla_dom_RemoteLazyInputStreamThread_h
|
|
@ -29,11 +29,11 @@ UNIFIED_SOURCES += [
|
|||
'FileCreatorChild.cpp',
|
||||
'FileCreatorParent.cpp',
|
||||
'IPCBlobInputStream.cpp',
|
||||
'IPCBlobInputStreamThread.cpp',
|
||||
'IPCBlobUtils.cpp',
|
||||
'RemoteLazyInputStreamChild.cpp',
|
||||
'RemoteLazyInputStreamParent.cpp',
|
||||
'RemoteLazyInputStreamStorage.cpp',
|
||||
'RemoteLazyInputStreamThread.cpp',
|
||||
'TemporaryIPCBlobChild.cpp',
|
||||
'TemporaryIPCBlobParent.cpp',
|
||||
]
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include "LSObject.h"
|
||||
|
||||
#include "ActorsChild.h"
|
||||
#include "IPCBlobInputStreamThread.h"
|
||||
#include "LocalStorageCommon.h"
|
||||
#include "mozilla/BasePrincipal.h"
|
||||
#include "mozilla/StaticPrefs_dom.h"
|
||||
|
@ -19,6 +18,7 @@
|
|||
#include "nsContentUtils.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsThread.h"
|
||||
#include "RemoteLazyInputStreamThread.h"
|
||||
|
||||
/**
|
||||
* Automatically cancel and abort synchronous LocalStorage requests (for example
|
||||
|
@ -83,15 +83,16 @@ class NestedEventTargetWrapper final : public nsISerialEventTarget {
|
|||
* The normal life-cycle of this method looks like:
|
||||
* - Main Thread: LSObject::DoRequestSynchronously creates a RequestHelper and
|
||||
* invokes StartAndReturnResponse(). It pushes the event queue and Dispatches
|
||||
* the RequestHelper to the DOM File Thread.
|
||||
* - DOM File Thread: RequestHelper::Run is called, invoking Start() which
|
||||
* invokes LSObject::StartRequest, which gets-or-creates the PBackground actor
|
||||
* if necessary (which may dispatch a runnable to the nested event queue on
|
||||
* the main thread), sends LSRequest constructor which is provided with a
|
||||
* callback reference to the RequestHelper. State advances to ResponsePending.
|
||||
* - DOM File Thread:: LSRequestChild::Recv__delete__ is received, which invokes
|
||||
* RequestHelepr::OnResponse, advancing the state to Finishing and dispatching
|
||||
* RequestHelper to its own nested event target.
|
||||
* the RequestHelper to the RemoteLazyInputStream thread.
|
||||
* - RemoteLazyInputStream Thread: RequestHelper::Run is called, invoking
|
||||
* Start() which invokes LSObject::StartRequest, which gets-or-creates the
|
||||
* PBackground actor if necessary (which may dispatch a runnable to the nested
|
||||
* event queue on the main thread), sends LSRequest constructor which is
|
||||
* provided with a callback reference to the RequestHelper. State advances to
|
||||
* ResponsePending.
|
||||
* - RemoteLazyInputStreamThread: LSRequestChild::Recv__delete__ is received,
|
||||
* which invokes RequestHelepr::OnResponse, advancing the state to Finishing
|
||||
* and dispatching RequestHelper to its own nested event target.
|
||||
* - Main Thread: RequestHelper::Run is called, invoking Finish() which advances
|
||||
* the state to Complete and sets mWaiting to false, allowing the nested event
|
||||
* loop being spun by StartAndReturnResponse to cease spinning and return the
|
||||
|
@ -103,11 +104,12 @@ class NestedEventTargetWrapper final : public nsISerialEventTarget {
|
|||
class RequestHelper final : public Runnable, public LSRequestChildCallback {
|
||||
enum class State {
|
||||
/**
|
||||
* The RequestHelper has been created and dispatched to the DOM File Thread.
|
||||
* The RequestHelper has been created and dispatched to the
|
||||
* RemoteLazyInputStream Thread.
|
||||
*/
|
||||
Initial,
|
||||
/**
|
||||
* Start() has been invoked on the DOM File Thread and
|
||||
* Start() has been invoked on the RemoteLazyInputStream Thread and
|
||||
* LSObject::StartRequest has been invoked from there, sending an IPC
|
||||
* message to PBackground to service the request. We stay in this state
|
||||
* until a response is received.
|
||||
|
@ -217,7 +219,7 @@ void LSObject::Initialize() {
|
|||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<nsIEventTarget> domFileThread =
|
||||
IPCBlobInputStreamThread::GetOrCreate();
|
||||
RemoteLazyInputStreamThread::GetOrCreate();
|
||||
if (NS_WARN_IF(!domFileThread)) {
|
||||
return;
|
||||
}
|
||||
|
@ -827,9 +829,9 @@ nsresult LSObject::DoRequestSynchronously(const LSRequestParams& aParams,
|
|||
|
||||
RefPtr<RequestHelper> helper = new RequestHelper(this, aParams);
|
||||
|
||||
// This will start and finish the request on the DOM File thread.
|
||||
// This will start and finish the request on the RemoteLazyInputStream thread.
|
||||
// The owning thread is synchronously blocked while the request is
|
||||
// asynchronously processed on the DOM File thread.
|
||||
// asynchronously processed on the RemoteLazyInputStream thread.
|
||||
nsresult rv = helper->StartAndReturnResponse(aResponse);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
@ -896,7 +898,7 @@ nsresult LSObject::EnsureDatabase() {
|
|||
uint64_t datastoreId = prepareDatastoreResponse.datastoreId();
|
||||
|
||||
// The datastore is now ready on the parent side (prepared by the asynchronous
|
||||
// request on the DOM File thread).
|
||||
// request on the RemoteLazyInputStream thread).
|
||||
// Let's create a direct connection to the datastore (through a database
|
||||
// actor) from the owning thread.
|
||||
// Note that we now can't error out, otherwise parent will keep an extra
|
||||
|
@ -961,7 +963,7 @@ nsresult LSObject::EnsureObserver() {
|
|||
uint64_t observerId = prepareObserverResponse.observerId();
|
||||
|
||||
// The obsserver is now ready on the parent side (prepared by the asynchronous
|
||||
// request on the DOM File thread).
|
||||
// request on the RemoteLazyInputStream thread).
|
||||
// Let's create a direct connection to the observer (through an observer
|
||||
// actor) from the owning thread.
|
||||
// Note that we now can't error out, otherwise parent will keep an extra
|
||||
|
@ -1105,8 +1107,8 @@ nsresult RequestHelper::StartAndReturnResponse(LSRequestResponse& aResponse) {
|
|||
// Normally, we would use the standard way of blocking the thread using
|
||||
// a monitor.
|
||||
// The problem is that BackgroundChild::GetOrCreateForCurrentThread()
|
||||
// called on the DOM File thread may dispatch a runnable to the main
|
||||
// thread to finish initialization of PBackground. A monitor would block
|
||||
// called on the RemoteLazyInputStream thread may dispatch a runnable to the
|
||||
// main thread to finish initialization of PBackground. A monitor would block
|
||||
// the main thread and the runnable would never get executed causing the
|
||||
// helper to be stuck in a wait loop.
|
||||
// However, BackgroundChild::GetOrCreateForCurrentThread() supports passing
|
||||
|
@ -1127,8 +1129,8 @@ nsresult RequestHelper::StartAndReturnResponse(LSRequestResponse& aResponse) {
|
|||
new NestedEventTargetWrapper(mNestedEventTarget);
|
||||
|
||||
nsCOMPtr<nsIEventTarget> domFileThread =
|
||||
XRE_IsParentProcess() ? IPCBlobInputStreamThread::GetOrCreate()
|
||||
: IPCBlobInputStreamThread::Get();
|
||||
XRE_IsParentProcess() ? RemoteLazyInputStreamThread::GetOrCreate()
|
||||
: RemoteLazyInputStreamThread::Get();
|
||||
if (NS_WARN_IF(!domFileThread)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -1202,8 +1204,8 @@ nsresult RequestHelper::StartAndReturnResponse(LSRequestResponse& aResponse) {
|
|||
// We can check mWaiting here because it's only ever touched on the main
|
||||
// thread.
|
||||
if (NS_WARN_IF(mWaiting)) {
|
||||
// Don't touch mResponse, mResultCode or mState here! The DOM File Thread
|
||||
// may be accessing them at the same moment.
|
||||
// Don't touch mResponse, mResultCode or mState here! The
|
||||
// RemoteLazyInputStream Thread may be accessing them at the same moment.
|
||||
|
||||
RefPtr<RequestHelper> self = this;
|
||||
|
||||
|
|
|
@ -81,16 +81,16 @@
|
|||
* like directory locking before sending a reply to a synchronous message, then
|
||||
* we would have to block the thread or spin the event loop which is usually a
|
||||
* bad idea, especially in the main process.
|
||||
* Instead, we can use a special thread in the content process called DOM File
|
||||
* thread for communication with the main process using asynchronous messages
|
||||
* and synchronously block the main thread until the DOM File thread is done
|
||||
* (the main thread blocking is a bit more complicated, see the comment in
|
||||
* RequestHelper::StartAndReturnResponse for more details).
|
||||
* Anyway, the extra hop to the DOM File thread brings another overhead and
|
||||
* latency. The final solution is to use a combination of the special thread
|
||||
* for complex stuff like datastore preparation and synchronous IPC messages
|
||||
* sent directly from the main thread for database access when data is already
|
||||
* loaded from disk into memory.
|
||||
* Instead, we can use a special thread in the content process called
|
||||
* RemoteLazyInputStream thread for communication with the main process using
|
||||
* asynchronous messages and synchronously block the main thread until the DOM
|
||||
* File thread is done (the main thread blocking is a bit more complicated, see
|
||||
* the comment in RequestHelper::StartAndReturnResponse for more details).
|
||||
* Anyway, the extra hop to the RemoteLazyInputStream thread brings another
|
||||
* overhead and latency. The final solution is to use a combination of the
|
||||
* special thread for complex stuff like datastore preparation and synchronous
|
||||
* IPC messages sent directly from the main thread for database access when data
|
||||
* is already loaded from disk into memory.
|
||||
*
|
||||
* Requests
|
||||
* ~~~~~~~~
|
||||
|
@ -116,13 +116,13 @@
|
|||
* responses and do safe main thread blocking at the same time.
|
||||
* It inherits from the "Runnable" class, so instances are ref counted and
|
||||
* they are internally used on multiple threads (specifically on the main
|
||||
* thread and on the DOM File thread). Anyway, users should create and use
|
||||
* instances of this class only on the main thread (apart from a special case
|
||||
* when we need to cancel the request from an internal chromium IPC thread to
|
||||
* prevent a dead lock involving CPOWs).
|
||||
* thread and on the RemoteLazyInputStream thread). Anyway, users should create
|
||||
* and use instances of this class only on the main thread (apart from a special
|
||||
* case when we need to cancel the request from an internal chromium IPC thread
|
||||
* to prevent a dead lock involving CPOWs).
|
||||
* The actual child actor is represented by the "LSRequestChild" class that
|
||||
* implements the "PBackgroundLSRequestChild" interface. An "LSRequestChild"
|
||||
* instance is not ref counted and lives on the DOM File thread.
|
||||
* instance is not ref counted and lives on the RemoteLazyInputStream thread.
|
||||
* Request responses are passed using the "LSRequestChildCallback" interface.
|
||||
*
|
||||
* Preparation of a datastore
|
||||
|
@ -157,9 +157,10 @@
|
|||
* In theory, the datastore preparation request could return a database actor
|
||||
* directly (instead of returning an id intended for database linking to a
|
||||
* datastore). However, as it was explained above, the preparation must be done
|
||||
* on the DOM File thread and database objects are used on the main thread. The
|
||||
* returned actor would have to be migrated from the DOM File thread to the
|
||||
* main thread and that's something which our IPDL doesn't support yet.
|
||||
* on the RemoteLazyInputStream thread and database objects are used on the main
|
||||
* thread. The returned actor would have to be migrated from the
|
||||
* RemoteLazyInputStream thread to the main thread and that's something which
|
||||
* our IPDL doesn't support yet.
|
||||
*
|
||||
* Exposing local storage
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -19,12 +19,12 @@ class AsyncRequestHelper final : public Runnable,
|
|||
public LSRequestChildCallback {
|
||||
enum class State {
|
||||
/**
|
||||
* The AsyncRequestHelper has been created and dispatched to the DOM File
|
||||
* Thread.
|
||||
* The AsyncRequestHelper has been created and dispatched to the
|
||||
* RemoteLazyInputStream Thread.
|
||||
*/
|
||||
Initial,
|
||||
/**
|
||||
* Start() has been invoked on the DOM File Thread and
|
||||
* Start() has been invoked on the RemoteLazyInputStream Thread and
|
||||
* LocalStorageManager2::StartRequest has been invoked from there, sending
|
||||
* an IPC message to PBackground to service the request. We stay in this
|
||||
* state until a response is received.
|
||||
|
@ -300,9 +300,10 @@ LocalStorageManager2::Preload(nsIPrincipal* aPrincipal, JSContext* aContext,
|
|||
RefPtr<AsyncRequestHelper> helper =
|
||||
new AsyncRequestHelper(this, promise, params);
|
||||
|
||||
// This will start and finish the async request on the DOM File thread.
|
||||
// This must be done on DOM File Thread because it's very likely that a
|
||||
// content process will issue a prepare datastore request for the same
|
||||
// This will start and finish the async request on the RemoteLazyInputStream
|
||||
// thread.
|
||||
// This must be done on RemoteLazyInputStream Thread because it's very likely
|
||||
// that a content process will issue a prepare datastore request for the same
|
||||
// principal while blocking the content process on the main thread.
|
||||
// There would be a potential for deadlock if the preloading was initialized
|
||||
// from the main thread of the parent process and a11y issued a synchronous
|
||||
|
@ -406,7 +407,7 @@ nsresult AsyncRequestHelper::Dispatch() {
|
|||
AssertIsOnOwningThread();
|
||||
|
||||
nsCOMPtr<nsIEventTarget> domFileThread =
|
||||
IPCBlobInputStreamThread::GetOrCreate();
|
||||
RemoteLazyInputStreamThread::GetOrCreate();
|
||||
if (NS_WARN_IF(!domFileThread)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
|
@ -93,7 +93,8 @@ child:
|
|||
* Cancel() would be received by the parent after it had already sent
|
||||
* __delete__. (Which may no longer be fatal thanks to improvements to the
|
||||
* IPC layer, but it would still lead to warnings, etc. And we don't
|
||||
* expect PBackground to be highly contended nor the DOM File thread.)
|
||||
* expect PBackground to be highly contended nor the RemoteLazyInputStream
|
||||
* thread.)
|
||||
*/
|
||||
async Ready();
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче