Logo Search packages:      
Sourcecode: galeon version File versions

GaleonWrapper.cpp

/*
 *  Copyright (C) 2000 Marco Pesenti Gritti
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "galeon-embed.h"
#include "galeon-debug.h"
#include "gul-string.h"
#include "GaleonWrapper.h"
#include "PrintProgressListener.h"
#include "mozilla-embed.h"
#include "EventContext.h"
#include "eel-gconf-extensions.h"
#include "galeon-embed-prefs.h"
#include "GaleonUtils.h"
#include "MozillaPrivate.h"
#include "GulString.h"

#include <gtkmozembed_internal.h>
#include <unistd.h>

#include <nsMemory.h>
#include <nsIInterfaceRequestorUtils.h>
#include <nsIContentViewer.h>
#include <nsIWebBrowserFind.h>
#include <nsIWebBrowserFocus.h>
#include <nsISHEntry.h>
#include <nsISHistoryInternal.h>
#include <nsIHistoryEntry.h>
#include <nsIWebBrowserPrint.h>
#include <nsIURI.h>
#include <nsIMarkupDocumentViewer.h>
#include <nsIDOMElement.h>
#include <nsIDOMNodeList.h>
#include <nsIDOMEventTarget.h>
#include <nsIDocShell.h>
#include <nsISHistory.h>
#include <nsIWebNavigation.h>
#include <nsIWebPageDescriptor.h>
#include <nsICacheEntryDescriptor.h>
#include <nsIDocCharset.h>
#include <nsIDOMMouseEvent.h>
#include <nsIDOMKeyEvent.h>
#include <nsIDOMNSUIEvent.h>
#include <nsIDOMNSEvent.h>
#include <nsIDOM3Document.h>
#include <nsIScriptSecurityManager.h>
#include <nsIServiceManager.h>
#include <nsIContentPolicy.h>
#include <nsIDOMDocumentView.h>
#include <nsIDOMAbstractView.h>
#include <nsNetCID.h>

#include <nsIDOMWindow2.h>
#include <nsIInterfaceRequestor.h>
#include <nsIClipboardCommands.h>
#include <nsIDOMDocumentStyle.h>
#include <nsIDocShellTreeItem.h>
#include <nsIDocShellTreeNode.h>
#include <nsIDOMPopupBlockedEvent.h>
#include <nsIDOMNSDocument.h>
#include <nsIDOMHTMLDocument.h>
#include <nsIDOMHTMLCollection.h>
#include <nsIDOMHTMLElement.h>
#include <nsIDOMHTMLImageElement.h>
#include <nsIDOMHTMLFormElement.h>
#include <nsIDOMHTMLAnchorElement.h>
#include <nsIDOMHTMLLinkElement.h>
#include <nsIDOMHTMLMetaElement.h>
#include <nsIDOMHTMLInputElement.h>
#include <nsIDOMHTMLTextAreaElement.h>
#include <nsICacheService.h>
#include <nsICacheSession.h>
#include <nsIDOMLocation.h>
#include <nsTime.h>
#include <nsITransportSecurityInfo.h>
#include <nsIConsoleService.h>
#include <nsIConsoleMessage.h>
#include <nsCompatibility.h>

#ifdef HAVE_MOZILLA_PSM
# include <nsISSLStatus.h>
# include <nsISSLStatusProvider.h>
# include <nsICertificateDialogs.h>
# include <nsIX509Cert.h>
# include <nsISecureBrowserUI.h>
#endif

template<class T>
static nsresult sProcessLinkNode(nsIDOMNode *node,
                         nsIDOMDocument *doc,
                         GList **ret);

static void
PopTargetDocument_WeakRef_cb (GaleonWrapper *wrapper,
                        GaleonEmbedEvent *event);

GaleonWrapper::GaleonWrapper () :
                  mFaviconEventListener(new GDOMEventListener())
                  ,mPopupEventListener(new GDOMPopupEventListener())
                  ,mContextMenuListenerBubble(new GDOMContextMenuListener())
                  ,mContextMenuListenerCapture(new GDOMContextMenuListener())
                  ,mModalAlertListener(new GDOMModalAlertEventListener)
                  ,mCurrentEvent(NULL)
{
}

GaleonWrapper::~GaleonWrapper ()
{
}

static nsresult
GetDOMEventTarget (nsIWebBrowser* aWebBrowser, nsIDOMEventTarget** aTarget)
{
      nsCOMPtr<nsIDOMWindow> domWin;
      aWebBrowser->GetContentDOMWindow (getter_AddRefs(domWin));
      NS_ENSURE_TRUE (domWin, NS_ERROR_FAILURE);

      nsCOMPtr<nsIDOMWindow2> domWin2 (do_QueryInterface (domWin));
      NS_ENSURE_TRUE (domWin2, NS_ERROR_FAILURE);
      
      return domWin2->GetWindowRoot (aTarget);
}

nsresult GaleonWrapper::Init (GtkMozEmbed *mozembed)
{
      nsresult rv;
      /* Dont redo intialisation if we have already run it */
      if (mWebBrowser) return NS_OK;

      gtk_moz_embed_get_nsIWebBrowser (mozembed,
                               getter_AddRefs(mWebBrowser));
      if (!mWebBrowser) return NS_ERROR_FAILURE;

      
      nsCOMPtr<nsIDOMWindow> DOMWindow;
      mWebBrowser->GetContentDOMWindow (getter_AddRefs (DOMWindow));

      /* This will instantiate an about:blank doc if necessary, but don't
       * initialize for mozilla XUL dialogs, it breaks them */
      if (!(gtk_moz_embed_get_chrome_mask (mozembed) & GTK_MOZ_EMBED_FLAG_OPENASCHROME))
      {
            nsCOMPtr<nsIDOMDocument> domDocument;
            rv = DOMWindow->GetDocument (getter_AddRefs (domDocument));
            NS_ENSURE_SUCCESS (rv, rv);
      }

      // set up favicon listener
      mFaviconEventListener->Init (GALEON_EMBED(mozembed));
      rv = ::GetDOMEventTarget (mWebBrowser, getter_AddRefs(mEventTarget));
      NS_ENSURE_SUCCESS (rv, rv);

      rv = mEventTarget->AddEventListener(NS_LITERAL_STRING("DOMLinkAdded"),
                                          mFaviconEventListener, PR_FALSE);
      if (NS_FAILED(rv)) g_warning ("AddFaviconEventListener failed!");

      // set up popup block listener
      mPopupEventListener->Init(GALEON_EMBED(mozembed));
      rv = mEventTarget->AddEventListener(NS_LITERAL_STRING("DOMPopupBlocked"),
                                    mPopupEventListener, PR_FALSE);
      if (NS_FAILED(rv)) g_warning ("AddPopupEventListener failed!");

      // set up popup block listener (capture listener)
      mContextMenuListenerCapture->Init(GALEON_EMBED(mozembed), PR_TRUE);
      rv = mEventTarget->AddEventListener(NS_LITERAL_STRING("contextmenu"),
                                  mContextMenuListenerCapture, PR_TRUE);
      if (NS_FAILED(rv)) g_warning ("AddContextMenuListener failed!");

      // set up popup block listener (bubble listener)
      mContextMenuListenerBubble->Init(GALEON_EMBED(mozembed), PR_FALSE);
      rv = mEventTarget->AddEventListener(NS_LITERAL_STRING("contextmenu"),
                                  mContextMenuListenerBubble, PR_FALSE );
      if (NS_FAILED(rv)) g_warning ("AddContextMenuListener2 failed!");
      
      // setup modal alert listener
      mModalAlertListener->Init (GALEON_EMBED (mozembed));
      rv = mEventTarget->AddEventListener(NS_LITERAL_STRING("DOMWillOpenModalDialog"),
                                  mModalAlertListener, PR_TRUE);
      if (NS_FAILED(rv)) g_warning ("Add DOMWillOpenModalDialog failed!");

      rv = mEventTarget->AddEventListener(NS_LITERAL_STRING("DOMModalDialogClosed"),
                                  mModalAlertListener, PR_TRUE);
      if (NS_FAILED(rv)) g_warning ("Add DOMModalDialogClosed failed!");


#ifdef HAVE_MOZILLA_PSM
      /* FIXME: mozilla sucks! nsWebBrowser already has an instance of this,
       * but we cannot get to it!
       * See https://bugzilla.mozilla.org/show_bug.cgi?id=94974,
       * also see http://bugzilla.gnome.org/show_bug.cgi?id=164670
       */
      mSecurityInfo = do_CreateInstance("@galeon.sf.net/hacks/secure-browser-ui;1");
      if (mSecurityInfo)
      {
            mSecurityInfo->Init (DOMWindow);
      }
      else
      {
            g_warning ("Failed to instantiate nsISecureBrowserUI!\n");
      }
#endif

      return NS_OK;
}

nsresult GaleonWrapper::GetContentViewer (nsIContentViewer **aViewer)
{
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIDocShell> ourDocShell(do_GetInterface(mWebBrowser));
      NS_ENSURE_TRUE (ourDocShell, NS_ERROR_FAILURE);

      return ourDocShell->GetContentViewer(aViewer);
}

nsresult GaleonWrapper::Print (nsIPrintSettings *options, PRBool preview, GtkWindow *parent)
{
      nsresult rv;

      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIWebBrowserPrint> print(do_GetInterface(mWebBrowser));
      NS_ENSURE_TRUE (print, NS_ERROR_FAILURE);

      if (!preview)
      {
            GPrintListener *listener = new GPrintListener(print, options, parent);
            rv = print->Print (options, listener);
      }
      else
      {
            rv = print->PrintPreview(options, nsnull, nsnull);
      }

      return rv;
}

nsresult GaleonWrapper::PrintPreviewClose (void)
{
      nsresult rv;
      PRBool isPreview = PR_FALSE;

      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIWebBrowserPrint> print(do_GetInterface(mWebBrowser));
      NS_ENSURE_TRUE (print, NS_ERROR_FAILURE);

      rv = print->GetDoingPrintPreview(&isPreview);
      if (NS_SUCCEEDED (rv) && isPreview == PR_TRUE)
      {
            rv = print->ExitPrintPreview();
      }

      return rv;
}

