mshtml: Allow task queue to be used for different targets.

This commit is contained in:
Jacek Caban 2009-10-26 23:05:10 +01:00 committed by Alexandre Julliard
parent fd47fa4647
commit 12bddc55ed
7 changed files with 167 additions and 164 deletions

View File

@ -1714,6 +1714,7 @@ static void init_doc(HTMLDocument *doc, IUnknown *unk_impl, IDispatchEx *dispex)
doc->unk_impl = unk_impl;
doc->dispex = dispex;
doc->task_magic = get_task_target_magic();
HTMLDocument_HTMLDocument3_Init(doc);
HTMLDocument_HTMLDocument5_Init(doc);
@ -1733,7 +1734,7 @@ static void init_doc(HTMLDocument *doc, IUnknown *unk_impl, IDispatchEx *dispex)
static void destroy_htmldoc(HTMLDocument *This)
{
remove_doc_tasks(This);
remove_target_tasks(This->task_magic);
ConnectionPointContainer_Destroy(&This->cp_container);
}

View File

@ -305,6 +305,8 @@ struct HTMLDocument {
HTMLWindow *window;
LONG task_magic;
ConnectionPointContainer cp_container;
ConnectionPoint cp_htmldocevents;
ConnectionPoint cp_htmldocevents2;
@ -671,6 +673,8 @@ HRESULT channelbsc_load_stream(nsChannelBSC*,IStream*);
void channelbsc_set_channel(nsChannelBSC*,nsChannel*,nsIStreamListener*,nsISupports*);
IMoniker *get_channelbsc_mon(nsChannelBSC*);
void parse_complete(HTMLDocumentObj*);
HRESULT HTMLSelectionObject_Create(HTMLDocumentNode*,nsISelection*,IHTMLSelectionObject**);
HRESULT HTMLTxtRange_Create(HTMLDocumentNode*,nsIDOMRange*,IHTMLTxtRange**);
IHTMLStyle *HTMLStyle_Create(nsIDOMCSSStyleDeclaration*);
@ -758,20 +762,19 @@ void set_dirty(HTMLDocument*,VARIANT_BOOL);
extern DWORD mshtml_tls;
typedef struct task_t {
HTMLDocument *doc;
enum {
TASK_SETDOWNLOADSTATE,
TASK_PARSECOMPLETE,
TASK_SETPROGRESS,
TASK_START_BINDING
} task_id;
nsChannelBSC *bscallback;
typedef struct task_t task_t;
typedef void (*task_proc_t)(task_t*);
struct task_t {
LONG target_magic;
task_proc_t proc;
struct task_t *next;
} task_t;
};
typedef struct {
task_t header;
HTMLDocumentObj *doc;
} docobj_task_t;
typedef struct {
HWND thread_hwnd;
@ -782,8 +785,11 @@ typedef struct {
thread_data_t *get_thread_data(BOOL);
HWND get_thread_hwnd(void);
void push_task(task_t*);
void remove_doc_tasks(const HTMLDocument*);
LONG get_task_target_magic(void);
void push_task(task_t*,task_proc_t,LONG);
void remove_target_tasks(LONG);
DWORD set_task_timer(HTMLDocument*,DWORD,BOOL,IDispatch*);
HRESULT clear_task_timer(HTMLDocument*,BOOL,DWORD);

View File

@ -472,6 +472,12 @@ static void NSAPI nsDocumentObserver_BeginLoad(nsIDocumentObserver *iface, nsIDo
{
}
static void parse_complete_proc(task_t *_task)
{
docobj_task_t *task = (docobj_task_t*)_task;
parse_complete(task->doc);
}
static void NSAPI nsDocumentObserver_EndLoad(nsIDocumentObserver *iface, nsIDocument *aDocument)
{
HTMLDocumentNode *This = NSDOCOBS_THIS(iface);
@ -481,18 +487,19 @@ static void NSAPI nsDocumentObserver_EndLoad(nsIDocumentObserver *iface, nsIDocu
This->content_ready = TRUE;
if(This == This->basedoc.doc_obj->basedoc.doc_node) {
task_t *task;
task = heap_alloc(sizeof(task_t));
docobj_task_t *task;
task->doc = &This->basedoc.doc_obj->basedoc;
task->task_id = TASK_PARSECOMPLETE;
task->next = NULL;
task = heap_alloc(sizeof(docobj_task_t));
if(!task)
return;
task->doc = This->basedoc.doc_obj;
/*
* This should be done in the worker thread that parses HTML,
* but we don't have such thread (Gecko parses HTML for us).
*/
push_task(task);
push_task(&task->header, &parse_complete_proc, This->basedoc.doc_obj->basedoc.task_magic);
}
}

View File

@ -724,12 +724,25 @@ static HTMLWindow *get_channel_window(nsChannel *This)
return window;
}
typedef struct {
task_t header;
HTMLDocument *doc;
nsChannelBSC *bscallback;
} start_binding_task_t;
static void start_binding_proc(task_t *_task)
{
start_binding_task_t *task = (start_binding_task_t*)_task;
start_binding(task->doc, (BSCallback*)task->bscallback, NULL);
}
static nsresult async_open(nsChannel *This, HTMLWindow *window, BOOL is_doc_channel, nsIStreamListener *listener,
nsISupports *context)
{
nsChannelBSC *bscallback;
IMoniker *mon = NULL;
task_t *task;
start_binding_task_t *task;
HRESULT hres;
hres = create_mon_for_nschannel(This, &mon);
@ -744,14 +757,12 @@ static nsresult async_open(nsChannel *This, HTMLWindow *window, BOOL is_doc_chan
channelbsc_set_channel(bscallback, This, listener, context);
task = heap_alloc(sizeof(task_t));
task = heap_alloc(sizeof(start_binding_task_t));
task->doc = &window->doc_obj->basedoc;
task->task_id = TASK_START_BINDING;
task->next = NULL;
task->bscallback = bscallback;
push_task(task);
push_task(&task->header, start_binding_proc, window->doc_obj->basedoc.task_magic);
return NS_OK;
}

View File

@ -590,7 +590,7 @@ static HRESULT exec_editmode(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in,
if(This->window->mon) {
/* FIXME: We should find nicer way to do this */
remove_doc_tasks(This);
remove_target_tasks(This->task_magic);
mon = This->window->mon;
IMoniker_AddRef(mon);

View File

@ -75,11 +75,88 @@ void set_current_mon(HTMLWindow *This, IMoniker *mon)
set_script_mode(This, use_gecko_script(This->url) ? SCRIPTMODE_GECKO : SCRIPTMODE_ACTIVESCRIPT);
}
static void set_progress_proc(task_t *_task)
{
docobj_task_t *task = (docobj_task_t*)_task;
IOleCommandTarget *olecmd = NULL;
HTMLDocumentObj *doc = task->doc;
HRESULT hres;
TRACE("(%p)\n", doc);
if(doc->client)
IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&olecmd);
if(olecmd) {
VARIANT progress_max, progress;
V_VT(&progress_max) = VT_I4;
V_I4(&progress_max) = 0; /* FIXME */
IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_SETPROGRESSMAX, OLECMDEXECOPT_DONTPROMPTUSER,
&progress_max, NULL);
V_VT(&progress) = VT_I4;
V_I4(&progress) = 0; /* FIXME */
IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_SETPROGRESSPOS, OLECMDEXECOPT_DONTPROMPTUSER,
&progress, NULL);
}
if(doc->usermode == EDITMODE && doc->hostui) {
DOCHOSTUIINFO hostinfo;
memset(&hostinfo, 0, sizeof(DOCHOSTUIINFO));
hostinfo.cbSize = sizeof(DOCHOSTUIINFO);
hres = IDocHostUIHandler_GetHostInfo(doc->hostui, &hostinfo);
if(SUCCEEDED(hres))
/* FIXME: use hostinfo */
TRACE("hostinfo = {%u %08x %08x %s %s}\n",
hostinfo.cbSize, hostinfo.dwFlags, hostinfo.dwDoubleClick,
debugstr_w(hostinfo.pchHostCss), debugstr_w(hostinfo.pchHostNS));
}
}
static void set_downloading_proc(task_t *_task)
{
HTMLDocumentObj *doc = ((docobj_task_t*)_task)->doc;
IOleCommandTarget *olecmd;
HRESULT hres;
TRACE("(%p)\n", doc);
if(doc->frame)
IOleInPlaceFrame_SetStatusText(doc->frame, NULL /* FIXME */);
if(!doc->client)
return;
hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&olecmd);
if(SUCCEEDED(hres)) {
VARIANT var;
V_VT(&var) = VT_I4;
V_I4(&var) = 1;
IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_SETDOWNLOADSTATE, OLECMDEXECOPT_DONTPROMPTUSER,
&var, NULL);
IOleCommandTarget_Release(olecmd);
}
if(doc->hostui) {
IDropTarget *drop_target = NULL;
hres = IDocHostUIHandler_GetDropTarget(doc->hostui, NULL /* FIXME */, &drop_target);
if(drop_target) {
FIXME("Use IDropTarget\n");
IDropTarget_Release(drop_target);
}
}
}
static HRESULT set_moniker(HTMLDocument *This, IMoniker *mon, IBindCtx *pibc, BOOL *bind_complete)
{
nsChannelBSC *bscallback;
LPOLESTR url = NULL;
task_t *task;
docobj_task_t *task;
HRESULT hres;
nsresult nsres;
@ -166,22 +243,14 @@ static HRESULT set_moniker(HTMLDocument *This, IMoniker *mon, IBindCtx *pibc, BO
bscallback = create_channelbsc(mon);
if(This->doc_obj->frame) {
task = heap_alloc(sizeof(task_t));
task->doc = This;
task->task_id = TASK_SETPROGRESS;
task->next = NULL;
push_task(task);
task = heap_alloc(sizeof(docobj_task_t));
task->doc = This->doc_obj;
push_task(&task->header, set_progress_proc, This->doc_obj->basedoc.task_magic);
}
task = heap_alloc(sizeof(task_t));
task->doc = This;
task->task_id = TASK_SETDOWNLOADSTATE;
task->next = NULL;
push_task(task);
task = heap_alloc(sizeof(docobj_task_t));
task->doc = This->doc_obj;
push_task(&task->header, set_downloading_proc, This->doc_obj->basedoc.task_magic);
if(This->doc_obj->nscontainer) {
This->doc_obj->nscontainer->bscallback = bscallback;

View File

@ -49,10 +49,14 @@ typedef struct {
struct list entry;
} task_timer_t;
void push_task(task_t *task)
void push_task(task_t *task, task_proc_t proc, LONG magic)
{
thread_data_t *thread_data = get_thread_data(TRUE);
task->target_magic = magic;
task->proc = proc;
task->next = NULL;
if(thread_data->task_queue_tail)
thread_data->task_queue_tail->next = task;
else
@ -87,7 +91,7 @@ static void release_task_timer(HWND thread_hwnd, task_timer_t *timer)
heap_free(timer);
}
void remove_doc_tasks(const HTMLDocument *doc)
void remove_target_tasks(LONG target)
{
thread_data_t *thread_data = get_thread_data(FALSE);
struct list *liter, *ltmp;
@ -99,7 +103,7 @@ void remove_doc_tasks(const HTMLDocument *doc)
LIST_FOR_EACH_SAFE(liter, ltmp, &thread_data->timer_list) {
timer = LIST_ENTRY(liter, task_timer_t, entry);
if(timer->doc == doc)
if(timer->doc->task_magic == target)
release_task_timer(thread_data->thread_hwnd, timer);
}
@ -109,11 +113,11 @@ void remove_doc_tasks(const HTMLDocument *doc)
}
while(thread_data->task_queue_head
&& thread_data->task_queue_head->doc == doc)
&& thread_data->task_queue_head->target_magic == target)
pop_task();
for(iter = thread_data->task_queue_head; iter; iter = iter->next) {
while(iter->next && iter->next->doc == doc) {
while(iter->next && iter->next->target_magic == target) {
tmp = iter->next;
iter->next = tmp->next;
heap_free(tmp);
@ -124,6 +128,12 @@ void remove_doc_tasks(const HTMLDocument *doc)
}
}
LONG get_task_target_magic(void)
{
static LONG magic = 0x10000000;
return InterlockedIncrement(&magic);
}
static BOOL queue_timer(thread_data_t *thread_data, task_timer_t *timer)
{
task_timer_t *iter;
@ -191,42 +201,6 @@ HRESULT clear_task_timer(HTMLDocument *doc, BOOL interval, DWORD id)
return S_OK;
}
static void set_downloading(HTMLDocumentObj *doc)
{
IOleCommandTarget *olecmd;
HRESULT hres;
TRACE("(%p)\n", doc);
if(doc->frame)
IOleInPlaceFrame_SetStatusText(doc->frame, NULL /* FIXME */);
if(!doc->client)
return;
hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&olecmd);
if(SUCCEEDED(hres)) {
VARIANT var;
V_VT(&var) = VT_I4;
V_I4(&var) = 1;
IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_SETDOWNLOADSTATE, OLECMDEXECOPT_DONTPROMPTUSER,
&var, NULL);
IOleCommandTarget_Release(olecmd);
}
if(doc->hostui) {
IDropTarget *drop_target = NULL;
hres = IDocHostUIHandler_GetDropTarget(doc->hostui, NULL /* FIXME */, &drop_target);
if(drop_target) {
FIXME("Use IDropTarget\n");
IDropTarget_Release(drop_target);
}
}
}
/* Calls undocumented 69 cmd of CGID_Explorer */
static void call_explorer_69(HTMLDocumentObj *doc)
{
@ -248,26 +222,26 @@ static void call_explorer_69(HTMLDocumentObj *doc)
FIXME("handle result\n");
}
static void set_parsecomplete(HTMLDocument *doc)
void parse_complete(HTMLDocumentObj *doc)
{
IOleCommandTarget *olecmd = NULL;
TRACE("(%p)\n", doc);
if(doc->doc_obj->usermode == EDITMODE)
init_editor(doc);
if(doc->usermode == EDITMODE)
init_editor(&doc->basedoc);
call_explorer_69(doc->doc_obj);
call_property_onchanged(&doc->cp_propnotif, 1005);
call_explorer_69(doc->doc_obj);
call_explorer_69(doc);
call_property_onchanged(&doc->basedoc.cp_propnotif, 1005);
call_explorer_69(doc);
/* FIXME: IE7 calls EnableModelless(TRUE), EnableModelless(FALSE) and sets interactive state here */
doc->doc_obj->readystate = READYSTATE_INTERACTIVE;
call_property_onchanged(&doc->cp_propnotif, DISPID_READYSTATE);
doc->readystate = READYSTATE_INTERACTIVE;
call_property_onchanged(&doc->basedoc.cp_propnotif, DISPID_READYSTATE);
if(doc->doc_obj->client)
IOleClientSite_QueryInterface(doc->doc_obj->client, &IID_IOleCommandTarget, (void**)&olecmd);
if(doc->client)
IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&olecmd);
if(olecmd) {
VARIANT state, progress;
@ -289,80 +263,15 @@ static void set_parsecomplete(HTMLDocument *doc)
IOleCommandTarget_Release(olecmd);
}
doc->doc_obj->readystate = READYSTATE_COMPLETE;
call_property_onchanged(&doc->cp_propnotif, DISPID_READYSTATE);
doc->readystate = READYSTATE_COMPLETE;
call_property_onchanged(&doc->basedoc.cp_propnotif, DISPID_READYSTATE);
if(doc->doc_obj->frame) {
if(doc->frame) {
static const WCHAR wszDone[] = {'D','o','n','e',0};
IOleInPlaceFrame_SetStatusText(doc->doc_obj->frame, wszDone);
IOleInPlaceFrame_SetStatusText(doc->frame, wszDone);
}
update_title(doc->doc_obj);
}
static void set_progress(HTMLDocument *doc)
{
IOleCommandTarget *olecmd = NULL;
HRESULT hres;
TRACE("(%p)\n", doc);
if(doc->doc_obj->client)
IOleClientSite_QueryInterface(doc->doc_obj->client, &IID_IOleCommandTarget, (void**)&olecmd);
if(olecmd) {
VARIANT progress_max, progress;
V_VT(&progress_max) = VT_I4;
V_I4(&progress_max) = 0; /* FIXME */
IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_SETPROGRESSMAX, OLECMDEXECOPT_DONTPROMPTUSER,
&progress_max, NULL);
V_VT(&progress) = VT_I4;
V_I4(&progress) = 0; /* FIXME */
IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_SETPROGRESSPOS, OLECMDEXECOPT_DONTPROMPTUSER,
&progress, NULL);
}
if(doc->doc_obj->usermode == EDITMODE && doc->doc_obj->hostui) {
DOCHOSTUIINFO hostinfo;
memset(&hostinfo, 0, sizeof(DOCHOSTUIINFO));
hostinfo.cbSize = sizeof(DOCHOSTUIINFO);
hres = IDocHostUIHandler_GetHostInfo(doc->doc_obj->hostui, &hostinfo);
if(SUCCEEDED(hres))
/* FIXME: use hostinfo */
TRACE("hostinfo = {%u %08x %08x %s %s}\n",
hostinfo.cbSize, hostinfo.dwFlags, hostinfo.dwDoubleClick,
debugstr_w(hostinfo.pchHostCss), debugstr_w(hostinfo.pchHostNS));
}
}
static void task_start_binding(HTMLDocument *doc, BSCallback *bscallback)
{
if(doc)
start_binding(doc, bscallback, NULL);
IUnknown_Release((IUnknown*)bscallback);
}
static void process_task(task_t *task)
{
switch(task->task_id) {
case TASK_SETDOWNLOADSTATE:
set_downloading(task->doc->doc_obj);
break;
case TASK_PARSECOMPLETE:
set_parsecomplete(task->doc);
break;
case TASK_SETPROGRESS:
set_progress(task->doc);
break;
case TASK_START_BINDING:
task_start_binding(task->doc, (BSCallback*)task->bscallback);
break;
default:
ERR("Wrong task_id %d\n", task->task_id);
}
update_title(doc);
}
static void call_timer_disp(IDispatch *disp)
@ -433,7 +342,7 @@ static LRESULT WINAPI hidden_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa
if(!task)
break;
process_task(task);
task->proc(task);
heap_free(task);
}