mshtml: Create inner window early in binding process and use it to store current binding callback.
diff --git a/dlls/mshtml/binding.h b/dlls/mshtml/binding.h
index 7e3b6d3..2970849 100644
--- a/dlls/mshtml/binding.h
+++ b/dlls/mshtml/binding.h
@@ -111,7 +111,7 @@
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;
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c
index d448614..0ced93d 100644
--- a/dlls/mshtml/htmlwindow.c
+++ b/dlls/mshtml/htmlwindow.c
@@ -197,8 +197,13 @@
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 @@
{
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 @@
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 @@
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 @@
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 @@
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 @@
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);
}
- nsIDOMHTMLDocument_Release(nshtmldoc);
+ 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);
+ }
+
return hres;
}
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index b63ad53..f0dde6c 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -326,7 +326,7 @@
HTMLFrameBase *frame_element;
READYSTATE readystate;
- nsChannelBSC *bscallback;
+ HTMLInnerWindow *pending_window;
IMoniker *mon;
IUri *uri;
BSTR url;
@@ -361,6 +361,7 @@
DWORD global_prop_cnt;
DWORD global_prop_size;
+ nsChannelBSC *bscallback;
struct list bindings;
};
@@ -665,7 +666,7 @@
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 @@
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;
diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c
index c07fd90..1fe4f9d 100644
--- a/dlls/mshtml/navigate.c
+++ b/dlls/mshtml/navigate.c
@@ -725,8 +725,6 @@
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 @@
}
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 @@
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 @@
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 @@
void abort_window_bindings(HTMLInnerWindow *window)
{
- BSCallback *iter, *next;
+ BSCallback *iter;
- LIST_FOR_EACH_ENTRY_SAFE(iter, next, &window->bindings, BSCallback, entry) {
+ while(!list_empty(&window->bindings)) {
+ iter = LIST_ENTRY(window->bindings.next, 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 @@
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 @@
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 @@
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 @@
}else {
navigate_javascript_task_t *task;
- IUnknown_Release((IUnknown*)bsc);
+ IBindStatusCallback_Release(&bsc->bsc.IBindStatusCallback_iface);
IMoniker_Release(mon);
task = heap_alloc(sizeof(*task));
diff --git a/dlls/mshtml/nsio.c b/dlls/mshtml/nsio.c
index e177390..0a8a124 100644
--- a/dlls/mshtml/nsio.c
+++ b/dlls/mshtml/nsio.c
@@ -1016,9 +1016,12 @@
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));
diff --git a/dlls/mshtml/persist.c b/dlls/mshtml/persist.c
index cb148c4..6f62c1b 100644
--- a/dlls/mshtml/persist.c
+++ b/dlls/mshtml/persist.c
@@ -370,9 +370,9 @@
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 @@
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 @@
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 @@
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 = {