NavigationHistoryEntry.cpp (5721B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/dom/NavigationHistoryEntry.h" 8 9 #include "mozilla/dom/Document.h" 10 #include "mozilla/dom/NavigationHistoryEntryBinding.h" 11 #include "mozilla/dom/SessionHistoryEntry.h" 12 #include "nsDocShell.h" 13 #include "nsGlobalWindowInner.h" 14 15 extern mozilla::LazyLogModule gNavigationAPILog; 16 17 namespace mozilla::dom { 18 19 NS_IMPL_CYCLE_COLLECTION_INHERITED(NavigationHistoryEntry, 20 DOMEventTargetHelper); 21 NS_IMPL_ADDREF_INHERITED(NavigationHistoryEntry, DOMEventTargetHelper) 22 NS_IMPL_RELEASE_INHERITED(NavigationHistoryEntry, DOMEventTargetHelper) 23 24 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(NavigationHistoryEntry) 25 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) 26 27 NavigationHistoryEntry::NavigationHistoryEntry( 28 nsIGlobalObject* aGlobal, const class SessionHistoryInfo* aSHInfo, 29 int64_t aIndex) 30 : DOMEventTargetHelper(aGlobal), 31 mSHInfo(MakeUnique<class SessionHistoryInfo>(*aSHInfo)), 32 mIndex(aIndex) {} 33 34 NavigationHistoryEntry::~NavigationHistoryEntry() = default; 35 36 // https://html.spec.whatwg.org/#dom-navigationhistoryentry-url 37 void NavigationHistoryEntry::GetUrl(nsAString& aResult) const { 38 if (!HasActiveDocument()) { 39 return; 40 } 41 42 // HasActiveDocument implies that GetAssociatedDocument returns non-null. 43 MOZ_DIAGNOSTIC_ASSERT(GetAssociatedDocument()); 44 45 if (!SameDocument()) { 46 const auto referrerPolicy = 47 GetAssociatedDocument()->ReferrerPolicyUsedToFetchThisDocument(); 48 if (referrerPolicy == ReferrerPolicy::No_referrer || 49 referrerPolicy == ReferrerPolicy::Origin) { 50 aResult.SetIsVoid(true); 51 return; 52 } 53 } 54 55 MOZ_ASSERT(mSHInfo); 56 nsCOMPtr<nsIURI> uri = mSHInfo->GetURI(); 57 MOZ_ASSERT(uri); 58 nsCString uriSpec; 59 uri->GetSpec(uriSpec); 60 CopyUTF8toUTF16(uriSpec, aResult); 61 } 62 63 // https://html.spec.whatwg.org/#dom-navigationhistoryentry-key 64 void NavigationHistoryEntry::GetKey(nsAString& aResult) const { 65 if (!HasActiveDocument()) { 66 return; 67 } 68 69 nsIDToCString keyString(mSHInfo->NavigationKey()); 70 // Omit the curly braces and NUL. 71 CopyUTF8toUTF16(Substring(keyString.get() + 1, NSID_LENGTH - 3), aResult); 72 } 73 74 // https://html.spec.whatwg.org/#dom-navigationhistoryentry-id 75 void NavigationHistoryEntry::GetId(nsAString& aResult) const { 76 if (!HasActiveDocument()) { 77 return; 78 } 79 80 nsIDToCString idString(mSHInfo->NavigationId()); 81 // Omit the curly braces and NUL. 82 CopyUTF8toUTF16(Substring(idString.get() + 1, NSID_LENGTH - 3), aResult); 83 } 84 85 // https://html.spec.whatwg.org/#dom-navigationhistoryentry-index 86 int64_t NavigationHistoryEntry::Index() const { 87 MOZ_ASSERT(mSHInfo); 88 if (!HasActiveDocument()) { 89 return -1; 90 } 91 return mIndex; 92 } 93 94 // https://html.spec.whatwg.org/#dom-navigationhistoryentry-samedocument 95 bool NavigationHistoryEntry::SameDocument() const { 96 if (!HasActiveDocument()) { 97 return false; 98 } 99 100 // HasActiveDocument implies that GetAssociatedDocument returns non-null. 101 MOZ_DIAGNOSTIC_ASSERT(GetAssociatedDocument()); 102 103 MOZ_ASSERT(mSHInfo); 104 auto* docShell = nsDocShell::Cast(GetAssociatedDocument()->GetDocShell()); 105 return docShell && docShell->IsSameDocumentAsActiveEntry(*mSHInfo); 106 } 107 108 // https://html.spec.whatwg.org/#dom-navigationhistoryentry-getstate 109 void NavigationHistoryEntry::GetState(JSContext* aCx, 110 JS::MutableHandle<JS::Value> aResult, 111 ErrorResult& aRv) const { 112 // Step 1 113 aResult.setUndefined(); 114 if (!HasActiveDocument()) { 115 return; 116 } 117 118 // Step 2 119 RefPtr<nsIStructuredCloneContainer> state = mSHInfo->GetNavigationAPIState(); 120 if (!state) { 121 return; 122 } 123 nsresult rv = state->DeserializeToJsval(aCx, aResult); 124 if (NS_FAILED(rv)) { 125 // nsStructuredCloneContainer::DeserializeToJsval suppresses exceptions, so 126 // the best we can do is just re-throw the NS_ERROR_DOM_DATA_CLONE_ERR. When 127 // nsStructuredCloneContainer::DeserializeToJsval throws better exceptions 128 // this should too. 129 // See also: NavigationDestination::GetState 130 aRv.Throw(rv); 131 } 132 } 133 134 void NavigationHistoryEntry::SetNavigationAPIState( 135 nsIStructuredCloneContainer* aState) { 136 mSHInfo->SetNavigationAPIState(aState); 137 } 138 139 bool NavigationHistoryEntry::IsSameEntry( 140 const class SessionHistoryInfo* aSHInfo) const { 141 return mSHInfo->NavigationId() == aSHInfo->NavigationId(); 142 } 143 144 bool NavigationHistoryEntry::SharesDocumentWith( 145 const class SessionHistoryInfo& aSHInfo) const { 146 return mSHInfo->SharesDocumentWith(aSHInfo); 147 } 148 149 JSObject* NavigationHistoryEntry::WrapObject( 150 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { 151 return NavigationHistoryEntry_Binding::Wrap(aCx, this, aGivenProto); 152 } 153 154 Document* NavigationHistoryEntry::GetAssociatedDocument() const { 155 nsGlobalWindowInner* window = GetOwnerWindow(); 156 return window ? window->GetDocument() : nullptr; 157 } 158 159 bool NavigationHistoryEntry::HasActiveDocument() const { 160 if (auto* document = GetAssociatedDocument()) { 161 return document->IsCurrentActiveDocument(); 162 } 163 164 return false; 165 } 166 167 const nsID& NavigationHistoryEntry::Key() const { 168 return mSHInfo->NavigationKey(); 169 } 170 171 nsIStructuredCloneContainer* NavigationHistoryEntry::GetNavigationAPIState() 172 const { 173 if (!mSHInfo) { 174 return nullptr; 175 } 176 177 return mSHInfo->GetNavigationAPIState(); 178 } 179 180 void NavigationHistoryEntry::ResetIndexForDisposal() { mIndex = -1; } 181 182 } // namespace mozilla::dom