Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / embedding / browser / activex / src / pluginhostctrl / nsURLDataCallback.cpp
blob4e5c156533ca6cce01eb6d285ba6181319be393e
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
22 * Adam Lock <adamlock@eircom.net>
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
37 #include "stdafx.h"
39 #include <process.h>
41 #include "Pluginhostctrl.h"
42 #include "nsPluginHostWnd.h"
43 #include "nsURLDataCallback.h"
46 /////////////////////////////////////////////////////////////////////////////
47 // nsURLDataCallback
49 nsURLDataCallback::nsURLDataCallback() :
50 m_pOwner(NULL),
51 m_pNotifyData(NULL),
52 m_szContentType(NULL),
53 m_szURL(NULL),
54 m_nDataPos(0),
55 m_nDataMax(0),
56 m_hPostData(NULL),
57 m_bSaveToTempFile(FALSE),
58 m_bNotifyOnWrite(TRUE),
59 m_szTempFileName(NULL),
60 m_pTempFile(NULL)
62 memset(&m_NPStream, 0, sizeof(m_NPStream));
63 m_NPStream.ndata = this;
66 nsURLDataCallback::~nsURLDataCallback()
68 SetPostData(NULL, 0);
69 SetURL(NULL);
70 SetContentType(NULL);
71 if (m_pTempFile)
73 fclose(m_pTempFile);
74 remove(m_szTempFileName);
76 if (m_szTempFileName)
78 free(m_szTempFileName);
82 void nsURLDataCallback::SetPostData(const void *pData, unsigned long nSize)
84 // Copy the post data into an HGLOBAL so it can be given to the
85 // bind object during the call to GetBindInfo
86 if (m_hPostData)
88 GlobalFree(m_hPostData);
89 m_hPostData = NULL;
91 if (pData)
93 m_hPostData = GlobalAlloc(GHND, nSize);
94 if (m_hPostData)
96 void *pPostData = GlobalLock(m_hPostData);
97 ATLASSERT(pPostData);
98 memcpy(pPostData, pData, nSize);
99 GlobalUnlock(m_hPostData);
104 HRESULT nsURLDataCallback::OpenURL(nsPluginHostWnd *pOwner, const TCHAR *szURL, void *pNotifyData, const void *pPostData, unsigned long nPostDataSize)
106 // Create the callback object
107 CComObject<nsURLDataCallback> *pCallback = NULL;
108 CComObject<nsURLDataCallback>::CreateInstance(&pCallback);
109 if (!pCallback)
111 return E_OUTOFMEMORY;
113 pCallback->AddRef();
115 // Initialise it
116 pCallback->SetOwner(pOwner);
117 pCallback->SetNotifyData(pNotifyData);
118 if (pPostData && nPostDataSize > 0)
120 pCallback->SetPostData(pPostData, nPostDataSize);
123 USES_CONVERSION;
124 pCallback->SetURL(T2CA(szURL));
126 // Create an object window on this thread that will be sent messages when
127 // something happens on the worker thread.
128 RECT rcPos = {0, 0, 10, 10};
129 pCallback->Create(HWND_DESKTOP, rcPos);
131 // Start the worker thread
132 _beginthread(StreamThread, 0, pCallback);
134 return S_OK;
137 void __cdecl nsURLDataCallback::StreamThread(void *pData)
139 HRESULT hr = CoInitialize(NULL);
140 ATLASSERT(SUCCEEDED(hr));
142 CComObject<nsURLDataCallback> *pThis = (CComObject<nsURLDataCallback> *) pData;
144 // Open the URL
145 hr = URLOpenStream(NULL, pThis->m_szURL, 0, static_cast<IBindStatusCallback*>(pThis));
146 ATLASSERT(SUCCEEDED(hr));
148 // Pump messages until WM_QUIT arrives
149 BOOL bQuit = FALSE;
150 while (!bQuit)
152 MSG msg;
153 if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
155 if (GetMessage(&msg, NULL, 0, 0))
157 DispatchMessage(&msg);
159 else
161 bQuit = TRUE;
166 CoUninitialize();
167 _endthread();
170 ///////////////////////////////////////////////////////////////////////////////
171 // Windows message handlers
173 LRESULT nsURLDataCallback::OnNPPNewStream(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
175 _NewStreamData *pNewStreamData = (_NewStreamData *) lParam;
177 // Notify the plugin that a new stream has been created
178 if (m_pOwner->m_NPPFuncs.newstream)
180 NPError npres = m_pOwner->m_NPPFuncs.newstream(
181 pNewStreamData->npp,
182 pNewStreamData->contenttype,
183 pNewStreamData->stream,
184 pNewStreamData->seekable,
185 pNewStreamData->stype);
187 // How does the plugin want its data?
188 switch (*(pNewStreamData->stype))
190 case NP_NORMAL:
191 m_bSaveToTempFile = FALSE;
192 m_bNotifyOnWrite = TRUE;
193 break;
194 case NP_ASFILEONLY:
195 m_bNotifyOnWrite = FALSE;
196 m_bSaveToTempFile = TRUE;
197 break;
198 case NP_ASFILE:
199 m_bNotifyOnWrite = TRUE;
200 m_bSaveToTempFile = TRUE;
201 break;
202 case NP_SEEK:
203 // TODO!!!
204 ATLASSERT(0);
205 break;
208 return 0;
211 LRESULT nsURLDataCallback::OnNPPDestroyStream(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
213 _DestroyStreamData *pDestroyStreamData = (_DestroyStreamData *) lParam;
215 // Tell the plugin the name of the temporary file containing the data
216 if (m_bSaveToTempFile)
218 // Close the file
219 if (m_pTempFile)
221 fclose(m_pTempFile);
224 // Determine whether the plugin should be told the name of the temp
225 // file depending on whether it completed properly or not.
226 char *szTempFileName = NULL;
227 if (pDestroyStreamData->reason == NPRES_DONE &&
228 m_pTempFile)
230 szTempFileName = m_szTempFileName;
233 // Notify the plugin
234 if (m_pOwner->m_NPPFuncs.asfile)
236 m_pOwner->m_NPPFuncs.asfile(
237 pDestroyStreamData->npp,
238 pDestroyStreamData->stream,
239 szTempFileName);
242 // Remove the file if it wasn't passed into the plugin
243 if (!szTempFileName ||
244 !m_pOwner->m_NPPFuncs.asfile)
246 remove(szTempFileName);
249 // Cleanup strings & pointers
250 if (m_szTempFileName)
252 free(m_szTempFileName);
253 m_szTempFileName = NULL;
255 m_pTempFile = NULL;
258 // Notify the plugin that the stream has been closed
259 if (m_pOwner->m_NPPFuncs.destroystream)
261 m_pOwner->m_NPPFuncs.destroystream(
262 pDestroyStreamData->npp,
263 pDestroyStreamData->stream,
264 pDestroyStreamData->reason);
267 return 0;
270 LRESULT nsURLDataCallback::OnNPPURLNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
272 _UrlNotifyData *pUrlNotifyData = (_UrlNotifyData *) lParam;
274 // Notify the plugin that the url has loaded
275 if (m_pNotifyData && m_pOwner->m_NPPFuncs.urlnotify)
277 m_pOwner->m_NPPFuncs.urlnotify(
278 pUrlNotifyData->npp,
279 pUrlNotifyData->url,
280 pUrlNotifyData->reason,
281 pUrlNotifyData->notifydata);
283 return 0;
286 LRESULT nsURLDataCallback::OnNPPWriteReady(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
288 _WriteReadyData *pWriteReadyData = (_WriteReadyData *) lParam;
289 if (m_pOwner->m_NPPFuncs.writeready &&
290 m_bNotifyOnWrite)
292 pWriteReadyData->result = m_pOwner->m_NPPFuncs.writeready(
293 pWriteReadyData->npp,
294 pWriteReadyData->stream);
297 return 0;
300 LRESULT nsURLDataCallback::OnNPPWrite(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
302 _WriteData *pWriteData = (_WriteData *) lParam;
304 #ifdef DUMP_STREAM_DATA_AS_HEX
305 // Dumps out the data to the display so you can see it's correct as its
306 // fed into the plugin.
307 const int kLineBreakAfter = 16;
308 const int kSpaceBreakAfter = 8;
309 ATLTRACE(_T("nsURLDataCallback::OnNPPWrite()\n"));
310 for (int i = 0; i < pWriteData->len; i++)
312 TCHAR szLine[100];
313 TCHAR szTmp[20];
314 if (i % kLineBreakAfter == 0)
316 _stprintf(szLine, _T("%04x "), i);
318 unsigned char b = ((unsigned char *) pWriteData->buffer)[i];
319 _stprintf(szTmp, _T("%02X "), (unsigned int) b);
320 _tcscat(szLine, szTmp);
322 if (i == pWriteData->len - 1 ||
323 i % kLineBreakAfter == kLineBreakAfter - 1)
325 _tcscat(szLine, _T("\n"));
326 ATLTRACE(szLine);
328 else if (i % kSpaceBreakAfter == kSpaceBreakAfter - 1)
330 _tcscat(szLine, _T(" "));
333 ATLTRACE(_T("--\n"));
334 #endif
336 if (m_bSaveToTempFile)
338 if (!m_szTempFileName)
340 m_szTempFileName = strdup(_tempnam(NULL, "moz"));
342 if (!m_pTempFile)
344 m_pTempFile = fopen(m_szTempFileName, "wb");
346 ATLASSERT(m_pTempFile);
347 if (m_pTempFile)
349 fwrite(pWriteData->buffer, 1, pWriteData->len, m_pTempFile);
353 if (m_pOwner->m_NPPFuncs.write &&
354 m_bNotifyOnWrite)
356 int32 nConsumed = m_pOwner->m_NPPFuncs.write(
357 pWriteData->npp,
358 pWriteData->stream,
359 pWriteData->offset,
360 pWriteData->len,
361 pWriteData->buffer);
362 if (nConsumed < 0)
364 // TODO destroy the stream!
366 ATLASSERT(nConsumed == pWriteData->len);
368 return 0;
371 LRESULT nsURLDataCallback::OnClassCreatePluginInstance(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
373 // Test whether the plugin for this content type exists or not and if not,
374 // create it right now.
375 if (!m_pOwner->m_bPluginIsAlive &&
376 m_pOwner->m_bCreatePluginFromStreamData)
378 if (FAILED(m_pOwner->LoadPluginByContentType(A2CT(m_szContentType))) ||
379 FAILED(m_pOwner->CreatePluginInstance()))
381 return 1;
384 return 0;
387 LRESULT nsURLDataCallback::OnClassCleanup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
389 DestroyWindow();
390 Release();
391 return 0;
394 ///////////////////////////////////////////////////////////////////////////////
395 // IBindStatusCallback implementation
397 HRESULT STDMETHODCALLTYPE nsURLDataCallback::OnStartBinding(
398 /* [in] */ DWORD dwReserved,
399 /* [in] */ IBinding __RPC_FAR *pib)
401 ATLTRACE(_T("nsURLDataCallback::OnStartBinding()\n"));
402 m_cpBinding = pib;
403 return S_OK;
406 HRESULT STDMETHODCALLTYPE nsURLDataCallback::GetPriority(
407 /* [out] */ LONG __RPC_FAR *pnPriority)
409 return E_NOTIMPL;
412 HRESULT STDMETHODCALLTYPE nsURLDataCallback::OnLowResource(
413 /* [in] */ DWORD reserved)
415 return S_OK;
418 HRESULT STDMETHODCALLTYPE nsURLDataCallback::OnProgress(
419 /* [in] */ ULONG ulProgress,
420 /* [in] */ ULONG ulProgressMax,
421 /* [in] */ ULONG ulStatusCode,
422 /* [in] */ LPCWSTR szStatusText)
424 switch (ulStatusCode)
426 case BINDSTATUS_BEGINDOWNLOADDATA:
427 case BINDSTATUS_REDIRECTING:
429 USES_CONVERSION;
430 SetURL(W2A(szStatusText));
432 break;
434 case BINDSTATUS_MIMETYPEAVAILABLE:
436 USES_CONVERSION;
437 SetContentType(W2A(szStatusText));
439 break;
442 m_nDataMax = ulProgressMax;
443 return S_OK;
446 HRESULT STDMETHODCALLTYPE nsURLDataCallback::OnStopBinding(
447 /* [in] */ HRESULT hresult,
448 /* [unique][in] */ LPCWSTR szError)
450 ATLTRACE(_T("nsURLDataCallback::OnStopBinding()\n"));
451 if (m_pOwner && m_pOwner->m_bPluginIsAlive)
453 // TODO check for aborted ops and send NPRES_USER_BREAK
454 NPReason reason = SUCCEEDED(hresult) ? NPRES_DONE : NPRES_NETWORK_ERR;
456 // Notify the plugin that the stream has been closed
457 _DestroyStreamData destroyStreamData;
458 destroyStreamData.npp = &m_pOwner->m_NPP;
459 destroyStreamData.stream = &m_NPStream;
460 destroyStreamData.reason = reason;
461 SendMessage(WM_NPP_DESTROYSTREAM, 0, (LPARAM) &destroyStreamData);
463 // Notify the plugin that the url has loaded
464 _UrlNotifyData urlNotifyData;
465 urlNotifyData.npp = &m_pOwner->m_NPP;
466 urlNotifyData.url = m_szURL;
467 urlNotifyData.reason = reason;
468 urlNotifyData.notifydata = m_pNotifyData;
469 SendMessage(WM_NPP_URLNOTIFY, 0, (LPARAM) &urlNotifyData);
472 m_cpBinding.Release();
474 SendMessage(WM_CLASS_CLEANUP);
475 PostQuitMessage(0);
477 return S_OK;
480 /* [local] */ HRESULT STDMETHODCALLTYPE nsURLDataCallback::GetBindInfo(
481 /* [out] */ DWORD __RPC_FAR *grfBINDF,
482 /* [unique][out][in] */ BINDINFO __RPC_FAR *pbindinfo)
484 *grfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE |
485 BINDF_GETNEWESTVERSION;
487 ULONG cbSize = pbindinfo->cbSize;
488 memset(pbindinfo, 0, cbSize); // zero out structure
489 pbindinfo->cbSize = cbSize;
490 if (m_hPostData)
492 pbindinfo->dwBindVerb = BINDVERB_POST;
493 pbindinfo->stgmedData.tymed = TYMED_HGLOBAL;
494 pbindinfo->stgmedData.hGlobal = m_hPostData;
496 else
498 pbindinfo->dwBindVerb = BINDVERB_GET;
501 return S_OK ;
504 /* [local] */ HRESULT STDMETHODCALLTYPE nsURLDataCallback::OnDataAvailable(
505 /* [in] */ DWORD grfBSCF,
506 /* [in] */ DWORD dwSize,
507 /* [in] */ FORMATETC __RPC_FAR *pformatetc,
508 /* [in] */ STGMEDIUM __RPC_FAR *pstgmed)
510 ATLTRACE(_T("nsURLDataCallback::OnDataAvailable()\n"));
511 if (pstgmed->tymed != TYMED_ISTREAM ||
512 !pstgmed->pstm)
514 return S_OK;
516 if (!m_pOwner)
518 return S_OK;
521 // Notify the plugin that a stream has been opened
522 if (grfBSCF & BSCF_FIRSTDATANOTIFICATION)
524 USES_CONVERSION;
526 // Test if there is a plugin yet. If not try and create one for this
527 // kind of content.
528 if (SendMessage(WM_CLASS_CREATEPLUGININSTANCE))
530 m_cpBinding->Abort();
531 return S_OK;
534 // Tell the plugin that there is a new stream of data
535 m_NPStream.url = m_szURL;
536 m_NPStream.end = 0;
537 m_NPStream.lastmodified = 0;
538 m_NPStream.notifyData = m_pNotifyData;
540 uint16 stype = NP_NORMAL;
541 _NewStreamData newStreamData;
542 newStreamData.npp = &m_pOwner->m_NPP;
543 newStreamData.contenttype = m_szContentType;
544 newStreamData.stream = &m_NPStream;
545 newStreamData.seekable = FALSE;
546 newStreamData.stype = &stype;
547 SendMessage(WM_NPP_NEWSTREAM, 0, (LPARAM) &newStreamData);
549 if (!m_pOwner->m_bPluginIsAlive)
551 return S_OK;
554 m_NPStream.end = m_nDataMax;
556 ATLTRACE(_T("Data for stream %s (%d of %d bytes are available)\n"), m_szURL, dwSize, m_NPStream.end);
558 // Feed the stream data into the plugin
559 HRESULT hr;
560 char bData[16384];
561 while (m_nDataPos < dwSize)
563 ULONG nBytesToRead = dwSize - m_nDataPos;
564 ULONG nBytesRead = 0;
566 if (nBytesToRead > sizeof(bData))
568 nBytesToRead = sizeof(bData);
571 // How many bytes can the plugin cope with?
572 _WriteReadyData writeReadyData;
573 writeReadyData.npp = &m_pOwner->m_NPP;
574 writeReadyData.stream = &m_NPStream;
575 writeReadyData.result = nBytesToRead;
576 SendMessage(WM_NPP_WRITEREADY, 0, (LPARAM) &writeReadyData);
577 if (nBytesToRead > writeReadyData.result)
579 nBytesToRead = writeReadyData.result;
582 // Read 'n' feed
583 ATLTRACE(_T(" Reading %d bytes\n"), (int) nBytesToRead);
584 hr = pstgmed->pstm->Read(&bData, nBytesToRead, &nBytesRead);
586 _WriteData writeData;
587 writeData.npp = &m_pOwner->m_NPP;
588 writeData.stream = &m_NPStream;
589 writeData.offset = m_nDataPos;
590 writeData.len = nBytesRead;
591 writeData.buffer = bData;
592 SendMessage(WM_NPP_WRITE, 0, (LPARAM) &writeData);
594 m_nDataPos += nBytesRead;
597 return S_OK;
600 HRESULT STDMETHODCALLTYPE nsURLDataCallback::OnObjectAvailable(
601 /* [in] */ REFIID riid,
602 /* [iid_is][in] */ IUnknown __RPC_FAR *punk)
604 return S_OK;
607 ///////////////////////////////////////////////////////////////////////////////
608 // IAuthenticate implementation
610 HRESULT STDMETHODCALLTYPE nsURLDataCallback::Authenticate(
611 /* [out] */ HWND __RPC_FAR *phwnd,
612 /* [out] */ LPWSTR __RPC_FAR *pszUsername,
613 /* [out] */ LPWSTR __RPC_FAR *pszPassword)
615 ATLTRACE(_T("nsURLDataCallback::Authenticate()\n"));
617 // Caller wants to pose a password dialog so get a parent HWND for it.
618 *phwnd = HWND_DESKTOP;
619 if (m_pOwner)
621 *phwnd = m_pOwner->m_hWnd;
622 CComPtr<IWebBrowserApp> cpBrowser;
623 m_pOwner->GetWebBrowserApp(&cpBrowser);
624 if (cpBrowser)
626 long hwnd = NULL;
627 cpBrowser->get_HWND(&hwnd);
628 if (hwnd)
630 *phwnd = (HWND) hwnd;
635 // Caller will figure these out for itself
636 *pszUsername = NULL;
637 *pszPassword = NULL;
639 return S_OK;