1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * Copyright 2006-2010 Jacek Caban for CodeWeavers
3*c2c66affSColin Finck *
4*c2c66affSColin Finck * This library is free software; you can redistribute it and/or
5*c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
6*c2c66affSColin Finck * License as published by the Free Software Foundation; either
7*c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
8*c2c66affSColin Finck *
9*c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
10*c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12*c2c66affSColin Finck * Lesser General Public License for more details.
13*c2c66affSColin Finck *
14*c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
15*c2c66affSColin Finck * License along with this library; if not, write to the Free Software
16*c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17*c2c66affSColin Finck */
18*c2c66affSColin Finck
19*c2c66affSColin Finck #include "mshtml_private.h"
20*c2c66affSColin Finck
21*c2c66affSColin Finck #include <hlguids.h>
22*c2c66affSColin Finck #include <htiface.h>
23*c2c66affSColin Finck
24*c2c66affSColin Finck #define CONTENT_LENGTH "Content-Length"
25*c2c66affSColin Finck #define UTF8_STR "utf-8"
26*c2c66affSColin Finck #define UTF16_STR "utf-16"
27*c2c66affSColin Finck
28*c2c66affSColin Finck static const WCHAR emptyW[] = {0};
29*c2c66affSColin Finck static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
30*c2c66affSColin Finck
31*c2c66affSColin Finck struct nsProtocolStream {
32*c2c66affSColin Finck nsIInputStream nsIInputStream_iface;
33*c2c66affSColin Finck
34*c2c66affSColin Finck LONG ref;
35*c2c66affSColin Finck
36*c2c66affSColin Finck char buf[1024];
37*c2c66affSColin Finck DWORD buf_size;
38*c2c66affSColin Finck };
39*c2c66affSColin Finck
impl_from_nsIInputStream(nsIInputStream * iface)40*c2c66affSColin Finck static inline nsProtocolStream *impl_from_nsIInputStream(nsIInputStream *iface)
41*c2c66affSColin Finck {
42*c2c66affSColin Finck return CONTAINING_RECORD(iface, nsProtocolStream, nsIInputStream_iface);
43*c2c66affSColin Finck }
44*c2c66affSColin Finck
nsInputStream_QueryInterface(nsIInputStream * iface,nsIIDRef riid,void ** result)45*c2c66affSColin Finck static nsresult NSAPI nsInputStream_QueryInterface(nsIInputStream *iface, nsIIDRef riid,
46*c2c66affSColin Finck void **result)
47*c2c66affSColin Finck {
48*c2c66affSColin Finck nsProtocolStream *This = impl_from_nsIInputStream(iface);
49*c2c66affSColin Finck
50*c2c66affSColin Finck *result = NULL;
51*c2c66affSColin Finck
52*c2c66affSColin Finck if(IsEqualGUID(&IID_nsISupports, riid)) {
53*c2c66affSColin Finck TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
54*c2c66affSColin Finck *result = &This->nsIInputStream_iface;
55*c2c66affSColin Finck }else if(IsEqualGUID(&IID_nsIInputStream, riid)) {
56*c2c66affSColin Finck TRACE("(%p)->(IID_nsIInputStream %p)\n", This, result);
57*c2c66affSColin Finck *result = &This->nsIInputStream_iface;
58*c2c66affSColin Finck }
59*c2c66affSColin Finck
60*c2c66affSColin Finck if(*result) {
61*c2c66affSColin Finck nsIInputStream_AddRef(&This->nsIInputStream_iface);
62*c2c66affSColin Finck return NS_OK;
63*c2c66affSColin Finck }
64*c2c66affSColin Finck
65*c2c66affSColin Finck WARN("unsupported interface %s\n", debugstr_guid(riid));
66*c2c66affSColin Finck return NS_NOINTERFACE;
67*c2c66affSColin Finck }
68*c2c66affSColin Finck
nsInputStream_AddRef(nsIInputStream * iface)69*c2c66affSColin Finck static nsrefcnt NSAPI nsInputStream_AddRef(nsIInputStream *iface)
70*c2c66affSColin Finck {
71*c2c66affSColin Finck nsProtocolStream *This = impl_from_nsIInputStream(iface);
72*c2c66affSColin Finck LONG ref = InterlockedIncrement(&This->ref);
73*c2c66affSColin Finck
74*c2c66affSColin Finck TRACE("(%p) ref=%d\n", This, ref);
75*c2c66affSColin Finck
76*c2c66affSColin Finck return ref;
77*c2c66affSColin Finck }
78*c2c66affSColin Finck
79*c2c66affSColin Finck
nsInputStream_Release(nsIInputStream * iface)80*c2c66affSColin Finck static nsrefcnt NSAPI nsInputStream_Release(nsIInputStream *iface)
81*c2c66affSColin Finck {
82*c2c66affSColin Finck nsProtocolStream *This = impl_from_nsIInputStream(iface);
83*c2c66affSColin Finck LONG ref = InterlockedDecrement(&This->ref);
84*c2c66affSColin Finck
85*c2c66affSColin Finck TRACE("(%p) ref=%d\n", This, ref);
86*c2c66affSColin Finck
87*c2c66affSColin Finck if(!ref)
88*c2c66affSColin Finck heap_free(This);
89*c2c66affSColin Finck
90*c2c66affSColin Finck return ref;
91*c2c66affSColin Finck }
92*c2c66affSColin Finck
nsInputStream_Close(nsIInputStream * iface)93*c2c66affSColin Finck static nsresult NSAPI nsInputStream_Close(nsIInputStream *iface)
94*c2c66affSColin Finck {
95*c2c66affSColin Finck nsProtocolStream *This = impl_from_nsIInputStream(iface);
96*c2c66affSColin Finck FIXME("(%p)\n", This);
97*c2c66affSColin Finck return NS_ERROR_NOT_IMPLEMENTED;
98*c2c66affSColin Finck }
99*c2c66affSColin Finck
nsInputStream_Available(nsIInputStream * iface,UINT64 * _retval)100*c2c66affSColin Finck static nsresult NSAPI nsInputStream_Available(nsIInputStream *iface, UINT64 *_retval)
101*c2c66affSColin Finck {
102*c2c66affSColin Finck nsProtocolStream *This = impl_from_nsIInputStream(iface);
103*c2c66affSColin Finck FIXME("(%p)->(%p)\n", This, _retval);
104*c2c66affSColin Finck return NS_ERROR_NOT_IMPLEMENTED;
105*c2c66affSColin Finck }
106*c2c66affSColin Finck
nsInputStream_Read(nsIInputStream * iface,char * aBuf,UINT32 aCount,UINT32 * _retval)107*c2c66affSColin Finck static nsresult NSAPI nsInputStream_Read(nsIInputStream *iface, char *aBuf, UINT32 aCount,
108*c2c66affSColin Finck UINT32 *_retval)
109*c2c66affSColin Finck {
110*c2c66affSColin Finck nsProtocolStream *This = impl_from_nsIInputStream(iface);
111*c2c66affSColin Finck DWORD read = aCount;
112*c2c66affSColin Finck
113*c2c66affSColin Finck TRACE("(%p)->(%p %d %p)\n", This, aBuf, aCount, _retval);
114*c2c66affSColin Finck
115*c2c66affSColin Finck if(read > This->buf_size)
116*c2c66affSColin Finck read = This->buf_size;
117*c2c66affSColin Finck
118*c2c66affSColin Finck if(read) {
119*c2c66affSColin Finck memcpy(aBuf, This->buf, read);
120*c2c66affSColin Finck if(read < This->buf_size)
121*c2c66affSColin Finck memmove(This->buf, This->buf+read, This->buf_size-read);
122*c2c66affSColin Finck This->buf_size -= read;
123*c2c66affSColin Finck }
124*c2c66affSColin Finck
125*c2c66affSColin Finck *_retval = read;
126*c2c66affSColin Finck return NS_OK;
127*c2c66affSColin Finck }
128*c2c66affSColin Finck
nsInputStream_ReadSegments(nsIInputStream * iface,nsresult (WINAPI * aWriter)(nsIInputStream *,void *,const char *,UINT32,UINT32,UINT32 *),void * aClousure,UINT32 aCount,UINT32 * _retval)129*c2c66affSColin Finck static nsresult NSAPI nsInputStream_ReadSegments(nsIInputStream *iface,
130*c2c66affSColin Finck nsresult (WINAPI *aWriter)(nsIInputStream*,void*,const char*,UINT32,UINT32,UINT32*),
131*c2c66affSColin Finck void *aClousure, UINT32 aCount, UINT32 *_retval)
132*c2c66affSColin Finck {
133*c2c66affSColin Finck nsProtocolStream *This = impl_from_nsIInputStream(iface);
134*c2c66affSColin Finck UINT32 written = 0;
135*c2c66affSColin Finck nsresult nsres;
136*c2c66affSColin Finck
137*c2c66affSColin Finck TRACE("(%p)->(%p %p %d %p)\n", This, aWriter, aClousure, aCount, _retval);
138*c2c66affSColin Finck
139*c2c66affSColin Finck if(!This->buf_size)
140*c2c66affSColin Finck return S_OK;
141*c2c66affSColin Finck
142*c2c66affSColin Finck if(aCount > This->buf_size)
143*c2c66affSColin Finck aCount = This->buf_size;
144*c2c66affSColin Finck
145*c2c66affSColin Finck nsres = aWriter(&This->nsIInputStream_iface, aClousure, This->buf, 0, aCount, &written);
146*c2c66affSColin Finck if(NS_FAILED(nsres))
147*c2c66affSColin Finck TRACE("aWriter failed: %08x\n", nsres);
148*c2c66affSColin Finck else if(written != This->buf_size)
149*c2c66affSColin Finck FIXME("written %d != buf_size %d\n", written, This->buf_size);
150*c2c66affSColin Finck
151*c2c66affSColin Finck This->buf_size -= written;
152*c2c66affSColin Finck
153*c2c66affSColin Finck *_retval = written;
154*c2c66affSColin Finck return nsres;
155*c2c66affSColin Finck }
156*c2c66affSColin Finck
nsInputStream_IsNonBlocking(nsIInputStream * iface,cpp_bool * _retval)157*c2c66affSColin Finck static nsresult NSAPI nsInputStream_IsNonBlocking(nsIInputStream *iface, cpp_bool *_retval)
158*c2c66affSColin Finck {
159*c2c66affSColin Finck nsProtocolStream *This = impl_from_nsIInputStream(iface);
160*c2c66affSColin Finck FIXME("(%p)->(%p)\n", This, _retval);
161*c2c66affSColin Finck return NS_ERROR_NOT_IMPLEMENTED;
162*c2c66affSColin Finck }
163*c2c66affSColin Finck
164*c2c66affSColin Finck static const nsIInputStreamVtbl nsInputStreamVtbl = {
165*c2c66affSColin Finck nsInputStream_QueryInterface,
166*c2c66affSColin Finck nsInputStream_AddRef,
167*c2c66affSColin Finck nsInputStream_Release,
168*c2c66affSColin Finck nsInputStream_Close,
169*c2c66affSColin Finck nsInputStream_Available,
170*c2c66affSColin Finck nsInputStream_Read,
171*c2c66affSColin Finck nsInputStream_ReadSegments,
172*c2c66affSColin Finck nsInputStream_IsNonBlocking
173*c2c66affSColin Finck };
174*c2c66affSColin Finck
create_nsprotocol_stream(void)175*c2c66affSColin Finck static nsProtocolStream *create_nsprotocol_stream(void)
176*c2c66affSColin Finck {
177*c2c66affSColin Finck nsProtocolStream *ret;
178*c2c66affSColin Finck
179*c2c66affSColin Finck ret = heap_alloc(sizeof(nsProtocolStream));
180*c2c66affSColin Finck if(!ret)
181*c2c66affSColin Finck return NULL;
182*c2c66affSColin Finck
183*c2c66affSColin Finck ret->nsIInputStream_iface.lpVtbl = &nsInputStreamVtbl;
184*c2c66affSColin Finck ret->ref = 1;
185*c2c66affSColin Finck ret->buf_size = 0;
186*c2c66affSColin Finck
187*c2c66affSColin Finck return ret;
188*c2c66affSColin Finck }
189*c2c66affSColin Finck
release_request_data(request_data_t * request_data)190*c2c66affSColin Finck static void release_request_data(request_data_t *request_data)
191*c2c66affSColin Finck {
192*c2c66affSColin Finck if(request_data->post_stream)
193*c2c66affSColin Finck nsIInputStream_Release(request_data->post_stream);
194*c2c66affSColin Finck heap_free(request_data->headers);
195*c2c66affSColin Finck if(request_data->post_data)
196*c2c66affSColin Finck GlobalFree(request_data->post_data);
197*c2c66affSColin Finck }
198*c2c66affSColin Finck
impl_from_IBindStatusCallback(IBindStatusCallback * iface)199*c2c66affSColin Finck static inline BSCallback *impl_from_IBindStatusCallback(IBindStatusCallback *iface)
200*c2c66affSColin Finck {
201*c2c66affSColin Finck return CONTAINING_RECORD(iface, BSCallback, IBindStatusCallback_iface);
202*c2c66affSColin Finck }
203*c2c66affSColin Finck
BindStatusCallback_QueryInterface(IBindStatusCallback * iface,REFIID riid,void ** ppv)204*c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface,
205*c2c66affSColin Finck REFIID riid, void **ppv)
206*c2c66affSColin Finck {
207*c2c66affSColin Finck BSCallback *This = impl_from_IBindStatusCallback(iface);
208*c2c66affSColin Finck
209*c2c66affSColin Finck *ppv = NULL;
210*c2c66affSColin Finck if(IsEqualGUID(&IID_IUnknown, riid)) {
211*c2c66affSColin Finck TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv);
212*c2c66affSColin Finck *ppv = &This->IBindStatusCallback_iface;
213*c2c66affSColin Finck }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
214*c2c66affSColin Finck TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv);
215*c2c66affSColin Finck *ppv = &This->IBindStatusCallback_iface;
216*c2c66affSColin Finck }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
217*c2c66affSColin Finck TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
218*c2c66affSColin Finck *ppv = &This->IServiceProvider_iface;
219*c2c66affSColin Finck }else if(IsEqualGUID(&IID_IHttpNegotiate, riid)) {
220*c2c66affSColin Finck TRACE("(%p)->(IID_IHttpNegotiate %p)\n", This, ppv);
221*c2c66affSColin Finck *ppv = &This->IHttpNegotiate2_iface;
222*c2c66affSColin Finck }else if(IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
223*c2c66affSColin Finck TRACE("(%p)->(IID_IHttpNegotiate2 %p)\n", This, ppv);
224*c2c66affSColin Finck *ppv = &This->IHttpNegotiate2_iface;
225*c2c66affSColin Finck }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) {
226*c2c66affSColin Finck TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv);
227*c2c66affSColin Finck *ppv = &This->IInternetBindInfo_iface;
228*c2c66affSColin Finck }
229*c2c66affSColin Finck
230*c2c66affSColin Finck if(*ppv) {
231*c2c66affSColin Finck IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
232*c2c66affSColin Finck return S_OK;
233*c2c66affSColin Finck }
234*c2c66affSColin Finck
235*c2c66affSColin Finck TRACE("Unsupported riid = %s\n", debugstr_guid(riid));
236*c2c66affSColin Finck return E_NOINTERFACE;
237*c2c66affSColin Finck }
238*c2c66affSColin Finck
BindStatusCallback_AddRef(IBindStatusCallback * iface)239*c2c66affSColin Finck static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface)
240*c2c66affSColin Finck {
241*c2c66affSColin Finck BSCallback *This = impl_from_IBindStatusCallback(iface);
242*c2c66affSColin Finck LONG ref = InterlockedIncrement(&This->ref);
243*c2c66affSColin Finck
244*c2c66affSColin Finck TRACE("(%p) ref = %d\n", This, ref);
245*c2c66affSColin Finck
246*c2c66affSColin Finck return ref;
247*c2c66affSColin Finck }
248*c2c66affSColin Finck
BindStatusCallback_Release(IBindStatusCallback * iface)249*c2c66affSColin Finck static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface)
250*c2c66affSColin Finck {
251*c2c66affSColin Finck BSCallback *This = impl_from_IBindStatusCallback(iface);
252*c2c66affSColin Finck LONG ref = InterlockedDecrement(&This->ref);
253*c2c66affSColin Finck
254*c2c66affSColin Finck TRACE("(%p) ref = %d\n", This, ref);
255*c2c66affSColin Finck
256*c2c66affSColin Finck if(!ref) {
257*c2c66affSColin Finck release_request_data(&This->request_data);
258*c2c66affSColin Finck if(This->mon)
259*c2c66affSColin Finck IMoniker_Release(This->mon);
260*c2c66affSColin Finck if(This->binding)
261*c2c66affSColin Finck IBinding_Release(This->binding);
262*c2c66affSColin Finck list_remove(&This->entry);
263*c2c66affSColin Finck list_init(&This->entry);
264*c2c66affSColin Finck
265*c2c66affSColin Finck This->vtbl->destroy(This);
266*c2c66affSColin Finck }
267*c2c66affSColin Finck
268*c2c66affSColin Finck return ref;
269*c2c66affSColin Finck }
270*c2c66affSColin Finck
BindStatusCallback_OnStartBinding(IBindStatusCallback * iface,DWORD dwReserved,IBinding * pbind)271*c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface,
272*c2c66affSColin Finck DWORD dwReserved, IBinding *pbind)
273*c2c66affSColin Finck {
274*c2c66affSColin Finck BSCallback *This = impl_from_IBindStatusCallback(iface);
275*c2c66affSColin Finck
276*c2c66affSColin Finck TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind);
277*c2c66affSColin Finck
278*c2c66affSColin Finck IBinding_AddRef(pbind);
279*c2c66affSColin Finck This->binding = pbind;
280*c2c66affSColin Finck
281*c2c66affSColin Finck if(This->window)
282*c2c66affSColin Finck list_add_head(&This->window->bindings, &This->entry);
283*c2c66affSColin Finck
284*c2c66affSColin Finck return This->vtbl->start_binding(This);
285*c2c66affSColin Finck }
286*c2c66affSColin Finck
BindStatusCallback_GetPriority(IBindStatusCallback * iface,LONG * pnPriority)287*c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
288*c2c66affSColin Finck {
289*c2c66affSColin Finck BSCallback *This = impl_from_IBindStatusCallback(iface);
290*c2c66affSColin Finck FIXME("(%p)->(%p)\n", This, pnPriority);
291*c2c66affSColin Finck return E_NOTIMPL;
292*c2c66affSColin Finck }
293*c2c66affSColin Finck
BindStatusCallback_OnLowResource(IBindStatusCallback * iface,DWORD reserved)294*c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
295*c2c66affSColin Finck {
296*c2c66affSColin Finck BSCallback *This = impl_from_IBindStatusCallback(iface);
297*c2c66affSColin Finck FIXME("(%p)->(%d)\n", This, reserved);
298*c2c66affSColin Finck return E_NOTIMPL;
299*c2c66affSColin Finck }
300*c2c66affSColin Finck
BindStatusCallback_OnProgress(IBindStatusCallback * iface,ULONG ulProgress,ULONG ulProgressMax,ULONG ulStatusCode,LPCWSTR szStatusText)301*c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
302*c2c66affSColin Finck ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
303*c2c66affSColin Finck {
304*c2c66affSColin Finck BSCallback *This = impl_from_IBindStatusCallback(iface);
305*c2c66affSColin Finck
306*c2c66affSColin Finck TRACE("%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode,
307*c2c66affSColin Finck debugstr_w(szStatusText));
308*c2c66affSColin Finck
309*c2c66affSColin Finck return This->vtbl->on_progress(This, ulStatusCode, szStatusText);
310*c2c66affSColin Finck }
311*c2c66affSColin Finck
BindStatusCallback_OnStopBinding(IBindStatusCallback * iface,HRESULT hresult,LPCWSTR szError)312*c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface,
313*c2c66affSColin Finck HRESULT hresult, LPCWSTR szError)
314*c2c66affSColin Finck {
315*c2c66affSColin Finck BSCallback *This = impl_from_IBindStatusCallback(iface);
316*c2c66affSColin Finck HRESULT hres;
317*c2c66affSColin Finck
318*c2c66affSColin Finck TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
319*c2c66affSColin Finck
320*c2c66affSColin Finck /* NOTE: IE7 calls GetBindResult here */
321*c2c66affSColin Finck
322*c2c66affSColin Finck hres = This->vtbl->stop_binding(This, hresult);
323*c2c66affSColin Finck
324*c2c66affSColin Finck if(This->binding) {
325*c2c66affSColin Finck IBinding_Release(This->binding);
326*c2c66affSColin Finck This->binding = NULL;
327*c2c66affSColin Finck }
328*c2c66affSColin Finck
329*c2c66affSColin Finck if(This->mon) {
330*c2c66affSColin Finck IMoniker_Release(This->mon);
331*c2c66affSColin Finck This->mon = NULL;
332*c2c66affSColin Finck }
333*c2c66affSColin Finck
334*c2c66affSColin Finck list_remove(&This->entry);
335*c2c66affSColin Finck list_init(&This->entry);
336*c2c66affSColin Finck This->window = NULL;
337*c2c66affSColin Finck
338*c2c66affSColin Finck return hres;
339*c2c66affSColin Finck }
340*c2c66affSColin Finck
BindStatusCallback_GetBindInfo(IBindStatusCallback * iface,DWORD * grfBINDF,BINDINFO * pbindinfo)341*c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface,
342*c2c66affSColin Finck DWORD *grfBINDF, BINDINFO *pbindinfo)
343*c2c66affSColin Finck {
344*c2c66affSColin Finck BSCallback *This = impl_from_IBindStatusCallback(iface);
345*c2c66affSColin Finck DWORD size;
346*c2c66affSColin Finck
347*c2c66affSColin Finck TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
348*c2c66affSColin Finck
349*c2c66affSColin Finck if(!This->bindinfo_ready) {
350*c2c66affSColin Finck HRESULT hres;
351*c2c66affSColin Finck
352*c2c66affSColin Finck hres = This->vtbl->init_bindinfo(This);
353*c2c66affSColin Finck if(FAILED(hres))
354*c2c66affSColin Finck return hres;
355*c2c66affSColin Finck
356*c2c66affSColin Finck This->bindinfo_ready = TRUE;
357*c2c66affSColin Finck }
358*c2c66affSColin Finck
359*c2c66affSColin Finck *grfBINDF = This->bindf;
360*c2c66affSColin Finck
361*c2c66affSColin Finck size = pbindinfo->cbSize;
362*c2c66affSColin Finck memset(pbindinfo, 0, size);
363*c2c66affSColin Finck pbindinfo->cbSize = size;
364*c2c66affSColin Finck
365*c2c66affSColin Finck pbindinfo->cbstgmedData = This->request_data.post_data_len;
366*c2c66affSColin Finck pbindinfo->dwCodePage = CP_UTF8;
367*c2c66affSColin Finck pbindinfo->dwOptions = 0x80000;
368*c2c66affSColin Finck
369*c2c66affSColin Finck if(This->request_data.post_data_len) {
370*c2c66affSColin Finck pbindinfo->dwBindVerb = BINDVERB_POST;
371*c2c66affSColin Finck
372*c2c66affSColin Finck pbindinfo->stgmedData.tymed = TYMED_HGLOBAL;
373*c2c66affSColin Finck pbindinfo->stgmedData.u.hGlobal = This->request_data.post_data;
374*c2c66affSColin Finck pbindinfo->stgmedData.pUnkForRelease = (IUnknown*)&This->IBindStatusCallback_iface;
375*c2c66affSColin Finck IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
376*c2c66affSColin Finck }
377*c2c66affSColin Finck
378*c2c66affSColin Finck return S_OK;
379*c2c66affSColin Finck }
380*c2c66affSColin Finck
BindStatusCallback_OnDataAvailable(IBindStatusCallback * iface,DWORD grfBSCF,DWORD dwSize,FORMATETC * pformatetc,STGMEDIUM * pstgmed)381*c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface,
382*c2c66affSColin Finck DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
383*c2c66affSColin Finck {
384*c2c66affSColin Finck BSCallback *This = impl_from_IBindStatusCallback(iface);
385*c2c66affSColin Finck
386*c2c66affSColin Finck TRACE("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
387*c2c66affSColin Finck
388*c2c66affSColin Finck return This->vtbl->read_data(This, pstgmed->u.pstm);
389*c2c66affSColin Finck }
390*c2c66affSColin Finck
BindStatusCallback_OnObjectAvailable(IBindStatusCallback * iface,REFIID riid,IUnknown * punk)391*c2c66affSColin Finck static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface,
392*c2c66affSColin Finck REFIID riid, IUnknown *punk)
393*c2c66affSColin Finck {
394*c2c66affSColin Finck BSCallback *This = impl_from_IBindStatusCallback(iface);
395*c2c66affSColin Finck FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk);
396*c2c66affSColin Finck return E_NOTIMPL;
397*c2c66affSColin Finck }
398*c2c66affSColin Finck
399*c2c66affSColin Finck static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
400*c2c66affSColin Finck BindStatusCallback_QueryInterface,
401*c2c66affSColin Finck BindStatusCallback_AddRef,
402*c2c66affSColin Finck BindStatusCallback_Release,
403*c2c66affSColin Finck BindStatusCallback_OnStartBinding,
404*c2c66affSColin Finck BindStatusCallback_GetPriority,
405*c2c66affSColin Finck BindStatusCallback_OnLowResource,
406*c2c66affSColin Finck BindStatusCallback_OnProgress,
407*c2c66affSColin Finck BindStatusCallback_OnStopBinding,
408*c2c66affSColin Finck BindStatusCallback_GetBindInfo,
409*c2c66affSColin Finck BindStatusCallback_OnDataAvailable,
410*c2c66affSColin Finck BindStatusCallback_OnObjectAvailable
411*c2c66affSColin Finck };
412*c2c66affSColin Finck
impl_from_IHttpNegotiate2(IHttpNegotiate2 * iface)413*c2c66affSColin Finck static inline BSCallback *impl_from_IHttpNegotiate2(IHttpNegotiate2 *iface)
414*c2c66affSColin Finck {
415*c2c66affSColin Finck return CONTAINING_RECORD(iface, BSCallback, IHttpNegotiate2_iface);
416*c2c66affSColin Finck }
417*c2c66affSColin Finck
HttpNegotiate_QueryInterface(IHttpNegotiate2 * iface,REFIID riid,void ** ppv)418*c2c66affSColin Finck static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate2 *iface,
419*c2c66affSColin Finck REFIID riid, void **ppv)
420*c2c66affSColin Finck {
421*c2c66affSColin Finck BSCallback *This = impl_from_IHttpNegotiate2(iface);
422*c2c66affSColin Finck return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv);
423*c2c66affSColin Finck }
424*c2c66affSColin Finck
HttpNegotiate_AddRef(IHttpNegotiate2 * iface)425*c2c66affSColin Finck static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate2 *iface)
426*c2c66affSColin Finck {
427*c2c66affSColin Finck BSCallback *This = impl_from_IHttpNegotiate2(iface);
428*c2c66affSColin Finck return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
429*c2c66affSColin Finck }
430*c2c66affSColin Finck
HttpNegotiate_Release(IHttpNegotiate2 * iface)431*c2c66affSColin Finck static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate2 *iface)
432*c2c66affSColin Finck {
433*c2c66affSColin Finck BSCallback *This = impl_from_IHttpNegotiate2(iface);
434*c2c66affSColin Finck return IBindStatusCallback_Release(&This->IBindStatusCallback_iface);
435*c2c66affSColin Finck }
436*c2c66affSColin Finck
HttpNegotiate_BeginningTransaction(IHttpNegotiate2 * iface,LPCWSTR szURL,LPCWSTR szHeaders,DWORD dwReserved,LPWSTR * pszAdditionalHeaders)437*c2c66affSColin Finck static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface,
438*c2c66affSColin Finck LPCWSTR szURL, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
439*c2c66affSColin Finck {
440*c2c66affSColin Finck BSCallback *This = impl_from_IHttpNegotiate2(iface);
441*c2c66affSColin Finck HRESULT hres;
442*c2c66affSColin Finck
443*c2c66affSColin Finck TRACE("(%p)->(%s %s %d %p)\n", This, debugstr_w(szURL), debugstr_w(szHeaders),
444*c2c66affSColin Finck dwReserved, pszAdditionalHeaders);
445*c2c66affSColin Finck
446*c2c66affSColin Finck *pszAdditionalHeaders = NULL;
447*c2c66affSColin Finck
448*c2c66affSColin Finck hres = This->vtbl->beginning_transaction(This, pszAdditionalHeaders);
449*c2c66affSColin Finck if(hres != S_FALSE)
450*c2c66affSColin Finck return hres;
451*c2c66affSColin Finck
452*c2c66affSColin Finck if(This->request_data.headers) {
453*c2c66affSColin Finck DWORD size;
454*c2c66affSColin Finck
455*c2c66affSColin Finck size = (strlenW(This->request_data.headers)+1)*sizeof(WCHAR);
456*c2c66affSColin Finck *pszAdditionalHeaders = CoTaskMemAlloc(size);
457*c2c66affSColin Finck if(!*pszAdditionalHeaders)
458*c2c66affSColin Finck return E_OUTOFMEMORY;
459*c2c66affSColin Finck memcpy(*pszAdditionalHeaders, This->request_data.headers, size);
460*c2c66affSColin Finck }
461*c2c66affSColin Finck
462*c2c66affSColin Finck return S_OK;
463*c2c66affSColin Finck }
464*c2c66affSColin Finck
HttpNegotiate_OnResponse(IHttpNegotiate2 * iface,DWORD dwResponseCode,LPCWSTR szResponseHeaders,LPCWSTR szRequestHeaders,LPWSTR * pszAdditionalRequestHeaders)465*c2c66affSColin Finck static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode,
466*c2c66affSColin Finck LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
467*c2c66affSColin Finck {
468*c2c66affSColin Finck BSCallback *This = impl_from_IHttpNegotiate2(iface);
469*c2c66affSColin Finck
470*c2c66affSColin Finck TRACE("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders),
471*c2c66affSColin Finck debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders);
472*c2c66affSColin Finck
473*c2c66affSColin Finck return This->vtbl->on_response(This, dwResponseCode, szResponseHeaders);
474*c2c66affSColin Finck }
475*c2c66affSColin Finck
HttpNegotiate_GetRootSecurityId(IHttpNegotiate2 * iface,BYTE * pbSecurityId,DWORD * pcbSecurityId,DWORD_PTR dwReserved)476*c2c66affSColin Finck static HRESULT WINAPI HttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
477*c2c66affSColin Finck BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
478*c2c66affSColin Finck {
479*c2c66affSColin Finck BSCallback *This = impl_from_IHttpNegotiate2(iface);
480*c2c66affSColin Finck FIXME("(%p)->(%p %p %ld)\n", This, pbSecurityId, pcbSecurityId, dwReserved);
481*c2c66affSColin Finck return E_NOTIMPL;
482*c2c66affSColin Finck }
483*c2c66affSColin Finck
484*c2c66affSColin Finck static const IHttpNegotiate2Vtbl HttpNegotiate2Vtbl = {
485*c2c66affSColin Finck HttpNegotiate_QueryInterface,
486*c2c66affSColin Finck HttpNegotiate_AddRef,
487*c2c66affSColin Finck HttpNegotiate_Release,
488*c2c66affSColin Finck HttpNegotiate_BeginningTransaction,
489*c2c66affSColin Finck HttpNegotiate_OnResponse,
490*c2c66affSColin Finck HttpNegotiate_GetRootSecurityId
491*c2c66affSColin Finck };
492*c2c66affSColin Finck
impl_from_IInternetBindInfo(IInternetBindInfo * iface)493*c2c66affSColin Finck static inline BSCallback *impl_from_IInternetBindInfo(IInternetBindInfo *iface)
494*c2c66affSColin Finck {
495*c2c66affSColin Finck return CONTAINING_RECORD(iface, BSCallback, IInternetBindInfo_iface);
496*c2c66affSColin Finck }
497*c2c66affSColin Finck
InternetBindInfo_QueryInterface(IInternetBindInfo * iface,REFIID riid,void ** ppv)498*c2c66affSColin Finck static HRESULT WINAPI InternetBindInfo_QueryInterface(IInternetBindInfo *iface,
499*c2c66affSColin Finck REFIID riid, void **ppv)
500*c2c66affSColin Finck {
501*c2c66affSColin Finck BSCallback *This = impl_from_IInternetBindInfo(iface);
502*c2c66affSColin Finck return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv);
503*c2c66affSColin Finck }
504*c2c66affSColin Finck
InternetBindInfo_AddRef(IInternetBindInfo * iface)505*c2c66affSColin Finck static ULONG WINAPI InternetBindInfo_AddRef(IInternetBindInfo *iface)
506*c2c66affSColin Finck {
507*c2c66affSColin Finck BSCallback *This = impl_from_IInternetBindInfo(iface);
508*c2c66affSColin Finck return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
509*c2c66affSColin Finck }
510*c2c66affSColin Finck
InternetBindInfo_Release(IInternetBindInfo * iface)511*c2c66affSColin Finck static ULONG WINAPI InternetBindInfo_Release(IInternetBindInfo *iface)
512*c2c66affSColin Finck {
513*c2c66affSColin Finck BSCallback *This = impl_from_IInternetBindInfo(iface);
514*c2c66affSColin Finck return IBindStatusCallback_Release(&This->IBindStatusCallback_iface);
515*c2c66affSColin Finck }
516*c2c66affSColin Finck
InternetBindInfo_GetBindInfo(IInternetBindInfo * iface,DWORD * grfBINDF,BINDINFO * pbindinfo)517*c2c66affSColin Finck static HRESULT WINAPI InternetBindInfo_GetBindInfo(IInternetBindInfo *iface,
518*c2c66affSColin Finck DWORD *grfBINDF, BINDINFO *pbindinfo)
519*c2c66affSColin Finck {
520*c2c66affSColin Finck BSCallback *This = impl_from_IInternetBindInfo(iface);
521*c2c66affSColin Finck FIXME("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
522*c2c66affSColin Finck return E_NOTIMPL;
523*c2c66affSColin Finck }
524*c2c66affSColin Finck
InternetBindInfo_GetBindString(IInternetBindInfo * iface,ULONG ulStringType,LPOLESTR * ppwzStr,ULONG cEl,ULONG * pcElFetched)525*c2c66affSColin Finck static HRESULT WINAPI InternetBindInfo_GetBindString(IInternetBindInfo *iface,
526*c2c66affSColin Finck ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
527*c2c66affSColin Finck {
528*c2c66affSColin Finck BSCallback *This = impl_from_IInternetBindInfo(iface);
529*c2c66affSColin Finck FIXME("(%p)->(%u %p %u %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
530*c2c66affSColin Finck return E_NOTIMPL;
531*c2c66affSColin Finck }
532*c2c66affSColin Finck
533*c2c66affSColin Finck static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
534*c2c66affSColin Finck InternetBindInfo_QueryInterface,
535*c2c66affSColin Finck InternetBindInfo_AddRef,
536*c2c66affSColin Finck InternetBindInfo_Release,
537*c2c66affSColin Finck InternetBindInfo_GetBindInfo,
538*c2c66affSColin Finck InternetBindInfo_GetBindString
539*c2c66affSColin Finck };
540*c2c66affSColin Finck
impl_from_IServiceProvider(IServiceProvider * iface)541*c2c66affSColin Finck static inline BSCallback *impl_from_IServiceProvider(IServiceProvider *iface)
542*c2c66affSColin Finck {
543*c2c66affSColin Finck return CONTAINING_RECORD(iface, BSCallback, IServiceProvider_iface);
544*c2c66affSColin Finck }
545*c2c66affSColin Finck
BSCServiceProvider_QueryInterface(IServiceProvider * iface,REFIID riid,void ** ppv)546*c2c66affSColin Finck static HRESULT WINAPI BSCServiceProvider_QueryInterface(IServiceProvider *iface,
547*c2c66affSColin Finck REFIID riid, void **ppv)
548*c2c66affSColin Finck {
549*c2c66affSColin Finck BSCallback *This = impl_from_IServiceProvider(iface);
550*c2c66affSColin Finck return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv);
551*c2c66affSColin Finck }
552*c2c66affSColin Finck
BSCServiceProvider_AddRef(IServiceProvider * iface)553*c2c66affSColin Finck static ULONG WINAPI BSCServiceProvider_AddRef(IServiceProvider *iface)
554*c2c66affSColin Finck {
555*c2c66affSColin Finck BSCallback *This = impl_from_IServiceProvider(iface);
556*c2c66affSColin Finck return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
557*c2c66affSColin Finck }
558*c2c66affSColin Finck
BSCServiceProvider_Release(IServiceProvider * iface)559*c2c66affSColin Finck static ULONG WINAPI BSCServiceProvider_Release(IServiceProvider *iface)
560*c2c66affSColin Finck {
561*c2c66affSColin Finck BSCallback *This = impl_from_IServiceProvider(iface);
562*c2c66affSColin Finck return IBindStatusCallback_Release(&This->IBindStatusCallback_iface);
563*c2c66affSColin Finck }
564*c2c66affSColin Finck
BSCServiceProvider_QueryService(IServiceProvider * iface,REFGUID guidService,REFIID riid,void ** ppv)565*c2c66affSColin Finck static HRESULT WINAPI BSCServiceProvider_QueryService(IServiceProvider *iface,
566*c2c66affSColin Finck REFGUID guidService, REFIID riid, void **ppv)
567*c2c66affSColin Finck {
568*c2c66affSColin Finck BSCallback *This = impl_from_IServiceProvider(iface);
569*c2c66affSColin Finck
570*c2c66affSColin Finck TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
571*c2c66affSColin Finck
572*c2c66affSColin Finck if(This->window && IsEqualGUID(guidService, &IID_IWindowForBindingUI))
573*c2c66affSColin Finck return IServiceProvider_QueryService(&This->window->base.IServiceProvider_iface, guidService, riid, ppv);
574*c2c66affSColin Finck return E_NOINTERFACE;
575*c2c66affSColin Finck }
576*c2c66affSColin Finck
577*c2c66affSColin Finck static const IServiceProviderVtbl ServiceProviderVtbl = {
578*c2c66affSColin Finck BSCServiceProvider_QueryInterface,
579*c2c66affSColin Finck BSCServiceProvider_AddRef,
580*c2c66affSColin Finck BSCServiceProvider_Release,
581*c2c66affSColin Finck BSCServiceProvider_QueryService
582*c2c66affSColin Finck };
583*c2c66affSColin Finck
init_bscallback(BSCallback * This,const BSCallbackVtbl * vtbl,IMoniker * mon,DWORD bindf)584*c2c66affSColin Finck void init_bscallback(BSCallback *This, const BSCallbackVtbl *vtbl, IMoniker *mon, DWORD bindf)
585*c2c66affSColin Finck {
586*c2c66affSColin Finck This->IBindStatusCallback_iface.lpVtbl = &BindStatusCallbackVtbl;
587*c2c66affSColin Finck This->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
588*c2c66affSColin Finck This->IHttpNegotiate2_iface.lpVtbl = &HttpNegotiate2Vtbl;
589*c2c66affSColin Finck This->IInternetBindInfo_iface.lpVtbl = &InternetBindInfoVtbl;
590*c2c66affSColin Finck This->vtbl = vtbl;
591*c2c66affSColin Finck This->ref = 1;
592*c2c66affSColin Finck This->bindf = bindf;
593*c2c66affSColin Finck This->bom = BOM_NONE;
594*c2c66affSColin Finck
595*c2c66affSColin Finck list_init(&This->entry);
596*c2c66affSColin Finck
597*c2c66affSColin Finck if(mon)
598*c2c66affSColin Finck IMoniker_AddRef(mon);
599*c2c66affSColin Finck This->mon = mon;
600*c2c66affSColin Finck }
601*c2c66affSColin Finck
read_stream(BSCallback * This,IStream * stream,void * buf,DWORD size,DWORD * ret_size)602*c2c66affSColin Finck HRESULT read_stream(BSCallback *This, IStream *stream, void *buf, DWORD size, DWORD *ret_size)
603*c2c66affSColin Finck {
604*c2c66affSColin Finck DWORD read_size = 0, skip=0;
605*c2c66affSColin Finck BYTE *data = buf;
606*c2c66affSColin Finck HRESULT hres;
607*c2c66affSColin Finck
608*c2c66affSColin Finck hres = IStream_Read(stream, buf, size, &read_size);
609*c2c66affSColin Finck
610*c2c66affSColin Finck if(!This->readed && This->bom == BOM_NONE) {
611*c2c66affSColin Finck if(read_size >= 2 && data[0] == 0xff && data[1] == 0xfe) {
612*c2c66affSColin Finck This->bom = BOM_UTF16;
613*c2c66affSColin Finck skip = 2;
614*c2c66affSColin Finck }else if(read_size >= 3 && data[0] == 0xef && data[1] == 0xbb && data[2] == 0xbf) {
615*c2c66affSColin Finck This->bom = BOM_UTF8;
616*c2c66affSColin Finck skip = 3;
617*c2c66affSColin Finck }
618*c2c66affSColin Finck if(skip) {
619*c2c66affSColin Finck read_size -= skip;
620*c2c66affSColin Finck if(read_size)
621*c2c66affSColin Finck memmove(data, data+skip, read_size);
622*c2c66affSColin Finck }
623*c2c66affSColin Finck }
624*c2c66affSColin Finck
625*c2c66affSColin Finck This->readed += read_size;
626*c2c66affSColin Finck *ret_size = read_size;
627*c2c66affSColin Finck return hres;
628*c2c66affSColin Finck }
629*c2c66affSColin Finck
parse_content_type(nsChannelBSC * This,const WCHAR * value)630*c2c66affSColin Finck static void parse_content_type(nsChannelBSC *This, const WCHAR *value)
631*c2c66affSColin Finck {
632*c2c66affSColin Finck const WCHAR *ptr;
633*c2c66affSColin Finck size_t len;
634*c2c66affSColin Finck
635*c2c66affSColin Finck static const WCHAR charsetW[] = {'c','h','a','r','s','e','t','='};
636*c2c66affSColin Finck
637*c2c66affSColin Finck ptr = strchrW(value, ';');
638*c2c66affSColin Finck if(!ptr)
639*c2c66affSColin Finck return;
640*c2c66affSColin Finck
641*c2c66affSColin Finck ptr++;
642*c2c66affSColin Finck while(*ptr && isspaceW(*ptr))
643*c2c66affSColin Finck ptr++;
644*c2c66affSColin Finck
645*c2c66affSColin Finck len = strlenW(value);
646*c2c66affSColin Finck if(ptr + sizeof(charsetW)/sizeof(WCHAR) < value+len && !memicmpW(ptr, charsetW, sizeof(charsetW)/sizeof(WCHAR))) {
647*c2c66affSColin Finck size_t charset_len, lena;
648*c2c66affSColin Finck nsACString charset_str;
649*c2c66affSColin Finck const WCHAR *charset;
650*c2c66affSColin Finck char *charseta;
651*c2c66affSColin Finck
652*c2c66affSColin Finck ptr += sizeof(charsetW)/sizeof(WCHAR);
653*c2c66affSColin Finck
654*c2c66affSColin Finck if(*ptr == '\'') {
655*c2c66affSColin Finck FIXME("Quoted value\n");
656*c2c66affSColin Finck return;
657*c2c66affSColin Finck }else {
658*c2c66affSColin Finck charset = ptr;
659*c2c66affSColin Finck while(*ptr && *ptr != ',')
660*c2c66affSColin Finck ptr++;
661*c2c66affSColin Finck charset_len = ptr-charset;
662*c2c66affSColin Finck }
663*c2c66affSColin Finck
664*c2c66affSColin Finck lena = WideCharToMultiByte(CP_ACP, 0, charset, charset_len, NULL, 0, NULL, NULL);
665*c2c66affSColin Finck charseta = heap_alloc(lena+1);
666*c2c66affSColin Finck if(!charseta)
667*c2c66affSColin Finck return;
668*c2c66affSColin Finck
669*c2c66affSColin Finck WideCharToMultiByte(CP_ACP, 0, charset, charset_len, charseta, lena, NULL, NULL);
670*c2c66affSColin Finck charseta[lena] = 0;
671*c2c66affSColin Finck
672*c2c66affSColin Finck nsACString_InitDepend(&charset_str, charseta);
673*c2c66affSColin Finck nsIHttpChannel_SetContentCharset(&This->nschannel->nsIHttpChannel_iface, &charset_str);
674*c2c66affSColin Finck nsACString_Finish(&charset_str);
675*c2c66affSColin Finck heap_free(charseta);
676*c2c66affSColin Finck }else {
677*c2c66affSColin Finck FIXME("unhandled: %s\n", debugstr_wn(ptr, len - (ptr-value)));
678*c2c66affSColin Finck }
679*c2c66affSColin Finck }
680*c2c66affSColin Finck
parse_headers(const WCHAR * headers,struct list * headers_list)681*c2c66affSColin Finck static HRESULT parse_headers(const WCHAR *headers, struct list *headers_list)
682*c2c66affSColin Finck {
683*c2c66affSColin Finck const WCHAR *header, *header_end, *colon, *value;
684*c2c66affSColin Finck HRESULT hres;
685*c2c66affSColin Finck
686*c2c66affSColin Finck header = headers;
687*c2c66affSColin Finck while(*header) {
688*c2c66affSColin Finck if(header[0] == '\r' && header[1] == '\n' && !header[2])
689*c2c66affSColin Finck break;
690*c2c66affSColin Finck for(colon = header; *colon && *colon != ':' && *colon != '\r'; colon++);
691*c2c66affSColin Finck if(*colon != ':')
692*c2c66affSColin Finck return E_FAIL;
693*c2c66affSColin Finck
694*c2c66affSColin Finck value = colon+1;
695*c2c66affSColin Finck while(*value == ' ')
696*c2c66affSColin Finck value++;
697*c2c66affSColin Finck if(!*value)
698*c2c66affSColin Finck return E_FAIL;
699*c2c66affSColin Finck
700*c2c66affSColin Finck for(header_end = value+1; *header_end && *header_end != '\r'; header_end++);
701*c2c66affSColin Finck
702*c2c66affSColin Finck hres = set_http_header(headers_list, header, colon-header, value, header_end-value);
703*c2c66affSColin Finck if(FAILED(hres))
704*c2c66affSColin Finck return hres;
705*c2c66affSColin Finck
706*c2c66affSColin Finck header = header_end;
707*c2c66affSColin Finck if(header[0] == '\r' && header[1] == '\n')
708*c2c66affSColin Finck header += 2;
709*c2c66affSColin Finck }
710*c2c66affSColin Finck
711*c2c66affSColin Finck return S_OK;
712*c2c66affSColin Finck }
713*c2c66affSColin Finck
process_response_headers(nsChannelBSC * This,const WCHAR * headers)714*c2c66affSColin Finck static HRESULT process_response_headers(nsChannelBSC *This, const WCHAR *headers)
715*c2c66affSColin Finck {
716*c2c66affSColin Finck http_header_t *iter;
717*c2c66affSColin Finck HRESULT hres;
718*c2c66affSColin Finck
719*c2c66affSColin Finck static const WCHAR content_typeW[] = {'c','o','n','t','e','n','t','-','t','y','p','e',0};
720*c2c66affSColin Finck
721*c2c66affSColin Finck hres = parse_headers(headers, &This->nschannel->response_headers);
722*c2c66affSColin Finck if(FAILED(hres))
723*c2c66affSColin Finck return hres;
724*c2c66affSColin Finck
725*c2c66affSColin Finck LIST_FOR_EACH_ENTRY(iter, &This->nschannel->response_headers, http_header_t, entry) {
726*c2c66affSColin Finck if(!strcmpiW(iter->header, content_typeW))
727*c2c66affSColin Finck parse_content_type(This, iter->data);
728*c2c66affSColin Finck }
729*c2c66affSColin Finck
730*c2c66affSColin Finck return S_OK;
731*c2c66affSColin Finck }
732*c2c66affSColin Finck
query_http_info(nsChannelBSC * This,IWinInetHttpInfo * wininet_info)733*c2c66affSColin Finck static void query_http_info(nsChannelBSC *This, IWinInetHttpInfo *wininet_info)
734*c2c66affSColin Finck {
735*c2c66affSColin Finck const WCHAR *ptr;
736*c2c66affSColin Finck DWORD len = 0;
737*c2c66affSColin Finck WCHAR *buf;
738*c2c66affSColin Finck
739*c2c66affSColin Finck IWinInetHttpInfo_QueryInfo(wininet_info, HTTP_QUERY_RAW_HEADERS_CRLF, NULL, &len, NULL, NULL);
740*c2c66affSColin Finck if(!len)
741*c2c66affSColin Finck return;
742*c2c66affSColin Finck
743*c2c66affSColin Finck buf = heap_alloc(len);
744*c2c66affSColin Finck if(!buf)
745*c2c66affSColin Finck return;
746*c2c66affSColin Finck
747*c2c66affSColin Finck IWinInetHttpInfo_QueryInfo(wininet_info, HTTP_QUERY_RAW_HEADERS_CRLF, buf, &len, NULL, NULL);
748*c2c66affSColin Finck if(!len) {
749*c2c66affSColin Finck heap_free(buf);
750*c2c66affSColin Finck return;
751*c2c66affSColin Finck }
752*c2c66affSColin Finck
753*c2c66affSColin Finck ptr = strchrW(buf, '\r');
754*c2c66affSColin Finck if(ptr && ptr[1] == '\n') {
755*c2c66affSColin Finck ptr += 2;
756*c2c66affSColin Finck process_response_headers(This, ptr);
757*c2c66affSColin Finck }
758*c2c66affSColin Finck
759*c2c66affSColin Finck heap_free(buf);
760*c2c66affSColin Finck }
761*c2c66affSColin Finck
start_binding(HTMLInnerWindow * inner_window,BSCallback * bscallback,IBindCtx * bctx)762*c2c66affSColin Finck HRESULT start_binding(HTMLInnerWindow *inner_window, BSCallback *bscallback, IBindCtx *bctx)
763*c2c66affSColin Finck {
764*c2c66affSColin Finck IStream *str = NULL;
765*c2c66affSColin Finck HRESULT hres;
766*c2c66affSColin Finck
767*c2c66affSColin Finck TRACE("(%p %p %p)\n", inner_window, bscallback, bctx);
768*c2c66affSColin Finck
769*c2c66affSColin Finck bscallback->window = inner_window;
770*c2c66affSColin Finck
771*c2c66affSColin Finck /* NOTE: IE7 calls IsSystemMoniker here*/
772*c2c66affSColin Finck
773*c2c66affSColin Finck if(bctx) {
774*c2c66affSColin Finck hres = RegisterBindStatusCallback(bctx, &bscallback->IBindStatusCallback_iface, NULL, 0);
775*c2c66affSColin Finck if(SUCCEEDED(hres))
776*c2c66affSColin Finck IBindCtx_AddRef(bctx);
777*c2c66affSColin Finck }else {
778*c2c66affSColin Finck hres = CreateAsyncBindCtx(0, &bscallback->IBindStatusCallback_iface, NULL, &bctx);
779*c2c66affSColin Finck }
780*c2c66affSColin Finck
781*c2c66affSColin Finck if(FAILED(hres)) {
782*c2c66affSColin Finck bscallback->window = NULL;
783*c2c66affSColin Finck return hres;
784*c2c66affSColin Finck }
785*c2c66affSColin Finck
786*c2c66affSColin Finck hres = IMoniker_BindToStorage(bscallback->mon, bctx, NULL, &IID_IStream, (void**)&str);
787*c2c66affSColin Finck IBindCtx_Release(bctx);
788*c2c66affSColin Finck if(FAILED(hres)) {
789*c2c66affSColin Finck WARN("BindToStorage failed: %08x\n", hres);
790*c2c66affSColin Finck bscallback->window = NULL;
791*c2c66affSColin Finck return hres;
792*c2c66affSColin Finck }
793*c2c66affSColin Finck
794*c2c66affSColin Finck if(str)
795*c2c66affSColin Finck IStream_Release(str);
796*c2c66affSColin Finck
797*c2c66affSColin Finck return S_OK;
798*c2c66affSColin Finck }
799*c2c66affSColin Finck
read_post_data_stream(nsIInputStream * stream,BOOL contains_headers,struct list * headers_list,request_data_t * request_data)800*c2c66affSColin Finck static HRESULT read_post_data_stream(nsIInputStream *stream, BOOL contains_headers, struct list *headers_list,
801*c2c66affSColin Finck request_data_t *request_data)
802*c2c66affSColin Finck {
803*c2c66affSColin Finck nsISeekableStream *seekable_stream;
804*c2c66affSColin Finck UINT64 available = 0;
805*c2c66affSColin Finck UINT32 data_len = 0;
806*c2c66affSColin Finck char *data, *post_data;
807*c2c66affSColin Finck nsresult nsres;
808*c2c66affSColin Finck HRESULT hres = S_OK;
809*c2c66affSColin Finck
810*c2c66affSColin Finck if(!stream)
811*c2c66affSColin Finck return S_OK;
812*c2c66affSColin Finck
813*c2c66affSColin Finck nsres = nsIInputStream_Available(stream, &available);
814*c2c66affSColin Finck if(NS_FAILED(nsres))
815*c2c66affSColin Finck return E_FAIL;
816*c2c66affSColin Finck
817*c2c66affSColin Finck post_data = data = GlobalAlloc(0, available+1);
818*c2c66affSColin Finck if(!data)
819*c2c66affSColin Finck return E_OUTOFMEMORY;
820*c2c66affSColin Finck
821*c2c66affSColin Finck nsres = nsIInputStream_Read(stream, data, available, &data_len);
822*c2c66affSColin Finck if(NS_FAILED(nsres)) {
823*c2c66affSColin Finck GlobalFree(data);
824*c2c66affSColin Finck return E_FAIL;
825*c2c66affSColin Finck }
826*c2c66affSColin Finck
827*c2c66affSColin Finck if(contains_headers) {
828*c2c66affSColin Finck if(data_len >= 2 && data[0] == '\r' && data[1] == '\n') {
829*c2c66affSColin Finck post_data = data+2;
830*c2c66affSColin Finck data_len -= 2;
831*c2c66affSColin Finck }else {
832*c2c66affSColin Finck WCHAR *headers;
833*c2c66affSColin Finck DWORD size;
834*c2c66affSColin Finck char *ptr;
835*c2c66affSColin Finck
836*c2c66affSColin Finck post_data += data_len;
837*c2c66affSColin Finck for(ptr = data; ptr+4 < data+data_len; ptr++) {
838*c2c66affSColin Finck if(!memcmp(ptr, "\r\n\r\n", 4)) {
839*c2c66affSColin Finck ptr += 2;
840*c2c66affSColin Finck post_data = ptr+2;
841*c2c66affSColin Finck break;
842*c2c66affSColin Finck }
843*c2c66affSColin Finck }
844*c2c66affSColin Finck
845*c2c66affSColin Finck data_len -= post_data-data;
846*c2c66affSColin Finck
847*c2c66affSColin Finck size = MultiByteToWideChar(CP_ACP, 0, data, ptr-data, NULL, 0);
848*c2c66affSColin Finck headers = heap_alloc((size+1)*sizeof(WCHAR));
849*c2c66affSColin Finck if(headers) {
850*c2c66affSColin Finck MultiByteToWideChar(CP_ACP, 0, data, ptr-data, headers, size);
851*c2c66affSColin Finck headers[size] = 0;
852*c2c66affSColin Finck if(headers_list)
853*c2c66affSColin Finck hres = parse_headers(headers, headers_list);
854*c2c66affSColin Finck if(SUCCEEDED(hres))
855*c2c66affSColin Finck request_data->headers = headers;
856*c2c66affSColin Finck else
857*c2c66affSColin Finck heap_free(headers);
858*c2c66affSColin Finck }else {
859*c2c66affSColin Finck hres = E_OUTOFMEMORY;
860*c2c66affSColin Finck }
861*c2c66affSColin Finck }
862*c2c66affSColin Finck }
863*c2c66affSColin Finck
864*c2c66affSColin Finck if(FAILED(hres)) {
865*c2c66affSColin Finck GlobalFree(data);
866*c2c66affSColin Finck return hres;
867*c2c66affSColin Finck }
868*c2c66affSColin Finck
869*c2c66affSColin Finck if(!data_len) {
870*c2c66affSColin Finck GlobalFree(data);
871*c2c66affSColin Finck post_data = NULL;
872*c2c66affSColin Finck }else if(post_data != data) {
873*c2c66affSColin Finck char *new_data;
874*c2c66affSColin Finck
875*c2c66affSColin Finck new_data = GlobalAlloc(0, data_len+1);
876*c2c66affSColin Finck if(new_data)
877*c2c66affSColin Finck memcpy(new_data, post_data, data_len);
878*c2c66affSColin Finck GlobalFree(data);
879*c2c66affSColin Finck if(!new_data)
880*c2c66affSColin Finck return E_OUTOFMEMORY;
881*c2c66affSColin Finck post_data = new_data;
882*c2c66affSColin Finck }
883*c2c66affSColin Finck
884*c2c66affSColin Finck if(post_data)
885*c2c66affSColin Finck post_data[data_len] = 0;
886*c2c66affSColin Finck request_data->post_data = post_data;
887*c2c66affSColin Finck request_data->post_data_len = data_len;
888*c2c66affSColin Finck
889*c2c66affSColin Finck nsres = nsIInputStream_QueryInterface(stream, &IID_nsISeekableStream, (void**)&seekable_stream);
890*c2c66affSColin Finck assert(nsres == NS_OK);
891*c2c66affSColin Finck
892*c2c66affSColin Finck nsres = nsISeekableStream_Seek(seekable_stream, NS_SEEK_SET, 0);
893*c2c66affSColin Finck assert(nsres == NS_OK);
894*c2c66affSColin Finck
895*c2c66affSColin Finck nsISeekableStream_Release(seekable_stream);
896*c2c66affSColin Finck
897*c2c66affSColin Finck nsIInputStream_AddRef(stream);
898*c2c66affSColin Finck request_data->post_stream = stream;
899*c2c66affSColin Finck TRACE("post_data = %s\n", debugstr_an(request_data->post_data, request_data->post_data_len));
900*c2c66affSColin Finck return S_OK;
901*c2c66affSColin Finck }
902*c2c66affSColin Finck
on_start_nsrequest(nsChannelBSC * This)903*c2c66affSColin Finck static HRESULT on_start_nsrequest(nsChannelBSC *This)
904*c2c66affSColin Finck {
905*c2c66affSColin Finck nsresult nsres;
906*c2c66affSColin Finck
907*c2c66affSColin Finck /* FIXME: it's needed for http connections from BindToObject. */
908*c2c66affSColin Finck if(!This->nschannel->response_status)
909*c2c66affSColin Finck This->nschannel->response_status = 200;
910*c2c66affSColin Finck
911*c2c66affSColin Finck nsres = nsIStreamListener_OnStartRequest(This->nslistener,
912*c2c66affSColin Finck (nsIRequest*)&This->nschannel->nsIHttpChannel_iface, This->nscontext);
913*c2c66affSColin Finck if(NS_FAILED(nsres)) {
914*c2c66affSColin Finck FIXME("OnStartRequest failed: %08x\n", nsres);
915*c2c66affSColin Finck return E_FAIL;
916*c2c66affSColin Finck }
917*c2c66affSColin Finck
918*c2c66affSColin Finck if(This->is_doc_channel) {
919*c2c66affSColin Finck if(!This->bsc.window)
920*c2c66affSColin Finck return E_ABORT; /* Binding aborted in OnStartRequest call. */
921*c2c66affSColin Finck update_window_doc(This->bsc.window);
922*c2c66affSColin Finck if(This->bsc.window->base.outer_window->readystate != READYSTATE_LOADING)
923*c2c66affSColin Finck set_ready_state(This->bsc.window->base.outer_window, READYSTATE_LOADING);
924*c2c66affSColin Finck }
925*c2c66affSColin Finck
926*c2c66affSColin Finck return S_OK;
927*c2c66affSColin Finck }
928*c2c66affSColin Finck
on_stop_nsrequest(nsChannelBSC * This,HRESULT result)929*c2c66affSColin Finck static void on_stop_nsrequest(nsChannelBSC *This, HRESULT result)
930*c2c66affSColin Finck {
931*c2c66affSColin Finck nsresult nsres, request_result;
932*c2c66affSColin Finck
933*c2c66affSColin Finck switch(result) {
934*c2c66affSColin Finck case S_OK:
935*c2c66affSColin Finck request_result = NS_OK;
936*c2c66affSColin Finck break;
937*c2c66affSColin Finck case E_ABORT:
938*c2c66affSColin Finck request_result = NS_BINDING_ABORTED;
939*c2c66affSColin Finck break;
940*c2c66affSColin Finck default:
941*c2c66affSColin Finck request_result = NS_ERROR_FAILURE;
942*c2c66affSColin Finck }
943*c2c66affSColin Finck
944*c2c66affSColin Finck if(This->nslistener) {
945*c2c66affSColin Finck nsres = nsIStreamListener_OnStopRequest(This->nslistener,
946*c2c66affSColin Finck (nsIRequest*)&This->nschannel->nsIHttpChannel_iface, This->nscontext,
947*c2c66affSColin Finck request_result);
948*c2c66affSColin Finck if(NS_FAILED(nsres))
949*c2c66affSColin Finck WARN("OnStopRequest failed: %08x\n", nsres);
950*c2c66affSColin Finck }
951*c2c66affSColin Finck
952*c2c66affSColin Finck if(This->nschannel && This->nschannel->load_group) {
953*c2c66affSColin Finck nsres = nsILoadGroup_RemoveRequest(This->nschannel->load_group,
954*c2c66affSColin Finck (nsIRequest*)&This->nschannel->nsIHttpChannel_iface, NULL, request_result);
955*c2c66affSColin Finck if(NS_FAILED(nsres))
956*c2c66affSColin Finck ERR("RemoveRequest failed: %08x\n", nsres);
957*c2c66affSColin Finck }
958*c2c66affSColin Finck }
959*c2c66affSColin Finck
read_stream_data(nsChannelBSC * This,IStream * stream)960*c2c66affSColin Finck static HRESULT read_stream_data(nsChannelBSC *This, IStream *stream)
961*c2c66affSColin Finck {
962*c2c66affSColin Finck DWORD read;
963*c2c66affSColin Finck nsresult nsres;
964*c2c66affSColin Finck HRESULT hres;
965*c2c66affSColin Finck
966*c2c66affSColin Finck if(!This->response_processed) {
967*c2c66affSColin Finck IWinInetHttpInfo *wininet_info;
968*c2c66affSColin Finck
969*c2c66affSColin Finck This->response_processed = TRUE;
970*c2c66affSColin Finck if(This->bsc.binding) {
971*c2c66affSColin Finck hres = IBinding_QueryInterface(This->bsc.binding, &IID_IWinInetHttpInfo, (void**)&wininet_info);
972*c2c66affSColin Finck if(SUCCEEDED(hres)) {
973*c2c66affSColin Finck query_http_info(This, wininet_info);
974*c2c66affSColin Finck IWinInetHttpInfo_Release(wininet_info);
975*c2c66affSColin Finck }
976*c2c66affSColin Finck }
977*c2c66affSColin Finck }
978*c2c66affSColin Finck
979*c2c66affSColin Finck if(!This->nschannel)
980*c2c66affSColin Finck return S_OK;
981*c2c66affSColin Finck
982*c2c66affSColin Finck if(!This->nslistener) {
983*c2c66affSColin Finck BYTE buf[1024];
984*c2c66affSColin Finck
985*c2c66affSColin Finck do {
986*c2c66affSColin Finck hres = read_stream(&This->bsc, stream, buf, sizeof(buf), &read);
987*c2c66affSColin Finck }while(hres == S_OK && read);
988*c2c66affSColin Finck
989*c2c66affSColin Finck return S_OK;
990*c2c66affSColin Finck }
991*c2c66affSColin Finck
992*c2c66affSColin Finck if(!This->nsstream) {
993*c2c66affSColin Finck This->nsstream = create_nsprotocol_stream();
994*c2c66affSColin Finck if(!This->nsstream)
995*c2c66affSColin Finck return E_OUTOFMEMORY;
996*c2c66affSColin Finck }
997*c2c66affSColin Finck
998*c2c66affSColin Finck do {
999*c2c66affSColin Finck BOOL first_read = !This->bsc.readed;
1000*c2c66affSColin Finck
1001*c2c66affSColin Finck hres = read_stream(&This->bsc, stream, This->nsstream->buf+This->nsstream->buf_size,
1002*c2c66affSColin Finck sizeof(This->nsstream->buf)-This->nsstream->buf_size, &read);
1003*c2c66affSColin Finck if(!read)
1004*c2c66affSColin Finck break;
1005*c2c66affSColin Finck
1006*c2c66affSColin Finck This->nsstream->buf_size += read;
1007*c2c66affSColin Finck
1008*c2c66affSColin Finck if(first_read) {
1009*c2c66affSColin Finck switch(This->bsc.bom) {
1010*c2c66affSColin Finck case BOM_UTF8:
1011*c2c66affSColin Finck This->nschannel->charset = heap_strdupA(UTF8_STR);
1012*c2c66affSColin Finck break;
1013*c2c66affSColin Finck case BOM_UTF16:
1014*c2c66affSColin Finck This->nschannel->charset = heap_strdupA(UTF16_STR);
1015*c2c66affSColin Finck case BOM_NONE:
1016*c2c66affSColin Finck /* FIXME: Get charset from HTTP headers */;
1017*c2c66affSColin Finck }
1018*c2c66affSColin Finck
1019*c2c66affSColin Finck if(!This->nschannel->content_type) {
1020*c2c66affSColin Finck WCHAR *mime;
1021*c2c66affSColin Finck
1022*c2c66affSColin Finck hres = FindMimeFromData(NULL, NULL, This->nsstream->buf, This->nsstream->buf_size,
1023*c2c66affSColin Finck This->is_doc_channel ? text_htmlW : NULL, 0, &mime, 0);
1024*c2c66affSColin Finck if(FAILED(hres))
1025*c2c66affSColin Finck return hres;
1026*c2c66affSColin Finck
1027*c2c66affSColin Finck TRACE("Found MIME %s\n", debugstr_w(mime));
1028*c2c66affSColin Finck
1029*c2c66affSColin Finck This->nschannel->content_type = heap_strdupWtoA(mime);
1030*c2c66affSColin Finck CoTaskMemFree(mime);
1031*c2c66affSColin Finck if(!This->nschannel->content_type)
1032*c2c66affSColin Finck return E_OUTOFMEMORY;
1033*c2c66affSColin Finck }
1034*c2c66affSColin Finck
1035*c2c66affSColin Finck hres = on_start_nsrequest(This);
1036*c2c66affSColin Finck if(FAILED(hres))
1037*c2c66affSColin Finck return hres;
1038*c2c66affSColin Finck }
1039*c2c66affSColin Finck
1040*c2c66affSColin Finck nsres = nsIStreamListener_OnDataAvailable(This->nslistener,
1041*c2c66affSColin Finck (nsIRequest*)&This->nschannel->nsIHttpChannel_iface, This->nscontext,
1042*c2c66affSColin Finck &This->nsstream->nsIInputStream_iface, This->bsc.readed-This->nsstream->buf_size,
1043*c2c66affSColin Finck This->nsstream->buf_size);
1044*c2c66affSColin Finck if(NS_FAILED(nsres))
1045*c2c66affSColin Finck ERR("OnDataAvailable failed: %08x\n", nsres);
1046*c2c66affSColin Finck
1047*c2c66affSColin Finck if(This->nsstream->buf_size == sizeof(This->nsstream->buf)) {
1048*c2c66affSColin Finck ERR("buffer is full\n");
1049*c2c66affSColin Finck break;
1050*c2c66affSColin Finck }
1051*c2c66affSColin Finck }while(hres == S_OK);
1052*c2c66affSColin Finck
1053*c2c66affSColin Finck return S_OK;
1054*c2c66affSColin Finck }
1055*c2c66affSColin Finck
1056*c2c66affSColin Finck typedef struct {
1057*c2c66affSColin Finck nsIAsyncVerifyRedirectCallback nsIAsyncVerifyRedirectCallback_iface;
1058*c2c66affSColin Finck
1059*c2c66affSColin Finck LONG ref;
1060*c2c66affSColin Finck
1061*c2c66affSColin Finck nsChannel *nschannel;
1062*c2c66affSColin Finck nsChannelBSC *bsc;
1063*c2c66affSColin Finck } nsRedirectCallback;
1064*c2c66affSColin Finck
impl_from_nsIAsyncVerifyRedirectCallback(nsIAsyncVerifyRedirectCallback * iface)1065*c2c66affSColin Finck static nsRedirectCallback *impl_from_nsIAsyncVerifyRedirectCallback(nsIAsyncVerifyRedirectCallback *iface)
1066*c2c66affSColin Finck {
1067*c2c66affSColin Finck return CONTAINING_RECORD(iface, nsRedirectCallback, nsIAsyncVerifyRedirectCallback_iface);
1068*c2c66affSColin Finck }
1069*c2c66affSColin Finck
nsAsyncVerifyRedirectCallback_QueryInterface(nsIAsyncVerifyRedirectCallback * iface,nsIIDRef riid,void ** result)1070*c2c66affSColin Finck static nsresult NSAPI nsAsyncVerifyRedirectCallback_QueryInterface(nsIAsyncVerifyRedirectCallback *iface,
1071*c2c66affSColin Finck nsIIDRef riid, void **result)
1072*c2c66affSColin Finck {
1073*c2c66affSColin Finck nsRedirectCallback *This = impl_from_nsIAsyncVerifyRedirectCallback(iface);
1074*c2c66affSColin Finck
1075*c2c66affSColin Finck if(IsEqualGUID(&IID_nsISupports, riid)) {
1076*c2c66affSColin Finck TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
1077*c2c66affSColin Finck *result = &This->nsIAsyncVerifyRedirectCallback_iface;
1078*c2c66affSColin Finck }else if(IsEqualGUID(&IID_nsIAsyncVerifyRedirectCallback, riid)) {
1079*c2c66affSColin Finck TRACE("(%p)->(IID_nsIAsyncVerifyRedirectCallback %p)\n", This, result);
1080*c2c66affSColin Finck *result = &This->nsIAsyncVerifyRedirectCallback_iface;
1081*c2c66affSColin Finck }else {
1082*c2c66affSColin Finck *result = NULL;
1083*c2c66affSColin Finck WARN("unimplemented iface %s\n", debugstr_guid(riid));
1084*c2c66affSColin Finck return NS_NOINTERFACE;
1085*c2c66affSColin Finck }
1086*c2c66affSColin Finck
1087*c2c66affSColin Finck nsISupports_AddRef((nsISupports*)*result);
1088*c2c66affSColin Finck return NS_OK;
1089*c2c66affSColin Finck }
1090*c2c66affSColin Finck
nsAsyncVerifyRedirectCallback_AddRef(nsIAsyncVerifyRedirectCallback * iface)1091*c2c66affSColin Finck static nsrefcnt NSAPI nsAsyncVerifyRedirectCallback_AddRef(nsIAsyncVerifyRedirectCallback *iface)
1092*c2c66affSColin Finck {
1093*c2c66affSColin Finck nsRedirectCallback *This = impl_from_nsIAsyncVerifyRedirectCallback(iface);
1094*c2c66affSColin Finck LONG ref = InterlockedIncrement(&This->ref);
1095*c2c66affSColin Finck
1096*c2c66affSColin Finck TRACE("(%p) ref=%d\n", This, ref);
1097*c2c66affSColin Finck
1098*c2c66affSColin Finck return ref;
1099*c2c66affSColin Finck }
1100*c2c66affSColin Finck
nsAsyncVerifyRedirectCallback_Release(nsIAsyncVerifyRedirectCallback * iface)1101*c2c66affSColin Finck static nsrefcnt NSAPI nsAsyncVerifyRedirectCallback_Release(nsIAsyncVerifyRedirectCallback *iface)
1102*c2c66affSColin Finck {
1103*c2c66affSColin Finck nsRedirectCallback *This = impl_from_nsIAsyncVerifyRedirectCallback(iface);
1104*c2c66affSColin Finck LONG ref = InterlockedDecrement(&This->ref);
1105*c2c66affSColin Finck
1106*c2c66affSColin Finck TRACE("(%p) ref=%d\n", This, ref);
1107*c2c66affSColin Finck
1108*c2c66affSColin Finck if(!ref) {
1109*c2c66affSColin Finck IBindStatusCallback_Release(&This->bsc->bsc.IBindStatusCallback_iface);
1110*c2c66affSColin Finck nsIHttpChannel_Release(&This->nschannel->nsIHttpChannel_iface);
1111*c2c66affSColin Finck heap_free(This);
1112*c2c66affSColin Finck }
1113*c2c66affSColin Finck
1114*c2c66affSColin Finck return ref;
1115*c2c66affSColin Finck }
1116*c2c66affSColin Finck
nsAsyncVerifyRedirectCallback_OnRedirectVerifyCallback(nsIAsyncVerifyRedirectCallback * iface,nsresult result)1117*c2c66affSColin Finck static nsresult NSAPI nsAsyncVerifyRedirectCallback_OnRedirectVerifyCallback(nsIAsyncVerifyRedirectCallback *iface, nsresult result)
1118*c2c66affSColin Finck {
1119*c2c66affSColin Finck nsRedirectCallback *This = impl_from_nsIAsyncVerifyRedirectCallback(iface);
1120*c2c66affSColin Finck nsChannel *old_nschannel;
1121*c2c66affSColin Finck nsresult nsres;
1122*c2c66affSColin Finck
1123*c2c66affSColin Finck TRACE("(%p)->(%08x)\n", This, result);
1124*c2c66affSColin Finck
1125*c2c66affSColin Finck old_nschannel = This->bsc->nschannel;
1126*c2c66affSColin Finck nsIHttpChannel_AddRef(&This->nschannel->nsIHttpChannel_iface);
1127*c2c66affSColin Finck This->bsc->nschannel = This->nschannel;
1128*c2c66affSColin Finck
1129*c2c66affSColin Finck if(This->nschannel->load_group) {
1130*c2c66affSColin Finck nsres = nsILoadGroup_AddRequest(This->nschannel->load_group, (nsIRequest*)&This->nschannel->nsIHttpChannel_iface,
1131*c2c66affSColin Finck NULL);
1132*c2c66affSColin Finck if(NS_FAILED(nsres))
1133*c2c66affSColin Finck ERR("AddRequest failed: %08x\n", nsres);
1134*c2c66affSColin Finck }
1135*c2c66affSColin Finck
1136*c2c66affSColin Finck if(This->bsc->is_doc_channel) {
1137*c2c66affSColin Finck IUri *uri = nsuri_get_uri(This->nschannel->uri);
1138*c2c66affSColin Finck
1139*c2c66affSColin Finck if(uri) {
1140*c2c66affSColin Finck set_current_uri(This->bsc->bsc.window->base.outer_window, uri);
1141*c2c66affSColin Finck IUri_Release(uri);
1142*c2c66affSColin Finck }else {
1143*c2c66affSColin Finck WARN("Could not get IUri from nsWineURI\n");
1144*c2c66affSColin Finck }
1145*c2c66affSColin Finck }
1146*c2c66affSColin Finck
1147*c2c66affSColin Finck if(old_nschannel) {
1148*c2c66affSColin Finck if(old_nschannel->load_group) {
1149*c2c66affSColin Finck nsres = nsILoadGroup_RemoveRequest(old_nschannel->load_group,
1150*c2c66affSColin Finck (nsIRequest*)&old_nschannel->nsIHttpChannel_iface, NULL, NS_OK);
1151*c2c66affSColin Finck if(NS_FAILED(nsres))
1152*c2c66affSColin Finck ERR("RemoveRequest failed: %08x\n", nsres);
1153*c2c66affSColin Finck }
1154*c2c66affSColin Finck nsIHttpChannel_Release(&old_nschannel->nsIHttpChannel_iface);
1155*c2c66affSColin Finck }
1156*c2c66affSColin Finck
1157*c2c66affSColin Finck return NS_OK;
1158*c2c66affSColin Finck }
1159*c2c66affSColin Finck
1160*c2c66affSColin Finck static const nsIAsyncVerifyRedirectCallbackVtbl nsAsyncVerifyRedirectCallbackVtbl = {
1161*c2c66affSColin Finck nsAsyncVerifyRedirectCallback_QueryInterface,
1162*c2c66affSColin Finck nsAsyncVerifyRedirectCallback_AddRef,
1163*c2c66affSColin Finck nsAsyncVerifyRedirectCallback_Release,
1164*c2c66affSColin Finck nsAsyncVerifyRedirectCallback_OnRedirectVerifyCallback
1165*c2c66affSColin Finck };
1166*c2c66affSColin Finck
create_redirect_callback(nsChannel * nschannel,nsChannelBSC * bsc,nsRedirectCallback ** ret)1167*c2c66affSColin Finck static HRESULT create_redirect_callback(nsChannel *nschannel, nsChannelBSC *bsc, nsRedirectCallback **ret)
1168*c2c66affSColin Finck {
1169*c2c66affSColin Finck nsRedirectCallback *callback;
1170*c2c66affSColin Finck
1171*c2c66affSColin Finck callback = heap_alloc(sizeof(*callback));
1172*c2c66affSColin Finck if(!callback)
1173*c2c66affSColin Finck return E_OUTOFMEMORY;
1174*c2c66affSColin Finck
1175*c2c66affSColin Finck callback->nsIAsyncVerifyRedirectCallback_iface.lpVtbl = &nsAsyncVerifyRedirectCallbackVtbl;
1176*c2c66affSColin Finck callback->ref = 1;
1177*c2c66affSColin Finck
1178*c2c66affSColin Finck nsIHttpChannel_AddRef(&nschannel->nsIHttpChannel_iface);
1179*c2c66affSColin Finck callback->nschannel = nschannel;
1180*c2c66affSColin Finck
1181*c2c66affSColin Finck IBindStatusCallback_AddRef(&bsc->bsc.IBindStatusCallback_iface);
1182*c2c66affSColin Finck callback->bsc = bsc;
1183*c2c66affSColin Finck
1184*c2c66affSColin Finck *ret = callback;
1185*c2c66affSColin Finck return S_OK;
1186*c2c66affSColin Finck }
1187*c2c66affSColin Finck
nsChannelBSC_from_BSCallback(BSCallback * iface)1188*c2c66affSColin Finck static inline nsChannelBSC *nsChannelBSC_from_BSCallback(BSCallback *iface)
1189*c2c66affSColin Finck {
1190*c2c66affSColin Finck return CONTAINING_RECORD(iface, nsChannelBSC, bsc);
1191*c2c66affSColin Finck }
1192*c2c66affSColin Finck
nsChannelBSC_destroy(BSCallback * bsc)1193*c2c66affSColin Finck static void nsChannelBSC_destroy(BSCallback *bsc)
1194*c2c66affSColin Finck {
1195*c2c66affSColin Finck nsChannelBSC *This = nsChannelBSC_from_BSCallback(bsc);
1196*c2c66affSColin Finck
1197*c2c66affSColin Finck if(This->nschannel)
1198*c2c66affSColin Finck nsIHttpChannel_Release(&This->nschannel->nsIHttpChannel_iface);
1199*c2c66affSColin Finck if(This->nslistener)
1200*c2c66affSColin Finck nsIStreamListener_Release(This->nslistener);
1201*c2c66affSColin Finck if(This->nscontext)
1202*c2c66affSColin Finck nsISupports_Release(This->nscontext);
1203*c2c66affSColin Finck if(This->nsstream)
1204*c2c66affSColin Finck nsIInputStream_Release(&This->nsstream->nsIInputStream_iface);
1205*c2c66affSColin Finck heap_free(This);
1206*c2c66affSColin Finck }
1207*c2c66affSColin Finck
nsChannelBSC_start_binding(BSCallback * bsc)1208*c2c66affSColin Finck static HRESULT nsChannelBSC_start_binding(BSCallback *bsc)
1209*c2c66affSColin Finck {
1210*c2c66affSColin Finck nsChannelBSC *This = nsChannelBSC_from_BSCallback(bsc);
1211*c2c66affSColin Finck
1212*c2c66affSColin Finck if(This->is_doc_channel)
1213*c2c66affSColin Finck This->bsc.window->base.outer_window->base.inner_window->doc->skip_mutation_notif = FALSE;
1214*c2c66affSColin Finck
1215*c2c66affSColin Finck return S_OK;
1216*c2c66affSColin Finck }
1217*c2c66affSColin Finck
nsChannelBSC_init_bindinfo(BSCallback * bsc)1218*c2c66affSColin Finck static HRESULT nsChannelBSC_init_bindinfo(BSCallback *bsc)
1219*c2c66affSColin Finck {
1220*c2c66affSColin Finck nsChannelBSC *This = nsChannelBSC_from_BSCallback(bsc);
1221*c2c66affSColin Finck nsChannel *nschannel = This->nschannel;
1222*c2c66affSColin Finck HRESULT hres;
1223*c2c66affSColin Finck
1224*c2c66affSColin Finck if(nschannel && nschannel->post_data_stream) {
1225*c2c66affSColin Finck hres = read_post_data_stream(nschannel->post_data_stream, nschannel->post_data_contains_headers,
1226*c2c66affSColin Finck &nschannel->request_headers, &This->bsc.request_data);
1227*c2c66affSColin Finck if(FAILED(hres))
1228*c2c66affSColin Finck return hres;
1229*c2c66affSColin Finck }
1230*c2c66affSColin Finck
1231*c2c66affSColin Finck return S_OK;
1232*c2c66affSColin Finck }
1233*c2c66affSColin Finck
1234*c2c66affSColin Finck typedef struct {
1235*c2c66affSColin Finck task_t header;
1236*c2c66affSColin Finck nsChannelBSC *bsc;
1237*c2c66affSColin Finck } stop_request_task_t;
1238*c2c66affSColin Finck
stop_request_proc(task_t * _task)1239*c2c66affSColin Finck static void stop_request_proc(task_t *_task)
1240*c2c66affSColin Finck {
1241*c2c66affSColin Finck stop_request_task_t *task = (stop_request_task_t*)_task;
1242*c2c66affSColin Finck
1243*c2c66affSColin Finck TRACE("(%p)\n", task->bsc);
1244*c2c66affSColin Finck
1245*c2c66affSColin Finck list_remove(&task->bsc->bsc.entry);
1246*c2c66affSColin Finck list_init(&task->bsc->bsc.entry);
1247*c2c66affSColin Finck on_stop_nsrequest(task->bsc, S_OK);
1248*c2c66affSColin Finck }
1249*c2c66affSColin Finck
stop_request_task_destr(task_t * _task)1250*c2c66affSColin Finck static void stop_request_task_destr(task_t *_task)
1251*c2c66affSColin Finck {
1252*c2c66affSColin Finck stop_request_task_t *task = (stop_request_task_t*)_task;
1253*c2c66affSColin Finck
1254*c2c66affSColin Finck IBindStatusCallback_Release(&task->bsc->bsc.IBindStatusCallback_iface);
1255*c2c66affSColin Finck heap_free(task);
1256*c2c66affSColin Finck }
1257*c2c66affSColin Finck
async_stop_request(nsChannelBSC * This)1258*c2c66affSColin Finck static HRESULT async_stop_request(nsChannelBSC *This)
1259*c2c66affSColin Finck {
1260*c2c66affSColin Finck stop_request_task_t *task;
1261*c2c66affSColin Finck
1262*c2c66affSColin Finck if(!This->bsc.readed) {
1263*c2c66affSColin Finck TRACE("No data read, calling OnStartRequest\n");
1264*c2c66affSColin Finck on_start_nsrequest(This);
1265*c2c66affSColin Finck }
1266*c2c66affSColin Finck
1267*c2c66affSColin Finck task = heap_alloc(sizeof(*task));
1268*c2c66affSColin Finck if(!task)
1269*c2c66affSColin Finck return E_OUTOFMEMORY;
1270*c2c66affSColin Finck
1271*c2c66affSColin Finck IBindStatusCallback_AddRef(&This->bsc.IBindStatusCallback_iface);
1272*c2c66affSColin Finck task->bsc = This;
1273*c2c66affSColin Finck
1274*c2c66affSColin Finck return push_task(&task->header, stop_request_proc, stop_request_task_destr, This->bsc.window->task_magic);
1275*c2c66affSColin Finck }
1276*c2c66affSColin Finck
handle_navigation_error(nsChannelBSC * This,DWORD result)1277*c2c66affSColin Finck static void handle_navigation_error(nsChannelBSC *This, DWORD result)
1278*c2c66affSColin Finck {
1279*c2c66affSColin Finck HTMLOuterWindow *outer_window;
1280*c2c66affSColin Finck HTMLDocumentObj *doc;
1281*c2c66affSColin Finck BOOL is_error_url;
1282*c2c66affSColin Finck SAFEARRAY *sa;
1283*c2c66affSColin Finck SAFEARRAYBOUND bound;
1284*c2c66affSColin Finck VARIANT var, varOut;
1285*c2c66affSColin Finck LONG ind;
1286*c2c66affSColin Finck BSTR unk;
1287*c2c66affSColin Finck HRESULT hres;
1288*c2c66affSColin Finck
1289*c2c66affSColin Finck if(!This->is_doc_channel || !This->bsc.window)
1290*c2c66affSColin Finck return;
1291*c2c66affSColin Finck
1292*c2c66affSColin Finck outer_window = This->bsc.window->base.outer_window;
1293*c2c66affSColin Finck
1294*c2c66affSColin Finck doc = outer_window->doc_obj;
1295*c2c66affSColin Finck if(!doc || !doc->doc_object_service || !doc->client)
1296*c2c66affSColin Finck return;
1297*c2c66affSColin Finck
1298*c2c66affSColin Finck hres = IDocObjectService_IsErrorUrl(doc->doc_object_service,
1299*c2c66affSColin Finck outer_window->url, &is_error_url);
1300*c2c66affSColin Finck if(FAILED(hres) || is_error_url)
1301*c2c66affSColin Finck return;
1302*c2c66affSColin Finck
1303*c2c66affSColin Finck if(!doc->client_cmdtrg)
1304*c2c66affSColin Finck return;
1305*c2c66affSColin Finck
1306*c2c66affSColin Finck bound.lLbound = 0;
1307*c2c66affSColin Finck bound.cElements = 8;
1308*c2c66affSColin Finck sa = SafeArrayCreate(VT_VARIANT, 1, &bound);
1309*c2c66affSColin Finck if(!sa)
1310*c2c66affSColin Finck return;
1311*c2c66affSColin Finck
1312*c2c66affSColin Finck ind = 0;
1313*c2c66affSColin Finck V_VT(&var) = VT_I4;
1314*c2c66affSColin Finck V_I4(&var) = result;
1315*c2c66affSColin Finck SafeArrayPutElement(sa, &ind, &var);
1316*c2c66affSColin Finck
1317*c2c66affSColin Finck ind = 1;
1318*c2c66affSColin Finck V_VT(&var) = VT_BSTR;
1319*c2c66affSColin Finck V_BSTR(&var) = outer_window->url;
1320*c2c66affSColin Finck SafeArrayPutElement(sa, &ind, &var);
1321*c2c66affSColin Finck
1322*c2c66affSColin Finck ind = 3;
1323*c2c66affSColin Finck V_VT(&var) = VT_UNKNOWN;
1324*c2c66affSColin Finck V_UNKNOWN(&var) = (IUnknown*)&outer_window->base.IHTMLWindow2_iface;
1325*c2c66affSColin Finck SafeArrayPutElement(sa, &ind, &var);
1326*c2c66affSColin Finck
1327*c2c66affSColin Finck /* FIXME: what are the following fields for? */
1328*c2c66affSColin Finck ind = 2;
1329*c2c66affSColin Finck V_VT(&var) = VT_UNKNOWN;
1330*c2c66affSColin Finck V_UNKNOWN(&var) = NULL;
1331*c2c66affSColin Finck SafeArrayPutElement(sa, &ind, &var);
1332*c2c66affSColin Finck
1333*c2c66affSColin Finck ind = 4;
1334*c2c66affSColin Finck V_VT(&var) = VT_BOOL;
1335*c2c66affSColin Finck V_BOOL(&var) = FALSE;
1336*c2c66affSColin Finck SafeArrayPutElement(sa, &ind, &var);
1337*c2c66affSColin Finck
1338*c2c66affSColin Finck ind = 5;
1339*c2c66affSColin Finck V_VT(&var) = VT_BOOL;
1340*c2c66affSColin Finck V_BOOL(&var) = FALSE;
1341*c2c66affSColin Finck SafeArrayPutElement(sa, &ind, &var);
1342*c2c66affSColin Finck
1343*c2c66affSColin Finck ind = 6;
1344*c2c66affSColin Finck V_VT(&var) = VT_BSTR;
1345*c2c66affSColin Finck unk = SysAllocString(NULL);
1346*c2c66affSColin Finck V_BSTR(&var) = unk;
1347*c2c66affSColin Finck SafeArrayPutElement(sa, &ind, &var);
1348*c2c66affSColin Finck
1349*c2c66affSColin Finck ind = 7;
1350*c2c66affSColin Finck V_VT(&var) = VT_UNKNOWN;
1351*c2c66affSColin Finck V_UNKNOWN(&var) = NULL;
1352*c2c66affSColin Finck SafeArrayPutElement(sa, &ind, &var);
1353*c2c66affSColin Finck
1354*c2c66affSColin Finck V_VT(&var) = VT_ARRAY;
1355*c2c66affSColin Finck V_ARRAY(&var) = sa;
1356*c2c66affSColin Finck V_VT(&varOut) = VT_BOOL;
1357*c2c66affSColin Finck V_BOOL(&varOut) = VARIANT_TRUE;
1358*c2c66affSColin Finck IOleCommandTarget_Exec(doc->client_cmdtrg, &CGID_DocHostCmdPriv, 1, 0, &var, FAILED(hres)?NULL:&varOut);
1359*c2c66affSColin Finck
1360*c2c66affSColin Finck SysFreeString(unk);
1361*c2c66affSColin Finck SafeArrayDestroy(sa);
1362*c2c66affSColin Finck }
1363*c2c66affSColin Finck
nsChannelBSC_stop_binding(BSCallback * bsc,HRESULT result)1364*c2c66affSColin Finck static HRESULT nsChannelBSC_stop_binding(BSCallback *bsc, HRESULT result)
1365*c2c66affSColin Finck {
1366*c2c66affSColin Finck nsChannelBSC *This = nsChannelBSC_from_BSCallback(bsc);
1367*c2c66affSColin Finck
1368*c2c66affSColin Finck if(result != E_ABORT) {
1369*c2c66affSColin Finck if(FAILED(result))
1370*c2c66affSColin Finck handle_navigation_error(This, result);
1371*c2c66affSColin Finck else if(This->is_doc_channel && This->nschannel) {
1372*c2c66affSColin Finck result = async_stop_request(This);
1373*c2c66affSColin Finck if(SUCCEEDED(result))
1374*c2c66affSColin Finck return S_OK;
1375*c2c66affSColin Finck }
1376*c2c66affSColin Finck }
1377*c2c66affSColin Finck
1378*c2c66affSColin Finck on_stop_nsrequest(This, result);
1379*c2c66affSColin Finck return S_OK;
1380*c2c66affSColin Finck }
1381*c2c66affSColin Finck
nsChannelBSC_read_data(BSCallback * bsc,IStream * stream)1382*c2c66affSColin Finck static HRESULT nsChannelBSC_read_data(BSCallback *bsc, IStream *stream)
1383*c2c66affSColin Finck {
1384*c2c66affSColin Finck nsChannelBSC *This = nsChannelBSC_from_BSCallback(bsc);
1385*c2c66affSColin Finck
1386*c2c66affSColin Finck return read_stream_data(This, stream);
1387*c2c66affSColin Finck }
1388*c2c66affSColin Finck
handle_redirect(nsChannelBSC * This,const WCHAR * new_url)1389*c2c66affSColin Finck static HRESULT handle_redirect(nsChannelBSC *This, const WCHAR *new_url)
1390*c2c66affSColin Finck {
1391*c2c66affSColin Finck nsRedirectCallback *callback;
1392*c2c66affSColin Finck nsIChannelEventSink *sink;
1393*c2c66affSColin Finck nsChannel *new_channel;
1394*c2c66affSColin Finck nsresult nsres;
1395*c2c66affSColin Finck HRESULT hres;
1396*c2c66affSColin Finck
1397*c2c66affSColin Finck TRACE("(%p)->(%s)\n", This, debugstr_w(new_url));
1398*c2c66affSColin Finck
1399*c2c66affSColin Finck if(!This->nschannel || !This->nschannel->notif_callback)
1400*c2c66affSColin Finck return S_OK;
1401*c2c66affSColin Finck
1402*c2c66affSColin Finck nsres = nsIInterfaceRequestor_GetInterface(This->nschannel->notif_callback, &IID_nsIChannelEventSink, (void**)&sink);
1403*c2c66affSColin Finck if(NS_FAILED(nsres))
1404*c2c66affSColin Finck return S_OK;
1405*c2c66affSColin Finck
1406*c2c66affSColin Finck hres = create_redirect_nschannel(new_url, This->nschannel, &new_channel);
1407*c2c66affSColin Finck if(SUCCEEDED(hres)) {
1408*c2c66affSColin Finck TRACE("%p %p->%p\n", This, This->nschannel, new_channel);
1409*c2c66affSColin Finck
1410*c2c66affSColin Finck hres = create_redirect_callback(new_channel, This, &callback);
1411*c2c66affSColin Finck nsIHttpChannel_Release(&new_channel->nsIHttpChannel_iface);
1412*c2c66affSColin Finck }
1413*c2c66affSColin Finck
1414*c2c66affSColin Finck if(SUCCEEDED(hres)) {
1415*c2c66affSColin Finck nsres = nsIChannelEventSink_AsyncOnChannelRedirect(sink, (nsIChannel*)&This->nschannel->nsIHttpChannel_iface,
1416*c2c66affSColin Finck (nsIChannel*)&callback->nschannel->nsIHttpChannel_iface, REDIRECT_TEMPORARY, /* FIXME */
1417*c2c66affSColin Finck &callback->nsIAsyncVerifyRedirectCallback_iface);
1418*c2c66affSColin Finck
1419*c2c66affSColin Finck if(NS_FAILED(nsres))
1420*c2c66affSColin Finck FIXME("AsyncOnChannelRedirect failed: %08x\n", hres);
1421*c2c66affSColin Finck else if(This->nschannel != callback->nschannel)
1422*c2c66affSColin Finck FIXME("nschannel not updated\n");
1423*c2c66affSColin Finck
1424*c2c66affSColin Finck nsIAsyncVerifyRedirectCallback_Release(&callback->nsIAsyncVerifyRedirectCallback_iface);
1425*c2c66affSColin Finck }
1426*c2c66affSColin Finck
1427*c2c66affSColin Finck nsIChannelEventSink_Release(sink);
1428*c2c66affSColin Finck return hres;
1429*c2c66affSColin Finck }
1430*c2c66affSColin Finck
is_supported_doc_mime(const WCHAR * mime)1431*c2c66affSColin Finck static BOOL is_supported_doc_mime(const WCHAR *mime)
1432*c2c66affSColin Finck {
1433*c2c66affSColin Finck char *nscat, *mimea;
1434*c2c66affSColin Finck BOOL ret;
1435*c2c66affSColin Finck
1436*c2c66affSColin Finck mimea = heap_strdupWtoA(mime);
1437*c2c66affSColin Finck if(!mimea)
1438*c2c66affSColin Finck return FALSE;
1439*c2c66affSColin Finck
1440*c2c66affSColin Finck nscat = get_nscategory_entry("Gecko-Content-Viewers", mimea);
1441*c2c66affSColin Finck
1442*c2c66affSColin Finck ret = nscat != NULL && !strcmp(nscat, "@mozilla.org/content/document-loader-factory;1");
1443*c2c66affSColin Finck
1444*c2c66affSColin Finck heap_free(mimea);
1445*c2c66affSColin Finck nsfree(nscat);
1446*c2c66affSColin Finck return ret;
1447*c2c66affSColin Finck }
1448*c2c66affSColin Finck
get_moniker_uri(IMoniker * mon)1449*c2c66affSColin Finck static IUri *get_moniker_uri(IMoniker *mon)
1450*c2c66affSColin Finck {
1451*c2c66affSColin Finck IUriContainer *uri_container;
1452*c2c66affSColin Finck IUri *ret = NULL;
1453*c2c66affSColin Finck HRESULT hres;
1454*c2c66affSColin Finck
1455*c2c66affSColin Finck hres = IMoniker_QueryInterface(mon, &IID_IUriContainer, (void**)&uri_container);
1456*c2c66affSColin Finck if(SUCCEEDED(hres)) {
1457*c2c66affSColin Finck hres = IUriContainer_GetIUri(uri_container, &ret);
1458*c2c66affSColin Finck IUriContainer_Release(uri_container);
1459*c2c66affSColin Finck if(FAILED(hres))
1460*c2c66affSColin Finck return NULL;
1461*c2c66affSColin Finck }else {
1462*c2c66affSColin Finck FIXME("No IUriContainer\n");
1463*c2c66affSColin Finck }
1464*c2c66affSColin Finck
1465*c2c66affSColin Finck return ret;
1466*c2c66affSColin Finck }
1467*c2c66affSColin Finck
handle_extern_mime_navigation(nsChannelBSC * This)1468*c2c66affSColin Finck static void handle_extern_mime_navigation(nsChannelBSC *This)
1469*c2c66affSColin Finck {
1470*c2c66affSColin Finck IWebBrowserPriv2IE9 *webbrowser_priv;
1471*c2c66affSColin Finck IOleCommandTarget *cmdtrg;
1472*c2c66affSColin Finck HTMLDocumentObj *doc_obj;
1473*c2c66affSColin Finck IBindCtx *bind_ctx;
1474*c2c66affSColin Finck IUri *uri;
1475*c2c66affSColin Finck VARIANT flags;
1476*c2c66affSColin Finck HRESULT hres;
1477*c2c66affSColin Finck
1478*c2c66affSColin Finck if(!This->bsc.window || !This->bsc.window->base.outer_window || !This->bsc.window->base.outer_window->doc_obj)
1479*c2c66affSColin Finck return;
1480*c2c66affSColin Finck
1481*c2c66affSColin Finck doc_obj = This->bsc.window->base.outer_window->doc_obj;
1482*c2c66affSColin Finck
1483*c2c66affSColin Finck hres = IOleClientSite_QueryInterface(doc_obj->client, &IID_IOleCommandTarget, (void**)&cmdtrg);
1484*c2c66affSColin Finck if(SUCCEEDED(hres)) {
1485*c2c66affSColin Finck IOleCommandTarget_Exec(cmdtrg, &CGID_ShellDocView, 62, 0, NULL, NULL);
1486*c2c66affSColin Finck IOleCommandTarget_Release(cmdtrg);
1487*c2c66affSColin Finck }
1488*c2c66affSColin Finck
1489*c2c66affSColin Finck set_document_navigation(doc_obj, FALSE);
1490*c2c66affSColin Finck
1491*c2c66affSColin Finck if(!doc_obj->webbrowser) {
1492*c2c66affSColin Finck FIXME("unimplemented in non-webbrowser mode\n");
1493*c2c66affSColin Finck return;
1494*c2c66affSColin Finck }
1495*c2c66affSColin Finck
1496*c2c66affSColin Finck uri = get_moniker_uri(This->bsc.mon);
1497*c2c66affSColin Finck if(!uri)
1498*c2c66affSColin Finck return;
1499*c2c66affSColin Finck
1500*c2c66affSColin Finck hres = CreateBindCtx(0, &bind_ctx);
1501*c2c66affSColin Finck if(FAILED(hres)) {
1502*c2c66affSColin Finck IUri_Release(uri);
1503*c2c66affSColin Finck return;
1504*c2c66affSColin Finck }
1505*c2c66affSColin Finck
1506*c2c66affSColin Finck V_VT(&flags) = VT_I4;
1507*c2c66affSColin Finck V_I4(&flags) = navHyperlink;
1508*c2c66affSColin Finck
1509*c2c66affSColin Finck hres = IUnknown_QueryInterface(doc_obj->webbrowser, &IID_IWebBrowserPriv2IE8, (void**)&webbrowser_priv);
1510*c2c66affSColin Finck if(SUCCEEDED(hres)) {
1511*c2c66affSColin Finck hres = IWebBrowserPriv2IE9_NavigateWithBindCtx2(webbrowser_priv, uri, &flags, NULL, NULL, NULL, bind_ctx, NULL, 0);
1512*c2c66affSColin Finck IWebBrowserPriv2IE9_Release(webbrowser_priv);
1513*c2c66affSColin Finck }else {
1514*c2c66affSColin Finck IWebBrowserPriv *webbrowser_priv_old;
1515*c2c66affSColin Finck VARIANT uriv;
1516*c2c66affSColin Finck
1517*c2c66affSColin Finck hres = IUnknown_QueryInterface(doc_obj->webbrowser, &IID_IWebBrowserPriv, (void**)&webbrowser_priv_old);
1518*c2c66affSColin Finck if(SUCCEEDED(hres)) {
1519*c2c66affSColin Finck V_VT(&uriv) = VT_BSTR;
1520*c2c66affSColin Finck IUri_GetDisplayUri(uri, &V_BSTR(&uriv));
1521*c2c66affSColin Finck
1522*c2c66affSColin Finck hres = IWebBrowserPriv_NavigateWithBindCtx(webbrowser_priv_old, &uriv, &flags, NULL, NULL, NULL, bind_ctx, NULL);
1523*c2c66affSColin Finck
1524*c2c66affSColin Finck SysFreeString(V_BSTR(&uriv));
1525*c2c66affSColin Finck IWebBrowserPriv_Release(webbrowser_priv_old);
1526*c2c66affSColin Finck }
1527*c2c66affSColin Finck }
1528*c2c66affSColin Finck
1529*c2c66affSColin Finck IUri_Release(uri);
1530*c2c66affSColin Finck }
1531*c2c66affSColin Finck
nsChannelBSC_on_progress(BSCallback * bsc,ULONG status_code,LPCWSTR status_text)1532*c2c66affSColin Finck static HRESULT nsChannelBSC_on_progress(BSCallback *bsc, ULONG status_code, LPCWSTR status_text)
1533*c2c66affSColin Finck {
1534*c2c66affSColin Finck nsChannelBSC *This = nsChannelBSC_from_BSCallback(bsc);
1535*c2c66affSColin Finck
1536*c2c66affSColin Finck switch(status_code) {
1537*c2c66affSColin Finck case BINDSTATUS_MIMETYPEAVAILABLE:
1538*c2c66affSColin Finck if(This->is_doc_channel && !is_supported_doc_mime(status_text)) {
1539*c2c66affSColin Finck FIXME("External MIME: %s\n", debugstr_w(status_text));
1540*c2c66affSColin Finck
1541*c2c66affSColin Finck handle_extern_mime_navigation(This);
1542*c2c66affSColin Finck
1543*c2c66affSColin Finck This->nschannel = NULL;
1544*c2c66affSColin Finck }
1545*c2c66affSColin Finck
1546*c2c66affSColin Finck if(!This->nschannel)
1547*c2c66affSColin Finck return S_OK;
1548*c2c66affSColin Finck
1549*c2c66affSColin Finck heap_free(This->nschannel->content_type);
1550*c2c66affSColin Finck This->nschannel->content_type = heap_strdupWtoA(status_text);
1551*c2c66affSColin Finck break;
1552*c2c66affSColin Finck case BINDSTATUS_REDIRECTING:
1553*c2c66affSColin Finck return handle_redirect(This, status_text);
1554*c2c66affSColin Finck case BINDSTATUS_BEGINDOWNLOADDATA: {
1555*c2c66affSColin Finck IWinInetHttpInfo *http_info;
1556*c2c66affSColin Finck DWORD status, size = sizeof(DWORD);
1557*c2c66affSColin Finck HRESULT hres;
1558*c2c66affSColin Finck
1559*c2c66affSColin Finck if(!This->bsc.binding)
1560*c2c66affSColin Finck break;
1561*c2c66affSColin Finck
1562*c2c66affSColin Finck hres = IBinding_QueryInterface(This->bsc.binding, &IID_IWinInetHttpInfo, (void**)&http_info);
1563*c2c66affSColin Finck if(FAILED(hres))
1564*c2c66affSColin Finck break;
1565*c2c66affSColin Finck
1566*c2c66affSColin Finck hres = IWinInetHttpInfo_QueryInfo(http_info,
1567*c2c66affSColin Finck HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL, NULL);
1568*c2c66affSColin Finck IWinInetHttpInfo_Release(http_info);
1569*c2c66affSColin Finck if(FAILED(hres) || status == HTTP_STATUS_OK)
1570*c2c66affSColin Finck break;
1571*c2c66affSColin Finck
1572*c2c66affSColin Finck handle_navigation_error(This, status);
1573*c2c66affSColin Finck }
1574*c2c66affSColin Finck }
1575*c2c66affSColin Finck
1576*c2c66affSColin Finck return S_OK;
1577*c2c66affSColin Finck }
1578*c2c66affSColin Finck
process_response_status_text(const WCHAR * header,const WCHAR * header_end,char ** status_text)1579*c2c66affSColin Finck static HRESULT process_response_status_text(const WCHAR *header, const WCHAR *header_end, char **status_text)
1580*c2c66affSColin Finck {
1581*c2c66affSColin Finck header = strchrW(header + 1, ' ');
1582*c2c66affSColin Finck if(!header || header >= header_end)
1583*c2c66affSColin Finck return E_FAIL;
1584*c2c66affSColin Finck header = strchrW(header + 1, ' ');
1585*c2c66affSColin Finck if(!header || header >= header_end)
1586*c2c66affSColin Finck return E_FAIL;
1587*c2c66affSColin Finck ++header;
1588*c2c66affSColin Finck
1589*c2c66affSColin Finck *status_text = heap_strndupWtoU(header, header_end - header);
1590*c2c66affSColin Finck
1591*c2c66affSColin Finck if(!*status_text)
1592*c2c66affSColin Finck return E_OUTOFMEMORY;
1593*c2c66affSColin Finck
1594*c2c66affSColin Finck return S_OK;
1595*c2c66affSColin Finck }
1596*c2c66affSColin Finck
nsChannelBSC_on_response(BSCallback * bsc,DWORD response_code,LPCWSTR response_headers)1597*c2c66affSColin Finck static HRESULT nsChannelBSC_on_response(BSCallback *bsc, DWORD response_code,
1598*c2c66affSColin Finck LPCWSTR response_headers)
1599*c2c66affSColin Finck {
1600*c2c66affSColin Finck nsChannelBSC *This = nsChannelBSC_from_BSCallback(bsc);
1601*c2c66affSColin Finck char *str;
1602*c2c66affSColin Finck HRESULT hres;
1603*c2c66affSColin Finck
1604*c2c66affSColin Finck This->response_processed = TRUE;
1605*c2c66affSColin Finck This->nschannel->response_status = response_code;
1606*c2c66affSColin Finck
1607*c2c66affSColin Finck if(response_headers) {
1608*c2c66affSColin Finck const WCHAR *headers;
1609*c2c66affSColin Finck
1610*c2c66affSColin Finck headers = strchrW(response_headers, '\r');
1611*c2c66affSColin Finck hres = process_response_status_text(response_headers, headers, &str);
1612*c2c66affSColin Finck if(FAILED(hres)) {
1613*c2c66affSColin Finck WARN("parsing headers failed: %08x\n", hres);
1614*c2c66affSColin Finck return hres;
1615*c2c66affSColin Finck }
1616*c2c66affSColin Finck
1617*c2c66affSColin Finck heap_free(This->nschannel->response_status_text);
1618*c2c66affSColin Finck This->nschannel->response_status_text = str;
1619*c2c66affSColin Finck
1620*c2c66affSColin Finck if(headers && headers[1] == '\n') {
1621*c2c66affSColin Finck headers += 2;
1622*c2c66affSColin Finck hres = process_response_headers(This, headers);
1623*c2c66affSColin Finck if(FAILED(hres)) {
1624*c2c66affSColin Finck WARN("parsing headers failed: %08x\n", hres);
1625*c2c66affSColin Finck return hres;
1626*c2c66affSColin Finck }
1627*c2c66affSColin Finck }
1628*c2c66affSColin Finck }
1629*c2c66affSColin Finck
1630*c2c66affSColin Finck return S_OK;
1631*c2c66affSColin Finck }
1632*c2c66affSColin Finck
nsChannelBSC_beginning_transaction(BSCallback * bsc,WCHAR ** additional_headers)1633*c2c66affSColin Finck static HRESULT nsChannelBSC_beginning_transaction(BSCallback *bsc, WCHAR **additional_headers)
1634*c2c66affSColin Finck {
1635*c2c66affSColin Finck nsChannelBSC *This = nsChannelBSC_from_BSCallback(bsc);
1636*c2c66affSColin Finck http_header_t *iter;
1637*c2c66affSColin Finck DWORD len = 0;
1638*c2c66affSColin Finck WCHAR *ptr;
1639*c2c66affSColin Finck
1640*c2c66affSColin Finck static const WCHAR content_lengthW[] =
1641*c2c66affSColin Finck {'C','o','n','t','e','n','t','-','L','e','n','g','t','h',0};
1642*c2c66affSColin Finck
1643*c2c66affSColin Finck if(!This->nschannel)
1644*c2c66affSColin Finck return S_FALSE;
1645*c2c66affSColin Finck
1646*c2c66affSColin Finck LIST_FOR_EACH_ENTRY(iter, &This->nschannel->request_headers, http_header_t, entry) {
1647*c2c66affSColin Finck if(strcmpW(iter->header, content_lengthW))
1648*c2c66affSColin Finck len += strlenW(iter->header) + 2 /* ": " */ + strlenW(iter->data) + 2 /* "\r\n" */;
1649*c2c66affSColin Finck }
1650*c2c66affSColin Finck
1651*c2c66affSColin Finck if(!len)
1652*c2c66affSColin Finck return S_OK;
1653*c2c66affSColin Finck
1654*c2c66affSColin Finck *additional_headers = ptr = CoTaskMemAlloc((len+1)*sizeof(WCHAR));
1655*c2c66affSColin Finck if(!ptr)
1656*c2c66affSColin Finck return E_OUTOFMEMORY;
1657*c2c66affSColin Finck
1658*c2c66affSColin Finck LIST_FOR_EACH_ENTRY(iter, &This->nschannel->request_headers, http_header_t, entry) {
1659*c2c66affSColin Finck if(!strcmpW(iter->header, content_lengthW))
1660*c2c66affSColin Finck continue;
1661*c2c66affSColin Finck
1662*c2c66affSColin Finck len = strlenW(iter->header);
1663*c2c66affSColin Finck memcpy(ptr, iter->header, len*sizeof(WCHAR));
1664*c2c66affSColin Finck ptr += len;
1665*c2c66affSColin Finck
1666*c2c66affSColin Finck *ptr++ = ':';
1667*c2c66affSColin Finck *ptr++ = ' ';
1668*c2c66affSColin Finck
1669*c2c66affSColin Finck len = strlenW(iter->data);
1670*c2c66affSColin Finck memcpy(ptr, iter->data, len*sizeof(WCHAR));
1671*c2c66affSColin Finck ptr += len;
1672*c2c66affSColin Finck
1673*c2c66affSColin Finck *ptr++ = '\r';
1674*c2c66affSColin Finck *ptr++ = '\n';
1675*c2c66affSColin Finck }
1676*c2c66affSColin Finck
1677*c2c66affSColin Finck *ptr = 0;
1678*c2c66affSColin Finck
1679*c2c66affSColin Finck return S_OK;
1680*c2c66affSColin Finck }
1681*c2c66affSColin Finck
1682*c2c66affSColin Finck static const BSCallbackVtbl nsChannelBSCVtbl = {
1683*c2c66affSColin Finck nsChannelBSC_destroy,
1684*c2c66affSColin Finck nsChannelBSC_init_bindinfo,
1685*c2c66affSColin Finck nsChannelBSC_start_binding,
1686*c2c66affSColin Finck nsChannelBSC_stop_binding,
1687*c2c66affSColin Finck nsChannelBSC_read_data,
1688*c2c66affSColin Finck nsChannelBSC_on_progress,
1689*c2c66affSColin Finck nsChannelBSC_on_response,
1690*c2c66affSColin Finck nsChannelBSC_beginning_transaction
1691*c2c66affSColin Finck };
1692*c2c66affSColin Finck
create_channelbsc(IMoniker * mon,const WCHAR * headers,BYTE * post_data,DWORD post_data_size,BOOL is_doc_binding,nsChannelBSC ** retval)1693*c2c66affSColin Finck HRESULT create_channelbsc(IMoniker *mon, const WCHAR *headers, BYTE *post_data, DWORD post_data_size,
1694*c2c66affSColin Finck BOOL is_doc_binding, nsChannelBSC **retval)
1695*c2c66affSColin Finck {
1696*c2c66affSColin Finck nsChannelBSC *ret;
1697*c2c66affSColin Finck DWORD bindf;
1698*c2c66affSColin Finck
1699*c2c66affSColin Finck ret = heap_alloc_zero(sizeof(*ret));
1700*c2c66affSColin Finck if(!ret)
1701*c2c66affSColin Finck return E_OUTOFMEMORY;
1702*c2c66affSColin Finck
1703*c2c66affSColin Finck bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
1704*c2c66affSColin Finck if(post_data_size)
1705*c2c66affSColin Finck bindf |= BINDF_FORMS_SUBMIT | BINDF_PRAGMA_NO_CACHE | BINDF_HYPERLINK | BINDF_GETNEWESTVERSION;
1706*c2c66affSColin Finck
1707*c2c66affSColin Finck init_bscallback(&ret->bsc, &nsChannelBSCVtbl, mon, bindf);
1708*c2c66affSColin Finck ret->is_doc_channel = is_doc_binding;
1709*c2c66affSColin Finck
1710*c2c66affSColin Finck if(headers) {
1711*c2c66affSColin Finck ret->bsc.request_data.headers = heap_strdupW(headers);
1712*c2c66affSColin Finck if(!ret->bsc.request_data.headers) {
1713*c2c66affSColin Finck IBindStatusCallback_Release(&ret->bsc.IBindStatusCallback_iface);
1714*c2c66affSColin Finck return E_OUTOFMEMORY;
1715*c2c66affSColin Finck }
1716*c2c66affSColin Finck }
1717*c2c66affSColin Finck
1718*c2c66affSColin Finck if(post_data) {
1719*c2c66affSColin Finck ret->bsc.request_data.post_data = GlobalAlloc(0, post_data_size+1);
1720*c2c66affSColin Finck if(!ret->bsc.request_data.post_data) {
1721*c2c66affSColin Finck release_request_data(&ret->bsc.request_data);
1722*c2c66affSColin Finck IBindStatusCallback_Release(&ret->bsc.IBindStatusCallback_iface);
1723*c2c66affSColin Finck return E_OUTOFMEMORY;
1724*c2c66affSColin Finck }
1725*c2c66affSColin Finck
1726*c2c66affSColin Finck memcpy(ret->bsc.request_data.post_data, post_data, post_data_size);
1727*c2c66affSColin Finck ((BYTE*)ret->bsc.request_data.post_data)[post_data_size] = 0;
1728*c2c66affSColin Finck ret->bsc.request_data.post_data_len = post_data_size;
1729*c2c66affSColin Finck }
1730*c2c66affSColin Finck
1731*c2c66affSColin Finck TRACE("created %p\n", ret);
1732*c2c66affSColin Finck *retval = ret;
1733*c2c66affSColin Finck return S_OK;
1734*c2c66affSColin Finck }
1735*c2c66affSColin Finck
1736*c2c66affSColin Finck typedef struct {
1737*c2c66affSColin Finck task_t header;
1738*c2c66affSColin Finck HTMLOuterWindow *window;
1739*c2c66affSColin Finck HTMLInnerWindow *pending_window;
1740*c2c66affSColin Finck } start_doc_binding_task_t;
1741*c2c66affSColin Finck
start_doc_binding_proc(task_t * _task)1742*c2c66affSColin Finck static void start_doc_binding_proc(task_t *_task)
1743*c2c66affSColin Finck {
1744*c2c66affSColin Finck start_doc_binding_task_t *task = (start_doc_binding_task_t*)_task;
1745*c2c66affSColin Finck
1746*c2c66affSColin Finck set_current_mon(task->window, task->pending_window->bscallback->bsc.mon, BINDING_NAVIGATED);
1747*c2c66affSColin Finck start_binding(task->pending_window, &task->pending_window->bscallback->bsc, NULL);
1748*c2c66affSColin Finck }
1749*c2c66affSColin Finck
start_doc_binding_task_destr(task_t * _task)1750*c2c66affSColin Finck static void start_doc_binding_task_destr(task_t *_task)
1751*c2c66affSColin Finck {
1752*c2c66affSColin Finck start_doc_binding_task_t *task = (start_doc_binding_task_t*)_task;
1753*c2c66affSColin Finck
1754*c2c66affSColin Finck IHTMLWindow2_Release(&task->pending_window->base.IHTMLWindow2_iface);
1755*c2c66affSColin Finck heap_free(task);
1756*c2c66affSColin Finck }
1757*c2c66affSColin Finck
async_start_doc_binding(HTMLOuterWindow * window,HTMLInnerWindow * pending_window)1758*c2c66affSColin Finck HRESULT async_start_doc_binding(HTMLOuterWindow *window, HTMLInnerWindow *pending_window)
1759*c2c66affSColin Finck {
1760*c2c66affSColin Finck start_doc_binding_task_t *task;
1761*c2c66affSColin Finck
1762*c2c66affSColin Finck TRACE("%p\n", pending_window);
1763*c2c66affSColin Finck
1764*c2c66affSColin Finck task = heap_alloc(sizeof(start_doc_binding_task_t));
1765*c2c66affSColin Finck if(!task)
1766*c2c66affSColin Finck return E_OUTOFMEMORY;
1767*c2c66affSColin Finck
1768*c2c66affSColin Finck task->window = window;
1769*c2c66affSColin Finck task->pending_window = pending_window;
1770*c2c66affSColin Finck IHTMLWindow2_AddRef(&pending_window->base.IHTMLWindow2_iface);
1771*c2c66affSColin Finck
1772*c2c66affSColin Finck return push_task(&task->header, start_doc_binding_proc, start_doc_binding_task_destr, pending_window->task_magic);
1773*c2c66affSColin Finck }
1774*c2c66affSColin Finck
abort_window_bindings(HTMLInnerWindow * window)1775*c2c66affSColin Finck void abort_window_bindings(HTMLInnerWindow *window)
1776*c2c66affSColin Finck {
1777*c2c66affSColin Finck BSCallback *iter;
1778*c2c66affSColin Finck
1779*c2c66affSColin Finck remove_target_tasks(window->task_magic);
1780*c2c66affSColin Finck
1781*c2c66affSColin Finck while(!list_empty(&window->bindings)) {
1782*c2c66affSColin Finck iter = LIST_ENTRY(window->bindings.next, BSCallback, entry);
1783*c2c66affSColin Finck
1784*c2c66affSColin Finck TRACE("Aborting %p\n", iter);
1785*c2c66affSColin Finck
1786*c2c66affSColin Finck IBindStatusCallback_AddRef(&iter->IBindStatusCallback_iface);
1787*c2c66affSColin Finck
1788*c2c66affSColin Finck if(iter->binding)
1789*c2c66affSColin Finck IBinding_Abort(iter->binding);
1790*c2c66affSColin Finck else
1791*c2c66affSColin Finck iter->vtbl->stop_binding(iter, E_ABORT);
1792*c2c66affSColin Finck
1793*c2c66affSColin Finck iter->window = NULL;
1794*c2c66affSColin Finck list_remove(&iter->entry);
1795*c2c66affSColin Finck list_init(&iter->entry);
1796*c2c66affSColin Finck
1797*c2c66affSColin Finck IBindStatusCallback_Release(&iter->IBindStatusCallback_iface);
1798*c2c66affSColin Finck }
1799*c2c66affSColin Finck
1800*c2c66affSColin Finck if(window->bscallback) {
1801*c2c66affSColin Finck IBindStatusCallback_Release(&window->bscallback->bsc.IBindStatusCallback_iface);
1802*c2c66affSColin Finck window->bscallback = NULL;
1803*c2c66affSColin Finck }
1804*c2c66affSColin Finck
1805*c2c66affSColin Finck if(window->mon) {
1806*c2c66affSColin Finck IMoniker_Release(window->mon);
1807*c2c66affSColin Finck window->mon = NULL;
1808*c2c66affSColin Finck }
1809*c2c66affSColin Finck }
1810*c2c66affSColin Finck
channelbsc_load_stream(HTMLInnerWindow * pending_window,IMoniker * mon,IStream * stream)1811*c2c66affSColin Finck HRESULT channelbsc_load_stream(HTMLInnerWindow *pending_window, IMoniker *mon, IStream *stream)
1812*c2c66affSColin Finck {
1813*c2c66affSColin Finck nsChannelBSC *bscallback = pending_window->bscallback;
1814*c2c66affSColin Finck HRESULT hres = S_OK;
1815*c2c66affSColin Finck
1816*c2c66affSColin Finck if(!bscallback->nschannel) {
1817*c2c66affSColin Finck ERR("NULL nschannel\n");
1818*c2c66affSColin Finck return E_FAIL;
1819*c2c66affSColin Finck }
1820*c2c66affSColin Finck
1821*c2c66affSColin Finck bscallback->nschannel->content_type = heap_strdupA("text/html");
1822*c2c66affSColin Finck if(!bscallback->nschannel->content_type)
1823*c2c66affSColin Finck return E_OUTOFMEMORY;
1824*c2c66affSColin Finck
1825*c2c66affSColin Finck set_current_mon(pending_window->base.outer_window, mon, 0);
1826*c2c66affSColin Finck
1827*c2c66affSColin Finck bscallback->bsc.window = pending_window;
1828*c2c66affSColin Finck if(stream)
1829*c2c66affSColin Finck hres = read_stream_data(bscallback, stream);
1830*c2c66affSColin Finck if(SUCCEEDED(hres))
1831*c2c66affSColin Finck hres = async_stop_request(bscallback);
1832*c2c66affSColin Finck if(FAILED(hres))
1833*c2c66affSColin Finck IBindStatusCallback_OnStopBinding(&bscallback->bsc.IBindStatusCallback_iface, hres,
1834*c2c66affSColin Finck ERROR_SUCCESS);
1835*c2c66affSColin Finck
1836*c2c66affSColin Finck return hres;
1837*c2c66affSColin Finck }
1838*c2c66affSColin Finck
channelbsc_set_channel(nsChannelBSC * This,nsChannel * channel,nsIStreamListener * listener,nsISupports * context)1839*c2c66affSColin Finck void channelbsc_set_channel(nsChannelBSC *This, nsChannel *channel, nsIStreamListener *listener, nsISupports *context)
1840*c2c66affSColin Finck {
1841*c2c66affSColin Finck nsIHttpChannel_AddRef(&channel->nsIHttpChannel_iface);
1842*c2c66affSColin Finck This->nschannel = channel;
1843*c2c66affSColin Finck
1844*c2c66affSColin Finck nsIStreamListener_AddRef(listener);
1845*c2c66affSColin Finck This->nslistener = listener;
1846*c2c66affSColin Finck
1847*c2c66affSColin Finck if(context) {
1848*c2c66affSColin Finck nsISupports_AddRef(context);
1849*c2c66affSColin Finck This->nscontext = context;
1850*c2c66affSColin Finck }
1851*c2c66affSColin Finck
1852*c2c66affSColin Finck if(This->bsc.request_data.headers) {
1853*c2c66affSColin Finck HRESULT hres;
1854*c2c66affSColin Finck
1855*c2c66affSColin Finck hres = parse_headers(This->bsc.request_data.headers, &channel->request_headers);
1856*c2c66affSColin Finck heap_free(This->bsc.request_data.headers);
1857*c2c66affSColin Finck This->bsc.request_data.headers = NULL;
1858*c2c66affSColin Finck if(FAILED(hres))
1859*c2c66affSColin Finck WARN("parse_headers failed: %08x\n", hres);
1860*c2c66affSColin Finck }
1861*c2c66affSColin Finck }
1862*c2c66affSColin Finck
1863*c2c66affSColin Finck typedef struct {
1864*c2c66affSColin Finck task_t header;
1865*c2c66affSColin Finck HTMLOuterWindow *window;
1866*c2c66affSColin Finck IUri *uri;
1867*c2c66affSColin Finck } navigate_javascript_task_t;
1868*c2c66affSColin Finck
navigate_javascript_proc(task_t * _task)1869*c2c66affSColin Finck static void navigate_javascript_proc(task_t *_task)
1870*c2c66affSColin Finck {
1871*c2c66affSColin Finck navigate_javascript_task_t *task = (navigate_javascript_task_t*)_task;
1872*c2c66affSColin Finck HTMLOuterWindow *window = task->window;
1873*c2c66affSColin Finck VARIANT v;
1874*c2c66affSColin Finck BSTR code;
1875*c2c66affSColin Finck HRESULT hres;
1876*c2c66affSColin Finck
1877*c2c66affSColin Finck static const WCHAR jscriptW[] = {'j','s','c','r','i','p','t',0};
1878*c2c66affSColin Finck
1879*c2c66affSColin Finck task->window->readystate = READYSTATE_COMPLETE;
1880*c2c66affSColin Finck
1881*c2c66affSColin Finck hres = IUri_GetPath(task->uri, &code);
1882*c2c66affSColin Finck if(FAILED(hres))
1883*c2c66affSColin Finck return;
1884*c2c66affSColin Finck
1885*c2c66affSColin Finck hres = UrlUnescapeW(code, NULL, NULL, URL_UNESCAPE_INPLACE);
1886*c2c66affSColin Finck if(FAILED(hres)) {
1887*c2c66affSColin Finck SysFreeString(code);
1888*c2c66affSColin Finck return;
1889*c2c66affSColin Finck }
1890*c2c66affSColin Finck
1891*c2c66affSColin Finck set_download_state(window->doc_obj, 1);
1892*c2c66affSColin Finck
1893*c2c66affSColin Finck V_VT(&v) = VT_EMPTY;
1894*c2c66affSColin Finck hres = exec_script(window->base.inner_window, code, jscriptW, &v);
1895*c2c66affSColin Finck SysFreeString(code);
1896*c2c66affSColin Finck if(SUCCEEDED(hres) && V_VT(&v) != VT_EMPTY) {
1897*c2c66affSColin Finck FIXME("javascirpt URL returned %s\n", debugstr_variant(&v));
1898*c2c66affSColin Finck VariantClear(&v);
1899*c2c66affSColin Finck }
1900*c2c66affSColin Finck
1901*c2c66affSColin Finck if(window->doc_obj->view_sink)
1902*c2c66affSColin Finck IAdviseSink_OnViewChange(window->doc_obj->view_sink, DVASPECT_CONTENT, -1);
1903*c2c66affSColin Finck
1904*c2c66affSColin Finck set_download_state(window->doc_obj, 0);
1905*c2c66affSColin Finck }
1906*c2c66affSColin Finck
navigate_javascript_task_destr(task_t * _task)1907*c2c66affSColin Finck static void navigate_javascript_task_destr(task_t *_task)
1908*c2c66affSColin Finck {
1909*c2c66affSColin Finck navigate_javascript_task_t *task = (navigate_javascript_task_t*)_task;
1910*c2c66affSColin Finck
1911*c2c66affSColin Finck IUri_Release(task->uri);
1912*c2c66affSColin Finck heap_free(task);
1913*c2c66affSColin Finck }
1914*c2c66affSColin Finck
1915*c2c66affSColin Finck typedef struct {
1916*c2c66affSColin Finck task_t header;
1917*c2c66affSColin Finck HTMLOuterWindow *window;
1918*c2c66affSColin Finck nsChannelBSC *bscallback;
1919*c2c66affSColin Finck DWORD flags;
1920*c2c66affSColin Finck IMoniker *mon;
1921*c2c66affSColin Finck IUri *uri;
1922*c2c66affSColin Finck } navigate_task_t;
1923*c2c66affSColin Finck
navigate_proc(task_t * _task)1924*c2c66affSColin Finck static void navigate_proc(task_t *_task)
1925*c2c66affSColin Finck {
1926*c2c66affSColin Finck navigate_task_t *task = (navigate_task_t*)_task;
1927*c2c66affSColin Finck HRESULT hres;
1928*c2c66affSColin Finck
1929*c2c66affSColin Finck hres = set_moniker(task->window, task->mon, task->uri, NULL, task->bscallback, TRUE);
1930*c2c66affSColin Finck if(SUCCEEDED(hres)) {
1931*c2c66affSColin Finck set_current_mon(task->window, task->bscallback->bsc.mon, task->flags);
1932*c2c66affSColin Finck set_current_uri(task->window, task->uri);
1933*c2c66affSColin Finck start_binding(task->window->pending_window, &task->bscallback->bsc, NULL);
1934*c2c66affSColin Finck }
1935*c2c66affSColin Finck }
1936*c2c66affSColin Finck
navigate_task_destr(task_t * _task)1937*c2c66affSColin Finck static void navigate_task_destr(task_t *_task)
1938*c2c66affSColin Finck {
1939*c2c66affSColin Finck navigate_task_t *task = (navigate_task_t*)_task;
1940*c2c66affSColin Finck
1941*c2c66affSColin Finck IBindStatusCallback_Release(&task->bscallback->bsc.IBindStatusCallback_iface);
1942*c2c66affSColin Finck IMoniker_Release(task->mon);
1943*c2c66affSColin Finck IUri_Release(task->uri);
1944*c2c66affSColin Finck heap_free(task);
1945*c2c66affSColin Finck }
1946*c2c66affSColin Finck
navigate_fragment(HTMLOuterWindow * window,IUri * uri)1947*c2c66affSColin Finck static HRESULT navigate_fragment(HTMLOuterWindow *window, IUri *uri)
1948*c2c66affSColin Finck {
1949*c2c66affSColin Finck nsIDOMLocation *nslocation;
1950*c2c66affSColin Finck nsAString nsfrag_str;
1951*c2c66affSColin Finck WCHAR *selector;
1952*c2c66affSColin Finck BSTR frag;
1953*c2c66affSColin Finck nsresult nsres;
1954*c2c66affSColin Finck HRESULT hres;
1955*c2c66affSColin Finck
1956*c2c66affSColin Finck const WCHAR selector_formatW[] = {'a','[','i','d','=','"','%','s','"',']',0};
1957*c2c66affSColin Finck
1958*c2c66affSColin Finck set_current_uri(window, uri);
1959*c2c66affSColin Finck
1960*c2c66affSColin Finck nsres = nsIDOMWindow_GetLocation(window->nswindow, &nslocation);
1961*c2c66affSColin Finck if(FAILED(nsres) || !nslocation)
1962*c2c66affSColin Finck return E_FAIL;
1963*c2c66affSColin Finck
1964*c2c66affSColin Finck hres = IUri_GetFragment(uri, &frag);
1965*c2c66affSColin Finck if(FAILED(hres)) {
1966*c2c66affSColin Finck nsIDOMLocation_Release(nslocation);
1967*c2c66affSColin Finck return hres;
1968*c2c66affSColin Finck }
1969*c2c66affSColin Finck
1970*c2c66affSColin Finck nsAString_InitDepend(&nsfrag_str, frag);
1971*c2c66affSColin Finck nsres = nsIDOMLocation_SetHash(nslocation, &nsfrag_str);
1972*c2c66affSColin Finck nsAString_Finish(&nsfrag_str);
1973*c2c66affSColin Finck nsIDOMLocation_Release(nslocation);
1974*c2c66affSColin Finck if(NS_FAILED(nsres))
1975*c2c66affSColin Finck ERR("SetHash failed: %08x\n", nsres);
1976*c2c66affSColin Finck
1977*c2c66affSColin Finck /*
1978*c2c66affSColin Finck * IE supports scrolling to anchor elements with "#hash" ids (note that '#' is part of the id),
1979*c2c66affSColin Finck * while Gecko scrolls only to elements with "hash" ids. We scroll the page ourselves if
1980*c2c66affSColin Finck * a[id="#hash"] element can be found.
1981*c2c66affSColin Finck */
1982*c2c66affSColin Finck selector = heap_alloc(sizeof(selector_formatW)+SysStringLen(frag)*sizeof(WCHAR));
1983*c2c66affSColin Finck if(selector) {
1984*c2c66affSColin Finck nsIDOMElement *nselem = NULL;
1985*c2c66affSColin Finck nsAString selector_str;
1986*c2c66affSColin Finck
1987*c2c66affSColin Finck sprintfW(selector, selector_formatW, frag);
1988*c2c66affSColin Finck nsAString_InitDepend(&selector_str, selector);
1989*c2c66affSColin Finck /* NOTE: Gecko doesn't set result to NULL if there is no match, so nselem must be initialized */
1990*c2c66affSColin Finck nsres = nsIDOMHTMLDocument_QuerySelector(window->base.inner_window->doc->nsdoc, &selector_str, &nselem);
1991*c2c66affSColin Finck nsAString_Finish(&selector_str);
1992*c2c66affSColin Finck heap_free(selector);
1993*c2c66affSColin Finck if(NS_SUCCEEDED(nsres) && nselem) {
1994*c2c66affSColin Finck nsIDOMHTMLElement *html_elem;
1995*c2c66affSColin Finck
1996*c2c66affSColin Finck nsres = nsIDOMElement_QueryInterface(nselem, &IID_nsIDOMHTMLElement, (void**)&html_elem);
1997*c2c66affSColin Finck nsIDOMElement_Release(nselem);
1998*c2c66affSColin Finck if(NS_SUCCEEDED(nsres)) {
1999*c2c66affSColin Finck nsIDOMHTMLElement_ScrollIntoView(html_elem, TRUE, 1);
2000*c2c66affSColin Finck nsIDOMHTMLElement_Release(html_elem);
2001*c2c66affSColin Finck }
2002*c2c66affSColin Finck }
2003*c2c66affSColin Finck }
2004*c2c66affSColin Finck
2005*c2c66affSColin Finck SysFreeString(frag);
2006*c2c66affSColin Finck
2007*c2c66affSColin Finck if(window->doc_obj->doc_object_service) {
2008*c2c66affSColin Finck IDocObjectService_FireNavigateComplete2(window->doc_obj->doc_object_service, &window->base.IHTMLWindow2_iface, 0x10);
2009*c2c66affSColin Finck IDocObjectService_FireDocumentComplete(window->doc_obj->doc_object_service, &window->base.IHTMLWindow2_iface, 0);
2010*c2c66affSColin Finck
2011*c2c66affSColin Finck }
2012*c2c66affSColin Finck
2013*c2c66affSColin Finck return S_OK;
2014*c2c66affSColin Finck }
2015*c2c66affSColin Finck
super_navigate(HTMLOuterWindow * window,IUri * uri,DWORD flags,const WCHAR * headers,BYTE * post_data,DWORD post_data_size)2016*c2c66affSColin Finck HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, DWORD flags, const WCHAR *headers, BYTE *post_data, DWORD post_data_size)
2017*c2c66affSColin Finck {
2018*c2c66affSColin Finck nsChannelBSC *bsc;
2019*c2c66affSColin Finck IUri *uri_nofrag;
2020*c2c66affSColin Finck IMoniker *mon;
2021*c2c66affSColin Finck DWORD scheme;
2022*c2c66affSColin Finck HRESULT hres;
2023*c2c66affSColin Finck
2024*c2c66affSColin Finck uri_nofrag = get_uri_nofrag(uri);
2025*c2c66affSColin Finck if(!uri_nofrag)
2026*c2c66affSColin Finck return E_FAIL;
2027*c2c66affSColin Finck
2028*c2c66affSColin Finck if(window->doc_obj->client && !(flags & BINDING_REFRESH)) {
2029*c2c66affSColin Finck IOleCommandTarget *cmdtrg;
2030*c2c66affSColin Finck
2031*c2c66affSColin Finck hres = IOleClientSite_QueryInterface(window->doc_obj->client, &IID_IOleCommandTarget, (void**)&cmdtrg);
2032*c2c66affSColin Finck if(SUCCEEDED(hres)) {
2033*c2c66affSColin Finck VARIANT in, out;
2034*c2c66affSColin Finck BSTR url_str;
2035*c2c66affSColin Finck
2036*c2c66affSColin Finck hres = IUri_GetDisplayUri(uri_nofrag, &url_str);
2037*c2c66affSColin Finck if(SUCCEEDED(hres)) {
2038*c2c66affSColin Finck V_VT(&in) = VT_BSTR;
2039*c2c66affSColin Finck V_BSTR(&in) = url_str;
2040*c2c66affSColin Finck V_VT(&out) = VT_BOOL;
2041*c2c66affSColin Finck V_BOOL(&out) = VARIANT_TRUE;
2042*c2c66affSColin Finck hres = IOleCommandTarget_Exec(cmdtrg, &CGID_ShellDocView, 67, 0, &in, &out);
2043*c2c66affSColin Finck IOleCommandTarget_Release(cmdtrg);
2044*c2c66affSColin Finck if(SUCCEEDED(hres))
2045*c2c66affSColin Finck VariantClear(&out);
2046*c2c66affSColin Finck SysFreeString(url_str);
2047*c2c66affSColin Finck }
2048*c2c66affSColin Finck }
2049*c2c66affSColin Finck }
2050*c2c66affSColin Finck
2051*c2c66affSColin Finck if(!(flags & BINDING_NOFRAG) && window->uri_nofrag && !post_data_size) {
2052*c2c66affSColin Finck BOOL eq;
2053*c2c66affSColin Finck
2054*c2c66affSColin Finck hres = IUri_IsEqual(uri_nofrag, window->uri_nofrag, &eq);
2055*c2c66affSColin Finck if(SUCCEEDED(hres) && eq) {
2056*c2c66affSColin Finck IUri_Release(uri_nofrag);
2057*c2c66affSColin Finck TRACE("fragment navigate\n");
2058*c2c66affSColin Finck return navigate_fragment(window, uri);
2059*c2c66affSColin Finck }
2060*c2c66affSColin Finck }
2061*c2c66affSColin Finck
2062*c2c66affSColin Finck hres = CreateURLMonikerEx2(NULL, uri_nofrag, &mon, URL_MK_UNIFORM);
2063*c2c66affSColin Finck IUri_Release(uri_nofrag);
2064*c2c66affSColin Finck if(FAILED(hres))
2065*c2c66affSColin Finck return hres;
2066*c2c66affSColin Finck
2067*c2c66affSColin Finck /* FIXME: Why not set_ready_state? */
2068*c2c66affSColin Finck window->readystate = READYSTATE_UNINITIALIZED;
2069*c2c66affSColin Finck
2070*c2c66affSColin Finck hres = create_channelbsc(mon, headers, post_data, post_data_size, TRUE, &bsc);
2071*c2c66affSColin Finck if(FAILED(hres)) {
2072*c2c66affSColin Finck IMoniker_Release(mon);
2073*c2c66affSColin Finck return hres;
2074*c2c66affSColin Finck }
2075*c2c66affSColin Finck
2076*c2c66affSColin Finck prepare_for_binding(&window->doc_obj->basedoc, mon, flags);
2077*c2c66affSColin Finck
2078*c2c66affSColin Finck hres = IUri_GetScheme(uri, &scheme);
2079*c2c66affSColin Finck if(SUCCEEDED(hres) && scheme == URL_SCHEME_JAVASCRIPT) {
2080*c2c66affSColin Finck navigate_javascript_task_t *task;
2081*c2c66affSColin Finck
2082*c2c66affSColin Finck IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface);
2083*c2c66affSColin Finck IMoniker_Release(mon);
2084*c2c66affSColin Finck
2085*c2c66affSColin Finck task = heap_alloc(sizeof(*task));
2086*c2c66affSColin Finck if(!task)
2087*c2c66affSColin Finck return E_OUTOFMEMORY;
2088*c2c66affSColin Finck
2089*c2c66affSColin Finck /* Why silently? */
2090*c2c66affSColin Finck window->readystate = READYSTATE_COMPLETE;
2091*c2c66affSColin Finck if(!(flags & BINDING_FROMHIST))
2092*c2c66affSColin Finck call_docview_84(window->doc_obj);
2093*c2c66affSColin Finck
2094*c2c66affSColin Finck IUri_AddRef(uri);
2095*c2c66affSColin Finck task->window = window;
2096*c2c66affSColin Finck task->uri = uri;
2097*c2c66affSColin Finck hres = push_task(&task->header, navigate_javascript_proc, navigate_javascript_task_destr, window->task_magic);
2098*c2c66affSColin Finck }else if(flags & BINDING_SUBMIT) {
2099*c2c66affSColin Finck hres = set_moniker(window, mon, uri, NULL, bsc, TRUE);
2100*c2c66affSColin Finck if(SUCCEEDED(hres))
2101*c2c66affSColin Finck hres = start_binding(window->pending_window, &bsc->bsc, NULL);
2102*c2c66affSColin Finck IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface);
2103*c2c66affSColin Finck IMoniker_Release(mon);
2104*c2c66affSColin Finck }else {
2105*c2c66affSColin Finck navigate_task_t *task;
2106*c2c66affSColin Finck
2107*c2c66affSColin Finck task = heap_alloc(sizeof(*task));
2108*c2c66affSColin Finck if(!task) {
2109*c2c66affSColin Finck IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface);
2110*c2c66affSColin Finck IMoniker_Release(mon);
2111*c2c66affSColin Finck return E_OUTOFMEMORY;
2112*c2c66affSColin Finck }
2113*c2c66affSColin Finck
2114*c2c66affSColin Finck /* Silently and repeated when real loading starts? */
2115*c2c66affSColin Finck window->readystate = READYSTATE_LOADING;
2116*c2c66affSColin Finck if(!(flags & (BINDING_FROMHIST|BINDING_REFRESH)))
2117*c2c66affSColin Finck call_docview_84(window->doc_obj);
2118*c2c66affSColin Finck
2119*c2c66affSColin Finck task->window = window;
2120*c2c66affSColin Finck task->bscallback = bsc;
2121*c2c66affSColin Finck task->flags = flags;
2122*c2c66affSColin Finck task->mon = mon;
2123*c2c66affSColin Finck
2124*c2c66affSColin Finck IUri_AddRef(uri);
2125*c2c66affSColin Finck task->uri = uri;
2126*c2c66affSColin Finck hres = push_task(&task->header, navigate_proc, navigate_task_destr, window->task_magic);
2127*c2c66affSColin Finck }
2128*c2c66affSColin Finck
2129*c2c66affSColin Finck return hres;
2130*c2c66affSColin Finck }
2131*c2c66affSColin Finck
navigate_new_window(HTMLOuterWindow * window,IUri * uri,const WCHAR * name,request_data_t * request_data,IHTMLWindow2 ** ret)2132*c2c66affSColin Finck HRESULT navigate_new_window(HTMLOuterWindow *window, IUri *uri, const WCHAR *name, request_data_t *request_data, IHTMLWindow2 **ret)
2133*c2c66affSColin Finck {
2134*c2c66affSColin Finck IWebBrowser2 *web_browser;
2135*c2c66affSColin Finck IHTMLWindow2 *new_window;
2136*c2c66affSColin Finck IBindCtx *bind_ctx;
2137*c2c66affSColin Finck nsChannelBSC *bsc;
2138*c2c66affSColin Finck HRESULT hres;
2139*c2c66affSColin Finck
2140*c2c66affSColin Finck if(request_data)
2141*c2c66affSColin Finck hres = create_channelbsc(NULL, request_data->headers,
2142*c2c66affSColin Finck request_data->post_data, request_data->post_data_len, FALSE,
2143*c2c66affSColin Finck &bsc);
2144*c2c66affSColin Finck else
2145*c2c66affSColin Finck hres = create_channelbsc(NULL, NULL, NULL, 0, FALSE, &bsc);
2146*c2c66affSColin Finck if(FAILED(hres))
2147*c2c66affSColin Finck return hres;
2148*c2c66affSColin Finck
2149*c2c66affSColin Finck hres = CreateAsyncBindCtx(0, &bsc->bsc.IBindStatusCallback_iface, NULL, &bind_ctx);
2150*c2c66affSColin Finck if(FAILED(hres)) {
2151*c2c66affSColin Finck IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface);
2152*c2c66affSColin Finck return hres;
2153*c2c66affSColin Finck }
2154*c2c66affSColin Finck
2155*c2c66affSColin Finck hres = CoCreateInstance(&CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER,
2156*c2c66affSColin Finck &IID_IWebBrowser2, (void**)&web_browser);
2157*c2c66affSColin Finck if(SUCCEEDED(hres)) {
2158*c2c66affSColin Finck ITargetFramePriv2 *target_frame_priv;
2159*c2c66affSColin Finck
2160*c2c66affSColin Finck hres = IWebBrowser2_QueryInterface(web_browser, &IID_ITargetFramePriv2, (void**)&target_frame_priv);
2161*c2c66affSColin Finck if(SUCCEEDED(hres)) {
2162*c2c66affSColin Finck hres = ITargetFramePriv2_AggregatedNavigation2(target_frame_priv,
2163*c2c66affSColin Finck HLNF_DISABLEWINDOWRESTRICTIONS|HLNF_OPENINNEWWINDOW, bind_ctx, &bsc->bsc.IBindStatusCallback_iface,
2164*c2c66affSColin Finck name, uri, emptyW);
2165*c2c66affSColin Finck ITargetFramePriv2_Release(target_frame_priv);
2166*c2c66affSColin Finck
2167*c2c66affSColin Finck if(SUCCEEDED(hres))
2168*c2c66affSColin Finck hres = do_query_service((IUnknown*)web_browser, &SID_SHTMLWindow, &IID_IHTMLWindow2, (void**)&new_window);
2169*c2c66affSColin Finck }
2170*c2c66affSColin Finck if(FAILED(hres)) {
2171*c2c66affSColin Finck IWebBrowser2_Quit(web_browser);
2172*c2c66affSColin Finck IWebBrowser2_Release(web_browser);
2173*c2c66affSColin Finck }
2174*c2c66affSColin Finck }else {
2175*c2c66affSColin Finck WARN("Could not create InternetExplorer instance: %08x\n", hres);
2176*c2c66affSColin Finck }
2177*c2c66affSColin Finck
2178*c2c66affSColin Finck IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface);
2179*c2c66affSColin Finck IBindCtx_Release(bind_ctx);
2180*c2c66affSColin Finck if(FAILED(hres))
2181*c2c66affSColin Finck return hres;
2182*c2c66affSColin Finck
2183*c2c66affSColin Finck IWebBrowser2_put_Visible(web_browser, VARIANT_TRUE);
2184*c2c66affSColin Finck IWebBrowser2_Release(web_browser);
2185*c2c66affSColin Finck
2186*c2c66affSColin Finck if(ret)
2187*c2c66affSColin Finck *ret = new_window;
2188*c2c66affSColin Finck else
2189*c2c66affSColin Finck IHTMLWindow2_Release(new_window);
2190*c2c66affSColin Finck return S_OK;
2191*c2c66affSColin Finck }
2192*c2c66affSColin Finck
hlink_frame_navigate(HTMLDocument * doc,LPCWSTR url,nsChannel * nschannel,DWORD hlnf,BOOL * cancel)2193*c2c66affSColin Finck HRESULT hlink_frame_navigate(HTMLDocument *doc, LPCWSTR url, nsChannel *nschannel, DWORD hlnf, BOOL *cancel)
2194*c2c66affSColin Finck {
2195*c2c66affSColin Finck IHlinkFrame *hlink_frame;
2196*c2c66affSColin Finck nsChannelBSC *callback;
2197*c2c66affSColin Finck IBindCtx *bindctx;
2198*c2c66affSColin Finck IMoniker *mon;
2199*c2c66affSColin Finck IHlink *hlink;
2200*c2c66affSColin Finck HRESULT hres;
2201*c2c66affSColin Finck
2202*c2c66affSColin Finck *cancel = FALSE;
2203*c2c66affSColin Finck
2204*c2c66affSColin Finck hres = do_query_service((IUnknown*)doc->doc_obj->client, &IID_IHlinkFrame, &IID_IHlinkFrame,
2205*c2c66affSColin Finck (void**)&hlink_frame);
2206*c2c66affSColin Finck if(FAILED(hres))
2207*c2c66affSColin Finck return S_OK;
2208*c2c66affSColin Finck
2209*c2c66affSColin Finck hres = create_channelbsc(NULL, NULL, NULL, 0, FALSE, &callback);
2210*c2c66affSColin Finck if(FAILED(hres)) {
2211*c2c66affSColin Finck IHlinkFrame_Release(hlink_frame);
2212*c2c66affSColin Finck return hres;
2213*c2c66affSColin Finck }
2214*c2c66affSColin Finck
2215*c2c66affSColin Finck if(nschannel)
2216*c2c66affSColin Finck read_post_data_stream(nschannel->post_data_stream, nschannel->post_data_contains_headers,
2217*c2c66affSColin Finck &nschannel->request_headers, &callback->bsc.request_data);
2218*c2c66affSColin Finck
2219*c2c66affSColin Finck hres = CreateAsyncBindCtx(0, &callback->bsc.IBindStatusCallback_iface, NULL, &bindctx);
2220*c2c66affSColin Finck if(SUCCEEDED(hres))
2221*c2c66affSColin Finck hres = CoCreateInstance(&CLSID_StdHlink, NULL, CLSCTX_INPROC_SERVER,
2222*c2c66affSColin Finck &IID_IHlink, (LPVOID*)&hlink);
2223*c2c66affSColin Finck
2224*c2c66affSColin Finck if(SUCCEEDED(hres))
2225*c2c66affSColin Finck hres = CreateURLMoniker(NULL, url, &mon);
2226*c2c66affSColin Finck
2227*c2c66affSColin Finck if(SUCCEEDED(hres)) {
2228*c2c66affSColin Finck IHlink_SetMonikerReference(hlink, HLINKSETF_TARGET, mon, NULL);
2229*c2c66affSColin Finck
2230*c2c66affSColin Finck if(hlnf & HLNF_OPENINNEWWINDOW) {
2231*c2c66affSColin Finck static const WCHAR wszBlank[] = {'_','b','l','a','n','k',0};
2232*c2c66affSColin Finck IHlink_SetTargetFrameName(hlink, wszBlank); /* FIXME */
2233*c2c66affSColin Finck }
2234*c2c66affSColin Finck
2235*c2c66affSColin Finck hres = IHlinkFrame_Navigate(hlink_frame, hlnf, bindctx,
2236*c2c66affSColin Finck &callback->bsc.IBindStatusCallback_iface, hlink);
2237*c2c66affSColin Finck IMoniker_Release(mon);
2238*c2c66affSColin Finck *cancel = hres == S_OK;
2239*c2c66affSColin Finck hres = S_OK;
2240*c2c66affSColin Finck }
2241*c2c66affSColin Finck
2242*c2c66affSColin Finck IHlinkFrame_Release(hlink_frame);
2243*c2c66affSColin Finck IBindCtx_Release(bindctx);
2244*c2c66affSColin Finck IBindStatusCallback_Release(&callback->bsc.IBindStatusCallback_iface);
2245*c2c66affSColin Finck return hres;
2246*c2c66affSColin Finck }
2247*c2c66affSColin Finck
navigate_uri(HTMLOuterWindow * window,IUri * uri,const WCHAR * display_uri,const request_data_t * request_data,DWORD flags)2248*c2c66affSColin Finck static HRESULT navigate_uri(HTMLOuterWindow *window, IUri *uri, const WCHAR *display_uri, const request_data_t *request_data,
2249*c2c66affSColin Finck DWORD flags)
2250*c2c66affSColin Finck {
2251*c2c66affSColin Finck nsWineURI *nsuri;
2252*c2c66affSColin Finck HRESULT hres;
2253*c2c66affSColin Finck
2254*c2c66affSColin Finck TRACE("%s\n", debugstr_w(display_uri));
2255*c2c66affSColin Finck
2256*c2c66affSColin Finck if(window->doc_obj && window->doc_obj->webbrowser) {
2257*c2c66affSColin Finck DWORD post_data_len = request_data ? request_data->post_data_len : 0;
2258*c2c66affSColin Finck void *post_data = post_data_len ? request_data->post_data : NULL;
2259*c2c66affSColin Finck const WCHAR *headers = request_data ? request_data->headers : NULL;
2260*c2c66affSColin Finck
2261*c2c66affSColin Finck if(!(flags & BINDING_REFRESH)) {
2262*c2c66affSColin Finck BSTR frame_name = NULL;
2263*c2c66affSColin Finck BOOL cancel = FALSE;
2264*c2c66affSColin Finck
2265*c2c66affSColin Finck if(window != window->doc_obj->basedoc.window) {
2266*c2c66affSColin Finck hres = IHTMLWindow2_get_name(&window->base.IHTMLWindow2_iface, &frame_name);
2267*c2c66affSColin Finck if(FAILED(hres))
2268*c2c66affSColin Finck return hres;
2269*c2c66affSColin Finck }
2270*c2c66affSColin Finck
2271*c2c66affSColin Finck hres = IDocObjectService_FireBeforeNavigate2(window->doc_obj->doc_object_service, NULL, display_uri, 0x40,
2272*c2c66affSColin Finck frame_name, post_data, post_data_len ? post_data_len+1 : 0, headers, TRUE, &cancel);
2273*c2c66affSColin Finck SysFreeString(frame_name);
2274*c2c66affSColin Finck if(SUCCEEDED(hres) && cancel) {
2275*c2c66affSColin Finck TRACE("Navigation canceled\n");
2276*c2c66affSColin Finck return S_OK;
2277*c2c66affSColin Finck }
2278*c2c66affSColin Finck }
2279*c2c66affSColin Finck
2280*c2c66affSColin Finck if(window == window->doc_obj->basedoc.window)
2281*c2c66affSColin Finck return super_navigate(window, uri, flags, headers, post_data, post_data_len);
2282*c2c66affSColin Finck }
2283*c2c66affSColin Finck
2284*c2c66affSColin Finck if(window->doc_obj && window == window->doc_obj->basedoc.window) {
2285*c2c66affSColin Finck BOOL cancel;
2286*c2c66affSColin Finck
2287*c2c66affSColin Finck hres = hlink_frame_navigate(&window->base.inner_window->doc->basedoc, display_uri, NULL, 0, &cancel);
2288*c2c66affSColin Finck if(FAILED(hres))
2289*c2c66affSColin Finck return hres;
2290*c2c66affSColin Finck
2291*c2c66affSColin Finck if(cancel) {
2292*c2c66affSColin Finck TRACE("Navigation handled by hlink frame\n");
2293*c2c66affSColin Finck return S_OK;
2294*c2c66affSColin Finck }
2295*c2c66affSColin Finck }
2296*c2c66affSColin Finck
2297*c2c66affSColin Finck hres = create_doc_uri(window, uri, &nsuri);
2298*c2c66affSColin Finck if(FAILED(hres))
2299*c2c66affSColin Finck return hres;
2300*c2c66affSColin Finck
2301*c2c66affSColin Finck hres = load_nsuri(window, nsuri, request_data ? request_data->post_stream : NULL, NULL, LOAD_FLAGS_NONE);
2302*c2c66affSColin Finck nsISupports_Release((nsISupports*)nsuri);
2303*c2c66affSColin Finck return hres;
2304*c2c66affSColin Finck }
2305*c2c66affSColin Finck
load_uri(HTMLOuterWindow * window,IUri * uri,DWORD flags)2306*c2c66affSColin Finck HRESULT load_uri(HTMLOuterWindow *window, IUri *uri, DWORD flags)
2307*c2c66affSColin Finck {
2308*c2c66affSColin Finck BSTR display_uri;
2309*c2c66affSColin Finck HRESULT hres;
2310*c2c66affSColin Finck
2311*c2c66affSColin Finck hres = IUri_GetDisplayUri(uri, &display_uri);
2312*c2c66affSColin Finck if(FAILED(hres))
2313*c2c66affSColin Finck return hres;
2314*c2c66affSColin Finck
2315*c2c66affSColin Finck hres = navigate_uri(window, uri, display_uri, NULL, flags);
2316*c2c66affSColin Finck SysFreeString(display_uri);
2317*c2c66affSColin Finck return hres;
2318*c2c66affSColin Finck }
2319*c2c66affSColin Finck
translate_uri(HTMLOuterWindow * window,IUri * orig_uri,BSTR * ret_display_uri,IUri ** ret_uri)2320*c2c66affSColin Finck static HRESULT translate_uri(HTMLOuterWindow *window, IUri *orig_uri, BSTR *ret_display_uri, IUri **ret_uri)
2321*c2c66affSColin Finck {
2322*c2c66affSColin Finck IUri *uri = NULL;
2323*c2c66affSColin Finck BSTR display_uri;
2324*c2c66affSColin Finck HRESULT hres;
2325*c2c66affSColin Finck
2326*c2c66affSColin Finck hres = IUri_GetDisplayUri(orig_uri, &display_uri);
2327*c2c66affSColin Finck if(FAILED(hres))
2328*c2c66affSColin Finck return hres;
2329*c2c66affSColin Finck
2330*c2c66affSColin Finck if(window->doc_obj && window->doc_obj->hostui) {
2331*c2c66affSColin Finck OLECHAR *translated_url = NULL;
2332*c2c66affSColin Finck
2333*c2c66affSColin Finck hres = IDocHostUIHandler_TranslateUrl(window->doc_obj->hostui, 0, display_uri,
2334*c2c66affSColin Finck &translated_url);
2335*c2c66affSColin Finck if(hres == S_OK && translated_url) {
2336*c2c66affSColin Finck TRACE("%08x %s -> %s\n", hres, debugstr_w(display_uri), debugstr_w(translated_url));
2337*c2c66affSColin Finck SysFreeString(display_uri);
2338*c2c66affSColin Finck hres = create_uri(translated_url, 0, &uri);
2339*c2c66affSColin Finck CoTaskMemFree(translated_url);
2340*c2c66affSColin Finck if(FAILED(hres))
2341*c2c66affSColin Finck return hres;
2342*c2c66affSColin Finck
2343*c2c66affSColin Finck hres = IUri_GetDisplayUri(uri, &display_uri);
2344*c2c66affSColin Finck if(FAILED(hres)) {
2345*c2c66affSColin Finck IUri_Release(uri);
2346*c2c66affSColin Finck return hres;
2347*c2c66affSColin Finck }
2348*c2c66affSColin Finck }
2349*c2c66affSColin Finck }
2350*c2c66affSColin Finck
2351*c2c66affSColin Finck if(!uri) {
2352*c2c66affSColin Finck IUri_AddRef(orig_uri);
2353*c2c66affSColin Finck uri = orig_uri;
2354*c2c66affSColin Finck }
2355*c2c66affSColin Finck
2356*c2c66affSColin Finck *ret_display_uri = display_uri;
2357*c2c66affSColin Finck *ret_uri = uri;
2358*c2c66affSColin Finck return S_OK;
2359*c2c66affSColin Finck }
2360*c2c66affSColin Finck
submit_form(HTMLOuterWindow * window,const WCHAR * target,IUri * submit_uri,nsIInputStream * post_stream)2361*c2c66affSColin Finck HRESULT submit_form(HTMLOuterWindow *window, const WCHAR *target, IUri *submit_uri, nsIInputStream *post_stream)
2362*c2c66affSColin Finck {
2363*c2c66affSColin Finck request_data_t request_data = {NULL};
2364*c2c66affSColin Finck HRESULT hres;
2365*c2c66affSColin Finck
2366*c2c66affSColin Finck hres = read_post_data_stream(post_stream, TRUE, NULL, &request_data);
2367*c2c66affSColin Finck if(FAILED(hres))
2368*c2c66affSColin Finck return hres;
2369*c2c66affSColin Finck
2370*c2c66affSColin Finck if(window) {
2371*c2c66affSColin Finck IUri *uri;
2372*c2c66affSColin Finck BSTR display_uri;
2373*c2c66affSColin Finck
2374*c2c66affSColin Finck window->readystate_locked++;
2375*c2c66affSColin Finck
2376*c2c66affSColin Finck hres = translate_uri(window, submit_uri, &display_uri, &uri);
2377*c2c66affSColin Finck if(SUCCEEDED(hres)) {
2378*c2c66affSColin Finck hres = navigate_uri(window, uri, display_uri, &request_data, BINDING_NAVIGATED|BINDING_SUBMIT);
2379*c2c66affSColin Finck IUri_Release(uri);
2380*c2c66affSColin Finck SysFreeString(display_uri);
2381*c2c66affSColin Finck }
2382*c2c66affSColin Finck
2383*c2c66affSColin Finck window->readystate_locked--;
2384*c2c66affSColin Finck }else
2385*c2c66affSColin Finck hres = navigate_new_window(window, submit_uri, target, &request_data, NULL);
2386*c2c66affSColin Finck
2387*c2c66affSColin Finck release_request_data(&request_data);
2388*c2c66affSColin Finck return hres;
2389*c2c66affSColin Finck }
2390*c2c66affSColin Finck
navigate_url(HTMLOuterWindow * window,const WCHAR * new_url,IUri * base_uri,DWORD flags)2391*c2c66affSColin Finck HRESULT navigate_url(HTMLOuterWindow *window, const WCHAR *new_url, IUri *base_uri, DWORD flags)
2392*c2c66affSColin Finck {
2393*c2c66affSColin Finck IUri *uri, *nav_uri;
2394*c2c66affSColin Finck BSTR display_uri;
2395*c2c66affSColin Finck HRESULT hres;
2396*c2c66affSColin Finck
2397*c2c66affSColin Finck if(new_url && base_uri)
2398*c2c66affSColin Finck hres = CoInternetCombineUrlEx(base_uri, new_url, URL_ESCAPE_SPACES_ONLY|URL_DONT_ESCAPE_EXTRA_INFO,
2399*c2c66affSColin Finck &nav_uri, 0);
2400*c2c66affSColin Finck else
2401*c2c66affSColin Finck hres = create_uri(new_url, 0, &nav_uri);
2402*c2c66affSColin Finck if(FAILED(hres))
2403*c2c66affSColin Finck return hres;
2404*c2c66affSColin Finck
2405*c2c66affSColin Finck hres = translate_uri(window, nav_uri, &display_uri, &uri);
2406*c2c66affSColin Finck IUri_Release(nav_uri);
2407*c2c66affSColin Finck if(FAILED(hres))
2408*c2c66affSColin Finck return hres;
2409*c2c66affSColin Finck
2410*c2c66affSColin Finck hres = navigate_uri(window, uri, display_uri, NULL, flags);
2411*c2c66affSColin Finck IUri_Release(uri);
2412*c2c66affSColin Finck SysFreeString(display_uri);
2413*c2c66affSColin Finck return hres;
2414*c2c66affSColin Finck }
2415