Skip to content

Commit

Permalink
Bug 1824847: Maintain number of active WebTransports per document for…
Browse files Browse the repository at this point in the history
… controlling BFCache entry r=smaug,saschanaz

Differential Revision: https://phabricator.services.mozilla.com/D173769
  • Loading branch information
jesup committed Apr 15, 2023
1 parent c10ddbf commit 533105f
Show file tree
Hide file tree
Showing 26 changed files with 625 additions and 0 deletions.
7 changes: 7 additions & 0 deletions dom/base/Document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11417,6 +11417,13 @@ bool Document::CanSavePresentation(nsIRequest* aNewRequest,
aBFCacheCombo |= BFCacheStatus::ACTIVE_LOCK;
ret = false;
}

if (win->HasActiveWebTransports()) {
MOZ_LOG(gPageCacheLog, mozilla::LogLevel::Verbose,
("Save of %s blocked due to WebTransport", uri.get()));
aBFCacheCombo |= BFCacheStatus::ACTIVE_WEBTRANSPORT;
ret = false;
}
}

return ret;
Expand Down
1 change: 1 addition & 0 deletions dom/base/Document.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ enum BFCacheStatus {
RESTORING = 1 << 14, // Status 14
BEFOREUNLOAD_LISTENER = 1 << 15, // Status 15
ACTIVE_LOCK = 1 << 16, // Status 16
ACTIVE_WEBTRANSPORT = 1 << 17, // Status 17
};

} // namespace dom
Expand Down
12 changes: 12 additions & 0 deletions dom/base/nsPIDOMWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,13 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
};
bool HasActiveLocks() { return mLockCount > 0; }

uint32_t UpdateWebTransportCount(bool aIncrement) {
MOZ_ASSERT_IF(!aIncrement, mWebTransportCount > 0);
mWebTransportCount += aIncrement ? 1 : -1;
return mWebTransportCount;
};
bool HasActiveWebTransports() { return mWebTransportCount > 0; }

protected:
void CreatePerformanceObjectIfNeeded();

Expand Down Expand Up @@ -758,6 +765,11 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
* workers.
*/
uint32_t mLockCount = 0;
/**
* Count of the number of active WebTransport objects, including ones from
* workers.
*/
uint32_t mWebTransportCount = 0;
};

NS_DEFINE_STATIC_IID_ACCESSOR(nsPIDOMWindowInner, NS_PIDOMWINDOWINNER_IID)
Expand Down
4 changes: 4 additions & 0 deletions dom/serviceworkers/ServiceWorkerPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,10 @@ class ServiceWorkerPrivate final : public RemoteWorkerObserver {
// no-op for service workers
}

void WebTransportNotified(bool aCreated) final {
// no-op for service workers
}

void Terminated() override;

// Refreshes only the parts of mRemoteWorkerData that may change over time.
Expand Down
77 changes: 77 additions & 0 deletions dom/webtransport/api/WebTransport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,19 @@
#include "nsIURL.h"
#include "nsIWebTransportStream.h"
#include "mozilla/Assertions.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/DOMExceptionBinding.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/PWebTransport.h"
#include "mozilla/dom/ReadableStream.h"
#include "mozilla/dom/ReadableStreamDefaultController.h"
#include "mozilla/dom/RemoteWorkerChild.h"
#include "mozilla/dom/WebTransportDatagramDuplexStream.h"
#include "mozilla/dom/WebTransportError.h"
#include "mozilla/dom/WebTransportLog.h"
#include "mozilla/dom/WindowGlobalChild.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/WorkerRunnable.h"
#include "mozilla/dom/WritableStream.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/Endpoint.h"
Expand Down Expand Up @@ -165,6 +170,9 @@ already_AddRefed<WebTransport> WebTransport::Constructor(
return nullptr;
}

// Don't let this document go into BFCache
result->NotifyToWindow(true);

