/*
- * Copyright 2006 Jacek Caban for CodeWeavers
+ * Copyright 2006-2007 Jacek Caban for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
#define CONTENT_LENGTH "Content-Length"
+#define UTF16_STR "utf-16"
#define NSINSTREAM(x) ((nsIInputStream*) &(x)->lpInputStreamVtbl)
nsProtocolStream *This = NSINSTREAM_THIS(iface);
LONG ref = InterlockedIncrement(&This->ref);
- TRACE("(%p) ref=%ld\n", This, ref);
+ TRACE("(%p) ref=%d\n", This, ref);
return ref;
}
nsProtocolStream *This = NSINSTREAM_THIS(iface);
LONG ref = InterlockedDecrement(&This->ref);
- TRACE("(%p) ref=%ld\n", This, ref);
+ TRACE("(%p) ref=%d\n", This, ref);
if(!ref)
mshtml_free(This);
{
nsProtocolStream *This = NSINSTREAM_THIS(iface);
- TRACE("(%p)->(%p %ld %p)\n", This, aBuf, aCount, _retval);
+ TRACE("(%p)->(%p %d %p)\n", This, aBuf, aCount, _retval);
/* Gecko always calls Read with big enough buffer */
if(aCount < This->buf_size)
PRUint32 written = 0;
nsresult nsres;
- FIXME("(%p)->(%p %p %ld %p)\n", This, aWriter, aClousure, aCount, _retval);
+ TRACE("(%p)->(%p %p %d %p)\n", This, aWriter, aClousure, aCount, _retval);
if(!This->buf_size)
return S_OK;
nsres = aWriter(NSINSTREAM(This), aClousure, This->buf, 0, This->buf_size, &written);
if(NS_FAILED(nsres))
- FIXME("aWritter failed: %08lx\n", nsres);
- if(written != This->buf_size)
- FIXME("written != buf_size\n");
+ TRACE("aWritter failed: %08x\n", nsres);
+ else if(written != This->buf_size)
+ FIXME("written %d != buf_size %d\n", written, This->buf_size);
This->buf_size -= written;
+ *_retval = written;
return nsres;
}
nsInputStream_IsNonBlocking
};
-static nsProtocolStream *create_nsprotocol_stream(IStream *stream)
+static nsProtocolStream *create_nsprotocol_stream(void)
{
nsProtocolStream *ret = mshtml_alloc(sizeof(nsProtocolStream));
return ret;
}
+static HRESULT read_stream_data(BSCallback *This, IStream *stream)
+{
+ nsresult nsres;
+ HRESULT hres;
+
+ if(!This->nslistener) {
+ BYTE buf[1024];
+ DWORD read;
+
+ do {
+ read = 0;
+ hres = IStream_Read(stream, buf, sizeof(buf), &read);
+ }while(hres == S_OK && read);
+
+ return S_OK;
+ }
+
+ if(!This->nsstream)
+ This->nsstream = create_nsprotocol_stream();
+
+ do {
+ hres = IStream_Read(stream, This->nsstream->buf, sizeof(This->nsstream->buf),
+ &This->nsstream->buf_size);
+ if(!This->nsstream->buf_size)
+ break;
+
+ if(!This->readed && This->nsstream->buf_size >= 2 && *(WORD*)This->nsstream->buf == 0xfeff) {
+ This->nschannel->charset = mshtml_alloc(sizeof(UTF16_STR));
+ memcpy(This->nschannel->charset, UTF16_STR, sizeof(UTF16_STR));
+ }
+
+ if(!This->readed) {
+ nsres = nsIStreamListener_OnStartRequest(This->nslistener,
+ (nsIRequest*)NSCHANNEL(This->nschannel), This->nscontext);
+ if(NS_FAILED(nsres))
+ FIXME("OnStartRequest failed: %08x\n", nsres);
+ }
+
+ This->readed += This->nsstream->buf_size;
+
+ nsres = nsIStreamListener_OnDataAvailable(This->nslistener,
+ (nsIRequest*)NSCHANNEL(This->nschannel), This->nscontext,
+ NSINSTREAM(This->nsstream), This->readed-This->nsstream->buf_size,
+ This->nsstream->buf_size);
+ if(NS_FAILED(nsres))
+ ERR("OnDataAvailable failed: %08x\n", nsres);
+
+ if(This->nsstream->buf_size)
+ FIXME("buffer is not empty!\n");
+ }while(hres == S_OK);
+
+ return S_OK;
+}
+
+static void add_nsrequest(BSCallback *This)
+{
+ if(This->nschannel && This->nschannel->load_group) {
+ nsresult nsres = nsILoadGroup_AddRequest(This->nschannel->load_group,
+ (nsIRequest*)NSCHANNEL(This->nschannel), This->nscontext);
+
+ if(NS_FAILED(nsres))
+ ERR("AddRequest failed:%08x\n", nsres);
+ }
+}
+
#define STATUSCLB_THIS(iface) DEFINE_THIS(BSCallback, BindStatusCallback, iface)
static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface,
BSCallback *This = STATUSCLB_THIS(iface);
LONG ref = InterlockedIncrement(&This->ref);
- TRACE("(%p) ref = %ld\n", This, ref);
+ TRACE("(%p) ref = %d\n", This, ref);
return ref;
}
BSCallback *This = STATUSCLB_THIS(iface);
LONG ref = InterlockedDecrement(&This->ref);
- TRACE("(%p) ref = %ld\n", This, ref);
+ TRACE("(%p) ref = %d\n", This, ref);
if(!ref) {
if(This->post_data)
nsISupports_Release(This->nscontext);
if(This->nsstream)
nsIInputStream_Release(NSINSTREAM(This->nsstream));
+ if(This->mon)
+ IMoniker_Release(This->mon);
+ if(This->binding)
+ IBinding_Release(This->binding);
mshtml_free(This->headers);
mshtml_free(This);
}
DWORD dwReserved, IBinding *pbind)
{
BSCallback *This = STATUSCLB_THIS(iface);
- FIXME("(%p)->(%ld %p)\n", This, dwReserved, pbind);
+
+ TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind);
+
+ IBinding_AddRef(pbind);
+ This->binding = pbind;
+
+ add_nsrequest(This);
+
return S_OK;
}
static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
{
BSCallback *This = STATUSCLB_THIS(iface);
- FIXME("(%p)->(%ld)\n", This, reserved);
+ FIXME("(%p)->(%d)\n", This, reserved);
return E_NOTIMPL;
}
{
BSCallback *This = STATUSCLB_THIS(iface);
- TRACE("%p)->(%lu %lu %lu %s)\n", This, ulProgress, ulProgressMax, ulStatusCode,
+ TRACE("%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode,
debugstr_w(szStatusText));
switch(ulStatusCode) {
{
BSCallback *This = STATUSCLB_THIS(iface);
- TRACE("(%p)->(%08lx %s)\n", This, hresult, debugstr_w(szError));
+ TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
- if(This->nslistener)
+ if(This->binding) {
+ IBinding_Release(This->binding);
+ This->binding = NULL;
+ }
+
+ if(This->nslistener) {
nsIStreamListener_OnStopRequest(This->nslistener, (nsIRequest*)NSCHANNEL(This->nschannel),
This->nscontext, NS_OK);
+ if(This->nschannel->load_group) {
+ nsresult nsres;
+
+ nsres = nsILoadGroup_RemoveRequest(This->nschannel->load_group,
+ (nsIRequest*)NSCHANNEL(This->nschannel), NULL, NS_OK);
+ if(NS_FAILED(nsres))
+ ERR("RemoveRequest failed: %08x\n", nsres);
+ }
+ }
+
+ if(This->doc) {
+ task_t *task = mshtml_alloc(sizeof(task_t));
+
+ task->doc = This->doc;
+ task->task_id = TASK_PARSECOMPLETE;
+ task->next = NULL;
+
+ /*
+ * This should be done in the worker thread that parses HTML,
+ * but we don't have such thread (Gecko parses HTML for us).
+ */
+ push_task(task);
+ }
+
return S_OK;
}
memset(pbindinfo, 0, size);
pbindinfo->cbSize = size;
- pbindinfo->cbStgmedData = This->post_data_len;
+ pbindinfo->cbstgmedData = This->post_data_len;
pbindinfo->dwCodePage = CP_UTF8;
- pbindinfo->dwOptions = 0x00020000;
+ pbindinfo->dwOptions = 0x80000;
if(This->post_data) {
pbindinfo->dwBindVerb = BINDVERB_POST;
DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
{
BSCallback *This = STATUSCLB_THIS(iface);
- nsresult nsres;
- HRESULT hres;
- TRACE("(%p)->(%08lx %ld %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
-
- if(This->nslistener) {
- if(!This->nsstream) {
- This->nsstream = create_nsprotocol_stream(pstgmed->u.pstm);
-
- nsres = nsIStreamListener_OnStartRequest(This->nslistener,
- (nsIRequest*)NSCHANNEL(This->nschannel), This->nscontext);
- if(NS_FAILED(nsres))
- FIXME("OnStartRequest failed: %08lx\n", nsres);
- }
-
- do {
- hres = IStream_Read(pstgmed->u.pstm, This->nsstream->buf, sizeof(This->nsstream->buf),
- &This->nsstream->buf_size);
- if(This->nsstream->buf_size) {
- nsres = nsIStreamListener_OnDataAvailable(This->nslistener,
- (nsIRequest*)NSCHANNEL(This->nschannel), This->nscontext,
- NSINSTREAM(This->nsstream), 0 /* FIXME */, dwSize);
- if(NS_FAILED(nsres))
- FIXME("OnDataAvailable failed: %08lx\n", nsres);
-
- if(This->nsstream->buf_size)
- FIXME("buffer is not empty!\n");
- }else {
- break;
- }
- }while(hres == S_OK);
- }
+ TRACE("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
- return S_OK;
+ return read_stream_data(This, pstgmed->u.pstm);
}
static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface,
BSCallback *This = HTTPNEG_THIS(iface);
DWORD size;
- TRACE("(%p)->(%s %s %ld %p)\n", This, debugstr_w(szURL), debugstr_w(szHeaders),
+ TRACE("(%p)->(%s %s %d %p)\n", This, debugstr_w(szURL), debugstr_w(szHeaders),
dwReserved, pszAdditionalHeaders);
if(!This->headers) {
LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
{
BSCallback *This = HTTPNEG_THIS(iface);
- FIXME("(%p)->(%ld %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders),
+ FIXME("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders),
debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders);
return E_NOTIMPL;
}
ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
{
BSCallback *This = BINDINFO_THIS(iface);
- FIXME("(%p)->(%lu %p %lu %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
+ FIXME("(%p)->(%u %p %u %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
return E_NOTIMPL;
}
BSCServiceProvider_QueryService
};
-BSCallback *create_bscallback(HTMLDocument *doc, LPCOLESTR url)
+BSCallback *create_bscallback(IMoniker *mon)
{
BSCallback *ret = mshtml_alloc(sizeof(BSCallback));
ret->post_data = NULL;
ret->headers = NULL;
ret->post_data_len = 0;
+ ret->readed = 0;
ret->nschannel = NULL;
ret->nslistener = NULL;
ret->nscontext = NULL;
ret->nsstream = NULL;
+ ret->binding = NULL;
+ ret->doc = NULL;
+
+ if(mon)
+ IMoniker_AddRef(mon);
+ ret->mon = mon;
return ret;
}
IMoniker *mon;
IHlink *hlink;
- callback = create_bscallback(doc, uri);
+ callback = create_bscallback(NULL);
if(post_data_stream) {
parse_post_data(post_data_stream, &callback->headers, &callback->post_data,
}
-HRESULT start_binding(BSCallback *bscallback, IMoniker *mon)
+HRESULT start_binding(BSCallback *bscallback)
{
IStream *str = NULL;
IBindCtx *bctx;
hres = CreateAsyncBindCtx(0, STATUSCLB(bscallback), NULL, &bctx);
if(FAILED(hres)) {
- WARN("CreateAsyncBindCtx failed: %08lx\n", hres);
+ WARN("CreateAsyncBindCtx failed: %08x\n", hres);
return hres;
}
- hres = IMoniker_BindToStorage(mon, bctx, NULL, &IID_IStream, (void**)&str);
+ hres = IMoniker_BindToStorage(bscallback->mon, bctx, NULL, &IID_IStream, (void**)&str);
IBindCtx_Release(bctx);
if(FAILED(hres)) {
- WARN("BindToStorage failed: %08lx\n", hres);
+ WARN("BindToStorage failed: %08x\n", hres);
return hres;
}
if(str)
IStream_Release(str);
+ IMoniker_Release(bscallback->mon);
+ bscallback->mon = NULL;
return S_OK;
}
+
+void set_document_bscallback(HTMLDocument *doc, BSCallback *callback)
+{
+ if(doc->bscallback) {
+ if(doc->bscallback->binding)
+ IBinding_Abort(doc->bscallback->binding);
+ doc->bscallback->doc = NULL;
+ IBindStatusCallback_Release(STATUSCLB(doc->bscallback));
+ }
+
+ doc->bscallback = callback;
+
+ if(callback) {
+ IBindStatusCallback_AddRef(STATUSCLB(callback));
+ callback->doc = doc;
+ }
+}
+
+HRESULT load_stream(BSCallback *bscallback, IStream *stream)
+{
+ HRESULT hres;
+
+ const char text_html[] = "text/html";
+
+ add_nsrequest(bscallback);
+
+ bscallback->nschannel->content = mshtml_alloc(sizeof(text_html));
+ memcpy(bscallback->nschannel->content, text_html, sizeof(text_html));
+
+ hres = read_stream_data(bscallback, stream);
+ IBindStatusCallback_OnStopBinding(STATUSCLB(bscallback), hres, ERROR_SUCCESS);
+
+ return hres;
+}