MessageManager::callFunctionOnMessageThread behaviour in IE


#1

Hi,
Iam new to JUCE and iam using version 1.5. Iam trying to build a browser plugin for IE and FF. I ran into the following problem in IE7.

  1. When IE 7 is opened and the main html page is opened the object tag loads my plugin. i have a non-gui thread in my plugin that is using the following
    MessageManager::callFunctionOnMessageThread method to invoke functions on the main browser thread. this works fine for one tab
  2. When i open a new tab in IE7 and open my html page a second instance of my plugin gets created as expected. but when i invoke the MessageManager::callFunctionOnMessageThread method nothing happens for this tab. i did find that the browser script objects passed to the plugin instances are unique. all iam doing within the MessageManager::callFunctionOnMessageThread method is “call” a function on the browser script object

any help would be appreciated. iam not sure if the message manager needs to be updated indicating that the new tab in the browser is the message thread where the event loop is running.

After further debugging i noticed that my callback function is being called. However the browser javascript object’s call method is not doing anything and returns. Tested with FF and this same code works fine.

Also found that the DynamicObjectWrappingIDispatch object’s invoke method returns a failure for the second tab in IE 7. Within the implementation of this method
if (source->GetIDsOfNames (IID_NULL, (LPOLESTR*)&name, 1, 0, &id) == S_OK)
is failing. so it seems the browser script object for the 2nd tab does not have this method. i also found a similar issue at the following
http://www.codeproject.com/Messages/1982674/Problem-with-mfc-activex-control-event-in-IE7-when.aspx

thanks in advance
vramaswa


#2

Hi

Well, it’s an interesting problem, but I’m a bit stuck for suggestions - it sounds like an IE7 problem rather than anything the plugin’s doing wrong… If GetIDsOfNames fails, there’s not really anything else that could be done. Have you tried IE8 to see if it’s something they’ve fixed?


#3

Hi,
Verified that it works fine in IE8. In IE8 all tabs or windows run as different processes and we dont run into this problem since there is one and one process and the worker thread posts its message to the main ui thread and it works fine. In IE7 it is not a bug. This is the multi-threaded architecture of IE7. It affects all add ons in general. Each tab in IE7 has its own thread and IE7 will not allow invocation of the automation API (IDispatch) across apartments unless you explicitly marshall the interface. so in my case the example

first thread (launched by the browser where the plugin is created)

  1. receive a dispatch from the browser to the activex
  2. wrap it in a DynamicObjectWrappingIDispatch - juce does this

second thread (created by the first thread)

  1. invoke a function on the message thread using MessageManager::callFunctionOnMessageThread
  2. this invokes the function and tries to invoke the Idispatch from the first thread. this will fail silently

i tried even to send message to the correct HWND belonging to the main thread instead of calling the MessageManager::callFunctionOnMessageThread
and it still fails silently. obviously when i invoked it from the main thread it works fine or works as designed.
the IDispatch needs to be marshalled using CoMarshalInterThreadInterfaceInStream() and CoGetInterfaceAndReleaseStream (this is not efficient since this pair needs to be called for every usage of the idispatch)

the preferred way according to miscosoft docs as well is using a GIT (Global Interface Table)
http://msdn.microsoft.com/en-us/library/ms678517(VS.85).aspx

Iam trying to implement the GIT but trying to change the existing JUCE code to get this working is not easy. Ideally the DynamicObjectWrappingIDispatch
should be using the correct version of the IDispatch based on the thread that is invoking it. Some rough thoughts on this

  1. Need totrack the thread id on which the IDispatch is created
  2. Need to add to the GIT and keep the cookie
  3. When called check if the current thread is samme as the created thread. if not then get the marshalled one from the GIT

Iam not sure if you have any thoughts on this.
thanks
vramaswa


#4

Words cannot adequately describe how much I hate Microsoft’s COM and all its related crap.

Seems like you’ve figured out the right answer, though I’ve no time to offer to do it right now. Happy to help if you want to try putting something in place…


#5

amen to your comments on COM. i will try to implement using GIT and send u the patches for review
thanks again
vramaswa