// Step 25 Return transport
return result.forget();
}
Expand Down Expand Up @@ -770,6 +778,75 @@ void WebTransport::Cleanup(WebTransportError* aError,
// Let go of the algorithms
mIncomingBidirectionalAlgorithm = nullptr;
mIncomingUnidirectionalAlgorithm = nullptr;

// We no longer block BFCache
NotifyToWindow(false);
}

void WebTransport::NotifyBFCacheOnMainThread(nsPIDOMWindowInner* aInner,
bool aCreated) {
AssertIsOnMainThread();
if (!aInner) {
return;
}
if (aCreated) {
aInner->RemoveFromBFCacheSync();
}

uint32_t count = aInner->UpdateWebTransportCount(aCreated);
// It's okay for WindowGlobalChild to not exist, as it should mean it already
// is destroyed and can't enter bfcache anyway.
if (WindowGlobalChild* child = aInner->GetWindowGlobalChild()) {
if (aCreated && count == 1) {
// The first WebTransport is active.
child->BlockBFCacheFor(BFCacheStatus::ACTIVE_WEBTRANSPORT);
} else if (count == 0) {
child->UnblockBFCacheFor(BFCacheStatus::ACTIVE_WEBTRANSPORT);
}
}
}

class BFCacheNotifyWTRunnable final : public WorkerProxyToMainThreadRunnable {
public:
explicit BFCacheNotifyWTRunnable(bool aCreated) : mCreated(aCreated) {}

void RunOnMainThread(WorkerPrivate* aWorkerPrivate) override {
MOZ_ASSERT(aWorkerPrivate);
AssertIsOnMainThread();
if (aWorkerPrivate->IsDedicatedWorker()) {
WebTransport::NotifyBFCacheOnMainThread(
aWorkerPrivate->GetAncestorWindow(), mCreated);
return;
}
if (aWorkerPrivate->IsSharedWorker()) {
aWorkerPrivate->GetRemoteWorkerController()->NotifyWebTransport(mCreated);
return;
}
MOZ_ASSERT_UNREACHABLE("Unexpected worker type");
}

void RunBackOnWorkerThreadForCleanup(WorkerPrivate* aWorkerPrivate) override {
MOZ_ASSERT(aWorkerPrivate);
aWorkerPrivate->AssertIsOnWorkerThread();
}

private:
bool mCreated;
};