nsresult GaleonWrapper::PrintPreviewNumPages (int *numPages)
{
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIWebBrowserPrint> print(do_GetInterface(mWebBrowser));
      NS_ENSURE_TRUE (print, NS_ERROR_FAILURE);

      return print->GetPrintPreviewNumPages(numPages);
}

nsresult GaleonWrapper::PrintPreviewNavigate(PRInt16 navType, PRInt32 pageNum)
{
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIWebBrowserPrint> print(do_GetInterface(mWebBrowser));
      NS_ENSURE_TRUE (print, NS_ERROR_FAILURE);

      return print->PrintPreviewNavigate(navType, pageNum);
}

nsresult GaleonWrapper::GetPrintSettings (nsIPrintSettings **options)
{
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIWebBrowserPrint> print(do_GetInterface(mWebBrowser));
      NS_ENSURE_TRUE (print, NS_ERROR_FAILURE);

      return print->GetGlobalPrintSettings(options);
}

nsresult GaleonWrapper::GetSHistory (nsISHistory **aSHistory)
{
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIWebNavigation> ContentNav = do_QueryInterface (mWebBrowser);
      NS_ENSURE_TRUE (ContentNav, NS_ERROR_FAILURE);

      nsCOMPtr<nsISHistory> SessionHistory;
      ContentNav->GetSessionHistory (getter_AddRefs (SessionHistory));
      NS_ENSURE_TRUE (SessionHistory, NS_ERROR_FAILURE);

      *aSHistory = SessionHistory.get();
      NS_IF_ADDREF (*aSHistory);

      return NS_OK;
}

nsresult GaleonWrapper::Destroy ()
{
      mEventTarget->RemoveEventListener(NS_LITERAL_STRING("DOMLinkAdded"),
                                mFaviconEventListener, PR_FALSE);
      mEventTarget->RemoveEventListener(NS_LITERAL_STRING("DOMPopupBlocked"),
                                mPopupEventListener, PR_FALSE);
      mEventTarget->RemoveEventListener(NS_LITERAL_STRING("contextmenu"),
                                mContextMenuListenerBubble, PR_FALSE);
      mEventTarget->RemoveEventListener(NS_LITERAL_STRING("contextmenu"),
                                mContextMenuListenerCapture, PR_TRUE);
      mEventTarget->RemoveEventListener(NS_LITERAL_STRING("DOMWillOpenModalDialog"),
                                mModalAlertListener, PR_TRUE);
      mEventTarget->RemoveEventListener(NS_LITERAL_STRING("DOMModalDialogClosed"),
                                mModalAlertListener, PR_TRUE);

      if (mCurrentEvent)
      {
            g_object_weak_unref (G_OBJECT (mCurrentEvent),
                             (GWeakNotify)PopTargetDocument_WeakRef_cb,
                             this);
            mCurrentEvent = NULL;
      }

      mEventTarget = nsnull;
            mWebBrowser = nsnull;
      
      return NS_OK;
}

nsresult GaleonWrapper::GoToHistoryIndex (PRInt16 index)
{
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIWebNavigation> ContentNav = do_QueryInterface (mWebBrowser);
      NS_ENSURE_TRUE (ContentNav, NS_ERROR_FAILURE);

      return ContentNav->GotoIndex (index);
}

nsresult GaleonWrapper::SetZoom (float aZoom)
{
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIContentViewer> contentViewer; 
      GetContentViewer (getter_AddRefs(contentViewer));
      NS_ENSURE_TRUE (contentViewer, NS_ERROR_FAILURE);

      nsCOMPtr<nsIMarkupDocumentViewer> mdv = do_QueryInterface(contentViewer);
      NS_ENSURE_TRUE (mdv, NS_ERROR_FAILURE);

      return mdv->SetTextZoom (aZoom);
}

nsresult GaleonWrapper::GetZoom (float *aZoom)
{
      nsCOMPtr<nsIContentViewer> contentViewer;
      GetContentViewer (getter_AddRefs (contentViewer));
      NS_ENSURE_TRUE (contentViewer, NS_ERROR_FAILURE);

      nsCOMPtr<nsIMarkupDocumentViewer> mdv = do_QueryInterface(contentViewer);
      NS_ENSURE_TRUE (mdv, NS_ERROR_FAILURE);

      return mdv->GetTextZoom (aZoom);
}

nsresult GaleonWrapper::FocusActivate ()
{
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIWebBrowserFocus> focus = do_GetInterface(mWebBrowser);
      NS_ENSURE_TRUE (focus, NS_ERROR_FAILURE);

      return focus->Activate();
}

nsresult GaleonWrapper::FocusDeactivate ()
{
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIWebBrowserFocus> focus = do_GetInterface(mWebBrowser);
      NS_ENSURE_TRUE (focus, NS_ERROR_FAILURE);

      return focus->Deactivate();
}


nsresult GaleonWrapper::GetFocusedDOMWindow (nsIDOMWindow **aDOMWindow)
{
      nsresult rv;
      
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIWebBrowserFocus> focus = do_GetInterface(mWebBrowser);
      NS_ENSURE_TRUE (focus, NS_ERROR_FAILURE);

      rv = focus->GetFocusedWindow (aDOMWindow);
      if (NS_FAILED(rv))
            rv = mWebBrowser->GetContentDOMWindow (aDOMWindow);
      return rv;
}

nsresult GaleonWrapper::GetDOMWindow (nsIDOMWindow **aDOMWindow)
{
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      return mWebBrowser->GetContentDOMWindow (aDOMWindow);
}

nsresult GaleonWrapper::GetDOMDocument (nsIDOMDocument **aDOMDocument)
{
      nsresult rv;

      /* Use the current target document */
      if (mTargetDocument)
      {
            *aDOMDocument = mTargetDocument.get();

            NS_IF_ADDREF(*aDOMDocument);

            return NS_OK;
      }

      /* Use the focused document */
      nsCOMPtr<nsIDOMWindow> DOMWindow;
      rv = GetFocusedDOMWindow (getter_AddRefs(DOMWindow));
      if (NS_SUCCEEDED(rv) && DOMWindow)
      {
            return DOMWindow->GetDocument (aDOMDocument);
      }

      /* Use the main document */
      return GetMainDOMDocument (aDOMDocument);
}

nsresult GaleonWrapper::GetMainDOMDocument (nsIDOMDocument **aDOMDocument)
{
      nsCOMPtr<nsIContentViewer> contentViewer; 
      GetContentViewer (getter_AddRefs(contentViewer));
      NS_ENSURE_TRUE (contentViewer, NS_ERROR_FAILURE);

      return contentViewer->GetDOMDocument (aDOMDocument);
}

nsresult GaleonWrapper::GetSHInfo (PRInt32 *count, PRInt32 *index)
{
      nsCOMPtr<nsISHistory> SessionHistory;
      GetSHistory (getter_AddRefs(SessionHistory));
      NS_ENSURE_TRUE (SessionHistory, NS_ERROR_FAILURE);

      SessionHistory->GetCount (count);
      SessionHistory->GetIndex (index);   

      return NS_OK;
}

nsresult GaleonWrapper::GetSHTitleAtIndex (PRInt32 index, PRUnichar **title)
{
      nsresult rv;

      nsCOMPtr<nsISHistory> SessionHistory;
      GetSHistory (getter_AddRefs(SessionHistory));
      NS_ENSURE_TRUE (SessionHistory, NS_ERROR_FAILURE);

      nsCOMPtr<nsIHistoryEntry> he;
      SessionHistory->GetEntryAtIndex (index, PR_FALSE,
                               getter_AddRefs (he));
      NS_ENSURE_TRUE (he, NS_ERROR_FAILURE);

      rv = he->GetTitle (title);
      NS_ENSURE_SUCCESS (rv, rv);

      return NS_OK;
}

nsresult GaleonWrapper::GetSHUrlAtIndex (PRInt32 index, nsACString &url)
{
      nsresult rv;

      nsCOMPtr<nsISHistory> SessionHistory;
      GetSHistory (getter_AddRefs(SessionHistory));
      NS_ENSURE_TRUE (SessionHistory, NS_ERROR_FAILURE);

      nsCOMPtr<nsIHistoryEntry> he;
      SessionHistory->GetEntryAtIndex (index, PR_FALSE,
                               getter_AddRefs (he));
      NS_ENSURE_TRUE (he, NS_ERROR_FAILURE);

      nsCOMPtr<nsIURI> uri;
      he->GetURI (getter_AddRefs(uri));
      NS_ENSURE_TRUE (uri, NS_ERROR_FAILURE);

      rv = uri->GetSpec(url);
      NS_ENSURE_SUCCESS (rv, rv);

      return NS_OK;
}

nsresult GaleonWrapper::FindSetProperties (const PRUnichar *search_string,
                                 PRBool case_sensitive,
                                 PRBool wrap_around)
{
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIWebBrowserFind> finder (do_GetInterface(mWebBrowser));
      
      finder->SetSearchString (search_string);
      finder->SetMatchCase (case_sensitive);
      finder->SetWrapFind (wrap_around);
      return NS_OK;
}

nsresult GaleonWrapper::Find (PRBool backwards,
                        PRBool *didFind)
{
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIWebBrowserFind> finder (do_GetInterface(mWebBrowser));
      NS_ENSURE_TRUE (finder, NS_ERROR_FAILURE);

      finder->SetFindBackwards (backwards);

      return finder->FindNext(didFind);
}


#ifdef HAVE_GTKMOZEMBED_BROKEN_RELOAD
/* Workaround for broken reload with frames, see mozilla bug
 * http://bugzilla.mozilla.org/show_bug.cgi?id=246392
 */
