Search code examples
javascriptc++windowscom

Using Javascript to Call C++ in Internet Explorer


I have seen this for BHO extensions, where the JavaScript can call functions in the C++ BHO. But lets say I am not using a BHO, instead I have a C++ console application that creates an IE COM object like so:

HRESULT hr = CoCreateInstance(
            CLSID_InternetExplorer,
            NULL,
            CLSCTX_LOCAL_SERVER,
            IID_IWebBrowser2,
            (void**)&_cBrowser);

I also have a class which "owns" the IWebBrowser2 object that comes back from this function.

class BrowserWrapper{
    public: 
        CComPtr<IWebBrowser2> pBrowser;

        void SomeFunction(...)
}

Is there a way to call a function like "SomeFunction" in the wrapper class from the JavaScript in the spawned IWebBrowser2 object?


Solution

  • You must implement the IDocHostUIHandler interface and set it to the web browser with a code similar to this (extracted from the doc):

    ComPtr<IDispatch> spDocument;
    hr = spWebBrowser2->get_Document(&spDocument);
    if (SUCCEEDED(hr) && (spDocument != nullptr))
    {
        // Request default handler from MSHTML client site
        ComPtr<IOleObject> spOleObject;
        if (SUCCEEDED(spDocument.As(&spOleObject)))
        {
            ComPtr<IOleClientSite> spClientSite;
            hr = spOleObject->GetClientSite(&spClientSite);
            if (SUCCEEDED(hr) && spClientSite)
            {
                // Save pointer for delegation to default 
                m_spDefaultDocHostUIHandler = spClientSite;
            }
        }
    
        // Set the new custom IDocHostUIHandler
        ComPtr<ICustomDoc> spCustomDoc;
        if (SUCCEEDED(spDocument.As(&spCustomDoc)))
        {
            // NOTE: spHandler is user-defined class
            spCustomDoc->SetUIHandler(spHandler.Get());
        }
    } 
    

    You must specifically implement the GetExternal method

    Now, in IE's javascript (or vbscript for that matter), you can access your host with a call like this:

    var ext = window.external; // this will call your host's IDocHostUIHandler.GetExternal method
    ext.SomeFunction(...); // implemented by your object
    

    What you return in GetExternal must be an IDispatch object that you can design the way you want.