mshtml: Create inner window early in binding process and use it to store current binding callback.

This commit is contained in:
Jacek Caban 2012-07-12 14:25:43 +02:00 committed by Alexandre Julliard
parent 7e2999e70f
commit 25c5082f90
6 changed files with 120 additions and 101 deletions

View File

@ -111,7 +111,7 @@ HRESULT super_navigate(HTMLOuterWindow*,IUri*,const WCHAR*,BYTE*,DWORD) DECLSPEC
HRESULT navigate_new_window(HTMLOuterWindow*,IUri*,const WCHAR*,IHTMLWindow2**) DECLSPEC_HIDDEN;
HRESULT create_channelbsc(IMoniker*,const WCHAR*,BYTE*,DWORD,nsChannelBSC**) DECLSPEC_HIDDEN;
HRESULT channelbsc_load_stream(nsChannelBSC*,IStream*) DECLSPEC_HIDDEN;
HRESULT channelbsc_load_stream(HTMLInnerWindow*,IStream*) DECLSPEC_HIDDEN;
void channelbsc_set_channel(nsChannelBSC*,nsChannel*,nsIStreamListener*,nsISupports*) DECLSPEC_HIDDEN;
IUri *nsuri_get_uri(nsWineURI*) DECLSPEC_HIDDEN;
HRESULT create_relative_uri(HTMLOuterWindow*,const WCHAR*,IUri**) DECLSPEC_HIDDEN;

View File