nsresult GaleonWrapper::ReloadPage (GtkMozEmbedReloadFlags aReloadFlags)
{
      nsresult rv;

      nsCOMPtr<nsISHistory> sessionHistory;
      rv = GetSHistory (getter_AddRefs (sessionHistory));
      NS_ENSURE_SUCCESS (rv, rv);

      nsCOMPtr<nsIWebNavigation> wn = do_QueryInterface (sessionHistory);

      if (!wn)
      {
            wn = do_QueryInterface (mWebBrowser);
      }

      if (!wn) return NS_ERROR_FAILURE;
      
      PRUint32 reloadFlags = 0;
      switch (aReloadFlags)
      {
      case GTK_MOZ_EMBED_FLAG_RELOADNORMAL: break;
      case GTK_MOZ_EMBED_FLAG_RELOADBYPASSPROXYANDCACHE:
            reloadFlags = nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE | 
                  nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY;
            break;
      case GTK_MOZ_EMBED_FLAG_RELOADCHARSETCHANGE:
            reloadFlags = nsIWebNavigation::LOAD_FLAGS_CHARSET_CHANGE;
            break;
      case GTK_MOZ_EMBED_FLAG_RELOADBYPASSCACHE:
      case GTK_MOZ_EMBED_FLAG_RELOADBYPASSPROXY:
            g_return_val_if_reached (NS_ERROR_FAILURE);
            break;
      }

      return wn->Reload (reloadFlags);
}
#endif

/* Don't use the Session History to reload a view source page,
 * it doesn't work:
 *
 * http://bugzilla.gnome.org/show_bug.cgi?id=152547
 */
nsresult GaleonWrapper::ReloadViewSourcePage()
{
      nsresult rv;

      nsCOMPtr<nsISHistory> sessionHistory;
      rv = GetSHistory (getter_AddRefs (sessionHistory));
      NS_ENSURE_SUCCESS (rv, rv);

      nsCOMPtr<nsIWebNavigation> wn = do_QueryInterface (mWebBrowser);
      NS_ENSURE_TRUE (wn, NS_ERROR_FAILURE);

      PRUint32 reloadFlags = nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE | 
                           nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY;
      return wn->Reload (reloadFlags);
}

nsresult GaleonWrapper::ReloadFrame()
{
      nsresult rv;

      nsCOMPtr<nsIDOMWindow> DOMWindow;
      rv = GetFocusedDOMWindow (getter_AddRefs(DOMWindow));
      NS_ENSURE_SUCCESS (rv, rv);

      nsCOMPtr<nsIDocShell> docshell = do_GetInterface (mWebBrowser);
      NS_ENSURE_TRUE (docshell, NS_ERROR_FAILURE);

      nsCOMPtr<nsIWebNavigation> wn = do_QueryInterface (docshell);
      NS_ENSURE_TRUE (wn, NS_ERROR_FAILURE);

      rv = wn->Reload (nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE |
                   nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY);
      NS_ENSURE_SUCCESS (rv, rv);
      
      return NS_OK;
}

nsresult GaleonWrapper::LoadDocument(nsISupports *aPageDescriptor,
                             PRUint32 aDisplayType)
{
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIDocShell> ds = do_GetInterface (mWebBrowser);
      NS_ENSURE_TRUE (ds, NS_ERROR_FAILURE);

      nsCOMPtr<nsIWebPageDescriptor> wpd = do_QueryInterface (ds);
      NS_ENSURE_TRUE (wpd, NS_ERROR_FAILURE);

      return wpd->LoadPage(aPageDescriptor, aDisplayType);
}

nsresult GaleonWrapper::GetPageDescriptor(nsISupports **aPageDescriptor)
{
      nsCOMPtr<nsIDocShell> ds = do_GetInterface (mWebBrowser);
      NS_ENSURE_TRUE (ds, NS_ERROR_FAILURE);

      nsCOMPtr<nsIWebPageDescriptor> wpd = do_QueryInterface (ds);
      NS_ENSURE_TRUE (wpd, NS_ERROR_FAILURE);

      return wpd->GetCurrentDescriptor(aPageDescriptor);
}

nsresult GaleonWrapper::GetMainDocumentUrl (nsACString &url)
{
      nsresult rv;

      nsCOMPtr<nsIDOMDocument> DOMDocument;

      rv = GetMainDOMDocument (getter_AddRefs(DOMDocument));
      if (NS_FAILED(rv) || !DOMDocument) return NS_ERROR_FAILURE;

      nsCOMPtr<nsIDOM3Document> doc = do_QueryInterface(DOMDocument);
      NS_ENSURE_TRUE (doc, NS_ERROR_FAILURE);

      GulString docURI;
      rv = doc->GetDocumentURI (docURI);
      NS_ENSURE_SUCCESS (rv, rv);

      NS_UTF16ToCString (docURI, NS_CSTRING_ENCODING_UTF8, url);
      return NS_OK;
}

nsresult GaleonWrapper::GetDocumentUrl (nsACString &url)
{
        nsresult rv;

        nsCOMPtr<nsIDOMDocument> DOMDocument;

        rv = GetDOMDocument (getter_AddRefs(DOMDocument));
        if (NS_FAILED(rv) || !DOMDocument) return NS_ERROR_FAILURE;

      nsCOMPtr<nsIDOM3Document> doc = do_QueryInterface(DOMDocument);
      NS_ENSURE_TRUE (doc, NS_ERROR_FAILURE);

      GulString docURI;
      rv = doc->GetDocumentURI (docURI);
      NS_ENSURE_SUCCESS (rv, rv);

      NS_UTF16ToCString (docURI, NS_CSTRING_ENCODING_UTF8, url);
      return NS_OK;
}

nsresult  GaleonWrapper::ClearHistory ()
{
      nsCOMPtr<nsISHistory> SessionHistory;
      GetSHistory (getter_AddRefs(SessionHistory));
      NS_ENSURE_TRUE (SessionHistory, NS_ERROR_FAILURE);

      PRInt32 count, index;
      SessionHistory->GetCount (&count);
      SessionHistory->GetIndex (&index);
      if (count <= 1) return NS_OK;
      
      /* Save the current entry */
      nsCOMPtr<nsIHistoryEntry> he;
      SessionHistory->GetEntryAtIndex (index, PR_FALSE,
                               getter_AddRefs (he));
      NS_ENSURE_TRUE (he, NS_ERROR_FAILURE);

      nsCOMPtr<nsISHEntry> she = do_QueryInterface (he);
      NS_ENSURE_TRUE (she, NS_ERROR_FAILURE);

      /* Clear the history */
      SessionHistory->PurgeHistory (count);

      /* Put the current entry back in */
      nsCOMPtr<nsISHistoryInternal> hi = do_QueryInterface (SessionHistory);
      NS_ENSURE_TRUE (hi, NS_ERROR_FAILURE);

      return hi->AddEntry (she, PR_TRUE);
}

nsresult  GaleonWrapper::CopyHistoryTo (GaleonWrapper *dest, 
                              PRBool back_history, 
                              PRBool forward_history, 
                              PRBool set_current)
{
      nsresult rv;
      
      nsCOMPtr<nsISHistory> h_src;
      GetSHistory (getter_AddRefs(h_src));
      NS_ENSURE_TRUE (h_src, NS_ERROR_FAILURE);

      PRInt32 count, index;
      h_src->GetCount (&count);
      h_src->GetIndex (&index);

      nsCOMPtr<nsISHistory> h_dest;
      dest->GetSHistory (getter_AddRefs (h_dest));
      NS_ENSURE_TRUE (h_dest, NS_ERROR_FAILURE);

      nsCOMPtr<nsISHistoryInternal> hi_dest = do_QueryInterface (h_dest);
      NS_ENSURE_TRUE (hi_dest, NS_ERROR_FAILURE);

      if (count)
      {
            nsCOMPtr<nsIHistoryEntry> he;
            nsCOMPtr<nsISHEntry> she;

            for (PRInt32 i = (back_history ? 0 : index + 1); 
                 i < (forward_history ? count : index + 1);
                 i++) 
            {
                  rv = h_src->GetEntryAtIndex (i, PR_FALSE,
                                         getter_AddRefs (he));
                  NS_ENSURE_SUCCESS (rv, rv);

                  she = do_QueryInterface (he);
                  NS_ENSURE_TRUE (she, NS_ERROR_FAILURE);
                  
                  rv = hi_dest->AddEntry (she, PR_TRUE);
                  NS_ENSURE_SUCCESS (rv, rv);
            }
            
            if (set_current)
            {
                  nsCOMPtr<nsIWebNavigation> wn_dest = do_QueryInterface (dest->mWebBrowser);
                  NS_ENSURE_TRUE (wn_dest, NS_ERROR_FAILURE);
                  
                  rv = wn_dest->GotoIndex(index);
                  if (!NS_SUCCEEDED(rv)) return NS_ERROR_FAILURE;
            }
      }

      return NS_OK;
}

nsresult GaleonWrapper::SetForcedEncoding (const char *encoding)
{
      nsCOMPtr<nsIContentViewer> contentViewer;
      GetContentViewer (getter_AddRefs(contentViewer));
      NS_ENSURE_TRUE (contentViewer, NS_ERROR_FAILURE);

      nsCOMPtr<nsIMarkupDocumentViewer> mdv = do_QueryInterface(contentViewer);
      NS_ENSURE_TRUE (mdv, NS_ERROR_FAILURE);

      return mdv->SetForceCharacterSet (GulDependentCString (encoding));
}

nsresult GaleonWrapper::GetForcedEncoding (nsACString &encoding)
{
      nsCOMPtr<nsIContentViewer> contentViewer;
      GetContentViewer (getter_AddRefs(contentViewer));
      NS_ENSURE_TRUE (contentViewer, NS_ERROR_FAILURE);

      nsCOMPtr<nsIMarkupDocumentViewer> mdv = do_QueryInterface(contentViewer);
      NS_ENSURE_TRUE (mdv, NS_ERROR_FAILURE);

      return mdv->GetForceCharacterSet (encoding);
}

nsresult GaleonWrapper::GetEncoding (nsACString &encoding)
{
      NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIDocCharset> docCharset = do_GetInterface (mWebBrowser);
      NS_ENSURE_TRUE (docCharset, NS_ERROR_FAILURE);

      char * charset;
      docCharset->GetCharset (&charset);
      encoding = charset;
      nsMemory::Free (charset);

      return NS_OK;
}