void WebTransport::NotifyToWindow(bool aCreated) const {
if (NS_IsMainThread()) {
NotifyBFCacheOnMainThread(GetParentObject()->AsInnerWindow(), aCreated);
return;
}

WorkerPrivate* wp = GetCurrentThreadWorkerPrivate();
if (wp->IsDedicatedWorker() || wp->IsSharedWorker()) {
RefPtr<BFCacheNotifyWTRunnable> runnable =
new BFCacheNotifyWTRunnable(aCreated);

runnable->Dispatch(wp);
}
};

} // namespace mozilla::dom
5 changes: 5 additions & 0 deletions dom/webtransport/api/WebTransport.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "nsTArray.h"
#include "nsISupports.h"
#include "nsWrapperCache.h"
#include "nsPIDOMWindow.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/WebTransportBinding.h"
#include "mozilla/dom/WebTransportChild.h"
Expand Down Expand Up @@ -53,6 +54,10 @@ class WebTransport final : public nsISupports, public nsWrapperCache {

enum class WebTransportState { CONNECTING, CONNECTED, CLOSED, FAILED };

static void NotifyBFCacheOnMainThread(nsPIDOMWindowInner* aInner,
bool aCreated);
void NotifyToWindow(bool aCreated) const;

// this calls CreateReadableStream(), which in this case doesn't actually run
// script. See also bug 1810942
MOZ_CAN_RUN_SCRIPT_BOUNDARY void Init(const GlobalObject& aGlobal,
Expand Down
2 changes: 2 additions & 0 deletions dom/workers/remoteworkers/PRemoteWorker.ipdl
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ parent:

async NotifyLock(bool aCreated);

async NotifyWebTransport(bool aCreated);

async Close();

async SetServiceWorkerSkipWaitingFlag() returns (bool aOk);
Expand Down
13 changes: 13 additions & 0 deletions dom/workers/remoteworkers/RemoteWorkerChild.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,19 @@ void RemoteWorkerChild::NotifyLock(bool aCreated) {
GetActorEventTarget()->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
}

void RemoteWorkerChild::NotifyWebTransport(bool aCreated) {
nsCOMPtr<nsIRunnable> r =
NS_NewRunnableFunction(__func__, [self = RefPtr(this), aCreated] {
if (!self->CanSend()) {
return;
}

Unused << self->SendNotifyWebTransport(aCreated);
});

GetActorEventTarget()->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
}

void RemoteWorkerChild::FlushReportsOnMainThread(
nsIConsoleReportCollector* aReporter) {
AssertIsOnMainThread();
Expand Down
2 changes: 2 additions & 0 deletions dom/workers/remoteworkers/RemoteWorkerChild.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class RemoteWorkerChild final : public PRemoteWorkerChild {

void NotifyLock(bool aCreated);

void NotifyWebTransport(bool aCreated);

void FlushReportsOnMainThread(nsIConsoleReportCollector* aReporter);

void AddPortIdentifier(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
Expand Down
6 changes: 6 additions & 0 deletions dom/workers/remoteworkers/RemoteWorkerController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ void RemoteWorkerController::NotifyLock(bool aCreated) {
mObserver->LockNotified(aCreated);
}

void RemoteWorkerController::NotifyWebTransport(bool aCreated) {
AssertIsOnBackgroundThread();

mObserver->WebTransportNotified(aCreated);
}

void RemoteWorkerController::WorkerTerminated() {
AssertIsOnBackgroundThread();

Expand Down
4 changes: 4 additions & 0 deletions dom/workers/remoteworkers/RemoteWorkerController.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ class RemoteWorkerObserver {

virtual void LockNotified(bool aCreated) = 0;

virtual void WebTransportNotified(bool aCreated) = 0;

virtual void Terminated() = 0;
};

Expand Down Expand Up @@ -157,6 +159,8 @@ class RemoteWorkerController final {

bool IsTerminated() const;

void NotifyWebTransport(bool aCreated);

private:
RemoteWorkerController(const RemoteWorkerData& aData,
RemoteWorkerObserver* aObserver);
Expand Down
4 changes: 4 additions & 0 deletions dom/workers/remoteworkers/RemoteWorkerControllerParent.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ class RemoteWorkerControllerParent final : public PRemoteWorkerControllerParent,
// no-op for service workers
}

void WebTransportNotified(bool aCreated) final {
// no-op for service workers
}

void Terminated() override;

RefPtr<RemoteWorkerController> mRemoteWorkerController;
Expand Down
11 changes: 11 additions & 0 deletions dom/workers/remoteworkers/RemoteWorkerParent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,17 @@ IPCResult RemoteWorkerParent::RecvNotifyLock(const bool& aCreated) {
return IPC_OK();
}

IPCResult RemoteWorkerParent::RecvNotifyWebTransport(const bool& aCreated) {
AssertIsOnBackgroundThread();
MOZ_ASSERT(XRE_IsParentProcess());

if (mController) {
mController->NotifyWebTransport(aCreated);
}

return IPC_OK();
}

void RemoteWorkerParent::MaybeSendDelete() {
if (mDeleteSent) {
return;
Expand Down
2 changes: 2 additions & 0 deletions dom/workers/remoteworkers/RemoteWorkerParent.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class RemoteWorkerParent final : public PRemoteWorkerParent {

mozilla::ipc::IPCResult RecvNotifyLock(const bool& aCreated);

mozilla::ipc::IPCResult RecvNotifyWebTransport(const bool& aCreated);

mozilla::ipc::IPCResult RecvClose();

mozilla::ipc::IPCResult RecvCreated(const bool& aStatus);
Expand Down
1 change: 1 addition & 0 deletions dom/workers/sharedworkers/PSharedWorker.ipdl
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ parent:
child:
async Error(ErrorValue value);
async NotifyLock(bool aCreated);
async NotifyWebTransport(bool aCreated);
async Terminate();

async __delete__();
Expand Down
11 changes: 11 additions & 0 deletions dom/workers/sharedworkers/SharedWorkerChild.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "mozilla/dom/RootedDictionary.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/SharedWorker.h"
#include "mozilla/dom/WebTransport.h"
#include "mozilla/dom/WindowGlobalChild.h"
#include "mozilla/dom/WorkerError.h"
#include "mozilla/dom/locks/LockManagerChild.h"
Expand Down Expand Up @@ -132,6 +133,16 @@ IPCResult SharedWorkerChild::RecvNotifyLock(bool aCreated) {
return IPC_OK();
}

IPCResult SharedWorkerChild::RecvNotifyWebTransport(bool aCreated) {
if (!mParent) {
return IPC_OK();
}

WebTransport::NotifyBFCacheOnMainThread(mParent->GetOwner(), aCreated);

return IPC_OK();
}

IPCResult SharedWorkerChild::RecvTerminate() {
if (mParent) {
mParent->Close();
Expand Down
2 changes: 2 additions & 0 deletions dom/workers/sharedworkers/SharedWorkerChild.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ class SharedWorkerChild final : public mozilla::dom::PSharedWorkerChild {

mozilla::ipc::IPCResult RecvNotifyLock(bool aCreated);

mozilla::ipc::IPCResult RecvNotifyWebTransport(bool aCreated);

mozilla::ipc::IPCResult RecvTerminate();

void ActorDestroy(ActorDestroyReason aWhy) override;
Expand Down
20 changes: 20 additions & 0 deletions dom/workers/sharedworkers/SharedWorkerManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ void SharedWorkerManager::AddActor(SharedWorkerParent* aParent) {
Unused << aParent->SendNotifyLock(true);
}

if (mWebTransportCount) {
Unused << aParent->SendNotifyWebTransport(true);
}

// NB: We don't update our Suspended/Frozen state here, yet. The aParent is
// responsible for doing so from SharedWorkerParent::ManagerCreated.
// XXX But we could avoid iterating all of our actors because if aParent is
Expand Down Expand Up @@ -254,6 +258,22 @@ void SharedWorkerManager::LockNotified(bool aCreated) {
}
};

void SharedWorkerManager::WebTransportNotified(bool aCreated) {
::mozilla::ipc::AssertIsOnBackgroundThread();
MOZ_ASSERT_IF(!aCreated, mWebTransportCount > 0);

mWebTransportCount += aCreated ? 1 : -1;

// Notify only when we either:
// 1. Got a first WebTransport
// 2. The last WebTransport goes away
if ((aCreated && mWebTransportCount == 1) || mWebTransportCount == 0) {
for (SharedWorkerParent* actor : mActors) {
Unused << actor->SendNotifyWebTransport(aCreated);
}
}
};

void SharedWorkerManager::Terminated() {
::mozilla::ipc::AssertIsOnBackgroundThread();

Expand Down
3 changes: 3 additions & 0 deletions dom/workers/sharedworkers/SharedWorkerManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ class SharedWorkerManager final : public RemoteWorkerObserver {

void LockNotified(bool aCreated) final;

void WebTransportNotified(bool aCreated) final;

void Terminated() override;

// Called on PBackground thread methods
Expand Down Expand Up @@ -144,6 +146,7 @@ class SharedWorkerManager final : public RemoteWorkerObserver {
bool mSuspended;
bool mFrozen;
uint32_t mLockCount = 0;
uint32_t mWebTransportCount = 0;

// Raw pointers because SharedWorkerParent unregisters itself in
// ActorDestroy().
Expand Down
4 changes: 4 additions & 0 deletions testing/web-platform/mozilla/meta/webtransport/__dir__.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
prefs: [network.webtransport.enabled:true, network.webtransport.datagrams.enabled:true, security.OCSP.enabled:0]
# OCSP is disabled for this directory because we get errors from attempts to access the internet with it on
disabled:
if os == "android": 1823759
Loading

0 comments on commit 533105f

Please sign in to comment.