MSHTML: Use nsIWebBrowserStream to load html

Jacek Caban jack at itma.pwr.wroc.pl
Thu Aug 11 05:57:32 CDT 2005


Changelog:
    Use nsIWebBrowserStream to load html
-------------- next part --------------
Index: dlls/mshtml/mshtml_private.h
===================================================================
RCS file: /home/wine/wine/dlls/mshtml/mshtml_private.h,v
retrieving revision 1.22
diff -u -p -r1.22 mshtml_private.h
--- dlls/mshtml/mshtml_private.h	11 Aug 2005 10:30:30 -0000	1.22
+++ dlls/mshtml/mshtml_private.h	11 Aug 2005 10:51:18 -0000
@@ -73,11 +73,11 @@ struct NSContainer {
     nsIWebBrowser *webbrowser;
     nsIWebNavigation *navigation;
     nsIBaseWindow *window;
+    nsIWebBrowserStream *stream;
 
     HWND hwnd;
 };
 
-
 #define HTMLDOC(x)       ((IHTMLDocument2*)               &(x)->lpHTMLDocument2Vtbl)
 #define PERSIST(x)       ((IPersist*)                     &(x)->lpPersistFileVtbl)
 #define PERSISTMON(x)    ((IPersistMoniker*)              &(x)->lpPersistMonikerVtbl)