nsresult GaleonWrapper::CanCutSelection(PRBool *rv)
{
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIClipboardCommands> clipboard (do_GetInterface(mWebBrowser));
      return clipboard->CanCutSelection (rv);
}

nsresult GaleonWrapper::CanCopySelection(PRBool *rv)
{
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIClipboardCommands> clipboard (do_GetInterface(mWebBrowser));
      return clipboard->CanCopySelection (rv);
}

nsresult GaleonWrapper::CanPaste(PRBool *rv)
{
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIClipboardCommands> clipboard (do_GetInterface(mWebBrowser));
      return clipboard->CanPaste (rv);
}

nsresult GaleonWrapper::CutSelection(void)
{
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIClipboardCommands> clipboard (do_GetInterface(mWebBrowser));
      return clipboard->CutSelection ();
}

nsresult GaleonWrapper::CopySelection(void)
{
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIClipboardCommands> clipboard (do_GetInterface(mWebBrowser));
      return clipboard->CopySelection ();
}

nsresult GaleonWrapper::Paste(void)
{
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIClipboardCommands> clipboard (do_GetInterface(mWebBrowser));
      return clipboard->Paste ();
}

nsresult GaleonWrapper::GetStyleSheets(nsIDOMStyleSheetList** list)
{
      nsCOMPtr<nsIDOMDocument> doc;
      GetDOMDocument(getter_AddRefs(doc));
      NS_ENSURE_TRUE (doc, NS_ERROR_FAILURE);

      nsCOMPtr<nsIDOMDocumentStyle> docstyle(do_QueryInterface(doc));
      NS_ENSURE_TRUE (docstyle, NS_ERROR_FAILURE);

      return docstyle->GetStyleSheets(list);
}

nsresult GaleonWrapper::LoadOverrideStyleSheet(char *css,
                                     nsIStyleSheet **aStyleSheet)
{
      nsresult rv;

      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIURI> uri;
      rv = GaleonUtils::NewURI(getter_AddRefs(uri), GulCString (css));
      NS_ENSURE_SUCCESS (rv, rv);

      /* Get the doc shell */
      nsCOMPtr<nsIDocShell> docShell = do_GetInterface (mWebBrowser);
      NS_ENSURE_TRUE (docShell, NS_ERROR_FAILURE);

      return MozillaPrivate::LoadOverrideStyleSheet (docShell, uri, aStyleSheet);
}

nsresult GaleonWrapper::RemoveOverrideStyleSheet(nsIStyleSheet *remove)
{
      nsCOMPtr<nsIDocShell> docShell = do_GetInterface (mWebBrowser);
      NS_ENSURE_TRUE (docShell, NS_ERROR_FAILURE);

      return MozillaPrivate::RemoveOverrideStyleSheet (docShell, remove);
}

nsresult GaleonWrapper::GetLinkInterfaceItems (GList **list)
{
#ifdef NOT_PORTED
      nsresult rv;
      PRUint32 links_count;

      /* we accept these rel=.. elements, specified by the w3c */
      const gchar *rel_types[] = {
            "START", "NEXT", "PREV", "PREVIOUS", "CONTENTS", "TOC", "INDEX",
            "GLOSSARY", "COPYRIGHT", "CHAPTER",  "SECTION",
            "SUBSECTION", "APPENDIX", "HELP", "TOP", "SEARCH", "MADE",
            "BOOKMARK", "HOME",
            NULL /* terminator, must be last */
      };

      nsCOMPtr<nsIDOMDocument> DOMDocument;
      rv = GetMainDOMDocument (getter_AddRefs(DOMDocument));
      if (NS_FAILED(rv) || !DOMDocument) return NS_ERROR_FAILURE;

      /* get list of link elements*/
      NS_NAMED_LITERAL_STRING(strname, "LINK");

      nsCOMPtr<nsIDOMNodeList> links;
      rv = aDOMDocument->GetElementsByTagName (strname, 
                                         getter_AddRefs (links));
      if (NS_FAILED (rv)) return NS_ERROR_FAILURE;

      rv = links->GetLength (&links_count);
      if (NS_FAILED (rv)) return NS_ERROR_FAILURE;

      for (PRUint32 i = 0; i < links_count; i++)
      {
            /* get to the link element */
            nsCOMPtr<nsIDOMNode> link;
            rv = links->Item (i, getter_AddRefs (link));
            if (NS_FAILED (rv)) return NS_ERROR_FAILURE;

            nsCOMPtr<nsIDOMElement> linkElement;
            linkElement = do_QueryInterface (aLink);
            if (!linkElement) return NS_ERROR_FAILURE;

            /* get rel=.. element */
            NS_NAMED_LITERAL_STRING(attr_rel, "rel");
            nsAutoString value;
            linkElement->GetAttribute (attr_rel, value);

            if (value.IsEmpty())
            {
                  NS_NAMED_LITERAL_STRING(attr_rev, "rev");
                  linkElement->GetAttribute (attr_rev, value);
                  if (value.IsEmpty()) continue;
            }

            nsCString relstr = NS_ConvertUCS2toUTF8(value);
            ToUpperCase(relstr);

            /* check for elements we want */
            for (gint j = 0; (rel_types[j] != NULL); j++)
            {
                  if (strcmp (relstr.get(), rel_types[j]) == 0)
                  {
                        /* found one! */
                        LinkInterfaceItem *lti =
                              g_new0 (LinkInterfaceItem, 1);

                        /* fill in struct */
                        lti->type = (LinkInterfaceItemType) j;

                        /* get href=.. element */
                        NS_NAMED_LITERAL_STRING(attr_href, "href");
                        nsAutoString value;
                        linkElement->GetAttribute (attr_href, value);

                        if (value.IsEmpty())
                        {
                              g_free (lti);
                              continue;
                        }

                        /* resolve uri */
                        nsCOMPtr<nsIDOM3Document> doc = 
                              do_QueryInterface (aDOMDocument);
                        if(!doc) return NS_ERROR_FAILURE;

                        nsAutoString spec;
                        doc->GetDocumentURI (spec);

                        nsCOMPtr<nsIURI> uri;
                        GaleonUtils::NewURI (getter_AddRefs (docUri), spec);

                        const nsACString &link = NS_ConvertUCS2toUTF8(value);
                        nsCAutoString href;
                        rv = uri->Resolve (link, href);
                        if (NS_FAILED (rv)) return NS_ERROR_FAILURE;
                        lti->href = g_strdup (href.get());
            
                        /* append to list of items */
                        *list = g_list_append (*list, lti);
            
                        /* get optional title=... element */
                        NS_NAMED_LITERAL_STRING(attr_title, "title");
                        linkElement->GetAttribute (attr_title, value);
                        if (value.IsEmpty()) continue;

                        const nsACString &title = NS_ConvertUCS2toUTF8 (value);
                        lti->title = gul_string_strip_newline (PromiseFlatCString(title).get());
                  }
            }
      }
#endif
      return NS_OK;
}

nsresult GaleonWrapper::GetRealURL (nsACString &ret)
{
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIWebNavigation> ContentNav = do_QueryInterface (mWebBrowser);
      NS_ENSURE_TRUE (ContentNav, NS_ERROR_FAILURE);

      nsCOMPtr<nsIURI> uri;
      ContentNav->GetCurrentURI (getter_AddRefs(uri));
      NS_ENSURE_TRUE (uri, NS_ERROR_FAILURE);

      return uri->GetSpec(ret);
}

nsresult GaleonWrapper::SelectAll (void)
{
      g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE);

      nsCOMPtr<nsIClipboardCommands> clipboard (do_GetInterface(mWebBrowser));
      return clipboard->SelectAll ();
}

nsresult GaleonWrapper::ScrollUp (void)
{
      nsCOMPtr<nsIDOMWindow> DOMWindow;
      GetFocusedDOMWindow (getter_AddRefs(DOMWindow));
      NS_ENSURE_TRUE (DOMWindow, NS_ERROR_FAILURE);

      return DOMWindow->ScrollByLines(-1);
}

nsresult GaleonWrapper::ScrollDown (void)
{
      nsCOMPtr<nsIDOMWindow> DOMWindow;
      GetFocusedDOMWindow (getter_AddRefs(DOMWindow));
      NS_ENSURE_TRUE (DOMWindow, NS_ERROR_FAILURE);

      return DOMWindow->ScrollByLines(1);
}

nsresult GaleonWrapper::ScrollLeft (void)
{
      nsCOMPtr<nsIDOMWindow> DOMWindow;
      GetFocusedDOMWindow (getter_AddRefs(DOMWindow));
      NS_ENSURE_TRUE (DOMWindow, NS_ERROR_FAILURE);
      
      return DOMWindow->ScrollBy(-16, 0);
}

nsresult GaleonWrapper::ScrollRight (void)
{
      nsCOMPtr<nsIDOMWindow> DOMWindow;
      GetFocusedDOMWindow (getter_AddRefs(DOMWindow));
      NS_ENSURE_TRUE (DOMWindow, NS_ERROR_FAILURE);
      
      return DOMWindow->ScrollBy(16, 0);
}

nsresult GaleonWrapper::FineScroll (int horiz, int vert)
{
      nsCOMPtr<nsIDOMWindow> DOMWindow;
      GetFocusedDOMWindow (getter_AddRefs(DOMWindow));
      NS_ENSURE_TRUE (DOMWindow, NS_ERROR_FAILURE);

      return DOMWindow->ScrollBy(horiz, vert);
}

nsresult
GaleonWrapper::GetSecurityInfo (PRUint32 *aState, nsACString& description)
{
#ifdef HAVE_MOZILLA_PSM
      NS_ENSURE_TRUE (mSecurityInfo, NS_ERROR_FAILURE);

      nsresult rv;
      rv = mSecurityInfo->GetState (aState);
      NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);

      GulString tooltip;
      rv = mSecurityInfo->GetTooltipText (tooltip);
      NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);

      NS_UTF16ToCString (tooltip, NS_CSTRING_ENCODING_UTF8, description);
      return NS_OK;