@ -197,8 +197,13 @@ static ULONG WINAPI HTMLWindow2_AddRef(IHTMLWindow2 *iface)
static void release_outer_window(HTMLOuterWindow *This)
{
if(This->pending_window) {
abort_window_bindings(This->pending_window);
This->pending_window->base.outer_window = NULL;
IHTMLWindow2_Release(&This->pending_window->base.IHTMLWindow2_iface);
}
remove_target_tasks(This->task_magic);
set_window_bscallback(This, NULL);
set_current_mon(This, NULL);
detach_inner_window(This);
release_children(This);
@ -228,9 +233,14 @@ static void release_inner_window(HTMLInnerWindow *This)
{
unsigned i;
TRACE("%p\n", This);
abort_window_bindings(This);
release_script_hosts(This);
htmldoc_release(&This->doc->basedoc);
if(This->doc)
htmldoc_release(&This->doc->basedoc);
release_dispex(&This->dispex);
for(i=0; i < This->global_prop_cnt; i++)
@ -2596,7 +2606,7 @@ static void *alloc_window(size_t size)
return window;
}
static HRESULT create_inner_window(HTMLOuterWindow *outer_window, HTMLDocumentNode *doc_node, HTMLInnerWindow **ret)
static HRESULT create_inner_window(HTMLOuterWindow *outer_window, HTMLInnerWindow **ret)
{
HTMLInnerWindow *window;
@ -2610,9 +2620,6 @@ static HRESULT create_inner_window(HTMLOuterWindow *outer_window, HTMLDocumentNo
window->base.outer_window = outer_window;
window->base.inner_window = window;
htmldoc_addref(&doc_node->basedoc);
window->doc = doc_node;
init_dispex(&window->dispex, (IUnknown*)&window->base.IHTMLWindow2_iface, &HTMLWindow_dispex);
*ret = window;
@ -2651,7 +2658,9 @@ HRESULT HTMLOuterWindow_Create(HTMLDocumentObj *doc_obj, nsIDOMWindow *nswindow,
window->scriptmode = parent ? parent->scriptmode : SCRIPTMODE_GECKO;
window->readystate = READYSTATE_UNINITIALIZED;
hres = update_window_doc(window);
hres = create_pending_window(window, NULL);
if(SUCCEEDED(hres))
hres = update_window_doc(window->pending_window);
if(FAILED(hres)) {
IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface);
return hres;
@ -2675,54 +2684,54 @@ HRESULT HTMLOuterWindow_Create(HTMLDocumentObj *doc_obj, nsIDOMWindow *nswindow,
list_add_tail(&parent->children, &window->sibling_entry);
}
TRACE("%p inner_window %p\n", window, window->base.inner_window);
*ret = window;
return S_OK;
}
static HRESULT window_set_docnode(HTMLOuterWindow *window, HTMLDocumentNode *doc_node)
HRESULT create_pending_window(HTMLOuterWindow *outer_window, nsChannelBSC *channelbsc)
{
HTMLInnerWindow *inner_window;
HTMLInnerWindow *pending_window;
HRESULT hres;
hres = create_inner_window(window, doc_node, &inner_window);
hres = create_inner_window(outer_window, &pending_window);
if(FAILED(hres))
return hres;
detach_inner_window(window);
window->base.inner_window = inner_window;
if(channelbsc) {
IBindStatusCallback_AddRef(&channelbsc->bsc.IBindStatusCallback_iface);
pending_window->bscallback = channelbsc;
if(window->doc_obj && window->doc_obj->basedoc.window == window) {
if(window->doc_obj->basedoc.doc_node)
htmldoc_release(&window->doc_obj->basedoc.doc_node->basedoc);
window->doc_obj->basedoc.doc_node = doc_node;
if(doc_node)
htmldoc_addref(&doc_node->basedoc);
channelbsc->window = outer_window;
}
if(doc_node && window->doc_obj && window->doc_obj->usermode == EDITMODE) {
nsAString mode_str;
nsresult nsres;
static const PRUnichar onW[] = {'o','n',0};
nsAString_Init(&mode_str, onW);
nsres = nsIDOMHTMLDocument_SetDesignMode(doc_node->nsdoc, &mode_str);
nsAString_Finish(&mode_str);
if(NS_FAILED(nsres))
ERR("SetDesignMode failed: %08x\n", nsres);
if(outer_window->pending_window) {
abort_window_bindings(outer_window->pending_window);
outer_window->pending_window->base.outer_window = NULL;
IHTMLWindow2_Release(&outer_window->pending_window->base.IHTMLWindow2_iface);
}
outer_window->pending_window = pending_window;
return S_OK;
}
HRESULT update_window_doc(HTMLOuterWindow *window)
HRESULT update_window_doc(HTMLInnerWindow *window)
{
HTMLOuterWindow *outer_window = window->base.outer_window;
nsIDOMHTMLDocument *nshtmldoc;
nsIDOMDocument *nsdoc;
nsresult nsres;
HRESULT hres;
nsres = nsIDOMWindow_GetDocument(window->nswindow, &nsdoc);
assert(!window->doc);
if(!outer_window) {
ERR("NULL outer window\n");
return E_UNEXPECTED;
}
nsres = nsIDOMWindow_GetDocument(outer_window->nswindow, &nsdoc);
if(NS_FAILED(nsres) || !nsdoc) {
ERR("GetDocument failed: %08x\n", nsres);
return E_FAIL;
@ -2735,21 +2744,40 @@ HRESULT update_window_doc(HTMLOuterWindow *window)
return E_FAIL;
}
if(!window->base.inner_window || window->base.inner_window->doc->nsdoc != nshtmldoc) {
HTMLDocumentNode *doc;
hres = create_doc_from_nsdoc(nshtmldoc, outer_window->doc_obj, outer_window, &window->doc);
nsIDOMHTMLDocument_Release(nshtmldoc);
if(FAILED(hres))
return hres;
hres = create_doc_from_nsdoc(nshtmldoc, window->doc_obj, window, &doc);
if(SUCCEEDED(hres)) {
hres = window_set_docnode(window, doc);
htmldoc_release(&doc->basedoc);
}else {
ERR("create_doc_from_nsdoc failed: %08x\n", hres);
}
}else {
hres = S_OK;
if(outer_window->doc_obj->usermode == EDITMODE) {
nsAString mode_str;
nsresult nsres;
static const PRUnichar onW[] = {'o','n',0};
nsAString_Init(&mode_str, onW);
nsres = nsIDOMHTMLDocument_SetDesignMode(window->doc->nsdoc, &mode_str);
nsAString_Finish(&mode_str);
if(NS_FAILED(nsres))
ERR("SetDesignMode failed: %08x\n", nsres);
}
if(window != outer_window->pending_window) {
ERR("not current pending window\n");
return S_OK;
}
detach_inner_window(outer_window);
outer_window->base.inner_window = window;
outer_window->pending_window = NULL;
if(outer_window->doc_obj && (outer_window->doc_obj->basedoc.window == outer_window || !outer_window->doc_obj->basedoc.window)) {
if(outer_window->doc_obj->basedoc.doc_node)
htmldoc_release(&outer_window->doc_obj->basedoc.doc_node->basedoc);
outer_window->doc_obj->basedoc.doc_node = window->doc;
htmldoc_addref(&window->doc->basedoc);
}
nsIDOMHTMLDocument_Release(nshtmldoc);
return hres;
}

View File

@ -326,7 +326,7 @@ struct HTMLOuterWindow {
HTMLFrameBase *frame_element;
READYSTATE readystate;
nsChannelBSC *bscallback;
HTMLInnerWindow *pending_window;
IMoniker *mon;
IUri *uri;
BSTR url;
@ -361,6 +361,7 @@ struct HTMLInnerWindow {
DWORD global_prop_cnt;
DWORD global_prop_size;
nsChannelBSC *bscallback;
struct list bindings;
};
@ -665,7 +666,7 @@ HRESULT create_doc_from_nsdoc(nsIDOMHTMLDocument*,HTMLDocumentObj*,HTMLOuterWind
HRESULT create_document_fragment(nsIDOMNode*,HTMLDocumentNode*,HTMLDocumentNode**) DECLSPEC_HIDDEN;
HRESULT HTMLOuterWindow_Create(HTMLDocumentObj*,nsIDOMWindow*,HTMLOuterWindow*,HTMLOuterWindow**) DECLSPEC_HIDDEN;
HRESULT update_window_doc(HTMLOuterWindow*) DECLSPEC_HIDDEN;
HRESULT update_window_doc(HTMLInnerWindow*) DECLSPEC_HIDDEN;
HTMLOuterWindow *nswindow_to_window(const nsIDOMWindow*) DECLSPEC_HIDDEN;
void get_top_window(HTMLOuterWindow*,HTMLOuterWindow**) DECLSPEC_HIDDEN;
HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow*,HTMLOptionElementFactory**) DECLSPEC_HIDDEN;
@ -750,11 +751,11 @@ void get_editor_controller(NSContainer*) DECLSPEC_HIDDEN;
nsresult get_nsinterface(nsISupports*,REFIID,void**) DECLSPEC_HIDDEN;
nsIWritableVariant *create_nsvariant(void) DECLSPEC_HIDDEN;
void set_window_bscallback(HTMLOuterWindow*,nsChannelBSC*) DECLSPEC_HIDDEN;
HRESULT create_pending_window(HTMLOuterWindow*,nsChannelBSC*) DECLSPEC_HIDDEN;
void set_current_mon(HTMLOuterWindow*,IMoniker*) DECLSPEC_HIDDEN;
void set_current_uri(HTMLOuterWindow*,IUri*) DECLSPEC_HIDDEN;
HRESULT start_binding(HTMLOuterWindow*,HTMLInnerWindow*,BSCallback*,IBindCtx*) DECLSPEC_HIDDEN;
HRESULT async_start_doc_binding(HTMLOuterWindow*,nsChannelBSC*) DECLSPEC_HIDDEN;
HRESULT async_start_doc_binding(HTMLOuterWindow*,HTMLInnerWindow*) DECLSPEC_HIDDEN;
void abort_window_bindings(HTMLInnerWindow*) DECLSPEC_HIDDEN;
void set_download_state(HTMLDocumentObj*,int) DECLSPEC_HIDDEN;
void call_docview_84(HTMLDocumentObj*) DECLSPEC_HIDDEN;

View File

@ -725,8 +725,6 @@ HRESULT start_binding(HTMLOuterWindow *window, HTMLInnerWindow *inner_window, BS
TRACE("(%p %p %p %p)\n", window, inner_window, bscallback, bctx);
bscallback->window = inner_window;
if(!inner_window && window)
bscallback->window = window->base.inner_window;
/* NOTE: IE7 calls IsSystemMoniker here*/
@ -995,12 +993,7 @@ static HRESULT on_start_nsrequest(nsChannelBSC *This)
}
if(This->window) {
list_remove(&This->bsc.entry);
list_init(&This->bsc.entry);
update_window_doc(This->window);
if(This->window->base.inner_window != This->bsc.window)
This->bsc.window = This->window->base.inner_window;
list_add_head(&This->bsc.window->bindings, &This->bsc.entry);
update_window_doc(This->bsc.window);
if(This->window->readystate != READYSTATE_LOADING)
set_ready_state(This->window, READYSTATE_LOADING);
}
@ -1331,6 +1324,7 @@ static HRESULT async_stop_request(nsChannelBSC *This)
IBindStatusCallback_AddRef(&This->bsc.IBindStatusCallback_iface);
task->bsc = This;
push_task(&task->header, stop_request_proc, stop_request_task_destr, This->window->doc_obj->basedoc.task_magic);
return S_OK;
}
@ -1650,59 +1644,40 @@ HRESULT create_channelbsc(IMoniker *mon, const WCHAR *headers, BYTE *post_data,
return S_OK;
}
void set_window_bscallback(HTMLOuterWindow *window, nsChannelBSC *callback)
{
if(window->bscallback) {
if(window->bscallback->bsc.binding)
IBinding_Abort(window->bscallback->bsc.binding);
window->bscallback->bsc.window = NULL;
window->bscallback->window = NULL;
IBindStatusCallback_Release(&window->bscallback->bsc.IBindStatusCallback_iface);
}
window->bscallback = callback;
if(callback) {
callback->window = window;
IBindStatusCallback_AddRef(&callback->bsc.IBindStatusCallback_iface);
callback->bsc.window = window->base.inner_window;
}
}
typedef struct {
task_t header;
HTMLOuterWindow *window;
nsChannelBSC *bscallback;
HTMLInnerWindow *pending_window;
} start_doc_binding_task_t;
static void start_doc_binding_proc(task_t *_task)
{
start_doc_binding_task_t *task = (start_doc_binding_task_t*)_task;
start_binding(task->window, NULL, (BSCallback*)task->bscallback, NULL);
start_binding(task->window, task->pending_window, &task->pending_window->bscallback->bsc, NULL);
}
static void start_doc_binding_task_destr(task_t *_task)
{
start_doc_binding_task_t *task = (start_doc_binding_task_t*)_task;
IBindStatusCallback_Release(&task->bscallback->bsc.IBindStatusCallback_iface);
IHTMLWindow2_Release(&task->pending_window->base.IHTMLWindow2_iface);
heap_free(task);
}
HRESULT async_start_doc_binding(HTMLOuterWindow *window, nsChannelBSC *bscallback)
HRESULT async_start_doc_binding(HTMLOuterWindow *window, HTMLInnerWindow *pending_window)
{
start_doc_binding_task_t *task;
TRACE("%p\n", bscallback);
TRACE("%p\n", pending_window);
task = heap_alloc(sizeof(start_doc_binding_task_t));
if(!task)
return E_OUTOFMEMORY;
task->window = window;
task->bscallback = bscallback;
IBindStatusCallback_AddRef(&bscallback->bsc.IBindStatusCallback_iface);
task->pending_window = pending_window;
IHTMLWindow2_AddRef(&pending_window->base.IHTMLWindow2_iface);
push_task(&task->header, start_doc_binding_proc, start_doc_binding_task_destr, window->task_magic);
return S_OK;
@ -1710,28 +1685,40 @@ HRESULT async_start_doc_binding(HTMLOuterWindow *window, nsChannelBSC *bscallbac
void abort_window_bindings(HTMLInnerWindow *window)
{
BSCallback *iter, *next;
BSCallback *iter;
while(!list_empty(&window->bindings)) {
iter = LIST_ENTRY(window->bindings.next, BSCallback, entry);
LIST_FOR_EACH_ENTRY_SAFE(iter, next, &window->bindings, BSCallback, entry) {
TRACE("Aborting %p\n", iter);
IBindStatusCallback_AddRef(&iter->IBindStatusCallback_iface);
if(iter->window && iter->window->doc)
remove_target_tasks(iter->window->doc->basedoc.task_magic);
if(iter->binding)
IBinding_Abort(iter->binding);
else {
list_remove(&iter->entry);
list_init(&iter->entry);
else
iter->vtbl->stop_binding(iter, E_ABORT);
}
iter->window = NULL;
list_remove(&iter->entry);
list_init(&iter->entry);
IBindStatusCallback_Release(&iter->IBindStatusCallback_iface);
}
if(window->bscallback) {
window->bscallback->window = NULL;
IBindStatusCallback_Release(&window->bscallback->bsc.IBindStatusCallback_iface);
window->bscallback = NULL;
}
}
HRESULT channelbsc_load_stream(nsChannelBSC *bscallback, IStream *stream)
HRESULT channelbsc_load_stream(HTMLInnerWindow *pending_window, IStream *stream)
{
nsChannelBSC *bscallback = pending_window->bscallback;
HRESULT hres = S_OK;
if(!bscallback->nschannel) {
@ -1743,7 +1730,7 @@ HRESULT channelbsc_load_stream(nsChannelBSC *bscallback, IStream *stream)
if(!bscallback->nschannel->content_type)
return E_OUTOFMEMORY;
list_add_head(&bscallback->bsc.window->bindings, &bscallback->bsc.entry);
bscallback->bsc.window = pending_window;
if(stream)
hres = read_stream_data(bscallback, stream);
if(SUCCEEDED(hres))
@ -1839,14 +1826,14 @@ static void navigate_proc(task_t *_task)
hres = set_moniker(&task->window->doc_obj->basedoc, task->mon, NULL, task->bscallback, TRUE);
if(SUCCEEDED(hres))
start_binding(task->window, NULL, (BSCallback*)task->bscallback, NULL);
start_binding(task->window, task->window->pending_window, &task->bscallback->bsc, NULL);
}
static void navigate_task_destr(task_t *_task)
{
navigate_task_t *task = (navigate_task_t*)_task;
IUnknown_Release((IUnknown*)task->bscallback);
IBindStatusCallback_Release(&task->bscallback->bsc.IBindStatusCallback_iface);
IMoniker_Release(task->mon);
heap_free(task);
}
@ -1946,7 +1933,7 @@ HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, const WCHAR *headers,
task = heap_alloc(sizeof(*task));
if(!task) {
IUnknown_Release((IUnknown*)bsc);
IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface);
IMoniker_Release(mon);
return E_OUTOFMEMORY;
}
@ -1963,7 +1950,7 @@ HRESULT super_navigate(HTMLOuterWindow *window, IUri *uri, const WCHAR *headers,
}else {
navigate_javascript_task_t *task;
IUnknown_Release((IUnknown*)bsc);
IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface);
IMoniker_Release(mon);
task = heap_alloc(sizeof(*task));

View File

@ -1016,9 +1016,12 @@ static nsresult async_open(nsChannel *This, HTMLOuterWindow *window, BOOL is_doc
channelbsc_set_channel(bscallback, This, listener, context);
if(is_doc_channel) {
set_window_bscallback(window, bscallback);
async_start_doc_binding(window, bscallback);
hres = create_pending_window(window, bscallback);
if(SUCCEEDED(hres))
async_start_doc_binding(window, window->pending_window);
IUnknown_Release((IUnknown*)bscallback);
if(FAILED(hres))
return NS_ERROR_UNEXPECTED;
}else {
start_binding_task_t *task = heap_alloc(sizeof(start_binding_task_t));

View File

@ -370,9 +370,9 @@ HRESULT set_moniker(HTMLDocument *This, IMoniker *mon, IBindCtx *pibc, nsChannel
hres = load_nsuri(This->window, nsuri, bscallback, 0/*LOAD_INITIAL_DOCUMENT_URI*/);
nsISupports_Release((nsISupports*)nsuri); /* FIXME */
if(SUCCEEDED(hres))
set_window_bscallback(This->window, bscallback);
hres = create_pending_window(This->window, bscallback);
if(bscallback != async_bsc)
IUnknown_Release((IUnknown*)bscallback);
IUnknown_Release(&bscallback->bsc.IBindStatusCallback_iface);
}
if(FAILED(hres)) {
@ -538,7 +538,7 @@ static HRESULT WINAPI PersistMoniker_Load(IPersistMoniker *iface, BOOL fFullyAva
if(FAILED(hres))
return hres;
return start_binding(This->window, NULL, (BSCallback*)This->window->bscallback, pibc);
return start_binding(This->window, This->window->pending_window, (BSCallback*)This->window->pending_window->bscallback, pibc);
}
static HRESULT WINAPI PersistMoniker_Save(IPersistMoniker *iface, IMoniker *pimkName,
@ -810,7 +810,7 @@ static HRESULT WINAPI PersistStreamInit_Load(IPersistStreamInit *iface, LPSTREAM
if(FAILED(hres))
return hres;
return channelbsc_load_stream(This->window->bscallback, pStm);
return channelbsc_load_stream(This->window->pending_window, pStm);
}
static HRESULT WINAPI PersistStreamInit_Save(IPersistStreamInit *iface, LPSTREAM pStm,
@ -869,7 +869,7 @@ static HRESULT WINAPI PersistStreamInit_InitNew(IPersistStreamInit *iface)
if(FAILED(hres))
return hres;
return channelbsc_load_stream(This->window->bscallback, NULL);
return channelbsc_load_stream(This->window->pending_window, NULL);
}
static const IPersistStreamInitVtbl PersistStreamInitVtbl = {