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
;
28 class nsIReferrerInfo
;
30 class nsITransferable
;
34 * This ole registered class is used to facilitate drag-drop of objects which
35 * can be adapted by an object derived from CfDragDrop. The CfDragDrop is
36 * associated with instances via SetDragDrop().
38 class nsDataObj
: public IDataObject
, public IDataObjectAsyncCapability
{
39 RefPtr
<mozilla::LazyIdleThread
> mIOThread
;
41 public: // construction, destruction
42 explicit nsDataObj(nsIURI
* uri
= nullptr);
47 public: // IUnknown methods - see iunknown.h for documentation
48 STDMETHODIMP_(ULONG
) AddRef() override
;
49 STDMETHODIMP
QueryInterface(REFIID
, void**) override
;
50 STDMETHODIMP_(ULONG
) Release() override
;
52 // support for clipboard
53 virtual void AddDataFlavor(const char* aDataFlavor
, LPFORMATETC aFE
);
54 void SetTransferable(nsITransferable
* aTransferable
);
56 public: // IDataObject methods - these are general comments. see CfDragDrop
57 // for overriding behavior
58 // Store data in pSTM according to the format specified by pFE, if the
59 // format is supported (supported formats are specified in CfDragDrop::
60 // GetFormats) and return NOERROR; otherwise return DATA_E_FORMATETC. It
61 // is the callers responsibility to free pSTM if NOERROR is returned.
62 STDMETHODIMP
GetData(LPFORMATETC pFE
, LPSTGMEDIUM pSTM
) override
;
64 // Similar to GetData except that the caller allocates the structure
65 // referenced by pSTM.
66 STDMETHODIMP
GetDataHere(LPFORMATETC pFE
, LPSTGMEDIUM pSTM
) override
;
68 // Returns S_TRUE if this object supports the format specified by pSTM,
70 STDMETHODIMP
QueryGetData(LPFORMATETC pFE
) override
;
72 // Set pCanonFE to the canonical format of pFE if one exists and return
73 // NOERROR, otherwise return DATA_S_SAMEFORMATETC. A canonical format
74 // implies an identical rendering.
75 STDMETHODIMP
GetCanonicalFormatEtc(LPFORMATETC pFE
,
76 LPFORMATETC pCanonFE
) final
;
78 // Set this objects data according to the format specified by pFE and
79 // the storage medium specified by pSTM and return NOERROR, if the format
80 // is supported. If release is TRUE this object must release the storage
81 // associated with pSTM.
82 STDMETHODIMP
SetData(LPFORMATETC pFE
, LPSTGMEDIUM pSTM
,
83 BOOL release
) override
;
85 // Set ppEnum to an IEnumFORMATETC object which will iterate all of the
86 // data formats that this object supports. direction is either DATADIR_GET
88 STDMETHODIMP
EnumFormatEtc(DWORD direction
, LPENUMFORMATETC
* ppEnum
) final
;
90 // Set up an advisory connection to this object based on the format specified
91 // by pFE, flags, and the pAdvise. Set pConn to the established advise
93 STDMETHODIMP
DAdvise(LPFORMATETC pFE
, DWORD flags
, LPADVISESINK pAdvise
,
96 // Turn off advising of a previous call to DAdvise which set pConn.
97 STDMETHODIMP
DUnadvise(DWORD pConn
) final
;
99 // Set ppEnum to an IEnumSTATDATA object which will iterate over the
100 // existing objects which have established advisory connections to this
102 STDMETHODIMP
EnumDAdvise(LPENUMSTATDATA
* ppEnum
) final
;
104 // IDataObjectAsyncCapability methods
105 STDMETHODIMP
EndOperation(HRESULT hResult
, IBindCtx
* pbcReserved
,
106 DWORD dwEffects
) final
;
107 STDMETHODIMP
GetAsyncMode(BOOL
* pfIsOpAsync
) final
;
108 STDMETHODIMP
InOperation(BOOL
* pfInAsyncOp
) final
;
109 STDMETHODIMP
SetAsyncMode(BOOL fDoOpAsync
) final
;
110 STDMETHODIMP
StartOperation(IBindCtx
* pbcReserved
) final
;
112 private: // other methods
113 // Gets the filename from the kFilePromiseURLMime flavour
114 HRESULT
GetDownloadDetails(nsIURI
** aSourceURI
, nsAString
& aFilename
);
116 // help determine the kind of drag
117 bool IsFlavourPresent(const char* inFlavour
);
120 HRESULT
GetFile(FORMATETC
& aFE
, STGMEDIUM
& aSTG
);
121 HRESULT
GetText(const nsACString
& aDF
, FORMATETC
& aFE
, STGMEDIUM
& aSTG
);
124 HRESULT
GetDib(const nsACString
& inFlavor
, FORMATETC
&, STGMEDIUM
& aSTG
);
126 HRESULT
DropImage(FORMATETC
& aFE
, STGMEDIUM
& aSTG
);
127 HRESULT
DropFile(FORMATETC
& aFE
, STGMEDIUM
& aSTG
);
128 HRESULT
DropTempFile(FORMATETC
& aFE
, STGMEDIUM
& aSTG
);
130 HRESULT
GetUniformResourceLocator(FORMATETC
& aFE
, STGMEDIUM
& aSTG
,
132 HRESULT
ExtractUniformResourceLocatorA(FORMATETC
& aFE
, STGMEDIUM
& aSTG
);
133 HRESULT
ExtractUniformResourceLocatorW(FORMATETC
& aFE
, STGMEDIUM
& aSTG
);
134 HRESULT
GetFileDescriptor(FORMATETC
& aFE
, STGMEDIUM
& aSTG
, bool aIsUnicode
);
137 HRESULT
GetFileContents(FORMATETC
& aFE
, STGMEDIUM
& aSTG
);
140 HRESULT
GetPreferredDropEffect(FORMATETC
& aFE
, STGMEDIUM
& aSTG
);
142 // Provide the structures needed for an internet shortcut by the shell
143 HRESULT
GetFileDescriptorInternetShortcutA(FORMATETC
& aFE
, STGMEDIUM
& aSTG
);
144 HRESULT
GetFileDescriptorInternetShortcutW(FORMATETC
& aFE
, STGMEDIUM
& aSTG
);
145 HRESULT
GetFileContentsInternetShortcut(FORMATETC
& aFE
, STGMEDIUM
& aSTG
);
147 // IStream implementation
148 HRESULT
GetFileDescriptor_IStreamA(FORMATETC
& aFE
, STGMEDIUM
& aSTG
);
149 HRESULT
GetFileDescriptor_IStreamW(FORMATETC
& aFE
, STGMEDIUM
& aSTG
);
150 HRESULT
GetFileContents_IStream(FORMATETC
& aFE
, STGMEDIUM
& aSTG
);
152 nsresult
ExtractShortcutURL(nsString
& outURL
);
153 nsresult
ExtractShortcutTitle(nsString
& outTitle
);
155 // munge our HTML data to win32's CF_HTML spec. Will null terminate
156 nsresult
BuildPlatformHTML(const char* inOurHTML
, char** outPlatformHTML
);
158 // Used for the SourceURL part of CF_HTML
159 nsCString mSourceURL
;
162 BOOL
FormatsMatch(const FORMATETC
& source
, const FORMATETC
& target
) const;
164 ULONG m_cRef
; // the reference count
167 nsTArray
<nsCString
> mDataFlavors
;
169 nsITransferable
* mTransferable
; // nsDataObj owns and ref counts
170 // nsITransferable, the nsITransferable does
171 // know anything about the nsDataObj
174 CEnumFormatEtc
* m_enumFE
; // Ownership Rules:
175 // nsDataObj owns and ref counts CEnumFormatEtc,
178 nsCOMPtr
<nsIFile
> mCachedTempFile
;
179 RefPtr
<nsDataObj
> mKeepAlive
;
183 ///////////////////////////////////////////////////////////////////////////////
184 // CStream class implementation
185 // this class is used in Drag and drop with download sample
186 // called from IDataObject::GetData
187 class CStreamBase
: public IStream
{
189 STDMETHODIMP
Clone(IStream
** ppStream
) final
;
190 STDMETHODIMP
Commit(DWORD dwFrags
) final
;
191 STDMETHODIMP
CopyTo(IStream
* pDestStream
, ULARGE_INTEGER nBytesToCopy
,
192 ULARGE_INTEGER
* nBytesRead
,
193 ULARGE_INTEGER
* nBytesWritten
) final
;
194 STDMETHODIMP
LockRegion(ULARGE_INTEGER nStart
, ULARGE_INTEGER nBytes
,
195 DWORD dwFlags
) final
;
196 STDMETHODIMP
Revert(void) final
;
197 STDMETHODIMP
Seek(LARGE_INTEGER nMove
, DWORD dwOrigin
,
198 ULARGE_INTEGER
* nNewPos
) final
;
199 STDMETHODIMP
SetSize(ULARGE_INTEGER nNewSize
) final
;
200 STDMETHODIMP
UnlockRegion(ULARGE_INTEGER nStart
, ULARGE_INTEGER nBytes
,
201 DWORD dwFlags
) final
;
202 STDMETHODIMP
Write(const void* pvBuffer
, ULONG nBytesToRead
,
203 ULONG
* nBytesRead
) final
;
206 uint32_t mStreamRead
;
209 virtual ~CStreamBase();
212 class CStream final
: public CStreamBase
, public nsIStreamListener
{
213 nsCOMPtr
<nsIChannel
> mChannel
;
214 FallibleTArray
<uint8_t> mChannelData
;
215 nsresult mChannelResult
;
219 nsresult
WaitForCompletion();
222 STDMETHOD(QueryInterface
)(REFIID refiid
, void** ppvResult
) final
;
225 STDMETHODIMP
Read(void* pvBuffer
, ULONG nBytesToRead
,
226 ULONG
* nBytesRead
) final
;
227 STDMETHODIMP
Stat(STATSTG
* statstg
, DWORD dwFlags
) final
;
231 nsresult
Init(nsIURI
* pSourceURI
, nsContentPolicyType aContentPolicyType
,
232 nsIPrincipal
* aRequestingPrincipal
,
233 nsICookieJarSettings
* aCookieJarSettings
,
234 nsIReferrerInfo
* aReferrerInfo
);
237 NS_DECL_NSIREQUESTOBSERVER
238 NS_DECL_NSISTREAMLISTENER
241 HRESULT
CreateStream(IStream
** outStream
);
243 // This class must be thread-safe.
244 class AutoCloseEvent final
{
245 const nsAutoHandle mEvent
;
247 AutoCloseEvent(const AutoCloseEvent
&) = delete;
248 void operator=(const AutoCloseEvent
&) = delete;
249 ~AutoCloseEvent() = default;
253 bool IsInited() const;
255 DWORD
Wait(DWORD aMillisec
) const;
256 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AutoCloseEvent
)
259 // This class must be thread-safe.
260 class AutoSetEvent final
{
261 const RefPtr
<AutoCloseEvent
> mEvent
;
263 AutoSetEvent(const AutoSetEvent
&) = delete;
264 void operator=(const AutoSetEvent
&) = delete;
268 explicit AutoSetEvent(mozilla::NotNull
<AutoCloseEvent
*> aEvent
);
270 bool IsWaiting() const;
271 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AutoSetEvent
)
274 // This class must be thread-safe.
275 class CMemStream final
: public CStreamBase
{
276 static mozilla::glue::Win32SRWLock mLock
;
277 const nsAutoGlobalMem mGlobalMem
;
278 const RefPtr
<AutoCloseEvent
> mEvent
;
279 const uint32_t mTotalLength
;
280 RefPtr
<IUnknown
> mMarshaler
;
282 virtual ~CMemStream();
283 void WaitForCompletion();
286 STDMETHODIMP
Read(void* pvBuffer
, ULONG nBytesToRead
,
287 ULONG
* nBytesRead
) final
;
288 STDMETHODIMP
Stat(STATSTG
* statstg
, DWORD dwFlags
) final
;
291 CMemStream(nsHGLOBAL aGlobalMem
, uint32_t mTotalLength
,
292 already_AddRefed
<AutoCloseEvent
> aEvent
);
295 STDMETHOD(QueryInterface
)(REFIID refiid
, void** ppvResult
) final
;
296 NS_INLINE_DECL_THREADSAFE_VIRTUAL_REFCOUNTING(CMemStream
, final
)
300 // Drag and drop helper data for implementing drag and drop image support
304 } DATAENTRY
, *LPDATAENTRY
;
306 nsTArray
<LPDATAENTRY
> mDataEntryList
;
307 nsCOMPtr
<nsITimer
> mTimer
;
309 bool LookupArbitraryFormat(FORMATETC
* aFormat
, LPDATAENTRY
* aDataEntry
,
311 bool CopyMediumData(STGMEDIUM
* aMediumDst
, STGMEDIUM
* aMediumSrc
,
312 LPFORMATETC aFormat
, BOOL aSetData
);
315 #endif // _NSDATAOBJ_H_