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