#else
      if (aState) *aState = 0;
      return NS_ERROR_FAILURE;
#endif
}

#ifdef HAVE_MOZILLA_PSM

nsresult GaleonWrapper::GetSSLStatus (nsISSLStatus **aSSLStatus)
{
      NS_ENSURE_TRUE (mSecurityInfo, NS_ERROR_FAILURE);

      nsCOMPtr<nsISSLStatusProvider> sp = do_QueryInterface (mSecurityInfo);
      NS_ENSURE_TRUE (sp, NS_ERROR_FAILURE);

      nsCOMPtr<nsISSLStatus> SSLStatus;
      sp->GetSSLStatus(getter_AddRefs(SSLStatus));
      NS_ENSURE_TRUE (SSLStatus, NS_ERROR_FAILURE);

      NS_ADDREF(*aSSLStatus = SSLStatus);
      return NS_OK;
}

#endif

nsresult GaleonWrapper::ShowPageCertificate ()
{
#ifndef HAVE_MOZILLA_PSM
      return NS_ERROR_NOT_IMPLEMENTED;
#else

      nsresult rv;
      nsCOMPtr<nsISSLStatus> SSLStatus;
      GetSSLStatus (getter_AddRefs(SSLStatus));
      NS_ENSURE_TRUE (SSLStatus, NS_ERROR_FAILURE);
      
      nsCOMPtr<nsIX509Cert> serverCert;
      SSLStatus->GetServerCert (getter_AddRefs (serverCert));
      NS_ENSURE_TRUE (serverCert, NS_ERROR_FAILURE);
      
      nsCOMPtr<nsICertificateDialogs> certDialogs =
            do_GetService (NS_CERTIFICATEDIALOGS_CONTRACTID, &rv);
      NS_ENSURE_TRUE (certDialogs, NS_ERROR_FAILURE);
      
      return certDialogs->ViewCert (NULL, serverCert);
#endif
}

nsresult GaleonWrapper::GetPageSecurityInfo (EmbedPageProperties *props)
{
      props->cipher_name = 0;
      props->key_length = 0;
      props->secret_key_length = 0;
      props->cert_issuer_name = 0;

      /* Will only happen if the embed has not initialised yet */
      if (!mSecurityInfo) return NS_OK;

#ifndef HAVE_MOZILLA_PSM
      return NS_OK;
#else
      nsCOMPtr<nsISSLStatus> SSLStatus;
      GetSSLStatus (getter_AddRefs(SSLStatus));
      NS_ENSURE_TRUE (SSLStatus, NS_ERROR_FAILURE);

      char * cipher;
      SSLStatus->GetCipherName (&cipher);
      props->cipher_name = g_strdup (cipher);
      nsMemory::Free (cipher);

      PRUint32 keyLength;

      SSLStatus->GetKeyLength (&keyLength);
      props->key_length = keyLength;

      SSLStatus->GetSecretKeyLength (&keyLength);
      props->secret_key_length = keyLength;
      
      nsCOMPtr<nsIX509Cert> cert;
      SSLStatus->GetServerCert (getter_AddRefs (cert));

      GulString value;
      cert->GetIssuerOrganization (value);
      if (!value.Length())
      {
            cert->GetIssuerName (value);
      }
      props->cert_issuer_name = g_strdup (GulCString(value).get());

      return NS_OK;
#endif
}

nsresult GaleonWrapper::GetCacheEntryDescriptor(const nsAString &aKey,
                                    nsICacheEntryDescriptor **aCacheEntryDescriptor)
{
      nsresult rv = NS_OK;

      nsCOMPtr<nsICacheService> cacheService =
            do_GetService(NS_CACHESERVICE_CONTRACTID);
      NS_ENSURE_TRUE (cacheService, NS_ERROR_FAILURE);

      char *url = g_strdup (GulCString (aKey).get());
      g_strdelimit (url, "#", '\0'); /* snip fragment, see bug #161201 */

      const char *cacheTypes[] = { "HTTP", "FTP" };
      for (unsigned int i = 0 ; i < G_N_ELEMENTS (cacheTypes); i++)
      {
            nsCOMPtr<nsICacheSession> cacheSession;
            cacheService->CreateSession(cacheTypes[i],
                                  nsICache::STORE_ANYWHERE,
                                  PR_TRUE,
                                  getter_AddRefs(cacheSession));
            NS_ENSURE_TRUE (cacheSession, NS_ERROR_FAILURE);

            cacheSession->SetDoomEntriesIfExpired(PR_FALSE);
            
            nsCOMPtr<nsICacheEntryDescriptor> cacheEntryDescriptor;

#ifdef HAVE_NSICACHESESSION_NSACSTRING
            rv = cacheSession->OpenCacheEntry(GulDependentCString(url),
                                      nsICache::ACCESS_READ,
                                      PR_FALSE,  aCacheEntryDescriptor);
#else
            rv = cacheSession->OpenCacheEntry(url, nsICache::ACCESS_READ,
                                      PR_FALSE,  aCacheEntryDescriptor);
#endif
            if (NS_SUCCEEDED (rv)) break;
      }
      g_free (url);
      return rv;
}

nsresult GaleonWrapper::GetPageProperties (EmbedPageProperties *props)
{
      nsresult rv;

      nsCOMPtr<nsIDOMDocument> DOMDocument;

      GetDOMDocument (getter_AddRefs(DOMDocument));
      NS_ENSURE_TRUE (DOMDocument, NS_ERROR_FAILURE);

      nsCOMPtr<nsIDOMNSDocument> doc = do_QueryInterface(DOMDocument);
      NS_ENSURE_TRUE (doc, NS_ERROR_FAILURE);

      GulString value;

      doc->GetLastModified(value);
      nsTime last_modified (GulCString(value).get(), PR_TRUE);
      LL_DIV (props->modification_time,
            NS_STATIC_CAST(PRTime, last_modified), PR_USEC_PER_SEC);

      doc->GetContentType(value);
      props->content_type = g_strdup (GulCString(value).get());

      doc->GetCharacterSet(value);
      props->encoding = g_strdup (GulCString(value).get());

      /* This might not work with XUL pages (e.g. about:config) */
      nsCOMPtr<nsIDOMHTMLDocument> HTMLDoc = do_QueryInterface(DOMDocument);
      if (HTMLDoc)
      {
            HTMLDoc->GetReferrer (value);
            if (value.Length())
            {
                  props->referring_url = g_strdup (GulCString(value).get());
            }
      }

      /* This might not work with XUL pages (e.g. about:config) */
      // Until https://bugzilla.mozilla.org/show_bug.cgi?id=154359 is fixed.
      rv = MozillaPrivate::GetCompatibilityMode(doc, &props->rendering_mode);
      NS_ENSURE_SUCCESS(rv, rv);

      /* Get the URL so we can look in the cache for the page */
      nsCOMPtr<nsIDOMLocation> DOMLocation;
      doc->GetLocation (getter_AddRefs (DOMLocation));
      NS_ENSURE_TRUE (DOMLocation, NS_ERROR_FAILURE);

      GulString url;
      DOMLocation->ToString (url);

      nsCOMPtr<nsICacheEntryDescriptor> cacheEntryDescriptor;
      GetCacheEntryDescriptor(url, getter_AddRefs(cacheEntryDescriptor));

      if (cacheEntryDescriptor)
      {
            PRUint32 expiry = 0, dataSize = 0;

            cacheEntryDescriptor->GetExpirationTime (&expiry);
            cacheEntryDescriptor->GetDataSize (&dataSize);
            props->expiration_time = expiry;
            props->size = dataSize;

            char *source;
            cacheEntryDescriptor->GetDeviceID (&source);
            if (strcmp (source, "disk") == 0)
            {
                  props->page_source = EMBED_SOURCE_DISK_CACHE;
            }
            else if (strcmp (source, "memory") == 0)
            {
                  props->page_source = EMBED_SOURCE_MEMORY_CACHE;
            }
            else
            {
                  props->page_source = EMBED_SOURCE_UNKNOWN_CACHE;
            }
            nsMemory::Free (source);
      }
      else
      {
            props->page_source = EMBED_SOURCE_NOT_CACHED;
            props->size = -1;
            props->expiration_time = 0;
      }

      GetPageSecurityInfo (props);

      GetMetaTags(&(props->metatags));
      GetForms(&(props->forms));
      GetLinks(&(props->links));
      GetImages(&(props->images));

      return NS_OK;
}

nsresult GaleonWrapper::GetMetaTags(GList **ret)
{
      nsresult rv;

      nsCOMPtr<nsIDOMDocument> doc;
      GetDOMDocument (getter_AddRefs(doc));
      NS_ENSURE_TRUE (doc, NS_ERROR_FAILURE);

      nsCOMPtr<nsIDOMNodeList> nodes;
      doc->GetElementsByTagName(NS_LITERAL_STRING("meta"),
                          getter_AddRefs(nodes));
      NS_ENSURE_TRUE (nodes, NS_ERROR_FAILURE);

      PRUint32 count(0);
      rv = nodes->GetLength(&count);
      NS_ENSURE_SUCCESS (rv, rv);

      for (PRUint32 i = 0; i < count; i++)
      {
            nsCOMPtr<nsIDOMNode> node;
            rv = nodes->Item(i, getter_AddRefs(node));
            if (NS_FAILED(rv) || !node) continue;

            nsCOMPtr<nsIDOMHTMLMetaElement> element;
            element = do_QueryInterface(node, &rv);
            if (NS_FAILED(rv) || !element) continue;
            
            EmbedPageMetaTag *tag = g_new0(EmbedPageMetaTag, 1);
            
            GulString tmp;

            rv = element->GetName(tmp);
            if (NS_FAILED(rv) || tmp.IsEmpty())
            {
                  rv = element->GetHttpEquiv(tmp);
                  if (NS_FAILED(rv) || tmp.IsEmpty())
                        continue;
            }
            tag->name = g_strdup(GulCString (tmp).get());

            rv = element->GetContent(tmp);
            if (NS_SUCCEEDED(rv))
            {
                  tag->content =
                        gul_string_strip_newline(GulCString(tmp).get());
            }

            *ret = g_list_append (*ret, tag);
      }
      return NS_OK;
}

