Commit 720c671d authored by Gabriel Ivăncescu's avatar Gabriel Ivăncescu Committed by Alexandre Julliard

mshtml: Implement StorageEvent and send it when clearing the storage.

parent 1cfbcab7
......@@ -3423,30 +3423,38 @@ static HRESULT WINAPI HTMLDocument6_get_onstorage(IHTMLDocument6 *iface,
VARIANT *p)
{
HTMLDocument *This = impl_from_IHTMLDocument6(iface);
FIXME("(%p)->(%p)\n", This, p);
return E_NOTIMPL;
TRACE("(%p)->(%p)\n", This, p);
return get_doc_event(This, EVENTID_STORAGE, p);
}
static HRESULT WINAPI HTMLDocument6_put_onstorage(IHTMLDocument6 *iface, VARIANT v)
{
HTMLDocument *This = impl_from_IHTMLDocument6(iface);
FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
return E_NOTIMPL;
TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
return set_doc_event(This, EVENTID_STORAGE, &v);
}
static HRESULT WINAPI HTMLDocument6_get_onstoragecommit(IHTMLDocument6 *iface,
VARIANT *p)
{
HTMLDocument *This = impl_from_IHTMLDocument6(iface);
FIXME("(%p)->(%p)\n", This, p);
return E_NOTIMPL;
TRACE("(%p)->(%p)\n", This, p);
return get_doc_event(This, EVENTID_STORAGECOMMIT, p);
}
static HRESULT WINAPI HTMLDocument6_put_onstoragecommit(IHTMLDocument6 *iface, VARIANT v)
{
HTMLDocument *This = impl_from_IHTMLDocument6(iface);
FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
return E_NOTIMPL;
TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
return set_doc_event(This, EVENTID_STORAGECOMMIT, &v);
}
static HRESULT WINAPI HTMLDocument6_getElementById(IHTMLDocument6 *iface,
......
......@@ -191,6 +191,10 @@ static const event_info_t event_info[] = {
EVENT_FIXME},
{L"selectstart", EVENT_TYPE_EVENT, DISPID_EVMETH_ONSELECTSTART,
EVENT_FIXME | EVENT_BUBBLES | EVENT_CANCELABLE},
{L"storage", EVENT_TYPE_EVENT, DISPID_EVMETH_ONSTORAGE,
0},
{L"storagecommit", EVENT_TYPE_EVENT, DISPID_EVMETH_ONSTORAGECOMMIT,
0},
{L"submit", EVENT_TYPE_EVENT, DISPID_EVMETH_ONSUBMIT,
EVENT_DEFAULTLISTENER | EVENT_HASDEFAULTHANDLERS | EVENT_BUBBLES | EVENT_CANCELABLE},
{L"timeout", EVENT_TYPE_PROGRESS, DISPID_EVPROP_TIMEOUT,
......@@ -2606,6 +2610,164 @@ static void DOMProgressEvent_destroy(DOMEvent *event)
nsIDOMProgressEvent_Release(This->nsevent);
}
typedef struct {
DOMEvent event;
IDOMStorageEvent IDOMStorageEvent_iface;
BSTR key;
BSTR old_value;
BSTR new_value;
} DOMStorageEvent;
static inline DOMStorageEvent *impl_from_IDOMStorageEvent(IDOMStorageEvent *iface)
{
return CONTAINING_RECORD(iface, DOMStorageEvent, IDOMStorageEvent_iface);
}
static HRESULT WINAPI DOMStorageEvent_QueryInterface(IDOMStorageEvent *iface, REFIID riid, void **ppv)
{
DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
return IDOMEvent_QueryInterface(&This->event.IDOMEvent_iface, riid, ppv);
}
static ULONG WINAPI DOMStorageEvent_AddRef(IDOMStorageEvent *iface)
{
DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
return IDOMEvent_AddRef(&This->event.IDOMEvent_iface);
}
static ULONG WINAPI DOMStorageEvent_Release(IDOMStorageEvent *iface)
{
DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
return IDOMEvent_Release(&This->event.IDOMEvent_iface);
}
static HRESULT WINAPI DOMStorageEvent_GetTypeInfoCount(IDOMStorageEvent *iface, UINT *pctinfo)
{
DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
return IDispatchEx_GetTypeInfoCount(&This->event.dispex.IDispatchEx_iface, pctinfo);
}
static HRESULT WINAPI DOMStorageEvent_GetTypeInfo(IDOMStorageEvent *iface, UINT iTInfo,
LCID lcid, ITypeInfo **ppTInfo)
{
DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
return IDispatchEx_GetTypeInfo(&This->event.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
}
static HRESULT WINAPI DOMStorageEvent_GetIDsOfNames(IDOMStorageEvent *iface, REFIID riid,
LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
{
DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
return IDispatchEx_GetIDsOfNames(&This->event.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
lcid, rgDispId);
}
static HRESULT WINAPI DOMStorageEvent_Invoke(IDOMStorageEvent *iface, DISPID dispIdMember,
REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
return IDispatchEx_Invoke(&This->event.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
}
static HRESULT WINAPI DOMStorageEvent_get_key(IDOMStorageEvent *iface, BSTR *p)
{
DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
TRACE("(%p)->(%p)\n", This, p);
if(This->key)
return (*p = SysAllocStringLen(This->key, SysStringLen(This->key))) ? S_OK : E_OUTOFMEMORY;
*p = NULL;
return S_OK;
}
static HRESULT WINAPI DOMStorageEvent_get_oldValue(IDOMStorageEvent *iface, BSTR *p)
{
DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
TRACE("(%p)->(%p)\n", This, p);
if(This->old_value)
return (*p = SysAllocStringLen(This->old_value, SysStringLen(This->old_value))) ? S_OK : E_OUTOFMEMORY;
*p = NULL;
return S_OK;
}
static HRESULT WINAPI DOMStorageEvent_get_newValue(IDOMStorageEvent *iface, BSTR *p)
{
DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
TRACE("(%p)->(%p)\n", This, p);
if(This->new_value)
return (*p = SysAllocStringLen(This->new_value, SysStringLen(This->new_value))) ? S_OK : E_OUTOFMEMORY;
*p = NULL;
return S_OK;
}
static HRESULT WINAPI DOMStorageEvent_get_url(IDOMStorageEvent *iface, BSTR *p)
{
DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
FIXME("(%p)->(%p)\n", This, p);
return E_NOTIMPL;
}
static HRESULT WINAPI DOMStorageEvent_get_storageArea(IDOMStorageEvent *iface, IHTMLStorage **p)
{
DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
FIXME("(%p)->(%p)\n", This, p);
return E_NOTIMPL;
}
static HRESULT WINAPI DOMStorageEvent_initStorageEvent(IDOMStorageEvent *iface, BSTR type, VARIANT_BOOL can_bubble,
VARIANT_BOOL cancelable, BSTR keyArg, BSTR oldValueArg,
BSTR newValueArg, BSTR urlArg, IHTMLStorage *storageAreaArg)
{
DOMStorageEvent *This = impl_from_IDOMStorageEvent(iface);
FIXME("(%p)->(%s %x %x %s %s %s %s %p)\n", This, debugstr_w(type), can_bubble, cancelable,
debugstr_w(keyArg), debugstr_w(oldValueArg), debugstr_w(newValueArg), debugstr_w(urlArg), storageAreaArg);
return E_NOTIMPL;
}
static const IDOMStorageEventVtbl DOMStorageEventVtbl = {
DOMStorageEvent_QueryInterface,
DOMStorageEvent_AddRef,
DOMStorageEvent_Release,
DOMStorageEvent_GetTypeInfoCount,
DOMStorageEvent_GetTypeInfo,
DOMStorageEvent_GetIDsOfNames,
DOMStorageEvent_Invoke,
DOMStorageEvent_get_key,
DOMStorageEvent_get_oldValue,
DOMStorageEvent_get_newValue,
DOMStorageEvent_get_url,
DOMStorageEvent_get_storageArea,
DOMStorageEvent_initStorageEvent
};
static DOMStorageEvent *DOMStorageEvent_from_DOMEvent(DOMEvent *event)
{
return CONTAINING_RECORD(event, DOMStorageEvent, event);
}
static void *DOMStorageEvent_query_interface(DOMEvent *event, REFIID riid)
{
DOMStorageEvent *storage_event = DOMStorageEvent_from_DOMEvent(event);
if(IsEqualGUID(&IID_IDOMStorageEvent, riid))
return &storage_event->IDOMStorageEvent_iface;
return NULL;
}
static void DOMStorageEvent_destroy(DOMEvent *event)
{
DOMStorageEvent *storage_event = DOMStorageEvent_from_DOMEvent(event);
SysFreeString(storage_event->key);
SysFreeString(storage_event->old_value);
SysFreeString(storage_event->new_value);
}
static const tid_t DOMEvent_iface_tids[] = {
IDOMEvent_tid,
0
......@@ -2698,6 +2860,19 @@ dispex_static_data_t DOMProgressEvent_dispex = {
DOMProgressEvent_iface_tids
};
static const tid_t DOMStorageEvent_iface_tids[] = {
IDOMEvent_tid,
IDOMStorageEvent_tid,
0
};
dispex_static_data_t DOMStorageEvent_dispex = {
L"StorageEvent",
NULL,
DispDOMStorageEvent_tid,
DOMStorageEvent_iface_tids
};
static void *event_ctor(unsigned size, dispex_static_data_t *dispex_data, void *(*query_interface)(DOMEvent*,REFIID),
void (*destroy)(DOMEvent*), nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
{
......@@ -2799,6 +2974,15 @@ static DOMEvent *message_event_ctor(nsIDOMEvent *nsevent, eventid_t event_id, co
return &message_event->event;
}
static DOMEvent *storage_event_ctor(nsIDOMEvent *nsevent, eventid_t event_id, compat_mode_t compat_mode)
{
DOMStorageEvent *storage_event = event_ctor(sizeof(DOMStorageEvent), &DOMStorageEvent_dispex,
DOMStorageEvent_query_interface, DOMStorageEvent_destroy, nsevent, event_id, compat_mode);
if(!storage_event) return NULL;
storage_event->IDOMStorageEvent_iface.lpVtbl = &DOMStorageEventVtbl;
return &storage_event->event;
}
static DOMEvent *alloc_event(nsIDOMEvent *nsevent, compat_mode_t compat_mode, eventid_t event_id)
{
static const struct {
......@@ -2814,8 +2998,12 @@ static DOMEvent *alloc_event(nsIDOMEvent *nsevent, compat_mode_t compat_mode, ev
DOMEvent *event;
unsigned i;
if(event_id == EVENTID_MESSAGE)
return message_event_ctor(nsevent, event_id, compat_mode);
switch(event_id) {
case EVENTID_MESSAGE: return message_event_ctor(nsevent, event_id, compat_mode);
case EVENTID_STORAGECOMMIT:
case EVENTID_STORAGE: return storage_event_ctor(nsevent, event_id, compat_mode);
default: break;
}
for(i = 0; i < ARRAY_SIZE(types_table); i++) {
void *iface;
......@@ -2931,6 +3119,31 @@ HRESULT create_message_event(HTMLDocumentNode *doc, VARIANT *data, DOMEvent **re
return S_OK;
}
HRESULT create_storage_event(HTMLDocumentNode *doc, BSTR key, BSTR old_value, BSTR new_value,
BOOL commit, DOMEvent **ret)
{
DOMStorageEvent *storage_event;
DOMEvent *event;
HRESULT hres;
hres = create_document_event(doc, commit ? EVENTID_STORAGECOMMIT : EVENTID_STORAGE, &event);
if(FAILED(hres))
return hres;
storage_event = DOMStorageEvent_from_DOMEvent(event);
if(!commit) {
if((key && !(storage_event->key = SysAllocString(key))) ||
(old_value && !(storage_event->old_value = SysAllocString(old_value))) ||
(new_value && !(storage_event->new_value = SysAllocString(new_value)))) {
IDOMEvent_Release(&event->IDOMEvent_iface);
return E_OUTOFMEMORY;
}
}
*ret = event;
return S_OK;
}
static HRESULT call_disp_func(IDispatch *disp, DISPPARAMS *dp, VARIANT *retv)
{
IDispatchEx *dispex;
......
......@@ -58,6 +58,8 @@ typedef enum {
EVENTID_SCROLL,
EVENTID_SELECTIONCHANGE,
EVENTID_SELECTSTART,
EVENTID_STORAGE,
EVENTID_STORAGECOMMIT,
EVENTID_SUBMIT,
EVENTID_TIMEOUT,
EVENTID_UNLOAD,
......@@ -112,6 +114,7 @@ HRESULT create_document_event(HTMLDocumentNode*,eventid_t,DOMEvent**) DECLSPEC_H
HRESULT create_document_event_str(HTMLDocumentNode*,const WCHAR*,IDOMEvent**) DECLSPEC_HIDDEN;
HRESULT create_event_from_nsevent(nsIDOMEvent*,compat_mode_t,DOMEvent**) DECLSPEC_HIDDEN;
HRESULT create_message_event(HTMLDocumentNode*,VARIANT*,DOMEvent**) DECLSPEC_HIDDEN;
HRESULT create_storage_event(HTMLDocumentNode*,BSTR,BSTR,BSTR,BOOL,DOMEvent**) DECLSPEC_HIDDEN;
void init_nsevents(HTMLDocumentNode*) DECLSPEC_HIDDEN;
void release_nsevents(HTMLDocumentNode*) DECLSPEC_HIDDEN;
......
......@@ -29,6 +29,7 @@
#include "wine/debug.h"
#include "mshtml_private.h"
#include "htmlevent.h"
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
......@@ -41,6 +42,7 @@ typedef struct {
LONG ref;
unsigned num_props;
BSTR *props;
HTMLInnerWindow *window;
struct session_map_entry *session_storage;
WCHAR *filename;
HANDLE mutex;
......@@ -195,6 +197,65 @@ static inline HTMLStorage *impl_from_IHTMLStorage(IHTMLStorage *iface)
return CONTAINING_RECORD(iface, HTMLStorage, IHTMLStorage_iface);
}
struct storage_event_task {
task_t header;
HTMLInnerWindow *window;
DOMEvent *event;
};
static void storage_event_proc(task_t *_task)
{
struct storage_event_task *task = (struct storage_event_task*)_task;
HTMLInnerWindow *window = task->window;
DOMEvent *event = task->event;
VARIANT_BOOL cancelled;
if(event->event_id == EVENTID_STORAGE && dispex_compat_mode(&window->event_target.dispex) >= COMPAT_MODE_IE9) {
dispatch_event(&window->event_target, event);
if(window->doc)
fire_event(&window->doc->node, L"onstorage", NULL, &cancelled);
}else if(window->doc) {
dispatch_event(&window->doc->node.event_target, event);
}
}
static void storage_event_destr(task_t *_task)
{
struct storage_event_task *task = (struct storage_event_task*)_task;
IDOMEvent_Release(&task->event->IDOMEvent_iface);
IHTMLWindow2_Release(&task->window->base.IHTMLWindow2_iface);
}
/* Takes ownership of old_value */
static HRESULT send_storage_event(HTMLStorage *storage, BSTR key, BSTR old_value, BSTR new_value)
{
HTMLInnerWindow *window = storage->window;
BOOL local = !!storage->filename;
struct storage_event_task *task;
DOMEvent *event;
HRESULT hres;
if(!window) {
SysFreeString(old_value);
return S_OK;
}
hres = create_storage_event(window->doc, key, old_value, new_value, local, &event);
SysFreeString(old_value);
if(FAILED(hres))
return hres;
if(!(task = heap_alloc(sizeof(*task)))) {
IDOMEvent_Release(&event->IDOMEvent_iface);
return E_OUTOFMEMORY;
}
task->event = event;
task->window = window;
IHTMLWindow2_AddRef(&task->window->base.IHTMLWindow2_iface);
return push_task(&task->header, storage_event_proc, storage_event_destr, window->task_magic);
}
static HRESULT WINAPI HTMLStorage_QueryInterface(IHTMLStorage *iface, REFIID riid, void **ppv)
{
HTMLStorage *This = impl_from_IHTMLStorage(iface);
......@@ -817,8 +878,9 @@ static HRESULT WINAPI HTMLStorage_clear(IHTMLStorage *iface)
HRESULT hres = S_OK;
if(!This->filename) {
UINT num_keys = This->session_storage->num_keys;
clear_session_storage(This->session_storage);
return S_OK;
return num_keys ? send_storage_event(This, NULL, NULL, NULL) : S_OK;
}
WaitForSingleObject(This->mutex, INFINITE);
......@@ -828,6 +890,8 @@ static HRESULT WINAPI HTMLStorage_clear(IHTMLStorage *iface)
hres = HRESULT_FROM_WIN32(error);
}
ReleaseMutex(This->mutex);
if(hres == S_OK)
hres = send_storage_event(This, NULL, NULL, NULL);
return hres;
}
......@@ -1266,9 +1330,17 @@ HRESULT create_html_storage(HTMLInnerWindow *window, BOOL local, IHTMLStorage **
storage->IHTMLStorage_iface.lpVtbl = &HTMLStorageVtbl;
storage->ref = 1;
storage->window = window;
init_dispatch(&storage->dispex, (IUnknown*)&storage->IHTMLStorage_iface, &HTMLStorage_dispex,
dispex_compat_mode(&window->event_target.dispex));
*p = &storage->IHTMLStorage_iface;
return S_OK;
}
void detach_html_storage(IHTMLStorage *iface)
{
HTMLStorage *storage = impl_from_IHTMLStorage(iface);
storage->window = NULL;
}
......@@ -299,10 +299,14 @@ static void release_inner_window(HTMLInnerWindow *This)
if(This->navigator)
IOmNavigator_Release(This->navigator);
if(This->session_storage)
if(This->session_storage) {
detach_html_storage(This->session_storage);
IHTMLStorage_Release(This->session_storage);
if(This->local_storage)
}
if(This->local_storage) {
detach_html_storage(This->local_storage);
IHTMLStorage_Release(This->local_storage);
}
if(This->mon)
IMoniker_Release(This->mon);
......@@ -2613,7 +2617,7 @@ HTMLWINDOW7_ONEVENT_PROPERTY_STUB(seeked)
HTMLWINDOW7_ONEVENT_PROPERTY_STUB(seeking)
HTMLWINDOW7_ONEVENT_PROPERTY_STUB(select)
HTMLWINDOW7_ONEVENT_PROPERTY_STUB(stalled)
HTMLWINDOW7_ONEVENT_PROPERTY_STUB(storage)
HTMLWINDOW7_ONEVENT_PROPERTY_IMPL(storage, EVENTID_STORAGE)
HTMLWINDOW7_ONEVENT_PROPERTY_IMPL(submit, EVENTID_SUBMIT)
HTMLWINDOW7_ONEVENT_PROPERTY_STUB(suspend)
HTMLWINDOW7_ONEVENT_PROPERTY_STUB(timeupdate)
......
......@@ -91,6 +91,7 @@ typedef struct EventTarget EventTarget;
XDIID(DispDOMMessageEvent) \
XDIID(DispDOMMouseEvent) \
XDIID(DispDOMProgressEvent) \
XDIID(DispDOMStorageEvent) \
XDIID(DispDOMUIEvent) \
XDIID(DispDOMDocumentType) \
XDIID(DispHTMLAnchorElement) \
......@@ -154,6 +155,7 @@ typedef struct EventTarget EventTarget;
XIID(IDOMMessageEvent) \
XIID(IDOMMouseEvent) \
XIID(IDOMProgressEvent) \
XIID(IDOMStorageEvent) \
XIID(IDOMUIEvent) \
XIID(IDOMDocumentType) \
XIID(IDocumentEvent) \
......@@ -956,6 +958,7 @@ HRESULT create_dom_implementation(HTMLDocumentNode*,IHTMLDOMImplementation**) DE
void detach_dom_implementation(IHTMLDOMImplementation*) DECLSPEC_HIDDEN;
HRESULT create_html_storage(HTMLInnerWindow*,BOOL,IHTMLStorage**) DECLSPEC_HIDDEN;
void detach_html_storage(IHTMLStorage*) DECLSPEC_HIDDEN;
void HTMLDocument_Persist_Init(HTMLDocument*) DECLSPEC_HIDDEN;
void HTMLDocument_OleCmd_Init(HTMLDocument*) DECLSPEC_HIDDEN;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment