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
22214ec3
Commit
22214ec3
authored
Feb 05, 2024
by
Gabriel Ivăncescu
Committed by
Alexandre Julliard
Feb 05, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mshtml: Use a hook to implement postMessage.
We need the caller ServiceProvider to obtain the source. Signed-off-by:
Gabriel Ivăncescu
<
gabrielopcode@gmail.com
>
parent
7c7544ab
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
211 additions
and
164 deletions
+211
-164
htmlwindow.c
dlls/mshtml/htmlwindow.c
+211
-162
mshtml_private_iface.idl
dlls/mshtml/mshtml_private_iface.idl
+0
-2
No files found.
dlls/mshtml/htmlwindow.c
View file @
22214ec3
...
...
@@ -2234,6 +2234,87 @@ static HRESULT WINAPI HTMLWindow6_get_maxConnectionsPerServer(IHTMLWindow6 *ifac
return
E_NOTIMPL
;
}
static
HRESULT
check_target_origin
(
HTMLInnerWindow
*
window
,
const
WCHAR
*
target_origin
)
{
BOOL
no_port
=
FALSE
;
IUri
*
uri
,
*
target
;
DWORD
port
,
port2
;
BSTR
bstr
,
bstr2
;
HRESULT
hres
;
if
(
!
target_origin
)
return
E_INVALIDARG
;
if
(
!
wcscmp
(
target_origin
,
L"*"
))
return
S_OK
;
hres
=
create_uri
(
target_origin
,
Uri_CREATE_NOFRAG
|
Uri_CREATE_NO_DECODE_EXTRA_INFO
,
&
target
);
if
(
FAILED
(
hres
))
return
hres
;
if
(
!
(
uri
=
window
->
base
.
outer_window
->
uri
))
{
FIXME
(
"window with no URI
\n
"
);
hres
=
S_FALSE
;
goto
done
;
}
bstr
=
NULL
;
hres
=
IUri_GetSchemeName
(
uri
,
&
bstr
);
if
(
hres
!=
S_OK
)
{
SysFreeString
(
bstr
);
goto
done
;
}
hres
=
IUri_GetSchemeName
(
target
,
&
bstr2
);
if
(
SUCCEEDED
(
hres
))
{
if
(
hres
==
S_OK
&&
wcsicmp
(
bstr
,
bstr2
))
hres
=
S_FALSE
;
SysFreeString
(
bstr2
);
}
SysFreeString
(
bstr
);
if
(
hres
!=
S_OK
)
goto
done
;
bstr
=
NULL
;
hres
=
IUri_GetHost
(
uri
,
&
bstr
);
if
(
hres
!=
S_OK
)
{
SysFreeString
(
bstr
);
goto
done
;
}
hres
=
IUri_GetHost
(
target
,
&
bstr2
);
if
(
SUCCEEDED
(
hres
))
{
if
(
hres
==
S_OK
&&
wcsicmp
(
bstr
,
bstr2
))
hres
=
S_FALSE
;
SysFreeString
(
bstr2
);
}
SysFreeString
(
bstr
);
if
(
hres
!=
S_OK
)
goto
done
;
/* Legacy modes ignore port */
if
(
dispex_compat_mode
(
&
window
->
event_target
.
dispex
)
<
COMPAT_MODE_IE9
)
goto
done
;
hres
=
IUri_GetPort
(
uri
,
&
port
);
if
(
hres
!=
S_OK
)
{
if
(
FAILED
(
hres
))
goto
done
;
no_port
=
TRUE
;
/* some protocols don't have ports (e.g. res) */
}
hres
=
IUri_GetPort
(
target
,
&
port2
);
if
(
hres
!=
S_OK
)
{
if
(
FAILED
(
hres
))
goto
done
;
if
(
no_port
)
hres
=
S_OK
;
}
else
if
(
no_port
||
port
!=
port2
)
{
hres
=
S_FALSE
;
}
done:
IUri_Release
(
target
);
return
hres
;
}
struct
post_message_task
{
event_task_t
header
;
DOMEvent
*
event
;
...
...
@@ -2251,6 +2332,77 @@ static void post_message_destr(event_task_t *_task)
IDOMEvent_Release
(
&
task
->
event
->
IDOMEvent_iface
);
}
static
HRESULT
post_message
(
HTMLInnerWindow
*
window
,
VARIANT
msg
,
BSTR
targetOrigin
,
VARIANT
transfer
,
IServiceProvider
*
caller
,
compat_mode_t
compat_mode
)
{
DOMEvent
*
event
;
HRESULT
hres
;
if
(
V_VT
(
&
transfer
)
!=
VT_EMPTY
&&
V_VT
(
&
transfer
)
!=
VT_ERROR
)
FIXME
(
"transfer not implemented, ignoring
\n
"
);
hres
=
check_target_origin
(
window
,
targetOrigin
);
if
(
hres
!=
S_OK
)
return
SUCCEEDED
(
hres
)
?
S_OK
:
hres
;
switch
(
V_VT
(
&
msg
))
{
case
VT_EMPTY
:
case
VT_NULL
:
case
VT_VOID
:
case
VT_I1
:
case
VT_I2
:
case
VT_I4
:
case
VT_I8
:
case
VT_UI1
:
case
VT_UI2
:
case
VT_UI4
:
case
VT_UI8
:
case
VT_INT
:
case
VT_UINT
:
case
VT_R4
:
case
VT_R8
:
case
VT_BOOL
:
case
VT_BSTR
:
case
VT_CY
:
case
VT_DATE
:
case
VT_DECIMAL
:
case
VT_HRESULT
:
break
;
case
VT_ERROR
:
V_VT
(
&
msg
)
=
VT_EMPTY
;
break
;
default:
FIXME
(
"Unsupported vt %d
\n
"
,
V_VT
(
&
msg
));
return
E_NOTIMPL
;
}
if
(
!
window
->
doc
)
{
FIXME
(
"No document
\n
"
);
return
E_FAIL
;
}
hres
=
create_message_event
(
window
->
doc
,
&
msg
,
&
event
);
if
(
FAILED
(
hres
))
return
hres
;
if
(
compat_mode
>=
COMPAT_MODE_IE9
)
{
struct
post_message_task
*
task
;
if
(
!
(
task
=
malloc
(
sizeof
(
*
task
))))
{
IDOMEvent_Release
(
&
event
->
IDOMEvent_iface
);
return
E_OUTOFMEMORY
;
}
/* Because message events can be sent to different windows, they get blocked by any context */
task
->
header
.
thread_blocked
=
TRUE
;
task
->
event
=
event
;
return
push_event_task
(
&
task
->
header
,
window
,
post_message_proc
,
post_message_destr
,
window
->
task_magic
);
}
dispatch_event
(
&
window
->
event_target
,
event
);
IDOMEvent_Release
(
&
event
->
IDOMEvent_iface
);
return
S_OK
;
}
static
HRESULT
WINAPI
HTMLWindow6_postMessage
(
IHTMLWindow6
*
iface
,
BSTR
msg
,
VARIANT
targetOrigin
)
{
HTMLWindow
*
This
=
impl_from_IHTMLWindow6
(
iface
);
...
...
@@ -2264,7 +2416,8 @@ static HRESULT WINAPI HTMLWindow6_postMessage(IHTMLWindow6 *iface, BSTR msg, VAR
V_VT
(
&
var
)
=
VT_BSTR
;
V_BSTR
(
&
var
)
=
msg
;
V_VT
(
&
transfer
)
=
VT_EMPTY
;
return
IWineHTMLWindowPrivate_postMessage
(
&
This
->
IWineHTMLWindowPrivate_iface
,
var
,
V_BSTR
(
&
targetOrigin
),
transfer
);
return
post_message
(
This
->
inner_window
,
var
,
V_BSTR
(
&
targetOrigin
),
transfer
,
NULL
,
dispex_compat_mode
(
&
This
->
inner_window
->
event_target
.
dispex
));
}
static
HRESULT
WINAPI
HTMLWindow6_toStaticHTML
(
IHTMLWindow6
*
iface
,
BSTR
bstrHTML
,
BSTR
*
pbstrStaticHTML
)
...
...
@@ -3197,162 +3350,6 @@ static HRESULT WINAPI window_private_matchMedia(IWineHTMLWindowPrivate *iface, B
return
create_media_query_list
(
This
,
media_query
,
media_query_list
);
}
static
HRESULT
check_target_origin
(
HTMLInnerWindow
*
window
,
const
WCHAR
*
target_origin
)
{
BOOL
no_port
=
FALSE
;
IUri
*
uri
,
*
target
;
DWORD
port
,
port2
;
BSTR
bstr
,
bstr2
;
HRESULT
hres
;
if
(
!
target_origin
)
return
E_INVALIDARG
;
if
(
!
wcscmp
(
target_origin
,
L"*"
))
return
S_OK
;
hres
=
create_uri
(
target_origin
,
Uri_CREATE_NOFRAG
|
Uri_CREATE_NO_DECODE_EXTRA_INFO
,
&
target
);
if
(
FAILED
(
hres
))
return
hres
;
if
(
!
(
uri
=
window
->
base
.
outer_window
->
uri
))
{
FIXME
(
"window with no URI
\n
"
);
hres
=
S_FALSE
;
goto
done
;
}
bstr
=
NULL
;
hres
=
IUri_GetSchemeName
(
uri
,
&
bstr
);
if
(
hres
!=
S_OK
)
{
SysFreeString
(
bstr
);
goto
done
;
}
hres
=
IUri_GetSchemeName
(
target
,
&
bstr2
);
if
(
SUCCEEDED
(
hres
))
{
if
(
hres
==
S_OK
&&
wcsicmp
(
bstr
,
bstr2
))
hres
=
S_FALSE
;
SysFreeString
(
bstr2
);
}
SysFreeString
(
bstr
);
if
(
hres
!=
S_OK
)
goto
done
;
bstr
=
NULL
;
hres
=
IUri_GetHost
(
uri
,
&
bstr
);
if
(
hres
!=
S_OK
)
{
SysFreeString
(
bstr
);
goto
done
;
}
hres
=
IUri_GetHost
(
target
,
&
bstr2
);
if
(
SUCCEEDED
(
hres
))
{
if
(
hres
==
S_OK
&&
wcsicmp
(
bstr
,
bstr2
))
hres
=
S_FALSE
;
SysFreeString
(
bstr2
);
}
SysFreeString
(
bstr
);
if
(
hres
!=
S_OK
)
goto
done
;
/* Legacy modes ignore port */
if
(
dispex_compat_mode
(
&
window
->
event_target
.
dispex
)
<
COMPAT_MODE_IE9
)
goto
done
;
hres
=
IUri_GetPort
(
uri
,
&
port
);
if
(
hres
!=
S_OK
)
{
if
(
FAILED
(
hres
))
goto
done
;
no_port
=
TRUE
;
/* some protocols don't have ports (e.g. res) */
}
hres
=
IUri_GetPort
(
target
,
&
port2
);
if
(
hres
!=
S_OK
)
{
if
(
FAILED
(
hres
))
goto
done
;
if
(
no_port
)
hres
=
S_OK
;
}
else
if
(
no_port
||
port
!=
port2
)
{
hres
=
S_FALSE
;
}
done:
IUri_Release
(
target
);
return
hres
;
}
static
HRESULT
WINAPI
window_private_postMessage
(
IWineHTMLWindowPrivate
*
iface
,
VARIANT
msg
,
BSTR
targetOrigin
,
VARIANT
transfer
)
{
HTMLWindow
*
This
=
impl_from_IWineHTMLWindowPrivateVtbl
(
iface
);
HTMLInnerWindow
*
window
=
This
->
inner_window
;
DOMEvent
*
event
;
HRESULT
hres
;
TRACE
(
"iface %p, msg %s, targetOrigin %s, transfer %s
\n
"
,
iface
,
debugstr_variant
(
&
msg
),
debugstr_w
(
targetOrigin
),
debugstr_variant
(
&
transfer
));
if
(
V_VT
(
&
transfer
)
!=
VT_EMPTY
&&
V_VT
(
&
transfer
)
!=
VT_ERROR
)
FIXME
(
"transfer not implemented, ignoring
\n
"
);
hres
=
check_target_origin
(
window
,
targetOrigin
);
if
(
hres
!=
S_OK
)
return
SUCCEEDED
(
hres
)
?
S_OK
:
hres
;
switch
(
V_VT
(
&
msg
))
{
case
VT_EMPTY
:
case
VT_NULL
:
case
VT_VOID
:
case
VT_I1
:
case
VT_I2
:
case
VT_I4
:
case
VT_I8
:
case
VT_UI1
:
case
VT_UI2
:
case
VT_UI4
:
case
VT_UI8
:
case
VT_INT
:
case
VT_UINT
:
case
VT_R4
:
case
VT_R8
:
case
VT_BOOL
:
case
VT_BSTR
:
case
VT_CY
:
case
VT_DATE
:
case
VT_DECIMAL
:
case
VT_HRESULT
:
break
;
case
VT_ERROR
:
V_VT
(
&
msg
)
=
VT_EMPTY
;
break
;
default:
FIXME
(
"Unsupported vt %d
\n
"
,
V_VT
(
&
msg
));
return
E_NOTIMPL
;
}
if
(
!
window
->
doc
)
{
FIXME
(
"No document
\n
"
);
return
E_FAIL
;
}
hres
=
create_message_event
(
window
->
doc
,
&
msg
,
&
event
);
if
(
FAILED
(
hres
))
return
hres
;
if
(
dispex_compat_mode
(
&
window
->
event_target
.
dispex
)
>=
COMPAT_MODE_IE9
)
{
struct
post_message_task
*
task
;
if
(
!
(
task
=
malloc
(
sizeof
(
*
task
))))
{
IDOMEvent_Release
(
&
event
->
IDOMEvent_iface
);
return
E_OUTOFMEMORY
;
}
/* Because message events can be sent to different windows, they get blocked by any context */
task
->
header
.
thread_blocked
=
TRUE
;
task
->
event
=
event
;
return
push_event_task
(
&
task
->
header
,
window
,
post_message_proc
,
post_message_destr
,
window
->
task_magic
);
}
dispatch_event
(
&
window
->
event_target
,
event
);
IDOMEvent_Release
(
&
event
->
IDOMEvent_iface
);
return
S_OK
;
}
static
HRESULT
WINAPI
window_private_get_console
(
IWineHTMLWindowPrivate
*
iface
,
IDispatch
**
console
)
{
HTMLWindow
*
This
=
impl_from_IWineHTMLWindowPrivateVtbl
(
iface
);
...
...
@@ -3401,7 +3398,6 @@ static const IWineHTMLWindowPrivateVtbl WineHTMLWindowPrivateVtbl = {
window_private_cancelAnimationFrame
,
window_private_get_console
,
window_private_matchMedia
,
window_private_postMessage
,
window_private_get_MutationObserver
};
...
...
@@ -4219,6 +4215,57 @@ static HRESULT IHTMLWindow3_setTimeout_hook(DispatchEx *dispex, WORD flags, DISP
return
dispex_call_builtin
(
dispex
,
DISPID_IHTMLWINDOW3_SETTIMEOUT
,
&
new_dp
,
res
,
ei
,
caller
);
}
static
HRESULT
IHTMLWindow6_postMessage_hook
(
DispatchEx
*
dispex
,
WORD
flags
,
DISPPARAMS
*
dp
,
VARIANT
*
res
,
EXCEPINFO
*
ei
,
IServiceProvider
*
caller
)
{
HTMLInnerWindow
*
This
=
impl_from_DispatchEx
(
dispex
);
BSTR
targetOrigin
,
converted_msg
=
NULL
;
VARIANT
msg
,
transfer
,
converted
;
compat_mode_t
compat_mode
;
HRESULT
hres
;
if
(
!
(
flags
&
DISPATCH_METHOD
)
||
dp
->
cArgs
<
2
||
dp
->
cNamedArgs
)
return
S_FALSE
;
compat_mode
=
dispex_compat_mode
(
&
This
->
event_target
.
dispex
);
msg
=
dp
->
rgvarg
[
dp
->
cArgs
-
1
];
V_VT
(
&
transfer
)
=
VT_EMPTY
;
if
(
compat_mode
>=
COMPAT_MODE_IE10
&&
dp
->
cArgs
>
2
)
transfer
=
dp
->
rgvarg
[
dp
->
cArgs
-
3
];
TRACE
(
"(%p)->(msg %s, targetOrigin %s, transfer %s)
\n
"
,
This
,
debugstr_variant
(
&
msg
),
debugstr_variant
(
&
dp
->
rgvarg
[
dp
->
cArgs
-
2
]),
debugstr_variant
(
&
transfer
));
if
(
compat_mode
<
COMPAT_MODE_IE10
&&
V_VT
(
&
msg
)
!=
VT_BSTR
)
{
hres
=
change_type
(
&
msg
,
&
dp
->
rgvarg
[
dp
->
cArgs
-
1
],
VT_BSTR
,
caller
);
if
(
FAILED
(
hres
))
return
hres
;
converted_msg
=
V_BSTR
(
&
msg
);
}
if
(
V_VT
(
&
dp
->
rgvarg
[
dp
->
cArgs
-
2
])
==
VT_BSTR
)
{
targetOrigin
=
V_BSTR
(
&
dp
->
rgvarg
[
dp
->
cArgs
-
2
]);
V_BSTR
(
&
converted
)
=
NULL
;
}
else
{
if
(
compat_mode
<
COMPAT_MODE_IE10
)
{
SysFreeString
(
converted_msg
);
return
E_INVALIDARG
;
}
hres
=
change_type
(
&
converted
,
&
dp
->
rgvarg
[
dp
->
cArgs
-
2
],
VT_BSTR
,
caller
);
if
(
FAILED
(
hres
))
{
SysFreeString
(
converted_msg
);
return
hres
;
}
targetOrigin
=
V_BSTR
(
&
converted
);
}
hres
=
post_message
(
This
,
msg
,
targetOrigin
,
transfer
,
caller
,
compat_mode
);
SysFreeString
(
V_BSTR
(
&
converted
));
SysFreeString
(
converted_msg
);
return
hres
;
}
static
void
HTMLWindow_init_dispex_info
(
dispex_data_t
*
info
,
compat_mode_t
compat_mode
)
{
static
const
dispex_hook_t
window2_hooks
[]
=
{
...
...
@@ -4244,6 +4291,10 @@ static void HTMLWindow_init_dispex_info(dispex_data_t *info, compat_mode_t compa
{
DISPID_IHTMLWINDOW4_CREATEPOPUP
,
NULL
},
{
DISPID_UNKNOWN
}
};
static
const
dispex_hook_t
window6_hooks
[]
=
{
{
DISPID_IHTMLWINDOW6_POSTMESSAGE
,
IHTMLWindow6_postMessage_hook
},
{
DISPID_UNKNOWN
}
};
/* Hide props not available in IE10 */
static
const
dispex_hook_t
private_ie10_hooks
[]
=
{
...
...
@@ -4259,6 +4310,7 @@ static void HTMLWindow_init_dispex_info(dispex_data_t *info, compat_mode_t compa
dispex_info_add_interface
(
info
,
IWineHTMLWindowPrivate_tid
,
compat_mode
>=
COMPAT_MODE_IE11
?
NULL
:
private_ie10_hooks
);
dispex_info_add_interface
(
info
,
IHTMLWindow6_tid
,
window6_hooks
);
dispex_info_add_interface
(
info
,
IHTMLWindow5_tid
,
NULL
);
dispex_info_add_interface
(
info
,
IHTMLWindow4_tid
,
compat_mode
>=
COMPAT_MODE_IE11
?
window4_ie11_hooks
:
NULL
);
dispex_info_add_interface
(
info
,
IHTMLWindow3_tid
,
compat_mode
>=
COMPAT_MODE_IE11
?
window3_ie11_hooks
:
window3_hooks
);
...
...
@@ -4290,10 +4342,7 @@ static const event_target_vtbl_t HTMLWindow_event_target_vtbl = {
.
set_current_event
=
HTMLWindow_set_current_event
};
static
const
tid_t
HTMLWindow_iface_tids
[]
=
{
IHTMLWindow6_tid
,
0
};
static
const
tid_t
HTMLWindow_iface_tids
[]
=
{
0
};
static
dispex_static_data_t
HTMLWindow_dispex
=
{
"Window"
,
...
...
dlls/mshtml/mshtml_private_iface.idl
View file @
22214ec3
...
...
@@ -131,8 +131,6 @@ interface IWineHTMLWindowPrivate : IDispatch
HRESULT
console
(
[
retval
,
out
]
IDispatch
**
console
)
;
[
id
(
53
)
]
HRESULT
matchMedia
(
[
in
]
BSTR
media_query
,
[
retval
,
out
]
IDispatch
**
media_query_list
)
;
[
id
(
54
)
]
HRESULT
postMessage
(
[
in
]
VARIANT
msg
,
[
in
]
BSTR
targetOrigin
,
[
in
,
optional
]
VARIANT
transfer
)
;
[
propget
,
id
(
DISPID_IWINEHTMLWINDOWPRIVATE_MUTATIONOBSERVER
)
]
HRESULT
MutationObserver
(
[
retval
,
out
]
IDispatch
**
observer_ctor
)
;
}
...
...
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