nsresult GaleonWrapper::GetImages(GList **ret)
{
      nsresult rv;
      GHashTable *hash = g_hash_table_new(g_str_hash, g_str_equal);

      nsCOMPtr<nsIDOMDocument> doc;
      GetDOMDocument(getter_AddRefs(doc));
      NS_ENSURE_TRUE (doc, NS_ERROR_FAILURE);

      nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryInterface(doc);
      NS_ENSURE_TRUE (htmlDoc, NS_ERROR_FAILURE);

      nsCOMPtr<nsIDOMHTMLCollection> nodes;
      htmlDoc->GetImages(getter_AddRefs(nodes));

      PRUint32 count(0);
      nodes->GetLength(&count);
      for (PRUint32 i = 0; i < count; i++)
      {
            nsCOMPtr<nsIDOMNode> node;
            rv = nodes->Item(i, getter_AddRefs(node));
            if (NS_FAILED(rv) || !node) continue;

            nsCOMPtr<nsIDOMHTMLImageElement> element;
            element = do_QueryInterface(node, &rv);
            if (NS_FAILED(rv) || !element) continue;

            EmbedPageImage *image = g_new0(EmbedPageImage, 1);
            
            GulString tmp;
            rv = element->GetSrc(tmp);
            if (NS_SUCCEEDED(rv))
            {
                  const GulCString cTmp(tmp);

                  if (g_hash_table_lookup(hash, cTmp.get()))
                  {
                        g_free (image);
                        continue;
                  }
                  image->url = g_strdup(cTmp.get());
                  g_hash_table_insert(hash, image->url,
                                  GINT_TO_POINTER(TRUE));
            }

            rv = element->GetAlt(tmp);
            if (NS_SUCCEEDED(rv))
            {
                  image->alt =
                        gul_string_strip_newline(GulCString(tmp).get());
            }
            rv = element->GetTitle(tmp);
            if (NS_SUCCEEDED(rv))
            {
                  image->title =
                        gul_string_strip_newline(GulCString(tmp).get());
            }
            rv = element->GetWidth(&(image->width));
            rv = element->GetHeight(&(image->height));

            *ret = g_list_append(*ret, image);
      }
      g_hash_table_destroy (hash);

      return NS_OK;
}

nsresult GaleonWrapper::GetForms (GList **ret)
{
      nsresult rv;

      nsCOMPtr<nsIDOMDocument> doc;
      GetDOMDocument (getter_AddRefs(doc));
      NS_ENSURE_TRUE (doc, NS_ERROR_FAILURE);

      nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryInterface(doc);
      NS_ENSURE_TRUE (htmlDoc, NS_ERROR_FAILURE);

      nsCOMPtr<nsIDOMHTMLCollection> nodes;
      htmlDoc->GetForms(getter_AddRefs(nodes));
      NS_ENSURE_TRUE (nodes, NS_ERROR_FAILURE);

      PRUint32 count(0);
      rv = nodes->GetLength(&count);
      if (NS_FAILED(rv)) return NS_ERROR_FAILURE;

      for (PRUint32 i = 0; i < count; i++)
      {
            nsCOMPtr<nsIDOMNode> node;
            rv = nodes->Item(i, getter_AddRefs(node));
            if (NS_FAILED(rv) || !node) continue;

            nsCOMPtr<nsIDOMHTMLFormElement> element;
            element = do_QueryInterface(node, &rv);
            if (NS_FAILED(rv) || !element) continue;
            
            EmbedPageForm *form = g_new0(EmbedPageForm, 1);
            
            GulString tmp;

            rv = element->GetAction(tmp);
            if (NS_SUCCEEDED(rv) && tmp.Length())
            {
                  nsCOMPtr<nsIDOM3Document> document;
                  document = do_QueryInterface (doc);
                  if (!document)
                  {
                        g_free(form);
                        continue;
                  }

                  GulString spec;
                  document->GetDocumentURI (spec);

                  nsCOMPtr<nsIURI> uri;
                  GaleonUtils::NewURI (getter_AddRefs (uri), spec);

                  GulCString c;
                  const GulCString s(tmp);
                  rv = uri->Resolve(s, c);

                  form->action = c.Length() ?
                               g_strdup (c.get()) :
                               g_strdup (s.get());
            }

            rv = element->GetName(tmp);
            if (NS_SUCCEEDED(rv) && tmp.Length())
            {
                  form->name = g_strdup(GulCString(tmp).get());
            }

            rv = element->GetMethod(tmp);
            if (NS_SUCCEEDED(rv) && tmp.Length())
            {
                  form->method = g_strdup(GulCString(tmp).get());
            }

            *ret = g_list_append (*ret, form);
      }
      return NS_OK;
}

/*
 * This is a template function because we are calling
 * methods with identical signatures on two different
 * interfaces.
 */
template <class T>
static nsresult sProcessLinkNode(nsIDOMNode *node,
                         nsIDOMDocument *doc,
                         GList **ret)
{
      nsresult rv;

      T element = do_QueryInterface(node);
      NS_ENSURE_TRUE (element, NS_ERROR_FAILURE);

      GulString tmp;
      rv = element->GetHref(tmp);
      NS_ENSURE_SUCCESS (rv, rv);
      NS_ENSURE_TRUE (tmp.Length(), NS_ERROR_FAILURE);

      //Resolve relative href
      nsCOMPtr<nsIDOM3Document> document = do_QueryInterface(doc, &rv);
      NS_ENSURE_TRUE (document, NS_ERROR_FAILURE);
      
      GulString spec;
      rv = document->GetDocumentURI (spec);
      NS_ENSURE_SUCCESS (rv, rv);

      nsCOMPtr<nsIURI> uri;
      rv = GaleonUtils::NewURI (getter_AddRefs (uri), spec);
      NS_ENSURE_SUCCESS (rv, rv);

      const GulCString href(tmp);
      GulCString fullHref;
      rv = uri->Resolve (href, fullHref);
      
      EmbedPageLink *link = g_new0(EmbedPageLink, 1);

      if (fullHref.Length())
      {
            link->url = g_strdup(fullHref.get());
      }
      else
      {
            link->url = g_strdup(href.get());
      }

      rv = element->GetTitle(tmp);
      if (NS_SUCCEEDED(rv) && tmp.Length())
      {
            link->title = gul_string_strip_newline(GulCString(tmp).get());
      }

      rv = element->GetRel(tmp);
      if (NS_SUCCEEDED(rv) && tmp.Length())
      {
            link->rel = g_strdup (GulCString(tmp).get());
      }
      if (!link->rel || strlen(link->rel) == 0)
      {
            element->GetRev(tmp);
            if (NS_SUCCEEDED(rv) && tmp.Length())
            {
                  g_free(link->rel);
                  link->rel = g_strdup(GulCString(tmp).get());
            }
      }
      
      *ret = g_list_append(*ret, link);

      return NS_OK;
}

nsresult GaleonWrapper::GetLinks (GList **ret)
{
      nsresult rv;

      nsCOMPtr<nsIDOMDocument> doc;
      GetMainDOMDocument(getter_AddRefs(doc));
      NS_ENSURE_TRUE (doc, NS_ERROR_FAILURE);

      /* first, get a list of <link> elements */
      nsCOMPtr<nsIDOMNodeList> links;
      doc->GetElementsByTagName(NS_LITERAL_STRING("link"),
                          getter_AddRefs(links));
      NS_ENSURE_TRUE (links, NS_ERROR_FAILURE);

      PRUint32 links_count;
      rv = links->GetLength(&links_count);
      NS_ENSURE_SUCCESS (rv, rv);

      for (PRUint32 i = 0; i < links_count; i++)
      {
            nsCOMPtr<nsIDOMNode> node;
            rv = links->Item(i, getter_AddRefs(node));
            if (NS_FAILED(rv) || !node) continue;

            sProcessLinkNode<nsCOMPtr<nsIDOMHTMLLinkElement> >(node, doc, ret);
      }

      /* next, get a list of anchors */
      nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryInterface(doc);
      NS_ENSURE_TRUE (htmlDoc, NS_ERROR_FAILURE);

      nsCOMPtr<nsIDOMHTMLCollection> anchors;
      htmlDoc->GetLinks(getter_AddRefs(anchors));

      PRUint32 anchor_count;
      anchors->GetLength(&anchor_count);
      for (PRUint32 i = 0; i < anchor_count; i++)
      {
            nsCOMPtr<nsIDOMNode> node;
            rv = anchors->Item(i, getter_AddRefs(node));
            if (NS_FAILED(rv) || !node) continue;

            sProcessLinkNode<nsCOMPtr<nsIDOMHTMLAnchorElement> >(node, doc, ret);
      }

      return NS_OK;
}


class GConsoleMessage : public nsIConsoleMessage
{
public:
    GConsoleMessage (const nsAString &message)
    { mMessage = message; }
    ~GConsoleMessage() {}

    NS_DECL_ISUPPORTS

    NS_IMETHODIMP GetMessage(PRUnichar **result)
    {
          *result = NS_StringCloneData (mMessage);
          return NS_OK;
    }

private:
    GulString mMessage;
};

NS_IMPL_THREADSAFE_ISUPPORTS1(GConsoleMessage, nsIConsoleMessage)


nsresult GaleonWrapper::EvaluateJS (const char *script)
{
      nsresult rv;

      nsCOMPtr<nsIDOMWindow> DOMWindow;
      GetDOMWindow (getter_AddRefs(DOMWindow));
      NS_ENSURE_TRUE (DOMWindow, NS_ERROR_FAILURE);

      PRBool isUndefined = PR_TRUE;
      GulString ret;
      rv = MozillaPrivate::EvaluateJS (DOMWindow, GulString(script),
                               ret, &isUndefined);
      NS_ENSURE_SUCCESS (rv, rv);

      if (ret.Length() && ! isUndefined)
      {
            nsCOMPtr<nsIConsoleService> consoleService =
                  do_GetService(NS_CONSOLESERVICE_CONTRACTID);
            nsCOMPtr<nsIConsoleMessage> message = new GConsoleMessage (ret);
     
            if (consoleService && message) 
            {
                  consoleService->LogMessage (message);
            }
      }

      return NS_OK;
}

