mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-16 23:05:42 +00:00
Part 9: Bug 1700623 - Notify main thread about storage updates periodically. r=asuth
This is used to update session store storage contents continuously. Depends on D111435 Differential Revision: https://phabricator.services.mozilla.com/D114586
This commit is contained in:
parent
046cb66bae
commit
3dd66dc912
@ -299,6 +299,8 @@ class CanonicalBrowsingContext final : public BrowsingContext {
|
||||
|
||||
void UpdateSessionStoreSessionStorage(const std::function<void()>& aDone);
|
||||
|
||||
static void UpdateSessionStoreForStorage(uint64_t aBrowsingContextId);
|
||||
|
||||
// Called when a BrowserParent for this BrowsingContext has been fully
|
||||
// destroyed (i.e. `ActorDestroy` was called).
|
||||
void BrowserParentDestroyed(BrowserParent* aBrowserParent,
|
||||
|
@ -53,6 +53,8 @@ void RecvPropagateBackgroundSessionStorageManager(
|
||||
if (sManagers) {
|
||||
if (RefPtr<BackgroundSessionStorageManager> mgr =
|
||||
sManagers->Get(aCurrentTopContextId)) {
|
||||
mgr->MaybeDispatchSessionStoreUpdate();
|
||||
mgr->SetCurrentBrowsingContextId(aTargetTopContextId);
|
||||
// Because of bfcache, we may re-register aTargetTopContextId in
|
||||
// CanonicalBrowsingContext::ReplacedBy.
|
||||
// XXXBFCache do we want to tweak this behavior and ensure this is
|
||||
@ -66,14 +68,19 @@ bool RecvRemoveBackgroundSessionStorageManager(uint64_t aTopContextId) {
|
||||
::mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
|
||||
if (sManagers) {
|
||||
sManagers->Remove(aTopContextId);
|
||||
RefPtr<BackgroundSessionStorageManager> mgr;
|
||||
sManagers->Remove(aTopContextId, getter_AddRefs(mgr));
|
||||
|
||||
if (mgr) {
|
||||
mgr->CancelSessionStoreUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RecvGetSessionStorageData(
|
||||
uint64_t aTopContextId, uint32_t aSizeLimit,
|
||||
uint64_t aTopContextId, uint32_t aSizeLimit, bool aCancelSessionStoreTimer,
|
||||
::mozilla::ipc::PBackgroundParent::GetSessionStorageManagerDataResolver&&
|
||||
aResolver) {
|
||||
nsTArray<mozilla::dom::SSCacheCopy> data;
|
||||
@ -89,6 +96,8 @@ bool RecvGetSessionStorageData(
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aCancelSessionStoreTimer) {
|
||||
manager->CancelSessionStoreUpdate();
|
||||
}
|
||||
|
||||
manager->GetData(aSizeLimit, data);
|
||||
@ -660,12 +669,17 @@ BackgroundSessionStorageManager* BackgroundSessionStorageManager::GetOrCreate(
|
||||
}
|
||||
|
||||
return sManagers
|
||||
->LookupOrInsertWith(aTopContextId,
|
||||
[] { return new BackgroundSessionStorageManager(); })
|
||||
->LookupOrInsertWith(
|
||||
aTopContextId,
|
||||
[aTopContextId] {
|
||||
return new BackgroundSessionStorageManager(aTopContextId);
|
||||
})
|
||||
.get();
|
||||
}
|
||||
|
||||
BackgroundSessionStorageManager::BackgroundSessionStorageManager() {
|
||||
BackgroundSessionStorageManager::BackgroundSessionStorageManager(
|
||||
uint64_t aBrowsingContextId)
|
||||
: mCurrentBrowsingContextId(aBrowsingContextId) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
::mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
}
|
||||
@ -694,7 +708,8 @@ void BackgroundSessionStorageManager::CopyDataToContentProcess(
|
||||
/* static */
|
||||
RefPtr<BackgroundSessionStorageManager::DataPromise>
|
||||
BackgroundSessionStorageManager::GetData(BrowsingContext* aContext,
|
||||
uint32_t aSizeLimit) {
|
||||
uint32_t aSizeLimit,
|
||||
bool aClearSessionStoreTimer) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(aContext->IsTop());
|
||||
|
||||
@ -754,11 +769,70 @@ void BackgroundSessionStorageManager::UpdateData(
|
||||
GetOriginRecord(aOriginAttrs, aOriginKey, true, nullptr);
|
||||
MOZ_ASSERT(originRecord);
|
||||
|
||||
MaybeScheduleSessionStoreUpdate();
|
||||
|
||||
originRecord->mCache->DeserializeWriteInfos(
|
||||
SessionStorageCache::eDefaultSetType, aDefaultWriteInfos);
|
||||
originRecord->mCache->DeserializeWriteInfos(
|
||||
SessionStorageCache::eSessionSetType, aSessionWriteInfos);
|
||||
}
|
||||
|
||||
void BackgroundSessionStorageManager::SetCurrentBrowsingContextId(
|
||||
uint64_t aBrowsingContextId) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(aBrowsingContextId != mCurrentBrowsingContextId);
|
||||
mCurrentBrowsingContextId = aBrowsingContextId;
|
||||
}
|
||||
|
||||
void BackgroundSessionStorageManager::MaybeScheduleSessionStoreUpdate() {
|
||||
if (mSessionStoreCallbackTimer) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (StaticPrefs::browser_sessionstore_debug_no_auto_updates()) {
|
||||
DispatchSessionStoreUpdate();
|
||||
return;
|
||||
}
|
||||
|
||||
auto result = NS_NewTimerWithFuncCallback(
|
||||
[](nsITimer*, void* aClosure) {
|
||||
auto* mgr = static_cast<BackgroundSessionStorageManager*>(aClosure);
|
||||
mgr->DispatchSessionStoreUpdate();
|
||||
},
|
||||
this, StaticPrefs::browser_sessionstore_interval(),
|
||||
nsITimer::TYPE_ONE_SHOT,
|
||||
"BackgroundSessionStorageManager::DispatchSessionStoreUpdate");
|
||||
|
||||
if (result.isErr()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mSessionStoreCallbackTimer = result.unwrap();
|
||||
}
|
||||
|
||||
void BackgroundSessionStorageManager::MaybeDispatchSessionStoreUpdate() {
|
||||
if (mSessionStoreCallbackTimer) {
|
||||
BackgroundSessionStorageManager::DispatchSessionStoreUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void BackgroundSessionStorageManager::DispatchSessionStoreUpdate() {
|
||||
::mozilla::ipc::AssertIsOnBackgroundThread();
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||
"CanonicalBrowsingContext::UpdateSessionStore",
|
||||
[targetBrowsingContextId = mCurrentBrowsingContextId]() {
|
||||
CanonicalBrowsingContext::UpdateSessionStoreForStorage(
|
||||
targetBrowsingContextId);
|
||||
}));
|
||||
|
||||
CancelSessionStoreUpdate();
|
||||
}
|
||||
|
||||
void BackgroundSessionStorageManager::CancelSessionStoreUpdate() {
|
||||
if (mSessionStoreCallbackTimer) {
|
||||
mSessionStoreCallbackTimer->Cancel();
|
||||
mSessionStoreCallbackTimer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "mozilla/ipc/PBackgroundParent.h"
|
||||
|
||||
class nsIPrincipal;
|
||||
class nsITimer;
|
||||
|
||||
namespace mozilla {
|
||||
class OriginAttributesPattern;
|
||||
@ -31,7 +32,7 @@ void RecvPropagateBackgroundSessionStorageManager(uint64_t aCurrentTopContextId,
|
||||
bool RecvRemoveBackgroundSessionStorageManager(uint64_t aTopContextId);
|
||||
|
||||
bool RecvGetSessionStorageData(
|
||||
uint64_t aTopContextId, uint32_t aSizeLimit,
|
||||
uint64_t aTopContextId, uint32_t aSizeLimit, bool aCancelSessionStoreTimer,
|
||||
::mozilla::ipc::PBackgroundParent::GetSessionStorageManagerDataResolver&&
|
||||
aResolver);
|
||||
|
||||
@ -182,7 +183,8 @@ class BackgroundSessionStorageManager final : public SessionStorageManagerBase {
|
||||
using DataPromise =
|
||||
::mozilla::ipc::PBackgroundChild::GetSessionStorageManagerDataPromise;
|
||||
static RefPtr<DataPromise> GetData(BrowsingContext* aContext,
|
||||
uint32_t aSizeLimit);
|
||||
uint32_t aSizeLimit,
|
||||
bool aClearSessionStoreTimer = false);
|
||||
|
||||
void GetData(uint32_t aSizeLimit, nsTArray<SSCacheCopy>& aCacheCopyList);
|
||||
|
||||
@ -195,11 +197,56 @@ class BackgroundSessionStorageManager final : public SessionStorageManagerBase {
|
||||
const nsTArray<SSWriteInfo>& aDefaultWriteInfos,
|
||||
const nsTArray<SSWriteInfo>& aSessionWriteInfos);
|
||||
|
||||
void SetCurrentBrowsingContextId(uint64_t aBrowsingContextId);
|
||||
|
||||
void MaybeDispatchSessionStoreUpdate();
|
||||
|
||||
void CancelSessionStoreUpdate();
|
||||
|
||||
private:
|
||||
// Only be called by GetOrCreate() on the parent process.
|
||||
explicit BackgroundSessionStorageManager();
|
||||
explicit BackgroundSessionStorageManager(uint64_t aBrowsingContextId);
|
||||
|
||||
~BackgroundSessionStorageManager();
|
||||
|
||||
// Sets a timer for notifying main thread that the cache has been
|
||||
// updated. May do nothing if we're coalescing notifications.
|
||||
void MaybeScheduleSessionStoreUpdate();
|
||||
|
||||
void DispatchSessionStoreUpdate();
|
||||
|
||||
// The most current browsing context using this manager
|
||||
uint64_t mCurrentBrowsingContextId;
|
||||
|
||||
// Callback for notifying main thread of calls to `UpdateData`.
|
||||
//
|
||||
// A timer that is held whenever this manager has dirty state that
|
||||
// has not yet been reflected to the main thread. The timer is used
|
||||
// to delay notifying the main thread to ask for changes, thereby
|
||||
// coalescing/throttling changes. (Note that SessionStorage, like
|
||||
// LocalStorage, treats attempts to set a value to its current value
|
||||
// as a no-op.)
|
||||
//
|
||||
|
||||
// The timer is initialized with a fixed delay as soon as the state
|
||||
// becomes dirty; additional mutations to our state will not reset
|
||||
// the timer because then we might never flush to the main
|
||||
// thread. The timer is cleared only when a new set of data is sent
|
||||
// to the main thread and therefore this manager no longer has any
|
||||
// dirty state. This means that there is a period of time after the
|
||||
// nsITimer fires where this value is non-null but there is no
|
||||
// scheduled timer while we wait for the main thread to request the
|
||||
// new state. Callers of GetData can also optionally cancel the
|
||||
// current timer to reduce the amounts of notifications.
|
||||
//
|
||||
// When this manager is moved to a new top-level browsing context id
|
||||
// via a PropagateBackgroundSessionStorageManager message, the
|
||||
// behavior of the timer doesn't change because the main thread knows
|
||||
// about the renaming and is initiating it (and any in-flight
|
||||
// GetSessionStorageManagerData requests will be unaffected because
|
||||
// they use async-returns so the response is inherently matched up via
|
||||
// the issued promise).
|
||||
nsCOMPtr<nsITimer> mSessionStoreCallbackTimer;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -1142,6 +1142,7 @@ BackgroundParentImpl::RecvRemoveBackgroundSessionStorageManager(
|
||||
|
||||
mozilla::ipc::IPCResult BackgroundParentImpl::RecvGetSessionStorageManagerData(
|
||||
const uint64_t& aTopContextId, const uint32_t& aSizeLimit,
|
||||
const bool& aCancelSessionStoreTimer,
|
||||
GetSessionStorageManagerDataResolver&& aResolver) {
|
||||
AssertIsInMainProcess();
|
||||
AssertIsOnBackgroundThread();
|
||||
@ -1151,6 +1152,7 @@ mozilla::ipc::IPCResult BackgroundParentImpl::RecvGetSessionStorageManagerData(
|
||||
}
|
||||
|
||||
if (!mozilla::dom::RecvGetSessionStorageData(aTopContextId, aSizeLimit,
|
||||
aCancelSessionStoreTimer,
|
||||
std::move(aResolver))) {
|
||||
return IPC_FAIL(this, "Couldn't get session storage data");
|
||||
}
|
||||
|
@ -320,6 +320,7 @@ class BackgroundParentImpl : public PBackgroundParent,
|
||||
|
||||
mozilla::ipc::IPCResult RecvGetSessionStorageManagerData(
|
||||
const uint64_t& aTopContextId, const uint32_t& aSizeLimit,
|
||||
const bool& aCancelSessionStoreTimer,
|
||||
GetSessionStorageManagerDataResolver&& aResolver) override;
|
||||
|
||||
already_AddRefed<PFileSystemRequestParent> AllocPFileSystemRequestParent(
|
||||
|
@ -211,7 +211,7 @@ parent:
|
||||
async RemoveBackgroundSessionStorageManager(uint64_t topContextId);
|
||||
|
||||
async GetSessionStorageManagerData(
|
||||
uint64_t aTopContextId, uint32_t aSizeLimit)
|
||||
uint64_t aTopContextId, uint32_t aSizeLimit, bool aCancelSessionStoreTimer)
|
||||
returns(SSCacheCopy[] aCacheCopy);
|
||||
|
||||
async PFileSystemRequest(FileSystemParams params);
|
||||
|
@ -1241,7 +1241,7 @@
|
||||
|
||||
# Minimal interval between two save operations in milliseconds (while the user is active).
|
||||
- name: browser.sessionstore.interval
|
||||
type: uint32_t
|
||||
type: RelaxedAtomicUint32
|
||||
value: 15000
|
||||
mirror: always
|
||||
|
||||
@ -1249,7 +1249,7 @@
|
||||
# browser tabs that were not caused by a flush from the parent.
|
||||
# This is a testing flag and should not be used by end-users.
|
||||
- name: browser.sessionstore.debug.no_auto_updates
|
||||
type: bool
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user