diff options
Diffstat (limited to '')
-rw-r--r-- | toolkit/components/sessionstore/RestoreTabContentObserver.cpp | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/toolkit/components/sessionstore/RestoreTabContentObserver.cpp b/toolkit/components/sessionstore/RestoreTabContentObserver.cpp new file mode 100644 index 0000000000..b0dda66ff0 --- /dev/null +++ b/toolkit/components/sessionstore/RestoreTabContentObserver.cpp @@ -0,0 +1,112 @@ +/* -*- Mode: C++; tab-width: 2; 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 "mozilla/dom/BrowsingContext.h" +#include "mozilla/dom/CanonicalBrowsingContext.h" +#include "mozilla/dom/Document.h" +#include "mozilla/dom/WindowGlobalChild.h" +#include "mozilla/dom/WindowGlobalParent.h" +#include "mozilla/Services.h" +#include "nsIObserverService.h" +#include "nsIURI.h" +#include "nsNetUtil.h" +#include "nsPIDOMWindow.h" +#include "nsReadableUtils.h" +#include "nsThreadUtils.h" +#include "RestoreTabContentObserver.h" + +using namespace mozilla::dom; + +NS_IMPL_ISUPPORTS(RestoreTabContentObserver, nsIObserver) + +const char* const kAboutReaderTopic = "AboutReader:Ready"; +const char* const kContentDocumentLoaded = "content-document-loaded"; +const char* const kChromeDocumentLoaded = "chrome-document-loaded"; + +/* static */ +void RestoreTabContentObserver::Initialize() { + MOZ_ASSERT(!gRestoreTabContentObserver); + MOZ_ASSERT(NS_IsMainThread()); + + RefPtr<RestoreTabContentObserver> observer = new RestoreTabContentObserver(); + + nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); + if (NS_WARN_IF(!obs)) { + return; + } + + obs->AddObserver(observer, kAboutReaderTopic, false); + obs->AddObserver(observer, kContentDocumentLoaded, false); + obs->AddObserver(observer, kChromeDocumentLoaded, false); + + gRestoreTabContentObserver = observer; +} + +/* static */ +void RestoreTabContentObserver::Shutdown() { + MOZ_ASSERT(NS_IsMainThread()); + + if (!gRestoreTabContentObserver) { + return; + } + + RefPtr<RestoreTabContentObserver> observer = gRestoreTabContentObserver; + gRestoreTabContentObserver = nullptr; + + nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); + if (!obs) { + return; + } + + obs->RemoveObserver(observer, kAboutReaderTopic); + obs->RemoveObserver(observer, kContentDocumentLoaded); + obs->RemoveObserver(observer, kChromeDocumentLoaded); +} + +NS_IMETHODIMP +RestoreTabContentObserver::Observe(nsISupports* aSubject, const char* aTopic, + const char16_t* aData) { + nsCOMPtr<nsPIDOMWindowInner> inner; + if (!strcmp(aTopic, kAboutReaderTopic)) { + inner = do_QueryInterface(aSubject); + } else if (!strcmp(aTopic, kContentDocumentLoaded) || + !strcmp(aTopic, kChromeDocumentLoaded)) { + nsCOMPtr<Document> doc = do_QueryInterface(aSubject); + inner = doc ? doc->GetInnerWindow() : nullptr; + } + if (!inner) { + return NS_OK; + } + + nsCOMPtr<nsIURI> uri = inner->GetDocumentURI(); + if (!uri) { + return NS_OK; + } + + // We'll handle loading about:reader with "AboutReader:Ready" + // rather than "content-document-loaded". + if (uri->SchemeIs("about") && + StringBeginsWith(uri->GetSpecOrDefault(), "about:reader"_ns) && + strcmp(aTopic, kAboutReaderTopic) != 0) { + return NS_OK; + } + + RefPtr<BrowsingContext> bc = inner->GetBrowsingContext(); + if (!bc || !bc->Top()->GetHasRestoreData()) { + return NS_OK; + } + if (XRE_IsParentProcess()) { + if (WindowGlobalParent* wgp = bc->Canonical()->GetCurrentWindowGlobal()) { + bc->Canonical()->Top()->RequestRestoreTabContent(wgp); + } + } else if (WindowContext* windowContext = bc->GetCurrentWindowContext()) { + if (WindowGlobalChild* wgc = windowContext->GetWindowGlobalChild()) { + wgc->SendRequestRestoreTabContent(); + } + } + return NS_OK; +} + +mozilla::StaticRefPtr<RestoreTabContentObserver> + RestoreTabContentObserver::gRestoreTabContentObserver; |