#define NUM_TEXTFIELDS_REQUIRED     3

nsresult 
GaleonWrapper::GetDocumentHasModifiedForms (nsIDOMDocument *aDomDoc, 
                                  PRUint32 *aNumTextFields,
                                  PRBool *aIsModified)
{
      nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryInterface(aDomDoc);
      NS_ENSURE_TRUE (htmlDoc, NS_ERROR_FAILURE);

      nsCOMPtr<nsIDOMHTMLCollection> forms;
      htmlDoc->GetForms (getter_AddRefs (forms));
      if (!forms) return NS_OK; /* it's ok not to have any forms */

      PRUint32 formNum;
      forms->GetLength (&formNum);

      /* check all forms */
      for (PRUint32 formIndex = 0; formIndex < formNum; formIndex++)
      {
            nsCOMPtr<nsIDOMNode> formNode;
            forms->Item (formIndex, getter_AddRefs (formNode));
            if (!formNode) continue;

            nsCOMPtr<nsIDOMHTMLFormElement> formElement = do_QueryInterface (formNode);
            if (!formElement) continue;

            nsCOMPtr<nsIDOMHTMLCollection> formElements;
            formElement->GetElements (getter_AddRefs (formElements));
            if (!formElements) continue;

            PRUint32 elementNum;
            formElements->GetLength (&elementNum);

            /* check all input elements in the form for user input */
            for (PRUint32 elementIndex = 0; elementIndex < elementNum; elementIndex++)
            {
                  nsCOMPtr<nsIDOMNode> domNode;
                  formElements->Item (elementIndex, getter_AddRefs (domNode));
                  if (!domNode) continue;

                  nsCOMPtr<nsIDOMHTMLTextAreaElement> areaElement = do_QueryInterface (domNode);
                  if (areaElement)
                  {
                        /* Treat a text area like NUM_TEXTFIELDS_REQUIRED text boxes,
                         * that way you only need one textare for the modified
                         * flag to properly work */
                        (*aNumTextFields) += NUM_TEXTFIELDS_REQUIRED;
                        GulString default_text, user_text;
                        areaElement->GetDefaultValue (default_text);
                        areaElement->GetValue (user_text);
                        
                        /* Mozilla Bug 218277, 195946 and others */
                        default_text.ReplaceChar(0xa0, ' ');

                        if (!user_text.Equals (default_text))
                        {
                              *aIsModified = PR_TRUE;
                              return NS_OK;
                        }

                        continue;
                  }

                  nsCOMPtr<nsIDOMHTMLInputElement> inputElement = do_QueryInterface(domNode);
                  if (!inputElement) continue;
      
                  GulString type;
                  inputElement->GetType(type);

                  GulCString cType(type);
                  if (cType.EqualsAsciiIgnoreCase("text"))
                  {
                        (*aNumTextFields)++;
                        GulString default_text, user_text;
                        PRInt32 max_length;
                        inputElement->GetDefaultValue (default_text);
                        inputElement->GetValue (user_text);
                        inputElement->GetMaxLength (&max_length);

                        /* Guard against arguably broken forms where
                         * default_text is longer than maxlength
                         * (user_text is cropped, default_text is not)
                         */
                        if (default_text.Length() > (PRUint32)max_length)
                        {
                              default_text.Cut (max_length, PR_UINT32_MAX);
                        }

                        /* Mozilla Bug 218277, 195946 and others */
                        default_text.ReplaceChar(0xa0, ' ');

                        if (!user_text.Equals (default_text))
                        {
                              *aIsModified = PR_TRUE;
                        }

                        if ((*aIsModified) && *aNumTextFields >= 
                            NUM_TEXTFIELDS_REQUIRED)
                        {
                              return NS_OK;
                        }
                  }
            }
      }

      return NS_OK;
}

nsresult 
GaleonWrapper::GetHasModifiedForms (PRBool *modified)
{
      *modified = PR_FALSE;

      nsCOMPtr<nsIDocShell> rootDocShell = do_GetInterface (mWebBrowser);
      NS_ENSURE_TRUE (rootDocShell, NS_ERROR_FAILURE);

      nsCOMPtr<nsISimpleEnumerator> enumerator;
      rootDocShell->GetDocShellEnumerator(nsIDocShellTreeItem::typeContent,
                                  nsIDocShell::ENUMERATE_FORWARDS,
                                  getter_AddRefs(enumerator));
      NS_ENSURE_TRUE (enumerator, NS_ERROR_FAILURE);

      PRBool hasMore;
      PRBool isModified = PR_FALSE;
      PRUint32 numTextFields = 0;
      while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore)
      {
            nsCOMPtr<nsISupports> element;
            enumerator->GetNext (getter_AddRefs(element));
            if (!element) continue;

            nsCOMPtr<nsIDocShell> docShell = do_QueryInterface (element);
            if (!docShell) continue;

            nsCOMPtr<nsIContentViewer> contentViewer;
            docShell->GetContentViewer (getter_AddRefs(contentViewer));
            if (!contentViewer) continue;

            nsCOMPtr<nsIDOMDocument> domDoc;
            contentViewer->GetDOMDocument (getter_AddRefs (domDoc));

            nsresult rv;
            rv = GetDocumentHasModifiedForms (domDoc, &numTextFields, &isModified);
            if (NS_SUCCEEDED (rv) &&
                numTextFields >= NUM_TEXTFIELDS_REQUIRED && isModified)
            {
                  *modified = PR_TRUE;
                  break;
            }
      }

      return NS_OK;
}

static void
PopTargetDocument_WeakRef_cb (GaleonWrapper *wrapper,
                        GaleonEmbedEvent *event)
{
      wrapper->PopTargetDocument();
}


/* 
 * Use the nsIDomDocument as the target for various functions, it is
 * used until the GaleonEmbedEvent object is unref'd
 */
nsresult GaleonWrapper::PushTargetDocument (nsIDOMDocument *domDoc,
                                  GaleonEmbedEvent *aEvent)
{
      mTargetDocument = domDoc;

      if (mCurrentEvent)
      {
            g_object_weak_unref (G_OBJECT (mCurrentEvent),
                             (GWeakNotify)PopTargetDocument_WeakRef_cb,
                             this);
      }

      mCurrentEvent = aEvent;

      if (mCurrentEvent)
      {
            g_object_weak_ref (G_OBJECT (mCurrentEvent),
                           (GWeakNotify)PopTargetDocument_WeakRef_cb,
                           this);
      }

      return NS_OK;
}

nsresult GaleonWrapper::PopTargetDocument ()
{
      mTargetDocument = nsnull;
      mCurrentEvent = NULL;

      return NS_OK;
}

////////////////////////////////////////////////////////////////////////////
NS_IMPL_ISUPPORTS1(GDOMEventListener, nsIDOMEventListener)

GDOMEventListener::GDOMEventListener() : mEmbed(0)
{
}

GDOMEventListener::~GDOMEventListener()
{
}

nsresult
GDOMEventListener::Init(GaleonEmbed *aEmbed)
{
      mEmbed = aEmbed;
      return NS_OK;
}

NS_IMETHODIMP
GDOMEventListener::HandleEvent (nsIDOMEvent* aDOMEvent)
{
      nsresult rv;

      nsCOMPtr<nsIDOMEventTarget> target;
      aDOMEvent->GetTarget(getter_AddRefs(target));
      NS_ENSURE_TRUE (target, NS_ERROR_FAILURE);

      nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(target);
      NS_ENSURE_TRUE (elem, NS_ERROR_FAILURE);

      GulString value;
      rv = elem->GetAttribute(NS_LITERAL_STRING("rel"), value);
      NS_ENSURE_SUCCESS (rv, rv);

      const GulCString rel(value);
      if (rel.EqualsAsciiIgnoreCase("SHORTCUT ICON") ||
          rel.EqualsAsciiIgnoreCase("ICON"))
      {
            rv = elem->GetAttribute (NS_LITERAL_STRING("href"), value);
            NS_ENSURE_SUCCESS (rv, rv);
            NS_ENSURE_FALSE (value.IsEmpty(), NS_ERROR_FAILURE);

            nsCOMPtr<nsIDOMDocument> domDoc;
            elem->GetOwnerDocument (getter_AddRefs(domDoc));
            NS_ENSURE_TRUE (domDoc, NS_ERROR_FAILURE);

            /* See if this is from the toplevel frame */
            nsCOMPtr<nsIDOMDocumentView> docView (do_QueryInterface (domDoc));
            NS_ENSURE_TRUE (docView, NS_ERROR_FAILURE);

            nsCOMPtr<nsIDOMAbstractView> abstractView;
            docView->GetDefaultView (getter_AddRefs (abstractView));

            nsCOMPtr<nsIDOMWindow> domWin (do_QueryInterface (abstractView));
            NS_ENSURE_TRUE (domWin, NS_ERROR_FAILURE);

            nsCOMPtr<nsIDOMWindow> topDomWin;
            domWin->GetTop (getter_AddRefs (topDomWin));

            nsCOMPtr<nsISupports> domWinAsISupports (do_QueryInterface (domWin));
            nsCOMPtr<nsISupports> topDomWinAsISupports (do_QueryInterface (topDomWin));
            /* disallow subframes to set favicon */
            if (domWinAsISupports != topDomWinAsISupports) return NS_OK;
            
            nsCOMPtr<nsIDOM3Document> doc = do_QueryInterface (domDoc);
            NS_ENSURE_TRUE (doc, NS_ERROR_FAILURE);

            GulString spec;
            rv = doc->GetDocumentURI (spec);
            NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);

            nsCOMPtr<nsIURI> docUri;
            GaleonUtils::NewURI (getter_AddRefs (docUri), spec);

            GulCString favicon;
            rv = docUri->Resolve (GulCString(value), favicon);
            NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);

            nsCOMPtr<nsIURI> favUri;
            GaleonUtils::NewURI (getter_AddRefs (favUri), favicon);
            NS_ENSURE_TRUE (favUri, NS_ERROR_FAILURE);

            /* check if load is allowed */
            nsCOMPtr<nsIScriptSecurityManager> secMan
                  (do_GetService("@mozilla.org/scriptsecuritymanager;1"));
            /* refuse if we can't check */
            NS_ENSURE_TRUE (secMan, NS_ERROR_FAILURE);

            rv = secMan->CheckLoadURI(docUri, favUri,
                                nsIScriptSecurityManager::STANDARD);
            /* failure means it didn't pass the security check */
            if (NS_FAILED (rv)) return NS_OK;

            /* security check passed, now check with content policy */
            nsCOMPtr<nsIContentPolicy> policy =
                  do_GetService("@mozilla.org/layout/content-policy;1");
            /* refuse if we can't check */
            NS_ENSURE_TRUE (policy, NS_ERROR_FAILURE);

