# Patch by Grant Gayed # https://bugs.eclipse.org/bugs/show_bug.cgi?id=268651#c18 # https://bugs.eclipse.org/bugs/attachment.cgi?id=130751 Index: Eclipse SWT Mozilla/common/org/eclipse/swt/browser/Mozilla.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.swt/Eclipse SWT Mozilla/common/org/eclipse/swt/browser/Mozilla.java,v retrieving revision 1.105.2.3 diff -u -r1.105.2.3 Mozilla.java --- src/org/eclipse/swt/browser/Mozilla.java 21 Aug 2008 16:02:30 -00001.105.2.3 +++ src/org/eclipse/swt/browser/Mozilla.java 2 Apr 2009 19:15:06 -0000 @@ -47,6 +47,7 @@ Shell tip = null; Listener listener; Vector unhookedDOMWindows = new Vector (); + byte[] htmlBytes; static nsIAppShell AppShell; static AppFileLocProvider LocationProvider; @@ -1130,21 +1131,21 @@ * Once the client does a proper navigate with either setUrl() or setText() then resume as * normal. The Mozilla bug for this is https://bugzilla.mozilla.org/show_bug.cgi?id=415789. */ - awaitingNavigate = true; - rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result); - if (rc != XPCOM.NS_OK) { - browser.dispose (); - error (rc); - } - if (result[0] == 0) { - browser.dispose (); - error (XPCOM.NS_ERROR_NO_INTERFACE); - } - nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]); - char[] uri = new char[ABOUT_BLANK.length () + 1]; - ABOUT_BLANK.getChars (0, ABOUT_BLANK.length (), uri, 0); - rc = webNavigation.LoadURI (uri, nsIWebNavigation.LOAD_FLAGS_NONE, 0, 0, 0); - webNavigation.Release (); +// awaitingNavigate = true; +// rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result); +// if (rc != XPCOM.NS_OK) { +// browser.dispose (); +// error (rc); +// } +// if (result[0] == 0) { +// browser.dispose (); +// error (XPCOM.NS_ERROR_NO_INTERFACE); +// } +// nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]); +// char[] uri = new char[ABOUT_BLANK.length () + 1]; +// ABOUT_BLANK.getChars (0, ABOUT_BLANK.length (), uri, 0); +// rc = webNavigation.LoadURI (uri, nsIWebNavigation.LOAD_FLAGS_NONE, 0, 0, 0); +// webNavigation.Release (); } } result[0] = 0; @@ -1223,6 +1224,7 @@ } public boolean back () { + htmlBytes = null; if (awaitingNavigate) return false; long /*int*/[] result = new long /*int*/[1]; @@ -1425,6 +1427,7 @@ } public boolean forward () { + htmlBytes = null; if (awaitingNavigate) return false; long /*int*/[] result = new long /*int*/[1]; @@ -1635,6 +1638,7 @@ webBrowser.Release (); webBrowser = null; webBrowserObject = null; + htmlBytes = null; if (tip != null && !tip.isDisposed ()) tip.dispose (); tip = null; @@ -1696,6 +1700,7 @@ } public void refresh () { + htmlBytes = null; if (awaitingNavigate) return; long /*int*/[] result = new long /*int*/[1]; @@ -1817,11 +1822,45 @@ } else { result[0] = 0; rc = interfaceRequestor.GetInterface (nsIDocShell.NS_IDOCSHELL_IID, result); - if (rc != XPCOM.NS_OK) error (rc); - if (result[0] == 0) error (XPCOM.NS_ERROR_NO_INTERFACE); - nsIDocShell docShell = new nsIDocShell (result[0]); - rc = docShell.LoadStream (inputStream.getAddress (), uri.getAddress (), aContentType, aContentCharset, 0); - docShell.Release (); + if (rc == XPCOM.NS_OK) { + if (result[0] == 0) error (XPCOM.NS_ERROR_NO_INTERFACE); + nsIDocShell docShell = new nsIDocShell (result[0]); + rc = docShell.LoadStream (inputStream.getAddress (), uri.getAddress (), aContentType, aContentCharset, 0); + docShell.Release (); + } else { + result[0] = 0; + rc = webBrowser.QueryInterface (nsIWebBrowserStream.NS_IWEBBROWSERSTREAM_IID, result); + if (rc == XPCOM.NS_OK) { + if (result[0] == 0) error (XPCOM.NS_ERROR_NO_INTERFACE); + /* + * Setting mozilla's content through nsIWebBrowserStream does not cause a page + * load to occur, so the events that usually accompany a page change are not + * fired. To make this behave as expected, navigate to about:blank first and + * then set the html content once the page has loaded. + */ + new nsISupports (result[0]).Release (); + result[0] = 0; + + /* + * If htmlBytes is not null then the about:blank page is already being loaded, + * so no Navigate is required. Just set the html that is to be shown. + */ + boolean blankLoading = htmlBytes != null; + htmlBytes = data; + if (blankLoading) return true; + + /* navigate to about:blank */ + rc = webBrowser.QueryInterface (nsIWebNavigation.NS_IWEBNAVIGATION_IID, result); + if (rc != XPCOM.NS_OK) error (rc); + if (result[0] == 0) error (XPCOM.NS_ERROR_NO_INTERFACE); + nsIWebNavigation webNavigation = new nsIWebNavigation (result[0]); + result[0] = 0; + char[] uriChars = new char[ABOUT_BLANK.length () + 1]; + ABOUT_BLANK.getChars (0, ABOUT_BLANK.length (), uriChars, 0); + rc = webNavigation.LoadURI (uriChars, nsIWebNavigation.LOAD_FLAGS_NONE, 0, 0, 0); + webNavigation.Release (); + } + } } } if (rc != XPCOM.NS_OK) error (rc); @@ -1836,6 +1875,7 @@ } public boolean setUrl (String url) { + htmlBytes = null; awaitingNavigate = false; long /*int*/[] result = new long /*int*/[1]; @@ -1852,6 +1892,7 @@ } public void stop () { + htmlBytes = null; if (awaitingNavigate) return; long /*int*/[] result = new long /*int*/[1]; @@ -2174,6 +2215,108 @@ unhookedDOMWindows.remove (ptrObject); new nsISupports (ptrObject.value).Release (); } + + /* + * If htmlBytes is not null then there is html from a previous setText() call + * waiting to be set into the about:blank page once it has completed loading. + */ + if (htmlBytes != null) { + nsIRequest req = new nsIRequest (aRequest); + long /*int*/ name = XPCOM.nsEmbedCString_new (); + rc = req.GetName (name); + if (rc != XPCOM.NS_OK) error (rc); + int length = XPCOM.nsEmbedCString_Length (name); + long /*int*/ buffer = XPCOM.nsEmbedCString_get (name); + byte[] dest = new byte[length]; + XPCOM.memmove (dest, buffer, length); + String url = new String (dest); + XPCOM.nsEmbedCString_delete (name); + + if (url.startsWith (ABOUT_BLANK)) { + /* + * Setting mozilla's content with nsIWebBrowserStream invalidates the + * DOM listeners that were hooked on it (about:blank), so remove them and + * add new ones after the content has been set. + */ + unhookDOMListeners (); + + rc = XPCOM.NS_GetServiceManager (result); + if (rc != XPCOM.NS_OK) error (rc); + if (result[0] == 0) error (XPCOM.NS_NOINTERFACE); + + nsIServiceManager serviceManager = new nsIServiceManager (result[0]); + result[0] = 0; + rc = serviceManager.GetService (XPCOM.NS_IOSERVICE_CID, nsIIOService.NS_IIOSERVICE_IID, result); + if (rc != XPCOM.NS_OK) error (rc); + if (result[0] == 0) error (XPCOM.NS_NOINTERFACE); + serviceManager.Release (); + + nsIIOService ioService = new nsIIOService (result[0]); + result[0] = 0; + /* + * Note. Mozilla ignores LINK tags used to load CSS stylesheets + * when the URI protocol for the nsInputStreamChannel + * is about:blank. The fix is to specify the file protocol. + */ + byte[] aString = MozillaDelegate.wcsToMbcs (null, URI_FROMMEMORY, false); + long /*int*/ aSpec = XPCOM.nsEmbedCString_new (aString, aString.length); + rc = ioService.NewURI (aSpec, null, 0, result); + if (rc != XPCOM.NS_OK) error (rc); + if (result[0] == 0) error (XPCOM.NS_NOINTERFACE); + XPCOM.nsEmbedCString_delete (aSpec); + ioService.Release (); + + nsIURI uri = new nsIURI (result[0]); + result[0] = 0; + + rc = webBrowser.QueryInterface (nsIWebBrowserStream.NS_IWEBBROWSERSTREAM_IID, result); + if (rc != XPCOM.NS_OK) error (rc); + if (result[0] == 0) error (XPCOM.NS_NOINTERFACE); + + nsIWebBrowserStream stream = new nsIWebBrowserStream (result[0]); + result[0] = 0; + + byte[] contentTypeBuffer = MozillaDelegate.wcsToMbcs (null, "text/html", true); // $NON-NLS-1$ + long /*int*/ aContentType = XPCOM.nsEmbedCString_new (contentTypeBuffer, contentTypeBuffer.length); + + rc = stream.OpenStream (uri.getAddress (), aContentType); + if (rc != XPCOM.NS_OK) error (rc); + long /*int*/ ptr = C.malloc (htmlBytes.length); + XPCOM.memmove (ptr, htmlBytes, htmlBytes.length); + int pageSize = 8192; + int pageCount = htmlBytes.length / pageSize + 1; + long /*int*/ current = ptr; + for (int i = 0; i < pageCount; i++) { + length = i == pageCount - 1 ? htmlBytes.length % pageSize : pageSize; + if (length > 0) { + rc = stream.AppendToStream (current, length); + if (rc != XPCOM.NS_OK) error (rc); + } + current += pageSize; + } + rc = stream.CloseStream (); + if (rc != XPCOM.NS_OK) error (rc); + C.free (ptr); + XPCOM.nsEmbedCString_delete (aContentType); + stream.Release (); + uri.Release (); + htmlBytes = null; + + rc = webBrowser.GetContentDOMWindow (result); + if (rc != XPCOM.NS_OK) error (rc); + if (result[0] == 0) error (XPCOM.NS_ERROR_NO_INTERFACE); + boolean isTop = result[0] == domWindow.getAddress (); + new nsISupports (result[0]).Release (); + result[0] = 0; + rc = domWindow.QueryInterface (nsIDOMEventTarget.NS_IDOMEVENTTARGET_IID, result); + if (rc != XPCOM.NS_OK) error (rc); + if (result[0] == 0) error (XPCOM.NS_ERROR_NO_INTERFACE); + nsIDOMEventTarget target = new nsIDOMEventTarget (result[0]); + result[0] = 0; + hookDOMListeners (target, isTop); + target.Release (); + } + } domWindow.Release (); /* Index: Eclipse SWT Mozilla/common/org/eclipse/swt/internal/mozilla/nsIWebBrowserStream.java =================================================================== RCS file: Eclipse SWT Mozilla/common/org/eclipse/swt/internal/mozilla/nsIWebBrowserStream.java diff -N Eclipse SWT Mozilla/common/org/eclipse/swt/internal/mozilla/nsIWebBrowserStream.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/swt/internal/mozilla/nsIWebBrowserStream.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,55 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by Netscape are Copyright (C) 1998-1999 + * Netscape Communications Corporation. All Rights Reserved. + * + * Contributor(s): + * + * IBM + * - Binding to permit interfacing between Mozilla and SWT + * - Copyright (C) 2003, 2009 IBM Corp. All Rights Reserved. + * + * ***** END LICENSE BLOCK ***** */ +package org.eclipse.swt.internal.mozilla; + +public class nsIWebBrowserStream extends nsISupports { + + static final int LAST_METHOD_ID = nsISupports.LAST_METHOD_ID + 3; + + public static final String NS_IWEBBROWSERSTREAM_IID_STR = + "86d02f0e-219b-4cfc-9c88-bd98d2cce0b8"; + + public static final nsID NS_IWEBBROWSERSTREAM_IID = + new nsID(NS_IWEBBROWSERSTREAM_IID_STR); + + public nsIWebBrowserStream(long /*int*/ address) { + super(address); + } + + public int OpenStream(long /*int*/ aBaseURI, long /*int*/ aContentType) { + return XPCOM.VtblCall(nsISupports.LAST_METHOD_ID + 1, getAddress(), aBaseURI, aContentType); + } + + public int AppendToStream(long /*int*/ aData, int aLen) { + return XPCOM.VtblCall(nsISupports.LAST_METHOD_ID + 2, getAddress(), aData, aLen); + } + + public int CloseStream() { + return XPCOM.VtblCall(nsISupports.LAST_METHOD_ID + 3, getAddress()); + } +}