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 _NSDATAOBJ_H_ 7 #define _NSDATAOBJ_H_ 8 9 #include <oleidl.h> 10 #include <shldisp.h> 11 12 #include "mozilla/glue/WinUtils.h" 13 #include "nsCOMPtr.h" 14 #include "nsString.h" 15 #include "nsIFile.h" 16 #include "nsIURI.h" 17 #include "nsIStreamListener.h" 18 #include "nsIChannel.h" 19 #include "nsCOMArray.h" 20 #include "nsITimer.h" 21 #include "nsIURI.h" 22 #include "nsString.h" 23 #include "nsWindowsHelpers.h" 24 25 class nsICookieJarSettings; 26 class nsIThread; 27 class nsIPrincipal; 28 class CEnumFormatEtc; 29 class nsITransferable; 30 31 /* 32 * This ole registered class is used to facilitate drag-drop of objects which 33 * can be adapted by an object derived from CfDragDrop. The CfDragDrop is 34 * associated with instances via SetDragDrop(). 35 */ 36 class nsDataObj : public IDataObject, public IDataObjectAsyncCapability { 37 nsCOMPtr<nsIThread> mIOThread; 38 39 public: // construction, destruction 40 explicit nsDataObj(nsIURI* uri = nullptr); 41 42 protected: 43 virtual ~nsDataObj(); 44 45 public: // IUnknown methods - see iunknown.h for documentation 46 STDMETHODIMP_(ULONG) AddRef() override; 47 STDMETHODIMP QueryInterface(REFIID, void**) override; 48 STDMETHODIMP_(ULONG) Release() override; 49 50 // support for clipboard 51 virtual void AddDataFlavor(const char* aDataFlavor, LPFORMATETC aFE); 52 void SetTransferable(nsITransferable* aTransferable); 53 54 public: // IDataObject methods - these are general comments. see CfDragDrop 55 // for overriding behavior 56 // Store data in pSTM according to the format specified by pFE, if the 57 // format is supported (supported formats are specified in CfDragDrop:: 58 // GetFormats) and return NOERROR; otherwise return DATA_E_FORMATETC. It 59 // is the callers responsibility to free pSTM if NOERROR is returned. 60 STDMETHODIMP GetData(LPFORMATETC pFE, LPSTGMEDIUM pSTM) override; 61 62 // Similar to GetData except that the caller allocates the structure 63 // referenced by pSTM. 64 STDMETHODIMP GetDataHere(LPFORMATETC pFE, LPSTGMEDIUM pSTM) override; 65 66 // Returns S_TRUE if this object supports the format specified by pSTM, 67 // S_FALSE otherwise. 68 STDMETHODIMP QueryGetData(LPFORMATETC pFE) override; 69 70 // Set pCanonFE to the canonical format of pFE if one exists and return 71 // NOERROR, otherwise return DATA_S_SAMEFORMATETC. A canonical format 72 // implies an identical rendering. 73 STDMETHODIMP GetCanonicalFormatEtc(LPFORMATETC pFE, 74 LPFORMATETC pCanonFE) final; 75 76 // Set this objects data according to the format specified by pFE and 77 // the storage medium specified by pSTM and return NOERROR, if the format 78 // is supported. If release is TRUE this object must release the storage 79 // associated with pSTM. 80 STDMETHODIMP SetData(LPFORMATETC pFE, LPSTGMEDIUM pSTM, 81 BOOL release) override; 82 83 // Set ppEnum to an IEnumFORMATETC object which will iterate all of the 84 // data formats that this object supports. direction is either DATADIR_GET 85 // or DATADIR_SET. 86 STDMETHODIMP EnumFormatEtc(DWORD direction, LPENUMFORMATETC* ppEnum) final; 87 88 // Set up an advisory connection to this object based on the format specified 89 // by pFE, flags, and the pAdvise. Set pConn to the established advise 90 // connection. 91 STDMETHODIMP DAdvise(LPFORMATETC pFE, DWORD flags, LPADVISESINK pAdvise, 92 DWORD* pConn) final; 93 94 // Turn off advising of a previous call to DAdvise which set pConn. 95 STDMETHODIMP DUnadvise(DWORD pConn) final; 96 97 // Set ppEnum to an IEnumSTATDATA object which will iterate over the 98 // existing objects which have established advisory connections to this 99 // object. 100 STDMETHODIMP EnumDAdvise(LPENUMSTATDATA* ppEnum) final; 101 102 // IDataObjectAsyncCapability methods 103 STDMETHODIMP EndOperation(HRESULT hResult, IBindCtx* pbcReserved, 104 DWORD dwEffects) final; 105 STDMETHODIMP GetAsyncMode(BOOL* pfIsOpAsync) final; 106 STDMETHODIMP InOperation(BOOL* pfInAsyncOp) final; 107 STDMETHODIMP SetAsyncMode(BOOL fDoOpAsync) final; 108 STDMETHODIMP StartOperation(IBindCtx* pbcReserved) final; 109 110 private: // other methods 111 // Gets the filename from the kFilePromiseURLMime flavour 112 HRESULT GetDownloadDetails(nsIURI** aSourceURI, nsAString& aFilename); 113 114 // help determine the kind of drag 115 bool IsFlavourPresent(const char* inFlavour); 116 117 protected: 118 HRESULT GetFile(FORMATETC& aFE, STGMEDIUM& aSTG); 119 HRESULT GetText(const nsACString& aDF, FORMATETC& aFE, STGMEDIUM& aSTG); 120 121 private: 122 HRESULT GetDib(const nsACString& inFlavor, FORMATETC&, STGMEDIUM& aSTG); 123 124 HRESULT DropImage(FORMATETC& aFE, STGMEDIUM& aSTG); 125 HRESULT DropFile(FORMATETC& aFE, STGMEDIUM& aSTG); 126 HRESULT DropTempFile(FORMATETC& aFE, STGMEDIUM& aSTG); 127 128 HRESULT GetUniformResourceLocator(FORMATETC& aFE, STGMEDIUM& aSTG, 129 bool aIsUnicode); 130 HRESULT ExtractUniformResourceLocatorA(FORMATETC& aFE, STGMEDIUM& aSTG); 131 HRESULT ExtractUniformResourceLocatorW(FORMATETC& aFE, STGMEDIUM& aSTG); 132 HRESULT GetFileDescriptor(FORMATETC& aFE, STGMEDIUM& aSTG, bool aIsUnicode); 133 134 protected: 135 HRESULT GetFileContents(FORMATETC& aFE, STGMEDIUM& aSTG); 136 137 private: 138 HRESULT GetPreferredDropEffect(FORMATETC& aFE, STGMEDIUM& aSTG); 139 140 // Provide the structures needed for an internet shortcut by the shell 141 HRESULT GetFileDescriptorInternetShortcutA(FORMATETC& aFE, STGMEDIUM& aSTG); 142 HRESULT GetFileDescriptorInternetShortcutW(FORMATETC& aFE, STGMEDIUM& aSTG); 143 HRESULT GetFileContentsInternetShortcut(FORMATETC& aFE, STGMEDIUM& aSTG); 144 145 // IStream implementation 146 HRESULT GetFileDescriptor_IStreamA(FORMATETC& aFE, STGMEDIUM& aSTG); 147 HRESULT GetFileDescriptor_IStreamW(FORMATETC& aFE, STGMEDIUM& aSTG); 148 HRESULT GetFileContents_IStream(FORMATETC& aFE, STGMEDIUM& aSTG); 149 150 nsresult ExtractShortcutURL(nsString& outURL); 151 nsresult ExtractShortcutTitle(nsString& outTitle); 152 153 // munge our HTML data to win32's CF_HTML spec. Will null terminate 154 nsresult BuildPlatformHTML(const char* inOurHTML, char** outPlatformHTML); 155 156 // Used for the SourceURL part of CF_HTML 157 nsCString mSourceURL; 158 159 protected: 160 BOOL FormatsMatch(const FORMATETC& source, const FORMATETC& target) const; 161 162 ULONG m_cRef; // the reference count 163 164 private: 165 nsTArray<nsCString> mDataFlavors; 166 167 nsITransferable* mTransferable; // nsDataObj owns and ref counts 168 // nsITransferable, the nsITransferable does 169 // know anything about the nsDataObj 170 171 protected: 172 CEnumFormatEtc* m_enumFE; // Ownership Rules: 173 // nsDataObj owns and ref counts CEnumFormatEtc, 174 175 private: 176 nsCOMPtr<nsIFile> mCachedTempFile; 177 RefPtr<nsDataObj> mKeepAlive; 178 179 BOOL mIsAsyncMode; 180 BOOL mIsInOperation; 181 /////////////////////////////////////////////////////////////////////////////// 182 // CStream class implementation 183 // this class is used in Drag and drop with download sample 184 // called from IDataObject::GetData 185 class CStreamBase : public IStream { 186 // IStream 187 STDMETHODIMP Clone(IStream** ppStream) final; 188 STDMETHODIMP Commit(DWORD dwFrags) final; 189 STDMETHODIMP CopyTo(IStream* pDestStream, ULARGE_INTEGER nBytesToCopy, 190 ULARGE_INTEGER* nBytesRead, 191 ULARGE_INTEGER* nBytesWritten) final; 192 STDMETHODIMP LockRegion(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes, 193 DWORD dwFlags) final; 194 STDMETHODIMP Revert(void) final; 195 STDMETHODIMP Seek(LARGE_INTEGER nMove, DWORD dwOrigin, 196 ULARGE_INTEGER* nNewPos) final; 197 STDMETHODIMP SetSize(ULARGE_INTEGER nNewSize) final; 198 STDMETHODIMP UnlockRegion(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes, 199 DWORD dwFlags) final; 200 STDMETHODIMP Write(const void* pvBuffer, ULONG nBytesToRead, 201 ULONG* nBytesRead) final; 202 203 protected: 204 uint32_t mStreamRead; 205 206 CStreamBase(); 207 virtual ~CStreamBase(); 208 }; 209 210 class CStream final : public CStreamBase, public nsIStreamListener { 211 nsCOMPtr<nsIChannel> mChannel; 212 FallibleTArray<uint8_t> mChannelData; 213 nsresult mChannelResult; 214 bool mChannelRead; 215 216 virtual ~CStream(); 217 nsresult WaitForCompletion(); 218 219 // IUnknown 220 STDMETHOD(QueryInterface)(REFIID refiid, void** ppvResult) final; 221 222 // IStream 223 STDMETHODIMP Read(void* pvBuffer, ULONG nBytesToRead, 224 ULONG* nBytesRead) final; 225 STDMETHODIMP Stat(STATSTG* statstg, DWORD dwFlags) final; 226 227 public: 228 CStream(); 229 nsresult Init(nsIURI* pSourceURI, nsContentPolicyType aContentPolicyType, 230 nsIPrincipal* aRequestingPrincipal, 231 nsICookieJarSettings* aCookieJarSettings); 232 233 NS_DECL_ISUPPORTS 234 NS_DECL_NSIREQUESTOBSERVER 235 NS_DECL_NSISTREAMLISTENER 236 }; 237 238 HRESULT CreateStream(IStream** outStream); 239 240 // This class must be thread-safe. 241 class AutoCloseEvent final { 242 const nsAutoHandle mEvent; 243 244 AutoCloseEvent(const AutoCloseEvent&) = delete; 245 void operator=(const AutoCloseEvent&) = delete; 246 ~AutoCloseEvent() = default; 247 248 public: 249 AutoCloseEvent(); 250 bool IsInited() const; 251 void Signal() const; 252 DWORD Wait(DWORD aMillisec) const; 253 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AutoCloseEvent) 254 }; 255 256 // This class must be thread-safe. 257 class AutoSetEvent final { 258 const RefPtr<AutoCloseEvent> mEvent; 259 260 AutoSetEvent(const AutoSetEvent&) = delete; 261 void operator=(const AutoSetEvent&) = delete; 262 ~AutoSetEvent(); 263 264 public: 265 explicit AutoSetEvent(mozilla::NotNull<AutoCloseEvent*> aEvent); 266 void Signal() const; 267 bool IsWaiting() const; 268 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AutoSetEvent) 269 }; 270 271 // This class must be thread-safe. 272 class CMemStream final : public CStreamBase { 273 static mozilla::glue::Win32SRWLock mLock; 274 const nsAutoGlobalMem mGlobalMem; 275 const RefPtr<AutoCloseEvent> mEvent; 276 const uint32_t mTotalLength; 277 RefPtr<IUnknown> mMarshaler; 278 279 virtual ~CMemStream(); 280 void WaitForCompletion(); 281 282 // IStream 283 STDMETHODIMP Read(void* pvBuffer, ULONG nBytesToRead, 284 ULONG* nBytesRead) final; 285 STDMETHODIMP Stat(STATSTG* statstg, DWORD dwFlags) final; 286 287 public: 288 CMemStream(nsHGLOBAL aGlobalMem, uint32_t mTotalLength, 289 already_AddRefed<AutoCloseEvent> aEvent); 290 291 // IUnknown 292 STDMETHOD(QueryInterface)(REFIID refiid, void** ppvResult) final; 293 NS_INLINE_DECL_THREADSAFE_VIRTUAL_REFCOUNTING(CMemStream, final) 294 }; 295 296 private: 297 // Drag and drop helper data for implementing drag and drop image support 298 typedef struct { 299 FORMATETC fe; 300 STGMEDIUM stgm; 301 } DATAENTRY, *LPDATAENTRY; 302 303 nsTArray<LPDATAENTRY> mDataEntryList; 304 nsCOMPtr<nsITimer> mTimer; 305 306 bool LookupArbitraryFormat(FORMATETC* aFormat, LPDATAENTRY* aDataEntry, 307 BOOL aAddorUpdate); 308 bool CopyMediumData(STGMEDIUM* aMediumDst, STGMEDIUM* aMediumSrc, 309 LPFORMATETC aFormat, BOOL aSetData); 310 }; 311 312 #endif // _NSDATAOBJ_H_ 313