summaryrefslogtreecommitdiffstats
path: root/toolkit/components/sessionstore/SessionStoreChild.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/sessionstore/SessionStoreChild.cpp')
-rw-r--r--toolkit/components/sessionstore/SessionStoreChild.cpp261
1 files changed, 261 insertions, 0 deletions
diff --git a/toolkit/components/sessionstore/SessionStoreChild.cpp b/toolkit/components/sessionstore/SessionStoreChild.cpp
new file mode 100644
index 0000000000..0b6d0dd17e
--- /dev/null
+++ b/toolkit/components/sessionstore/SessionStoreChild.cpp
@@ -0,0 +1,261 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 "mozilla/dom/SessionStoreChild.h"
+
+#include "mozilla/AlreadyAddRefed.h"
+#include "mozilla/Assertions.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/ScopeExit.h"
+#include "mozilla/dom/BrowserChild.h"
+#include "mozilla/dom/BrowsingContext.h"
+#include "mozilla/dom/InProcessChild.h"
+#include "mozilla/dom/InProcessParent.h"
+#include "mozilla/dom/BrowserSessionStore.h"
+#include "mozilla/dom/SessionStoreChangeListener.h"
+#include "mozilla/dom/SessionStoreParent.h"
+#include "mozilla/dom/WindowGlobalParent.h"
+#include "mozilla/ipc/Endpoint.h"
+#include "nsCOMPtr.h"
+#include "nsFrameLoader.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
+
+class nsIDocShell;
+
+static already_AddRefed<TabListener> CreateTabListener(nsIDocShell* aDocShell) {
+ RefPtr<TabListener> tabListener =
+ mozilla::MakeRefPtr<TabListener>(aDocShell, nullptr);
+ nsresult rv = tabListener->Init();
+ if (NS_FAILED(rv)) {
+ return nullptr;
+ }
+
+ return tabListener.forget();
+}
+
+already_AddRefed<SessionStoreChild> SessionStoreChild::GetOrCreate(
+ BrowsingContext* aBrowsingContext, Element* aOwnerElement) {
+ RefPtr<TabListener> tabListener =
+ CreateTabListener(aBrowsingContext->GetDocShell());
+ if (!tabListener) {
+ return nullptr;
+ }
+
+ RefPtr<SessionStoreChangeListener> sessionStoreChangeListener =
+ SessionStoreChangeListener::Create(aBrowsingContext);
+ if (!sessionStoreChangeListener) {
+ return nullptr;
+ }
+
+ RefPtr<SessionStoreChild> sessionStoreChild =
+ new SessionStoreChild(tabListener, sessionStoreChangeListener);
+
+ sessionStoreChangeListener->SetActor(sessionStoreChild);
+
+ if (XRE_IsParentProcess()) {
+ MOZ_DIAGNOSTIC_ASSERT(aOwnerElement);
+ InProcessChild* inProcessChild = InProcessChild::Singleton();
+ InProcessParent* inProcessParent = InProcessParent::Singleton();
+ if (!inProcessChild || !inProcessParent) {
+ return nullptr;
+ }
+
+ RefPtr<BrowserSessionStore> sessionStore =
+ BrowserSessionStore::GetOrCreate(aBrowsingContext->Canonical()->Top());
+ if (!sessionStore) {
+ return nullptr;
+ }
+
+ CanonicalBrowsingContext* browsingContext = aBrowsingContext->Canonical();
+ RefPtr<SessionStoreParent> sessionStoreParent =
+ new SessionStoreParent(browsingContext, sessionStore);
+ ManagedEndpoint<PSessionStoreParent> endpoint =
+ inProcessChild->OpenPSessionStoreEndpoint(sessionStoreChild);
+ inProcessParent->BindPSessionStoreEndpoint(std::move(endpoint),
+ sessionStoreParent);
+ } else {
+ MOZ_DIAGNOSTIC_ASSERT(!aOwnerElement);
+ RefPtr<BrowserChild> browserChild =
+ BrowserChild::GetFrom(aBrowsingContext->GetDOMWindow());
+
+ MOZ_DIAGNOSTIC_ASSERT(browserChild);
+ MOZ_DIAGNOSTIC_ASSERT(aBrowsingContext->IsInProcess());
+ sessionStoreChild = static_cast<SessionStoreChild*>(
+ browserChild->SendPSessionStoreConstructor(sessionStoreChild));
+ }
+
+ return sessionStoreChild.forget();
+}
+
+/* static */
+SessionStoreChild* SessionStoreChild::From(WindowGlobalChild* aWindowChild) {
+ if (!aWindowChild) {
+ return nullptr;
+ }
+
+ // If `aWindowChild` is inprocess
+ if (RefPtr<BrowserChild> browserChild = aWindowChild->GetBrowserChild()) {
+ return browserChild->GetSessionStoreChild();
+ }
+
+ if (XRE_IsContentProcess()) {
+ return nullptr;
+ }
+
+ WindowGlobalParent* windowParent = aWindowChild->WindowContext()->Canonical();
+ if (!windowParent) {
+ return nullptr;
+ }
+
+ RefPtr<nsFrameLoader> frameLoader = windowParent->GetRootFrameLoader();
+ if (!frameLoader) {
+ return nullptr;
+ }
+
+ return frameLoader->GetSessionStoreChild();
+}
+
+SessionStoreChild::SessionStoreChild(
+ TabListener* aSessionStoreListener,
+ SessionStoreChangeListener* aSessionStoreChangeListener)
+ : mSessionStoreListener(aSessionStoreListener),
+ mSessionStoreChangeListener(aSessionStoreChangeListener) {}
+
+void SessionStoreChild::SetEpoch(uint32_t aEpoch) {
+ if (mSessionStoreListener) {
+ mSessionStoreListener->SetEpoch(aEpoch);
+ }
+
+ if (mSessionStoreChangeListener) {
+ mSessionStoreChangeListener->SetEpoch(aEpoch);
+ }
+}
+
+void SessionStoreChild::SetOwnerContent(Element* aElement) {
+ if (mSessionStoreChangeListener) {
+ mSessionStoreChangeListener->FlushSessionStore();
+ }
+
+ if (!aElement) {
+ return;
+ }
+
+ if (mSessionStoreListener) {
+ mSessionStoreListener->SetOwnerContent(aElement);
+ }
+}
+
+void SessionStoreChild::Stop() {
+ if (mSessionStoreListener) {
+ mSessionStoreListener->RemoveListeners();
+ mSessionStoreListener = nullptr;
+ }
+
+ if (mSessionStoreChangeListener) {
+ mSessionStoreChangeListener->Stop();
+ }
+}
+
+void SessionStoreChild::UpdateEventTargets() {
+ if (mSessionStoreChangeListener) {
+ mSessionStoreChangeListener->UpdateEventTargets();
+ }
+}
+
+void SessionStoreChild::UpdateSessionStore(bool aSessionHistoryUpdate,
+ const MaybeSessionStoreZoom& aZoom) {
+ if (!mSessionStoreListener) {
+ // This is the case when we're shutting down, and expect a final update.
+ SessionStoreUpdate(Nothing(), Nothing(), Nothing(), aSessionHistoryUpdate,
+ 0);
+ return;
+ }
+
+ RefPtr<ContentSessionStore> store = mSessionStoreListener->GetSessionStore();
+
+ Maybe<nsCString> docShellCaps;
+ if (store->IsDocCapChanged()) {
+ docShellCaps.emplace(store->GetDocShellCaps());
+ }
+
+ Maybe<bool> privatedMode;
+ if (store->IsPrivateChanged()) {
+ privatedMode.emplace(store->GetPrivateModeEnabled());
+ }
+
+ SessionStoreUpdate(
+ docShellCaps, privatedMode, aZoom,
+ store->GetAndClearSHistoryChanged() || aSessionHistoryUpdate,
+ mSessionStoreListener->GetEpoch());
+}
+
+void SessionStoreChild::FlushSessionStore() {
+ if (mSessionStoreChangeListener) {
+ mSessionStoreChangeListener->FlushSessionStore();
+ }
+}
+
+void SessionStoreChild::UpdateSHistoryChanges() {
+ if (mSessionStoreListener) {
+ mSessionStoreListener->UpdateSHistoryChanges();
+ }
+}
+
+mozilla::ipc::IPCResult SessionStoreChild::RecvFlushTabState(
+ FlushTabStateResolver&& aResolver) {
+ if (mSessionStoreChangeListener) {
+ mSessionStoreChangeListener->FlushSessionStore();
+ }
+ aResolver(true);
+
+ return IPC_OK();
+}
+
+void SessionStoreChild::SessionStoreUpdate(
+ const Maybe<nsCString>& aDocShellCaps, const Maybe<bool>& aPrivatedMode,
+ const MaybeSessionStoreZoom& aZoom, const bool aNeedCollectSHistory,
+ const uint32_t& aEpoch) {
+ if (XRE_IsContentProcess()) {
+ Unused << SendSessionStoreUpdate(aDocShellCaps, aPrivatedMode, aZoom,
+ aNeedCollectSHistory, aEpoch);
+ } else if (SessionStoreParent* sessionStoreParent =
+ static_cast<SessionStoreParent*>(
+ InProcessChild::ParentActorFor(this))) {
+ sessionStoreParent->SessionStoreUpdate(aDocShellCaps, aPrivatedMode, aZoom,
+ aNeedCollectSHistory, aEpoch);
+ }
+}
+
+void SessionStoreChild::IncrementalSessionStoreUpdate(
+ const MaybeDiscarded<BrowsingContext>& aBrowsingContext,
+ const Maybe<FormData>& aFormData, const Maybe<nsPoint>& aScrollPosition,
+ uint32_t aEpoch) {
+ if (XRE_IsContentProcess()) {
+ Unused << SendIncrementalSessionStoreUpdate(aBrowsingContext, aFormData,
+ aScrollPosition, aEpoch);
+ } else if (SessionStoreParent* sessionStoreParent =
+ static_cast<SessionStoreParent*>(
+ InProcessChild::ParentActorFor(this))) {
+ sessionStoreParent->IncrementalSessionStoreUpdate(
+ aBrowsingContext, aFormData, aScrollPosition, aEpoch);
+ }
+}
+
+void SessionStoreChild::ResetSessionStore(
+ const MaybeDiscarded<BrowsingContext>& aBrowsingContext, uint32_t aEpoch) {
+ if (XRE_IsContentProcess()) {
+ Unused << SendResetSessionStore(aBrowsingContext, aEpoch);
+ } else if (SessionStoreParent* sessionStoreParent =
+ static_cast<SessionStoreParent*>(
+ InProcessChild::ParentActorFor(this))) {
+ sessionStoreParent->ResetSessionStore(aBrowsingContext, aEpoch);
+ }
+}
+
+NS_IMPL_CYCLE_COLLECTION(SessionStoreChild, mSessionStoreListener,
+ mSessionStoreChangeListener)