#define CONTENT_LENGTH "Content-Length"
#define UTF16_STR "utf-16"
+static WCHAR emptyW[] = {0};
+
typedef struct {
const nsIInputStreamVtbl *lpInputStreamVtbl;
typedef struct {
void (*destroy)(BSCallback*);
+ HRESULT (*init_bindinfo)(BSCallback*);
HRESULT (*start_binding)(BSCallback*);
HRESULT (*stop_binding)(BSCallback*,HRESULT);
HRESULT (*read_data)(BSCallback*,IStream*);
HRESULT (*on_progress)(BSCallback*,ULONG,LPCWSTR);
+ HRESULT (*on_response)(BSCallback*,DWORD);
} BSCallbackVtbl;
struct BSCallback {
ULONG post_data_len;
ULONG readed;
DWORD bindf;
+ BOOL bindinfo_ready;
IMoniker *mon;
IBinding *binding;
- HTMLDocument *doc;
+ HTMLDocumentNode *doc;
struct list entry;
};
PRUint32 *_retval)
{
nsProtocolStream *This = NSINSTREAM_THIS(iface);
+ DWORD read = aCount;
TRACE("(%p)->(%p %d %p)\n", This, aBuf, aCount, _retval);
- /* Gecko always calls Read with big enough buffer */
- if(aCount < This->buf_size)
- FIXME("aCount < This->buf_size\n");
+ if(read > This->buf_size)
+ read = This->buf_size;
- *_retval = This->buf_size;
- if(This->buf_size)
- memcpy(aBuf, This->buf, This->buf_size);
- This->buf_size = 0;
+ if(read) {
+ memcpy(aBuf, This->buf, read);
+ if(read < This->buf_size)
+ memmove(This->buf, This->buf+read, This->buf_size-read);
+ This->buf_size -= read;
+ }
+ *_retval = read;
return NS_OK;
}
HRESULT hresult, LPCWSTR szError)
{
BSCallback *This = STATUSCLB_THIS(iface);
+ HRESULT hres;
TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
/* NOTE: IE7 calls GetBindResult here */
+ hres = This->vtbl->stop_binding(This, hresult);
+
if(This->binding) {
IBinding_Release(This->binding);
This->binding = NULL;
}
list_remove(&This->entry);
+ This->doc = NULL;
- return This->vtbl->stop_binding(This, hresult);
+ return hres;
}
static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface,
TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
+ if(!This->bindinfo_ready) {
+ HRESULT hres;
+
+ hres = This->vtbl->init_bindinfo(This);
+ if(FAILED(hres))
+ return hres;
+
+ This->bindinfo_ready = TRUE;
+ }
+
*grfBINDF = This->bindf;
size = pbindinfo->cbSize;
LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
{
BSCallback *This = HTTPNEG_THIS(iface);
- FIXME("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders),
+
+ TRACE("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders),
debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders);
- return E_NOTIMPL;
+
+ return This->vtbl->on_response(This, dwResponseCode);
}
static HRESULT WINAPI HttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
}
/* Calls undocumented 84 cmd of CGID_ShellDocView */
-static void call_docview_84(HTMLDocument *doc)
+static void call_docview_84(HTMLDocumentObj *doc)
{
IOleCommandTarget *olecmd;
VARIANT var;
*post_data_len_ret = post_data_len;
}
-HRESULT start_binding(HTMLDocument *doc, BSCallback *bscallback, IBindCtx *bctx)
+HRESULT start_binding(HTMLWindow *window, HTMLDocumentNode *doc, BSCallback *bscallback, IBindCtx *bctx)
{
IStream *str = NULL;
HRESULT hres;
/* NOTE: IE7 calls IsSystemMoniker here*/
- call_docview_84(doc);
+ if(window)
+ call_docview_84(window->doc_obj);
if(bctx) {
RegisterBindStatusCallback(bctx, STATUSCLB(bscallback), NULL, 0);
heap_free(This);
}
+static HRESULT BufferBSC_init_bindinfo(BSCallback *bsc)
+{
+ return S_OK;
+}
+
static HRESULT BufferBSC_start_binding(BSCallback *bsc)
{
return S_OK;
return S_OK;
}
+static HRESULT BufferBSC_on_response(BSCallback *bsc, DWORD response_code)
+{
+ return S_OK;
+}
+
#undef BUFFERBSC_THIS
static const BSCallbackVtbl BufferBSCVtbl = {
BufferBSC_destroy,
+ BufferBSC_init_bindinfo,
BufferBSC_start_binding,
BufferBSC_stop_binding,
BufferBSC_read_data,
BufferBSC_on_progress,
+ BufferBSC_on_response
};
return ret;
}
-HRESULT bind_mon_to_buffer(HTMLDocument *doc, IMoniker *mon, void **buf, DWORD *size)
+HRESULT bind_mon_to_buffer(HTMLDocumentNode *doc, IMoniker *mon, void **buf, DWORD *size)
{
BufferBSC *bsc = create_bufferbsc(mon);
HRESULT hres;
*buf = NULL;
- hres = start_binding(doc, &bsc->bsc, NULL);
+ hres = start_binding(NULL, doc, &bsc->bsc, NULL);
if(SUCCEEDED(hres)) {
hres = bsc->hres;
if(SUCCEEDED(hres)) {
struct nsChannelBSC {
BSCallback bsc;
+ HTMLWindow *window;
+
nsChannel *nschannel;
nsIStreamListener *nslistener;
nsISupports *nscontext;
nsProtocolStream *nsstream;
};
+static void on_start_nsrequest(nsChannelBSC *This)
+{
+ nsresult nsres;
+
+ /* FIXME: it's needed for http connections from BindToObject. */
+ if(!This->nschannel->response_status)
+ This->nschannel->response_status = 200;
+
+ nsres = nsIStreamListener_OnStartRequest(This->nslistener,
+ (nsIRequest*)NSCHANNEL(This->nschannel), This->nscontext);
+ if(NS_FAILED(nsres))
+ FIXME("OnStartRequest failed: %08x\n", nsres);
+}
+
+static void on_stop_nsrequest(nsChannelBSC *This, HRESULT result)
+{
+ nsresult nsres;
+
+ if(!This->nslistener)
+ return;
+
+ if(!This->bsc.readed && SUCCEEDED(result)) {
+ TRACE("No data read! Calling OnStartRequest\n");
+ on_start_nsrequest(This);
+ }
+
+ nsres = nsIStreamListener_OnStopRequest(This->nslistener, (nsIRequest*)NSCHANNEL(This->nschannel),
+ This->nscontext, SUCCEEDED(result) ? NS_OK : NS_ERROR_FAILURE);
+ if(NS_FAILED(nsres))
+ WARN("OnStopRequest failed: %08x\n", nsres);
+}
+
static HRESULT read_stream_data(nsChannelBSC *This, IStream *stream)
{
+ DWORD read;
nsresult nsres;
HRESULT hres;
if(!This->nslistener) {
BYTE buf[1024];
- DWORD read;
do {
read = 0;
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)
+ read = 0;
+ hres = IStream_Read(stream, This->nsstream->buf+This->nsstream->buf_size,
+ sizeof(This->nsstream->buf)-This->nsstream->buf_size, &read);
+ if(!read)
break;
- if(!This->bsc.readed && This->nsstream->buf_size >= 2 && *(WORD*)This->nsstream->buf == 0xfeff) {
- This->nschannel->charset = heap_alloc(sizeof(UTF16_STR));
- memcpy(This->nschannel->charset, UTF16_STR, sizeof(UTF16_STR));
- }
+ This->nsstream->buf_size += read;
if(!This->bsc.readed) {
- nsres = nsIStreamListener_OnStartRequest(This->nslistener,
- (nsIRequest*)NSCHANNEL(This->nschannel), This->nscontext);
- if(NS_FAILED(nsres))
- FIXME("OnStartRequest failed: %08x\n", nsres);
+ if(This->nsstream->buf_size >= 2
+ && (BYTE)This->nsstream->buf[0] == 0xff
+ && (BYTE)This->nsstream->buf[1] == 0xfe)
+ This->nschannel->charset = heap_strdupA(UTF16_STR);
- /* events are reset when a new document URI is loaded, so re-initialise them here */
- if(This->bsc.doc && This->bsc.doc->bscallback == This && This->bsc.doc->nscontainer) {
- update_nsdocument(This->bsc.doc);
- init_nsevents(This->bsc.doc->nscontainer);
+ on_start_nsrequest(This);
+
+ if(This->window)
+ update_window_doc(This->window);
}
- }
This->bsc.readed += 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");
+ if(This->nsstream->buf_size == sizeof(This->nsstream->buf)) {
+ ERR("buffer is full\n");
+ break;
+ }
}while(hres == S_OK);
return S_OK;
}
-static void on_stop_nsrequest(nsChannelBSC *This)
-{
- if(!This->nslistener)
- return;
-
- nsIStreamListener_OnStopRequest(This->nslistener, (nsIRequest*)NSCHANNEL(This->nschannel),
- This->nscontext, NS_OK);
-}
-
static void add_nsrequest(nsChannelBSC *This)
{
nsresult nsres;
return S_OK;
}
+static HRESULT nsChannelBSC_init_bindinfo(BSCallback *bsc)
+{
+ nsChannelBSC *This = NSCHANNELBSC_THIS(bsc);
+
+ if(This->nschannel && This->nschannel->post_data_stream) {
+ parse_post_data(This->nschannel->post_data_stream, &This->bsc.headers, &This->bsc.post_data, &This->bsc.post_data_len);
+ TRACE("headers = %s post_data = %s\n", debugstr_w(This->bsc.headers),
+ debugstr_an(This->bsc.post_data, This->bsc.post_data_len));
+ }
+
+ return S_OK;
+}
+
static HRESULT nsChannelBSC_stop_binding(BSCallback *bsc, HRESULT result)
{
nsChannelBSC *This = NSCHANNELBSC_THIS(bsc);
- on_stop_nsrequest(This);
+ on_stop_nsrequest(This, result);
if(This->nslistener) {
if(This->nschannel->load_group) {
}
}
- if(FAILED(result))
- return S_OK;
-
- if(This->bsc.doc && This->bsc.doc->bscallback == This && !This->bsc.doc->nscontainer) {
- task_t *task = heap_alloc(sizeof(task_t));
-
- task->doc = This->bsc.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.
- */
- push_task(task);
- }
-
return S_OK;
}
return S_OK;
}
+static HRESULT nsChannelBSC_on_response(BSCallback *bsc, DWORD response_code)
+{
+ nsChannelBSC *This = NSCHANNELBSC_THIS(bsc);
+
+ This->nschannel->response_status = response_code;
+ return S_OK;
+}
+
#undef NSCHANNELBSC_THIS
static const BSCallbackVtbl nsChannelBSCVtbl = {
nsChannelBSC_destroy,
+ nsChannelBSC_init_bindinfo,
nsChannelBSC_start_binding,
nsChannelBSC_stop_binding,
nsChannelBSC_read_data,
nsChannelBSC_on_progress,
+ nsChannelBSC_on_response
};
nsChannelBSC *create_channelbsc(IMoniker *mon)
return This->bsc.mon;
}
-void set_document_bscallback(HTMLDocument *doc, nsChannelBSC *callback)
+void set_window_bscallback(HTMLWindow *window, nsChannelBSC *callback)
{
- BSCallback *iter;
+ if(window->bscallback) {
+ if(window->bscallback->bsc.binding)
+ IBinding_Abort(window->bscallback->bsc.binding);
+ window->bscallback->bsc.doc = NULL;
+ window->bscallback->window = NULL;
+ IBindStatusCallback_Release(STATUSCLB(&window->bscallback->bsc));
+ }
+
+ window->bscallback = callback;
- if(doc->bscallback) {
- if(doc->bscallback->bsc.binding)
- IBinding_Abort(doc->bscallback->bsc.binding);
- doc->bscallback->bsc.doc = NULL;
- IBindStatusCallback_Release(STATUSCLB(&doc->bscallback->bsc));
+ if(callback) {
+ callback->window = window;
+ IBindStatusCallback_AddRef(STATUSCLB(&callback->bsc));
+ callback->bsc.doc = window->doc;
}
+}
+
+void abort_document_bindings(HTMLDocumentNode *doc)
+{
+ BSCallback *iter;
LIST_FOR_EACH_ENTRY(iter, &doc->bindings, BSCallback, entry) {
+ if(iter->binding)
+ IBinding_Abort(iter->binding);
iter->doc = NULL;
list_remove(&iter->entry);
}
-
- doc->bscallback = callback;
-
- if(callback) {
- IBindStatusCallback_AddRef(STATUSCLB(&callback->bsc));
- callback->bsc.doc = doc;
- }
}
HRESULT channelbsc_load_stream(nsChannelBSC *bscallback, IStream *stream)
{
HRESULT hres;
- const char text_html[] = "text/html";
+ if(!bscallback->nschannel) {
+ ERR("NULL nschannel\n");
+ return E_FAIL;
+ }
+
+ bscallback->nschannel->content_type = heap_strdupA("text/html");
+ if(!bscallback->nschannel->content_type)
+ return E_OUTOFMEMORY;
add_nsrequest(bscallback);
- if(bscallback->nschannel)
- bscallback->nschannel->content_type = heap_strdupA(text_html);
-
hres = read_stream_data(bscallback, stream);
IBindStatusCallback_OnStopBinding(STATUSCLB(&bscallback->bsc), hres, ERROR_SUCCESS);
}
}
-void hlink_frame_navigate(HTMLDocument *doc, IHlinkFrame *hlink_frame,
- LPCWSTR uri, nsIInputStream *post_data_stream, DWORD hlnf)
+HRESULT hlink_frame_navigate(HTMLDocument *doc, LPCWSTR url,
+ nsIInputStream *post_data_stream, DWORD hlnf)
{
+ IHlinkFrame *hlink_frame;
+ IServiceProvider *sp;
BSCallback *callback;
IBindCtx *bindctx;
IMoniker *mon;
IHlink *hlink;
- HRESULT hr;
+ HRESULT hres;
+
+ hres = IOleClientSite_QueryInterface(doc->doc_obj->client, &IID_IServiceProvider,
+ (void**)&sp);
+ if(FAILED(hres))
+ return hres;
+
+ hres = IServiceProvider_QueryService(sp, &IID_IHlinkFrame, &IID_IHlinkFrame,
+ (void**)&hlink_frame);
+ IServiceProvider_Release(sp);
+ if(FAILED(hres))
+ return hres;
callback = &create_channelbsc(NULL)->bsc;
debugstr_an(callback->post_data, callback->post_data_len));
}
- hr = CreateAsyncBindCtx(0, STATUSCLB(callback), NULL, &bindctx);
- if (FAILED(hr)) {
- IBindStatusCallback_Release(STATUSCLB(callback));
- return;
- }
+ hres = CreateAsyncBindCtx(0, STATUSCLB(callback), NULL, &bindctx);
+ if(SUCCEEDED(hres))
+ hres = CoCreateInstance(&CLSID_StdHlink, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IHlink, (LPVOID*)&hlink);
- hr = CoCreateInstance(&CLSID_StdHlink, NULL, CLSCTX_INPROC_SERVER, &IID_IHlink, (LPVOID*)&hlink);
- if (FAILED(hr)) {
- IBindCtx_Release(bindctx);
- IBindStatusCallback_Release(STATUSCLB(callback));
- return;
- }
+ if(SUCCEEDED(hres))
+ hres = CreateURLMoniker(NULL, url, &mon);
- hr = CreateURLMoniker(NULL, uri, &mon);
- if (SUCCEEDED(hr)) {
- IHlink_SetMonikerReference(hlink, 0, mon, NULL);
+ if(SUCCEEDED(hres)) {
+ IHlink_SetMonikerReference(hlink, HLINKSETF_TARGET, mon, NULL);
if(hlnf & HLNF_OPENINNEWWINDOW) {
static const WCHAR wszBlank[] = {'_','b','l','a','n','k',0};
IHlink_SetTargetFrameName(hlink, wszBlank); /* FIXME */
}
- IHlinkFrame_Navigate(hlink_frame, hlnf, bindctx, STATUSCLB(callback), hlink);
+ hres = IHlinkFrame_Navigate(hlink_frame, hlnf, bindctx, STATUSCLB(callback), hlink);
IMoniker_Release(mon);
}
+ IHlinkFrame_Release(hlink_frame);
IBindCtx_Release(bindctx);
IBindStatusCallback_Release(STATUSCLB(callback));
+ return hres;
+}
+
+HRESULT navigate_url(HTMLDocumentNode *doc, OLECHAR *url)
+{
+ OLECHAR *translated_url = NULL;
+ HRESULT hres;
+
+ if(!url)
+ url = emptyW;
+
+ if(doc->basedoc.doc_obj->hostui) {
+ hres = IDocHostUIHandler_TranslateUrl(doc->basedoc.doc_obj->hostui, 0, url,
+ &translated_url);
+ if(hres == S_OK)
+ url = translated_url;
+ }
+
+ hres = hlink_frame_navigate(&doc->basedoc, url, NULL, 0);
+ if(FAILED(hres))
+ FIXME("hlink_frame_navigate failed: %08x\n", hres);
+
+ CoTaskMemFree(translated_url);
+ return hres;
}