summaryrefslogtreecommitdiffstats
path: root/netwerk/protocol/http/OpaqueResponseUtils.h
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/protocol/http/OpaqueResponseUtils.h')
-rw-r--r--netwerk/protocol/http/OpaqueResponseUtils.h145
1 files changed, 145 insertions, 0 deletions
diff --git a/netwerk/protocol/http/OpaqueResponseUtils.h b/netwerk/protocol/http/OpaqueResponseUtils.h
new file mode 100644
index 0000000000..202b604f7f
--- /dev/null
+++ b/netwerk/protocol/http/OpaqueResponseUtils.h
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+
+/* 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 mozilla_net_OpaqueResponseUtils_h
+#define mozilla_net_OpaqueResponseUtils_h
+
+#include "mozilla/dom/JSValidatorParent.h"
+#include "nsIContentPolicy.h"
+#include "nsIStreamListener.h"
+#include "nsUnknownDecoder.h"
+#include "nsMimeTypes.h"
+#include "nsIHttpChannel.h"
+
+#include "mozilla/Variant.h"
+#include "mozilla/Logging.h"
+
+#include "nsCOMPtr.h"
+#include "nsString.h"
+#include "nsTArray.h"
+
+class nsIContentSniffer;
+static mozilla::LazyLogModule gORBLog("ORB");
+
+namespace mozilla::net {
+
+class HttpBaseChannel;
+class nsHttpResponseHead;
+
+enum class OpaqueResponseBlockedReason : uint32_t {
+ ALLOWED_SAFE_LISTED,
+ BLOCKED_BLOCKLISTED_NEVER_SNIFFED,
+ BLOCKED_206_AND_BLOCKLISTED,
+ BLOCKED_NOSNIFF_AND_EITHER_BLOCKLISTED_OR_TEXTPLAIN,
+ BLOCKED_SHOULD_SNIFF
+};
+
+OpaqueResponseBlockedReason GetOpaqueResponseBlockedReason(
+ const nsACString& aContentType, uint16_t aStatus, bool aNoSniff);
+
+OpaqueResponseBlockedReason GetOpaqueResponseBlockedReason(
+ const nsHttpResponseHead& aResponseHead);
+
+// Returns a tuple of (rangeStart, rangeEnd, rangeTotal) from the input range
+// header string if succeed.
+Result<std::tuple<int64_t, int64_t, int64_t>, nsresult>
+ParseContentRangeHeaderString(const nsAutoCString& aRangeStr);
+
+bool IsFirstPartialResponse(nsHttpResponseHead& aResponseHead);
+
+void LogORBError(nsILoadInfo* aLoadInfo, nsIURI* aURI);
+
+class OpaqueResponseBlocker final : public nsIStreamListener {
+ enum class State { Sniffing, Allowed, Blocked };
+
+ public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIREQUESTOBSERVER
+ NS_DECL_NSISTREAMLISTENER;
+
+ OpaqueResponseBlocker(nsIStreamListener* aNext, HttpBaseChannel* aChannel,
+ const nsCString& aContentType, bool aNoSniff);
+
+ bool IsSniffing() const;
+ void AllowResponse();
+ void BlockResponse(HttpBaseChannel* aChannel, nsresult aReason);
+
+ nsresult EnsureOpaqueResponseIsAllowedAfterSniff(nsIRequest* aRequest);
+
+ private:
+ virtual ~OpaqueResponseBlocker() = default;
+
+ nsresult ValidateJavaScript(HttpBaseChannel* aChannel, nsIURI* aURI,
+ nsILoadInfo* aLoadInfo);
+
+ void ResolveAndProcessData(HttpBaseChannel* aChannel, bool aAllowed,
+ Maybe<ipc::Shmem>& aSharedData);
+
+ void MaybeRunOnStopRequest(HttpBaseChannel* aChannel);
+
+ nsCOMPtr<nsIStreamListener> mNext;
+
+ const nsCString mContentType;
+ const bool mNoSniff;
+
+ State mState = State::Sniffing;
+ nsresult mStatus = NS_OK;
+
+ RefPtr<dom::JSValidatorParent> mJSValidator;
+
+ Maybe<nsresult> mPendingOnStopRequestStatus{Nothing()};
+};
+
+class nsCompressedAudioVideoImageDetector : public nsUnknownDecoder {
+ const std::function<void(void*, const uint8_t*, uint32_t)> mCallback;
+
+ public:
+ nsCompressedAudioVideoImageDetector(
+ nsIStreamListener* aListener,
+ std::function<void(void*, const uint8_t*, uint32_t)>&& aCallback)
+ : nsUnknownDecoder(aListener), mCallback(aCallback) {}
+
+ protected:
+ virtual void DetermineContentType(nsIRequest* aRequest) override {
+ nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest);
+ if (!httpChannel) {
+ return;
+ }
+
+ const char* testData = mBuffer;
+ uint32_t testDataLen = mBufferLen;
+ // Check if data are compressed.
+ nsAutoCString decodedData;
+
+ // ConvertEncodedData is always called only on a single thread for each
+ // instance of an object.
+ nsresult rv = ConvertEncodedData(aRequest, mBuffer, mBufferLen);
+ if (NS_SUCCEEDED(rv)) {
+ MutexAutoLock lock(mMutex);
+ decodedData = mDecodedData;
+ }
+ if (!decodedData.IsEmpty()) {
+ testData = decodedData.get();
+ testDataLen = std::min<uint32_t>(decodedData.Length(), 512u);
+ }
+
+ mCallback(httpChannel, (const uint8_t*)testData, testDataLen);
+
+ nsAutoCString contentType;
+ rv = httpChannel->GetContentType(contentType);
+
+ MutexAutoLock lock(mMutex);
+ if (!contentType.IsEmpty()) {
+ mContentType = contentType;
+ } else {
+ mContentType = UNKNOWN_CONTENT_TYPE;
+ }
+ }
+};
+} // namespace mozilla::net
+
+#endif // mozilla_net_OpaqueResponseUtils_h