Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
3ba9c760
Commit
3ba9c760
authored
Aug 26, 2022
by
Gabriel Ivăncescu
Committed by
Alexandre Julliard
Aug 27, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mshtml: Implement setItem() for sessionStorage.
Signed-off-by:
Gabriel Ivăncescu
<
gabrielopcode@gmail.com
>
parent
b3489305
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
270 additions
and
5 deletions
+270
-5
htmlstorage.c
dlls/mshtml/htmlstorage.c
+198
-4
main.c
dlls/mshtml/main.c
+1
-0
mshtml_private.h
dlls/mshtml/mshtml_private.h
+3
-0
task.c
dlls/mshtml/task.c
+1
-0
misc.c
dlls/mshtml/tests/misc.c
+67
-1
No files found.
dlls/mshtml/htmlstorage.c
View file @
3ba9c760
...
@@ -36,10 +36,134 @@ typedef struct {
...
@@ -36,10 +36,134 @@ typedef struct {
DispatchEx
dispex
;
DispatchEx
dispex
;
IHTMLStorage
IHTMLStorage_iface
;
IHTMLStorage
IHTMLStorage_iface
;
LONG
ref
;
LONG
ref
;
struct
session_map_entry
*
session_storage
;
WCHAR
*
filename
;
WCHAR
*
filename
;
HANDLE
mutex
;
HANDLE
mutex
;
}
HTMLStorage
;
}
HTMLStorage
;
struct
session_map_entry
{
struct
wine_rb_entry
entry
;
struct
wine_rb_tree
data_map
;
UINT
ref
;
UINT
num_keys
;
UINT
origin_len
;
WCHAR
origin
[
1
];
};
int
session_storage_map_cmp
(
const
void
*
key
,
const
struct
wine_rb_entry
*
entry
)
{
struct
session_map_entry
*
p
=
WINE_RB_ENTRY_VALUE
(
entry
,
struct
session_map_entry
,
entry
);
UINT
len
=
SysStringLen
((
BSTR
)
key
);
return
(
len
!=
p
->
origin_len
)
?
(
len
-
p
->
origin_len
)
:
memcmp
(
key
,
p
->
origin
,
len
*
sizeof
(
WCHAR
));
}
struct
session_entry
{
struct
wine_rb_entry
entry
;
BSTR
value
;
WCHAR
key
[
1
];
};
static
int
session_entry_cmp
(
const
void
*
key
,
const
struct
wine_rb_entry
*
entry
)
{
struct
session_entry
*
data
=
WINE_RB_ENTRY_VALUE
(
entry
,
struct
session_entry
,
entry
);
return
wcscmp
(
key
,
data
->
key
);
}
static
struct
session_map_entry
*
grab_session_map_entry
(
BSTR
origin
)
{
struct
session_map_entry
*
entry
;
struct
wine_rb_entry
*
rb_entry
;
thread_data_t
*
thread_data
;
UINT
origin_len
;
thread_data
=
get_thread_data
(
TRUE
);
if
(
!
thread_data
)
return
NULL
;
rb_entry
=
wine_rb_get
(
&
thread_data
->
session_storage_map
,
origin
);
if
(
rb_entry
)
{
entry
=
WINE_RB_ENTRY_VALUE
(
rb_entry
,
struct
session_map_entry
,
entry
);
entry
->
ref
++
;
return
entry
;
}
origin_len
=
SysStringLen
(
origin
);
entry
=
heap_alloc
(
FIELD_OFFSET
(
struct
session_map_entry
,
origin
[
origin_len
]));
if
(
!
entry
)
return
NULL
;
wine_rb_init
(
&
entry
->
data_map
,
session_entry_cmp
);
entry
->
ref
=
1
;
entry
->
num_keys
=
0
;
entry
->
origin_len
=
origin_len
;
memcpy
(
entry
->
origin
,
origin
,
origin_len
*
sizeof
(
WCHAR
));
wine_rb_put
(
&
thread_data
->
session_storage_map
,
origin
,
&
entry
->
entry
);
return
entry
;
}
static
void
release_session_map_entry
(
struct
session_map_entry
*
entry
)
{
if
(
!
entry
||
--
entry
->
ref
||
entry
->
num_keys
)
return
;
wine_rb_remove
(
&
get_thread_data
(
FALSE
)
->
session_storage_map
,
&
entry
->
entry
);
heap_free
(
entry
);
}
static
HRESULT
get_session_entry
(
struct
session_map_entry
*
entry
,
const
WCHAR
*
name
,
BOOL
create
,
struct
session_entry
**
ret
)
{
const
WCHAR
*
key
=
name
?
name
:
L""
;
struct
wine_rb_entry
*
rb_entry
;
struct
session_entry
*
data
;
UINT
key_len
;
rb_entry
=
wine_rb_get
(
&
entry
->
data_map
,
key
);
if
(
rb_entry
)
{
*
ret
=
WINE_RB_ENTRY_VALUE
(
rb_entry
,
struct
session_entry
,
entry
);
return
S_OK
;
}
if
(
!
create
)
{
*
ret
=
NULL
;
return
S_OK
;
}
key_len
=
wcslen
(
key
);
if
(
!
(
data
=
heap_alloc
(
FIELD_OFFSET
(
struct
session_entry
,
key
[
key_len
+
1
]))))
return
E_OUTOFMEMORY
;
data
->
value
=
NULL
;
memcpy
(
data
->
key
,
key
,
(
key_len
+
1
)
*
sizeof
(
WCHAR
));
entry
->
num_keys
++
;
wine_rb_put
(
&
entry
->
data_map
,
key
,
&
data
->
entry
);
*
ret
=
data
;
return
S_OK
;
}
static
void
clear_session_storage
(
struct
session_map_entry
*
entry
)
{
struct
session_entry
*
iter
,
*
iter2
;
WINE_RB_FOR_EACH_ENTRY_DESTRUCTOR
(
iter
,
iter2
,
&
entry
->
data_map
,
struct
session_entry
,
entry
)
{
SysFreeString
(
iter
->
value
);
heap_free
(
iter
);
}
wine_rb_destroy
(
&
entry
->
data_map
,
NULL
,
NULL
);
entry
->
num_keys
=
0
;
}
void
destroy_session_storage
(
thread_data_t
*
thread_data
)
{
struct
session_map_entry
*
iter
,
*
iter2
;
WINE_RB_FOR_EACH_ENTRY_DESTRUCTOR
(
iter
,
iter2
,
&
thread_data
->
session_storage_map
,
struct
session_map_entry
,
entry
)
{
clear_session_storage
(
iter
);
heap_free
(
iter
);
}
}
static
inline
HTMLStorage
*
impl_from_IHTMLStorage
(
IHTMLStorage
*
iface
)
static
inline
HTMLStorage
*
impl_from_IHTMLStorage
(
IHTMLStorage
*
iface
)
{
{
return
CONTAINING_RECORD
(
iface
,
HTMLStorage
,
IHTMLStorage_iface
);
return
CONTAINING_RECORD
(
iface
,
HTMLStorage
,
IHTMLStorage_iface
);
...
@@ -85,6 +209,7 @@ static ULONG WINAPI HTMLStorage_Release(IHTMLStorage *iface)
...
@@ -85,6 +209,7 @@ static ULONG WINAPI HTMLStorage_Release(IHTMLStorage *iface)
TRACE
(
"(%p) ref=%ld
\n
"
,
This
,
ref
);
TRACE
(
"(%p) ref=%ld
\n
"
,
This
,
ref
);
if
(
!
ref
)
{
if
(
!
ref
)
{
release_session_map_entry
(
This
->
session_storage
);
release_dispex
(
&
This
->
dispex
);
release_dispex
(
&
This
->
dispex
);
heap_free
(
This
->
filename
);
heap_free
(
This
->
filename
);
CloseHandle
(
This
->
mutex
);
CloseHandle
(
This
->
mutex
);
...
@@ -438,13 +563,24 @@ done:
...
@@ -438,13 +563,24 @@ done:
static
HRESULT
WINAPI
HTMLStorage_setItem
(
IHTMLStorage
*
iface
,
BSTR
bstrKey
,
BSTR
bstrValue
)
static
HRESULT
WINAPI
HTMLStorage_setItem
(
IHTMLStorage
*
iface
,
BSTR
bstrKey
,
BSTR
bstrValue
)
{
{
HTMLStorage
*
This
=
impl_from_IHTMLStorage
(
iface
);
HTMLStorage
*
This
=
impl_from_IHTMLStorage
(
iface
);
struct
session_entry
*
session_entry
;
HRESULT
hres
;
HRESULT
hres
;
TRACE
(
"(%p)->(%s %s)
\n
"
,
This
,
debugstr_w
(
bstrKey
),
debugstr_w
(
bstrValue
));
TRACE
(
"(%p)->(%s %s)
\n
"
,
This
,
debugstr_w
(
bstrKey
),
debugstr_w
(
bstrValue
));
if
(
!
This
->
filename
)
{
if
(
!
This
->
filename
)
{
FIXME
(
"session storage not supported
\n
"
);
BSTR
value
=
SysAllocString
(
bstrValue
?
bstrValue
:
L""
);
return
E_NOTIMPL
;
if
(
!
value
)
return
E_OUTOFMEMORY
;
hres
=
get_session_entry
(
This
->
session_storage
,
bstrKey
,
TRUE
,
&
session_entry
);
if
(
FAILED
(
hres
))
SysFreeString
(
value
);
else
{
SysFreeString
(
session_entry
->
value
);
session_entry
->
value
=
value
;
}
return
hres
;
}
}
WaitForSingleObject
(
This
->
mutex
,
INFINITE
);
WaitForSingleObject
(
This
->
mutex
,
INFINITE
);
...
@@ -548,6 +684,52 @@ static dispex_static_data_t HTMLStorage_dispex = {
...
@@ -548,6 +684,52 @@ static dispex_static_data_t HTMLStorage_dispex = {
HTMLStorage_iface_tids
HTMLStorage_iface_tids
};
};
static
HRESULT
build_session_origin
(
IUri
*
uri
,
BSTR
hostname
,
BSTR
*
ret
)
{
UINT
host_len
,
scheme_len
;
BSTR
scheme
,
origin
;
HRESULT
hres
;
hres
=
IUri_GetSchemeName
(
uri
,
&
scheme
);
if
(
FAILED
(
hres
))
return
hres
;
if
(
hres
!=
S_OK
)
{
SysFreeString
(
scheme
);
scheme
=
NULL
;
}
/* Since it's only used for lookup, we can apply transformations to
keep the lookup itself simple and fast. First, we convert `https`
to `http` because they are equal for lookup. Next, we place the
scheme after the hostname, separated by NUL, to compare the host
first, since it tends to differ more often. Lastly, we lowercase
the whole thing since lookup must be case-insensitive. */
scheme_len
=
SysStringLen
(
scheme
);
host_len
=
SysStringLen
(
hostname
);
if
(
scheme_len
==
5
&&
!
wcsicmp
(
scheme
,
L"https"
))
scheme_len
--
;
origin
=
SysAllocStringLen
(
NULL
,
host_len
+
1
+
scheme_len
);
if
(
origin
)
{
WCHAR
*
p
=
origin
;
memcpy
(
p
,
hostname
,
host_len
*
sizeof
(
WCHAR
));
p
+=
host_len
;
*
p
=
' '
;
/* for wcslwr */
memcpy
(
p
+
1
,
scheme
,
scheme_len
*
sizeof
(
WCHAR
));
p
[
1
+
scheme_len
]
=
'\0'
;
_wcslwr
(
origin
);
*
p
=
'\0'
;
}
SysFreeString
(
scheme
);
if
(
!
origin
)
return
E_OUTOFMEMORY
;
*
ret
=
origin
;
return
S_OK
;
}
static
WCHAR
*
build_filename
(
BSTR
hostname
)
static
WCHAR
*
build_filename
(
BSTR
hostname
)
{
{
static
const
WCHAR
store
[]
=
L"
\\
Microsoft
\\
Internet Explorer
\\
DOMStore
\\
"
;
static
const
WCHAR
store
[]
=
L"
\\
Microsoft
\\
Internet Explorer
\\
DOMStore
\\
"
;
...
@@ -593,8 +775,8 @@ static WCHAR *build_mutexname(const WCHAR *filename)
...
@@ -593,8 +775,8 @@ static WCHAR *build_mutexname(const WCHAR *filename)
HRESULT
create_html_storage
(
HTMLInnerWindow
*
window
,
BOOL
local
,
IHTMLStorage
**
p
)
HRESULT
create_html_storage
(
HTMLInnerWindow
*
window
,
BOOL
local
,
IHTMLStorage
**
p
)
{
{
IUri
*
uri
=
window
->
base
.
outer_window
->
uri
;
IUri
*
uri
=
window
->
base
.
outer_window
->
uri
;
BSTR
origin
,
hostname
=
NULL
;
HTMLStorage
*
storage
;
HTMLStorage
*
storage
;
BSTR
hostname
=
NULL
;
HRESULT
hres
;
HRESULT
hres
;
if
(
!
uri
)
if
(
!
uri
)
...
@@ -633,8 +815,20 @@ HRESULT create_html_storage(HTMLInnerWindow *window, BOOL local, IHTMLStorage **
...
@@ -633,8 +815,20 @@ HRESULT create_html_storage(HTMLInnerWindow *window, BOOL local, IHTMLStorage **
heap_free
(
storage
);
heap_free
(
storage
);
return
HRESULT_FROM_WIN32
(
GetLastError
());
return
HRESULT_FROM_WIN32
(
GetLastError
());
}
}
}
else
}
else
{
hres
=
build_session_origin
(
uri
,
hostname
,
&
origin
);
SysFreeString
(
hostname
);
SysFreeString
(
hostname
);
if
(
hres
!=
S_OK
)
{
heap_free
(
storage
);
return
hres
;
}
storage
->
session_storage
=
grab_session_map_entry
(
origin
);
SysFreeString
(
origin
);
if
(
!
storage
->
session_storage
)
{
heap_free
(
storage
);
return
E_OUTOFMEMORY
;
}
}
storage
->
IHTMLStorage_iface
.
lpVtbl
=
&
HTMLStorageVtbl
;
storage
->
IHTMLStorage_iface
.
lpVtbl
=
&
HTMLStorageVtbl
;
storage
->
ref
=
1
;
storage
->
ref
=
1
;
...
...
dlls/mshtml/main.c
View file @
3ba9c760
...
@@ -256,6 +256,7 @@ static void thread_detach(void)
...
@@ -256,6 +256,7 @@ static void thread_detach(void)
if
(
thread_data
->
thread_hwnd
)
if
(
thread_data
->
thread_hwnd
)
DestroyWindow
(
thread_data
->
thread_hwnd
);
DestroyWindow
(
thread_data
->
thread_hwnd
);
destroy_session_storage
(
thread_data
);
heap_free
(
thread_data
);
heap_free
(
thread_data
);
}
}
...
...
dlls/mshtml/mshtml_private.h
View file @
3ba9c760
...
@@ -1238,10 +1238,13 @@ typedef struct {
...
@@ -1238,10 +1238,13 @@ typedef struct {
HWND
thread_hwnd
;
HWND
thread_hwnd
;
struct
list
task_list
;
struct
list
task_list
;
struct
list
timer_list
;
struct
list
timer_list
;
struct
wine_rb_tree
session_storage_map
;
}
thread_data_t
;
}
thread_data_t
;
thread_data_t
*
get_thread_data
(
BOOL
)
DECLSPEC_HIDDEN
;
thread_data_t
*
get_thread_data
(
BOOL
)
DECLSPEC_HIDDEN
;
HWND
get_thread_hwnd
(
void
)
DECLSPEC_HIDDEN
;
HWND
get_thread_hwnd
(
void
)
DECLSPEC_HIDDEN
;
int
session_storage_map_cmp
(
const
void
*
,
const
struct
wine_rb_entry
*
)
DECLSPEC_HIDDEN
;
void
destroy_session_storage
(
thread_data_t
*
)
DECLSPEC_HIDDEN
;
LONG
get_task_target_magic
(
void
)
DECLSPEC_HIDDEN
;
LONG
get_task_target_magic
(
void
)
DECLSPEC_HIDDEN
;
HRESULT
push_task
(
task_t
*
,
task_proc_t
,
task_proc_t
,
LONG
)
DECLSPEC_HIDDEN
;
HRESULT
push_task
(
task_t
*
,
task_proc_t
,
task_proc_t
,
LONG
)
DECLSPEC_HIDDEN
;
...
...
dlls/mshtml/task.c
View file @
3ba9c760
...
@@ -416,6 +416,7 @@ thread_data_t *get_thread_data(BOOL create)
...
@@ -416,6 +416,7 @@ thread_data_t *get_thread_data(BOOL create)
TlsSetValue
(
mshtml_tls
,
thread_data
);
TlsSetValue
(
mshtml_tls
,
thread_data
);
list_init
(
&
thread_data
->
task_list
);
list_init
(
&
thread_data
->
task_list
);
list_init
(
&
thread_data
->
timer_list
);
list_init
(
&
thread_data
->
timer_list
);
wine_rb_init
(
&
thread_data
->
session_storage_map
,
session_storage_map_cmp
);
}
}
return
thread_data
;
return
thread_data
;
...
...
dlls/mshtml/tests/misc.c
View file @
3ba9c760
...
@@ -168,6 +168,31 @@ static HRESULT get_localstorage(IHTMLDocument2 *doc, IHTMLStorage **storage)
...
@@ -168,6 +168,31 @@ static HRESULT get_localstorage(IHTMLDocument2 *doc, IHTMLStorage **storage)
return
hres
;
return
hres
;
}
}
static
HRESULT
get_sessionstorage
(
IHTMLDocument2
*
doc
,
IHTMLStorage
**
storage
)
{
IHTMLWindow2
*
window
;
IHTMLWindow6
*
window6
;
HRESULT
hres
;
hres
=
IHTMLDocument2_get_parentWindow
(
doc
,
&
window
);
ok
(
hres
==
S_OK
,
"get_parentWindow failed: %08lx
\n
"
,
hres
);
ok
(
window
!=
NULL
,
"window == NULL
\n
"
);
hres
=
IHTMLWindow2_QueryInterface
(
window
,
&
IID_IHTMLWindow6
,
(
void
**
)
&
window6
);
IHTMLWindow2_Release
(
window
);
if
(
FAILED
(
hres
))
{
win_skip
(
"IHTMLWindow6 not supported
\n
"
);
return
hres
;
}
hres
=
IHTMLWindow6_get_sessionStorage
(
window6
,
storage
);
ok
(
hres
==
S_OK
,
"get_sessionStorage failed: %08lx
\n
"
,
hres
);
ok
(
*
storage
!=
NULL
,
"*storage == NULL
\n
"
);
IHTMLWindow6_Release
(
window6
);
return
hres
;
}
static
void
test_HTMLStorage
(
void
)
static
void
test_HTMLStorage
(
void
)
{
{
IHTMLDocument2
*
doc
,
*
doc2
;
IHTMLDocument2
*
doc
,
*
doc2
;
...
@@ -291,8 +316,49 @@ static void test_HTMLStorage(void)
...
@@ -291,8 +316,49 @@ static void test_HTMLStorage(void)
IHTMLStorage_Release
(
storage
);
IHTMLStorage_Release
(
storage
);
IHTMLStorage_Release
(
storage2
);
IHTMLStorage_Release
(
storage2
);
IHTMLDocument2_Release
(
doc
);
/* Session storage on same docs */
hres
=
get_sessionstorage
(
doc
,
&
storage
);
ok
(
hres
==
S_OK
,
"got %08lx
\n
"
,
hres
);
hres
=
get_sessionstorage
(
doc2
,
&
storage2
);
ok
(
hres
==
S_OK
,
"got %08lx
\n
"
,
hres
);
key
=
SysAllocString
(
L"undefined"
);
value
=
SysAllocString
(
L"null"
);
hres
=
IHTMLStorage_setItem
(
storage
,
key
,
value
);
ok
(
hres
==
S_OK
,
"setItem failed: %08lx
\n
"
,
hres
);
SysFreeString
(
value
);
SysFreeString
(
key
);
value
=
SysAllocString
(
L"asdf"
);
hres
=
IHTMLStorage_setItem
(
storage
,
NULL
,
value
);
ok
(
hres
==
S_OK
,
"setItem failed: %08lx
\n
"
,
hres
);
SysFreeString
(
value
);
key
=
SysAllocString
(
L"null-value"
);
hres
=
IHTMLStorage_setItem
(
storage
,
key
,
NULL
);
ok
(
hres
==
S_OK
,
"setItem failed: %08lx
\n
"
,
hres
);
SysFreeString
(
key
);
key
=
SysAllocString
(
L"aaaa"
);
value
=
SysAllocString
(
L"bbbb"
);
hres
=
IHTMLStorage_setItem
(
storage2
,
key
,
value
);
ok
(
hres
==
S_OK
,
"setItem failed: %08lx
\n
"
,
hres
);
SysFreeString
(
value
);
SysFreeString
(
key
);
key
=
SysAllocString
(
L"foo"
);
value
=
SysAllocString
(
L"bar"
);
hres
=
IHTMLStorage_setItem
(
storage
,
key
,
value
);
ok
(
hres
==
S_OK
,
"setItem failed: %08lx
\n
"
,
hres
);
SysFreeString
(
value
);
SysFreeString
(
key
);
IHTMLStorage_Release
(
storage2
);
IHTMLStorage_Release
(
storage
);
IHTMLDocument2_Release
(
doc2
);
IHTMLDocument2_Release
(
doc2
);
IHTMLDocument2_Release
(
doc
);
}
}
START_TEST
(
misc
)
START_TEST
(
misc
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment