Blob Blame History Raw
### Eclipse Workspace Patch 1.0
#P org.eclipse.swt
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
--- Eclipse SWT Mozilla/common/org/eclipse/swt/browser/Mozilla.java	21 Aug 2008 16:02:30 -0000	1.105.2.3
+++ Eclipse SWT Mozilla/common/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;
@@ -1168,21 +1169,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 ();
 
 				dialogFactory.isPre_1_9 = false;
 			}
@@ -1264,6 +1265,7 @@
 }
 
 public boolean back () {
+	htmlBytes = null;
 	if (awaitingNavigate) return false;
 
 	int /*long*/[] result = new int /*long*/[1];
@@ -1466,6 +1468,7 @@
 }
 
 public boolean forward () {
+	htmlBytes = null;
 	if (awaitingNavigate) return false;
 
 	int /*long*/[] result = new int /*long*/[1];
@@ -1676,6 +1679,7 @@
 	webBrowser.Release ();
 	webBrowser = null;
 	webBrowserObject = null;
+	htmlBytes = null;
 
 	if (tip != null && !tip.isDisposed ()) tip.dispose ();
 	tip = null;
@@ -1737,6 +1741,7 @@
 }
 
 public void refresh () {
+	htmlBytes = null;
 	if (awaitingNavigate) return;
 
 	int /*long*/[] result = new int /*long*/[1];
@@ -1858,11 +1863,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);
@@ -1877,6 +1916,7 @@
 }
 
 public boolean setUrl (String url) {
+	htmlBytes = null;
 	awaitingNavigate = false;
 
 	int /*long*/[] result = new int /*long*/[1];
@@ -1893,6 +1933,7 @@
 }
 
 public void stop () {
+	htmlBytes = null;
 	if (awaitingNavigate) return;
 
 	int /*long*/[] result = new int /*long*/[1];
@@ -2215,6 +2256,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);
+			int /*long*/ name = XPCOM.nsEmbedCString_new ();
+			rc = req.GetName (name);
+			if (rc != XPCOM.NS_OK) error (rc);
+			int length = XPCOM.nsEmbedCString_Length (name);
+			int /*long*/ 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);
+				int /*long*/ 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$
+				int /*long*/ aContentType = XPCOM.nsEmbedCString_new (contentTypeBuffer, contentTypeBuffer.length);
+
+				rc = stream.OpenStream (uri.getAddress (), aContentType);
+				if (rc != XPCOM.NS_OK) error (rc);
+				int /*long*/ ptr = C.malloc (htmlBytes.length);
+				XPCOM.memmove (ptr, htmlBytes, htmlBytes.length);
+				int pageSize = 8192;
+				int pageCount = htmlBytes.length / pageSize + 1;
+				int /*long*/ 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
+++ Eclipse SWT Mozilla/common/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(int /*long*/ address) {
+		super(address);
+	}
+
+	public int OpenStream(int /*long*/ aBaseURI, int /*long*/ aContentType) {
+		return XPCOM.VtblCall(nsISupports.LAST_METHOD_ID + 1, getAddress(), aBaseURI, aContentType);
+	}
+
+	public int AppendToStream(int /*long*/ 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());
+	}
+}