diff --git a/embedding/browser/gtk/Makefile.in b/embedding/browser/gtk/Makefile.in
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/Makefile.in
@@ -0,0 +1,54 @@
+# 
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.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 the Mozilla browser.
+#
+# The Initial Developer of the Original Code is
+# Christopher Blizzard.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Christopher Blizzard <blizzard@mozilla.org>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE		= gtkembedmoz
+
+DIRS=src
+
+ifdef ENABLE_TESTS
+TOOL_DIRS  += tests
+endif
+
+include $(topsrcdir)/config/rules.mk
diff --git a/embedding/browser/gtk/src/EmbedCertificates.cpp b/embedding/browser/gtk/src/EmbedCertificates.cpp
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/EmbedCertificates.cpp
@@ -0,0 +1,253 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 tw=80 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Terry Hayes <thayes@netscape.com>
+ *   Javier Delgadillo <javi@netscape.com>
+ *   Oleg Romashin <romaxa@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/**
+ * Derived from nsNSSDialogs http://landfill.mozilla.org/mxr-test/seamonkey/source/security/manager/pki/src/nsNSSDialogs.cpp
+ */
+#include <strings.h>
+#include "nsIURI.h"
+#include "EmbedPrivate.h"
+#include "nsServiceManagerUtils.h"
+#include "nsIWebNavigationInfo.h"
+#include "nsDocShellCID.h"
+#include "nsCOMPtr.h"
+#ifdef MOZILLA_INTERNAL_API
+#include "nsString.h"
+#include "nsXPIDLString.h"
+#include "nsReadableUtils.h"
+#else
+#include "nsStringAPI.h"
+#endif
+#include "nsIPrompt.h"
+#include "nsIDOMWindowInternal.h"
+#include "nsIComponentManager.h"
+#include "nsIServiceManager.h"
+#include "nsIStringBundle.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "nsIX509Cert.h"
+#include "nsIX509CertDB.h"
+#include "nsIDateTimeFormat.h"
+#include "nsDateTimeFormatCID.h"
+#include "EmbedCertificates.h"
+#include "nsIKeygenThread.h"
+#include "nsIX509CertValidity.h"
+#include "nsICRLInfo.h"
+#include "gtkmozembed.h"
+
+#define PIPSTRING_BUNDLE_URL "chrome://pippki/locale/pippki.properties"
+
+EmbedCertificates::EmbedCertificates(void)
+{
+}
+
+EmbedCertificates::~EmbedCertificates()
+{
+}
+
+NS_IMPL_THREADSAFE_ADDREF(EmbedCertificates)
+NS_IMPL_THREADSAFE_RELEASE(EmbedCertificates)
+NS_INTERFACE_MAP_BEGIN(EmbedCertificates)
+NS_INTERFACE_MAP_ENTRY(nsITokenPasswordDialogs)
+NS_INTERFACE_MAP_ENTRY(nsICertificateDialogs)
+NS_INTERFACE_MAP_ENTRY(nsIClientAuthDialogs)
+NS_INTERFACE_MAP_ENTRY(nsICertPickDialogs)
+NS_INTERFACE_MAP_ENTRY(nsITokenDialogs)
+NS_INTERFACE_MAP_ENTRY(nsIGeneratingKeypairInfoDialogs)
+NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMCryptoDialogs)
+NS_INTERFACE_MAP_END
+
+nsresult
+EmbedCertificates::Init(void)
+{
+  nsresult rv;
+  nsCOMPtr<nsIStringBundleService> service =
+           do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
+  if (NS_FAILED(rv)) return NS_OK;
+  rv = service->CreateBundle(PIPSTRING_BUNDLE_URL,
+                             getter_AddRefs(mPIPStringBundle));
+  return NS_OK;
+}
+
+nsresult
+EmbedCertificates::SetPassword(nsIInterfaceRequestor *ctx,
+                          const PRUnichar *tokenName, PRBool* _canceled)
+{
+  *_canceled = PR_FALSE;
+  return NS_OK;
+}
+
+nsresult
+EmbedCertificates::GetPassword(nsIInterfaceRequestor *ctx,
+                          const PRUnichar *tokenName,
+                          PRUnichar **_password,
+                          PRBool* _canceled)
+{
+  *_canceled = PR_FALSE;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedCertificates::CrlImportStatusDialog(nsIInterfaceRequestor *ctx, nsICRLInfo *crl)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedCertificates::ConfirmDownloadCACert(nsIInterfaceRequestor *ctx,
+                                    nsIX509Cert *cert,
+                                    PRUint32 *_trust,
+                                    PRBool *_retval)
+{
+  // If an implementation chooses not to implement UI for displaying
+  // the cert and asking the user for confirmation,
+  // then this function must return PR_FALSE.
+  *_retval = PR_FALSE;
+  *_trust = nsIX509CertDB::UNTRUSTED;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedCertificates::NotifyCACertExists(nsIInterfaceRequestor *ctx)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedCertificates::ChooseCertificate(
+  nsIInterfaceRequestor *ctx,
+  const PRUnichar *cn,
+  const PRUnichar *organization,
+  const PRUnichar *issuer,
+  const PRUnichar **certNickList,
+  const PRUnichar **certDetailsList,
+  PRUint32 count,
+  PRInt32 *selectedIndex,
+  PRBool *canceled)
+{
+  *canceled = PR_FALSE;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedCertificates::PickCertificate(
+  nsIInterfaceRequestor *ctx,
+  const PRUnichar **certNickList,
+  const PRUnichar **certDetailsList,
+  PRUint32 count,
+  PRInt32 *selectedIndex,
+  PRBool *canceled)
+{
+  *canceled = PR_FALSE;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedCertificates::SetPKCS12FilePassword(
+  nsIInterfaceRequestor *ctx,
+  nsAString &_password,
+  PRBool *_retval)
+{
+  /* The person who wrote this method implementation did
+   * not read the contract.
+   */
+  *_retval = PR_FALSE;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedCertificates::GetPKCS12FilePassword(
+  nsIInterfaceRequestor *ctx,
+  nsAString &_password,
+  PRBool *_retval)
+{
+  /* The person who wrote this method implementation did
+   * not read the contract.
+   */
+  *_retval = PR_FALSE;
+  return NS_OK;
+}
+
+/* void viewCert (in nsIX509Cert cert); */
+NS_IMETHODIMP
+EmbedCertificates::ViewCert(
+  nsIInterfaceRequestor *ctx,
+  nsIX509Cert *cert)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedCertificates::DisplayGeneratingKeypairInfo(nsIInterfaceRequestor *aCtx, nsIKeygenThread *runnable)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedCertificates::ChooseToken(
+  nsIInterfaceRequestor *aCtx,
+  const PRUnichar **aTokenList,
+  PRUint32 aCount,
+  PRUnichar **aTokenChosen,
+  PRBool *aCanceled)
+{
+  *aCanceled = PR_FALSE;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedCertificates::DisplayProtectedAuth(
+  nsIInterfaceRequestor *aCtx,
+  nsIProtectedAuthThread *runnable)
+{
+  return NS_OK;
+}
+
+/* boolean ConfirmKeyEscrow (in nsIX509Cert escrowAuthority); */
+NS_IMETHODIMP
+EmbedCertificates::ConfirmKeyEscrow(nsIX509Cert *escrowAuthority, PRBool *_retval)
+{
+  // If an implementation chooses not to implement UI that asks the user for 
+  // confirmation to hand out the private key, 
+  // then this function must return PR_FALSE.
+  *_retval = PR_FALSE;
+  return NS_OK;
+}
+
diff --git a/embedding/browser/gtk/src/EmbedCertificates.h b/embedding/browser/gtk/src/EmbedCertificates.h
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/EmbedCertificates.h
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Terry Hayes <thayes@netscape.com>
+ *   Javier Delgadillo <javi@netscape.com>
+ *   Oleg Romashin <romaxa@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/**
+ * Derived from nsNSSDialogs http://landfill.mozilla.org/mxr-test/seamonkey/source/security/manager/pki/src/nsNSSDialogs.h
+ */
+#ifndef __EmbedCertificates_h
+#define __EmbedCertificates_h
+#include "nsITokenPasswordDialogs.h"
+#include "nsICertificateDialogs.h"
+#include "nsIClientAuthDialogs.h"
+#include "nsICertPickDialogs.h"
+#include "nsITokenDialogs.h"
+#include "nsIDOMCryptoDialogs.h"
+#include "nsIGenKeypairInfoDlg.h"
+#include "nsCOMPtr.h"
+#include "nsIStringBundle.h"
+#define EMBED_CERTIFICATES_CID \
+  { 0x518e071f, 0x1dd2, 0x11b2, \
+  { 0x93, 0x7e, 0xc4, 0x5f, 0x14, 0xde, 0xf7, 0x78 }}
+#define EMBED_CERTIFICATES_DESCRIPTION "Certificates Listener Impl"
+class EmbedPrivate;
+class EmbedCertificates
+: public nsITokenPasswordDialogs,
+  public nsICertificateDialogs,
+  public nsIClientAuthDialogs,
+  public nsICertPickDialogs,
+  public nsITokenDialogs,
+  public nsIDOMCryptoDialogs,
+  public nsIGeneratingKeypairInfoDialogs
+{
+  public:
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSITOKENPASSWORDDIALOGS
+    NS_DECL_NSICERTIFICATEDIALOGS
+    NS_DECL_NSICLIENTAUTHDIALOGS
+    NS_DECL_NSICERTPICKDIALOGS
+    NS_DECL_NSITOKENDIALOGS
+    NS_DECL_NSIDOMCRYPTODIALOGS
+    NS_DECL_NSIGENERATINGKEYPAIRINFODIALOGS
+    EmbedCertificates();
+    virtual ~EmbedCertificates();
+    nsresult Init(void);
+  protected:
+  nsCOMPtr<nsIStringBundle> mPIPStringBundle;
+};
+#endif /* __EmbedCertificates_h */
diff --git a/embedding/browser/gtk/src/EmbedContentListener.cpp b/embedding/browser/gtk/src/EmbedContentListener.cpp
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/EmbedContentListener.cpp
@@ -0,0 +1,156 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIURI.h"
+
+#include "EmbedContentListener.h"
+#include "EmbedPrivate.h"
+
+#include "nsServiceManagerUtils.h"
+#include "nsIWebNavigationInfo.h"
+#include "nsDocShellCID.h"
+
+EmbedContentListener::EmbedContentListener(void)
+{
+  mOwner = nsnull;
+}
+
+EmbedContentListener::~EmbedContentListener()
+{
+}
+
+NS_IMPL_ISUPPORTS2(EmbedContentListener,
+                   nsIURIContentListener,
+                   nsISupportsWeakReference)
+
+nsresult
+EmbedContentListener::Init(EmbedPrivate *aOwner)
+{
+  mOwner = aOwner;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedContentListener::OnStartURIOpen(nsIURI     *aURI,
+				     PRBool     *aAbortOpen)
+{
+  nsresult rv;
+
+  nsCAutoString specString;
+  rv = aURI->GetSpec(specString);
+
+  if (NS_FAILED(rv))
+    return rv;
+
+  gint return_val = FALSE;
+  g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                moz_embed_signals[OPEN_URI], 0,
+                specString.get(), &return_val);
+
+  *aAbortOpen = return_val;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedContentListener::DoContent(const char         *aContentType,
+				PRBool             aIsContentPreferred,
+				nsIRequest         *aRequest,
+				nsIStreamListener **aContentHandler,
+				PRBool             *aAbortProcess)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+EmbedContentListener::IsPreferred(const char        *aContentType,
+				  char             **aDesiredContentType,
+				  PRBool            *aCanHandleContent)
+{
+  return CanHandleContent(aContentType, PR_TRUE, aDesiredContentType,
+			  aCanHandleContent);
+}
+
+NS_IMETHODIMP
+EmbedContentListener::CanHandleContent(const char        *aContentType,
+				       PRBool           aIsContentPreferred,
+				       char             **aDesiredContentType,
+				       PRBool            *_retval)
+{
+  *_retval = PR_FALSE;
+  *aDesiredContentType = nsnull;
+  
+  if (aContentType) {
+    nsCOMPtr<nsIWebNavigationInfo> webNavInfo(
+           do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID));
+    if (webNavInfo) {
+      PRUint32 canHandle;
+      nsresult rv =
+	webNavInfo->IsTypeSupported(nsDependentCString(aContentType),
+				    mOwner ? mOwner->mNavigation.get() : nsnull,
+				    &canHandle);
+      NS_ENSURE_SUCCESS(rv, rv);
+      *_retval = (canHandle != nsIWebNavigationInfo::UNSUPPORTED);
+    }
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedContentListener::GetLoadCookie(nsISupports **aLoadCookie)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+EmbedContentListener::SetLoadCookie(nsISupports *aLoadCookie)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+EmbedContentListener::GetParentContentListener(nsIURIContentListener **aParent)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+EmbedContentListener::SetParentContentListener(nsIURIContentListener *aParent)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
diff --git a/embedding/browser/gtk/src/EmbedContentListener.h b/embedding/browser/gtk/src/EmbedContentListener.h
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/EmbedContentListener.h
@@ -0,0 +1,66 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __EmbedContentListener_h
+#define __EmbedContentListener_h
+
+#include "nsIURIContentListener.h"
+#include "nsWeakReference.h"
+
+class EmbedPrivate;
+
+class EmbedContentListener : public nsIURIContentListener,
+                             public nsSupportsWeakReference
+{
+ public:
+
+  EmbedContentListener();
+  virtual ~EmbedContentListener();
+
+  nsresult Init (EmbedPrivate *aOwner);
+
+  NS_DECL_ISUPPORTS
+
+  NS_DECL_NSIURICONTENTLISTENER
+
+ private:
+
+  EmbedPrivate *mOwner;
+  
+};
+
+#endif /* __EmbedContentListener_h */
diff --git a/embedding/browser/gtk/src/EmbedContextMenuInfo.cpp b/embedding/browser/gtk/src/EmbedContextMenuInfo.cpp
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/EmbedContextMenuInfo.cpp
@@ -0,0 +1,618 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 tw=80 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Oleg Romashin.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Oleg Romashin <romaxa@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "EmbedContextMenuInfo.h"
+#include "nsIImageLoadingContent.h"
+#include "imgILoader.h"
+#include "nsIDOMDocument.h"
+#include "nsIDOMHTMLDocument.h"
+#include "nsIDOMHTMLElement.h"
+#include "nsIDOMHTMLHtmlElement.h"
+#include "nsIDOMHTMLAnchorElement.h"
+#include "nsIDOMHTMLImageElement.h"
+#include "nsIDOMHTMLAreaElement.h"
+#include "nsIDOMHTMLLinkElement.h"
+#include "nsIDOMDocumentView.h"
+#include "nsIDOMAbstractView.h"
+#include "nsIDOMViewCSS.h"
+#include "nsIDOMCSSStyleDeclaration.h"
+#include "nsIDOMCSSValue.h"
+#include "nsIDOMCSSPrimitiveValue.h"
+#include "nsNetUtil.h"
+#include "nsUnicharUtils.h"
+#include "nsIDOMMouseEvent.h"
+#include "nsIDOMNSEvent.h"
+#include "nsIDOMWindow.h"
+#include "nsIDOMWindowCollection.h"
+#include "nsIWebBrowser.h"
+#include "nsIContent.h"
+#include "nsIPresShell.h"
+#include "nsIFormControl.h"
+#include "nsIDOMNSHTMLTextAreaElement.h"
+#include "nsIDOMHTMLInputElement.h"
+#include "nsIDOMHTMLTextAreaElement.h"
+#include "nsIDOMNSHTMLDocument.h"
+#include "nsIDOMNodeList.h"
+#include "nsISelection.h"
+#include "nsIDocument.h"
+#include "EmbedPrivate.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <glib.h>
+#if defined(FIXED_BUG347731) || !defined(MOZ_ENABLE_LIBXUL)
+#include "nsIFrame.h"
+#endif
+
+//*****************************************************************************
+// class EmbedContextMenuInfo
+//*****************************************************************************
+EmbedContextMenuInfo::EmbedContextMenuInfo(EmbedPrivate *aOwner) : mCtxFrameNum(-1), mEmbedCtxType(0)
+{
+  mOwner = aOwner;
+  mEventNode = nsnull;
+  mCtxDocument = nsnull;
+  mNSHHTMLElement = nsnull;
+  mNSHHTMLElementSc = nsnull;
+  mCtxEvent = nsnull;
+  mEventNode = nsnull;
+  mFormRect = nsIntRect(0,0,0,0);
+}
+
+EmbedContextMenuInfo::~EmbedContextMenuInfo(void)
+{
+  mEventNode = nsnull;
+  mCtxDocument = nsnull;
+  mNSHHTMLElement = nsnull;
+  mNSHHTMLElementSc = nsnull;
+  mCtxEvent = nsnull;
+  mEventNode = nsnull;
+}
+
+NS_IMPL_ADDREF(EmbedContextMenuInfo)
+NS_IMPL_RELEASE(EmbedContextMenuInfo)
+NS_INTERFACE_MAP_BEGIN(EmbedContextMenuInfo)
+NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+nsresult
+EmbedContextMenuInfo::SetFrameIndex()
+{
+  nsCOMPtr<nsIDOMWindowCollection> frames;
+  mCtxDomWindow->GetFrames(getter_AddRefs(frames));
+  nsCOMPtr<nsIDOMWindow> currentWindow;
+  PRUint32 frameCount = 0;
+  frames->GetLength(&frameCount);
+  for (unsigned int i= 0; i < frameCount; i++) {
+    frames->Item(i, getter_AddRefs(currentWindow));
+    nsCOMPtr<nsIDOMDocument> currentDoc;
+    currentWindow->GetDocument(getter_AddRefs(currentDoc));
+    if (currentDoc == mCtxDocument) {
+      mCtxFrameNum = i;
+      mCtxDomWindow = currentWindow;
+      nsCOMPtr<nsIDOMNSDocument> doc = do_QueryInterface(currentDoc);
+      if (doc)
+        doc->GetTitle(mCtxDocTitle);
+      return NS_OK;
+    }
+  }
+  return NS_ERROR_FAILURE;
+}
+
+nsresult
+EmbedContextMenuInfo::GetFormControlType(nsIDOMEvent* aEvent)
+{
+  if (!aEvent)
+    return NS_OK;
+  nsCOMPtr<nsIDOMNSEvent> nsevent(do_QueryInterface(aEvent));
+  nsCOMPtr<nsIDOMEventTarget> target;
+  nsevent->GetOriginalTarget(getter_AddRefs(target));
+  //    mOrigTarget  = target;
+  if (SetFormControlType(target)) {
+    nsCOMPtr<nsIDOMNode> eventNode = do_QueryInterface(target);
+    if (!eventNode)
+      return NS_OK;
+    //Frame Stuff
+    nsCOMPtr<nsIDOMDocument> domDoc;
+    nsresult rv = eventNode->GetOwnerDocument(getter_AddRefs(domDoc));
+    if (!NS_SUCCEEDED(rv) || !domDoc) {
+      return NS_OK;
+    }
+    mEventNode = eventNode;
+    mCtxDocument = domDoc;
+    nsCOMPtr<nsIDocument> doc = do_QueryInterface(mCtxDocument);
+    if (!doc)
+      return NS_OK;
+    nsIPresShell *presShell = doc->GetShell();
+    if (!presShell)
+      return NS_OK;
+    nsCOMPtr<nsIContent> tgContent = do_QueryInterface(mEventTarget);
+    nsIFrame* frame = nsnull;
+#if defined(FIXED_BUG347731) || !defined(MOZ_ENABLE_LIBXUL)
+    frame = tgContent->GetDocument() == presShell->GetDocument() ?
+      tgContent->GetPrimaryFrame() : nsnull;
+    if (frame)
+      mFormRect = frame->GetScreenRectExternal();
+#endif
+    return NS_OK;
+  }
+  return NS_ERROR_FAILURE;
+}
+
+nsresult
+EmbedContextMenuInfo::SetFormControlType(nsIDOMEventTarget *originalTarget)
+{
+  nsresult rv = NS_ERROR_FAILURE;
+  nsCOMPtr<nsIContent> targetContent = do_QueryInterface(originalTarget);
+  mCtxFormType = 0;
+  if (targetContent && targetContent->IsNodeOfType(nsIContent::eHTML_FORM_CONTROL)) {
+    nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(targetContent));
+    if (formControl) {
+      mCtxFormType = formControl->GetType();
+      rv = NS_OK;
+      //#ifdef MOZ_LOGGING
+      switch (mCtxFormType) {
+      case NS_FORM_BUTTON_BUTTON:
+        break;
+      case NS_FORM_BUTTON_RESET:
+        break;
+      case NS_FORM_BUTTON_SUBMIT:
+        break;
+      case NS_FORM_INPUT_BUTTON:
+        break;
+      case NS_FORM_INPUT_CHECKBOX:
+        break;
+      case NS_FORM_INPUT_FILE:
+        mEmbedCtxType |= GTK_MOZ_EMBED_CTX_INPUT;
+        break;
+      case NS_FORM_INPUT_HIDDEN:
+        break;
+      case NS_FORM_INPUT_RESET:
+        break;
+      case NS_FORM_INPUT_IMAGE:
+        break;
+      case NS_FORM_INPUT_PASSWORD:
+        mEmbedCtxType |= GTK_MOZ_EMBED_CTX_INPUT;
+        mEmbedCtxType |= GTK_MOZ_EMBED_CTX_IPASSWORD;
+        break;
+      case NS_FORM_INPUT_RADIO:
+        break;
+      case NS_FORM_INPUT_SUBMIT:
+        break;
+      case NS_FORM_INPUT_EMAIL:
+      case NS_FORM_INPUT_SEARCH:
+      case NS_FORM_INPUT_TEXT:
+      case NS_FORM_INPUT_TEL:
+      case NS_FORM_INPUT_URL:
+        mEmbedCtxType |= GTK_MOZ_EMBED_CTX_INPUT;
+        break;
+      case NS_FORM_LABEL:
+        break;
+      case NS_FORM_SELECT:
+        break;
+      case NS_FORM_TEXTAREA:
+        mEmbedCtxType |= GTK_MOZ_EMBED_CTX_INPUT;
+        break;
+      case NS_FORM_OBJECT:
+        break;
+      case NS_FORM_OUTPUT:
+        break;
+      default:
+        break;
+      }
+      if (mEmbedCtxType & GTK_MOZ_EMBED_CTX_INPUT) {
+        PRBool rdonly = PR_FALSE;
+        if (mCtxFormType == NS_FORM_TEXTAREA) {
+          nsCOMPtr<nsIDOMHTMLTextAreaElement> input;
+          input = do_QueryInterface(mEventNode, &rv);
+          if (!NS_FAILED(rv) && input)
+            rv = input->GetReadOnly(&rdonly);
+          if (!NS_FAILED(rv) && rdonly) {
+            mEmbedCtxType |= GTK_MOZ_EMBED_CTX_ROINPUT;
+          }
+        } else {
+          nsCOMPtr<nsIDOMHTMLInputElement> input;
+          input = do_QueryInterface(mEventNode, &rv);
+          if (!NS_FAILED(rv) && input)
+            rv = input->GetReadOnly(&rdonly);
+          if (!NS_FAILED(rv) && rdonly) {
+            mEmbedCtxType |= GTK_MOZ_EMBED_CTX_ROINPUT;
+          }
+        }
+      }
+      //#endif
+    }
+  }
+  return rv;
+}
+
+const char*
+EmbedContextMenuInfo::GetSelectedText()
+{
+  nsString cString;
+  nsresult rv = NS_ERROR_FAILURE;
+  if (mCtxFormType != 0 && mEventNode) {
+    PRInt32 TextLength = 0, selStart = 0, selEnd = 0;
+    if (mCtxFormType == NS_FORM_INPUT_TEXT || mCtxFormType == NS_FORM_INPUT_FILE) {
+      nsCOMPtr<nsIDOMHTMLInputElement> nsinput = do_QueryInterface(mEventNode, &rv);
+      if (NS_SUCCEEDED(rv) && nsinput)
+        nsinput->GetTextLength(&TextLength);
+      if (TextLength > 0) {
+        nsinput->GetSelectionEnd(&selEnd);
+        nsinput->GetSelectionStart(&selStart);
+        if (selStart < selEnd || mCtxFormType == NS_FORM_INPUT_FILE) {
+          nsCOMPtr<nsIDOMHTMLInputElement> input = do_QueryInterface(mEventNode, &rv);
+          rv = input->GetValue(cString);
+        }
+      }
+    } else if (mCtxFormType == NS_FORM_TEXTAREA) {
+      nsCOMPtr<nsIDOMNSHTMLTextAreaElement> nsinput = do_QueryInterface(mEventNode, &rv);
+      if (NS_SUCCEEDED(rv) && nsinput)
+        nsinput->GetTextLength(&TextLength);
+      if (TextLength > 0) {
+        nsinput->GetSelectionStart(&selStart);
+        nsinput->GetSelectionEnd(&selEnd);
+        if (selStart < selEnd) {
+          nsCOMPtr<nsIDOMHTMLTextAreaElement> input = do_QueryInterface(mEventNode, &rv);
+          rv = input->GetValue(cString);
+        }
+      }
+    }
+    if (NS_SUCCEEDED(rv) && !cString.IsEmpty()) {
+      if (selStart < selEnd) {
+        cString.Cut(0, selStart);
+        cString.Cut(selEnd-selStart, TextLength);
+      }
+      rv = NS_OK;
+    }
+  } else if (mCtxDocument) {
+    nsCOMPtr<nsIDOMNSHTMLDocument> htmlDoc = do_QueryInterface(mCtxDocument, &rv);
+    if (NS_FAILED(rv) || !htmlDoc)
+      return nsnull;
+    rv = htmlDoc->GetSelection(cString);
+    if (NS_FAILED(rv) || cString.IsEmpty())
+      return nsnull;
+    rv = NS_OK;
+  }
+  if (rv == NS_OK) {
+    return NS_ConvertUTF16toUTF8(cString).get();
+  }
+  return nsnull;
+}
+
+nsresult
+EmbedContextMenuInfo::CheckDomImageElement(nsIDOMNode *node, nsString& aHref,
+                                           PRInt32 *aWidth, PRInt32 *aHeight)
+{
+  nsresult rv = NS_ERROR_FAILURE;
+  nsCOMPtr<nsIDOMHTMLImageElement> image =
+    do_QueryInterface(node, &rv);
+  if (image) {
+    rv = image->GetSrc(aHref);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = image->GetWidth(aWidth);
+    rv = image->GetHeight(aHeight);
+    rv = NS_OK;
+  }
+  return rv;
+}
+
+nsresult
+EmbedContextMenuInfo::GetImageRequest(imgIRequest **aRequest, nsIDOMNode *aDOMNode)
+{
+  NS_ENSURE_ARG(aDOMNode);
+  NS_ENSURE_ARG_POINTER(aRequest);
+
+  // Get content
+  nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(aDOMNode));
+  NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
+
+  return content->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
+                             aRequest);
+}
+
+nsresult
+EmbedContextMenuInfo::CheckDomHtmlNode(nsIDOMNode *aNode)
+{
+  nsresult rv = NS_ERROR_FAILURE;
+  nsString uTag;
+  PRUint16 dnode_type;
+
+  nsCOMPtr<nsIDOMNode> node;
+  if (!aNode && mEventNode)
+    node = mEventNode;
+  nsCOMPtr<nsIDOMHTMLElement> element  = do_QueryInterface(node, &rv);
+  if (!element) {
+    element = do_QueryInterface(mOrigNode, &rv);
+    if (element) {
+      node = mOrigNode;
+      element  = do_QueryInterface(node, &rv);
+    }
+  }
+
+  rv = node->GetNodeType(&dnode_type);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  if (!((nsIDOMNode::ELEMENT_NODE == dnode_type) && element)) {
+    return rv;
+  }
+  nsCOMPtr<nsIDOMNSHTMLElement> nodeElement = do_QueryInterface(node, &rv);
+  if (NS_SUCCEEDED(rv) && nodeElement) {
+    mNSHHTMLElement = nodeElement;
+  } else {
+    mNSHHTMLElement = nsnull;
+  }
+  rv = element->GetLocalName(uTag);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  if (uTag.LowerCaseEqualsLiteral("object")) {
+  }
+  else if (uTag.LowerCaseEqualsLiteral("html")) {
+  }
+  else if (uTag.LowerCaseEqualsLiteral("a")) {
+    nsCOMPtr<nsIDOMHTMLAnchorElement> anchor = do_QueryInterface(node);
+    anchor->GetHref(mCtxHref);
+    mEmbedCtxType |= GTK_MOZ_EMBED_CTX_LINK;
+    if (anchor && !mCtxHref.IsEmpty()) {
+      if (mCtxHref.LowerCaseEqualsLiteral("text/smartbookmark")) {
+        nsCOMPtr<nsIDOMNode> childNode;
+        node->GetFirstChild(getter_AddRefs(childNode));
+        if (childNode) {
+          PRInt32 width, height;
+          rv = CheckDomImageElement(node, mCtxImgHref, &width, &height);
+          if (NS_SUCCEEDED(rv))
+            mEmbedCtxType |= GTK_MOZ_EMBED_CTX_IMAGE;
+        }
+      } else if (StringBeginsWith(mCtxHref, NS_LITERAL_STRING("mailto:"))) {
+        mEmbedCtxType |= GTK_MOZ_EMBED_CTX_EMAIL;
+      }
+    }
+  }
+  else if (uTag.LowerCaseEqualsLiteral("area")) {
+    nsCOMPtr<nsIDOMHTMLAreaElement> area = do_QueryInterface(node, &rv);
+    if (NS_SUCCEEDED(rv) && area) {
+      PRBool aNoHref = PR_FALSE;
+      rv = area->GetNoHref(&aNoHref);
+      if (!aNoHref)
+        rv = area->GetHref(mCtxHref);
+      else
+        rv = area->GetTarget(mCtxHref);
+      mEmbedCtxType |= GTK_MOZ_EMBED_CTX_LINK;
+      rv = NS_OK;
+    }
+  }
+  else if (uTag.LowerCaseEqualsLiteral("img")) {
+    PRInt32 width, height;
+    rv = CheckDomImageElement(node, mCtxImgHref, &width, &height);
+    if (NS_SUCCEEDED(rv))
+      mEmbedCtxType |= GTK_MOZ_EMBED_CTX_IMAGE;
+  } else {
+    rv = NS_ERROR_FAILURE;
+  }
+  return rv;
+}
+
+nsresult
+EmbedContextMenuInfo::UpdateContextData(void *aEvent)
+{
+  NS_ENSURE_ARG_POINTER(aEvent);
+  nsresult rv;
+  nsCOMPtr<nsIDOMEvent> event = do_QueryInterface((nsISupports*)aEvent, &rv);
+  if (NS_FAILED(rv) || !event)
+    return NS_ERROR_FAILURE;
+  return UpdateContextData(event);
+}
+
+nsresult
+EmbedContextMenuInfo::GetElementForScroll(nsIDOMEvent *aEvent)
+{
+  if (!aEvent) return NS_ERROR_UNEXPECTED;
+  nsCOMPtr<nsIDOMNSEvent> nsevent(do_QueryInterface(aEvent));
+  nsCOMPtr<nsIDOMEventTarget> target;
+  nsevent->GetOriginalTarget(getter_AddRefs(target));
+  if (!target) return NS_ERROR_UNEXPECTED;
+  nsCOMPtr<nsIDOMNode> targetDOMNode(do_QueryInterface(target));
+  if (!targetDOMNode) return NS_ERROR_UNEXPECTED;
+  nsCOMPtr<nsIDOMDocument> targetDOMDocument;
+  targetDOMNode->GetOwnerDocument(getter_AddRefs(targetDOMDocument));
+  if (!targetDOMDocument) return NS_ERROR_UNEXPECTED;
+  return GetElementForScroll(targetDOMDocument);
+}
+
+nsresult
+EmbedContextMenuInfo::GetElementForScroll(nsIDOMDocument *targetDOMDocument)
+{
+  nsCOMPtr<nsIDOMElement> targetDOMElement;
+  targetDOMDocument->GetDocumentElement(getter_AddRefs(targetDOMElement));
+  if (!targetDOMElement) return NS_ERROR_UNEXPECTED;
+  nsString bodyName(NS_LITERAL_STRING("body"));
+  nsCOMPtr<nsIDOMNodeList> bodyList;
+  targetDOMElement->GetElementsByTagName(bodyName, getter_AddRefs(bodyList));
+  PRUint32 i = 0;
+  bodyList->GetLength(&i);
+  if (i) {
+    nsCOMPtr<nsIDOMNode> domBodyNode;
+    bodyList->Item(0, getter_AddRefs(domBodyNode));
+    if (!domBodyNode) return NS_ERROR_UNEXPECTED;
+    mNSHHTMLElementSc = do_QueryInterface(domBodyNode);
+    if (!mNSHHTMLElementSc) return NS_ERROR_UNEXPECTED;
+  }
+  return NS_OK;
+}
+
+nsresult
+EmbedContextMenuInfo::UpdateContextData(nsIDOMEvent *aDOMEvent)
+{
+  if (mCtxEvent == aDOMEvent)
+    return NS_OK;
+
+  nsresult rv = nsnull;
+  mCtxEvent = aDOMEvent;
+  NS_ENSURE_ARG_POINTER(mCtxEvent);
+
+  PRUint16 eventphase;
+  mCtxEvent->GetEventPhase(&eventphase);
+  if (!eventphase) {
+    mCtxEvent = nsnull;
+    return NS_ERROR_FAILURE;
+  }
+
+  nsCOMPtr<nsIDOMEventTarget> originalTarget = nsnull;
+  nsCOMPtr<nsIDOMNode> originalNode = nsnull;
+
+  nsCOMPtr<nsIDOMNSEvent> aEvent = do_QueryInterface(mCtxEvent, &rv);
+  if (NS_FAILED(rv) || !aEvent)
+    return NS_OK;
+
+  nsCOMPtr<nsIDOMMouseEvent> mouseEvent(do_QueryInterface(mCtxEvent, &rv));
+  if (mouseEvent) {
+    ((nsIDOMMouseEvent*)mouseEvent)->GetClientX(&mX);
+    ((nsIDOMMouseEvent*)mouseEvent)->GetClientY(&mY);
+  }
+
+  if (aEvent)
+    rv = aEvent->GetOriginalTarget(getter_AddRefs(originalTarget));
+  originalNode = do_QueryInterface(originalTarget);
+  if (NS_FAILED(rv) || !originalNode)
+    return NS_ERROR_NULL_POINTER;
+
+  //    nsresult SelText = mOwner->ClipBoardAction(GTK_MOZ_EMBED_CAN_COPY);
+  if (originalNode == mOrigNode)
+    return NS_OK;
+
+  mEmbedCtxType = GTK_MOZ_EMBED_CTX_NONE;
+  mOrigNode = originalNode;
+  if (mOrigNode) {
+    nsString SOrigNode;
+    mOrigNode->GetNodeName(SOrigNode);
+    if (SOrigNode.EqualsLiteral("#document"))
+      return NS_OK;
+    if (SOrigNode.EqualsLiteral("xul:thumb")
+        || SOrigNode.EqualsLiteral("xul:slider")
+        || SOrigNode.EqualsLiteral("xul:scrollbarbutton")
+        || SOrigNode.EqualsLiteral("xul:vbox")
+        || SOrigNode.EqualsLiteral("xul:spacer")) {
+      mEmbedCtxType |= GTK_MOZ_EMBED_CTX_XUL;
+      return NS_OK;
+    }
+  }
+  if (mCtxEvent)
+    rv = mCtxEvent->GetTarget(getter_AddRefs(mEventTarget));
+  if (NS_FAILED(rv) || !mEventTarget) {
+    return NS_OK;
+  }
+  nsCOMPtr<nsIDOMNode> eventNode = do_QueryInterface(mEventTarget, &rv);
+  mEventNode = eventNode;
+  //Frame Stuff
+  nsCOMPtr<nsIDOMDocument> domDoc;
+  if (mEventNode)
+    rv = mEventNode->GetOwnerDocument(getter_AddRefs(domDoc));
+  if (!NS_SUCCEEDED(rv) || !domDoc) {
+    //  return NS_OK;
+  }
+  if (NS_SUCCEEDED(rv) && domDoc && mCtxDocument != domDoc) {
+    mCtxDocument = domDoc;
+    mNSHHTMLElementSc = nsnull;
+    mCtxDocument->GetDocumentURI(mCtxURI);
+    NS_ENSURE_ARG_POINTER(mOwner);
+    nsCOMPtr<nsIWebBrowser> webBrowser;
+    mOwner->mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+    webBrowser->GetContentDOMWindow(getter_AddRefs(mCtxDomWindow));
+    nsCOMPtr<nsIDOMDocument> mainDocument;
+    mCtxDomWindow->GetDocument(getter_AddRefs(mainDocument));
+    if (!mainDocument) {
+      return NS_OK;
+    }
+    mCtxFrameNum = -1;
+    if (mainDocument != domDoc) {
+      mEmbedCtxType |= GTK_MOZ_EMBED_CTX_IFRAME;
+      SetFrameIndex();
+    }
+  }
+  nsCOMPtr<nsIDOMElement> targetDOMElement;
+  mCtxDocument->GetDocumentElement(getter_AddRefs(targetDOMElement));
+  if (!targetDOMElement) return NS_ERROR_UNEXPECTED;
+  nsCOMPtr<nsIDOMNSHTMLDocument> htmlDoc = do_QueryInterface(mCtxDocument);
+  if (htmlDoc) {
+    nsString DMode;
+    htmlDoc->GetDesignMode(DMode);
+    if (DMode.EqualsLiteral("on")) {
+      mEmbedCtxType |= GTK_MOZ_EMBED_CTX_INPUT;
+      mEmbedCtxType |= GTK_MOZ_EMBED_CTX_RICHEDIT;
+    }
+  }
+  nsCOMPtr<nsIDocument> doc = do_QueryInterface(mCtxDocument);
+  if (!doc)
+    return NS_OK;
+  nsIPresShell *presShell = doc->GetShell();
+  if (!presShell)
+    return NS_OK;
+  nsCOMPtr<nsIContent> tgContent = do_QueryInterface(mEventTarget);
+  nsIFrame* frame = nsnull;
+#if defined(FIXED_BUG347731) || !defined(MOZ_ENABLE_LIBXUL)
+  if (mEmbedCtxType & GTK_MOZ_EMBED_CTX_RICHEDIT)
+    frame = presShell->GetRootFrame();
+  else if (tgContent->GetDocument() == presShell->GetDocument()) {
+    frame = tgContent->GetPrimaryFrame();
+  }
+  if (frame) {
+    mFormRect = frame->GetScreenRectExternal();
+  }
+#endif
+  if (NS_SUCCEEDED(SetFormControlType(mEventTarget))) {
+    return NS_OK;
+  }
+  CheckDomHtmlNode();
+  nsCOMPtr<nsIDOMNode> node = mEventNode;
+  nsCOMPtr<nsIDOMNode> parentNode;
+  node->GetParentNode(getter_AddRefs(parentNode));
+  node = parentNode;
+  while (node) {
+    if (NS_FAILED(CheckDomHtmlNode()))
+      break;
+    node->GetParentNode(getter_AddRefs(parentNode));
+    node = parentNode;
+  }
+  mEmbedCtxType |= GTK_MOZ_EMBED_CTX_DOCUMENT;
+  return NS_OK;
+}
diff --git a/embedding/browser/gtk/src/EmbedContextMenuInfo.h b/embedding/browser/gtk/src/EmbedContextMenuInfo.h
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/EmbedContextMenuInfo.h
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 tw=80 et cindent: */
+/*
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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 the Mozilla browser.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Oleg Romashin.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Oleg Romashin <romaxa@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef EmbedContextMenuInfo_h__
+#define EmbedContextMenuInfo_h__
+#include "nsCOMPtr.h"
+#include "nsIDOMNode.h"
+#include "nsIDOMEvent.h"
+#include "imgIContainer.h"
+#include "imgIRequest.h"
+#include "nsIDOMEventTarget.h"
+#include "nsRect.h"
+// for strings
+#ifdef MOZILLA_INTERNAL_API
+#include "nsXPIDLString.h"
+#include "nsReadableUtils.h"
+#endif
+#include "EmbedWindow.h"
+#include "nsIDOMNSHTMLElement.h"
+//*****************************************************************************
+// class EmbedContextMenuInfo
+//
+//*****************************************************************************
+class EmbedContextMenuInfo : public nsISupports
+{
+public:
+  EmbedContextMenuInfo(EmbedPrivate *aOwner);
+  virtual ~EmbedContextMenuInfo(void);
+  NS_DECL_ISUPPORTS
+  nsresult          GetFormControlType(nsIDOMEvent *aDOMEvent);
+  nsresult          UpdateContextData(nsIDOMEvent *aDOMEvent);
+  nsresult          UpdateContextData(void *aEvent);
+  const char*       GetSelectedText();
+  nsresult          GetElementForScroll(nsIDOMDocument *targetDOMDocument);
+  nsresult          GetElementForScroll(nsIDOMEvent *aEvent);
+  nsresult          CheckDomImageElement(nsIDOMNode *node, nsString& aHref,
+                                       PRInt32 *aWidth, PRInt32 *aHeight);
+  nsresult          GetImageRequest(imgIRequest **aRequest, nsIDOMNode *aDOMNode);
+  nsString          GetCtxDocTitle(void) { return mCtxDocTitle; }
+
+
+  PRInt32                 mX, mY, mObjWidth, mObjHeight, mCtxFrameNum;
+  nsString                mCtxURI, mCtxHref, mCtxImgHref;
+  PRUint32                mEmbedCtxType;
+  PRInt32 mCtxFormType;
+  nsCOMPtr<nsIDOMNode>    mEventNode;
+  nsCOMPtr<nsIDOMEventTarget> mEventTarget;
+  nsCOMPtr<nsIDOMDocument>mCtxDocument;
+  nsIntRect               mFormRect;
+  nsCOMPtr<nsIDOMWindow>  mCtxDomWindow;
+  nsCOMPtr<nsIDOMEvent>   mCtxEvent;
+  nsCOMPtr<nsIDOMNSHTMLElement> mNSHHTMLElement;
+  nsCOMPtr<nsIDOMNSHTMLElement> mNSHHTMLElementSc;
+private:
+  nsresult          SetFrameIndex();
+  nsresult          SetFormControlType(nsIDOMEventTarget *originalTarget);
+  nsresult          CheckDomHtmlNode(nsIDOMNode *aNode = nsnull);
+
+  EmbedPrivate           *mOwner;
+  nsCOMPtr<nsIDOMNode>    mOrigNode;
+  nsString                mCtxDocTitle;
+}; // class EmbedContextMenuInfo
+#endif // EmbedContextMenuInfo_h__
diff --git a/embedding/browser/gtk/src/EmbedEventListener.cpp b/embedding/browser/gtk/src/EmbedEventListener.cpp
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/EmbedEventListener.cpp
@@ -0,0 +1,304 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsCOMPtr.h"
+#include "nsIDOMMouseEvent.h"
+
+#include "nsIDOMKeyEvent.h"
+#include "nsIDOMUIEvent.h"
+
+#include "EmbedEventListener.h"
+#include "EmbedPrivate.h"
+
+EmbedEventListener::EmbedEventListener(void)
+{
+  mOwner = nsnull;
+}
+
+EmbedEventListener::~EmbedEventListener()
+{
+}
+
+NS_IMPL_ADDREF(EmbedEventListener)
+NS_IMPL_RELEASE(EmbedEventListener)
+NS_INTERFACE_MAP_BEGIN(EmbedEventListener)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMKeyListener)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMKeyListener)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMUIListener)
+NS_INTERFACE_MAP_END
+
+nsresult
+EmbedEventListener::Init(EmbedPrivate *aOwner)
+{
+  mOwner = aOwner;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedEventListener::HandleEvent(nsIDOMEvent* aDOMEvent)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedEventListener::KeyDown(nsIDOMEvent* aDOMEvent)
+{
+  nsCOMPtr <nsIDOMKeyEvent> keyEvent;
+  keyEvent = do_QueryInterface(aDOMEvent);
+  if (!keyEvent)
+    return NS_OK;
+  // Return FALSE to this function to mark the event as not
+  // consumed...
+  gint return_val = FALSE;
+  g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                moz_embed_signals[DOM_KEY_DOWN], 0,
+                (void *)keyEvent, &return_val);
+  if (return_val) {
+    aDOMEvent->StopPropagation();
+    aDOMEvent->PreventDefault();
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedEventListener::KeyUp(nsIDOMEvent* aDOMEvent)
+{
+  nsCOMPtr <nsIDOMKeyEvent> keyEvent;
+  keyEvent = do_QueryInterface(aDOMEvent);
+  if (!keyEvent)
+    return NS_OK;
+  // return FALSE to this function to mark this event as not
+  // consumed...
+  gint return_val = FALSE;
+  g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                moz_embed_signals[DOM_KEY_UP], 0,
+                (void *)keyEvent, &return_val);
+  if (return_val) {
+    aDOMEvent->StopPropagation();
+    aDOMEvent->PreventDefault();
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedEventListener::KeyPress(nsIDOMEvent* aDOMEvent)
+{
+  nsCOMPtr <nsIDOMKeyEvent> keyEvent;
+  keyEvent = do_QueryInterface(aDOMEvent);
+  if (!keyEvent)
+    return NS_OK;
+  // Return TRUE from your signal handler to mark the event as consumed.
+  gint return_val = FALSE;
+  g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                moz_embed_signals[DOM_KEY_PRESS], 0,
+                (void *)keyEvent, &return_val);
+  if (return_val) {
+    aDOMEvent->StopPropagation();
+    aDOMEvent->PreventDefault();
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedEventListener::MouseDown(nsIDOMEvent* aDOMEvent)
+{
+  nsCOMPtr <nsIDOMMouseEvent> mouseEvent;
+  mouseEvent = do_QueryInterface(aDOMEvent);
+  if (!mouseEvent)
+    return NS_OK;
+  // Return TRUE from your signal handler to mark the event as consumed.
+  gint return_val = FALSE;
+  g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                moz_embed_signals[DOM_MOUSE_DOWN], 0,
+                (void *)mouseEvent, &return_val);
+  if (return_val) {
+    aDOMEvent->StopPropagation();
+    aDOMEvent->PreventDefault();
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedEventListener::MouseUp(nsIDOMEvent* aDOMEvent)
+{
+  nsCOMPtr <nsIDOMMouseEvent> mouseEvent;
+  mouseEvent = do_QueryInterface(aDOMEvent);
+  if (!mouseEvent)
+    return NS_OK;
+  // Return TRUE from your signal handler to mark the event as consumed.
+  gint return_val = FALSE;
+  g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                moz_embed_signals[DOM_MOUSE_UP], 0,
+                (void *)mouseEvent, &return_val);
+  if (return_val) {
+    aDOMEvent->StopPropagation();
+    aDOMEvent->PreventDefault();
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedEventListener::MouseClick(nsIDOMEvent* aDOMEvent)
+{
+  nsCOMPtr <nsIDOMMouseEvent> mouseEvent;
+  mouseEvent = do_QueryInterface(aDOMEvent);
+  if (!mouseEvent)
+    return NS_OK;
+  // Return TRUE from your signal handler to mark the event as consumed.
+  gint return_val = FALSE;
+  g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                moz_embed_signals[DOM_MOUSE_CLICK], 0,
+                (void *)mouseEvent, &return_val);
+  if (return_val) {
+    aDOMEvent->StopPropagation();
+    aDOMEvent->PreventDefault();
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedEventListener::MouseDblClick(nsIDOMEvent* aDOMEvent)
+{
+  nsCOMPtr <nsIDOMMouseEvent> mouseEvent;
+  mouseEvent = do_QueryInterface(aDOMEvent);
+  if (!mouseEvent)
+    return NS_OK;
+  // Return TRUE from your signal handler to mark the event as consumed.
+  gint return_val = FALSE;
+  g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                moz_embed_signals[DOM_MOUSE_DBL_CLICK], 0,
+                (void *)mouseEvent, &return_val);
+  if (return_val) {
+    aDOMEvent->StopPropagation();
+    aDOMEvent->PreventDefault();
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedEventListener::MouseOver(nsIDOMEvent* aDOMEvent)
+{
+  nsCOMPtr <nsIDOMMouseEvent> mouseEvent;
+  mouseEvent = do_QueryInterface(aDOMEvent);
+  if (!mouseEvent)
+    return NS_OK;
+  // Return TRUE from your signal handler to mark the event as consumed.
+  gint return_val = FALSE;
+  g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                moz_embed_signals[DOM_MOUSE_OVER], 0,
+                (void *)mouseEvent, &return_val);
+  if (return_val) {
+    aDOMEvent->StopPropagation();
+    aDOMEvent->PreventDefault();
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedEventListener::MouseOut(nsIDOMEvent* aDOMEvent)
+{
+  nsCOMPtr <nsIDOMMouseEvent> mouseEvent;
+  mouseEvent = do_QueryInterface(aDOMEvent);
+  if (!mouseEvent)
+    return NS_OK;
+  // Return TRUE from your signal handler to mark the event as consumed.
+  gint return_val = FALSE;
+  g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                moz_embed_signals[DOM_MOUSE_OUT], 0,
+                (void *)mouseEvent, &return_val);
+  if (return_val) {
+    aDOMEvent->StopPropagation();
+    aDOMEvent->PreventDefault();
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedEventListener::Activate(nsIDOMEvent* aDOMEvent)
+{
+  nsCOMPtr <nsIDOMUIEvent> uiEvent = do_QueryInterface(aDOMEvent);
+  if (!uiEvent)
+    return NS_OK;
+  // Return TRUE from your signal handler to mark the event as consumed.
+  gint return_val = FALSE;
+  g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                moz_embed_signals[DOM_ACTIVATE], 0,
+                (void *)uiEvent, &return_val);
+  if (return_val) {
+    aDOMEvent->StopPropagation();
+    aDOMEvent->PreventDefault();
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedEventListener::FocusIn(nsIDOMEvent* aDOMEvent)
+{
+  nsCOMPtr <nsIDOMUIEvent> uiEvent = do_QueryInterface(aDOMEvent);
+  if (!uiEvent)
+    return NS_OK;
+  // Return TRUE from your signal handler to mark the event as consumed.
+  gint return_val = FALSE;
+  g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                moz_embed_signals[DOM_FOCUS_IN], 0,
+                (void *)uiEvent, &return_val);
+  if (return_val) {
+    aDOMEvent->StopPropagation();
+    aDOMEvent->PreventDefault();
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedEventListener::FocusOut(nsIDOMEvent* aDOMEvent)
+{
+  nsCOMPtr <nsIDOMUIEvent> uiEvent = do_QueryInterface(aDOMEvent);
+  if (!uiEvent)
+    return NS_OK;
+  // Return TRUE from your signal handler to mark the event as consumed.
+  gint return_val = FALSE;
+  g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                moz_embed_signals[DOM_FOCUS_OUT], 0,
+                (void *)uiEvent, &return_val);
+  if (return_val) {
+    aDOMEvent->StopPropagation();
+    aDOMEvent->PreventDefault();
+  }
+  return NS_OK;
+}
diff --git a/embedding/browser/gtk/src/EmbedEventListener.h b/embedding/browser/gtk/src/EmbedEventListener.h
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/EmbedEventListener.h
@@ -0,0 +1,90 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __EmbedEventListener_h
+#define __EmbedEventListener_h
+
+#include "nsIDOMKeyListener.h"
+#include "nsIDOMMouseListener.h"
+#include "nsIDOMUIListener.h"
+
+class EmbedPrivate;
+
+class EmbedEventListener : public nsIDOMKeyListener,
+                           public nsIDOMMouseListener,
+                           public nsIDOMUIListener
+{
+ public:
+
+  EmbedEventListener();
+  virtual ~EmbedEventListener();
+
+  nsresult Init(EmbedPrivate *aOwner);
+
+  NS_DECL_ISUPPORTS
+
+  // nsIDOMEventListener
+
+  NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
+
+  // nsIDOMKeyListener
+  
+  NS_IMETHOD KeyDown(nsIDOMEvent* aDOMEvent);
+  NS_IMETHOD KeyUp(nsIDOMEvent* aDOMEvent);
+  NS_IMETHOD KeyPress(nsIDOMEvent* aDOMEvent);
+
+  // nsIDOMMouseListener
+
+  NS_IMETHOD MouseDown(nsIDOMEvent* aDOMEvent);
+  NS_IMETHOD MouseUp(nsIDOMEvent* aDOMEvent);
+  NS_IMETHOD MouseClick(nsIDOMEvent* aDOMEvent);
+  NS_IMETHOD MouseDblClick(nsIDOMEvent* aDOMEvent);
+  NS_IMETHOD MouseOver(nsIDOMEvent* aDOMEvent);
+  NS_IMETHOD MouseOut(nsIDOMEvent* aDOMEvent);
+
+  // nsIDOMUIListener
+
+  NS_IMETHOD Activate(nsIDOMEvent* aDOMEvent);
+  NS_IMETHOD FocusIn(nsIDOMEvent* aDOMEvent);
+  NS_IMETHOD FocusOut(nsIDOMEvent* aDOMEvent);
+
+ private:
+
+  EmbedPrivate *mOwner;
+};
+
+#endif /* __EmbedEventListener_h */
diff --git a/embedding/browser/gtk/src/EmbedGtkTools.cpp b/embedding/browser/gtk/src/EmbedGtkTools.cpp
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/EmbedGtkTools.cpp
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=4 sts=2 tw=80 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Oleg Romashin.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Oleg Romashin <romaxa@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "EmbedGtkTools.h"
+#ifndef MOZILLA_INTERNAL_API
+#include "nsServiceManagerUtils.h"
+#endif
+#include "EmbedPrivate.h"
+
+GtkWidget * GetGtkWidgetForDOMWindow(nsIDOMWindow* aDOMWindow)
+{
+  nsCOMPtr<nsIWindowWatcher> wwatch = do_GetService("@mozilla.org/embedcomp/window-watcher;1");
+  if (!aDOMWindow)
+    return NULL;
+  nsCOMPtr<nsIWebBrowserChrome> chrome;
+  wwatch->GetChromeForWindow(aDOMWindow, getter_AddRefs(chrome));
+  if (!chrome) {
+    return GTK_WIDGET(EmbedCommon::GetAnyLiveWidget());
+  }
+
+  nsCOMPtr<nsIEmbeddingSiteWindow> siteWindow = nsnull;
+  siteWindow = do_QueryInterface(chrome);
+
+  if (!siteWindow) {
+    return GTK_WIDGET(EmbedCommon::GetAnyLiveWidget());
+  }
+
+  GtkWidget* parentWidget;
+  siteWindow->GetSiteWindow((void**)&parentWidget);
+  if (GTK_IS_WIDGET(parentWidget))
+    return parentWidget;
+  return NULL;
+}
+
+GtkWindow * GetGtkWindowForDOMWindow(nsIDOMWindow* aDOMWindow)
+{
+  GtkWidget* parentWidget = GetGtkWidgetForDOMWindow(aDOMWindow);
+  if (!parentWidget)
+    return NULL;
+  GtkWidget* gtkWin = gtk_widget_get_toplevel(parentWidget);
+  if (GTK_WIDGET_TOPLEVEL(gtkWin))
+    return GTK_WINDOW(gtkWin);
+  return NULL;
+}
+
+nsresult GetContentViewer(nsIWebBrowser *webBrowser, nsIContentViewer **aViewer)
+{
+  g_return_val_if_fail(webBrowser, NS_ERROR_FAILURE);
+  nsCOMPtr<nsIDocShell> docShell(do_GetInterface((nsISupports*)webBrowser));
+  NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
+  return docShell->GetContentViewer(aViewer);
+}
diff --git a/embedding/browser/gtk/src/EmbedGtkTools.h b/embedding/browser/gtk/src/EmbedGtkTools.h
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/EmbedGtkTools.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Oleg Romashin.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Oleg Romashin <romaxa@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef __EmbedTools_h
+#define __EmbedTools_h
+
+#include "nsCOMPtr.h"
+#ifdef MOZILLA_INTERNAL_API
+#include "nsString.h"
+#else
+#include "nsStringAPI.h"
+#endif
+#include "nsIDOMWindow.h"
+#include "nsIWindowWatcher.h"
+#include "nsIWebBrowserChrome.h"
+#include "nsIEmbeddingSiteWindow.h"
+#include "nsIServiceManager.h"
+#include "nsIContentViewer.h"
+#include "nsIDocShell.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include <gtk/gtk.h>
+
+GtkWidget*
+GetGtkWidgetForDOMWindow(nsIDOMWindow* aDOMWindow);
+
+GtkWindow*
+GetGtkWindowForDOMWindow(nsIDOMWindow* aDOMWindow);
+
+nsresult
+GetContentViewer(nsIWebBrowser *webBrowser, nsIContentViewer **aViewer);
+
+#endif /* __EmbedTools_h */
diff --git a/embedding/browser/gtk/src/EmbedPrivate.cpp b/embedding/browser/gtk/src/EmbedPrivate.cpp
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/EmbedPrivate.cpp
@@ -0,0 +1,983 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIDocShell.h"
+#include "nsIWebProgress.h"
+#include "nsIWidget.h"
+#include "nsCRT.h"
+#include "nsNetUtil.h"
+#include "nsIWebBrowserStream.h"
+#include "nsIWebBrowserFocus.h"
+#include "nsIDirectoryService.h"
+#include "nsAppDirectoryServiceDefs.h"
+
+// for do_GetInterface
+#include "nsIInterfaceRequestor.h"
+// for do_CreateInstance
+#include "nsIComponentManager.h"
+#include "nsComponentManagerUtils.h"
+
+// for initializing our window watcher service
+#include "nsIWindowWatcher.h"
+
+#include "nsILocalFile.h"
+
+#include "nsXULAppAPI.h"
+
+// all of the crap that we need for event listeners
+// and when chrome windows finish loading
+#include "nsIDOMWindow.h"
+#include "nsPIDOMWindow.h"
+#include "nsIDOMWindowInternal.h"
+
+// For seting scrollbar visibilty
+#include "nsIDOMBarProp.h"
+
+// all of our local includes
+#include "EmbedPrivate.h"
+#include "EmbedWindow.h"
+#include "EmbedProgress.h"
+#include "EmbedContentListener.h"
+#include "EmbedEventListener.h"
+#include "EmbedWindowCreator.h"
+#include "GtkPromptService.h"
+
+#include "mozilla/ModuleUtils.h"
+
+#ifdef MOZ_ACCESSIBILITY_ATK
+#include "nsIAccessibilityService.h"
+#include "nsIAccessible.h"
+#include "nsIDOMDocument.h"
+#endif
+
+PRUint32                 EmbedPrivate::sWidgetCount = 0;
+
+char                    *EmbedPrivate::sPath        = nsnull;
+char                    *EmbedPrivate::sCompPath    = nsnull;
+nsTArray<EmbedPrivate*> *EmbedPrivate::sWindowList  = nsnull;
+nsILocalFile            *EmbedPrivate::sProfileDir  = nsnull;
+nsISupports             *EmbedPrivate::sProfileLock = nsnull;
+GtkWidget               *EmbedPrivate::sOffscreenWindow = 0;
+GtkWidget               *EmbedPrivate::sOffscreenFixed  = 0;
+
+nsIDirectoryServiceProvider *EmbedPrivate::sAppFileLocProvider = nsnull;
+
+class GTKEmbedDirectoryProvider : public nsIDirectoryServiceProvider2
+{
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_NSIDIRECTORYSERVICEPROVIDER
+  NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
+};
+
+static const GTKEmbedDirectoryProvider kDirectoryProvider;
+
+NS_IMPL_QUERY_INTERFACE2(GTKEmbedDirectoryProvider,
+                         nsIDirectoryServiceProvider,
+                         nsIDirectoryServiceProvider2)
+
+NS_IMETHODIMP_(nsrefcnt)
+GTKEmbedDirectoryProvider::AddRef()
+{
+  return 1;
+}
+
+NS_IMETHODIMP_(nsrefcnt)
+GTKEmbedDirectoryProvider::Release()
+{
+  return 1;
+}
+
+NS_IMETHODIMP
+GTKEmbedDirectoryProvider::GetFile(const char *aKey, PRBool *aPersist,
+                                   nsIFile* *aResult)
+{
+  if (EmbedPrivate::sAppFileLocProvider) {
+    nsresult rv = EmbedPrivate::sAppFileLocProvider->GetFile(aKey, aPersist,
+                                                             aResult);
+    if (NS_SUCCEEDED(rv))
+      return rv;
+  }
+
+  if (EmbedPrivate::sProfileDir && (!strcmp(aKey, NS_APP_USER_PROFILE_50_DIR)
+                                 || !strcmp(aKey, NS_APP_PROFILE_DIR_STARTUP))) {
+    *aPersist = PR_TRUE;
+    return EmbedPrivate::sProfileDir->Clone(aResult);
+  }
+
+  return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+GTKEmbedDirectoryProvider::GetFiles(const char *aKey,
+                                    nsISimpleEnumerator* *aResult)
+{
+  nsCOMPtr<nsIDirectoryServiceProvider2>
+    dp2(do_QueryInterface(EmbedPrivate::sAppFileLocProvider));
+
+  if (!dp2)
+    return NS_ERROR_FAILURE;
+
+  return dp2->GetFiles(aKey, aResult);
+}
+
+#define NS_PROMPTSERVICE_CID \
+ {0x95611356, 0xf583, 0x46f5, {0x81, 0xff, 0x4b, 0x3e, 0x01, 0x62, 0xc6, 0x19}}
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(GtkPromptService)
+NS_DEFINE_NAMED_CID(NS_PROMPTSERVICE_CID);
+
+static const mozilla::Module::CIDEntry kDefaultPromptCIDs[] = {
+  { &kNS_PROMPTSERVICE_CID, false, NULL, GtkPromptServiceConstructor },
+  { NULL }
+};
+
+static const mozilla::Module::ContractIDEntry kDefaultPromptContracts[] = {
+  { "@mozilla.org/embedcomp/prompt-service;1", &kNS_PROMPTSERVICE_CID },
+  { NULL }
+};
+
+static const mozilla::Module kDefaultPromptModule = {
+  mozilla::Module::kVersion,
+  kDefaultPromptCIDs,
+  kDefaultPromptContracts
+};
+
+EmbedPrivate::EmbedPrivate(void)
+{
+  mOwningWidget     = nsnull;
+  mWindow           = nsnull;
+  mProgress         = nsnull;
+  mContentListener  = nsnull;
+  mEventListener    = nsnull;
+  mChromeMask       = nsIWebBrowserChrome::CHROME_ALL;
+  mIsChrome         = PR_FALSE;
+  mChromeLoaded     = PR_FALSE;
+  mListenersAttached = PR_FALSE;
+  mMozWindowWidget  = 0;
+  mIsDestroyed      = PR_FALSE;
+
+  PushStartup();
+  if (!sWindowList) {
+    sWindowList = new nsTArray<EmbedPrivate*>();
+  }
+  sWindowList->AppendElement(this);
+}
+
+EmbedPrivate::~EmbedPrivate()
+{
+  sWindowList->RemoveElement(this);
+  PopStartup();
+}
+
+nsresult
+EmbedPrivate::Init(GtkMozEmbed *aOwningWidget)
+{
+  // are we being re-initialized?
+  if (mOwningWidget)
+    return NS_OK;
+
+  // hang on with a reference to the owning widget
+  mOwningWidget = aOwningWidget;
+
+  // Create our embed window, and create an owning reference to it and
+  // initialize it.  It is assumed that this window will be destroyed
+  // when we go out of scope.
+  mWindow = new EmbedWindow();
+  mWindowGuard = static_cast<nsIWebBrowserChrome *>(mWindow);
+  mWindow->Init(this);
+
+  // Create our progress listener object, make an owning reference,
+  // and initialize it.  It is assumed that this progress listener
+  // will be destroyed when we go out of scope.
+  mProgress = new EmbedProgress();
+  mProgressGuard = static_cast<nsIWebProgressListener *>
+                                (mProgress);
+  mProgress->Init(this);
+
+  // Create our content listener object, initialize it and attach it.
+  // It is assumed that this will be destroyed when we go out of
+  // scope.
+  mContentListener = new EmbedContentListener();
+  mContentListenerGuard = static_cast<nsISupports*>(static_cast<nsIURIContentListener*>(mContentListener));
+  mContentListener->Init(this);
+
+  // Create our key listener object and initialize it.  It is assumed
+  // that this will be destroyed before we go out of scope.
+  mEventListener = new EmbedEventListener();
+  mEventListenerGuard =
+    static_cast<nsISupports *>(static_cast<nsIDOMKeyListener *>(mEventListener));
+  mEventListener->Init(this);
+
+  // has the window creator service been set up?
+  static int initialized = PR_FALSE;
+  // Set up our window creator ( only once )
+  if (!initialized) {
+    // We set this flag here instead of on success.  If it failed we
+    // don't want to keep trying and leaking window creator objects.
+    initialized = PR_TRUE;
+
+    // create our local object
+    EmbedWindowCreator *creator = new EmbedWindowCreator();
+    nsCOMPtr<nsIWindowCreator> windowCreator;
+    windowCreator = static_cast<nsIWindowCreator *>(creator);
+
+    // Attach it via the watcher service
+    nsCOMPtr<nsIWindowWatcher> watcher = do_GetService(NS_WINDOWWATCHER_CONTRACTID);
+    if (watcher)
+      watcher->SetWindowCreator(windowCreator);
+  }
+  return NS_OK;
+}
+
+nsresult
+EmbedPrivate::Realize(PRBool *aAlreadyRealized)
+{
+
+  *aAlreadyRealized = PR_FALSE;
+
+  // create the offscreen window if we have to
+  EnsureOffscreenWindow();
+
+  // Have we ever been initialized before?  If so then just reparent
+  // from the offscreen window.
+  if (mMozWindowWidget) {
+    gtk_widget_reparent(mMozWindowWidget, GTK_WIDGET(mOwningWidget));
+    *aAlreadyRealized = PR_TRUE;
+    return NS_OK;
+  }
+
+  // Get the nsIWebBrowser object for our embedded window.
+  nsCOMPtr<nsIWebBrowser> webBrowser;
+  mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+
+  // get a handle on the navigation object
+  mNavigation = do_QueryInterface(webBrowser);
+
+  // Create our session history object and tell the navigation object
+  // to use it.  We need to do this before we create the web browser
+  // window.
+  mSessionHistory = do_CreateInstance(NS_SHISTORY_CONTRACTID);
+  mNavigation->SetSessionHistory(mSessionHistory);
+
+  // create the window
+  mWindow->CreateWindow();
+
+  // bind the progress listener to the browser object
+  nsCOMPtr<nsISupportsWeakReference> supportsWeak;
+  supportsWeak = do_QueryInterface(mProgressGuard);
+  nsCOMPtr<nsIWeakReference> weakRef;
+  supportsWeak->GetWeakReference(getter_AddRefs(weakRef));
+  webBrowser->AddWebBrowserListener(weakRef,
+				    NS_GET_IID(nsIWebProgressListener));
+
+  // set ourselves as the parent uri content listener
+  nsCOMPtr<nsIURIContentListener> uriListener;
+  uriListener = do_QueryInterface(mContentListenerGuard);
+  webBrowser->SetParentURIContentListener(uriListener);
+
+  // save the window id of the newly created window
+  nsCOMPtr<nsIWidget> mozWidget;
+  mWindow->mBaseWindow->GetMainWidget(getter_AddRefs(mozWidget));
+  // get the native drawing area
+  GdkWindow *tmp_window =
+    static_cast<GdkWindow *>(
+		   mozWidget->GetNativeData(NS_NATIVE_WINDOW));
+  // and, thanks to superwin we actually need the parent of that.
+  tmp_window = gdk_window_get_parent(tmp_window);
+  // save the widget ID - it should be the mozarea of the window.
+  gpointer data = nsnull;
+  gdk_window_get_user_data(tmp_window, &data);
+  mMozWindowWidget = static_cast<GtkWidget *>(data);
+
+  // Apply the current chrome mask
+  ApplyChromeMask();
+
+  return NS_OK;
+}
+
+void
+EmbedPrivate::Unrealize(void)
+{
+  // reparent to our offscreen window
+  gtk_widget_reparent(mMozWindowWidget, sOffscreenFixed);
+}
+
+void
+EmbedPrivate::Show(void)
+{
+  // Get the nsIWebBrowser object for our embedded window.
+  nsCOMPtr<nsIWebBrowser> webBrowser;
+  mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+
+  // and set the visibility on the thing
+  nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(webBrowser);
+  baseWindow->SetVisibility(PR_TRUE);
+}
+
+void
+EmbedPrivate::Hide(void)
+{
+  // Get the nsIWebBrowser object for our embedded window.
+  nsCOMPtr<nsIWebBrowser> webBrowser;
+  mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+
+  // and set the visibility on the thing
+  nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(webBrowser);
+  baseWindow->SetVisibility(PR_FALSE);
+}
+
+void
+EmbedPrivate::Resize(PRUint32 aWidth, PRUint32 aHeight)
+{
+  mWindow->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION |
+			 nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER,
+			 0, 0, aWidth, aHeight);
+}
+
+void
+EmbedPrivate::Destroy(void)
+{
+  // This flag might have been set from
+  // EmbedWindow::DestroyBrowserWindow() as well if someone used a
+  // window.close() or something or some other script action to close
+  // the window.  No harm setting it again.
+  mIsDestroyed = PR_TRUE;
+
+  // Get the nsIWebBrowser object for our embedded window.
+  nsCOMPtr<nsIWebBrowser> webBrowser;
+  mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+
+  // Release our progress listener
+  nsCOMPtr<nsISupportsWeakReference> supportsWeak;
+  supportsWeak = do_QueryInterface(mProgressGuard);
+  nsCOMPtr<nsIWeakReference> weakRef;
+  supportsWeak->GetWeakReference(getter_AddRefs(weakRef));
+  webBrowser->RemoveWebBrowserListener(weakRef,
+				       NS_GET_IID(nsIWebProgressListener));
+  weakRef = nsnull;
+  supportsWeak = nsnull;
+
+  // Release our content listener
+  webBrowser->SetParentURIContentListener(nsnull);
+  mContentListenerGuard = nsnull;
+  mContentListener = nsnull;
+
+  // Now that we have removed the listener, release our progress
+  // object
+  mProgressGuard = nsnull;
+  mProgress = nsnull;
+
+  // detach our event listeners and release the event receiver
+  DetachListeners();
+  if (mEventTarget)
+    mEventTarget = nsnull;
+
+  // destroy our child window
+  mWindow->ReleaseChildren();
+
+  // release navigation
+  mNavigation = nsnull;
+
+  // release session history
+  mSessionHistory = nsnull;
+
+  mOwningWidget = nsnull;
+
+  mMozWindowWidget = 0;
+}
+
+void
+EmbedPrivate::SetURI(const char *aURI)
+{
+  mURI.Assign(aURI);
+}
+
+void
+EmbedPrivate::LoadCurrentURI(void)
+{
+  if (mURI.Length()) {
+    nsCOMPtr<nsPIDOMWindow> piWin;
+    GetPIDOMWindow(getter_AddRefs(piWin));
+
+    nsAutoPopupStatePusher popupStatePusher(piWin, openAllowed);
+
+    mNavigation->LoadURI(NS_ConvertUTF8toUTF16(mURI).get(), // URI string
+                         nsIWebNavigation::LOAD_FLAGS_NONE | // Load flags
+                         nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP,  // Allow keyword.URL.. functionality
+                         nsnull,                            // Referring URI
+                         nsnull,                            // Post data
+                         nsnull);                           // extra headers
+  }
+}
+
+void
+EmbedPrivate::Reload(PRUint32 reloadFlags)
+{
+  /* Use the session history if it is available, this
+   * allows framesets to reload correctly */
+  nsCOMPtr<nsIWebNavigation> wn;
+
+  if (mSessionHistory) {
+    wn = do_QueryInterface(mSessionHistory);
+  }
+  if (!wn)
+    wn = mNavigation;
+
+  if (wn)
+    wn->Reload(reloadFlags);
+}
+
+
+void
+EmbedPrivate::ApplyChromeMask()
+{
+   if (mWindow) {
+      nsCOMPtr<nsIWebBrowser> webBrowser;
+      mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+
+      nsCOMPtr<nsIDOMWindow> domWindow;
+      webBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
+      if (domWindow) {
+
+         nsCOMPtr<nsIDOMBarProp> scrollbars;
+         domWindow->GetScrollbars(getter_AddRefs(scrollbars));
+         if (scrollbars) {
+
+            scrollbars->SetVisible
+               (mChromeMask & nsIWebBrowserChrome::CHROME_SCROLLBARS ?
+                PR_TRUE : PR_FALSE);
+         }
+      }
+   }
+}
+
+
+void
+EmbedPrivate::SetChromeMask(PRUint32 aChromeMask)
+{
+   mChromeMask = aChromeMask;
+
+   ApplyChromeMask();
+}
+
+
+/* static */
+void
+EmbedPrivate::PushStartup(void)
+{
+  // increment the number of widgets
+  sWidgetCount++;
+
+  // if this is the first widget, fire up xpcom
+  if (sWidgetCount == 1) {
+    nsresult rv;
+
+    nsCOMPtr<nsILocalFile> binDir;
+    if (sCompPath) {
+      rv = NS_NewNativeLocalFile(nsDependentCString(sCompPath), 1, getter_AddRefs(binDir));
+      if (NS_FAILED(rv))
+	return;
+    }
+
+    const char *grePath = sPath;
+
+    if (!grePath)
+      grePath = getenv("MOZILLA_FIVE_HOME");
+
+    if (!grePath)
+      return;
+
+    nsCOMPtr<nsILocalFile> greDir;
+    rv = NS_NewNativeLocalFile(nsDependentCString(grePath), PR_TRUE,
+                               getter_AddRefs(greDir));
+    if (NS_FAILED(rv))
+      return;
+
+    if (sProfileDir && !sProfileLock) {
+      rv = XRE_LockProfileDirectory(sProfileDir,
+                                    &sProfileLock);
+      if (NS_FAILED(rv)) return;
+    }
+
+    rv = XRE_InitEmbedding2(greDir, binDir,
+                            const_cast<GTKEmbedDirectoryProvider*>(&kDirectoryProvider));
+    if (NS_FAILED(rv))
+      return;
+
+    if (sProfileDir)
+      XRE_NotifyProfile();
+
+    RegisterAppComponents();
+  }
+}
+
+/* static */
+void
+EmbedPrivate::PopStartup(void)
+{
+  sWidgetCount--;
+  if (sWidgetCount == 0) {
+
+    // destroy the offscreen window
+    DestroyOffscreenWindow();
+
+    // we no longer need a reference to the DirectoryServiceProvider
+    if (sAppFileLocProvider) {
+      NS_RELEASE(sAppFileLocProvider);
+      sAppFileLocProvider = nsnull;
+    }
+
+    // shut down XPCOM/Embedding
+    XRE_TermEmbedding();
+
+    NS_IF_RELEASE(sProfileLock);
+    NS_IF_RELEASE(sProfileDir);
+  }
+}
+
+/* static */
+void EmbedPrivate::SetPath(const char *aPath)
+{
+  if (sPath)
+    free(sPath);
+  if (aPath)
+    sPath = strdup(aPath);
+  else
+    sPath = nsnull;
+}
+
+/* static */
+void
+EmbedPrivate::SetCompPath(const char *aPath)
+{
+  if (sCompPath)
+    free(sCompPath);
+  if (aPath)
+    sCompPath = strdup(aPath);
+  else
+    sCompPath = nsnull;
+}
+
+/* static */
+void
+EmbedPrivate::SetProfilePath(const char *aDir, const char *aName)
+{
+  if (sProfileDir) {
+    if (sWidgetCount) {
+      NS_ERROR("Cannot change profile directory during run.");
+      return;
+    }
+
+    NS_RELEASE(sProfileDir);
+    NS_RELEASE(sProfileLock);
+  }
+
+  nsresult rv =
+    NS_NewNativeLocalFile(nsDependentCString(aDir), PR_TRUE, &sProfileDir);
+
+  if (NS_SUCCEEDED(rv) && aName)
+    rv = sProfileDir->AppendNative(nsDependentCString(aName));
+
+  if (NS_SUCCEEDED(rv)) {
+    PRBool exists = PR_FALSE;
+    rv = sProfileDir->Exists(&exists);
+    if (!exists)
+      rv = sProfileDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
+    rv = XRE_LockProfileDirectory(sProfileDir, &sProfileLock);
+  }
+
+  if (NS_SUCCEEDED(rv)) {
+    if (sWidgetCount)
+      XRE_NotifyProfile();
+
+    return;
+  }
+
+  NS_WARNING("Failed to lock profile.");
+
+  // Failed
+  NS_IF_RELEASE(sProfileDir);
+  NS_IF_RELEASE(sProfileLock);
+}
+
+void
+EmbedPrivate::SetDirectoryServiceProvider(nsIDirectoryServiceProvider * appFileLocProvider)
+{
+  if (sAppFileLocProvider)
+    NS_RELEASE(sAppFileLocProvider);
+
+  if (appFileLocProvider) {
+    sAppFileLocProvider = appFileLocProvider;
+    NS_ADDREF(sAppFileLocProvider);
+  }
+}
+
+nsresult
+EmbedPrivate::OpenStream(const char *aBaseURI, const char *aContentType)
+{
+  nsCOMPtr<nsIWebBrowser> webBrowser;
+  mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+
+  nsCOMPtr<nsIWebBrowserStream> wbStream = do_QueryInterface(webBrowser);
+  if (!wbStream) return NS_ERROR_FAILURE;
+
+  nsCOMPtr<nsIURI> uri;
+  nsresult rv = NS_NewURI(getter_AddRefs(uri), aBaseURI);
+  if (NS_FAILED(rv))
+    return rv;
+
+  rv = wbStream->OpenStream(uri, nsDependentCString(aContentType));
+  return rv;
+}
+
+nsresult
+EmbedPrivate::AppendToStream(const PRUint8 *aData, PRUint32 aLen)
+{
+  // Attach listeners to this document since in some cases we don't
+  // get updates for content added this way.
+  ContentStateChange();
+
+  nsCOMPtr<nsIWebBrowser> webBrowser;
+  mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+
+  nsCOMPtr<nsIWebBrowserStream> wbStream = do_QueryInterface(webBrowser);
+  if (!wbStream) return NS_ERROR_FAILURE;
+
+  return wbStream->AppendToStream(aData, aLen);
+}
+
+nsresult
+EmbedPrivate::CloseStream(void)
+{
+  nsCOMPtr<nsIWebBrowser> webBrowser;
+  mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+
+  nsCOMPtr<nsIWebBrowserStream> wbStream = do_QueryInterface(webBrowser);
+  if (!wbStream) return NS_ERROR_FAILURE;
+
+  return wbStream->CloseStream();
+}
+
+/* static */
+EmbedPrivate *
+EmbedPrivate::FindPrivateForBrowser(nsIWebBrowserChrome *aBrowser)
+{
+  if (!sWindowList)
+    return nsnull;
+
+  // Get the number of browser windows.
+  PRInt32 count = sWindowList->Length();
+  // This function doesn't get called very often at all ( only when
+  // creating a new window ) so it's OK to walk the list of open
+  // windows.
+  for (int i = 0; i < count; i++) {
+    EmbedPrivate *tmpPrivate = sWindowList->ElementAt(i);
+    // get the browser object for that window
+    nsIWebBrowserChrome *chrome = static_cast<nsIWebBrowserChrome *>(
+						 tmpPrivate->mWindow);
+    if (chrome == aBrowser)
+      return tmpPrivate;
+  }
+
+  return nsnull;
+}
+
+void
+EmbedPrivate::ContentStateChange(void)
+{
+
+  // we don't attach listeners to chrome
+  if (mListenersAttached && !mIsChrome)
+    return;
+
+  GetListener();
+
+  if (!mEventTarget)
+    return;
+
+  AttachListeners();
+
+}
+
+void
+EmbedPrivate::ContentFinishedLoading(void)
+{
+  if (mIsChrome) {
+    // We're done loading.
+    mChromeLoaded = PR_TRUE;
+
+    // get the web browser
+    nsCOMPtr<nsIWebBrowser> webBrowser;
+    mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+
+    // get the content DOM window for that web browser
+    nsCOMPtr<nsIDOMWindow> domWindow;
+    webBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
+    if (!domWindow) {
+      NS_WARNING("no dom window in content finished loading\n");
+      return;
+    }
+
+    // resize the content
+    domWindow->SizeToContent();
+
+    // and since we're done loading show the window, assuming that the
+    // visibility flag has been set.
+    PRBool visibility;
+    mWindow->GetVisibility(&visibility);
+    if (visibility)
+      mWindow->SetVisibility(PR_TRUE);
+  }
+}
+
+void
+EmbedPrivate::ChildFocusIn(void)
+{
+  if (mIsDestroyed)
+    return;
+
+  nsresult rv;
+  nsCOMPtr<nsIWebBrowser> webBrowser;
+  rv = mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+  if (NS_FAILED(rv))
+    return;
+
+  nsCOMPtr<nsIWebBrowserFocus> webBrowserFocus(do_QueryInterface(webBrowser));
+  if (!webBrowserFocus)
+    return;
+  
+  webBrowserFocus->Activate();
+}
+
+void
+EmbedPrivate::ChildFocusOut(void)
+{
+  if (mIsDestroyed)
+    return;
+
+  nsresult rv;
+  nsCOMPtr<nsIWebBrowser> webBrowser;
+  rv = mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+  if (NS_FAILED(rv))
+	  return;
+
+  nsCOMPtr<nsIWebBrowserFocus> webBrowserFocus(do_QueryInterface(webBrowser));
+  if (!webBrowserFocus)
+	  return;
+  
+  webBrowserFocus->Deactivate();
+}
+
+// Get the event listener for the chrome event handler.
+
+void
+EmbedPrivate::GetListener(void)
+{
+  if (mEventTarget)
+    return;
+
+  nsCOMPtr<nsPIDOMWindow> piWin;
+  GetPIDOMWindow(getter_AddRefs(piWin));
+
+  if (!piWin)
+    return;
+
+  mEventTarget = do_QueryInterface(piWin->GetChromeEventHandler());
+}
+
+// attach key and mouse event listeners
+
+void
+EmbedPrivate::AttachListeners(void)
+{
+  if (!mEventTarget || mListenersAttached)
+    return;
+
+  nsIDOMEventListener *eventListener =
+    static_cast<nsIDOMEventListener *>(static_cast<nsIDOMKeyListener *>(mEventListener));
+
+  // add the key listener
+  nsresult rv;
+  rv = mEventTarget->AddEventListenerByIID(eventListener,
+					     NS_GET_IID(nsIDOMKeyListener));
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to add key listener\n");
+    return;
+  }
+
+  rv = mEventTarget->AddEventListenerByIID(eventListener,
+					     NS_GET_IID(nsIDOMMouseListener));
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to add mouse listener\n");
+    return;
+  }
+
+  rv = mEventTarget->AddEventListenerByIID(eventListener,
+                                             NS_GET_IID(nsIDOMUIListener));
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to add UI listener\n");
+    return;
+  }
+
+  // ok, all set.
+  mListenersAttached = PR_TRUE;
+}
+
+void
+EmbedPrivate::DetachListeners(void)
+{
+  if (!mListenersAttached || !mEventTarget)
+    return;
+
+  nsIDOMEventListener *eventListener =
+    static_cast<nsIDOMEventListener *>(static_cast<nsIDOMKeyListener *>(mEventListener));
+
+  nsresult rv;
+  rv = mEventTarget->RemoveEventListenerByIID(eventListener,
+						NS_GET_IID(nsIDOMKeyListener));
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to remove key listener\n");
+    return;
+  }
+
+  rv =
+    mEventTarget->RemoveEventListenerByIID(eventListener,
+					     NS_GET_IID(nsIDOMMouseListener));
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to remove mouse listener\n");
+    return;
+  }
+
+  rv = mEventTarget->RemoveEventListenerByIID(eventListener,
+						NS_GET_IID(nsIDOMUIListener));
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to remove UI listener\n");
+    return;
+  }
+
+  mListenersAttached = PR_FALSE;
+}
+
+nsresult
+EmbedPrivate::GetPIDOMWindow(nsPIDOMWindow **aPIWin)
+{
+  *aPIWin = nsnull;
+
+  // get the web browser
+  nsCOMPtr<nsIWebBrowser> webBrowser;
+  mWindow->GetWebBrowser(getter_AddRefs(webBrowser));
+
+  // get the content DOM window for that web browser
+  nsCOMPtr<nsIDOMWindow> domWindow;
+  webBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
+  if (!domWindow)
+    return NS_ERROR_FAILURE;
+
+  // get the private DOM window
+  nsCOMPtr<nsPIDOMWindow> domWindowPrivate = do_QueryInterface(domWindow);
+  // and the root window for that DOM window
+  *aPIWin = domWindowPrivate->GetPrivateRoot();
+
+  if (*aPIWin) {
+    NS_ADDREF(*aPIWin);
+    return NS_OK;
+  }
+
+  return NS_ERROR_FAILURE;
+
+}
+
+#ifdef MOZ_ACCESSIBILITY_ATK
+void *
+EmbedPrivate::GetAtkObjectForCurrentDocument()
+{
+  if (!mNavigation)
+    return nsnull;
+
+  nsCOMPtr<nsIAccessibilityService> accService =
+    do_GetService("@mozilla.org/accessibilityService;1");
+  if (accService) {
+    //get current document
+    nsCOMPtr<nsIDOMDocument> domDoc;
+    mNavigation->GetDocument(getter_AddRefs(domDoc));
+    NS_ENSURE_TRUE(domDoc, nsnull);
+
+    nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(domDoc));
+    NS_ENSURE_TRUE(domNode, nsnull);
+
+    nsCOMPtr<nsIAccessible> acc;
+    accService->GetAccessibleFor(domNode, getter_AddRefs(acc));
+    NS_ENSURE_TRUE(acc, nsnull);
+
+    void *atkObj = nsnull;
+    if (NS_SUCCEEDED(acc->GetNativeInterface(&atkObj)))
+      return atkObj;
+  }
+  return nsnull;
+}
+#endif /* MOZ_ACCESSIBILITY_ATK */
+
+/* static */
+void
+EmbedPrivate::RegisterAppComponents(void)
+{
+  XRE_AddStaticComponent(&kDefaultPromptModule);
+}
+
+/* static */
+void
+EmbedPrivate::EnsureOffscreenWindow(void)
+{
+  if (sOffscreenWindow)
+    return;
+  sOffscreenWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+  gtk_widget_realize(sOffscreenWindow);
+  sOffscreenFixed = gtk_fixed_new();
+  gtk_container_add(GTK_CONTAINER(sOffscreenWindow), sOffscreenFixed);
+  gtk_widget_realize(sOffscreenFixed);
+}
+
+/* static */
+void
+EmbedPrivate::DestroyOffscreenWindow(void)
+{
+  if (!sOffscreenWindow)
+    return;
+  gtk_widget_destroy(sOffscreenWindow);
+  sOffscreenWindow = 0;
+}
diff --git a/embedding/browser/gtk/src/EmbedPrivate.h b/embedding/browser/gtk/src/EmbedPrivate.h
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/EmbedPrivate.h
@@ -0,0 +1,188 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __EmbedPrivate_h
+#define __EmbedPrivate_h
+
+#include "nsCOMPtr.h"
+#include "nsStringGlue.h"
+#include "nsIWebNavigation.h"
+#include "nsISHistory.h"
+// for our one function that gets the EmbedPrivate via the chrome
+// object.
+#include "nsIWebBrowserChrome.h"
+#include "nsIAppShell.h"
+#include "nsPIDOMEventTarget.h"
+#include "nsTArray.h"
+
+#include "gtkmozembedprivate.h"
+
+class EmbedProgress;
+class EmbedWindow;
+class EmbedContentListener;
+class EmbedEventListener;
+
+class nsPIDOMWindow;
+class nsIDirectoryServiceProvider;
+
+class EmbedPrivate {
+
+ public:
+
+  EmbedPrivate();
+  ~EmbedPrivate();
+
+  nsresult    Init            (GtkMozEmbed *aOwningWidget);
+  nsresult    Realize         (PRBool *aAlreadRealized);
+  void        Unrealize       (void);
+  void        Show            (void);
+  void        Hide            (void);
+  void        Resize          (PRUint32 aWidth, PRUint32 aHeight);
+  void        Destroy         (void);
+  void        SetURI          (const char *aURI);
+  void        LoadCurrentURI  (void);
+  void        Reload          (PRUint32 reloadFlags);
+
+  void        SetChromeMask   (PRUint32 chromeMask);
+  void        ApplyChromeMask ();
+
+  static void PushStartup     (void);
+  static void PopStartup      (void);
+  static void SetPath         (const char *aPath);
+  static void SetCompPath     (const char *aPath);
+  static void SetProfilePath  (const char *aDir, const char *aName);
+  static void SetDirectoryServiceProvider (nsIDirectoryServiceProvider * appFileLocProvider);
+
+  nsresult OpenStream         (const char *aBaseURI, const char *aContentType);
+  nsresult AppendToStream     (const PRUint8 *aData, PRUint32 aLen);
+  nsresult CloseStream        (void);
+
+  // This function will find the specific EmbedPrivate object for a
+  // given nsIWebBrowserChrome.
+  static EmbedPrivate *FindPrivateForBrowser(nsIWebBrowserChrome *aBrowser);
+
+  // This is an upcall that will come from the progress listener
+  // whenever there is a content state change.  We need this so we can
+  // attach event listeners.
+  void        ContentStateChange    (void);
+
+  // This is an upcall from the progress listener when content is
+  // finished loading.  We have this so that if it's chrome content
+  // that we can size to content properly and show ourselves if
+  // visibility is set.
+  void        ContentFinishedLoading(void);
+
+  // these are when the widget itself gets focus in and focus out
+  // events
+  void        ChildFocusIn (void);
+  void        ChildFocusOut(void);
+
+#ifdef MOZ_ACCESSIBILITY_ATK
+  void *GetAtkObjectForCurrentDocument();
+#endif
+
+  GtkMozEmbed                   *mOwningWidget;
+
+  // all of the objects that we own
+  EmbedWindow                   *mWindow;
+  nsCOMPtr<nsISupports>          mWindowGuard;
+  EmbedProgress                 *mProgress;
+  nsCOMPtr<nsISupports>          mProgressGuard;
+  EmbedContentListener          *mContentListener;
+  nsCOMPtr<nsISupports>          mContentListenerGuard;
+  EmbedEventListener            *mEventListener;
+  nsCOMPtr<nsISupports>          mEventListenerGuard;
+
+  nsCOMPtr<nsIWebNavigation>     mNavigation;
+  nsCOMPtr<nsISHistory>          mSessionHistory;
+
+  // our event receiver
+  nsCOMPtr<nsPIDOMEventTarget>   mEventTarget;
+
+  // the currently loaded uri
+  nsCString                      mURI;
+
+  // the number of widgets that have been created
+  static PRUint32                sWidgetCount;
+  // the path to the GRE
+  static char                   *sPath;
+  // the path to components
+  static char                   *sCompPath;
+  // the appshell we have created
+  static nsIAppShell            *sAppShell;
+  // the list of all open windows
+  static nsTArray<EmbedPrivate*> *sWindowList;
+  // what is our profile path?
+  static nsILocalFile           *sProfileDir;
+  static nsISupports            *sProfileLock;
+
+  static nsIDirectoryServiceProvider * sAppFileLocProvider;
+
+  // chrome mask
+  PRUint32                       mChromeMask;
+  // is this a chrome window?
+  PRBool                         mIsChrome;
+  // has the chrome finished loading?
+  PRBool                         mChromeLoaded;
+  // saved window ID for reparenting later
+  GtkWidget                     *mMozWindowWidget;
+  // has someone called Destroy() on us?
+  PRBool                         mIsDestroyed;
+
+ private:
+
+  // is the chrome listener attached yet?
+  PRBool                         mListenersAttached;
+
+  void GetListener    (void);
+  void AttachListeners(void);
+  void DetachListeners(void);
+
+  // this will get the PIDOMWindow for this widget
+  nsresult        GetPIDOMWindow   (nsPIDOMWindow **aPIWin);
+  
+  static void RegisterAppComponents();
+
+  // offscreen window methods and the offscreen widget
+  static void       EnsureOffscreenWindow(void);
+  static void       DestroyOffscreenWindow(void);
+  static GtkWidget *sOffscreenWindow;
+  static GtkWidget *sOffscreenFixed;
+ 
+};
+
+#endif /* __EmbedPrivate_h */
diff --git a/embedding/browser/gtk/src/EmbedProgress.cpp b/embedding/browser/gtk/src/EmbedProgress.cpp
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/EmbedProgress.cpp
@@ -0,0 +1,215 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "EmbedProgress.h"
+
+#include "nsIChannel.h"
+#include "nsIWebProgress.h"
+#include "nsIDOMWindow.h"
+
+#include "nsIURI.h"
+
+EmbedProgress::EmbedProgress(void)
+{
+  mOwner = nsnull;
+}
+
+EmbedProgress::~EmbedProgress()
+{
+}
+
+NS_IMPL_ISUPPORTS2(EmbedProgress,
+		   nsIWebProgressListener,
+		   nsISupportsWeakReference)
+
+nsresult
+EmbedProgress::Init(EmbedPrivate *aOwner)
+{
+  mOwner = aOwner;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedProgress::OnStateChange(nsIWebProgress *aWebProgress,
+			     nsIRequest     *aRequest,
+			     PRUint32        aStateFlags,
+			     nsresult        aStatus)
+{
+  // give the widget a chance to attach any listeners
+  mOwner->ContentStateChange();
+  // if we've got the start flag, emit the signal
+  if ((aStateFlags & GTK_MOZ_EMBED_FLAG_IS_NETWORK) && 
+      (aStateFlags & GTK_MOZ_EMBED_FLAG_START))
+  {
+    g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                  moz_embed_signals[NET_START], 0);
+  }
+
+  // get the uri for this request
+  nsCAutoString uriString;
+  RequestToURIString(aRequest, uriString);
+
+  // is it the same as the current URI?
+  if (mOwner->mURI.Equals(uriString))
+  {
+    // for people who know what they are doing
+    g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                  moz_embed_signals[NET_STATE], 0,
+                  aStateFlags, aStatus);
+  }
+  g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                moz_embed_signals[NET_STATE_ALL], 0,
+                uriString.get(),
+                (gint)aStateFlags, (gint)aStatus);
+  // and for stop, too
+  if ((aStateFlags & GTK_MOZ_EMBED_FLAG_IS_NETWORK) &&
+      (aStateFlags & GTK_MOZ_EMBED_FLAG_STOP))
+  {
+    g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                  moz_embed_signals[NET_STOP], 0);
+    // let our owner know that the load finished
+    mOwner->ContentFinishedLoading();
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedProgress::OnProgressChange(nsIWebProgress *aWebProgress,
+				nsIRequest     *aRequest,
+				PRInt32         aCurSelfProgress,
+				PRInt32         aMaxSelfProgress,
+				PRInt32         aCurTotalProgress,
+				PRInt32         aMaxTotalProgress)
+{
+
+  nsCAutoString uriString;
+  RequestToURIString(aRequest, uriString);
+
+  // is it the same as the current uri?
+  if (mOwner->mURI.Equals(uriString)) {
+    g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                  moz_embed_signals[PROGRESS], 0,
+                  aCurTotalProgress, aMaxTotalProgress);
+  }
+
+  g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                moz_embed_signals[PROGRESS_ALL], 0,
+                uriString.get(),
+                aCurTotalProgress, aMaxTotalProgress);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedProgress::OnLocationChange(nsIWebProgress *aWebProgress,
+				nsIRequest     *aRequest,
+				nsIURI         *aLocation)
+{
+  nsCAutoString newURI;
+  NS_ENSURE_ARG_POINTER(aLocation);
+  aLocation->GetSpec(newURI);
+
+  // Make sure that this is the primary frame change and not
+  // just a subframe.
+  PRBool isSubFrameLoad = PR_FALSE;
+  if (aWebProgress) {
+    nsCOMPtr<nsIDOMWindow> domWindow;
+    nsCOMPtr<nsIDOMWindow> topDomWindow;
+
+    aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
+
+    // get the root dom window
+    if (domWindow)
+      domWindow->GetTop(getter_AddRefs(topDomWindow));
+
+    if (domWindow != topDomWindow)
+      isSubFrameLoad = PR_TRUE;
+  }
+
+  if (!isSubFrameLoad) {
+    mOwner->SetURI(newURI.get());
+    g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                  moz_embed_signals[LOCATION], 0);
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedProgress::OnStatusChange(nsIWebProgress  *aWebProgress,
+			      nsIRequest      *aRequest,
+			      nsresult         aStatus,
+			      const PRUnichar *aMessage)
+{
+  g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                moz_embed_signals[STATUS_CHANGE], 0,
+                static_cast<void *>(aRequest),
+                static_cast<int>(aStatus),
+                static_cast<const void *>(aMessage));
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedProgress::OnSecurityChange(nsIWebProgress *aWebProgress,
+				nsIRequest     *aRequest,
+				PRUint32         aState)
+{
+  g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                moz_embed_signals[SECURITY_CHANGE], 0,
+                static_cast<void *>(aRequest),
+                aState);
+  return NS_OK;
+}
+
+/* static */
+void
+EmbedProgress::RequestToURIString(nsIRequest *aRequest, nsACString &aString)
+{
+  // is it a channel
+  nsCOMPtr<nsIChannel> channel;
+  channel = do_QueryInterface(aRequest);
+  if (!channel)
+    return;
+  
+  nsCOMPtr<nsIURI> uri;
+  channel->GetURI(getter_AddRefs(uri));
+  if (!uri)
+    return;
+  
+  uri->GetSpec(aString);
+}
diff --git a/embedding/browser/gtk/src/EmbedProgress.h b/embedding/browser/gtk/src/EmbedProgress.h
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/EmbedProgress.h
@@ -0,0 +1,66 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __EmbedProgress_h
+#define __EmbedProgress_h
+
+#include "nsIWebProgressListener.h"
+#include "nsWeakReference.h"
+#include "EmbedPrivate.h"
+
+class EmbedProgress : public nsIWebProgressListener,
+                      public nsSupportsWeakReference
+{
+ public:
+  EmbedProgress();
+  virtual ~EmbedProgress();
+
+  nsresult Init(EmbedPrivate *aOwner);
+
+  NS_DECL_ISUPPORTS
+
+  NS_DECL_NSIWEBPROGRESSLISTENER
+
+ private:
+
+  static void RequestToURIString (nsIRequest *aRequest, nsACString &aString);
+
+  EmbedPrivate *mOwner;
+
+};
+
+#endif /* __EmbedProgress_h */
diff --git a/embedding/browser/gtk/src/EmbedPrompter.cpp b/embedding/browser/gtk/src/EmbedPrompter.cpp
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/EmbedPrompter.cpp
@@ -0,0 +1,411 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Brian Ryner <bryner@brianryner.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "EmbedPrompter.h"
+
+enum {
+    INCLUDE_USERNAME = 1 << 0,
+    INCLUDE_PASSWORD = 1 << 1,
+    INCLUDE_CHECKBOX = 1 << 2,
+    INCLUDE_CANCEL   = 1 << 3
+};
+
+struct DialogDescription {
+    int          flags;
+    const gchar* icon;
+};
+
+// This table contains the optional widgets and icons associated with
+// each type of dialog.
+
+static const DialogDescription DialogTable[] = {
+    { 0,                      GTK_STOCK_DIALOG_WARNING  },  // ALERT
+    { INCLUDE_CHECKBOX,       GTK_STOCK_DIALOG_WARNING  },  // ALERT_CHECK
+    { INCLUDE_CANCEL,         GTK_STOCK_DIALOG_QUESTION },  // CONFIRM
+    { INCLUDE_CHECKBOX |
+      INCLUDE_CANCEL,         GTK_STOCK_DIALOG_QUESTION },  // CONFIRM_CHECK
+    { INCLUDE_CANCEL |
+      INCLUDE_CHECKBOX,       GTK_STOCK_DIALOG_QUESTION },  // PROMPT
+    { INCLUDE_CANCEL |
+      INCLUDE_USERNAME |
+      INCLUDE_PASSWORD |
+      INCLUDE_CHECKBOX,       GTK_STOCK_DIALOG_QUESTION },  // PROMPT_USER_PASS
+    { INCLUDE_CANCEL |
+      INCLUDE_PASSWORD |
+      INCLUDE_CHECKBOX,       GTK_STOCK_DIALOG_QUESTION },  // PROMPT_PASS
+    { INCLUDE_CANCEL,         GTK_STOCK_DIALOG_QUESTION },  // SELECT
+    { INCLUDE_CANCEL |
+      INCLUDE_CHECKBOX,       GTK_STOCK_DIALOG_QUESTION }   // UNIVERSAL
+};
+
+EmbedPrompter::EmbedPrompter(void)
+    : mCheckValue(PR_FALSE),
+      mItemList(nsnull),
+      mItemCount(0),
+      mButtonPressed(0),
+      mConfirmResult(PR_FALSE),
+      mSelectedItem(0),
+      mWindow(NULL),
+      mUserField(NULL),
+      mPassField(NULL),
+      mTextField(NULL),
+      mComboBox(NULL),
+      mCheckBox(NULL)
+{
+}
+
+EmbedPrompter::~EmbedPrompter(void)
+{
+    if (mItemList)
+        delete[] mItemList;
+}
+
+nsresult
+EmbedPrompter::Create(PromptType aType, GtkWindow* aParentWindow)
+{
+    mWindow = gtk_dialog_new_with_buttons(mTitle.get(), aParentWindow,
+                                          (GtkDialogFlags)0,
+                                          NULL);
+
+    // only add the dialog to the window group if the parent already has a window group,
+    // so as not to break app's expectations about modal dialogs.
+    if (aParentWindow && aParentWindow->group) {
+        gtk_window_group_add_window (aParentWindow->group, GTK_WINDOW (mWindow));
+    }
+
+    // gtk will resize this for us as necessary
+    gtk_window_set_default_size(GTK_WINDOW(mWindow), 100, 50);
+
+    // this HBox will contain the icon, and a vbox which contains the
+    // dialog text and other widgets.
+    GtkWidget* dialogHBox = gtk_hbox_new(FALSE, 12);
+
+
+    // Set up dialog properties according to the GNOME HIG
+    // (http://developer.gnome.org/projects/gup/hig/1.0/windows.html#alert-windows)
+
+    gtk_container_set_border_width(GTK_CONTAINER(mWindow), 6);
+    gtk_dialog_set_has_separator(GTK_DIALOG(mWindow), FALSE);
+    gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(mWindow)->vbox), 12);
+    gtk_container_set_border_width(GTK_CONTAINER(dialogHBox), 6);
+
+
+    // This is the VBox which will contain the label and other controls.
+    GtkWidget* contentsVBox = gtk_vbox_new(FALSE, 12);
+
+    // get the stock icon for this dialog and put it in the box
+    const gchar* iconDesc = DialogTable[aType].icon;
+    GtkWidget* icon = gtk_image_new_from_stock(iconDesc, GTK_ICON_SIZE_DIALOG);
+    gtk_misc_set_alignment(GTK_MISC(icon), 0.5, 0.0);
+    gtk_box_pack_start(GTK_BOX(dialogHBox), icon, FALSE, FALSE, 0);
+
+    // now pack the label into the vbox
+    GtkWidget* label = gtk_label_new(mMessageText.get());
+    gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+    gtk_label_set_selectable(GTK_LABEL(label), TRUE);
+    gtk_box_pack_start(GTK_BOX(contentsVBox), label, FALSE, FALSE, 0);
+
+    int widgetFlags = DialogTable[aType].flags;
+
+    if (widgetFlags & (INCLUDE_USERNAME | INCLUDE_PASSWORD)) {
+
+        // If we're creating a username and/or password field, make an hbox
+        // which will contain two vboxes, one for the labels and one for the
+        // text fields.  This will let us line up the textfields.
+
+        GtkWidget* userPassHBox = gtk_hbox_new(FALSE, 12);
+        GtkWidget* userPassLabels = gtk_vbox_new(TRUE, 6);
+        GtkWidget* userPassFields = gtk_vbox_new(TRUE, 6);
+
+        if (widgetFlags & INCLUDE_USERNAME) {
+            GtkWidget* userLabel = gtk_label_new("User Name:");
+            gtk_box_pack_start(GTK_BOX(userPassLabels), userLabel, FALSE,
+                               FALSE, 0);
+
+            mUserField = gtk_entry_new();
+
+            if (!mUser.IsEmpty())
+                gtk_entry_set_text(GTK_ENTRY(mUserField), mUser.get());
+
+            gtk_entry_set_activates_default(GTK_ENTRY(mUserField), TRUE);
+
+            gtk_box_pack_start(GTK_BOX(userPassFields), mUserField, FALSE,
+                               FALSE, 0);
+        }
+        if (widgetFlags & INCLUDE_PASSWORD) {
+            GtkWidget* passLabel = gtk_label_new("Password:");
+            gtk_box_pack_start(GTK_BOX(userPassLabels), passLabel, FALSE,
+                               FALSE, 0);
+
+            mPassField = gtk_entry_new();
+
+            if (!mPass.IsEmpty())
+                gtk_entry_set_text(GTK_ENTRY(mPassField), mPass.get());
+
+            gtk_entry_set_visibility(GTK_ENTRY(mPassField), FALSE);
+            gtk_entry_set_activates_default(GTK_ENTRY(mPassField), TRUE);
+
+            gtk_box_pack_start(GTK_BOX(userPassFields), mPassField, FALSE,
+                               FALSE, 0);
+        }
+
+        gtk_box_pack_start(GTK_BOX(userPassHBox), userPassLabels, FALSE,
+                           FALSE, 0);
+        gtk_box_pack_start(GTK_BOX(userPassHBox), userPassFields, FALSE,
+                           FALSE, 0);
+        gtk_box_pack_start(GTK_BOX(contentsVBox), userPassHBox, FALSE, FALSE, 0);
+    }
+
+    if (aType == TYPE_PROMPT) {
+        mTextField = gtk_entry_new();
+
+        if (!mTextValue.IsEmpty())
+            gtk_entry_set_text(GTK_ENTRY(mTextField), mTextValue.get());
+
+        gtk_entry_set_activates_default(GTK_ENTRY(mTextField), TRUE);
+
+        gtk_box_pack_start(GTK_BOX(contentsVBox), mTextField, FALSE, FALSE, 0);
+    }
+
+    // Add a checkbox
+    if ((widgetFlags & INCLUDE_CHECKBOX) && !mCheckMessage.IsEmpty()) {
+        mCheckBox = gtk_check_button_new_with_label(mCheckMessage.get());
+
+        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mCheckBox),
+                                     mCheckValue);
+        gtk_label_set_line_wrap(GTK_LABEL(gtk_bin_get_child(GTK_BIN(mCheckBox))),
+				TRUE);
+
+        gtk_box_pack_start(GTK_BOX(contentsVBox), mCheckBox, FALSE, FALSE, 0);
+    }
+
+    // Add a dropdown menu
+    if (aType == TYPE_SELECT) {
+        // Build up a GtkComboBox containing the items
+        GtkWidget* mComboBox = gtk_combo_box_new_text();
+        for (PRUint32 i = 0; i < mItemCount; ++i) {
+            gtk_combo_box_append_text(GTK_COMBO_BOX(mComboBox), mItemList[i].get());
+        }
+        gtk_box_pack_start(GTK_BOX(contentsVBox), mComboBox, FALSE, FALSE, 0);
+    }
+
+    if (aType == TYPE_UNIVERSAL) {
+        // Create buttons based on the flags passed in.
+        for (PRUint32 i = EMBED_MAX_BUTTONS; i-- > 0; ) {
+            if (!mButtonLabels[i].IsEmpty())
+                gtk_dialog_add_button(GTK_DIALOG(mWindow),
+                                      mButtonLabels[i].get(), i);
+        }
+        gtk_dialog_set_default_response(GTK_DIALOG(mWindow), 0);
+    } else {
+        // Create standard ok and cancel buttons
+        if (widgetFlags & INCLUDE_CANCEL)
+            gtk_dialog_add_button(GTK_DIALOG(mWindow), GTK_STOCK_CANCEL,
+                                  GTK_RESPONSE_CANCEL);
+
+        GtkWidget* okButton = gtk_dialog_add_button(GTK_DIALOG(mWindow),
+                                                    GTK_STOCK_OK,
+                                                    GTK_RESPONSE_ACCEPT);
+        gtk_widget_grab_default(okButton);
+    }
+
+    // Pack the contentsVBox into the dialogHBox and the dialog.
+    gtk_box_pack_start(GTK_BOX(dialogHBox), contentsVBox, FALSE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(mWindow)->vbox), dialogHBox, FALSE,
+                       FALSE, 0);
+
+    return NS_OK;
+}
+
+void
+EmbedPrompter::SetTitle(const PRUnichar *aTitle)
+{
+    mTitle.Assign(NS_ConvertUTF16toUTF8(aTitle));
+}
+
+void
+EmbedPrompter::SetTextValue(const PRUnichar *aTextValue)
+{
+    mTextValue.Assign(NS_ConvertUTF16toUTF8(aTextValue));
+}
+
+void
+EmbedPrompter::SetCheckMessage(const PRUnichar *aMessage)
+{
+    mCheckMessage.Assign(NS_ConvertUTF16toUTF8(aMessage));
+}
+
+void
+EmbedPrompter::SetMessageText(const PRUnichar *aMessageText)
+{
+    mMessageText.Assign(NS_ConvertUTF16toUTF8(aMessageText));
+}
+
+void
+EmbedPrompter::SetUser(const PRUnichar *aUser)
+{
+    mUser.Assign(NS_ConvertUTF16toUTF8(aUser));
+}
+
+void
+EmbedPrompter::SetPassword(const PRUnichar *aPass)
+{
+    mPass.Assign(NS_ConvertUTF16toUTF8(aPass));
+}
+
+void
+EmbedPrompter::SetCheckValue(const PRBool aValue)
+{
+    mCheckValue = aValue;
+}
+
+void
+EmbedPrompter::SetItems(const PRUnichar** aItemArray, PRUint32 aCount)
+{
+    if (mItemList)
+        delete[] mItemList;
+
+    mItemCount = aCount;
+    mItemList = new nsCString[aCount];
+    for (PRUint32 i = 0; i < aCount; ++i)
+        mItemList[i].Assign(NS_ConvertUTF16toUTF8(aItemArray[i]));
+}
+
+void
+EmbedPrompter::SetButtons(const PRUnichar* aButton0Label,
+                          const PRUnichar* aButton1Label,
+                          const PRUnichar* aButton2Label)
+{
+    mButtonLabels[0].Assign(NS_ConvertUTF16toUTF8(aButton0Label));
+    mButtonLabels[1].Assign(NS_ConvertUTF16toUTF8(aButton1Label));
+    mButtonLabels[2].Assign(NS_ConvertUTF16toUTF8(aButton2Label));
+}
+
+void
+EmbedPrompter::GetCheckValue(PRBool *aValue)
+{
+    *aValue = mCheckValue;
+}
+
+void
+EmbedPrompter::GetConfirmValue(PRBool *aConfirmValue)
+{
+    *aConfirmValue = mConfirmResult;
+}
+ 
+void
+EmbedPrompter::GetTextValue(PRUnichar **aTextValue)
+{
+    *aTextValue = ToNewUnicode(NS_ConvertUTF8toUTF16(mTextValue));
+}
+
+void
+EmbedPrompter::GetUser(PRUnichar **aUser)
+{
+    *aUser = ToNewUnicode(NS_ConvertUTF8toUTF16(mUser));
+}
+
+void
+EmbedPrompter::GetPassword(PRUnichar **aPass)
+{
+    *aPass = ToNewUnicode(NS_ConvertUTF8toUTF16(mPass));
+}
+
+void
+EmbedPrompter::GetSelectedItem(PRInt32 *aIndex)
+{
+    *aIndex = mSelectedItem;
+}
+
+void
+EmbedPrompter::GetButtonPressed(PRInt32 *aButton)
+{
+    *aButton = mButtonPressed;
+}
+
+void
+EmbedPrompter::Run(void)
+{
+    gtk_widget_show_all(mWindow);
+    gint response = gtk_dialog_run(GTK_DIALOG(mWindow));
+    switch (response) {
+    case GTK_RESPONSE_NONE:
+    case GTK_RESPONSE_CANCEL:
+    case GTK_RESPONSE_DELETE_EVENT:
+        mConfirmResult = PR_FALSE;
+        break;
+    case GTK_RESPONSE_ACCEPT:
+        mConfirmResult = PR_TRUE;
+        SaveDialogValues();
+        break;
+    default:
+        mButtonPressed = response;
+        SaveDialogValues();
+    }
+
+    gtk_widget_destroy(mWindow);
+}
+
+void
+EmbedPrompter::SaveDialogValues()
+{
+    if (mUserField)
+        mUser.Assign(gtk_entry_get_text(GTK_ENTRY(mUserField)));
+
+    if (mPassField)
+        mPass.Assign(gtk_entry_get_text(GTK_ENTRY(mPassField)));
+
+    if (mCheckBox)
+        mCheckValue = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(mCheckBox));
+
+    if (mTextField)
+        mTextValue.Assign(gtk_entry_get_text(GTK_ENTRY(mTextField)));
+
+    if (mComboBox)
+    {
+        gchar *str = gtk_combo_box_get_active_text(GTK_COMBO_BOX(mComboBox));
+        for (PRUint32 i = 0; i < mItemCount; ++i) {
+            if(mItemList[i].Equals(str))
+            {
+                mSelectedItem = i;
+                break;
+            }
+        }
+    }
+}
diff --git a/embedding/browser/gtk/src/EmbedPrompter.h b/embedding/browser/gtk/src/EmbedPrompter.h
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/EmbedPrompter.h
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *   Brian Ryner <bryner@brianryner.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsStringGlue.h"
+#include <gtk/gtk.h>
+
+#define EMBED_MAX_BUTTONS 3
+
+class EmbedPrompter {
+
+public:
+
+    EmbedPrompter();
+    ~EmbedPrompter();
+
+    enum PromptType {
+        TYPE_ALERT,
+        TYPE_ALERT_CHECK,
+        TYPE_CONFIRM,
+        TYPE_CONFIRM_CHECK,
+        TYPE_PROMPT,
+        TYPE_PROMPT_USER_PASS,
+        TYPE_PROMPT_PASS,
+        TYPE_SELECT,
+        TYPE_UNIVERSAL
+    };
+
+    nsresult Create(PromptType aType, GtkWindow* aParentWindow);
+    void     SetTitle(const PRUnichar *aTitle);
+    void     SetTextValue (const PRUnichar *aTextValue);
+    void     SetCheckMessage(const PRUnichar *aCheckMessage);
+    void     SetCheckValue(const PRBool aValue);
+    void     SetMessageText(const PRUnichar *aMessageText);
+    void     SetUser(const PRUnichar *aUser);
+    void     SetPassword(const PRUnichar *aPass);
+    void     SetButtons(const PRUnichar* aButton0Label,
+                        const PRUnichar* aButton1Label,
+                        const PRUnichar* aButton2Label);
+    void     SetItems(const PRUnichar **aItemArray, PRUint32 aCount);
+
+    void     GetCheckValue(PRBool *aValue);
+    void     GetConfirmValue(PRBool *aConfirmValue);
+    void     GetTextValue(PRUnichar **aTextValue);
+    void     GetUser(PRUnichar **aUser);
+    void     GetPassword(PRUnichar **aPass);
+    void     GetButtonPressed(PRInt32 *aButton);
+    void     GetSelectedItem(PRInt32 *aIndex);
+
+    void     Run(void);
+
+private:
+
+    void     SaveDialogValues();
+
+    nsCString    mTitle;
+    nsCString    mMessageText;
+    nsCString    mTextValue;
+    nsCString    mCheckMessage;
+    PRBool       mCheckValue;
+    nsCString    mUser;
+    nsCString    mPass;
+    nsCString    mButtonLabels[EMBED_MAX_BUTTONS];
+    nsCString   *mItemList;
+    PRUint32     mItemCount;
+
+    PRInt32      mButtonPressed;
+    PRBool       mConfirmResult;
+    PRInt32      mSelectedItem;
+
+    GtkWidget   *mWindow;
+    GtkWidget   *mUserField;
+    GtkWidget   *mPassField;
+    GtkWidget   *mTextField;
+    GtkWidget   *mComboBox;
+    GtkWidget   *mCheckBox;
+};
diff --git a/embedding/browser/gtk/src/EmbedWindow.cpp b/embedding/browser/gtk/src/EmbedWindow.cpp
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/EmbedWindow.cpp
@@ -0,0 +1,474 @@
+/*
+ * vim:ts=2:et:sw=2
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsCWebBrowser.h"
+#include "nsIComponentManager.h"
+#include "nsComponentManagerUtils.h"
+#include "nsIDocShellTreeItem.h"
+#include "nsIWidget.h"
+
+#include "EmbedWindow.h"
+#include "EmbedPrivate.h"
+#include "EmbedPrompter.h"
+
+GtkWidget *EmbedWindow::sTipWindow = nsnull;
+
+EmbedWindow::EmbedWindow(void)
+{
+  mOwner       = nsnull;
+  mVisibility  = PR_FALSE;
+  mIsModal     = PR_FALSE;
+}
+
+EmbedWindow::~EmbedWindow(void)
+{
+  ExitModalEventLoop(PR_FALSE);
+}
+
+nsresult
+EmbedWindow::Init(EmbedPrivate *aOwner)
+{
+  // save our owner for later
+  mOwner = aOwner;
+
+  // create our nsIWebBrowser object and set up some basic defaults.
+  mWebBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID);
+  if (!mWebBrowser)
+    return NS_ERROR_FAILURE;
+
+  mWebBrowser->SetContainerWindow(static_cast<nsIWebBrowserChrome *>(this));
+  
+  nsCOMPtr<nsIDocShellTreeItem> item = do_QueryInterface(mWebBrowser);
+  item->SetItemType(nsIDocShellTreeItem::typeContentWrapper);
+
+  return NS_OK;
+}
+
+nsresult
+EmbedWindow::CreateWindow(void)
+{
+  nsresult rv;
+  GtkWidget *ownerAsWidget = GTK_WIDGET(mOwner->mOwningWidget);
+
+  // Get the base window interface for the web browser object and
+  // create the window.
+  mBaseWindow = do_QueryInterface(mWebBrowser);
+  rv = mBaseWindow->InitWindow(GTK_WIDGET(mOwner->mOwningWidget),
+			       nsnull,
+			       0, 0, 
+			       ownerAsWidget->allocation.width,
+			       ownerAsWidget->allocation.height);
+  if (NS_FAILED(rv))
+    return rv;
+
+  rv = mBaseWindow->Create();
+  if (NS_FAILED(rv))
+    return rv;
+
+  return NS_OK;
+}
+
+void
+EmbedWindow::ReleaseChildren(void)
+{
+  ExitModalEventLoop(PR_FALSE);
+    
+  mBaseWindow->Destroy();
+  mBaseWindow = 0;
+  mWebBrowser = 0;
+}
+
+// nsISupports
+
+NS_IMPL_ADDREF(EmbedWindow)
+NS_IMPL_RELEASE(EmbedWindow)
+
+NS_INTERFACE_MAP_BEGIN(EmbedWindow)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowserChrome)
+  NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
+  NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChromeFocus)
+  NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow)
+  NS_INTERFACE_MAP_ENTRY(nsITooltipListener)
+  NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
+NS_INTERFACE_MAP_END
+
+// nsIWebBrowserChrome
+
+NS_IMETHODIMP
+EmbedWindow::SetStatus(PRUint32 aStatusType, const PRUnichar *aStatus)
+{
+  switch (aStatusType) {
+  case STATUS_SCRIPT: 
+    {
+      mJSStatus = aStatus;
+      g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                    moz_embed_signals[JS_STATUS], 0);
+    }
+    break;
+  case STATUS_SCRIPT_DEFAULT:
+    // Gee, that's nice.
+    break;
+  case STATUS_LINK:
+    {
+      mLinkMessage = aStatus;
+      g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                    moz_embed_signals[LINK_MESSAGE], 0);
+    }
+    break;
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::GetWebBrowser(nsIWebBrowser **aWebBrowser)
+{
+  *aWebBrowser = mWebBrowser;
+  NS_IF_ADDREF(*aWebBrowser);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::SetWebBrowser(nsIWebBrowser *aWebBrowser)
+{
+  mWebBrowser = aWebBrowser;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::GetChromeFlags(PRUint32 *aChromeFlags)
+{
+  *aChromeFlags = mOwner->mChromeMask;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::SetChromeFlags(PRUint32 aChromeFlags)
+{
+  mOwner->SetChromeMask(aChromeFlags);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::DestroyBrowserWindow(void)
+{
+  // mark the owner as destroyed so it won't emit events anymore.
+  mOwner->mIsDestroyed = PR_TRUE;
+
+  g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                moz_embed_signals[DESTROY_BROWSER], 0);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::SizeBrowserTo(PRInt32 aCX, PRInt32 aCY)
+{
+  g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                moz_embed_signals[SIZE_TO], 0, aCX, aCY);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::ShowAsModal(void)
+{
+  mIsModal = PR_TRUE;
+  GtkWidget *toplevel;
+  toplevel = gtk_widget_get_toplevel(GTK_WIDGET(mOwner->mOwningWidget));
+  gtk_grab_add(toplevel);
+  gtk_main();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::IsWindowModal(PRBool *_retval)
+{
+  *_retval = mIsModal;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::ExitModalEventLoop(nsresult aStatus)
+{
+  if (mIsModal) {
+    GtkWidget *toplevel;
+    toplevel = gtk_widget_get_toplevel(GTK_WIDGET(mOwner->mOwningWidget));
+    gtk_grab_remove(toplevel);
+    mIsModal = PR_FALSE;
+    gtk_main_quit();
+  }
+  return NS_OK;
+}
+
+// nsIWebBrowserChromeFocus
+
+NS_IMETHODIMP
+EmbedWindow::FocusNextElement()
+{
+  GtkWidget *toplevel;
+  toplevel = gtk_widget_get_toplevel(GTK_WIDGET(mOwner->mOwningWidget));
+  if (!GTK_WIDGET_TOPLEVEL(toplevel))
+    return NS_OK;
+
+  g_signal_emit_by_name(G_OBJECT(toplevel), "move_focus",
+			GTK_DIR_TAB_FORWARD);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::FocusPrevElement()
+{
+  GtkWidget *toplevel;
+  toplevel = gtk_widget_get_toplevel(GTK_WIDGET(mOwner->mOwningWidget));
+  if (!GTK_WIDGET_TOPLEVEL(toplevel))
+    return NS_OK;
+
+  g_signal_emit_by_name(G_OBJECT(toplevel), "move_focus",
+			GTK_DIR_TAB_BACKWARD);
+  return NS_OK;
+}
+
+// nsIEmbeddingSiteWindow
+
+NS_IMETHODIMP
+EmbedWindow::SetDimensions(PRUint32 aFlags, PRInt32 aX, PRInt32 aY,
+			   PRInt32 aCX, PRInt32 aCY)
+{
+  if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION &&
+      (aFlags & (nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER |
+		 nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER))) {
+    return mBaseWindow->SetPositionAndSize(aX, aY, aCX, aCY, PR_TRUE);
+  }
+  else if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) {
+    return mBaseWindow->SetPosition(aX, aY);
+  }
+  else if (aFlags & (nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER |
+		     nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER)) {
+    return mBaseWindow->SetSize(aCX, aCY, PR_TRUE);
+  }
+  return NS_ERROR_INVALID_ARG;
+}
+
+NS_IMETHODIMP
+EmbedWindow::GetDimensions(PRUint32 aFlags, PRInt32 *aX,
+			   PRInt32 *aY, PRInt32 *aCX, PRInt32 *aCY)
+{
+  if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION &&
+      (aFlags & (nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER |
+		 nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER))) {
+    return mBaseWindow->GetPositionAndSize(aX, aY, aCX, aCY);
+  }
+  else if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) {
+    return mBaseWindow->GetPosition(aX, aY);
+  }
+  else if (aFlags & (nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER |
+		     nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER)) {
+    return mBaseWindow->GetSize(aCX, aCY);
+  }
+  return NS_ERROR_INVALID_ARG;
+}
+
+NS_IMETHODIMP
+EmbedWindow::SetFocus(void)
+{
+  // XXX might have to do more here.
+  return mBaseWindow->SetFocus();
+}
+
+NS_IMETHODIMP
+EmbedWindow::GetTitle(PRUnichar **aTitle)
+{
+  *aTitle = ToNewUnicode(mTitle);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::SetTitle(const PRUnichar *aTitle)
+{
+  mTitle = aTitle;
+  g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                moz_embed_signals[TITLE], 0);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::GetSiteWindow(void **aSiteWindow)
+{
+  GtkWidget *ownerAsWidget (GTK_WIDGET(mOwner->mOwningWidget));
+  *aSiteWindow = static_cast<void *>(ownerAsWidget);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::GetVisibility(PRBool *aVisibility)
+{
+  // XXX See bug 312998
+  // Work around the problem that sometimes the window
+  // is already visible even though mVisibility isn't true
+  // yet.
+  *aVisibility = mVisibility ||
+                 (!mOwner->mIsChrome &&
+                  mOwner->mOwningWidget &&
+                  GTK_WIDGET_MAPPED(mOwner->mOwningWidget));
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::SetVisibility(PRBool aVisibility)
+{
+  // We always set the visibility so that if it's chrome and we finish
+  // the load we know that we have to show the window.
+  mVisibility = aVisibility;
+
+  // if this is a chrome window and the chrome hasn't finished loading
+  // yet then don't show the window yet.
+  if (mOwner->mIsChrome && !mOwner->mChromeLoaded)
+    return NS_OK;
+
+  g_signal_emit(G_OBJECT(mOwner->mOwningWidget),
+                moz_embed_signals[VISIBILITY], 0,
+                aVisibility);
+  return NS_OK;
+}
+
+// nsITooltipListener
+
+static gint
+tooltips_paint_window(GtkWidget *window)
+{
+  // draw tooltip style border around the text
+  gtk_paint_flat_box(window->style, window->window,
+                     GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+                     NULL, window, "tooltip",
+                     0, 0,
+                     window->allocation.width, window->allocation.height);
+
+  return FALSE;
+}
+                                     
+NS_IMETHODIMP
+EmbedWindow::OnShowTooltip(PRInt32 aXCoords, PRInt32 aYCoords,
+			   const PRUnichar *aTipText)
+{
+  nsAutoString tipText ( aTipText );
+
+  const char* tipString = ToNewUTF8String(tipText);
+
+  if (sTipWindow)
+    gtk_widget_destroy(sTipWindow);
+  
+  // get the root origin for this content window
+  nsCOMPtr<nsIWidget> mainWidget;
+  mBaseWindow->GetMainWidget(getter_AddRefs(mainWidget));
+  GdkWindow *window;
+  window = static_cast<GdkWindow *>(mainWidget->GetNativeData(NS_NATIVE_WINDOW));
+  gint root_x, root_y;
+  gdk_window_get_origin(window, &root_x, &root_y);
+
+  // XXX work around until I can get pink to figure out why
+  // tooltips vanish if they show up right at the origin of the
+  // cursor.
+  root_y += 10;
+  
+  sTipWindow = gtk_window_new(GTK_WINDOW_POPUP);
+  gtk_widget_set_app_paintable(sTipWindow, TRUE);
+  gtk_window_set_resizable(GTK_WINDOW(sTipWindow), TRUE);
+  // needed to get colors + fonts etc correctly
+  gtk_widget_set_name(sTipWindow, "gtk-tooltips");
+  gtk_window_set_type_hint(GTK_WINDOW(sTipWindow), GDK_WINDOW_TYPE_HINT_TOOLTIP);
+  
+  // set up the popup window as a transient of the widget.
+  GtkWidget *toplevel_window;
+  toplevel_window = gtk_widget_get_toplevel(GTK_WIDGET(mOwner->mOwningWidget));
+  if (!GTK_WINDOW(toplevel_window)) {
+    NS_ERROR("no gtk window in hierarchy!");
+    return NS_ERROR_FAILURE;
+  }
+  gtk_window_set_transient_for(GTK_WINDOW(sTipWindow),
+			       GTK_WINDOW(toplevel_window));
+  
+  // realize the widget
+  gtk_widget_realize(sTipWindow);
+
+  g_signal_connect(G_OBJECT(sTipWindow), "expose_event",
+                   G_CALLBACK(tooltips_paint_window), NULL);
+
+  // set up the label for the tooltip
+  GtkWidget *label = gtk_label_new(tipString);
+  // wrap automatically
+  gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+  gtk_container_add(GTK_CONTAINER(sTipWindow), label);
+  gtk_container_set_border_width(GTK_CONTAINER(sTipWindow), 4);
+  // set the coords for the widget
+  gtk_widget_set_uposition(sTipWindow, aXCoords + root_x,
+			   aYCoords + root_y);
+
+  // and show it.
+  gtk_widget_show_all(sTipWindow);
+
+  NS_Free( (void*)tipString );
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+EmbedWindow::OnHideTooltip(void)
+{
+  if (sTipWindow)
+    gtk_widget_destroy(sTipWindow);
+  sTipWindow = NULL;
+  return NS_OK;
+}
+
+// nsIInterfaceRequestor
+
+NS_IMETHODIMP
+EmbedWindow::GetInterface(const nsIID &aIID, void** aInstancePtr)
+{
+  nsresult rv;
+  
+  rv = QueryInterface(aIID, aInstancePtr);
+
+  // pass it up to the web browser object
+  if (NS_FAILED(rv) || !*aInstancePtr) {
+    nsCOMPtr<nsIInterfaceRequestor> ir = do_QueryInterface(mWebBrowser);
+    return ir->GetInterface(aIID, aInstancePtr);
+  }
+
+  return rv;
+}
diff --git a/embedding/browser/gtk/src/EmbedWindow.h b/embedding/browser/gtk/src/EmbedWindow.h
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/EmbedWindow.h
@@ -0,0 +1,101 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __EmbedWindow_h
+#define __EmbedWindow_h
+
+#include "nsIWebBrowserChrome.h"
+#include "nsIWebBrowserChromeFocus.h"
+#include "nsIEmbeddingSiteWindow.h"
+#include "nsITooltipListener.h"
+#include "nsISupports.h"
+#include "nsIWebBrowser.h"
+#include "nsIBaseWindow.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsCOMPtr.h"
+#include "nsStringGlue.h"
+
+#include <gtk/gtk.h>
+
+class EmbedPrivate;
+
+class EmbedWindow : public nsIWebBrowserChrome,
+		    public nsIWebBrowserChromeFocus,
+                    public nsIEmbeddingSiteWindow,
+                    public nsITooltipListener,
+		    public nsIInterfaceRequestor
+{
+
+ public:
+
+  EmbedWindow();
+  virtual ~EmbedWindow();
+
+  nsresult Init            (EmbedPrivate *aOwner);
+  nsresult CreateWindow    (void);
+  void     ReleaseChildren (void);
+
+  NS_DECL_ISUPPORTS
+
+  NS_DECL_NSIWEBBROWSERCHROME
+
+  NS_DECL_NSIWEBBROWSERCHROMEFOCUS
+
+  NS_DECL_NSIEMBEDDINGSITEWINDOW
+
+  NS_DECL_NSITOOLTIPLISTENER
+
+  NS_DECL_NSIINTERFACEREQUESTOR
+
+  nsString                 mTitle;
+  nsString                 mJSStatus;
+  nsString                 mLinkMessage;
+
+  nsCOMPtr<nsIBaseWindow>  mBaseWindow; // [OWNER]
+
+private:
+
+  EmbedPrivate            *mOwner;
+  nsCOMPtr<nsIWebBrowser>  mWebBrowser; // [OWNER]
+  static GtkWidget        *sTipWindow;
+  PRBool                   mVisibility;
+  PRBool                   mIsModal;
+
+};
+  
+
+#endif /* __EmbedWindow_h */
diff --git a/embedding/browser/gtk/src/EmbedWindowCreator.cpp b/embedding/browser/gtk/src/EmbedWindowCreator.cpp
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/EmbedWindowCreator.cpp
@@ -0,0 +1,106 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright (C) Christopher Blizzard.  All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "EmbedWindowCreator.h"
+#include "EmbedPrivate.h"
+#include "EmbedWindow.h"
+
+// in order to create orphaned windows
+#include "gtkmozembedprivate.h"
+
+EmbedWindowCreator::EmbedWindowCreator(void)
+{
+}
+
+EmbedWindowCreator::~EmbedWindowCreator()
+{
+}
+
+NS_IMPL_ISUPPORTS1(EmbedWindowCreator, nsIWindowCreator)
+
+NS_IMETHODIMP
+EmbedWindowCreator::CreateChromeWindow(nsIWebBrowserChrome *aParent,
+				       PRUint32 aChromeFlags,
+				       nsIWebBrowserChrome **_retval)
+{
+  NS_ENSURE_ARG_POINTER(_retval);
+
+  GtkMozEmbed *newEmbed = nsnull;
+
+  // No parent?  Ask via the singleton object instead.
+  if (!aParent) {
+    gtk_moz_embed_single_create_window(&newEmbed,
+				       (guint)aChromeFlags);
+  }
+  else {
+    // Find the EmbedPrivate object for this web browser chrome object.
+    EmbedPrivate *embedPrivate = EmbedPrivate::FindPrivateForBrowser(aParent);
+    
+    if (!embedPrivate)
+      return NS_ERROR_FAILURE;
+    
+    g_signal_emit(G_OBJECT(embedPrivate->mOwningWidget),
+                  moz_embed_signals[NEW_WINDOW], 0,
+                  &newEmbed, (guint)aChromeFlags);
+    
+  }
+
+  // check to make sure that we made a new window
+  if (!newEmbed)
+    return NS_ERROR_FAILURE;
+
+  // The window _must_ be realized before we pass it back to the
+  // function that created it. Functions that create new windows
+  // will do things like GetDocShell() and the widget has to be
+  // realized before that can happen.
+  gtk_widget_realize(GTK_WIDGET(newEmbed));
+  
+  EmbedPrivate *newEmbedPrivate = static_cast<EmbedPrivate *>(newEmbed->data);
+
+  // set the chrome flag on the new window if it's a chrome open
+  if (aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)
+    newEmbedPrivate->mIsChrome = PR_TRUE;
+
+  *_retval = static_cast<nsIWebBrowserChrome *>(newEmbedPrivate->mWindow);
+  
+  if (*_retval) {
+    NS_ADDREF(*_retval);
+    return NS_OK;
+  }
+
+  return NS_ERROR_FAILURE;
+}
diff --git a/embedding/browser/gtk/src/EmbedWindowCreator.h b/embedding/browser/gtk/src/EmbedWindowCreator.h
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/EmbedWindowCreator.h
@@ -0,0 +1,54 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __EmbedWindowCreator_h
+#define __EmbedWindowCreator_h
+
+#include <nsIWindowCreator.h>
+
+class EmbedWindowCreator : public nsIWindowCreator
+{
+ public:
+  EmbedWindowCreator();
+  virtual ~EmbedWindowCreator();
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIWINDOWCREATOR
+  
+};
+
+#endif /* __EmbedWindowCreator_h */
diff --git a/embedding/browser/gtk/src/GtkPromptService.cpp b/embedding/browser/gtk/src/GtkPromptService.cpp
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/GtkPromptService.cpp
@@ -0,0 +1,349 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Brian Ryner <bryner@brianryner.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "GtkPromptService.h"
+#include "EmbedPrompter.h"
+#include "nsStringGlue.h"
+#include "nsIWindowWatcher.h"
+#include "nsIWebBrowserChrome.h"
+#include "nsIEmbeddingSiteWindow.h"
+#include "nsCOMPtr.h"
+#include "nsIServiceManager.h"
+#include "nsServiceManagerUtils.h"
+
+GtkPromptService::GtkPromptService()
+{
+}
+
+GtkPromptService::~GtkPromptService()
+{
+}
+
+NS_IMPL_ISUPPORTS1(GtkPromptService, nsIPromptService)
+
+NS_IMETHODIMP
+GtkPromptService::Alert(nsIDOMWindow* aParent, const PRUnichar* aDialogTitle, 
+                        const PRUnichar* aDialogText)
+{
+    EmbedPrompter prompter;
+    prompter.SetTitle(aDialogTitle ? aDialogTitle : NS_LITERAL_STRING("Alert").get());
+    prompter.SetMessageText(aDialogText);
+    prompter.Create(EmbedPrompter::TYPE_ALERT, 
+                    GetGtkWindowForDOMWindow(aParent));
+    prompter.Run();
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+GtkPromptService::AlertCheck(nsIDOMWindow* aParent,
+                             const PRUnichar* aDialogTitle,
+                             const PRUnichar* aDialogText,
+                             const PRUnichar* aCheckMsg, PRBool* aCheckValue)
+{
+    NS_ENSURE_ARG_POINTER(aCheckValue);
+
+    EmbedPrompter prompter;
+    prompter.SetTitle(aDialogTitle ? aDialogTitle : NS_LITERAL_STRING("Alert").get());
+    prompter.SetMessageText(aDialogText);
+    prompter.SetCheckMessage(aCheckMsg);
+    prompter.SetCheckValue(*aCheckValue);
+    prompter.Create(EmbedPrompter::TYPE_ALERT_CHECK,
+                    GetGtkWindowForDOMWindow(aParent));
+    prompter.Run();
+    prompter.GetCheckValue(aCheckValue);
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+GtkPromptService::Confirm(nsIDOMWindow* aParent,
+                          const PRUnichar* aDialogTitle,
+                          const PRUnichar* aDialogText, PRBool* aConfirm)
+{
+    EmbedPrompter prompter;
+    prompter.SetTitle(aDialogTitle ? aDialogTitle : NS_LITERAL_STRING("Confirm").get());
+    prompter.SetMessageText(aDialogText);
+    prompter.Create(EmbedPrompter::TYPE_CONFIRM,
+                    GetGtkWindowForDOMWindow(aParent));
+    prompter.Run();
+    prompter.GetConfirmValue(aConfirm);
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+GtkPromptService::ConfirmCheck(nsIDOMWindow* aParent,
+                               const PRUnichar* aDialogTitle,
+                               const PRUnichar* aDialogText,
+                               const PRUnichar* aCheckMsg,
+                               PRBool* aCheckValue, PRBool* aConfirm)
+{
+    NS_ENSURE_ARG_POINTER(aCheckValue);
+
+    EmbedPrompter prompter;
+    prompter.SetTitle(aDialogTitle ? aDialogTitle : NS_LITERAL_STRING("Confirm").get());
+    prompter.SetMessageText(aDialogText);
+    prompter.SetCheckMessage(aCheckMsg);
+    prompter.SetCheckValue(*aCheckValue);
+    prompter.Create(EmbedPrompter::TYPE_CONFIRM_CHECK,
+                    GetGtkWindowForDOMWindow(aParent));
+    prompter.Run();
+    prompter.GetCheckValue(aCheckValue);
+    prompter.GetConfirmValue(aConfirm);
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+GtkPromptService::ConfirmEx(nsIDOMWindow* aParent,
+                            const PRUnichar* aDialogTitle,
+                            const PRUnichar* aDialogText,
+                            PRUint32 aButtonFlags,
+                            const PRUnichar* aButton0Title,
+                            const PRUnichar* aButton1Title,
+                            const PRUnichar* aButton2Title,
+                            const PRUnichar* aCheckMsg, PRBool* aCheckValue,
+                            PRInt32* aRetVal)
+{
+    EmbedPrompter prompter;
+    prompter.SetTitle(aDialogTitle ? aDialogTitle : NS_LITERAL_STRING("Confirm").get());
+    prompter.SetMessageText(aDialogText);
+
+    nsAutoString button0Label, button1Label, button2Label;
+    GetButtonLabel(aButtonFlags, BUTTON_POS_0, aButton0Title, button0Label);
+    GetButtonLabel(aButtonFlags, BUTTON_POS_1, aButton1Title, button1Label);
+    GetButtonLabel(aButtonFlags, BUTTON_POS_2, aButton2Title, button2Label);
+    prompter.SetButtons(button0Label.get(), button1Label.get(),
+                        button2Label.get());
+
+    if (aCheckMsg)
+        prompter.SetCheckMessage(aCheckMsg);
+    if (aCheckValue)
+        prompter.SetCheckValue(*aCheckValue);
+
+    prompter.Create(EmbedPrompter::TYPE_UNIVERSAL,
+                    GetGtkWindowForDOMWindow(aParent));
+    prompter.Run();
+
+    if (aCheckValue)
+        prompter.GetCheckValue(aCheckValue);
+
+    prompter.GetButtonPressed(aRetVal);
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+GtkPromptService::Prompt(nsIDOMWindow* aParent, const PRUnichar* aDialogTitle,
+                         const PRUnichar* aDialogText, PRUnichar** aValue,
+                         const PRUnichar* aCheckMsg, PRBool* aCheckValue,
+                         PRBool* aConfirm)
+{
+    EmbedPrompter prompter;
+    prompter.SetTitle(aDialogTitle ? aDialogTitle : NS_LITERAL_STRING("Prompt").get());
+    prompter.SetMessageText(aDialogText);
+    prompter.SetTextValue(*aValue);
+    if (aCheckMsg)
+        prompter.SetCheckMessage(aCheckMsg);
+    if (aCheckValue)
+        prompter.SetCheckValue(*aCheckValue);
+
+    prompter.Create(EmbedPrompter::TYPE_PROMPT,
+                    GetGtkWindowForDOMWindow(aParent));
+    prompter.Run();
+    if (aCheckValue)
+        prompter.GetCheckValue(aCheckValue);
+    prompter.GetConfirmValue(aConfirm);
+    if (*aConfirm) {
+        if (*aValue)
+            NS_Free(*aValue);
+        prompter.GetTextValue(aValue);
+    }
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+GtkPromptService::PromptUsernameAndPassword(nsIDOMWindow* aParent,
+                                            const PRUnichar* aDialogTitle,
+                                            const PRUnichar* aDialogText,
+                                            PRUnichar** aUsername,
+                                            PRUnichar** aPassword,
+                                            const PRUnichar* aCheckMsg,
+                                            PRBool* aCheckValue,
+                                            PRBool* aConfirm)
+{
+    EmbedPrompter prompter;
+    prompter.SetTitle(aDialogTitle ? aDialogTitle : NS_LITERAL_STRING("Prompt").get());
+    prompter.SetMessageText(aDialogText);
+    prompter.SetUser(*aUsername);
+    prompter.SetPassword(*aPassword);
+    if (aCheckMsg)
+        prompter.SetCheckMessage(aCheckMsg);
+    if (aCheckValue)
+        prompter.SetCheckValue(*aCheckValue);
+
+    prompter.Create(EmbedPrompter::TYPE_PROMPT_USER_PASS,
+                    GetGtkWindowForDOMWindow(aParent));
+    prompter.Run();
+    if (aCheckValue)
+        prompter.GetCheckValue(aCheckValue);
+    prompter.GetConfirmValue(aConfirm);
+    if (*aConfirm) {
+        if (*aUsername)
+            NS_Free(*aUsername);
+        prompter.GetUser(aUsername);
+
+        if (*aPassword)
+            NS_Free(*aPassword);
+        prompter.GetPassword(aPassword);
+    }
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+GtkPromptService::PromptPassword(nsIDOMWindow* aParent,
+                                 const PRUnichar* aDialogTitle,
+                                 const PRUnichar* aDialogText,
+                                 PRUnichar** aPassword,
+                                 const PRUnichar* aCheckMsg,
+                                 PRBool* aCheckValue, PRBool* aConfirm)
+{
+    EmbedPrompter prompter;
+    prompter.SetTitle(aDialogTitle ? aDialogTitle : NS_LITERAL_STRING("Prompt").get());
+    prompter.SetMessageText(aDialogText);
+    prompter.SetPassword(*aPassword);
+    if (aCheckMsg)
+        prompter.SetCheckMessage(aCheckMsg);
+    if (aCheckValue)
+        prompter.SetCheckValue(*aCheckValue);
+
+    prompter.Create(EmbedPrompter::TYPE_PROMPT_PASS,
+                    GetGtkWindowForDOMWindow(aParent));
+    prompter.Run();
+    if (aCheckValue)
+        prompter.GetCheckValue(aCheckValue);
+    prompter.GetConfirmValue(aConfirm);
+    if (*aConfirm) {
+        if (*aPassword)
+            NS_Free(*aPassword);
+        prompter.GetPassword(aPassword);
+    }
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+GtkPromptService::Select(nsIDOMWindow* aParent, const PRUnichar* aDialogTitle,
+                         const PRUnichar* aDialogText, PRUint32 aCount,
+                         const PRUnichar** aSelectList, PRInt32* outSelection,
+                         PRBool* aConfirm)
+{
+    EmbedPrompter prompter;
+    prompter.SetTitle(aDialogTitle ? aDialogTitle : NS_LITERAL_STRING("Select").get());
+    prompter.SetMessageText(aDialogText);
+    prompter.SetItems(aSelectList, aCount);
+    prompter.Create(EmbedPrompter::TYPE_SELECT,
+                    GetGtkWindowForDOMWindow(aParent));
+    prompter.Run();
+    prompter.GetSelectedItem(outSelection);
+    prompter.GetConfirmValue(aConfirm);
+    return NS_OK;
+}
+
+GtkWindow*
+GtkPromptService::GetGtkWindowForDOMWindow(nsIDOMWindow* aDOMWindow)
+{
+    nsCOMPtr<nsIWindowWatcher> wwatch = do_GetService("@mozilla.org/embedcomp/window-watcher;1");
+
+    if (!aDOMWindow)
+        return NULL;
+
+    nsCOMPtr<nsIWebBrowserChrome> chrome;
+    wwatch->GetChromeForWindow(aDOMWindow, getter_AddRefs(chrome));
+    nsCOMPtr<nsIEmbeddingSiteWindow> siteWindow = do_QueryInterface(chrome);
+
+    if (!siteWindow)
+        return NULL;
+
+    GtkWidget* parentWidget;
+    siteWindow->GetSiteWindow((void**)&parentWidget);
+
+    if (!parentWidget)
+        return NULL;
+
+    GtkWidget* gtkWin = gtk_widget_get_toplevel(parentWidget);
+    if (GTK_WIDGET_TOPLEVEL(gtkWin))
+        return GTK_WINDOW(gtkWin);
+
+    return NULL;
+}
+
+void
+GtkPromptService::GetButtonLabel(PRUint32 aFlags, PRUint32 aPos,
+                                 const PRUnichar* aStringValue,
+                                 nsAString& aLabel)
+{
+    PRUint32 posFlag = (aFlags & (255 * aPos)) / aPos;
+    switch (posFlag) {
+    case 0:
+        break;
+    case BUTTON_TITLE_OK:
+        aLabel.AssignLiteral(GTK_STOCK_OK);
+        break;
+    case BUTTON_TITLE_CANCEL:
+        aLabel.AssignLiteral(GTK_STOCK_CANCEL);
+        break;
+    case BUTTON_TITLE_YES:
+        aLabel.AssignLiteral(GTK_STOCK_YES);
+        break;
+    case BUTTON_TITLE_NO:
+        aLabel.AssignLiteral(GTK_STOCK_NO);
+        break;
+    case BUTTON_TITLE_SAVE:
+        aLabel.AssignLiteral(GTK_STOCK_SAVE);
+        break;
+    case BUTTON_TITLE_DONT_SAVE:
+        aLabel.AssignLiteral("Don't Save");
+        break;
+    case BUTTON_TITLE_REVERT:
+        aLabel.AssignLiteral("Revert");
+        break;
+    case BUTTON_TITLE_IS_STRING:
+        aLabel = aStringValue;
+        break;
+    default:
+        NS_WARNING("Unexpected button flags");
+    }
+}
diff --git a/embedding/browser/gtk/src/GtkPromptService.h b/embedding/browser/gtk/src/GtkPromptService.h
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/GtkPromptService.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Brian Ryner <bryner@brianryner.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIPromptService.h"
+#include "nsStringGlue.h"
+#include <gtk/gtk.h>
+
+class nsIDOMWindow;
+
+class GtkPromptService : public nsIPromptService
+{
+public:
+    GtkPromptService();
+    virtual ~GtkPromptService();
+
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIPROMPTSERVICE
+
+private:
+    GtkWindow* GetGtkWindowForDOMWindow(nsIDOMWindow* aDOMWindow);
+    void GetButtonLabel(PRUint32 aFlags, PRUint32 aPos,
+                        const PRUnichar* aStringValue, nsAString &aLabel);
+};
diff --git a/embedding/browser/gtk/src/Makefile.in b/embedding/browser/gtk/src/Makefile.in
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/Makefile.in
@@ -0,0 +1,112 @@
+# 
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.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 the Mozilla browser.
+#
+# The Initial Developer of the Original Code is
+# Christopher Blizzard.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Christopher Blizzard <blizzard@mozilla.org>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE		= gtkembedmoz
+LIBRARY_NAME	= gtkembedmoz
+LIBXUL_LIBRARY	= 1
+FORCE_STATIC_LIB = 1
+DEFINES += -DIMPL_XREAPI
+
+
+
+CPPSRCS		= \
+		gtkmozembed2.cpp \
+		EmbedPrivate.cpp \
+		EmbedWindow.cpp \
+		EmbedProgress.cpp \
+		EmbedContentListener.cpp \
+		EmbedEventListener.cpp \
+		EmbedWindowCreator.cpp \
+		$(NULL)
+
+ifdef MOZ_ENABLE_GTK2
+CSRCS           = \
+		gtkmozembedmarshal.c
+CPPSRCS         += \
+		EmbedPrompter.cpp \
+		GtkPromptService.cpp
+endif
+
+LOCAL_INCLUDES += \
+		  -I. \
+		  $(NULL)
+
+include $(topsrcdir)/config/config.mk
+
+EXPORTS		= \
+		gtkmozembed.h \
+		gtkmozembed_glue.cpp \
+		gtkmozembed_internal.h
+
+include $(topsrcdir)/config/rules.mk
+
+ifeq ($(OS_ARCH), SunOS)
+ifndef GNU_CC
+# When using Sun's WorkShop compiler, including
+# /wherever/workshop-5.0/SC5.0/include/CC/std/time.h
+# causes most of these compiles to fail with:
+# line 29: Error: Multiple declaration for std::tm.
+# So, this gets around the problem.
+DEFINES         += -D_TIME_H=1
+endif
+endif
+
+CXXFLAGS        += $(MOZ_GTK_CFLAGS) $(MOZ_GTK2_CFLAGS)
+CFLAGS          += $(MOZ_GTK_CFLAGS) $(MOZ_GTK2_CFLAGS)
+DEFINES         += -D_IMPL_GTKMOZEMBED
+
+MARSHAL_FILE = gtkmozembedmarshal
+MARSHAL_PREFIX = gtkmozembed
+
+$(MARSHAL_FILE).h: $(MARSHAL_FILE).list
+	glib-genmarshal --prefix=$(MARSHAL_PREFIX) $(srcdir)/$(MARSHAL_FILE).list --skip-source --header > $@
+
+$(MARSHAL_FILE).c: $(MARSHAL_FILE).list $(MARSHAL_FILE).h
+	glib-genmarshal --prefix=$(MARSHAL_PREFIX) $(srcdir)/$(MARSHAL_FILE).list --skip-source --body > $@
+
+gtkmozembed2.$(OBJ_SUFFIX): $(MARSHAL_FILE).h
+
+GARBAGE += $(MARSHAL_FILE).h $(MARSHAL_FILE).c
+
diff --git a/embedding/browser/gtk/src/gtkmozembed.h b/embedding/browser/gtk/src/gtkmozembed.h
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/gtkmozembed.h
@@ -0,0 +1,287 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *   Ramiro Estrugo <ramiro@eazel.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef gtkmozembed_h
+#define gtkmozembed_h
+
+#include <stddef.h>
+#include <gtk/gtk.h>
+
+#ifdef MOZILLA_CLIENT
+#include "nscore.h"
+#else /* MOZILLA_CLIENT */
+#ifndef nscore_h__
+/* Because this header may be included from files which not part of the mozilla
+   build system, define macros from nscore.h */
+
+#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
+#define NS_HIDDEN __attribute__((visibility("hidden")))
+#else
+#define NS_HIDDEN
+#endif
+
+#define NS_FROZENCALL
+#define NS_EXPORT_(type) type
+#define NS_IMPORT_(type) type
+#endif /* nscore_h__ */
+#endif /* MOZILLA_CLIENT */
+
+#ifdef XPCOM_GLUE
+
+#define GTKMOZEMBED_API(type, name, params) \
+  typedef type (NS_FROZENCALL * name##Type) params; \
+  extern name##Type name NS_HIDDEN;
+
+#else /* XPCOM_GLUE */
+
+#ifdef _IMPL_GTKMOZEMBED
+#define GTKMOZEMBED_API(type, name, params) NS_EXPORT_(type) name params;
+#else
+#define GTKMOZEMBED_API(type,name, params) NS_IMPORT_(type) name params;
+#endif
+
+#endif /* XPCOM_GLUE */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define GTK_TYPE_MOZ_EMBED             (gtk_moz_embed_get_type())
+#define GTK_MOZ_EMBED(obj)             G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_MOZ_EMBED, GtkMozEmbed)
+#define GTK_MOZ_EMBED_CLASS(klass)     G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_MOZ_EMBED, GtkMozEmbedClass)
+#define GTK_IS_MOZ_EMBED(obj)          G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_MOZ_EMBED)
+#define GTK_IS_MOZ_EMBED_CLASS(klass)  G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_MOZ_EMBED)
+
+typedef struct _GtkMozEmbed      GtkMozEmbed;
+typedef struct _GtkMozEmbedClass GtkMozEmbedClass;
+
+struct _GtkMozEmbed
+{
+  GtkBin    bin;
+  void     *data;
+};
+
+struct _GtkMozEmbedClass
+{
+  GtkBinClass parent_class;
+
+  void (* link_message)        (GtkMozEmbed *embed);
+  void (* js_status)           (GtkMozEmbed *embed);
+  void (* location)            (GtkMozEmbed *embed);
+  void (* title)               (GtkMozEmbed *embed);
+  void (* progress)            (GtkMozEmbed *embed, gint curprogress,
+                                gint maxprogress);
+  void (* progress_all)        (GtkMozEmbed *embed, const char *aURI,
+                                gint curprogress, gint maxprogress);
+  void (* net_state)           (GtkMozEmbed *embed, gint state, guint status);
+  void (* net_state_all)       (GtkMozEmbed *embed, const char *aURI,
+                                gint state, guint status);
+  void (* net_start)           (GtkMozEmbed *embed);
+  void (* net_stop)            (GtkMozEmbed *embed);
+  void (* new_window)          (GtkMozEmbed *embed, GtkMozEmbed **newEmbed,
+                                guint chromemask);
+  void (* visibility)          (GtkMozEmbed *embed, gboolean visibility);
+  void (* destroy_brsr)        (GtkMozEmbed *embed);
+  gint (* open_uri)            (GtkMozEmbed *embed, const char *aURI);
+  void (* size_to)             (GtkMozEmbed *embed, gint width, gint height);
+  gint (* dom_key_down)        (GtkMozEmbed *embed, gpointer dom_event);
+  gint (* dom_key_press)       (GtkMozEmbed *embed, gpointer dom_event);
+  gint (* dom_key_up)          (GtkMozEmbed *embed, gpointer dom_event);
+  gint (* dom_mouse_down)      (GtkMozEmbed *embed, gpointer dom_event);
+  gint (* dom_mouse_up)        (GtkMozEmbed *embed, gpointer dom_event);
+  gint (* dom_mouse_click)     (GtkMozEmbed *embed, gpointer dom_event);
+  gint (* dom_mouse_dbl_click) (GtkMozEmbed *embed, gpointer dom_event);
+  gint (* dom_mouse_over)      (GtkMozEmbed *embed, gpointer dom_event);
+  gint (* dom_mouse_out)       (GtkMozEmbed *embed, gpointer dom_event);
+  void (* security_change)     (GtkMozEmbed *embed, gpointer request,
+                                guint state);
+  void (* status_change)       (GtkMozEmbed *embed, gpointer request,
+                                gint status, gpointer message);
+  gint (* dom_activate)        (GtkMozEmbed *embed, gpointer dom_event);
+  gint (* dom_focus_in)        (GtkMozEmbed *embed, gpointer dom_event);
+  gint (* dom_focus_out)       (GtkMozEmbed *embed, gpointer dom_event);
+};
+
+GTKMOZEMBED_API(GType,      gtk_moz_embed_get_type,        (void))
+GTKMOZEMBED_API(GtkWidget*, gtk_moz_embed_new,             (void))
+GTKMOZEMBED_API(void,       gtk_moz_embed_push_startup,    (void))
+GTKMOZEMBED_API(void,       gtk_moz_embed_pop_startup,     (void))
+
+/* Tell gtkmozembed where the gtkmozembed libs live. If this is not specified,
+   The MOZILLA_FIVE_HOME environment variable is checked. */
+GTKMOZEMBED_API(void,       gtk_moz_embed_set_path,        (const char *aPath))
+
+GTKMOZEMBED_API(void,       gtk_moz_embed_set_comp_path,   (const char *aPath))
+GTKMOZEMBED_API(void,      gtk_moz_embed_set_profile_path, (const char *aDir,
+                                                            const char *aName))
+GTKMOZEMBED_API(void,      gtk_moz_embed_load_url,        (GtkMozEmbed *embed,
+                                                           const char *url))
+GTKMOZEMBED_API(void,      gtk_moz_embed_stop_load,       (GtkMozEmbed *embed))
+GTKMOZEMBED_API(gboolean,  gtk_moz_embed_can_go_back,     (GtkMozEmbed *embed))
+GTKMOZEMBED_API(gboolean,  gtk_moz_embed_can_go_forward,  (GtkMozEmbed *embed))
+GTKMOZEMBED_API(void,      gtk_moz_embed_go_back,         (GtkMozEmbed *embed))
+GTKMOZEMBED_API(void,      gtk_moz_embed_go_forward,      (GtkMozEmbed *embed))
+GTKMOZEMBED_API(void,   gtk_moz_embed_render_data,     (GtkMozEmbed *embed, 
+                                                        const char *data,
+                                                        guint32 len,
+                                                        const char *base_uri, 
+                                                        const char *mime_type))
+GTKMOZEMBED_API(void,   gtk_moz_embed_open_stream,     (GtkMozEmbed *embed,
+                                                        const char *base_uri,
+                                                        const char *mime_type))
+GTKMOZEMBED_API(void,   gtk_moz_embed_append_data,      (GtkMozEmbed *embed,
+                                                         const char *data,
+                                                         guint32 len))
+GTKMOZEMBED_API(void,   gtk_moz_embed_close_stream,     (GtkMozEmbed *embed))
+GTKMOZEMBED_API(char*,  gtk_moz_embed_get_link_message, (GtkMozEmbed *embed))
+GTKMOZEMBED_API(char*,  gtk_moz_embed_get_js_status,    (GtkMozEmbed *embed))
+GTKMOZEMBED_API(char*,  gtk_moz_embed_get_title,        (GtkMozEmbed *embed))
+GTKMOZEMBED_API(char*,  gtk_moz_embed_get_location,     (GtkMozEmbed *embed))
+GTKMOZEMBED_API(void,   gtk_moz_embed_reload,           (GtkMozEmbed *embed,
+                                                         gint32 flags))
+GTKMOZEMBED_API(void,   gtk_moz_embed_set_chrome_mask,  (GtkMozEmbed *embed, 
+                                                         guint32 flags))
+GTKMOZEMBED_API(guint32, gtk_moz_embed_get_chrome_mask, (GtkMozEmbed *embed))
+
+/* These are straight out of nsIWebProgressListener.h */
+
+typedef enum
+{
+  GTK_MOZ_EMBED_FLAG_START = 1,
+  GTK_MOZ_EMBED_FLAG_REDIRECTING = 2,
+  GTK_MOZ_EMBED_FLAG_TRANSFERRING = 4,
+  GTK_MOZ_EMBED_FLAG_NEGOTIATING = 8,
+  GTK_MOZ_EMBED_FLAG_STOP = 16,
+  
+  GTK_MOZ_EMBED_FLAG_IS_REQUEST = 65536,
+  GTK_MOZ_EMBED_FLAG_IS_DOCUMENT = 131072,
+  GTK_MOZ_EMBED_FLAG_IS_NETWORK = 262144,
+  GTK_MOZ_EMBED_FLAG_IS_WINDOW = 524288,
+
+  GTK_MOZ_EMBED_FLAG_RESTORING = 16777216
+} GtkMozEmbedProgressFlags;
+
+/* These are from various networking headers */
+
+typedef enum
+{
+  /* NS_ERROR_UNKNOWN_HOST */
+  GTK_MOZ_EMBED_STATUS_FAILED_DNS     = 2152398878U,
+ /* NS_ERROR_CONNECTION_REFUSED */
+  GTK_MOZ_EMBED_STATUS_FAILED_CONNECT = 2152398861U,
+ /* NS_ERROR_NET_TIMEOUT */
+  GTK_MOZ_EMBED_STATUS_FAILED_TIMEOUT = 2152398862U,
+ /* NS_BINDING_ABORTED */
+  GTK_MOZ_EMBED_STATUS_FAILED_USERCANCELED = 2152398850U
+} GtkMozEmbedStatusFlags;
+
+/* These used to be straight out of nsIWebNavigation.h until the API
+   changed.  Now there's a mapping table that maps these values to the
+   internal values. */
+
+typedef enum 
+{
+  GTK_MOZ_EMBED_FLAG_RELOADNORMAL = 0,
+  GTK_MOZ_EMBED_FLAG_RELOADBYPASSCACHE = 1,
+  GTK_MOZ_EMBED_FLAG_RELOADBYPASSPROXY = 2,
+  GTK_MOZ_EMBED_FLAG_RELOADBYPASSPROXYANDCACHE = 3,
+  GTK_MOZ_EMBED_FLAG_RELOADCHARSETCHANGE = 4
+} GtkMozEmbedReloadFlags;
+
+/* These are straight out of nsIWebBrowserChrome.h */
+
+typedef enum
+{
+  GTK_MOZ_EMBED_FLAG_DEFAULTCHROME = 1U,
+  GTK_MOZ_EMBED_FLAG_WINDOWBORDERSON = 2U,
+  GTK_MOZ_EMBED_FLAG_WINDOWCLOSEON = 4U,
+  GTK_MOZ_EMBED_FLAG_WINDOWRESIZEON = 8U,
+  GTK_MOZ_EMBED_FLAG_MENUBARON = 16U,
+  GTK_MOZ_EMBED_FLAG_TOOLBARON = 32U,
+  GTK_MOZ_EMBED_FLAG_LOCATIONBARON = 64U,
+  GTK_MOZ_EMBED_FLAG_STATUSBARON = 128U,
+  GTK_MOZ_EMBED_FLAG_PERSONALTOOLBARON = 256U,
+  GTK_MOZ_EMBED_FLAG_SCROLLBARSON = 512U,
+  GTK_MOZ_EMBED_FLAG_TITLEBARON = 1024U,
+  GTK_MOZ_EMBED_FLAG_EXTRACHROMEON = 2048U,
+  GTK_MOZ_EMBED_FLAG_ALLCHROME = 4094U,
+  GTK_MOZ_EMBED_FLAG_WINDOWRAISED = 33554432U,
+  GTK_MOZ_EMBED_FLAG_WINDOWLOWERED = 67108864U,
+  GTK_MOZ_EMBED_FLAG_CENTERSCREEN = 134217728U,
+  GTK_MOZ_EMBED_FLAG_DEPENDENT = 268435456U,
+  GTK_MOZ_EMBED_FLAG_MODAL = 536870912U,
+  GTK_MOZ_EMBED_FLAG_OPENASDIALOG = 1073741824U,
+  GTK_MOZ_EMBED_FLAG_OPENASCHROME = 2147483648U 
+} GtkMozEmbedChromeFlags;
+
+/* this is a singleton object that you can hook up to to get signals
+   that are not handed out on a per widget basis. */
+
+#define GTK_TYPE_MOZ_EMBED_SINGLE            (gtk_moz_embed_single_get_type())
+#define GTK_MOZ_EMBED_SINGLE(obj)            GTK_CHECK_CAST((obj), GTK_TYPE_MOZ_EMBED_SINGLE, GtkMozEmbedSingle)
+#define GTK_MOZ_EMBED_SINGLE_CLASS(klass)    GTK_CHEK_CLASS_CAST((klass), GTK_TYPE_MOZ_EMBED_SINGLE, GtkMozEmbedSingleClass)
+#define GTK_IS_MOZ_EMBED_SINGLE(obj)         GTK_CHECK_TYPE((obj), GTK_TYPE_MOZ_EMBED_SINGLE)
+#define GTK_IS_MOZ_EMBED_SINGLE_CLASS(klass) GTK_CHECK_CLASS_TYPE((klass), GTK_TYPE_MOZ_EMBED)
+#define GTK_MOZ_EMBED_SINGLE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_MOZ_EMBED_SINGLE, GtkMozEmbedSingleClass))
+
+typedef struct _GtkMozEmbedSingle      GtkMozEmbedSingle;
+typedef struct _GtkMozEmbedSingleClass GtkMozEmbedSingleClass;
+
+struct _GtkMozEmbedSingle
+{
+  GtkObject  object;
+  void      *data;
+};
+
+struct _GtkMozEmbedSingleClass
+{
+  GtkObjectClass parent_class;
+
+  void (* new_window_orphan)   (GtkMozEmbedSingle *embed,
+                                GtkMozEmbed **newEmbed,
+                                guint chromemask);
+};
+
+GTKMOZEMBED_API(GType,               gtk_moz_embed_single_get_type, (void))
+GTKMOZEMBED_API(GtkMozEmbedSingle *, gtk_moz_embed_single_get,      (void))
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* gtkmozembed_h */
diff --git a/embedding/browser/gtk/src/gtkmozembed2.cpp b/embedding/browser/gtk/src/gtkmozembed2.cpp
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/gtkmozembed2.cpp
@@ -0,0 +1,1132 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard. Portions created by Christopher Blizzard are Copyright (C) Christopher Blizzard.  All Rights Reserved.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *   Ramiro Estrugo <ramiro@eazel.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdio.h>
+
+#include "gtkmozembed.h"
+#include "gtkmozembedprivate.h"
+#include "gtkmozembed_internal.h"
+
+#include "EmbedPrivate.h"
+#include "EmbedWindow.h"
+
+// so we can do our get_nsIWebBrowser later...
+#include "nsIWebBrowser.h"
+
+#include "gtkmozembedmarshal.h"
+
+#define NEW_TOOLKIT_STRING(x) g_strdup(NS_ConvertUTF16toUTF8(x).get())
+#define GET_OBJECT_CLASS_TYPE(x) G_OBJECT_CLASS_TYPE(x)
+
+class nsIDirectoryServiceProvider;
+
+// class and instance initialization
+
+static void
+gtk_moz_embed_class_init(GtkMozEmbedClass *klass);
+
+static void
+gtk_moz_embed_init(GtkMozEmbed *embed);
+
+// GtkObject methods
+
+static void
+gtk_moz_embed_destroy(GtkObject *object);
+
+// GtkWidget methods
+
+static void
+gtk_moz_embed_realize(GtkWidget *widget);
+
+static void
+gtk_moz_embed_unrealize(GtkWidget *widget);
+
+static void
+gtk_moz_embed_size_allocate(GtkWidget *widget, GtkAllocation *allocation);
+
+static void
+gtk_moz_embed_map(GtkWidget *widget);
+
+static void
+gtk_moz_embed_unmap(GtkWidget *widget);
+
+#ifdef MOZ_ACCESSIBILITY_ATK
+static AtkObject* gtk_moz_embed_get_accessible (GtkWidget *widget);
+#endif
+
+static gint
+handle_child_focus_in(GtkWidget     *aWidget,
+		      GdkEventFocus *aGdkFocusEvent,
+		      GtkMozEmbed   *aEmbed);
+
+static gint
+handle_child_focus_out(GtkWidget     *aWidget,
+		       GdkEventFocus *aGdkFocusEvent,
+		       GtkMozEmbed   *aEmbed);
+
+// globals for this type of widget
+
+static GtkBinClass *embed_parent_class;
+
+guint moz_embed_signals[EMBED_LAST_SIGNAL] = { 0 };
+
+// GtkObject + class-related functions
+
+GType
+gtk_moz_embed_get_type(void)
+{
+  static GType moz_embed_type = 0;
+  if (moz_embed_type == 0)
+  {
+    const GTypeInfo our_info =
+    {
+      sizeof(GtkMozEmbedClass),
+      NULL, /* base_init */
+      NULL, /* base_finalize */
+      (GClassInitFunc)gtk_moz_embed_class_init,
+      NULL,
+      NULL, /* class_data */
+      sizeof(GtkMozEmbed),
+      0, /* n_preallocs */
+      (GInstanceInitFunc)gtk_moz_embed_init,
+    };
+
+    moz_embed_type = g_type_register_static(GTK_TYPE_BIN,
+                                            "GtkMozEmbed",
+                                            &our_info,
+                                            (GTypeFlags)0);
+  }
+
+  return moz_embed_type;
+}
+
+static void
+gtk_moz_embed_class_init(GtkMozEmbedClass *klass)
+{
+  GtkContainerClass  *container_class;
+  GtkWidgetClass     *widget_class;
+  GtkObjectClass     *object_class;
+
+  container_class = GTK_CONTAINER_CLASS(klass);
+  widget_class    = GTK_WIDGET_CLASS(klass);
+  object_class    = GTK_OBJECT_CLASS(klass);
+
+  embed_parent_class = (GtkBinClass *)g_type_class_peek(gtk_bin_get_type());
+
+  widget_class->realize = gtk_moz_embed_realize;
+  widget_class->unrealize = gtk_moz_embed_unrealize;
+  widget_class->size_allocate = gtk_moz_embed_size_allocate;
+  widget_class->map = gtk_moz_embed_map;
+  widget_class->unmap = gtk_moz_embed_unmap;
+
+#ifdef MOZ_ACCESSIBILITY_ATK
+  widget_class->get_accessible = gtk_moz_embed_get_accessible;
+#endif
+
+  object_class->destroy = gtk_moz_embed_destroy;
+
+  // set up our signals
+
+  moz_embed_signals[LINK_MESSAGE] =
+    g_signal_new("link_message",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_FIRST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, link_message),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__VOID,
+                 G_TYPE_NONE, 0);
+  moz_embed_signals[JS_STATUS] =
+    g_signal_new("js_status",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_FIRST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, js_status),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__VOID,
+                 G_TYPE_NONE, 0);
+  moz_embed_signals[LOCATION] =
+    g_signal_new("location",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_FIRST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, location),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__VOID,
+                 G_TYPE_NONE, 0);
+  moz_embed_signals[TITLE] =
+    g_signal_new("title",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_FIRST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, title),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__VOID,
+                 G_TYPE_NONE, 0);
+  moz_embed_signals[PROGRESS] =
+    g_signal_new("progress",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_FIRST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, progress),
+                 NULL, NULL,
+                 gtkmozembed_VOID__INT_INT,
+                 G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
+  moz_embed_signals[PROGRESS_ALL] =
+    g_signal_new("progress_all",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_FIRST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, progress_all),
+                 NULL, NULL,
+                 gtkmozembed_VOID__STRING_INT_INT,
+                 G_TYPE_NONE, 3,
+                 G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE,
+                 G_TYPE_INT, G_TYPE_INT);
+  moz_embed_signals[NET_STATE] =
+    g_signal_new("net_state",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_FIRST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, net_state),
+                 NULL, NULL,
+                 gtkmozembed_VOID__INT_UINT,
+                 G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_UINT);
+  moz_embed_signals[NET_STATE_ALL] =
+    g_signal_new("net_state_all",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_FIRST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, net_state_all),
+                 NULL, NULL,
+                 gtkmozembed_VOID__STRING_INT_UINT,
+                 G_TYPE_NONE, 3,
+                 G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE,
+                 G_TYPE_INT, G_TYPE_UINT);
+  moz_embed_signals[NET_START] =
+    g_signal_new("net_start",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_FIRST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, net_start),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__VOID,
+                 G_TYPE_NONE, 0);
+  moz_embed_signals[NET_STOP] =
+    g_signal_new("net_stop",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_FIRST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, net_stop),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__VOID,
+                 G_TYPE_NONE, 0);
+  moz_embed_signals[NEW_WINDOW] =
+    g_signal_new("new_window",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_FIRST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, new_window),
+                 NULL, NULL,
+                 gtkmozembed_VOID__POINTER_UINT,
+                 G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT);
+  moz_embed_signals[VISIBILITY] =
+    g_signal_new("visibility",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_FIRST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, visibility),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__BOOLEAN,
+                 G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+  moz_embed_signals[DESTROY_BROWSER] =
+    g_signal_new("destroy_browser",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_FIRST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, destroy_brsr),
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__VOID,
+                 G_TYPE_NONE, 0);
+  moz_embed_signals[OPEN_URI] =
+    g_signal_new("open_uri",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, open_uri),
+                 NULL, NULL,
+                 gtkmozembed_BOOL__STRING,
+                 G_TYPE_BOOLEAN, 1, G_TYPE_STRING |
+                 G_SIGNAL_TYPE_STATIC_SCOPE);
+  moz_embed_signals[SIZE_TO] =
+    g_signal_new("size_to",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, size_to),
+                 NULL, NULL,
+                 gtkmozembed_VOID__INT_INT,
+                 G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
+  moz_embed_signals[DOM_KEY_DOWN] =
+    g_signal_new("dom_key_down",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, dom_key_down),
+                 NULL, NULL,
+                 gtkmozembed_BOOL__POINTER,
+                 G_TYPE_BOOLEAN, 1, G_TYPE_POINTER);
+  moz_embed_signals[DOM_KEY_PRESS] =
+    g_signal_new("dom_key_press",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, dom_key_press),
+                 NULL, NULL,
+                 gtkmozembed_BOOL__POINTER,
+                 G_TYPE_BOOLEAN, 1, G_TYPE_POINTER);
+  moz_embed_signals[DOM_KEY_UP] =
+    g_signal_new("dom_key_up",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, dom_key_up),
+                 NULL, NULL,
+                 gtkmozembed_BOOL__POINTER,
+                 G_TYPE_BOOLEAN, 1, G_TYPE_POINTER);
+  moz_embed_signals[DOM_MOUSE_DOWN] =
+    g_signal_new("dom_mouse_down",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, dom_mouse_down),
+                 NULL, NULL,
+                 gtkmozembed_BOOL__POINTER,
+                 G_TYPE_BOOLEAN, 1, G_TYPE_POINTER);
+  moz_embed_signals[DOM_MOUSE_UP] =
+    g_signal_new("dom_mouse_up",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, dom_mouse_up),
+                 NULL, NULL,
+                 gtkmozembed_BOOL__POINTER,
+                 G_TYPE_BOOLEAN, 1, G_TYPE_POINTER);
+  moz_embed_signals[DOM_MOUSE_CLICK] =
+    g_signal_new("dom_mouse_click",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, dom_mouse_click),
+                 NULL, NULL,
+                 gtkmozembed_BOOL__POINTER,
+                 G_TYPE_BOOLEAN, 1, G_TYPE_POINTER);
+  moz_embed_signals[DOM_MOUSE_DBL_CLICK] =
+    g_signal_new("dom_mouse_dbl_click",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, dom_mouse_dbl_click),
+                 NULL, NULL,
+                 gtkmozembed_BOOL__POINTER,
+                 G_TYPE_BOOLEAN, 1, G_TYPE_POINTER);
+  moz_embed_signals[DOM_MOUSE_OVER] =
+    g_signal_new("dom_mouse_over",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, dom_mouse_over),
+                 NULL, NULL,
+                 gtkmozembed_BOOL__POINTER,
+                 G_TYPE_BOOLEAN, 1, G_TYPE_POINTER);
+  moz_embed_signals[DOM_MOUSE_OUT] =
+    g_signal_new("dom_mouse_out",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, dom_mouse_out),
+                 NULL, NULL,
+                 gtkmozembed_BOOL__POINTER,
+                 G_TYPE_BOOLEAN, 1, G_TYPE_POINTER);
+  moz_embed_signals[SECURITY_CHANGE] =
+    g_signal_new("security_change",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, security_change),
+                 NULL, NULL,
+                 gtkmozembed_VOID__POINTER_UINT,
+                 G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT);
+  moz_embed_signals[STATUS_CHANGE] =
+    g_signal_new("status_change",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, status_change),
+                 NULL, NULL,
+                 gtkmozembed_VOID__POINTER_INT_POINTER,
+                 G_TYPE_NONE, 3,
+                 G_TYPE_POINTER, G_TYPE_INT, G_TYPE_POINTER);
+  moz_embed_signals[DOM_ACTIVATE] =
+    g_signal_new("dom_activate",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, dom_activate),
+                 NULL, NULL,
+                 gtkmozembed_BOOL__POINTER,
+                 G_TYPE_BOOLEAN, 1, G_TYPE_POINTER);
+  moz_embed_signals[DOM_FOCUS_IN] =
+    g_signal_new("dom_focus_in",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, dom_focus_in),
+                 NULL, NULL,
+                 gtkmozembed_BOOL__POINTER,
+                 G_TYPE_BOOLEAN, 1, G_TYPE_POINTER);
+  moz_embed_signals[DOM_FOCUS_OUT] =
+    g_signal_new("dom_focus_out",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET(GtkMozEmbedClass, dom_focus_out),
+                 NULL, NULL,
+                 gtkmozembed_BOOL__POINTER,
+                 G_TYPE_BOOLEAN, 1, G_TYPE_POINTER);
+}
+
+static void
+gtk_moz_embed_init(GtkMozEmbed *embed)
+{
+  EmbedPrivate *priv = new EmbedPrivate();
+  embed->data = priv;
+  gtk_widget_set_name(GTK_WIDGET(embed), "gtkmozembed");
+
+  GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(embed), GTK_NO_WINDOW);
+}
+
+GtkWidget *
+gtk_moz_embed_new(void)
+{
+  return GTK_WIDGET(g_object_new(GTK_TYPE_MOZ_EMBED, NULL));
+}
+
+// GtkObject methods
+
+static void
+gtk_moz_embed_destroy(GtkObject *object)
+{
+  GtkMozEmbed  *embed;
+  EmbedPrivate *embedPrivate;
+  
+  g_return_if_fail(object != NULL);
+  g_return_if_fail(GTK_IS_MOZ_EMBED(object));
+
+  embed = GTK_MOZ_EMBED(object);
+  embedPrivate = (EmbedPrivate *)embed->data;
+
+  if (embedPrivate) {
+
+    // Destroy the widget only if it's been Init()ed.
+    if(embedPrivate->mMozWindowWidget != 0) {
+      embedPrivate->Destroy();
+    }
+
+    delete embedPrivate;
+    embed->data = NULL;
+  }
+}
+
+// GtkWidget methods
+
+static void
+gtk_moz_embed_realize(GtkWidget *widget)
+{
+  GtkMozEmbed    *embed;
+  EmbedPrivate   *embedPrivate;
+  GdkWindowAttr   attributes;
+  gint            attributes_mask;
+  
+  g_return_if_fail(widget != NULL);
+  g_return_if_fail(GTK_IS_MOZ_EMBED(widget));
+
+  embed = GTK_MOZ_EMBED(widget);
+  embedPrivate = (EmbedPrivate *)embed->data;
+
+  GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
+
+  attributes.window_type = GDK_WINDOW_CHILD;
+  attributes.x = widget->allocation.x;
+  attributes.y = widget->allocation.y;
+  attributes.width = widget->allocation.width;
+  attributes.height = widget->allocation.height;
+  attributes.wclass = GDK_INPUT_OUTPUT;
+  attributes.visual = gtk_widget_get_visual (widget);
+  attributes.colormap = gtk_widget_get_colormap (widget);
+  attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
+
+  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
+				   &attributes, attributes_mask);
+  gdk_window_set_user_data (widget->window, embed);
+
+  widget->style = gtk_style_attach (widget->style, widget->window);
+  gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+
+  // initialize the window
+  nsresult rv;
+  rv = embedPrivate->Init(embed);
+  g_return_if_fail(NS_SUCCEEDED(rv));
+  
+  PRBool alreadyRealized = PR_FALSE;
+  rv = embedPrivate->Realize(&alreadyRealized);
+  g_return_if_fail(NS_SUCCEEDED(rv));
+
+  // if we're already realized we don't need to hook up to anything below
+  if (alreadyRealized)
+    return;
+
+  if (embedPrivate->mURI.Length())
+    embedPrivate->LoadCurrentURI();
+
+  // connect to the focus out event for the child
+  GtkWidget *child_widget = GTK_BIN(widget)->child;
+  g_signal_connect_object(G_OBJECT(child_widget),
+                          "focus_out_event",
+                          G_CALLBACK(handle_child_focus_out),
+                          embed,
+                          G_CONNECT_AFTER);
+  g_signal_connect_object(G_OBJECT(child_widget),
+                          "focus_in_event",
+                          G_CALLBACK(handle_child_focus_in),
+                          embed,
+                          G_CONNECT_AFTER);
+}
+
+static void
+gtk_moz_embed_unrealize(GtkWidget *widget)
+{
+  GtkMozEmbed  *embed;
+  EmbedPrivate *embedPrivate;
+  
+  g_return_if_fail(widget != NULL);
+  g_return_if_fail(GTK_IS_MOZ_EMBED(widget));
+
+  embed = GTK_MOZ_EMBED(widget);
+  embedPrivate = (EmbedPrivate *)embed->data;
+
+  if (embedPrivate) {
+    embedPrivate->Unrealize();
+  }
+
+  if (GTK_WIDGET_CLASS(embed_parent_class)->unrealize)
+    (* GTK_WIDGET_CLASS(embed_parent_class)->unrealize)(widget);
+}
+
+static void
+gtk_moz_embed_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
+{
+  GtkMozEmbed  *embed;
+  EmbedPrivate *embedPrivate;
+  
+  g_return_if_fail(widget != NULL);
+  g_return_if_fail(GTK_IS_MOZ_EMBED(widget));
+
+  embed = GTK_MOZ_EMBED(widget);
+  embedPrivate = (EmbedPrivate *)embed->data;
+  
+  widget->allocation = *allocation;
+
+  if (GTK_WIDGET_REALIZED(widget))
+  {
+    gdk_window_move_resize(widget->window,
+			   allocation->x, allocation->y,
+			   allocation->width, allocation->height);
+    embedPrivate->Resize(allocation->width, allocation->height);
+  }
+}
+
+static void
+gtk_moz_embed_map(GtkWidget *widget)
+{
+  GtkMozEmbed  *embed;
+  EmbedPrivate *embedPrivate;
+  
+  g_return_if_fail(widget != NULL);
+  g_return_if_fail(GTK_IS_MOZ_EMBED(widget));
+
+  embed = GTK_MOZ_EMBED(widget);
+  embedPrivate = (EmbedPrivate *)embed->data;
+
+  GTK_WIDGET_SET_FLAGS(widget, GTK_MAPPED);
+
+  embedPrivate->Show();
+
+  gdk_window_show(widget->window);
+  
+}
+
+static void
+gtk_moz_embed_unmap(GtkWidget *widget)
+{
+  GtkMozEmbed  *embed;
+  EmbedPrivate *embedPrivate;
+  
+  g_return_if_fail(widget != NULL);
+  g_return_if_fail(GTK_IS_MOZ_EMBED(widget));
+
+  embed = GTK_MOZ_EMBED(widget);
+  embedPrivate = (EmbedPrivate *)embed->data;
+
+  GTK_WIDGET_UNSET_FLAGS(widget, GTK_MAPPED);
+
+  gdk_window_hide(widget->window);
+
+  embedPrivate->Hide();
+}
+
+#ifdef MOZ_ACCESSIBILITY_ATK
+static AtkObject*
+gtk_moz_embed_get_accessible (GtkWidget *widget)
+{
+  g_return_val_if_fail(widget != NULL, NULL);
+  g_return_val_if_fail(GTK_IS_MOZ_EMBED(widget), NULL);
+
+  GtkMozEmbed  *embed = GTK_MOZ_EMBED(widget);;
+  EmbedPrivate *embedPrivate = (EmbedPrivate *)embed->data;
+  return static_cast<AtkObject *>(
+                        embedPrivate->GetAtkObjectForCurrentDocument());
+}
+#endif /* MOZ_ACCESSIBILITY_ATK */
+
+static gint
+handle_child_focus_in(GtkWidget     *aWidget,
+		      GdkEventFocus *aGdkFocusEvent,
+		      GtkMozEmbed   *aEmbed)
+{
+  EmbedPrivate *embedPrivate;
+
+  embedPrivate = (EmbedPrivate *)aEmbed->data;
+
+  embedPrivate->ChildFocusIn();
+
+  return FALSE;
+}
+
+static gint
+handle_child_focus_out(GtkWidget     *aWidget,
+		       GdkEventFocus *aGdkFocusEvent,
+		       GtkMozEmbed   *aEmbed)
+{
+  EmbedPrivate *embedPrivate;
+
+  embedPrivate = (EmbedPrivate *)aEmbed->data;
+
+  embedPrivate->ChildFocusOut();
+ 
+  return FALSE;
+}
+
+// Widget methods
+
+void
+gtk_moz_embed_push_startup(void)
+{
+  EmbedPrivate::PushStartup();
+}
+
+void
+gtk_moz_embed_pop_startup(void)
+{
+  EmbedPrivate::PopStartup();
+}
+
+void
+gtk_moz_embed_set_path(const char *aPath)
+{
+  EmbedPrivate::SetPath(aPath);
+}
+
+void
+gtk_moz_embed_set_comp_path(const char *aPath)
+{
+  EmbedPrivate::SetCompPath(aPath);
+}
+
+void
+gtk_moz_embed_set_profile_path(const char *aDir, const char *aName)
+{
+  EmbedPrivate::SetProfilePath(aDir, aName);
+}
+
+void
+gtk_moz_embed_set_directory_service_provider(nsIDirectoryServiceProvider *appFileLocProvider) {
+  EmbedPrivate::SetDirectoryServiceProvider(appFileLocProvider);
+}
+
+void
+gtk_moz_embed_load_url(GtkMozEmbed *embed, const char *url)
+{
+  EmbedPrivate *embedPrivate;
+  
+  g_return_if_fail(embed != NULL);
+  g_return_if_fail(GTK_IS_MOZ_EMBED(embed));
+
+  embedPrivate = (EmbedPrivate *)embed->data;
+
+  embedPrivate->SetURI(url);
+
+  // If the widget is realized, load the URI.  If it isn't then we
+  // will load it later.
+  if (GTK_WIDGET_REALIZED(embed))
+    embedPrivate->LoadCurrentURI();
+}
+
+void
+gtk_moz_embed_stop_load(GtkMozEmbed *embed)
+{
+  EmbedPrivate *embedPrivate;
+  
+  g_return_if_fail(embed != NULL);
+  g_return_if_fail(GTK_IS_MOZ_EMBED(embed));
+
+  embedPrivate = (EmbedPrivate *)embed->data;
+
+  if (embedPrivate->mNavigation)
+    embedPrivate->mNavigation->Stop(nsIWebNavigation::STOP_ALL);
+}
+
+gboolean
+gtk_moz_embed_can_go_back(GtkMozEmbed *embed)
+{
+  PRBool retval = PR_FALSE;
+  EmbedPrivate *embedPrivate;
+
+  g_return_val_if_fail ((embed != NULL), FALSE);
+  g_return_val_if_fail (GTK_IS_MOZ_EMBED(embed), FALSE);
+
+  embedPrivate = (EmbedPrivate *)embed->data;
+
+  if (embedPrivate->mNavigation)
+    embedPrivate->mNavigation->GetCanGoBack(&retval);
+  return retval;
+}
+
+gboolean
+gtk_moz_embed_can_go_forward(GtkMozEmbed *embed)
+{
+  PRBool retval = PR_FALSE;
+  EmbedPrivate *embedPrivate;
+
+  g_return_val_if_fail ((embed != NULL), FALSE);
+  g_return_val_if_fail (GTK_IS_MOZ_EMBED(embed), FALSE);
+
+  embedPrivate = (EmbedPrivate *)embed->data;
+
+  if (embedPrivate->mNavigation)
+    embedPrivate->mNavigation->GetCanGoForward(&retval);
+  return retval;
+}
+
+void
+gtk_moz_embed_go_back(GtkMozEmbed *embed)
+{
+  EmbedPrivate *embedPrivate;
+
+  g_return_if_fail (embed != NULL);
+  g_return_if_fail (GTK_IS_MOZ_EMBED(embed));
+
+  embedPrivate = (EmbedPrivate *)embed->data;
+
+  if (embedPrivate->mNavigation)
+    embedPrivate->mNavigation->GoBack();
+}
+
+void
+gtk_moz_embed_go_forward(GtkMozEmbed *embed)
+{
+  EmbedPrivate *embedPrivate;
+
+  g_return_if_fail (embed != NULL);
+  g_return_if_fail (GTK_IS_MOZ_EMBED(embed));
+
+  embedPrivate = (EmbedPrivate *)embed->data;
+
+  if (embedPrivate->mNavigation)
+    embedPrivate->mNavigation->GoForward();
+}
+
+void
+gtk_moz_embed_render_data(GtkMozEmbed *embed, const char *data,
+			  guint32 len, const char *base_uri,
+			  const char *mime_type)
+{
+  EmbedPrivate *embedPrivate;
+
+  g_return_if_fail (embed != NULL);
+  g_return_if_fail (GTK_IS_MOZ_EMBED(embed));
+
+  embedPrivate = (EmbedPrivate *)embed->data;
+
+  embedPrivate->OpenStream(base_uri, mime_type);
+  embedPrivate->AppendToStream((const PRUint8*)data, len);
+  embedPrivate->CloseStream();
+}
+
+void
+gtk_moz_embed_open_stream(GtkMozEmbed *embed, const char *base_uri,
+			  const char *mime_type)
+{
+  EmbedPrivate *embedPrivate;
+
+  g_return_if_fail (embed != NULL);
+  g_return_if_fail (GTK_IS_MOZ_EMBED(embed));
+  g_return_if_fail (GTK_WIDGET_REALIZED(GTK_WIDGET(embed)));
+
+  embedPrivate = (EmbedPrivate *)embed->data;
+
+  embedPrivate->OpenStream(base_uri, mime_type);
+}
+
+void gtk_moz_embed_append_data(GtkMozEmbed *embed, const char *data,
+			       guint32 len)
+{
+  EmbedPrivate *embedPrivate;
+
+  g_return_if_fail (embed != NULL);
+  g_return_if_fail (GTK_IS_MOZ_EMBED(embed));
+  g_return_if_fail (GTK_WIDGET_REALIZED(GTK_WIDGET(embed)));
+
+  embedPrivate = (EmbedPrivate *)embed->data;
+  embedPrivate->AppendToStream((const PRUint8*)data, len);
+}
+
+void
+gtk_moz_embed_close_stream(GtkMozEmbed *embed)
+{
+  EmbedPrivate *embedPrivate;
+
+  g_return_if_fail (embed != NULL);
+  g_return_if_fail (GTK_IS_MOZ_EMBED(embed));
+  g_return_if_fail (GTK_WIDGET_REALIZED(GTK_WIDGET(embed)));
+
+  embedPrivate = (EmbedPrivate *)embed->data;
+  embedPrivate->CloseStream();
+}
+
+char *
+gtk_moz_embed_get_link_message(GtkMozEmbed *embed)
+{
+  char *retval = nsnull;
+  EmbedPrivate *embedPrivate;
+
+  g_return_val_if_fail ((embed != NULL), (char *)NULL);
+  g_return_val_if_fail (GTK_IS_MOZ_EMBED(embed), (char *)NULL);
+
+  embedPrivate = (EmbedPrivate *)embed->data;
+
+  if (embedPrivate->mWindow)
+    retval = NEW_TOOLKIT_STRING(embedPrivate->mWindow->mLinkMessage);
+
+  return retval;
+}
+
+char *
+gtk_moz_embed_get_js_status(GtkMozEmbed *embed)
+{
+  char *retval = nsnull;
+  EmbedPrivate *embedPrivate;
+
+  g_return_val_if_fail ((embed != NULL), (char *)NULL);
+  g_return_val_if_fail (GTK_IS_MOZ_EMBED(embed), (char *)NULL);
+
+  embedPrivate = (EmbedPrivate *)embed->data;
+
+  if (embedPrivate->mWindow)
+    retval = NEW_TOOLKIT_STRING(embedPrivate->mWindow->mJSStatus);
+
+  return retval;
+}
+
+char *
+gtk_moz_embed_get_title(GtkMozEmbed *embed)
+{
+  char *retval = nsnull;
+  EmbedPrivate *embedPrivate;
+
+  g_return_val_if_fail ((embed != NULL), (char *)NULL);
+  g_return_val_if_fail (GTK_IS_MOZ_EMBED(embed), (char *)NULL);
+
+  embedPrivate = (EmbedPrivate *)embed->data;
+
+  if (embedPrivate->mWindow)
+    retval = NEW_TOOLKIT_STRING(embedPrivate->mWindow->mTitle);
+
+  return retval;
+}
+
+char *
+gtk_moz_embed_get_location(GtkMozEmbed *embed)
+{
+  char *retval = nsnull;
+  EmbedPrivate *embedPrivate;
+
+  g_return_val_if_fail ((embed != NULL), (char *)NULL);
+  g_return_val_if_fail (GTK_IS_MOZ_EMBED(embed), (char *)NULL);
+
+  embedPrivate = (EmbedPrivate *)embed->data;
+  
+  if (!embedPrivate->mURI.IsEmpty())
+    retval = g_strdup(embedPrivate->mURI.get());
+
+  return retval;
+}
+
+void
+gtk_moz_embed_reload(GtkMozEmbed *embed, gint32 flags)
+{
+  EmbedPrivate *embedPrivate;
+
+  g_return_if_fail (embed != NULL);
+  g_return_if_fail (GTK_IS_MOZ_EMBED(embed));
+
+  embedPrivate = (EmbedPrivate *)embed->data;
+
+  PRUint32 reloadFlags = 0;
+  
+  // map the external API to the internal web navigation API.
+  switch (flags) {
+  case GTK_MOZ_EMBED_FLAG_RELOADNORMAL:
+    reloadFlags = 0;
+    break;
+  case GTK_MOZ_EMBED_FLAG_RELOADBYPASSCACHE:
+    reloadFlags = nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE;
+    break;
+  case GTK_MOZ_EMBED_FLAG_RELOADBYPASSPROXY:
+    reloadFlags = nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY;
+    break;
+  case GTK_MOZ_EMBED_FLAG_RELOADBYPASSPROXYANDCACHE:
+    reloadFlags = (nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY |
+		   nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE);
+    break;
+  case GTK_MOZ_EMBED_FLAG_RELOADCHARSETCHANGE:
+    reloadFlags = nsIWebNavigation::LOAD_FLAGS_CHARSET_CHANGE;
+    break;
+  default:
+    reloadFlags = 0;
+    break;
+  }
+
+  embedPrivate->Reload(reloadFlags);
+}
+
+void
+gtk_moz_embed_set_chrome_mask(GtkMozEmbed *embed, guint32 flags)
+{
+  EmbedPrivate *embedPrivate;
+
+  g_return_if_fail (embed != NULL);
+  g_return_if_fail (GTK_IS_MOZ_EMBED(embed));
+
+  embedPrivate = (EmbedPrivate *)embed->data;
+
+  embedPrivate->SetChromeMask(flags);
+}
+
+guint32
+gtk_moz_embed_get_chrome_mask(GtkMozEmbed *embed)
+{
+  EmbedPrivate *embedPrivate;
+
+  g_return_val_if_fail ((embed != NULL), 0);
+  g_return_val_if_fail (GTK_IS_MOZ_EMBED(embed), 0);
+
+  embedPrivate = (EmbedPrivate *)embed->data;
+
+  return embedPrivate->mChromeMask;
+}
+
+void
+gtk_moz_embed_get_nsIWebBrowser  (GtkMozEmbed *embed, nsIWebBrowser **retval)
+{
+  EmbedPrivate *embedPrivate;
+
+  g_return_if_fail (embed != NULL);
+  g_return_if_fail (GTK_IS_MOZ_EMBED(embed));
+
+  embedPrivate = (EmbedPrivate *)embed->data;
+  
+  if (embedPrivate->mWindow)
+    embedPrivate->mWindow->GetWebBrowser(retval);
+}
+
+PRUnichar *
+gtk_moz_embed_get_title_unichar (GtkMozEmbed *embed)
+{
+  PRUnichar *retval = nsnull;
+  EmbedPrivate *embedPrivate;
+                   
+  g_return_val_if_fail ((embed != NULL), (PRUnichar *)NULL);
+  g_return_val_if_fail (GTK_IS_MOZ_EMBED(embed), (PRUnichar *)NULL);
+  
+  embedPrivate = (EmbedPrivate *)embed->data;
+                   
+  if (embedPrivate->mWindow)
+    retval = ToNewUnicode(embedPrivate->mWindow->mTitle);
+                   
+  return retval;
+}
+
+PRUnichar *
+gtk_moz_embed_get_js_status_unichar (GtkMozEmbed *embed)
+{
+  PRUnichar *retval = nsnull;
+  EmbedPrivate *embedPrivate;
+                   
+  g_return_val_if_fail ((embed != NULL), (PRUnichar *)NULL);
+  g_return_val_if_fail (GTK_IS_MOZ_EMBED(embed), (PRUnichar *)NULL);
+  
+  embedPrivate = (EmbedPrivate *)embed->data;
+                   
+  if (embedPrivate->mWindow)
+    retval = ToNewUnicode(embedPrivate->mWindow->mJSStatus);
+                   
+  return retval;
+}
+
+PRUnichar *
+gtk_moz_embed_get_link_message_unichar (GtkMozEmbed *embed)
+{
+  PRUnichar *retval = nsnull;
+  EmbedPrivate *embedPrivate;
+                   
+  g_return_val_if_fail ((embed != NULL), (PRUnichar *)NULL);
+  g_return_val_if_fail (GTK_IS_MOZ_EMBED(embed), (PRUnichar *)NULL);
+  
+  embedPrivate = (EmbedPrivate *)embed->data;
+                   
+  if (embedPrivate->mWindow)
+    retval = ToNewUnicode(embedPrivate->mWindow->mLinkMessage);
+                   
+  return retval;
+}
+
+// class and instance initialization
+
+static void
+gtk_moz_embed_single_class_init(GtkMozEmbedSingleClass *klass);
+
+static void
+gtk_moz_embed_single_init(GtkMozEmbedSingle *embed);
+
+GtkMozEmbedSingle *
+gtk_moz_embed_single_new(void);
+
+enum {
+  NEW_WINDOW_ORPHAN,
+  SINGLE_LAST_SIGNAL
+};
+
+guint moz_embed_single_signals[SINGLE_LAST_SIGNAL] = { 0 };
+
+// GtkObject + class-related functions
+
+GType
+gtk_moz_embed_single_get_type(void)
+{
+  static GType moz_embed_single_type = 0;
+  if (moz_embed_single_type == 0)
+  {
+    const GTypeInfo our_info =
+    {
+      sizeof(GtkMozEmbedClass),
+      NULL, /* base_init */
+      NULL, /* base_finalize */
+      (GClassInitFunc)gtk_moz_embed_single_class_init,
+      NULL,
+      NULL, /* class_data */
+      sizeof(GtkMozEmbed),
+      0, /* n_preallocs */
+      (GInstanceInitFunc)gtk_moz_embed_single_init,
+    };
+
+    moz_embed_single_type = g_type_register_static(GTK_TYPE_OBJECT,
+                                                   "GtkMozEmbedSingle",
+                                                   &our_info,
+                                                   (GTypeFlags)0);
+  }
+
+  return moz_embed_single_type;
+}
+
+static void
+gtk_moz_embed_single_class_init(GtkMozEmbedSingleClass *klass)
+{
+  GtkObjectClass     *object_class;
+
+  object_class    = GTK_OBJECT_CLASS(klass);
+
+  // set up our signals
+
+  moz_embed_single_signals[NEW_WINDOW_ORPHAN] =
+    g_signal_new("new_window_orphan",
+                 G_TYPE_FROM_CLASS(klass),
+                 G_SIGNAL_RUN_FIRST,
+                 G_STRUCT_OFFSET(GtkMozEmbedSingleClass, new_window_orphan),
+                 NULL, NULL,
+                 gtkmozembed_VOID__POINTER_UINT,
+                 G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT);
+
+}
+
+static void
+gtk_moz_embed_single_init(GtkMozEmbedSingle *embed)
+{
+  // this is a placeholder for later in case we need to stash data at
+  // a later data and maintain backwards compatibility.
+  embed->data = nsnull;
+}
+
+GtkMozEmbedSingle *
+gtk_moz_embed_single_new(void)
+{
+  return (GtkMozEmbedSingle *)g_object_new(GTK_TYPE_MOZ_EMBED_SINGLE, NULL);
+}
+
+GtkMozEmbedSingle *
+gtk_moz_embed_single_get(void)
+{
+  static GtkMozEmbedSingle *singleton_object = nsnull;
+  if (!singleton_object)
+  {
+    singleton_object = gtk_moz_embed_single_new();
+  }
+
+  return singleton_object;
+}
+
+// our callback from the window creator service
+void
+gtk_moz_embed_single_create_window(GtkMozEmbed **aNewEmbed,
+				   guint         aChromeFlags)
+{
+  GtkMozEmbedSingle *single = gtk_moz_embed_single_get();
+
+  *aNewEmbed = nsnull;
+
+  if (!single)
+    return;
+
+  g_signal_emit(G_OBJECT(single),
+                moz_embed_single_signals[NEW_WINDOW_ORPHAN], 0,
+                aNewEmbed, aChromeFlags);
+
+}
diff --git a/embedding/browser/gtk/src/gtkmozembed_glue.cpp b/embedding/browser/gtk/src/gtkmozembed_glue.cpp
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/gtkmozembed_glue.cpp
@@ -0,0 +1,116 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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 embedding.
+ *
+ * The Initial Developer of the Original Code is
+ * Benjamin Smedberg <benjamin@smedbergs.us>.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Mozilla Foundation <http://www.mozilla.org/>. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// This file is an implementation file, meant to be #included in a
+// single C++ file of an embedding application. It is called after
+// XPCOMGlueStartup to glue the gtkmozembed functions.
+
+#include "gtkmozembed.h"
+#include "gtkmozembed_internal.h"
+#include "nsXPCOMGlue.h"
+
+#ifndef XPCOM_GLUE
+#error This file only makes sense when XPCOM_GLUE is defined.
+#endif
+
+#define GTKMOZEMBED_FUNCTIONS \
+  GTKF(gtk_moz_embed_get_type) \
+  GTKF(gtk_moz_embed_new) \
+  GTKF(gtk_moz_embed_push_startup) \
+  GTKF(gtk_moz_embed_pop_startup) \
+  GTKF(gtk_moz_embed_set_path) \
+  GTKF(gtk_moz_embed_set_comp_path) \
+  GTKF(gtk_moz_embed_set_profile_path) \
+  GTKF(gtk_moz_embed_load_url) \
+  GTKF(gtk_moz_embed_stop_load) \
+  GTKF(gtk_moz_embed_can_go_back) \
+  GTKF(gtk_moz_embed_can_go_forward) \
+  GTKF(gtk_moz_embed_go_back) \
+  GTKF(gtk_moz_embed_go_forward) \
+  GTKF(gtk_moz_embed_render_data) \
+  GTKF(gtk_moz_embed_open_stream) \
+  GTKF(gtk_moz_embed_append_data) \
+  GTKF(gtk_moz_embed_close_stream) \
+  GTKF(gtk_moz_embed_get_link_message) \
+  GTKF(gtk_moz_embed_get_js_status) \
+  GTKF(gtk_moz_embed_get_title) \
+  GTKF(gtk_moz_embed_get_location) \
+  GTKF(gtk_moz_embed_reload) \
+  GTKF(gtk_moz_embed_set_chrome_mask) \
+  GTKF(gtk_moz_embed_get_chrome_mask) \
+  GTKF(gtk_moz_embed_single_get_type) \
+  GTKF(gtk_moz_embed_single_get)
+
+#define GTKMOZEMBED_FUNCTIONS_INTERNAL \
+  GTKF(gtk_moz_embed_get_nsIWebBrowser) \
+  GTKF(gtk_moz_embed_get_title_unichar) \
+  GTKF(gtk_moz_embed_get_js_status_unichar) \
+  GTKF(gtk_moz_embed_get_link_message_unichar) \
+  GTKF(gtk_moz_embed_set_directory_service_provider)
+
+#define GTKF(fname) fname##Type fname;
+
+GTKMOZEMBED_FUNCTIONS
+GTKMOZEMBED_FUNCTIONS_INTERNAL
+
+#undef GTKF
+
+#define GTKF(fname) { #fname, (NSFuncPtr*) &fname },
+
+static const nsDynamicFunctionLoad GtkSymbols[] = {
+GTKMOZEMBED_FUNCTIONS
+  { nsnull, nsnull }
+};
+
+static const nsDynamicFunctionLoad GtkSymbolsInternal[] = {
+GTKMOZEMBED_FUNCTIONS_INTERNAL
+  { nsnull, nsnull }
+};
+#undef GTKF
+
+static nsresult
+GTKEmbedGlueStartup()
+{
+  return XPCOMGlueLoadXULFunctions(GtkSymbols);
+}
+
+static nsresult
+GTKEmbedGlueStartupInternal()
+{
+  return XPCOMGlueLoadXULFunctions(GtkSymbolsInternal);
+}
+
diff --git a/embedding/browser/gtk/src/gtkmozembed_internal.h b/embedding/browser/gtk/src/gtkmozembed_internal.h
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/gtkmozembed_internal.h
@@ -0,0 +1,70 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef gtkmozembed_internal_h
+#define gtkmozembed_internal_h
+
+#include "nsIWebBrowser.h"
+#include "nsXPCOM.h"
+
+struct nsModuleComponentInfo;
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+GTKMOZEMBED_API(void,
+  gtk_moz_embed_get_nsIWebBrowser, (GtkMozEmbed *embed,
+                                    nsIWebBrowser **retval))
+GTKMOZEMBED_API(PRUnichar*,
+  gtk_moz_embed_get_title_unichar, (GtkMozEmbed *embed))
+
+GTKMOZEMBED_API(PRUnichar*,
+  gtk_moz_embed_get_js_status_unichar, (GtkMozEmbed *embed))
+
+GTKMOZEMBED_API(PRUnichar*,
+  gtk_moz_embed_get_link_message_unichar, (GtkMozEmbed *embed))
+
+GTKMOZEMBED_API(void,
+  gtk_moz_embed_set_directory_service_provider, (nsIDirectoryServiceProvider *appFileLocProvider))
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* gtkmozembed_internal_h */
+
diff --git a/embedding/browser/gtk/src/gtkmozembedmarshal.list b/embedding/browser/gtk/src/gtkmozembedmarshal.list
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/gtkmozembedmarshal.list
@@ -0,0 +1,34 @@
+BOOL:STRING
+BOOL:STRING,STRING
+BOOL:STRING,STRING,POINTER
+BOOL:STRING,STRING,POINTER,INT
+BOOL:STRING,STRING,POINTER,POINTER,STRING,POINTER
+BOOL:STRING,STRING,POINTER,STRING,POINTER
+BOOL:STRING,STRING,STRING,POINTER
+INT:STRING,INT,INT,INT,INT,INT
+INT:STRING,STRING,INT,INT,INT,INT
+INT:STRING,STRING,UINT,STRING,STRING,STRING,STRING,POINTER
+INT:VOID
+STRING:STRING,STRING
+VOID:BOOL
+VOID:INT,INT
+VOID:INT,INT,BOOL
+VOID:INT,STRING
+VOID:INT,STRING,STRING
+VOID:INT,UINT
+VOID:POINTER,INT,POINTER
+VOID:POINTER,INT,STRING,STRING,STRING,STRING,STRING,BOOLEAN,INT
+VOID:POINTER,STRING,BOOL,BOOL
+VOID:STRING,INT,INT
+VOID:STRING,INT,UINT
+VOID:STRING,STRING
+VOID:STRING,STRING,POINTER
+VOID:STRING,STRING,STRING,ULONG,INT
+VOID:STRING,STRING,STRING,POINTER
+VOID:UINT,INT,INT,STRING,STRING,STRING,STRING
+VOID:ULONG,ULONG,ULONG
+VOID:POINTER,UINT
+BOOL:POINTER,UINT
+BOOL:POINTER
+VOID:POINTER
+BOOL:STRING,STRING,POINTER
diff --git a/embedding/browser/gtk/src/gtkmozembedprivate.h b/embedding/browser/gtk/src/gtkmozembedprivate.h
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/src/gtkmozembedprivate.h
@@ -0,0 +1,91 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef gtkmozembedprivate_h
+#define gtkmozembedprivate_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "gtkmozembed.h"
+
+/* signals */
+
+enum {
+  LINK_MESSAGE,
+  JS_STATUS,
+  LOCATION,
+  TITLE,
+  PROGRESS,
+  PROGRESS_ALL,
+  NET_STATE,
+  NET_STATE_ALL,
+  NET_START,
+  NET_STOP,
+  NEW_WINDOW,
+  VISIBILITY,
+  DESTROY_BROWSER,
+  OPEN_URI,
+  SIZE_TO,
+  DOM_KEY_DOWN,
+  DOM_KEY_PRESS,
+  DOM_KEY_UP,
+  DOM_MOUSE_DOWN,
+  DOM_MOUSE_UP,
+  DOM_MOUSE_CLICK,
+  DOM_MOUSE_DBL_CLICK,
+  DOM_MOUSE_OVER,
+  DOM_MOUSE_OUT,
+  SECURITY_CHANGE,
+  STATUS_CHANGE,
+  DOM_ACTIVATE,
+  DOM_FOCUS_IN,
+  DOM_FOCUS_OUT,
+  EMBED_LAST_SIGNAL
+};
+
+extern guint moz_embed_signals[EMBED_LAST_SIGNAL];
+
+extern void gtk_moz_embed_single_create_window(GtkMozEmbed **aNewEmbed,
+					       guint aChromeFlags);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* gtkmozembedprivate_h */
diff --git a/embedding/browser/gtk/tests/Makefile.in b/embedding/browser/gtk/tests/Makefile.in
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/tests/Makefile.in
@@ -0,0 +1,101 @@
+# 
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.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 the Mozilla browser.
+#
+# The Initial Developer of the Original Code is
+# Christopher Blizzard.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Christopher Blizzard <blizzard@mozilla.org>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE		= gtkembedmoz
+
+CPPSRCS         = \
+		TestGtkEmbed.cpp \
+		TestGtkEmbedNotebook.cpp
+
+ifdef MOZ_X11
+CPPSRCS +=	TestGtkEmbedSocket.cpp \
+		TestGtkEmbedChild.cpp
+endif
+
+SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=)
+
+# ENABLE_GNOME=1
+
+ifdef ENABLE_GNOME
+CPPSRCS	       += TestGtkEmbedMDI.cpp
+endif
+
+ifdef MOZ_ENABLE_GTK2
+LIBS		+= \
+		$(XLDFLAGS) \
+		$(XLIBS) \
+		$(NULL)
+endif
+
+include $(topsrcdir)/config/config.mk
+
+include $(topsrcdir)/config/rules.mk
+
+LIBS += $(XPCOM_STANDALONE_GLUE_LDOPTS)
+
+DEFINES += -DXPCOM_GLUE
+STL_FLAGS =
+
+CXXFLAGS	+= $(MOZ_GTK2_CFLAGS)
+
+ifdef ENABLE_GNOME
+CXXFLAGS	+= `gnome-config --cflags gnomeui`
+EXTRA_LIBS	+= `gnome-config --libs gnomeui`
+endif
+
+EXTRA_LIBS	+= \
+		$(TK_LIBS) \
+		$(NULL)
+
+ifeq ($(OS_ARCH), SunOS)
+ifndef GNU_CC
+# When using Sun's WorkShop compiler, including
+# /wherever/workshop-5.0/SC5.0/include/CC/std/time.h
+# causes most of these compiles to fail with:
+# line 29: Error: Multiple declaration for std::tm.
+# So, this gets around the problem.
+DEFINES           += -D_TIME_H=1
+endif
+endif
diff --git a/embedding/browser/gtk/tests/TestGtkEmbed.cpp b/embedding/browser/gtk/tests/TestGtkEmbed.cpp
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/tests/TestGtkEmbed.cpp
@@ -0,0 +1,1145 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "gtkmozembed.h"
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+// mozilla specific headers
+#include "nsIDOMKeyEvent.h"
+#include "nsIDOMMouseEvent.h"
+#include "nsIDOMUIEvent.h"
+
+#include "nsCOMPtr.h"
+#include "nsISupportsUtils.h"
+#include "nsServiceManagerUtils.h"
+#include "nsIObserverService.h"
+
+#include "nsStringAPI.h"
+#include "gtkmozembed_glue.cpp"
+
+typedef struct _TestGtkBrowser {
+  GtkWidget  *topLevelWindow;
+  GtkWidget  *topLevelVBox;
+  GtkWidget  *menuBar;
+  GtkWidget  *fileMenuItem;
+  GtkWidget  *fileMenu;
+  GtkWidget  *fileOpenNewBrowser;
+  GtkWidget  *fileStream;
+  GtkWidget  *fileMemory;
+  GtkWidget  *fileClose;
+  GtkWidget  *fileQuit;
+  GtkWidget  *toolbarHBox;
+  GtkWidget  *toolbar;
+  GtkWidget  *backButton;
+  GtkWidget  *stopButton;
+  GtkWidget  *forwardButton;
+  GtkWidget  *reloadButton;
+  GtkWidget  *urlEntry;
+  GtkWidget  *mozEmbed;
+  GtkWidget  *progressAreaHBox;
+  GtkWidget  *progressBar;
+  GtkWidget  *statusAlign;
+  GtkWidget  *statusBar;
+  const char *statusMessage;
+  int         loadPercent;
+  int         bytesLoaded;
+  int         maxBytesLoaded;
+  char       *tempMessage;
+  gboolean menuBarOn;
+  gboolean toolBarOn;
+  gboolean locationBarOn;
+  gboolean statusBarOn;
+
+} TestGtkBrowser;
+
+// the list of browser windows currently open
+GList *browser_list = g_list_alloc();
+
+static TestGtkBrowser *new_gtk_browser    (guint32 chromeMask);
+static void            set_browser_visibility (TestGtkBrowser *browser,
+					       gboolean visibility);
+
+static int num_browsers = 0;
+
+// callbacks from the UI
+static void     back_clicked_cb    (GtkButton   *button, 
+				    TestGtkBrowser *browser);
+static void     stop_clicked_cb    (GtkButton   *button,
+				    TestGtkBrowser *browser);
+static void     forward_clicked_cb (GtkButton   *button,
+				    TestGtkBrowser *browser);
+static void     reload_clicked_cb  (GtkButton   *button,
+				    TestGtkBrowser *browser);
+static void     url_activate_cb    (GtkEditable *widget, 
+				    TestGtkBrowser *browser);
+static void     menu_open_new_cb   (GtkMenuItem *menuitem,
+				    TestGtkBrowser *browser);
+static void     menu_stream_cb     (GtkMenuItem *menuitem,
+				    TestGtkBrowser *browser);
+static void     menu_memory_cb     (GtkMenuItem *menuitem,
+				    TestGtkBrowser *browser);
+static void     menu_close_cb      (GtkMenuItem *menuitem,
+				    TestGtkBrowser *browser);
+static void     menu_quit_cb       (GtkMenuItem *menuitem,
+				    TestGtkBrowser *browser);
+static gboolean delete_cb          (GtkWidget *widget, GdkEventAny *event,
+				    TestGtkBrowser *browser);
+static void     destroy_cb         (GtkWidget *widget,
+				    TestGtkBrowser *browser);
+
+// callbacks from the widget
+static void location_changed_cb  (GtkMozEmbed *embed, TestGtkBrowser *browser);
+static void title_changed_cb     (GtkMozEmbed *embed, TestGtkBrowser *browser);
+static void load_started_cb      (GtkMozEmbed *embed, TestGtkBrowser *browser);
+static void load_finished_cb     (GtkMozEmbed *embed, TestGtkBrowser *browser);
+static void net_state_change_cb  (GtkMozEmbed *embed, gint flags,
+				  guint status, TestGtkBrowser *browser);
+static void net_state_change_all_cb (GtkMozEmbed *embed, const char *uri,
+				     gint flags, guint status,
+				     TestGtkBrowser *browser);
+static void progress_change_cb   (GtkMozEmbed *embed, gint cur, gint max,
+				  TestGtkBrowser *browser);
+static void progress_change_all_cb (GtkMozEmbed *embed, const char *uri,
+				    gint cur, gint max,
+				    TestGtkBrowser *browser);
+static void link_message_cb      (GtkMozEmbed *embed, TestGtkBrowser *browser);
+static void js_status_cb         (GtkMozEmbed *embed, TestGtkBrowser *browser);
+static void new_window_cb        (GtkMozEmbed *embed,
+				  GtkMozEmbed **retval, guint chromemask,
+				  TestGtkBrowser *browser);
+static void visibility_cb        (GtkMozEmbed *embed, 
+				  gboolean visibility,
+				  TestGtkBrowser *browser);
+static void destroy_brsr_cb      (GtkMozEmbed *embed, TestGtkBrowser *browser);
+static gint open_uri_cb          (GtkMozEmbed *embed, const char *uri,
+				  TestGtkBrowser *browser);
+static void size_to_cb           (GtkMozEmbed *embed, gint width,
+				  gint height, TestGtkBrowser *browser);
+static gint dom_key_down_cb      (GtkMozEmbed *embed, nsIDOMKeyEvent *event,
+				  TestGtkBrowser *browser);
+static gint dom_key_press_cb     (GtkMozEmbed *embed, nsIDOMKeyEvent *event,
+				  TestGtkBrowser *browser);
+static gint dom_key_up_cb        (GtkMozEmbed *embed, nsIDOMKeyEvent *event,
+				  TestGtkBrowser *browser);
+static gint dom_mouse_down_cb    (GtkMozEmbed *embed, nsIDOMMouseEvent *event,
+				  TestGtkBrowser *browser);
+static gint dom_mouse_up_cb      (GtkMozEmbed *embed, nsIDOMMouseEvent *event,
+				  TestGtkBrowser *browser);
+static gint dom_mouse_click_cb   (GtkMozEmbed *embed, nsIDOMMouseEvent *event,
+				  TestGtkBrowser *browser);
+static gint dom_mouse_dbl_click_cb (GtkMozEmbed *embed, 
+				  nsIDOMMouseEvent *event,
+				  TestGtkBrowser *browser);
+static gint dom_mouse_over_cb    (GtkMozEmbed *embed, nsIDOMMouseEvent *event,
+				  TestGtkBrowser *browser);
+static gint dom_mouse_out_cb     (GtkMozEmbed *embed, nsIDOMMouseEvent *event,
+				  TestGtkBrowser *browser);
+static gint dom_activate_cb      (GtkMozEmbed *embed, nsIDOMUIEvent *event,
+				  TestGtkBrowser *browser);
+static gint dom_focus_in_cb      (GtkMozEmbed *embed, nsIDOMUIEvent *event,
+				  TestGtkBrowser *browser);
+static gint dom_focus_out_cb     (GtkMozEmbed *embed, nsIDOMUIEvent *event,
+				  TestGtkBrowser *browser);
+
+// callbacks from the singleton object
+static void new_window_orphan_cb (GtkMozEmbedSingle *embed,
+				  GtkMozEmbed **retval, guint chromemask,
+				  gpointer data);
+
+// some utility functions
+static void update_status_bar_text  (TestGtkBrowser *browser);
+static void update_temp_message     (TestGtkBrowser *browser,
+				     const char *message);
+static void update_nav_buttons      (TestGtkBrowser *browser);
+
+int
+main(int argc, char **argv)
+{
+  gtk_set_locale();
+  gtk_init(&argc, &argv);
+
+  static const GREVersionRange greVersion = {
+    "1.9a", PR_TRUE,
+    "2", PR_TRUE
+  };
+
+  char xpcomPath[PATH_MAX];
+
+  nsresult rv = GRE_GetGREPathWithProperties(&greVersion, 1, nsnull, 0,
+                                             xpcomPath, sizeof(xpcomPath));
+  if (NS_FAILED(rv)) {
+    fprintf(stderr, "Couldn't find a compatible GRE.\n");
+    return 1;
+  }
+
+  rv = XPCOMGlueStartup(xpcomPath);
+  if (NS_FAILED(rv)) {
+    fprintf(stderr, "Couldn't start XPCOM.");
+    return 1;
+  }
+
+  rv = GTKEmbedGlueStartup();
+  if (NS_FAILED(rv)) {
+    fprintf(stderr, "Couldn't find GTKMozEmbed symbols.");
+    return 1;
+  }
+
+  char *lastSlash = strrchr(xpcomPath, '/');
+  if (lastSlash)
+    *lastSlash = '\0';
+
+  gtk_moz_embed_set_path(xpcomPath);
+
+  char *home_path;
+  char *full_path;
+  home_path = getenv("HOME");
+  if (!home_path) {
+    fprintf(stderr, "Failed to get HOME\n");
+    exit(1);
+  }
+  
+  full_path = g_strdup_printf("%s/%s", home_path, ".TestGtkEmbed");
+  
+  gtk_moz_embed_set_profile_path(full_path, "TestGtkEmbed");
+
+  TestGtkBrowser *browser = new_gtk_browser(GTK_MOZ_EMBED_FLAG_DEFAULTCHROME);
+
+  // set our minimum size
+  gtk_widget_set_size_request(browser->mozEmbed, 400, 400);
+
+  set_browser_visibility(browser, TRUE);
+
+  if (argc > 1)
+    gtk_moz_embed_load_url(GTK_MOZ_EMBED(browser->mozEmbed), argv[1]);
+
+  // get the singleton object and hook up to its new window callback
+  // so we can create orphaned windows.
+
+  GtkMozEmbedSingle *single;
+
+  single = gtk_moz_embed_single_get();
+  if (!single) {
+    fprintf(stderr, "Failed to get singleton embed object!\n");
+    exit(1);
+  }
+
+  g_signal_connect(GTK_OBJECT(single), "new_window_orphan",
+                   G_CALLBACK(new_window_orphan_cb), NULL);
+
+  gtk_moz_embed_push_startup();
+  gtk_main();
+  gtk_moz_embed_pop_startup();
+}
+
+static TestGtkBrowser *
+new_gtk_browser(guint32 chromeMask)
+{
+  guint32         actualChromeMask = chromeMask;
+  TestGtkBrowser *browser = 0;
+
+  num_browsers++;
+
+  browser = g_new0(TestGtkBrowser, 1);
+
+  browser_list = g_list_prepend(browser_list, browser);
+
+  browser->menuBarOn = FALSE;
+  browser->toolBarOn = FALSE;
+  browser->locationBarOn = FALSE;
+  browser->statusBarOn = FALSE;
+
+  g_print("new_gtk_browser\n");
+
+  if (chromeMask == GTK_MOZ_EMBED_FLAG_DEFAULTCHROME)
+    actualChromeMask = GTK_MOZ_EMBED_FLAG_ALLCHROME;
+
+  if (actualChromeMask & GTK_MOZ_EMBED_FLAG_MENUBARON)
+  {
+    browser->menuBarOn = TRUE;
+    g_print("\tmenu bar\n");
+  }
+  if (actualChromeMask & GTK_MOZ_EMBED_FLAG_TOOLBARON)
+  {
+    browser->toolBarOn = TRUE;
+    g_print("\ttool bar\n");
+  }
+  if (actualChromeMask & GTK_MOZ_EMBED_FLAG_LOCATIONBARON)
+  {
+    browser->locationBarOn = TRUE;
+    g_print("\tlocation bar\n");
+  }
+  if (actualChromeMask & GTK_MOZ_EMBED_FLAG_STATUSBARON)
+  {
+    browser->statusBarOn = TRUE;
+    g_print("\tstatus bar\n");
+  }
+
+  // create our new toplevel window
+  browser->topLevelWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+  // new vbox
+  browser->topLevelVBox = gtk_vbox_new(FALSE, 0);
+  // add it to the toplevel window
+  gtk_container_add(GTK_CONTAINER(browser->topLevelWindow),
+		    browser->topLevelVBox);
+  // create our menu bar
+  browser->menuBar = gtk_menu_bar_new();
+  // create the file menu
+  browser->fileMenuItem = gtk_menu_item_new_with_label("File");
+  browser->fileMenu = gtk_menu_new();
+  gtk_menu_item_set_submenu (GTK_MENU_ITEM(browser->fileMenuItem),
+			     browser->fileMenu);
+
+  browser->fileOpenNewBrowser = 
+    gtk_menu_item_new_with_label("Open New Browser");
+  gtk_menu_shell_append((GtkMenuShell *)GTK_MENU(browser->fileMenu),
+                        browser->fileOpenNewBrowser);
+  
+  browser->fileStream =
+    gtk_menu_item_new_with_label("Test Stream");
+  gtk_menu_shell_append((GtkMenuShell *)GTK_MENU(browser->fileMenu),
+                        browser->fileStream);
+
+  browser->fileMemory =
+    gtk_menu_item_new_with_label("Release Memory");
+  gtk_menu_shell_append((GtkMenuShell *)GTK_MENU(browser->fileMenu),
+                        browser->fileMemory);
+
+  browser->fileClose =
+    gtk_menu_item_new_with_label("Close");
+  gtk_menu_shell_append((GtkMenuShell *)GTK_MENU(browser->fileMenu),
+                        browser->fileClose);
+
+  browser->fileQuit =
+    gtk_menu_item_new_with_label("Quit");
+  gtk_menu_shell_append((GtkMenuShell *)GTK_MENU(browser->fileMenu),
+                        browser->fileQuit);
+  
+  // append it
+  gtk_menu_shell_append((GtkMenuShell *)GTK_MENU_BAR(browser->menuBar),
+                        browser->fileMenuItem);
+
+  // add it to the vbox
+  gtk_box_pack_start(GTK_BOX(browser->topLevelVBox),
+		     browser->menuBar,
+		     FALSE, // expand
+		     FALSE, // fill
+		     0);    // padding
+  // create the hbox that will contain the toolbar and the url text entry bar
+  browser->toolbarHBox = gtk_hbox_new(FALSE, 0);
+  // add that hbox to the vbox
+  gtk_box_pack_start(GTK_BOX(browser->topLevelVBox), 
+		     browser->toolbarHBox,
+		     FALSE, // expand
+		     FALSE, // fill
+		     0);    // padding
+  // new horiz toolbar with buttons + icons
+  browser->toolbar = gtk_toolbar_new();
+  gtk_toolbar_set_orientation(GTK_TOOLBAR(browser->toolbar),
+			      GTK_ORIENTATION_HORIZONTAL);
+  gtk_toolbar_set_style(GTK_TOOLBAR(browser->toolbar),
+			GTK_TOOLBAR_BOTH);
+
+  // add it to the hbox
+  gtk_box_pack_start(GTK_BOX(browser->toolbarHBox), browser->toolbar,
+		   FALSE, // expand
+		   FALSE, // fill
+		   0);    // padding
+  // new back button
+  browser->backButton =
+    gtk_toolbar_append_item(GTK_TOOLBAR(browser->toolbar),
+			    "Back",
+			    "Go Back",
+			    "Go Back",
+			    0, // XXX replace with icon
+			    G_CALLBACK(back_clicked_cb),
+			    browser);
+  // new stop button
+  browser->stopButton = 
+    gtk_toolbar_append_item(GTK_TOOLBAR(browser->toolbar),
+			    "Stop",
+			    "Stop",
+			    "Stop",
+			    0, // XXX replace with icon
+			    G_CALLBACK(stop_clicked_cb),
+			    browser);
+  // new forward button
+  browser->forwardButton =
+    gtk_toolbar_append_item(GTK_TOOLBAR(browser->toolbar),
+			    "Forward",
+			    "Forward",
+			    "Forward",
+			    0, // XXX replace with icon
+			    G_CALLBACK(forward_clicked_cb),
+			    browser);
+  // new reload button
+  browser->reloadButton = 
+    gtk_toolbar_append_item(GTK_TOOLBAR(browser->toolbar),
+			    "Reload",
+			    "Reload",
+			    "Reload",
+			    0, // XXX replace with icon
+			    G_CALLBACK(reload_clicked_cb),
+			    browser);
+  // create the url text entry
+  browser->urlEntry = gtk_entry_new();
+  // add it to the hbox
+  gtk_box_pack_start(GTK_BOX(browser->toolbarHBox), browser->urlEntry,
+		     TRUE, // expand
+		     TRUE, // fill
+		     0);    // padding
+  // create our new gtk moz embed widget
+  browser->mozEmbed = gtk_moz_embed_new();
+  gtk_moz_embed_push_startup();
+  // add it to the toplevel vbox
+  gtk_box_pack_start(GTK_BOX(browser->topLevelVBox), browser->mozEmbed,
+		     TRUE, // expand
+		     TRUE, // fill
+		     0);   // padding
+  // create the new hbox for the progress area
+  browser->progressAreaHBox = gtk_hbox_new(FALSE, 0);
+  // add it to the vbox
+  gtk_box_pack_start(GTK_BOX(browser->topLevelVBox), browser->progressAreaHBox,
+		     FALSE, // expand
+		     FALSE, // fill
+		     0);   // padding
+  // create our new progress bar
+  browser->progressBar = gtk_progress_bar_new();
+  // add it to the hbox
+  gtk_box_pack_start(GTK_BOX(browser->progressAreaHBox), browser->progressBar,
+		     FALSE, // expand
+		     FALSE, // fill
+		     0); // padding
+  
+  // create our status area and the alignment object that will keep it
+  // from expanding
+  browser->statusAlign = gtk_alignment_new(0, 0, 1, 1);
+  gtk_widget_set_size_request(browser->statusAlign, 1, -1);
+  // create the status bar
+  browser->statusBar = gtk_statusbar_new();
+  gtk_container_add(GTK_CONTAINER(browser->statusAlign), browser->statusBar);
+  // add it to the hbox
+  gtk_box_pack_start(GTK_BOX(browser->progressAreaHBox), browser->statusAlign,
+		     TRUE, // expand
+		     TRUE, // fill
+		     0);   // padding
+  // by default none of the buttons are marked as sensitive.
+  gtk_widget_set_sensitive(browser->backButton, FALSE);
+  gtk_widget_set_sensitive(browser->stopButton, FALSE);
+  gtk_widget_set_sensitive(browser->forwardButton, FALSE);
+  gtk_widget_set_sensitive(browser->reloadButton, FALSE);
+  
+  // catch the destruction of the toplevel window
+  g_signal_connect(GTK_OBJECT(browser->topLevelWindow), "delete_event",
+                   G_CALLBACK(delete_cb), browser);
+
+  // hook up the activate signal to the right callback
+  g_signal_connect(GTK_OBJECT(browser->urlEntry), "activate",
+                   G_CALLBACK(url_activate_cb), browser);
+
+  // hook up to the open new browser activation
+  g_signal_connect(GTK_OBJECT(browser->fileOpenNewBrowser), "activate",
+                   G_CALLBACK(menu_open_new_cb), browser);
+  // hook up to the stream test
+  g_signal_connect(GTK_OBJECT(browser->fileStream), "activate",
+                   G_CALLBACK(menu_stream_cb), browser);
+  // hook up the memory pressure release function
+  g_signal_connect(GTK_OBJECT(browser->fileMemory), "activate",
+                   G_CALLBACK(menu_memory_cb), browser);
+  // close this window
+  g_signal_connect(GTK_OBJECT(browser->fileClose), "activate",
+                   G_CALLBACK(menu_close_cb), browser);
+  // quit the application
+  g_signal_connect(GTK_OBJECT(browser->fileQuit), "activate",
+                   G_CALLBACK(menu_quit_cb), browser);
+
+  // hook up the location change to update the urlEntry
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "location",
+                   G_CALLBACK(location_changed_cb), browser);
+  // hook up the title change to update the window title
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "title",
+                   G_CALLBACK(title_changed_cb), browser);
+  // hook up the start and stop signals
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "net_start",
+                   G_CALLBACK(load_started_cb), browser);
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "net_stop",
+                   G_CALLBACK(load_finished_cb), browser);
+  // hook up to the change in network status
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "net_state",
+                   G_CALLBACK(net_state_change_cb), browser);
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "net_state_all",
+                   G_CALLBACK(net_state_change_all_cb), browser);
+  // hookup to changes in progress
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "progress",
+                   G_CALLBACK(progress_change_cb), browser);
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "progress_all",
+                   G_CALLBACK(progress_change_all_cb), browser);
+  // hookup to changes in over-link message
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "link_message",
+                   G_CALLBACK(link_message_cb), browser);
+  // hookup to changes in js status message
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "js_status",
+                   G_CALLBACK(js_status_cb), browser);
+  // hookup to see whenever a new window is requested
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "new_window",
+                   G_CALLBACK(new_window_cb), browser);
+  // hookup to any requested visibility changes
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "visibility",
+                   G_CALLBACK(visibility_cb), browser);
+  // hookup to the signal that says that the browser requested to be
+  // destroyed
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "destroy_browser",
+                   G_CALLBACK(destroy_brsr_cb), browser);
+  // hookup to the signal that is called when someone clicks on a link
+  // to load a new uri
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "open_uri",
+                   G_CALLBACK(open_uri_cb), browser);
+  // this signal is emitted when there's a request to change the
+  // containing browser window to a certain height, like with width
+  // and height args for a window.open in javascript
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "size_to",
+                   G_CALLBACK(size_to_cb), browser);
+  // key event signals
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_key_down",
+                   G_CALLBACK(dom_key_down_cb), browser);
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_key_press",
+                   G_CALLBACK(dom_key_press_cb), browser);
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_key_up",
+                   G_CALLBACK(dom_key_up_cb), browser);
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_mouse_down",
+                   G_CALLBACK(dom_mouse_down_cb), browser);
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_mouse_up",
+                   G_CALLBACK(dom_mouse_up_cb), browser);
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_mouse_click",
+                   G_CALLBACK(dom_mouse_click_cb), browser);
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_mouse_dbl_click",
+                   G_CALLBACK(dom_mouse_dbl_click_cb), browser);
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_mouse_over",
+                   G_CALLBACK(dom_mouse_over_cb), browser);
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_mouse_out",
+                   G_CALLBACK(dom_mouse_out_cb), browser);
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_activate",
+                   G_CALLBACK(dom_activate_cb), browser);
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_focus_in",
+                   G_CALLBACK(dom_focus_in_cb), browser);
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "dom_focus_out",
+                   G_CALLBACK(dom_focus_out_cb), browser);
+  // hookup to when the window is destroyed
+  g_signal_connect(GTK_OBJECT(browser->mozEmbed), "destroy",
+                   G_CALLBACK(destroy_cb), browser);
+  
+  // set the chrome type so it's stored in the object
+  gtk_moz_embed_set_chrome_mask(GTK_MOZ_EMBED(browser->mozEmbed),
+				actualChromeMask);
+
+  return browser;
+}
+
+void
+set_browser_visibility (TestGtkBrowser *browser, gboolean visibility)
+{
+  if (!visibility)
+  {
+    gtk_widget_hide(browser->topLevelWindow);
+    return;
+  }
+  
+  if (browser->menuBarOn)
+    gtk_widget_show_all(browser->menuBar);
+  else
+    gtk_widget_hide_all(browser->menuBar);
+
+  // since they are on the same line here...
+  if (browser->toolBarOn || browser->locationBarOn)
+    gtk_widget_show_all(browser->toolbarHBox);
+  else 
+    gtk_widget_hide_all(browser->toolbarHBox);
+
+  if (browser->statusBarOn)
+    gtk_widget_show_all(browser->progressAreaHBox);
+  else
+    gtk_widget_hide_all(browser->progressAreaHBox);
+
+  gtk_widget_show(browser->mozEmbed);
+  gtk_widget_show(browser->topLevelVBox);
+  gtk_widget_show(browser->topLevelWindow);
+}
+
+void
+back_clicked_cb (GtkButton *button, TestGtkBrowser *browser)
+{
+  gtk_moz_embed_go_back(GTK_MOZ_EMBED(browser->mozEmbed));
+}
+
+void
+stop_clicked_cb (GtkButton *button, TestGtkBrowser *browser)
+{
+  g_print("stop_clicked_cb\n");
+  gtk_moz_embed_stop_load(GTK_MOZ_EMBED(browser->mozEmbed));
+}
+
+void
+forward_clicked_cb (GtkButton *button, TestGtkBrowser *browser)
+{
+  g_print("forward_clicked_cb\n");
+  gtk_moz_embed_go_forward(GTK_MOZ_EMBED(browser->mozEmbed));
+}
+
+void
+reload_clicked_cb  (GtkButton *button, TestGtkBrowser *browser)
+{
+  g_print("reload_clicked_cb\n");
+  GdkModifierType state = (GdkModifierType)0;
+  gint x, y;
+  gdk_window_get_pointer(NULL, &x, &y, &state);
+  
+  gtk_moz_embed_reload(GTK_MOZ_EMBED(browser->mozEmbed),
+		       (state & GDK_SHIFT_MASK) ?
+		       GTK_MOZ_EMBED_FLAG_RELOADBYPASSCACHE : 
+		       GTK_MOZ_EMBED_FLAG_RELOADNORMAL);
+}
+
+void 
+stream_clicked_cb  (GtkButton   *button, TestGtkBrowser *browser)
+{
+  const char *data;
+  const char *data2;
+  data = "<html>Hi";
+  data2 = " there</html>\n";
+  g_print("stream_clicked_cb\n");
+  gtk_moz_embed_open_stream(GTK_MOZ_EMBED(browser->mozEmbed),
+			    "file://", "text/html");
+  gtk_moz_embed_append_data(GTK_MOZ_EMBED(browser->mozEmbed),
+			    data, strlen(data));
+  gtk_moz_embed_append_data(GTK_MOZ_EMBED(browser->mozEmbed),
+			    data2, strlen(data2));
+  gtk_moz_embed_close_stream(GTK_MOZ_EMBED(browser->mozEmbed));
+}
+
+void
+url_activate_cb    (GtkEditable *widget, TestGtkBrowser *browser)
+{
+  gchar *text = gtk_editable_get_chars(widget, 0, -1);
+  g_print("loading url %s\n", text);
+  gtk_moz_embed_load_url(GTK_MOZ_EMBED(browser->mozEmbed), text);
+  g_free(text);
+}
+
+void
+menu_open_new_cb   (GtkMenuItem *menuitem, TestGtkBrowser *browser)
+{
+  g_print("opening new browser.\n");
+  TestGtkBrowser *newBrowser = 
+    new_gtk_browser(GTK_MOZ_EMBED_FLAG_DEFAULTCHROME);
+  gtk_widget_set_size_request(newBrowser->mozEmbed, 400, 400);
+  set_browser_visibility(newBrowser, TRUE);
+}
+
+void
+menu_stream_cb     (GtkMenuItem *menuitem, TestGtkBrowser *browser)
+{
+  g_print("menu_stream_cb\n");
+  const char *data;
+  const char *data2;
+  data = "<html>Hi";
+  data2 = " <a href='foo.html'>there</a></html>\n";
+  g_print("stream_clicked_cb\n");
+  gtk_moz_embed_open_stream(GTK_MOZ_EMBED(browser->mozEmbed),
+			    "file://", "text/html");
+  gtk_moz_embed_append_data(GTK_MOZ_EMBED(browser->mozEmbed),
+			    data, strlen(data));
+  gtk_moz_embed_append_data(GTK_MOZ_EMBED(browser->mozEmbed),
+			    data2, strlen(data2));
+  gtk_moz_embed_close_stream(GTK_MOZ_EMBED(browser->mozEmbed));
+}
+
+void
+menu_memory_cb (GtkMenuItem *menuitem, TestGtkBrowser *browser)
+{
+  g_print("menu_memory_cb\n");
+  nsCOMPtr<nsIObserverService> os = do_GetService("@mozilla.org/observer-service;1");
+  if (!os)
+    return;
+
+  // Compact like you mean it.  We do this three times to give the
+  // cycle collector a chance to try and reclaim as much as we can.
+  os->NotifyObservers(nsnull, "memory-pressure", NS_LITERAL_STRING("heap-minimize").get());
+  os->NotifyObservers(nsnull, "memory-pressure", NS_LITERAL_STRING("heap-minimize").get());
+  os->NotifyObservers(nsnull, "memory-pressure", NS_LITERAL_STRING("heap-minimize").get());
+}
+
+void
+menu_close_cb (GtkMenuItem *menuitem, TestGtkBrowser *browser)
+{
+  gtk_widget_destroy(browser->topLevelWindow);
+}
+
+void
+menu_quit_cb (GtkMenuItem *menuitem, TestGtkBrowser *browser)
+{
+  TestGtkBrowser *tmpBrowser;
+  GList *tmp_list = browser_list;
+  tmpBrowser = (TestGtkBrowser *)tmp_list->data;
+  while (tmpBrowser) {
+    tmp_list = tmp_list->next;
+    gtk_widget_destroy(tmpBrowser->topLevelWindow);
+    tmpBrowser = (TestGtkBrowser *)tmp_list->data;
+  }
+}
+
+gboolean
+delete_cb(GtkWidget *widget, GdkEventAny *event, TestGtkBrowser *browser)
+{
+  g_print("delete_cb\n");
+  gtk_widget_destroy(widget);
+  return TRUE;
+}
+
+static gboolean
+idle_quit(void*)
+{
+  gtk_main_quit();
+  return FALSE;
+}
+
+static gboolean
+idle_pop(void*)
+{
+  gtk_moz_embed_pop_startup();
+  return FALSE;
+}
+
+void
+destroy_cb         (GtkWidget *widget, TestGtkBrowser *browser)
+{
+  GList *tmp_list;
+  g_print("destroy_cb\n");
+  num_browsers--;
+  tmp_list = g_list_find(browser_list, browser);
+  browser_list = g_list_remove_link(browser_list, tmp_list);
+  if (browser->tempMessage)
+    g_free(browser->tempMessage);
+  g_idle_add(idle_pop, NULL);
+  if (num_browsers == 0)
+    g_idle_add (idle_quit, NULL);
+}
+
+void
+location_changed_cb (GtkMozEmbed *embed, TestGtkBrowser *browser)
+{
+  char *newLocation;
+  int   newPosition = 0;
+  g_print("location_changed_cb\n");
+  newLocation = gtk_moz_embed_get_location(embed);
+  if (newLocation)
+  {
+    gtk_editable_delete_text(GTK_EDITABLE(browser->urlEntry), 0, -1);
+    gtk_editable_insert_text(GTK_EDITABLE(browser->urlEntry),
+			     newLocation, strlen(newLocation), &newPosition);
+    g_free(newLocation);
+  }
+  else
+    g_print("failed to get location!\n");
+  // always make sure to clear the tempMessage.  it might have been
+  // set from the link before a click and we wouldn't have gotten the
+  // callback to unset it.
+  update_temp_message(browser, 0);
+  // update the nav buttons on a location change
+  update_nav_buttons(browser);
+}
+
+void
+title_changed_cb    (GtkMozEmbed *embed, TestGtkBrowser *browser)
+{
+  char *newTitle;
+  g_print("title_changed_cb\n");
+  newTitle = gtk_moz_embed_get_title(embed);
+  if (newTitle)
+  {
+    gtk_window_set_title(GTK_WINDOW(browser->topLevelWindow), newTitle);
+    g_free(newTitle);
+  }
+  
+}
+
+void
+load_started_cb     (GtkMozEmbed *embed, TestGtkBrowser *browser)
+{
+  g_print("load_started_cb\n");
+  gtk_widget_set_sensitive(browser->stopButton, TRUE);
+  gtk_widget_set_sensitive(browser->reloadButton, FALSE);
+  browser->loadPercent = 0;
+  browser->bytesLoaded = 0;
+  browser->maxBytesLoaded = 0;
+  update_status_bar_text(browser);
+}
+
+void
+load_finished_cb    (GtkMozEmbed *embed, TestGtkBrowser *browser)
+{
+  g_print("load_finished_cb\n");
+  gtk_widget_set_sensitive(browser->stopButton, FALSE);
+  gtk_widget_set_sensitive(browser->reloadButton, TRUE);
+  browser->loadPercent = 0;
+  browser->bytesLoaded = 0;
+  browser->maxBytesLoaded = 0;
+  update_status_bar_text(browser);
+  gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(browser->progressBar), 0);
+}
+
+
+void
+net_state_change_cb (GtkMozEmbed *embed, gint flags, guint status,
+		     TestGtkBrowser *browser)
+{
+  g_print("net_state_change_cb %d\n", flags);
+  if (flags & GTK_MOZ_EMBED_FLAG_IS_REQUEST) {
+    if (flags & GTK_MOZ_EMBED_FLAG_REDIRECTING)
+    browser->statusMessage = "Redirecting to site...";
+    else if (flags & GTK_MOZ_EMBED_FLAG_TRANSFERRING)
+    browser->statusMessage = "Transferring data from site...";
+    else if (flags & GTK_MOZ_EMBED_FLAG_NEGOTIATING)
+    browser->statusMessage = "Waiting for authorization...";
+  }
+
+  if (status == GTK_MOZ_EMBED_STATUS_FAILED_DNS)
+    browser->statusMessage = "Site not found.";
+  else if (status == GTK_MOZ_EMBED_STATUS_FAILED_CONNECT)
+    browser->statusMessage = "Failed to connect to site.";
+  else if (status == GTK_MOZ_EMBED_STATUS_FAILED_TIMEOUT)
+    browser->statusMessage = "Failed due to connection timeout.";
+  else if (status == GTK_MOZ_EMBED_STATUS_FAILED_USERCANCELED)
+    browser->statusMessage = "User canceled connecting to site.";
+
+  if (flags & GTK_MOZ_EMBED_FLAG_IS_DOCUMENT) {
+    if (flags & GTK_MOZ_EMBED_FLAG_START)
+      browser->statusMessage = "Loading site...";
+    else if (flags & GTK_MOZ_EMBED_FLAG_STOP)
+      browser->statusMessage = "Done.";
+  }
+
+  update_status_bar_text(browser);
+  
+}
+
+void net_state_change_all_cb (GtkMozEmbed *embed, const char *uri,
+				     gint flags, guint status,
+				     TestGtkBrowser *browser)
+{
+  //  g_print("net_state_change_all_cb %s %d %d\n", uri, flags, status);
+}
+
+void progress_change_cb   (GtkMozEmbed *embed, gint cur, gint max,
+			   TestGtkBrowser *browser)
+{
+  g_print("progress_change_cb cur %d max %d\n", cur, max);
+
+  // avoid those pesky divide by zero errors
+  if (max < 1)
+  {
+    browser->loadPercent = 0;
+    browser->bytesLoaded = cur;
+    browser->maxBytesLoaded = 0;
+    update_status_bar_text(browser);
+  }
+  else
+  {
+    browser->bytesLoaded = cur;
+    browser->maxBytesLoaded = max;
+    if (cur > max)
+      browser->loadPercent = 100;
+    else
+      browser->loadPercent = (cur * 100) / max;
+    update_status_bar_text(browser);
+    gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(browser->progressBar),
+                                  browser->loadPercent / 100.0);
+  }
+  
+}
+
+void progress_change_all_cb (GtkMozEmbed *embed, const char *uri,
+			     gint cur, gint max,
+			     TestGtkBrowser *browser)
+{
+  //g_print("progress_change_all_cb %s cur %d max %d\n", uri, cur, max);
+}
+
+void
+link_message_cb      (GtkMozEmbed *embed, TestGtkBrowser *browser)
+{
+  char *message;
+  g_print("link_message_cb\n");
+  message = gtk_moz_embed_get_link_message(embed);
+  if (!message || !*message)
+    update_temp_message(browser, 0);
+  else
+    update_temp_message(browser, message);
+  if (message)
+    g_free(message);
+}
+
+void
+js_status_cb (GtkMozEmbed *embed, TestGtkBrowser *browser)
+{
+ char *message;
+  g_print("js_status_cb\n");
+  message = gtk_moz_embed_get_js_status(embed);
+  if (!message || !*message)
+    update_temp_message(browser, 0);
+  else
+    update_temp_message(browser, message);
+  if (message)
+    g_free(message);
+}
+
+void
+new_window_cb (GtkMozEmbed *embed, GtkMozEmbed **newEmbed, guint chromemask, TestGtkBrowser *browser)
+{
+  g_print("new_window_cb\n");
+  g_print("embed is %p chromemask is %d\n", (void *)embed, chromemask);
+  TestGtkBrowser *newBrowser = new_gtk_browser(chromemask);
+  gtk_widget_set_size_request(newBrowser->mozEmbed, 400, 400);
+  *newEmbed = GTK_MOZ_EMBED(newBrowser->mozEmbed);
+  g_print("new browser is %p\n", (void *)*newEmbed);
+}
+
+void
+visibility_cb (GtkMozEmbed *embed, gboolean visibility, TestGtkBrowser *browser)
+{
+  g_print("visibility_cb %d\n", visibility);
+  set_browser_visibility(browser, visibility);
+}
+
+void
+destroy_brsr_cb      (GtkMozEmbed *embed, TestGtkBrowser *browser)
+{
+  g_print("destroy_brsr_cb\n");
+  gtk_widget_destroy(browser->topLevelWindow);
+}
+
+gint
+open_uri_cb          (GtkMozEmbed *embed, const char *uri, TestGtkBrowser *browser)
+{
+  g_print("open_uri_cb %s\n", uri);
+
+  // interrupt this test load
+  if (!strcmp(uri, "http://people.redhat.com/blizzard/monkeys.txt"))
+    return TRUE;
+  // don't interrupt anything
+  return FALSE;
+}
+
+void
+size_to_cb (GtkMozEmbed *embed, gint width, gint height,
+	    TestGtkBrowser *browser)
+{
+  g_print("*** size_to_cb %d %d\n", width, height);
+  gtk_widget_set_size_request(browser->mozEmbed, width, height);
+}
+
+gint dom_key_down_cb      (GtkMozEmbed *embed, nsIDOMKeyEvent *event,
+			   TestGtkBrowser *browser)
+{
+  PRUint32 keyCode = 0;
+  //  g_print("dom_key_down_cb\n");
+  event->GetKeyCode(&keyCode);
+  // g_print("key code is %d\n", keyCode);
+  return NS_OK;
+}
+
+gint dom_key_press_cb     (GtkMozEmbed *embed, nsIDOMKeyEvent *event,
+			   TestGtkBrowser *browser)
+{
+  PRUint32 keyCode = 0;
+  // g_print("dom_key_press_cb\n");
+  event->GetCharCode(&keyCode);
+  // g_print("char code is %d\n", keyCode);
+  return NS_OK;
+}
+
+gint dom_key_up_cb        (GtkMozEmbed *embed, nsIDOMKeyEvent *event,
+			   TestGtkBrowser *browser)
+{
+  PRUint32 keyCode = 0;
+  // g_print("dom_key_up_cb\n");
+  event->GetKeyCode(&keyCode);
+  // g_print("key code is %d\n", keyCode);
+  return NS_OK;
+}
+
+gint dom_mouse_down_cb    (GtkMozEmbed *embed, nsIDOMMouseEvent *event,
+			   TestGtkBrowser *browser)
+{
+  //  g_print("dom_mouse_down_cb\n");
+  return NS_OK;
+ }
+
+gint dom_mouse_up_cb      (GtkMozEmbed *embed, nsIDOMMouseEvent *event,
+			   TestGtkBrowser *browser)
+{
+  //  g_print("dom_mouse_up_cb\n");
+  return NS_OK;
+}
+
+gint dom_mouse_click_cb   (GtkMozEmbed *embed, nsIDOMMouseEvent *event,
+			   TestGtkBrowser *browser)
+{
+  //  g_print("dom_mouse_click_cb\n");
+  PRUint16 button;
+  event->GetButton(&button);
+  printf("button was %d\n", button);
+  return NS_OK;
+}
+
+gint dom_mouse_dbl_click_cb (GtkMozEmbed *embed, nsIDOMMouseEvent *event,
+			     TestGtkBrowser *browser)
+{
+  //  g_print("dom_mouse_dbl_click_cb\n");
+  return NS_OK;
+}
+
+gint dom_mouse_over_cb    (GtkMozEmbed *embed, nsIDOMMouseEvent *event,
+			   TestGtkBrowser *browser)
+{
+  //g_print("dom_mouse_over_cb\n");
+  return NS_OK;
+}
+
+gint dom_mouse_out_cb     (GtkMozEmbed *embed, nsIDOMMouseEvent *event,
+			   TestGtkBrowser *browser)
+{
+  //g_print("dom_mouse_out_cb\n");
+  return NS_OK;
+}
+
+gint dom_activate_cb      (GtkMozEmbed *embed, nsIDOMUIEvent *event,
+			   TestGtkBrowser *browser)
+{
+  //g_print("dom_activate_cb\n");
+  return NS_OK;
+}
+
+gint dom_focus_in_cb      (GtkMozEmbed *embed, nsIDOMUIEvent *event,
+			   TestGtkBrowser *browser)
+{
+  //g_print("dom_focus_in_cb\n");
+  return NS_OK;
+}
+
+gint dom_focus_out_cb     (GtkMozEmbed *embed, nsIDOMUIEvent *event,
+			   TestGtkBrowser *browser)
+{
+  //g_print("dom_focus_out_cb\n");
+  return NS_OK;
+}
+
+void new_window_orphan_cb (GtkMozEmbedSingle *embed,
+			   GtkMozEmbed **retval, guint chromemask,
+			   gpointer data)
+{
+  g_print("new_window_orphan_cb\n");
+  g_print("chromemask is %d\n", chromemask);
+  TestGtkBrowser *newBrowser = new_gtk_browser(chromemask);
+  *retval = GTK_MOZ_EMBED(newBrowser->mozEmbed);
+  g_print("new browser is %p\n", (void *)*retval);
+}
+
+// utility functions
+
+void
+update_status_bar_text(TestGtkBrowser *browser)
+{
+  gchar message[256];
+  
+  gtk_statusbar_pop(GTK_STATUSBAR(browser->statusBar), 1);
+  if (browser->tempMessage)
+    gtk_statusbar_push(GTK_STATUSBAR(browser->statusBar), 1, browser->tempMessage);
+  else
+  {
+    if (browser->loadPercent)
+    {
+      g_snprintf(message, 255, "%s (%d%% complete, %d bytes of %d loaded)", browser->statusMessage, browser->loadPercent, browser->bytesLoaded, browser->maxBytesLoaded);
+    }
+    else if (browser->bytesLoaded)
+    {
+      g_snprintf(message, 255, "%s (%d bytes loaded)", browser->statusMessage, browser->bytesLoaded);
+    }
+    else if (browser->statusMessage == NULL)
+    {
+      g_snprintf(message, 255, " ");
+    }
+    else
+    {
+      g_snprintf(message, 255, "%s", browser->statusMessage);
+    }
+    gtk_statusbar_push(GTK_STATUSBAR(browser->statusBar), 1, message);
+  }
+}
+
+void
+update_temp_message(TestGtkBrowser *browser, const char *message)
+{
+  if (browser->tempMessage)
+    g_free(browser->tempMessage);
+  if (message)
+    browser->tempMessage = g_strdup(message);
+  else
+    browser->tempMessage = 0;
+  // now that we've updated the temp message, redraw the status bar
+  update_status_bar_text(browser);
+}
+
+
+void
+update_nav_buttons      (TestGtkBrowser *browser)
+{
+  gboolean can_go_back;
+  gboolean can_go_forward;
+  can_go_back = gtk_moz_embed_can_go_back(GTK_MOZ_EMBED(browser->mozEmbed));
+  can_go_forward = gtk_moz_embed_can_go_forward(GTK_MOZ_EMBED(browser->mozEmbed));
+  if (can_go_back)
+    gtk_widget_set_sensitive(browser->backButton, TRUE);
+  else
+    gtk_widget_set_sensitive(browser->backButton, FALSE);
+  if (can_go_forward)
+    gtk_widget_set_sensitive(browser->forwardButton, TRUE);
+  else
+    gtk_widget_set_sensitive(browser->forwardButton, FALSE);
+ }
+
diff --git a/embedding/browser/gtk/tests/TestGtkEmbedChild.cpp b/embedding/browser/gtk/tests/TestGtkEmbedChild.cpp
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/tests/TestGtkEmbedChild.cpp
@@ -0,0 +1,185 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "gtkmozembed.h"
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "nsStringAPI.h"
+#include "gtkmozembed_glue.cpp"
+
+int (*old_handler) (Display *, XErrorEvent *);
+
+int error_handler (Display *d, XErrorEvent *e)
+{
+  if ((e->error_code == BadWindow) || (e->error_code == BadDrawable))
+    {
+      XID resourceid = e->resourceid;
+      GdkWindow *window = gdk_window_lookup (resourceid);
+
+      if (window)
+        {
+          if (!g_dataset_get_data (window, "bonobo-error"))
+            {
+              g_dataset_set_data_full (window, "bonobo-error",
+                                       g_new (gint, 1),
+                                       (GDestroyNotify)g_free);
+
+              g_warning ("Error accessing window %ld", resourceid);
+            }
+        }
+      return 0;
+    }
+  else
+    {
+      return (*old_handler)(d, e);
+    }
+}
+
+void
+load_page(gpointer data);
+
+GtkWidget *embed = 0;
+GtkWidget *entry = 0;
+
+int
+main(int argc, char **argv)
+{
+  guint32 xid;
+
+  GtkWidget *window;
+  GtkWidget *hbox;
+  GtkWidget *vbox;
+  GtkWidget *button;
+
+  gtk_init(&argc, &argv);
+
+  static const GREVersionRange greVersion = {
+    "1.9a", PR_TRUE,
+    "2", PR_TRUE
+  };
+
+  char xpcomPath[PATH_MAX];
+
+  nsresult rv = GRE_GetGREPathWithProperties(&greVersion, 1, nsnull, 0,
+                                             xpcomPath, sizeof(xpcomPath));
+  if (NS_FAILED(rv)) {
+    fprintf(stderr, "Couldn't find a compatible GRE.\n");
+    return 1;
+  }
+
+  rv = XPCOMGlueStartup(xpcomPath);
+  if (NS_FAILED(rv)) {
+    fprintf(stderr, "Couldn't start XPCOM.");
+    return 1;
+  }
+
+  rv = GTKEmbedGlueStartup();
+  if (NS_FAILED(rv)) {
+    fprintf(stderr, "Couldn't find GTKMozEmbed symbols.");
+    return 1;
+  }
+
+  char *lastSlash = strrchr(xpcomPath, '/');
+  if (lastSlash)
+    *lastSlash = '\0';
+
+  gtk_moz_embed_set_path(xpcomPath);
+
+  old_handler = XSetErrorHandler (error_handler);
+
+  if (argc < 2) {
+    fprintf(stderr, "Usage: TestGtkEmbedChild WINDOW_ID\n");
+    exit(1);
+  }
+
+  xid = strtol (argv[1], (char **)NULL, 0);
+
+  if (xid == 0) {
+    fprintf(stderr, "Invalid window id '%s'\n", argv[1]);
+    exit(1);
+  }
+
+  window = gtk_plug_new(xid);
+
+  g_signal_connect(GTK_OBJECT(window), "destroy",
+                   G_CALLBACK(gtk_main_quit), NULL);
+
+  gtk_container_set_border_width(GTK_CONTAINER(window), 0);
+
+  vbox = gtk_vbox_new (FALSE, 0);
+  gtk_container_add(GTK_CONTAINER(window), vbox);
+  gtk_widget_show(vbox);
+
+  hbox = gtk_hbox_new (FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
+  gtk_widget_show (hbox);
+
+  entry = gtk_entry_new ();
+  gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
+  gtk_widget_show (entry);
+
+  button = gtk_button_new_with_label("Load");
+  gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
+  gtk_widget_show(button);
+
+  g_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(load_page), NULL);
+
+  embed = gtk_moz_embed_new();
+  gtk_box_pack_start(GTK_BOX(vbox), embed, TRUE, TRUE, 0);
+  gtk_widget_set_size_request(embed, 200, 200);
+  gtk_widget_show(embed);
+
+  gtk_widget_show(window);
+  
+  gtk_main();
+
+  fprintf(stderr, "exiting.\n");
+
+  return 0;
+}
+
+void
+load_page(gpointer data)
+{
+  gchar *text = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
+  g_print("load url %s\n", text);
+  gtk_moz_embed_load_url(GTK_MOZ_EMBED(embed), text);
+  g_free(text);
+}
diff --git a/embedding/browser/gtk/tests/TestGtkEmbedMDI.cpp b/embedding/browser/gtk/tests/TestGtkEmbedMDI.cpp
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/tests/TestGtkEmbedMDI.cpp
@@ -0,0 +1,142 @@
+/** simplemdi.c **/
+/*
+ * Sample code from "GNOME/GTK+ Programming Bible" by Arthur Griffith
+ * Modified by Kevin Gibbs (kgibbs@stanford.edu) to provide sample of
+ * GtkMozEmbed realization/unrealization crashes.
+ *
+ * To get a fatal crash, simply run the program, click on the "Mozilla"
+ * tab to display the MozEmbed widget, and then try to drag that MDI tab
+ * off to a new window.
+ * 
+ * Although this test might seem elaborate, it is really only a convenient
+ * to create a situation where the widget is realized, unrealized, and
+ * realized again at some point. (Dragging the MDI tab off to a new window
+ * causes all widgets to be unrealized in the old window, and then realized
+ * again in the new window.) 
+ */
+
+#include <gnome.h>
+#include "gtkmozembed.h"
+
+// Testing flags
+//
+
+// Define this flag to have the test program use the gtkmozembed widget.
+// Without this flag, mozilla is never loaded in the program, and a simple
+// widget is used in place of the mozembed widget.
+#define USE_MOZILLA_TEST
+
+// Define this flag to have a simpler test than the usual one. The normal
+// test builds a notebook inside of each MDI view, with one page being a label
+// and the other page being a browser widget. The simpler test does not
+// build a notebook and simply puts the browser widget in the MDI view itself.
+// Currently, this test is not very interesting, since for some reason all
+// the webshells just create and destroy themselves. (???)
+//#define SIMPLER_TEST
+
+// Define this flag to use a GnomePixmap instead of a GtkLabel as the
+// replacement for the gtkmozembed widget when USE_MOZILLA_TEST is
+// undefined. This is to stress test the program a bit more by providing a
+// replacement widget slightly more complex than GtkLabel.
+// (Has no effect when USE_MOZILLA_TEST is defined.)
+#define SAMPLE_PIXMAP
+
+
+gint eventDelete(GtkWidget *widget,
+        GdkEvent *event,gpointer data);
+gint eventDestroy(GtkWidget *widget,
+        GdkEvent *event,gpointer data);
+
+static void addChild(GtkObject *mdi,gchar *name);
+static GtkWidget *setLabel(GnomeMDIChild *child,
+        GtkWidget *currentLabel,gpointer data);
+static GtkWidget *createView(GnomeMDIChild *child,
+        gpointer data);
+
+int main(int argc,char *argv[])
+{
+    GtkObject *mdi;
+
+    gnome_init("simplemdi","1.0",argc,argv);
+    mdi = gnome_mdi_new("simplemdi","Simple MDI");
+    gtk_signal_connect(mdi,"destroy",
+            GTK_SIGNAL_FUNC(eventDestroy),NULL);
+
+    addChild(mdi,"First");
+    addChild(mdi,"Second");
+    addChild(mdi,"Third");
+    addChild(mdi,"Last");
+
+    gnome_mdi_set_mode(GNOME_MDI(mdi),GNOME_MDI_NOTEBOOK);
+    //gnome_mdi_open_toplevel(GNOME_MDI(mdi));
+
+    gtk_main();
+    exit(0);
+}
+static void addChild(GtkObject *mdi,gchar *name)
+{
+    GnomeMDIGenericChild *child;
+
+    child = gnome_mdi_generic_child_new(name);
+    gnome_mdi_add_child(GNOME_MDI(mdi),
+            GNOME_MDI_CHILD(child));
+
+    gnome_mdi_generic_child_set_view_creator(child,
+            createView,name);
+    gnome_mdi_generic_child_set_label_func(child,setLabel,
+            NULL);
+    gnome_mdi_add_view(GNOME_MDI(mdi),
+            GNOME_MDI_CHILD(child));
+}
+static GtkWidget *createView(GnomeMDIChild *child,
+        gpointer data)
+{
+#ifdef USE_MOZILLA_TEST
+    GtkWidget *browser = gtk_moz_embed_new();
+#else
+#ifndef SAMPLE_PIXMAP
+    GtkWidget *browser = gtk_label_new("lynx 0.01a");
+#else
+    /* Another example -- */
+    GtkWidget *browser =
+      gnome_pixmap_new_from_file("/usr/share/pixmaps/emacs.png");
+#endif /* SAMPLE_PIXMAP */
+#endif /* USE_MOZILLA_TEST */
+
+    GtkWidget *notebook = gtk_notebook_new();
+    char str[80];
+
+    sprintf(str,"View of the\n%s widget",(gchar *)data);
+
+#ifdef USE_MOZILLA_TEST
+    gtk_moz_embed_load_url(GTK_MOZ_EMBED(browser), "http://www.mozilla.org");
+#endif /* USE_MOZILLA_TEST */
+
+#ifndef SIMPLER_TEST
+    gtk_notebook_append_page(GTK_NOTEBOOK(notebook), gtk_label_new(str),
+			     gtk_label_new("Label"));
+    gtk_notebook_append_page(GTK_NOTEBOOK(notebook), browser,
+			     gtk_label_new("Mozilla"));
+    gtk_widget_show_all(notebook);
+    return (notebook);
+#else
+    gtk_widget_show(browser);
+    return (browser);
+#endif /* SIMPLER_TEST */
+}
+
+static GtkWidget *setLabel(GnomeMDIChild *child,
+        GtkWidget *currentLabel,gpointer data)
+{
+    if(currentLabel == NULL)
+        return(gtk_label_new(child->name));
+
+    gtk_label_set_text(GTK_LABEL(currentLabel),
+            child->name);
+    return(currentLabel);
+}
+gint eventDestroy(GtkWidget *widget,
+        GdkEvent *event,gpointer data) {
+    gtk_main_quit();
+    return(0);
+}
diff --git a/embedding/browser/gtk/tests/TestGtkEmbedNotebook.cpp b/embedding/browser/gtk/tests/TestGtkEmbedNotebook.cpp
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/tests/TestGtkEmbedNotebook.cpp
@@ -0,0 +1,86 @@
+#include <gtk/gtk.h>
+#include <gtkmozembed.h>
+#include <stdio.h>
+#include "nsStringAPI.h"
+#include "gtkmozembed_glue.cpp"
+
+int main(int argc, char *argv[])
+{
+	GtkWidget *window;
+	GtkWidget *label;
+	GtkWidget *mozembed;
+	GtkWidget *container;
+	char *url;
+
+	gtk_init(&argc, &argv);
+	
+        static const GREVersionRange greVersion = {
+                "1.9a", PR_TRUE,
+                "2", PR_TRUE
+        };
+
+        char xpcomPath[PATH_MAX];
+
+        nsresult rv =
+                GRE_GetGREPathWithProperties(&greVersion, 1, nsnull, 0,
+                                             xpcomPath, sizeof(xpcomPath));
+        if (NS_FAILED(rv)) {
+                fprintf(stderr, "Couldn't find a compatible GRE.\n");
+                return 1;
+        }
+
+        rv = XPCOMGlueStartup(xpcomPath);
+        if (NS_FAILED(rv)) {
+                fprintf(stderr, "Couldn't start XPCOM.");
+                return 1;
+        }
+
+        rv = GTKEmbedGlueStartup();
+        if (NS_FAILED(rv)) {
+                fprintf(stderr, "Couldn't find GTKMozEmbed symbols.");
+                return 1;
+        }
+
+        char *lastSlash = strrchr(xpcomPath, '/');
+        if (lastSlash)
+                *lastSlash = '\0';
+
+        gtk_moz_embed_set_path(xpcomPath);
+
+	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+	
+	container = gtk_notebook_new();
+	mozembed = gtk_moz_embed_new();
+	label = gtk_label_new("Can you see this message?\n"
+			      "Once you switch to mozembed page " 
+			      "you never see this message.");
+
+	g_signal_connect(GTK_OBJECT(mozembed), "destroy",
+	                 G_CALLBACK(gtk_main_quit),
+NULL);
+
+	gtk_container_add(GTK_CONTAINER(window), container);
+
+	gtk_notebook_append_page(GTK_NOTEBOOK(container),
+			label,
+			gtk_label_new("gtk label"));
+
+	gtk_notebook_append_page(GTK_NOTEBOOK(container),
+			mozembed,
+			gtk_label_new("mozembed"));
+
+
+
+
+	gtk_widget_set_size_request(window, 400, 300);
+	gtk_widget_show(mozembed);
+	gtk_widget_show(label);
+	gtk_widget_show_all(window);
+
+	url = (argc > 1) ? argv[1] : (char *)"localhost";
+	gtk_moz_embed_load_url(GTK_MOZ_EMBED(mozembed), url);
+
+	gtk_main();
+	
+	return 0;
+}
diff --git a/embedding/browser/gtk/tests/TestGtkEmbedSocket.cpp b/embedding/browser/gtk/tests/TestGtkEmbedSocket.cpp
new file mode 100644
--- /dev/null
+++ b/embedding/browser/gtk/tests/TestGtkEmbedSocket.cpp
@@ -0,0 +1,109 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Christopher Blizzard.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Christopher Blizzard <blizzard@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+GtkWidget *toplevel_window = 0;
+GtkWidget *button = 0;
+GtkWidget *vbox = 0;
+GtkWidget *gtk_socket = 0;
+
+void
+insert_mozilla(gpointer data);
+
+int
+main(int argc, char **argv)
+{
+  gtk_init(&argc, &argv);
+
+  toplevel_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+  g_signal_connect(GTK_OBJECT(toplevel_window), "destroy",
+                   G_CALLBACK(exit), NULL);
+
+  vbox = gtk_vbox_new(FALSE, 0);
+  gtk_container_add(GTK_CONTAINER(toplevel_window), vbox);
+  gtk_widget_show(vbox);
+
+  button = gtk_button_new_with_label("Insert Mozilla");
+
+  gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
+  gtk_widget_show(button);
+
+  g_signal_connect(GTK_OBJECT(button), "clicked",
+                   G_CALLBACK(insert_mozilla), NULL);
+
+  gtk_widget_show(toplevel_window);
+
+  gtk_main();
+
+  return 0;
+}
+
+void
+insert_mozilla(gpointer data)
+{
+  char buffer[20];
+  int pid;
+
+  if (gtk_socket)
+    return;
+
+  gtk_socket = gtk_socket_new();
+  gtk_box_pack_start(GTK_BOX(vbox), gtk_socket, TRUE, TRUE, 0);
+  gtk_widget_show(gtk_socket);
+
+  sprintf(buffer, "%#lx", GDK_WINDOW_XWINDOW(gtk_socket->window));
+
+  gdk_flush();
+
+  if ((pid = fork()) == 0) { /* child */
+    execl("./TestGtkEmbedChild", "./TestGtkEmbedChild", buffer, NULL);
+    fprintf(stderr, "can't exec child\n");
+    _exit(1);
+  }
+  else if (pid > 0) { /* parent */
+  }
+  else {
+    fprintf(stderr, "Can't fork.\n");
+  }
+}
diff --git a/toolkit/toolkit-makefiles.sh b/toolkit/toolkit-makefiles.sh
--- a/toolkit/toolkit-makefiles.sh
+++ b/toolkit/toolkit-makefiles.sh
@@ -547,16 +547,19 @@ MAKEFILES_embedding="
   embedding/browser/Makefile
   embedding/browser/activex/src/Makefile
   embedding/browser/activex/src/common/Makefile
   embedding/browser/activex/src/control/Makefile
   embedding/browser/activex/src/control_kicker/Makefile
   embedding/browser/activex/src/plugin/Makefile
   embedding/browser/build/Makefile
   embedding/browser/webBrowser/Makefile