@@ -113,6 +113,12 @@ void HTMLDocument_NSContainer_Destroy(HT
 HRESULT ProtocolFactory_Create(REFCLSID,REFIID,void**);
 
 void close_gecko(void);
+
+nsIURI *get_nsIURI(LPCWSTR);
+
+nsACString *nsACString_Create(void);
+void nsACString_SetData(nsACString*,const char*);
+void nsACString_Destroy(nsACString*);
 
 DEFINE_GUID(CLSID_AboutProtocol, 0x3050F406, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
 DEFINE_GUID(CLSID_JSProtocol, 0x3050F3B2, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
Index: dlls/mshtml/nsembed.c
===================================================================
RCS file: /home/wine/wine/dlls/mshtml/nsembed.c,v
retrieving revision 1.4
diff -u -p -r1.4 nsembed.c
--- dlls/mshtml/nsembed.c	11 Aug 2005 10:30:30 -0000	1.4
+++ dlls/mshtml/nsembed.c	11 Aug 2005 10:51:18 -0000
@@ -40,12 +40,13 @@ DEFINE_GUID(CLSID_nsWebBrowser, 0xf1eac7
 
 #define NS_APPSTARTUPNOTIFIER_CONTRACTID "@mozilla.org/embedcomp/appstartup-notifier;1"
 #define NS_WEBBROWSER_CONTRACTID "@mozilla.org/embedding/browser/nsWebBrowser;1"
+#define NS_IOSERVICE_CONTRACTID "@mozilla.org/network/io-service;1"
 
 #define APPSTARTUP_TOPIC "app-startup"
 
 #define PR_UINT32_MAX 0xffffffff
 
-typedef struct {
+typedef struct nsACString {
     void *d1;
     PRUint32 d2;
     void *d3;
@@ -54,14 +55,18 @@ typedef struct {
 static nsresult (*NS_InitXPCOM2)(nsIServiceManager**,void*,void*);
 static nsresult (*NS_ShutdownXPCOM)(nsIServiceManager*);
 static nsresult (*NS_StringContainerInit)(nsString*);
+static nsresult (*NS_CStringContainerInit)(nsACString*);
 static nsresult (*NS_StringContainerFinish)(nsString*);
+static nsresult (*NS_CStringContainerFinish)(nsACString*);
 static nsresult (*NS_StringSetData)(nsString*,const PRUnichar*,PRUint32);
+static nsresult (*NS_CStringSetData)(nsString*,const char*,PRUint32);
 static nsresult (*NS_NewLocalFile)(const nsString*,PRBool,nsIFile**);
 
 static HINSTANCE hXPCOM = NULL;
 
 static nsIServiceManager *pServMgr = NULL;
 static nsIComponentManager *pCompMgr = NULL;
+static nsIIOService *pIOService = NULL;
 
 static const WCHAR wszNsContainer[] = {'N','s','C','o','n','t','a','i','n','e','r',0};
 
@@ -213,14 +218,17 @@ static BOOL load_gecko()
 #define NS_DLSYM(func) \
     func = (typeof(func))GetProcAddress(hXPCOM, #func); \
     if(!func) \
-        ERR("Could not GetProcAddress(" #func ") failed\n");
+        ERR("Could not GetProcAddress(" #func ") failed\n")
 
-    NS_DLSYM(NS_InitXPCOM2)
-    NS_DLSYM(NS_ShutdownXPCOM)
-    NS_DLSYM(NS_StringContainerInit)
-    NS_DLSYM(NS_StringContainerFinish)
-    NS_DLSYM(NS_StringSetData)
-    NS_DLSYM(NS_NewLocalFile)
+    NS_DLSYM(NS_InitXPCOM2);
+    NS_DLSYM(NS_ShutdownXPCOM);
+    NS_DLSYM(NS_StringContainerInit);
+    NS_DLSYM(NS_CStringContainerInit);
+    NS_DLSYM(NS_StringContainerFinish);
+    NS_DLSYM(NS_CStringContainerFinish);
+    NS_DLSYM(NS_StringSetData);
+    NS_DLSYM(NS_CStringSetData);
+    NS_DLSYM(NS_NewLocalFile);
 
 #undef NS_DLSYM
 
@@ -260,6 +268,25 @@ static BOOL load_gecko()
     return TRUE;
 }
 
+nsACString *nsACString_Create(void)
+{
+    nsACString *ret;
+    ret = HeapAlloc(GetProcessHeap(), 0, sizeof(nsACString));
+    NS_CStringContainerInit(ret);
+    return ret;
+}
+
+void nsACString_SetData(nsACString *str, const char *data)
+{
+    NS_CStringSetData(str, data, PR_UINT32_MAX);
+}
+
+void nsACString_Destroy(nsACString *str)
+{
+    NS_CStringContainerFinish(str);
+    HeapFree(GetProcessHeap(), 0, str);
+}
+
 void close_gecko()
 {
     TRACE("()\n");
@@ -274,6 +301,38 @@ void close_gecko()
         FreeLibrary(hXPCOM);
 }
 
+nsIURI *get_nsIURI(LPCWSTR url)
+{
+    nsIURI *ret;
+    nsACString *acstr;
+    nsresult nsres;
+    char *urla;
+    int len;
+
+    if(!pIOService) {
+        nsres = nsIServiceManager_GetServiceByContactID(pServMgr, NS_IOSERVICE_CONTRACTID,
+                &IID_nsIIOService, (void**)&pIOService);
+        if(NS_FAILED(nsres))
+            ERR("Failed to create nsIOService: %08lx\n", nsres);
+    }
+
+    len = WideCharToMultiByte(CP_ACP, 0, url, -1, NULL, -1, NULL, NULL);
+    urla = HeapAlloc(GetProcessHeap(), 0, len);
+    WideCharToMultiByte(CP_ACP, 0, url, -1, urla, -1, NULL, NULL);
+
+    acstr = nsACString_Create();
+    nsACString_SetData(acstr, urla);
+
+    nsres = nsIIOService_NewURI(pIOService, acstr, NULL, NULL, &ret);
+    if(NS_FAILED(nsres))
+        FIXME("NewURI failed: %08lx\n", nsres);
+
+    nsACString_Destroy(acstr);
+    HeapFree(GetProcessHeap(), 0, urla);
+
+    return ret;
+}
+
 void HTMLDocument_NSContainer_Init(HTMLDocument *This)
 {
     nsIWebBrowserSetup *wbsetup;
@@ -312,6 +371,11 @@ void HTMLDocument_NSContainer_Init(HTMLD
     if(NS_FAILED(nsres))
         ERR("Could not get nsIWebNavigation interface: %08lx\n", nsres);
 
+    nsres = nsIWebBrowserStream_QueryInterface(This->nscontainer->webbrowser, &IID_nsIWebBrowserStream,
+            (void**)&This->nscontainer->stream);
+    if(NS_FAILED(nsres))
+        ERR("Could not get nsIWebBrowserStream interface: %08lx\n", nsres);
+
     if(!nscontainer_class)
         register_nscontainer_class();
 
@@ -340,6 +404,9 @@ void HTMLDocument_NSContainer_Destroy(HT
     nsIWebBrowser_Release(This->nscontainer->webbrowser);
     nsIWebNavigation_Release(This->nscontainer->navigation);
     nsIBaseWindow_Release(This->nscontainer->window);
+
+    if(This->nscontainer->stream)
+        nsIWebBrowserStream_Release(This->nscontainer->stream);
 
     HeapFree(GetProcessHeap(), 0, This->nscontainer);
 }
Index: dlls/mshtml/nsiface.idl
===================================================================
RCS file: /home/wine/wine/dlls/mshtml/nsiface.idl,v
retrieving revision 1.1
diff -u -p -r1.1 nsiface.idl
--- dlls/mshtml/nsiface.idl	1 Aug 2005 10:59:45 -0000	1.1
+++ dlls/mshtml/nsiface.idl	11 Aug 2005 10:51:18 -0000
@@ -39,11 +39,12 @@ typedef WCHAR PRUnichar;
 typedef LPWSTR nswstring;
 typedef ULONG PRUint32;
 typedef LONG PRInt32;
+typedef BYTE PRUint8;
 typedef BOOL PRBool;
 typedef LARGE_INTEGER PRInt64;
 
 typedef int nsAString;
-typedef int nsACString;
+typedef struct nsACString nsACString;
 
 interface nsIWebBrowserChrome;
 
@@ -64,10 +65,11 @@ typedef nsISupports nsIURIContentListene
 typedef nsISupports nsIDOMWindow;
 typedef nsISupports nsIInputStream;
 typedef nsISupports nsIDOMDocument;
-typedef nsISupports nsIURI;
 typedef nsISupports nsISHistory;
 typedef nsISupports nsISimpleEnumerator;
 typedef nsISupports nsIWidget;
+typedef nsISupports nsIProtocolHandler;
+typedef nsISupports nsIChannel;
 
 [
     object,
@@ -106,6 +108,40 @@ interface nsIComponentManager : nsISuppo
 
 [
     object,
+    uuid(07a22cc0-0ce5-11d3-9331-00104ba0fd40)
+]
+interface nsIURI : nsISupports
+{
+    nsresult GetSpec(nsACString *aSpec);
+    nsresult SetSpec(const nsACString *aSpec);
+    nsresult GetPrePath(nsACString *aPrePath);
+    nsresult GetScheme(nsACString *aScheme);
+    nsresult SetScheme(const nsACString *aScheme);
+    nsresult GetUserPass(nsACString *aUserPass);
+    nsresult SetUserPass(const nsACString *aUserPass);
+    nsresult GetUsername(nsACString *aUsername);
+    nsresult SetUsername(const nsACString *aUsername);
+    nsresult GetPassword(nsACString *aPassword);
+    nsresult SetPassword(const nsACString *aPassword);
+    nsresult GetHostPort(nsACString *aHostPort);
+    nsresult SetHostPort(const nsACString *aHostPort);
+    nsresult GetHost(nsACString *aHost);
+    nsresult SetHost(const nsACString *aHost);
+    nsresult GetPort(PRInt32 *aPort);
+    nsresult SetPort(PRInt32 aPort);
+    nsresult GetPath(nsACString *aPath);
+    nsresult SetPath(const nsACString *aPath);
+    nsresult Equals(nsIURI *other, PRBool *_retval);
+    nsresult SchemeIs(const char *scheme, PRBool *_retval);
+    nsresult Clone(nsIURI **_retval);
+    nsresult Resolve(const nsACString *relativePath, nsACString *_retval);
+    nsresult GetAsciiSpec(nsACString *aAsciiSpec);
+    nsresult GetAsciiHost(nsACString *aAsciiHost);
+    nsresult GetOriginCharset(nsACString *aOriginCharset);
+}
+
+[
+    object,
     uuid(69e5df00-7b8b-11d3-af61-00a024ffc08c)
 ]
 interface nsIWebBrowser : nsISupports
@@ -238,4 +274,32 @@ interface nsIFile : nsISupports
     nsresult Contains(nsIFile *inFile, PRBool recir, PRBool *_retval);
     nsresult GetParent(nsIFile **aParent);
     nsresult GetDirectoryEntries(nsISimpleEnumerator **aDirectoryEntries);
+}
+
+[
+    object,
+    uuid(86d02f0e-219b-4cfc-9c88-bd98d2cce0b8)
+]
+interface nsIWebBrowserStream : nsISupports
+{
+    nsresult OpenStream(nsIURI *aBaseURI, nsACString *aContentType);
+    nsresult AppendToStream(PRUint8 *aData, PRUint32 aLen);
+    nsresult CloseStream();
+}
+
+[
+    object,
+    uuid(bddeda3f-9020-4d12-8c70-984ee9f7935e)
+]
+interface nsIIOService : nsISupports
+{
+    nsresult GetProtocolHandler(const char *aScheme, nsIProtocolHandler **_retval);
+    nsresult GetProtocolFlags(const char *aScheme, PRUint32 *_retval);
+    nsresult NewURI(const nsACString *aSpec, const char *aOriginCharset, nsIURI *aBaseURI, nsIURI **_retval);
+    nsresult NewFileURI(nsIFile *aFile, nsIURI **_retval);
+    nsresult NewChannelFromURI(nsIURI *aURI, nsIChannel **_retval);
+    nsresult NewChannel(const nsACString *aSpec, const char *aOriginCharset, nsIURI *aBaseURI, nsIChannel **_retval);
+    nsresult GetOffline(PRBool *aOffline);
+    nsresult SetOffline(PRBool aOffline);
+    nsresult AllowPort(PRInt32 aPort, const char *aScheme, PRBool *_retval);
 }
Index: dlls/mshtml/persist.c
===================================================================
RCS file: /home/wine/wine/dlls/mshtml/persist.c,v
retrieving revision 1.8
diff -u -p -r1.8 persist.c
--- dlls/mshtml/persist.c	11 Aug 2005 10:30:30 -0000	1.8
+++ dlls/mshtml/persist.c	11 Aug 2005 10:51:18 -0000
@@ -22,6 +22,8 @@
 #include <stdio.h>
 
 #define COBJMACROS
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
 
 #include "windef.h"
 #include "winbase.h"
@@ -41,6 +43,8 @@ struct BindStatusCallback {
 
     HTMLDocument *doc;
     IBinding *binding;
+    IStream *stream;
+    LPOLESTR url;
 };
 
 #define STATUSCLB_THIS(iface) DEFINE_THIS(BindStatusCallback, BindStatusCallback, iface)
@@ -89,6 +93,9 @@ static ULONG WINAPI BindStatusCallback_R
         if(This->doc->status_callback == This)
             This->doc->status_callback = NULL;
         IHTMLDocument2_Release(HTMLDOC(This->doc));
+        if(This->stream)
+            IStream_Release(This->stream);
+        CoTaskMemFree(This->url);
         HeapFree(GetProcessHeap(), 0, This);
     }
 
@@ -105,6 +112,22 @@ static HRESULT WINAPI BindStatusCallback
     This->binding = pbind;
     IBinding_AddRef(pbind);
 
+    if(This->doc->nscontainer && This->doc->nscontainer->stream) {
+        nsACString *strTextHtml;
+        nsresult nsres;
+        nsIURI *uri = get_nsIURI(This->url);
+
+        strTextHtml = nsACString_Create();
+        /* FIXME: Set it correctly */
+        nsACString_SetData(strTextHtml, "text/html");
+
+        nsres = nsIWebBrowserStream_OpenStream(This->doc->nscontainer->stream, uri, strTextHtml);
+        if(NS_FAILED(nsres))
+            ERR("OpenStream failed: %08lx\n", nsres);
+
+        nsIURI_Release(uri);
+    }
+
     return S_OK;
 }
 
@@ -138,6 +161,9 @@ static HRESULT WINAPI BindStatusCallback
 
     TRACE("(%p)->(%08lx %s)\n", This, hresult, debugstr_w(szError));
 
+    if(This->doc->nscontainer && This->doc->nscontainer->stream)
+        nsIWebBrowserStream_CloseStream(This->doc->nscontainer->stream);
+
     IBinding_Release(This->binding);
     This->binding = NULL;
     return S_OK;
@@ -163,7 +189,26 @@ static HRESULT WINAPI BindStatusCallback
         DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
 {
     BindStatusCallback *This = STATUSCLB_THIS(iface);
+
     TRACE("(%p)->(%08lx %ld %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
+
+    if(!This->stream) {
+        This->stream = pstgmed->u.pstm;
+        IStream_AddRef(This->stream);
+    }
+
+    if(This->doc->nscontainer && This->doc->nscontainer->stream) {
+        BYTE buf[1024];
+        DWORD size;
+        HRESULT hres;
+
+        do {
+            size = sizeof(buf);
+            hres = IStream_Read(This->stream, buf, size, &size);
+            nsIWebBrowserStream_AppendToStream(This->doc->nscontainer->stream, buf, size);
+        }while(hres == S_OK);
+    }
+
     return S_OK;
 }
 
@@ -189,12 +234,14 @@ static const IBindStatusCallbackVtbl Bin
     BindStatusCallback_OnObjectAvailable
 };
 
-static BindStatusCallback *BindStatusCallback_Create(HTMLDocument *doc)
+static BindStatusCallback *BindStatusCallback_Create(HTMLDocument *doc, LPOLESTR url)
 {
     BindStatusCallback *ret = HeapAlloc(GetProcessHeap(), 0, sizeof(BindStatusCallback));
     ret->lpBindStatusCallbackVtbl = &BindStatusCallbackVtbl;
     ret->ref = 0;
+    ret->url = url;
     ret->doc = doc;
+    ret->stream = NULL;
     IHTMLDocument2_AddRef(HTMLDOC(doc));
     return ret;
 }
@@ -244,29 +291,34 @@ static HRESULT WINAPI PersistMoniker_Loa
     IBindCtx *pbind;
     BindStatusCallback *callback;
     IStream *str;
-    LPWSTR url;
+    LPOLESTR url;
     HRESULT hres;
     nsresult nsres;
 
     FIXME("(%p)->(%x %p %p %08lx)\n", This, fFullyAvailable, pimkName, pibc, grfMode);
 
-    /* FIXME:
-     * This is a HACK, we should use moniker's BindToStorage instead of Gecko's LoadURI.
-     */
-    if(This->nscontainer) {
-        hres = IMoniker_GetDisplayName(pimkName, pibc, NULL, &url);
-        if(FAILED(hres)) {
-            WARN("GetDiaplayName failed: %08lx\n", hres);
-            return hres;
-        }
-        TRACE("got url: %s\n", debugstr_w(url));
+    hres = IMoniker_GetDisplayName(pimkName, pibc, NULL, &url);
+    if(FAILED(hres)) {
+        WARN("GetDiaplayName failed: %08lx\n", hres);
+        return hres;
+    }
+
+    TRACE("got url: %s\n", debugstr_w(url));
 
+    if(This->nscontainer && !This->nscontainer->stream) {
+        /*
+         * This is a workaround for older Gecko that doesn't support nsIWebBrowserStream.
+         * It uses Gecko's LoadURI instead of IMoniker's BindToStorage. Should we improve
+         * it (to do so we'd have to use not frozen interfaces)?
+         */
         nsres = nsIWebNavigation_LoadURI(This->nscontainer->navigation, url,
                 LOAD_FLAGS_NONE, NULL, NULL, NULL);
-        if(NS_SUCCEEDED(nsres))
+        if(NS_SUCCEEDED(nsres)) {
+            CoTaskMemFree(url);
             return S_OK;
-        else
+        }else {
             WARN("LoadURI failed: %08lx\n", nsres);
+        }
     }    
 
     /* FIXME: Use grfMode */
@@ -279,11 +331,12 @@ static HRESULT WINAPI PersistMoniker_Loa
     if(This->status_callback && This->status_callback->binding)
         IBinding_Abort(This->status_callback->binding);
 
-    callback = This->status_callback = BindStatusCallback_Create(This);
+    callback = This->status_callback = BindStatusCallback_Create(This, url);
 
     CreateAsyncBindCtx(0, STATUSCLB(callback), NULL, &pbind);
 
     hres = IMoniker_BindToStorage(pimkName, pbind, NULL, &IID_IStream, (void**)&str);
+    IBindCtx_Release(pbind);
     if(str)
         IStream_Release(str);
     if(FAILED(hres)) {


More information about the wine-patches mailing list