InternalHeaders.h (6064B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 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 #ifndef mozilla_dom_InternalHeaders_h 8 #define mozilla_dom_InternalHeaders_h 9 10 // needed for HeadersGuardEnum. 11 #include "mozilla/dom/HeadersBinding.h" 12 #include "mozilla/dom/RequestBinding.h" 13 #include "nsClassHashtable.h" 14 #include "nsWrapperCache.h" 15 16 class nsIRequest; 17 18 namespace mozilla { 19 20 class ErrorResult; 21 22 namespace dom { 23 24 template <typename K, typename V> 25 class Record; 26 class HeadersEntry; 27 28 class InternalHeaders final { 29 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(InternalHeaders) 30 31 public: 32 struct Entry { 33 Entry(const nsACString& aName, const nsACString& aValue) 34 : mName(aName), mValue(aValue) {} 35 36 Entry() = default; 37 38 nsCString mName; 39 nsCString mValue; 40 }; 41 42 private: 43 HeadersGuardEnum mGuard; 44 nsTArray<Entry> mList; 45 46 nsTArray<Entry> mSortedList; 47 48 // This boolean is set to true at any writing operation to mList. It's set to 49 // false when mSortedList is regenerated. This happens when the header is 50 // iterated. 51 bool mListDirty; 52 53 public: 54 explicit InternalHeaders(HeadersGuardEnum aGuard = HeadersGuardEnum::None) 55 : mGuard(aGuard), mListDirty(false) {} 56 57 explicit InternalHeaders(const InternalHeaders& aOther) 58 : mGuard(HeadersGuardEnum::None), mListDirty(true) { 59 ErrorResult result; 60 Fill(aOther, result); 61 MOZ_ASSERT(!result.Failed()); 62 // Note that it's important to set the guard after Fill(), to make sure 63 // that Fill() doesn't fail if aOther is immutable. 64 mGuard = aOther.mGuard; 65 } 66 67 explicit InternalHeaders(nsTArray<Entry>&& aHeaders, 68 HeadersGuardEnum aGuard = HeadersGuardEnum::None); 69 70 InternalHeaders(const nsTArray<HeadersEntry>& aHeadersEntryList, 71 HeadersGuardEnum aGuard); 72 73 void ToIPC(nsTArray<HeadersEntry>& aIPCHeaders, HeadersGuardEnum& aGuard); 74 75 void Append(const nsACString& aName, const nsACString& aValue, 76 ErrorResult& aRv); 77 void Delete(const nsACString& aName, ErrorResult& aRv); 78 void Get(const nsACString& aName, nsACString& aValue, ErrorResult& aRv) const; 79 void GetSetCookie(nsTArray<nsCString>& aValues) const; 80 void GetFirst(const nsACString& aName, nsACString& aValue, 81 ErrorResult& aRv) const; 82 bool Has(const nsACString& aName, ErrorResult& aRv) const; 83 void Set(const nsACString& aName, const nsACString& aValue, ErrorResult& aRv); 84 85 uint32_t GetIterableLength() { 86 MaybeSortList(); 87 return mSortedList.Length(); 88 } 89 const NS_ConvertASCIItoUTF16 GetKeyAtIndex(unsigned aIndex) { 90 MaybeSortList(); 91 MOZ_ASSERT(aIndex < mSortedList.Length()); 92 return NS_ConvertASCIItoUTF16(mSortedList[aIndex].mName); 93 } 94 const NS_ConvertASCIItoUTF16 GetValueAtIndex(unsigned aIndex) { 95 MaybeSortList(); 96 MOZ_ASSERT(aIndex < mSortedList.Length()); 97 return NS_ConvertASCIItoUTF16(mSortedList[aIndex].mValue); 98 } 99 100 void Clear(); 101 102 HeadersGuardEnum Guard() const { return mGuard; } 103 void SetGuard(HeadersGuardEnum aGuard, ErrorResult& aRv); 104 105 void Fill(const InternalHeaders& aInit, ErrorResult& aRv); 106 void Fill(const Sequence<Sequence<nsCString>>& aInit, ErrorResult& aRv); 107 void Fill(const Record<nsCString, nsCString>& aInit, ErrorResult& aRv); 108 void FillResponseHeaders(nsIRequest* aRequest); 109 110 bool HasOnlySimpleHeaders() const; 111 112 bool HasRevalidationHeaders() const; 113 114 static already_AddRefed<InternalHeaders> BasicHeaders( 115 InternalHeaders* aHeaders); 116 117 static already_AddRefed<InternalHeaders> CORSHeaders( 118 InternalHeaders* aHeaders, 119 RequestCredentials aCredentialsMode = RequestCredentials::Omit); 120 121 void GetEntries(nsTArray<InternalHeaders::Entry>& aEntries) const; 122 123 void GetUnsafeHeaders(nsTArray<nsCString>& aNames) const; 124 125 private: 126 virtual ~InternalHeaders(); 127 128 static bool IsInvalidName(const nsACString& aName, ErrorResult& aRv); 129 static bool IsInvalidValue(const nsACString& aValue, ErrorResult& aRv); 130 bool IsValidHeaderValue(const nsCString& aLowerName, 131 const nsCString& aNormalizedValue, ErrorResult& aRv); 132 bool IsImmutable(ErrorResult& aRv) const; 133 bool IsForbiddenRequestHeader(const nsCString& aName, 134 const nsACString& aValue) const; 135 bool IsForbiddenRequestNoCorsHeader(const nsCString& aName) const; 136 bool IsForbiddenRequestNoCorsHeader(const nsCString& aName, 137 const nsACString& aValue) const; 138 bool IsForbiddenResponseHeader(const nsCString& aName) const; 139 140 bool IsInvalidMutableHeader(const nsCString& aName, ErrorResult& aRv) const { 141 return IsInvalidMutableHeader(aName, ""_ns, aRv); 142 } 143 144 bool IsInvalidMutableHeader(const nsCString& aName, const nsACString& aValue, 145 ErrorResult& aRv) const { 146 return IsInvalidName(aName, aRv) || IsInvalidValue(aValue, aRv) || 147 IsImmutable(aRv) || IsForbiddenRequestHeader(aName, aValue) || 148 IsForbiddenRequestNoCorsHeader(aName, aValue) || 149 IsForbiddenResponseHeader(aName); 150 } 151 152 // This method updates the passed name to match the capitalization of a header 153 // with the same name (ignoring case, per the spec). 154 void ReuseExistingNameIfExists(nsCString& aName) const; 155 156 void RemovePrivilegedNoCorsRequestHeaders(); 157 158 void GetInternal(const nsCString& aLowerName, nsACString& aValue, 159 ErrorResult& aRv) const; 160 161 bool DeleteInternal(const nsCString& aLowerName, ErrorResult& aRv); 162 163 static bool IsNoCorsSafelistedRequestHeaderName(const nsCString& aName); 164 165 static bool IsPrivilegedNoCorsRequestHeaderName(const nsCString& aName); 166 167 static bool IsRevalidationHeader(const nsCString& aName); 168 169 void MaybeSortList(); 170 void SetListDirty(); 171 }; 172 173 } // namespace dom 174 } // namespace mozilla 175 176 #endif // mozilla_dom_InternalHeaders_h