summaryrefslogtreecommitdiffstats
path: root/netwerk/protocol/http/nsHttpResponseHead.h
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/protocol/http/nsHttpResponseHead.h')
-rw-r--r--netwerk/protocol/http/nsHttpResponseHead.h239
1 files changed, 239 insertions, 0 deletions
diff --git a/netwerk/protocol/http/nsHttpResponseHead.h b/netwerk/protocol/http/nsHttpResponseHead.h
new file mode 100644
index 0000000000..9caf92b3e1
--- /dev/null
+++ b/netwerk/protocol/http/nsHttpResponseHead.h
@@ -0,0 +1,239 @@
+/* -*- Mode: C++; tab-width: 4; 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/. */
+
+#ifndef nsHttpResponseHead_h__
+#define nsHttpResponseHead_h__
+
+#include "nsHttpHeaderArray.h"
+#include "nsHttp.h"
+#include "nsString.h"
+#include "mozilla/RecursiveMutex.h"
+
+#ifdef Status
+/* Xlib headers insist on this for some reason... Nuke it because
+ it'll override our member name */
+typedef Status __StatusTmp;
+# undef Status
+typedef __StatusTmp Status;
+#endif
+
+class nsIHttpHeaderVisitor;
+
+// This needs to be forward declared here so we can include only this header
+// without also including PHttpChannelParams.h
+namespace IPC {
+template <typename>
+struct ParamTraits;
+} // namespace IPC
+
+namespace mozilla {
+namespace net {
+
+//-----------------------------------------------------------------------------
+// nsHttpResponseHead represents the status line and headers from an HTTP
+// response.
+//-----------------------------------------------------------------------------
+
+class nsHttpResponseHead {
+ public:
+ nsHttpResponseHead() = default;
+
+ nsHttpResponseHead(const nsHttpResponseHead& aOther);
+ nsHttpResponseHead& operator=(const nsHttpResponseHead& aOther);
+
+ void Enter() const MOZ_CAPABILITY_ACQUIRE(mRecursiveMutex) {
+ mRecursiveMutex.Lock();
+ }
+ void Exit() const MOZ_CAPABILITY_RELEASE(mRecursiveMutex) {
+ mRecursiveMutex.Unlock();
+ }
+ void AssertMutexOwned() const { mRecursiveMutex.AssertCurrentThreadIn(); }
+
+ HttpVersion Version();
+ uint16_t Status() const;
+ void StatusText(nsACString& aStatusText);
+ int64_t ContentLength();
+ void ContentType(nsACString& aContentType) const;
+ void ContentCharset(nsACString& aContentCharset);
+ bool Public();
+ bool Private();
+ bool NoStore();
+ bool NoCache();
+ bool Immutable();
+ /**
+ * Full length of the entity. For byte-range requests, this may be larger
+ * than ContentLength(), which will only represent the requested part of the
+ * entity.
+ */
+ int64_t TotalEntitySize();
+
+ [[nodiscard]] nsresult SetHeader(const nsACString& h, const nsACString& v,
+ bool m = false);
+ [[nodiscard]] nsresult SetHeader(const nsHttpAtom& h, const nsACString& v,
+ bool m = false);
+ [[nodiscard]] nsresult GetHeader(const nsHttpAtom& h, nsACString& v) const;
+ void ClearHeader(const nsHttpAtom& h);
+ void ClearHeaders();
+ bool HasHeaderValue(const nsHttpAtom& h, const char* v);
+ bool HasHeader(const nsHttpAtom& h) const;
+
+ void SetContentType(const nsACString& s);
+ void SetContentCharset(const nsACString& s);
+ void SetContentLength(int64_t);
+
+ // write out the response status line and headers as a single text block,
+ // optionally pruning out transient headers (ie. headers that only make
+ // sense the first time the response is handled).
+ // Both functions append to the string supplied string.
+ void Flatten(nsACString&, bool pruneTransients);
+ void FlattenNetworkOriginalHeaders(nsACString& buf);
+
+ // The next 2 functions parse flattened response head and original net
+ // headers. They are used when we are reading an entry from the cache.
+ //
+ // To keep proper order of the original headers we MUST call
+ // ParseCachedOriginalHeaders FIRST and then ParseCachedHead.
+ //
+ // block must be null terminated.
+ [[nodiscard]] nsresult ParseCachedHead(const char* block);
+ [[nodiscard]] nsresult ParseCachedOriginalHeaders(char* block);
+
+ // parse the status line.
+ nsresult ParseStatusLine(const nsACString& line);
+
+ // parse a header line.
+ [[nodiscard]] nsresult ParseHeaderLine(const nsACString& line);
+
+ // cache validation support methods
+ [[nodiscard]] nsresult ComputeFreshnessLifetime(uint32_t*);
+ [[nodiscard]] nsresult ComputeCurrentAge(uint32_t now, uint32_t requestTime,
+ uint32_t* result);
+ bool MustValidate();
+ bool MustValidateIfExpired();
+
+ // return true if the response contains a valid Cache-control:
+ // stale-while-revalidate and |now| is less than or equal |expiration +
+ // stale-while-revalidate|. Otherwise false.
+ bool StaleWhileRevalidate(uint32_t now, uint32_t expiration);
+
+ // returns true if the server appears to support byte range requests.
+ bool IsResumable();
+
+ // returns true if the Expires header has a value in the past relative to the
+ // value of the Date header.
+ bool ExpiresInPast();
+
+ // update headers...
+ void UpdateHeaders(nsHttpResponseHead* aOther);
+
+ // reset the response head to it's initial state
+ void Reset();
+
+ [[nodiscard]] nsresult GetLastModifiedValue(uint32_t* result);
+
+ bool operator==(const nsHttpResponseHead& aOther) const;
+
+ // Using this function it is possible to itereate through all headers
+ // automatically under one lock.
+ [[nodiscard]] nsresult VisitHeaders(nsIHttpHeaderVisitor* visitor,
+ nsHttpHeaderArray::VisitorFilter filter);
+ [[nodiscard]] nsresult GetOriginalHeader(const nsHttpAtom& aHeader,
+ nsIHttpHeaderVisitor* aVisitor);
+
+ bool HasContentType() const;
+ bool HasContentCharset();
+ bool GetContentTypeOptionsHeader(nsACString& aOutput);
+
+ private:
+ [[nodiscard]] nsresult SetHeader_locked(const nsHttpAtom& atom,
+ const nsACString& h,
+ const nsACString& v, bool m = false)
+ MOZ_REQUIRES(mRecursiveMutex);
+ void AssignDefaultStatusText() MOZ_REQUIRES(mRecursiveMutex);
+ void ParseVersion(const char*) MOZ_REQUIRES(mRecursiveMutex);
+ void ParseCacheControl(const char*) MOZ_REQUIRES(mRecursiveMutex);
+ void ParsePragma(const char*) MOZ_REQUIRES(mRecursiveMutex);
+ // Parses a content-length header-value as described in
+ // https://fetch.spec.whatwg.org/#content-length-header
+ nsresult ParseResponseContentLength(const nsACString& aHeaderStr)
+ MOZ_REQUIRES(mRecursiveMutex);
+
+ nsresult ParseStatusLine_locked(const nsACString& line)
+ MOZ_REQUIRES(mRecursiveMutex);
+ [[nodiscard]] nsresult ParseHeaderLine_locked(const nsACString& line,
+ bool originalFromNetHeaders)
+ MOZ_REQUIRES(mRecursiveMutex);
+
+ // these return failure if the header does not exist.
+ [[nodiscard]] nsresult ParseDateHeader(const nsHttpAtom& header,
+ uint32_t* result) const
+ MOZ_REQUIRES(mRecursiveMutex);
+ [[nodiscard]] nsresult GetAgeValue(uint32_t* result);
+ [[nodiscard]] nsresult GetMaxAgeValue(uint32_t* result);
+ [[nodiscard]] nsresult GetStaleWhileRevalidateValue(uint32_t* result);
+ [[nodiscard]] nsresult GetDateValue(uint32_t* result);
+ [[nodiscard]] nsresult GetExpiresValue(uint32_t* result);
+
+ bool ExpiresInPast_locked() const MOZ_REQUIRES(mRecursiveMutex);
+ [[nodiscard]] nsresult GetAgeValue_locked(uint32_t* result) const
+ MOZ_REQUIRES(mRecursiveMutex);
+ [[nodiscard]] nsresult GetExpiresValue_locked(uint32_t* result) const
+ MOZ_REQUIRES(mRecursiveMutex);
+ [[nodiscard]] nsresult GetMaxAgeValue_locked(uint32_t* result) const
+ MOZ_REQUIRES(mRecursiveMutex);
+ [[nodiscard]] nsresult GetStaleWhileRevalidateValue_locked(
+ uint32_t* result) const MOZ_REQUIRES(mRecursiveMutex);
+
+ [[nodiscard]] nsresult GetDateValue_locked(uint32_t* result) const
+ MOZ_REQUIRES(mRecursiveMutex) {
+ return ParseDateHeader(nsHttp::Date, result);
+ }
+
+ [[nodiscard]] nsresult GetLastModifiedValue_locked(uint32_t* result) const
+ MOZ_REQUIRES(mRecursiveMutex) {
+ return ParseDateHeader(nsHttp::Last_Modified, result);
+ }
+
+ bool NoCache_locked() const MOZ_REQUIRES(mRecursiveMutex) {
+ // We ignore Pragma: no-cache if Cache-Control is set.
+ MOZ_ASSERT_IF(mCacheControlNoCache, mHasCacheControl);
+ return mHasCacheControl ? mCacheControlNoCache : mPragmaNoCache;
+ }
+
+ private:
+ // All members must be copy-constructable and assignable
+ nsHttpHeaderArray mHeaders MOZ_GUARDED_BY(mRecursiveMutex);
+ HttpVersion mVersion MOZ_GUARDED_BY(mRecursiveMutex){HttpVersion::v1_1};
+ uint16_t mStatus MOZ_GUARDED_BY(mRecursiveMutex){200};
+ nsCString mStatusText MOZ_GUARDED_BY(mRecursiveMutex);
+ int64_t mContentLength MOZ_GUARDED_BY(mRecursiveMutex){-1};
+ nsCString mContentType MOZ_GUARDED_BY(mRecursiveMutex);
+ nsCString mContentCharset MOZ_GUARDED_BY(mRecursiveMutex);
+ bool mHasCacheControl MOZ_GUARDED_BY(mRecursiveMutex){false};
+ bool mCacheControlPublic MOZ_GUARDED_BY(mRecursiveMutex){false};
+ bool mCacheControlPrivate MOZ_GUARDED_BY(mRecursiveMutex){false};
+ bool mCacheControlNoStore MOZ_GUARDED_BY(mRecursiveMutex){false};
+ bool mCacheControlNoCache MOZ_GUARDED_BY(mRecursiveMutex){false};
+ bool mCacheControlImmutable MOZ_GUARDED_BY(mRecursiveMutex){false};
+ bool mCacheControlStaleWhileRevalidateSet MOZ_GUARDED_BY(mRecursiveMutex){
+ false};
+ uint32_t mCacheControlStaleWhileRevalidate MOZ_GUARDED_BY(mRecursiveMutex){0};
+ bool mCacheControlMaxAgeSet MOZ_GUARDED_BY(mRecursiveMutex){false};
+ uint32_t mCacheControlMaxAge MOZ_GUARDED_BY(mRecursiveMutex){0};
+ bool mPragmaNoCache MOZ_GUARDED_BY(mRecursiveMutex){false};
+
+ // We are using RecursiveMutex instead of a Mutex because VisitHeader
+ // function calls nsIHttpHeaderVisitor::VisitHeader while under lock.
+ mutable RecursiveMutex mRecursiveMutex{"nsHttpResponseHead.mRecursiveMutex"};
+ // During VisitHeader we sould not allow call to SetHeader.
+ bool mInVisitHeaders MOZ_GUARDED_BY(mRecursiveMutex){false};
+
+ friend struct IPC::ParamTraits<nsHttpResponseHead>;
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif // nsHttpResponseHead_h__