+  embedding/browser/gtk/Makefile
+  embedding/browser/gtk/src/Makefile
+  embedding/browser/gtk/tests/Makefile
   embedding/components/Makefile
   embedding/components/appstartup/Makefile
   embedding/components/appstartup/src/Makefile
   embedding/components/build/Makefile
   embedding/components/commandhandler/Makefile
   embedding/components/commandhandler/public/Makefile
   embedding/components/commandhandler/src/Makefile
   embedding/components/find/Makefile
diff --git a/toolkit/library/Makefile.in b/toolkit/library/Makefile.in
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -80,6 +80,13 @@
 DEFINES += -DMOZ_ENABLE_GTK2
 endif
 
+# dependent libraries
+ifneq (,$(MOZ_ENABLE_GTK2))
+SHARED_LIBRARY_LIBS += \
+  $(DEPTH)/embedding/browser/gtk/src/$(LIB_PREFIX)gtkembedmoz.$(LIB_SUFFIX)
+DEFINES += -DMOZ_ENABLE_GTK2
+endif
+
 SHARED_LIBRARY_LIBS += \
 	$(DEPTH)/toolkit/xre/$(LIB_PREFIX)xulapp_s.$(LIB_SUFFIX) \
 	$(NULL)
diff --git a/toolkit/toolkit-tiers.mk b/toolkit/toolkit-tiers.mk
--- a/toolkit/toolkit-tiers.mk
+++ b/toolkit/toolkit-tiers.mk
@@ -223,6 +223,12 @@
 
 tier_platform_dirs += services/crypto/component
 
+ifndef BUILD_STATIC_LIBS
+ifneq (,$(MOZ_ENABLE_GTK2))
+tier_platform_dirs += embedding/browser/gtk
+endif
+endif
+
 tier_platform_dirs += startupcache
 
 ifdef APP_LIBXUL_STATICDIRS
