1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "mozilla/dom/BrowsingContext.h"
6 #include "mozilla/dom/CanonicalBrowsingContext.h"
7 #include "mozilla/dom/Document.h"
8 #include "mozilla/dom/WindowGlobalChild.h"
9 #include "mozilla/dom/WindowGlobalParent.h"
10 #include "mozilla/Services.h"
11 #include "nsIObserverService.h"
12 #include "nsIURI.h"
13 #include "nsNetUtil.h"
14 #include "nsPIDOMWindow.h"
15 #include "nsReadableUtils.h"
16 #include "nsThreadUtils.h"
17 #include "RestoreTabContentObserver.h"
18
19 using namespace mozilla::dom;
20
21 NS_IMPL_ISUPPORTS(RestoreTabContentObserver, nsIObserver)
22
23 const char* const kAboutReaderTopic = "AboutReader:Ready";
24 const char* const kContentDocumentLoaded = "content-document-loaded";
25 const char* const kChromeDocumentLoaded = "chrome-document-loaded";
26
27 /* static */
Initialize()28 void RestoreTabContentObserver::Initialize() {
29 MOZ_ASSERT(!gRestoreTabContentObserver);
30 MOZ_ASSERT(NS_IsMainThread());
31
32 RefPtr<RestoreTabContentObserver> observer = new RestoreTabContentObserver();
33
34 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
35 if (NS_WARN_IF(!obs)) {
36 return;
37 }
38
39 obs->AddObserver(observer, kAboutReaderTopic, false);
40 obs->AddObserver(observer, kContentDocumentLoaded, false);
41 obs->AddObserver(observer, kChromeDocumentLoaded, false);
42
43 gRestoreTabContentObserver = observer;
44 }
45
46 /* static */
Shutdown()47 void RestoreTabContentObserver::Shutdown() {
48 MOZ_ASSERT(NS_IsMainThread());
49
50 if (!gRestoreTabContentObserver) {
51 return;
52 }
53
54 RefPtr<RestoreTabContentObserver> observer = gRestoreTabContentObserver;
55 gRestoreTabContentObserver = nullptr;
56
57 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
58 if (!obs) {
59 return;
60 }
61
62 obs->RemoveObserver(observer, kAboutReaderTopic);
63 obs->RemoveObserver(observer, kContentDocumentLoaded);
64 obs->RemoveObserver(observer, kChromeDocumentLoaded);
65 }
66
67 NS_IMETHODIMP
Observe(nsISupports * aSubject,const char * aTopic,const char16_t * aData)68 RestoreTabContentObserver::Observe(nsISupports* aSubject, const char* aTopic,
69 const char16_t* aData) {
70 nsCOMPtr<nsPIDOMWindowInner> inner;
71 if (!strcmp(aTopic, kAboutReaderTopic)) {
72 inner = do_QueryInterface(aSubject);
73 } else if (!strcmp(aTopic, kContentDocumentLoaded) ||
74 !strcmp(aTopic, kChromeDocumentLoaded)) {
75 nsCOMPtr<Document> doc = do_QueryInterface(aSubject);
76 inner = doc ? doc->GetInnerWindow() : nullptr;
77 }
78 if (!inner) {
79 return NS_OK;
80 }
81
82 nsCOMPtr<nsIURI> uri = inner->GetDocumentURI();
83 if (!uri) {
84 return NS_OK;
85 }
86
87 // We'll handle loading about:reader with "AboutReader:Ready"
88 // rather than "content-document-loaded".
89 if (uri->SchemeIs("about") &&
90 StringBeginsWith(uri->GetSpecOrDefault(), "about:reader"_ns) &&
91 strcmp(aTopic, kAboutReaderTopic) != 0) {
92 return NS_OK;
93 }
94
95 RefPtr<BrowsingContext> bc = inner->GetBrowsingContext();
96 if (!bc || !bc->Top()->GetHasRestoreData()) {
97 return NS_OK;
98 }
99 if (XRE_IsParentProcess()) {
100 if (WindowGlobalParent* wgp = bc->Canonical()->GetCurrentWindowGlobal()) {
101 bc->Canonical()->Top()->RequestRestoreTabContent(wgp);
102 }
103 } else if (WindowContext* windowContext = bc->GetCurrentWindowContext()) {
104 if (WindowGlobalChild* wgc = windowContext->GetWindowGlobalChild()) {
105 wgc->SendRequestRestoreTabContent();
106 }
107 }
108 return NS_OK;
109 }
110
111 mozilla::StaticRefPtr<RestoreTabContentObserver>
112 RestoreTabContentObserver::gRestoreTabContentObserver;
113