nsUnknownDecoder.h (5149B)
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 6 #ifndef nsUnknownDecoder_h__ 7 #define nsUnknownDecoder_h__ 8 9 #include "nsIStreamConverter.h" 10 #include "nsIThreadRetargetableStreamListener.h" 11 #include "nsIContentSniffer.h" 12 #include "mozilla/Mutex.h" 13 #include "mozilla/Atomics.h" 14 15 #include "nsCOMPtr.h" 16 #include "nsString.h" 17 18 #define NS_UNKNOWNDECODER_CID \ 19 {/* 7d7008a0-c49a-11d3-9b22-0080c7cb1080 */ \ 20 0x7d7008a0, \ 21 0xc49a, \ 22 0x11d3, \ 23 {0x9b, 0x22, 0x00, 0x80, 0xc7, 0xcb, 0x10, 0x80}} 24 25 class nsUnknownDecoder : public nsIStreamConverter, public nsIContentSniffer { 26 public: 27 // nsISupports methods 28 NS_DECL_ISUPPORTS 29 30 // nsIStreamConverter methods 31 NS_DECL_NSISTREAMCONVERTER 32 33 // nsIStreamListener methods 34 NS_DECL_NSISTREAMLISTENER 35 36 // nsIRequestObserver methods 37 NS_DECL_NSIREQUESTOBSERVER 38 39 // nsIContentSniffer methods 40 NS_DECL_NSICONTENTSNIFFER 41 42 // nsIThreadRetargetableStreamListener methods 43 NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER 44 45 explicit nsUnknownDecoder(nsIStreamListener* aListener = nullptr); 46 47 protected: 48 virtual ~nsUnknownDecoder(); 49 50 virtual void DetermineContentType(nsIRequest* aRequest); 51 nsresult FireListenerNotifications(nsIRequest* request, nsISupports* aCtxt); 52 53 class ConvertedStreamListener : public nsIStreamListener { 54 public: 55 explicit ConvertedStreamListener(nsUnknownDecoder* aDecoder); 56 57 NS_DECL_ISUPPORTS 58 NS_DECL_NSIREQUESTOBSERVER 59 NS_DECL_NSISTREAMLISTENER 60 61 private: 62 virtual ~ConvertedStreamListener() = default; 63 static nsresult AppendDataToString(nsIInputStream* inputStream, 64 void* closure, const char* rawSegment, 65 uint32_t toOffset, uint32_t count, 66 uint32_t* writeCount); 67 nsUnknownDecoder* mDecoder; 68 }; 69 70 protected: 71 nsCOMPtr<nsIStreamListener> mNextListener; 72 73 // Various sniffer functions. Returning true means that a type 74 // was determined; false means no luck. 75 bool SniffForHTML(nsIRequest* aRequest); 76 bool SniffForXML(nsIRequest* aRequest); 77 78 // SniffURI guesses at the content type based on the URI (typically 79 // using the extentsion) 80 bool SniffURI(nsIRequest* aRequest); 81 82 // LastDitchSniff guesses at text/plain vs. application/octet-stream 83 // by just looking at whether the data contains null bytes, and 84 // maybe at the fraction of chars with high bit set. Use this only 85 // as a last-ditch attempt to decide a content type! 86 bool LastDitchSniff(nsIRequest* aRequest); 87 88 /** 89 * An entry struct for our array of sniffers. Each entry has either 90 * a type associated with it (set these with the SNIFFER_ENTRY macro) 91 * or a function to be executed (set these with the 92 * SNIFFER_ENTRY_WITH_FUNC macro). The function should take a single 93 * nsIRequest* and returns bool -- true if it sets mContentType, 94 * false otherwise 95 */ 96 struct nsSnifferEntry { 97 using TypeSniffFunc = bool (nsUnknownDecoder::*)(nsIRequest*); 98 99 const char* mBytes; 100 uint32_t mByteLen; 101 102 // Exactly one of mMimeType and mContentTypeSniffer should be set non-null 103 const char* mMimeType; 104 TypeSniffFunc mContentTypeSniffer; 105 }; 106 107 #define SNIFFER_ENTRY(_bytes, _type) \ 108 {_bytes, sizeof(_bytes) - 1, _type, nullptr} 109 110 #define SNIFFER_ENTRY_WITH_FUNC(_bytes, _func) \ 111 {_bytes, sizeof(_bytes) - 1, nullptr, _func} 112 113 static nsSnifferEntry sSnifferEntries[]; 114 static uint32_t sSnifferEntryNum; 115 116 // We guarantee in order delivery of OnStart, OnStop and OnData, therefore 117 // we do not need proper locking for mBuffer. 118 mozilla::Atomic<char*> mBuffer; 119 mozilla::Atomic<uint32_t> mBufferLen; 120 121 nsCString mContentType; 122 123 // This mutex syncs: mContentType, mDecodedData and mNextListener. 124 mutable mozilla::Mutex mMutex MOZ_UNANNOTATED; 125 126 protected: 127 nsresult ConvertEncodedData(nsIRequest* request, const char* data, 128 uint32_t length); 129 nsCString mDecodedData; // If data are encoded this will be uncompress data. 130 }; 131 132 #define NS_BINARYDETECTOR_CID \ 133 {/* a2027ec6-ba0d-4c72-805d-148233f5f33c */ \ 134 0xa2027ec6, \ 135 0xba0d, \ 136 0x4c72, \ 137 {0x80, 0x5d, 0x14, 0x82, 0x33, 0xf5, 0xf3, 0x3c}} 138 139 /** 140 * Class that detects whether a data stream is text or binary. This reuses 141 * most of nsUnknownDecoder except the actual content-type determination logic 142 * -- our overridden DetermineContentType simply calls LastDitchSniff and sets 143 * the type to APPLICATION_GUESS_FROM_EXT if the data is detected as binary. 144 */ 145 class nsBinaryDetector : public nsUnknownDecoder { 146 protected: 147 virtual void DetermineContentType(nsIRequest* aRequest) override; 148 }; 149 150 #endif /* nsUnknownDecoder_h__ */