#ifdef HAVE_NEW_NSICONTENTPOLICY_API
            GulString typeVal;
            elem->GetAttribute (NS_LITERAL_STRING ("type"), typeVal);

            PRInt16 decision = 0;
            rv = policy->ShouldLoad (nsIContentPolicy::TYPE_IMAGE,
                               favUri, docUri, target,
                               GulCString(typeVal),
                               nsnull,
                               &decision);
            NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
            if (decision != nsIContentPolicy::ACCEPT) return NS_OK;
#else
            PRBool shouldLoad = PR_FALSE;
            rv = policy->ShouldLoad (nsIContentPolicy::IMAGE,
                               favUri, target,
                               domWin,
                               &shouldLoad);
            NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE);
            if (!shouldLoad) return NS_OK;
#endif

            /* ok, we accept this as a valid favicon for this site */
            g_signal_emit_by_name (mEmbed, "ge_favicon", favicon.get());
      }

      return NS_OK;
}

//------------------------------------------------------------------------------
NS_IMPL_ISUPPORTS1(GDOMPopupEventListener, nsIDOMEventListener)

NS_IMETHODIMP
GDOMPopupEventListener::HandleEvent (nsIDOMEvent* aDOMEvent)
{
      nsresult rv;

      nsCOMPtr<nsIDOMPopupBlockedEvent> popupEvent =
            do_QueryInterface(aDOMEvent);
      NS_ENSURE_TRUE (popupEvent, NS_ERROR_FAILURE);

      nsCOMPtr<nsIURI> requesterURI;
      popupEvent->GetRequestingWindowURI(getter_AddRefs(requesterURI));
      NS_ENSURE_TRUE (requesterURI, NS_ERROR_FAILURE);

      GulCString spec;
      rv = requesterURI->GetSpec(spec);
      NS_ENSURE_SUCCESS (rv, rv);
      NS_ENSURE_FALSE (spec.IsEmpty(), NS_ERROR_FAILURE);

      g_signal_emit_by_name (mEmbed, "ge_popupblocked", spec.get());

      return rv;
}

// ------------------------------------------------------------
 
NS_IMETHODIMP
GDOMModalAlertEventListener::HandleEvent (nsIDOMEvent * aDOMEvent)
{
#ifdef HAVE_NSIDOMNSEVENT_GETISTRUSTED
      NS_ENSURE_TRUE (mEmbed, NS_ERROR_FAILURE);

      /* make sure the event is trusted */
      nsCOMPtr<nsIDOMNSEvent> nsEvent (do_QueryInterface (aDOMEvent));
      NS_ENSURE_TRUE (nsEvent, NS_ERROR_FAILURE);

        PRBool isTrusted = PR_FALSE;
      nsEvent->GetIsTrusted (&isTrusted);
      if (!isTrusted) return NS_OK;

      nsresult rv;
      GulString type;
      rv = aDOMEvent->GetType (type);
      NS_ENSURE_SUCCESS (rv, rv);

      LOG ("ModalAlertListener event %s", GulCString(type).get());

      if (type.Equals(NS_LITERAL_STRING("DOMWillOpenModalDialog")))
      {
            gboolean retval = FALSE;
            g_signal_emit_by_name (mEmbed, "ge-modal-alert", &retval);

            /* suppress alert */
            if (retval)
            {
                  aDOMEvent->PreventDefault ();
                  aDOMEvent->StopPropagation();
            }
      }
      else if (type.Equals(NS_LITERAL_STRING("DOMModalDialogClosed")))
      {
            g_signal_emit_by_name (mEmbed, "ge-modal-alert-closed");
      }

#endif
      return NS_OK;
}



//------------------------------------------------------------------------------
NS_IMPL_ISUPPORTS1(GDOMContextMenuListener, nsIDOMContextMenuListener)

nsresult
GDOMContextMenuListener::Init(GaleonEmbed *aEmbed, PRBool aIsCapturePhase)
{
      mEmbed = aEmbed;
      mIsCapturePhase = aIsCapturePhase;
      return NS_OK;
}

/**
 *  This is the callback for when a contextmenu event occurs
 *  Events are propagated along the dom tree as follows:
 *
 *  [ root ] ---------> [ target ] ----------> [ root ]
 *  <-----------------> <------->  <------------------>
 *     Capture Phase     At target     Bubble Phase
 *
 * By hooking into both the capture an bubble phase (i.e first and last)
 * we can either:
 * 
 * 1) Block Javascript calls (which occur in the at target or bubble phase)
 *    by calling StopPropagation() on the event in the capture phase
 *
 * 2) Allow javascript to block us by doing nothing in the capture
 *    phase, and checking for PreventDefault() in the bubble phase
 *
 * The above is my understanding of DOM events - Crispin 2004/09/04
 */
NS_IMETHODIMP
GDOMContextMenuListener::ContextMenu (nsIDOMEvent* aDOMEvent)
{
      nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aDOMEvent);
      NS_ENSURE_TRUE (mouseEvent, NS_ERROR_FAILURE);

#if 0 
      /* In theory we can use the same object for both the
       * capture and bubble phases of the contextmenu handling,
       * however 1.7 is totally broken: The GetEventPhase()
       * call always returns 'AT_TARGET' which isn't particularly
       * useful.
       *
       * See http://bugzilla.mozilla.org/show_bug.cgi?id=245569
       *
       * When 1.7 is no longer supported, we can remove the
       * mIsCapturePhase variable, and use the same listener
       * for both bubble and capture phases.
       */
      PRUint16 eventPhase;
      aDOMEvent->GetEventPhase (&eventPhase);
      PRBool IsCapturePhase = (eventPhase == nsIDOMEvent::CAPTURING_PHASE) ? 
            PR_TRUE : PR_FALSE;
#else
      PRBool IsCapturePhase = mIsCapturePhase;
#endif

      GaleonWrapper *wrapper = (GaleonWrapper*)mozilla_embed_get_galeon_wrapper(MOZILLA_EMBED (mEmbed));
      GaleonEmbedEvent *info;
      info = galeon_embed_event_new ();
      
      EventContext ctx;
      ctx.Init (wrapper);
        nsresult rv = ctx.GetMouseEventInfo (mouseEvent, info);
      /* Don't do any magic handling if we can't actually show the context
       * menu, this can happen for XUL pages (e.g. about:config) */
      if (NS_FAILED (rv))
      {
            g_object_unref (info);
            return NS_OK;     
      }

      gboolean show_context_menu = TRUE;
      gboolean allow_javascript = eel_gconf_get_boolean (CONF_FILTERING_ALLOW_CONTEXTMENU); 
      if (allow_javascript)
      {
            /* Allow javascript calls to prevent our context menu */
            if (IsCapturePhase)
            {
                  /* Don't handle the context menu till the bubble, which
                   * is after the javascript events have been called */
                  show_context_menu = FALSE;
            }
            
            nsCOMPtr<nsIDOMNSUIEvent> nsUIEvent = do_QueryInterface(mouseEvent);
            PRBool preventDefault = PR_FALSE;
            nsUIEvent->GetPreventDefault(&preventDefault);
            if (preventDefault)
            {
                  show_context_menu = FALSE;
            }
      }
      else
      {
            /* Handle our context menu straight away, blocking
             * javascript calls */
            if (IsCapturePhase)
            {
                  /* Dont't handle this event any more */
                  aDOMEvent->PreventDefault();
                  aDOMEvent->StopPropagation();
            }
            else
            {
                  /* We shouldn't actually get here, as the capture phase
                   * should be called first, and stop the propagation */
                  g_return_val_if_reached (NS_ERROR_FAILURE);
            }

      }


      if (show_context_menu)
      {
            if (info->mouse_button == 0)
            {
                  // Translate relative coordinates to absolute values, and try
                  // to avoid covering links by adding a little offset.
                  int x, y;
                  gdk_window_get_origin (GTK_WIDGET(mEmbed)->window, &x, &y);
                  info->x += x + 6; 
                  info->y += y + 6;

                  // Set the keycode to something sensible
                  info->keycode = nsIDOMKeyEvent::DOM_VK_CONTEXT_MENU;
            }

            nsCOMPtr<nsIDOMDocument> domDoc;
            rv = ctx.GetTargetDocument (getter_AddRefs(domDoc));
            if (NS_SUCCEEDED(rv))
            {
                  rv = wrapper->PushTargetDocument (domDoc, info);
                  if (NS_SUCCEEDED(rv))
                  {
                        g_signal_emit_by_name (mEmbed, "ge_contextmenu", info);
                  }
            }

      }
      
      g_object_unref (info);

      return NS_OK;
}

NS_IMETHODIMP
GDOMContextMenuListener::HandleEvent (nsIDOMEvent* aDOMEvent)
{
      return NS_ERROR_NOT_IMPLEMENTED;
}

Generated by  Doxygen 1.6.0   Back to index