EVALUATION
When we make a JavaScript-to-Java call, we need to run a nested
message pump (currently on the Windows platform only) in order to
allow the browser to repaint while we are waiting for the result to
come back from Java. This nested message pump is also used to
implement modal dialog blocking of the browser window.
We were dispatching too many types of messages in this message pump,
causing input events like mouse and keyboard events to be dispatched
while a JavaScript-to-Java call was running. This could cause
JavaScript-level event handlers to be called recursively, which is
incorrect.
The fix is to not dispatch any input events in this nested message
pump in the normal case. However, this does not work when a Java modal
dialog is visible; testing has shown that when a modal dialog is up,
and the message hooks are installed which implement the blocking of
the browser window, the nested message pump actually must dispatch
input events. A boolean parameter was added to the native method for
the message pump to toggle its behavior. The existing infrastructure
for the modal dialog handling in the new plug-in made this a very
simple and localized change.
The structure of the message pump was changed to alternate between
waiting for the event object for a brief period of time, with no
interruptions from Windows messages, and dispatching a bounded number
of messages. This was found to be necessary because we are no longer
dispatching all Windows events, so using MsgWaitForMultipleObjects was
causing the message loop to consume all CPU, apparently preventing the
thread which would otherwise signal the event object from running. The
wait period and number of messages processed was tuned slightly with
the NeuroDNA application, but the specific numbers do not appear to
have a large impact on overall responsiveness.
Also fixed a small issue in the LiveConnect code to improve the error
reporting in the case where null is passed as an argument to a Java
method taking a primitive type such as "int".
|
SUGGESTED FIX
Below suggested fix is for the old (classic) Java Plug-in:
------- JavaAdapter.cpp -------
*** //C/tmp/sccs.001000 Tue Jan 15 19:57:19 2008
--- JavaAdapter.cpp Tue Jan 15 19:57:01 2008
***************
*** 437,454 ****
dwRet = MsgWaitForMultipleObjects(1, &hEvent, FALSE, time, QS_
ALLINPUT );
// If there is a message in the queue
if (dwRet == WAIT_OBJECT_0 + 1 ) {
! MSG msg;
! while( PeekMessage(&msg, hWndActive, 0, 0, PM_NOREMOVE) )
{
// processing WM_PAINT and WM_TIMER messages seems suffi
cient
// messages may need to consider are WM_NCPAINT, WM_ERAS
EBKGND, and focus related ones
! PeekMessage(&msg, msg.hwnd, msg.message, msg.message, PM_REMOVE);
! TranslateMessage(&msg);
! DispatchMessage(&msg);
! if( !(msg.message == WM_PAINT || msg.message == WM_TIMER ) ) {
! // Set focus on the modal window as long as it's
active
! if ( ::GetActiveWindow() != modalhWnd ) {
! ::SetFocus(modalhWnd);
! }
}
// Check if the JS-Java method is done(i.e event is si
gnalled)
--- 437,458 ----
dwRet = MsgWaitForMultipleObjects(1, &hEvent, FALSE, time, QS_
ALLINPUT );
// If there is a message in the queue
if (dwRet == WAIT_OBJECT_0 + 1 ) {
! MSG msg;
! while( PeekMessage(&msg, hWndActive, 0, 0, PM_NOREMOVE) ) {
// processing WM_PAINT and WM_TIMER messages seems suffi
cient
// messages may need to consider are WM_NCPAINT, WM_ERAS
EBKGND, and focus related ones
! PeekMessage(&msg, msg.hwnd, msg.message, msg.message, PM
_REMOVE);
! if( (msg.message == WM_PAINT) || (msg.message == WM_TIME
R) ||
! (msg.message == WM_SETFOCUS) || (msg.message == WM_K
ILLFOCUS) ||
! (msg.message == WM_NCPAINT) || (msg.message == WM_NC
ACTIVATE) ||
! (msg.message == WM_ACTIVATE) || (msg.message == WM_M
OUSEACTIVATE)) {
! TranslateMessage(&msg);
! DispatchMessage(&msg);
! } else {
! // Set focus on the modal window as long as it's ac
tive
! if ( ::GetActiveWindow() != modalhWnd ) {
! ::SetFocus(modalhWnd);
! }
}
// Check if the JS-Java method is done(i.e event is si
gnalled)
***************
*** 481,491 ****
// If there is a message in the queue
if (dwRet == WAIT_OBJECT_0 + 1 ) {
MSG msg;
! while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
! if (!IsDialogMessage(pJA->m_hWnd, &msg)) {
! TranslateMessage(&msg);
! DispatchMessage(&msg);
! }
// Check if the JS-Java method is done(i.e event is sign
alled)
if(WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0) {
dwRet = WAIT_OBJECT_0;
--- 485,493 ----
// If there is a message in the queue
if (dwRet == WAIT_OBJECT_0 + 1 ) {
MSG msg;
! while( PeekMessage(&msg, NULL, WM_JPI_MIN, WM_JPI_MAX, PM_RE
MOVE) ) {
! TranslateMessage(&msg);
! DispatchMessage(&msg);
// Check if the JS-Java method is done(i.e event is sign
alled)
if(WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0) {
dwRet = WAIT_OBJECT_0;
|