/* * Copyright (C) 2000-2004 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. * * $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "EphyBrowser.h" #include "GlobalHistory.h" #include "ContentHandler.h" #include "ephy-embed.h" #include "ephy-string.h" #include "ephy-debug.h" #include #include #include "nsIInterfaceRequestorUtils.h" #include "nsIURI.h" #include "nsISimpleEnumerator.h" #include "nsIContentViewer.h" #include "nsIGlobalHistory.h" #include "nsIWebBrowserFind.h" #include "nsIWebBrowserFocus.h" #include "nsICommandManager.h" #include "nsIWebBrowserPrint.h" #include "nsIDocShellTreeItem.h" #include "nsIDocShellTreeNode.h" #include "nsIDocShellTreeOwner.h" #include "nsIDocumentCharsetInfo.h" #include "nsIWebPageDescriptor.h" #include "nsISHEntry.h" #include "nsIHistoryEntry.h" #include "nsIDOMHTMLDocument.h" #include "nsIDOMHTMLCollection.h" #include "nsIDOMHTMLElement.h" #include "nsIDOMHTMLFormElement.h" #include "nsIDOMHTMLInputElement.h" #include "nsIDOMHTMLTextAreaElement.h" #include "nsIDOMDocument.h" #include "nsIDOMEvent.h" #include "nsIDOMEventTarget.h" #include "nsIDOMNode.h" #include "nsIDOMElement.h" #ifdef ALLOW_PRIVATE_API #include "nsPIDOMWindow.h" #include "nsIMarkupDocumentViewer.h" #include "nsIChromeEventHandler.h" #include "nsIDOMWindowInternal.h" #endif #ifdef ALLOW_PRIVATE_STRINGS #include "nsString.h" #include "nsReadableUtils.h" #include "nsIDocument.h" #include "nsIDeviceContext.h" #include "nsIPresContext.h" #include "nsIAtom.h" #endif EphyEventListener::EphyEventListener(void) { LOG ("EphyEventListener ctor (%p)", this) mOwner = nsnull; } EphyEventListener::~EphyEventListener() { LOG ("EphyEventListener dtor (%p)", this) } NS_IMPL_ISUPPORTS1(EphyEventListener, nsIDOMEventListener) nsresult EphyEventListener::Init(EphyEmbed *aOwner) { mOwner = aOwner; return NS_OK; } nsresult EphyFaviconEventListener::HandleFaviconLink (nsIDOMNode *node) { nsresult result; nsCOMPtr linkElement; linkElement = do_QueryInterface (node); if (!linkElement) return NS_ERROR_FAILURE; NS_NAMED_LITERAL_STRING(attr_rel, "rel"); nsAutoString value; result = linkElement->GetAttribute (attr_rel, value); if (NS_FAILED (result)) return NS_ERROR_FAILURE; if (value.EqualsIgnoreCase("SHORTCUT ICON") || value.EqualsIgnoreCase("ICON")) { NS_NAMED_LITERAL_STRING(attr_href, "href"); nsAutoString value; result = linkElement->GetAttribute (attr_href, value); if (NS_FAILED (result) || value.IsEmpty()) return NS_ERROR_FAILURE; nsCOMPtr domDoc; node->GetOwnerDocument(getter_AddRefs(domDoc)); NS_ENSURE_TRUE (domDoc, NS_ERROR_FAILURE); nsCOMPtr doc = do_QueryInterface (domDoc); NS_ENSURE_TRUE (doc, NS_ERROR_FAILURE); #if MOZILLA_SNAPSHOT > 13 nsIURI *uri; uri = doc->GetDocumentURI (); #elif MOZILLA_SNAPSHOT > 11 nsIURI *uri; uri = doc->GetDocumentURL (); #endif if (!uri) return NS_ERROR_FAILURE; const nsACString &link = NS_ConvertUTF16toUTF8(value); nsCAutoString favicon_url; result = uri->Resolve (link, favicon_url); if (NS_FAILED (result)) return NS_ERROR_FAILURE; char *url = g_strdup (favicon_url.get()); g_signal_emit_by_name (mOwner, "ge_favicon", url); g_free (url); } return NS_OK; } NS_IMETHODIMP EphyFaviconEventListener::HandleEvent(nsIDOMEvent* aDOMEvent) { nsCOMPtr eventTarget; aDOMEvent->GetTarget(getter_AddRefs(eventTarget)); nsCOMPtr node = do_QueryInterface(eventTarget); NS_ENSURE_TRUE (node, NS_ERROR_FAILURE); HandleFaviconLink (node); return NS_OK; } EphyBrowser::EphyBrowser () { mFaviconEventListener = nsnull; mEventReceiver = nsnull; mInitialized = PR_FALSE; } EphyBrowser::~EphyBrowser () { } nsresult EphyBrowser::Init (GtkMozEmbed *mozembed) { nsresult rv; if (mInitialized) return NS_OK; gtk_moz_embed_get_nsIWebBrowser (mozembed, getter_AddRefs(mWebBrowser)); NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE); mWebBrowser->GetContentDOMWindow (getter_AddRefs (mDOMWindow)); NS_ENSURE_TRUE (mDOMWindow, NS_ERROR_FAILURE); /* This will instantiate an about:blank doc if necessary */ nsCOMPtr domDocument; rv = mDOMWindow->GetDocument (getter_AddRefs (domDocument)); NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE); mFaviconEventListener = new EphyFaviconEventListener(); if (!mFaviconEventListener) return NS_ERROR_OUT_OF_MEMORY; rv = mFaviconEventListener->Init (EPHY_EMBED (mozembed)); NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE); rv = GetListener(); NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE); mInitialized = PR_TRUE; return AttachListeners(); } nsresult EphyBrowser::GetListener (void) { if (mEventReceiver) return NS_ERROR_FAILURE; nsCOMPtr domWindowExternal; mWebBrowser->GetContentDOMWindow(getter_AddRefs(domWindowExternal)); nsCOMPtr domWindow; domWindow = do_QueryInterface(domWindowExternal); nsCOMPtr piWin(do_QueryInterface(domWindow)); NS_ENSURE_TRUE (piWin, NS_ERROR_FAILURE); nsCOMPtr chromeHandler; piWin->GetChromeEventHandler(getter_AddRefs(chromeHandler)); mEventReceiver = do_QueryInterface(chromeHandler); NS_ENSURE_TRUE (mEventReceiver, NS_ERROR_FAILURE); return NS_OK; } nsresult EphyBrowser::AttachListeners(void) { nsresult rv; NS_ENSURE_TRUE (mEventReceiver, NS_ERROR_FAILURE); nsCOMPtr target; target = do_QueryInterface (mEventReceiver); rv = target->AddEventListener(NS_LITERAL_STRING("DOMLinkAdded"), mFaviconEventListener, PR_FALSE); NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE); return NS_OK; } nsresult EphyBrowser::DetachListeners(void) { nsresult rv; NS_ENSURE_TRUE (mEventReceiver, NS_ERROR_FAILURE); nsCOMPtr target; target = do_QueryInterface (mEventReceiver); rv = target->RemoveEventListener(NS_LITERAL_STRING("DOMLinkAdded"), mFaviconEventListener, PR_FALSE); NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE); return NS_OK; } nsresult EphyBrowser::Print (nsIPrintSettings *options, PRBool preview) { nsresult result; NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE); nsCOMPtr print(do_GetInterface(mWebBrowser)); NS_ENSURE_TRUE (print, NS_ERROR_FAILURE); if (!preview) { result = print->Print (options, nsnull); } else { result = print->PrintPreview(options, nsnull, nsnull); } return result; } nsresult EphyBrowser::PrintPreviewClose (void) { nsresult rv; PRBool isPreview = PR_FALSE; NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE); nsCOMPtr print(do_GetInterface(mWebBrowser)); NS_ENSURE_TRUE (print, NS_ERROR_FAILURE); rv = print->GetDoingPrintPreview(&isPreview); NS_ENSURE_SUCCESS (rv, NS_ERROR_FAILURE); if (isPreview == PR_TRUE) { rv = print->ExitPrintPreview(); } return rv; } nsresult EphyBrowser::PrintPreviewNumPages (int *numPages) { NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE); nsCOMPtr print(do_GetInterface(mWebBrowser)); NS_ENSURE_TRUE (print, NS_ERROR_FAILURE); return print->GetPrintPreviewNumPages(numPages); } nsresult EphyBrowser::PrintPreviewNavigate(PRInt16 navType, PRInt32 pageNum) { NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE); nsCOMPtr print(do_GetInterface(mWebBrowser)); NS_ENSURE_TRUE (print, NS_ERROR_FAILURE); return print->PrintPreviewNavigate(navType, pageNum); } nsresult EphyBrowser::GetPrintSettings (nsIPrintSettings **options) { NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE); nsCOMPtr print(do_GetInterface(mWebBrowser)); NS_ENSURE_TRUE (print, NS_ERROR_FAILURE); return print->GetGlobalPrintSettings(options); } nsresult EphyBrowser::GetSHistory (nsISHistory **aSHistory) { nsresult result; NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE); nsCOMPtr ContentNav = do_QueryInterface (mWebBrowser); NS_ENSURE_TRUE (ContentNav, NS_ERROR_FAILURE); nsCOMPtr SessionHistory; result = ContentNav->GetSessionHistory (getter_AddRefs (SessionHistory)); NS_ENSURE_TRUE (SessionHistory, NS_ERROR_FAILURE); *aSHistory = SessionHistory.get(); NS_IF_ADDREF (*aSHistory); return NS_OK; } nsresult EphyBrowser::Destroy () { DetachListeners (); mWebBrowser = nsnull; return NS_OK; } nsresult EphyBrowser::GoToHistoryIndex (PRInt16 index) { NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE); nsCOMPtr ContentNav = do_QueryInterface (mWebBrowser); NS_ENSURE_TRUE (ContentNav, NS_ERROR_FAILURE); return ContentNav->GotoIndex (index); } nsresult EphyBrowser::SetZoom (float aZoom, PRBool reflow) { NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE); if (reflow) { nsCOMPtr contentViewer; GetContentViewer (getter_AddRefs(contentViewer)); NS_ENSURE_TRUE (contentViewer, NS_ERROR_FAILURE); nsCOMPtr mdv = do_QueryInterface(contentViewer); NS_ENSURE_TRUE (mdv, NS_ERROR_FAILURE); return mdv->SetTextZoom (aZoom); } else { nsCOMPtr DocShell; DocShell = do_GetInterface (mWebBrowser); NS_ENSURE_TRUE (DocShell, NS_ERROR_FAILURE); SetZoomOnDocshell (aZoom, DocShell); nsCOMPtr docShellNode(do_QueryInterface(DocShell)); if (docShellNode) { PRInt32 i; PRInt32 n; docShellNode->GetChildCount(&n); for (i=0; i < n; i++) { nsCOMPtr child; docShellNode->GetChildAt(i, getter_AddRefs(child)); nsCOMPtr childAsShell(do_QueryInterface(child)); if (childAsShell) { return SetZoomOnDocshell (aZoom, childAsShell); } } } } return NS_OK; } nsresult EphyBrowser::SetZoomOnDocshell (float aZoom, nsIDocShell *DocShell) { nsCOMPtr PresContext; DocShell->GetPresContext (getter_AddRefs(PresContext)); NS_ENSURE_TRUE (PresContext, NS_ERROR_FAILURE); #if MOZILLA_SNAPSHOT > 13 nsIDeviceContext *DeviceContext; DeviceContext = PresContext->DeviceContext(); NS_ENSURE_TRUE (DeviceContext, NS_ERROR_FAILURE); #else nsCOMPtr DeviceContext; PresContext->GetDeviceContext (getter_AddRefs(DeviceContext)); NS_ENSURE_TRUE (DeviceContext, NS_ERROR_FAILURE); #endif return DeviceContext->SetTextZoom (aZoom); } nsresult EphyBrowser::GetContentViewer (nsIContentViewer **aViewer) { NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE); nsCOMPtr ourDocShell(do_GetInterface(mWebBrowser)); NS_ENSURE_TRUE (ourDocShell, NS_ERROR_FAILURE); return ourDocShell->GetContentViewer(aViewer); } nsresult EphyBrowser::GetZoom (float *aZoom) { nsCOMPtr contentViewer; GetContentViewer (getter_AddRefs(contentViewer)); NS_ENSURE_TRUE (contentViewer, NS_ERROR_FAILURE); nsCOMPtr mdv = do_QueryInterface(contentViewer); NS_ENSURE_TRUE (mdv, NS_ERROR_FAILURE); return mdv->GetTextZoom (aZoom); } nsresult EphyBrowser::GetDocument (nsIDOMDocument **aDOMDocument) { return mDOMWindow->GetDocument (aDOMDocument); } nsresult EphyBrowser::GetTargetDocument (nsIDOMDocument **aDOMDocument) { nsresult result; NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE); /* Use the current target document */ if (mTargetDocument) { *aDOMDocument = mTargetDocument.get(); NS_IF_ADDREF(*aDOMDocument); return NS_OK; } /* Use the focused document */ nsCOMPtr webBrowserFocus; webBrowserFocus = do_QueryInterface (mWebBrowser); NS_ENSURE_TRUE (webBrowserFocus, NS_ERROR_FAILURE); nsCOMPtr DOMWindow; result = webBrowserFocus->GetFocusedWindow (getter_AddRefs(DOMWindow)); if (NS_SUCCEEDED(result) && DOMWindow) { return DOMWindow->GetDocument (aDOMDocument); } /* Use the main document */ return mDOMWindow->GetDocument (aDOMDocument); } nsresult EphyBrowser::GetSHInfo (PRInt32 *count, PRInt32 *index) { nsCOMPtr SessionHistory; GetSHistory (getter_AddRefs(SessionHistory)); NS_ENSURE_TRUE (SessionHistory, NS_ERROR_FAILURE); SessionHistory->GetCount (count); SessionHistory->GetIndex (index); return NS_OK; } nsresult EphyBrowser::GetSHTitleAtIndex (PRInt32 index, PRUnichar **title) { nsCOMPtr SessionHistory; GetSHistory (getter_AddRefs(SessionHistory)); NS_ENSURE_TRUE (SessionHistory, NS_ERROR_FAILURE); nsCOMPtr he; SessionHistory->GetEntryAtIndex (index, PR_FALSE, getter_AddRefs (he)); NS_ENSURE_TRUE (he, NS_ERROR_FAILURE); nsresult result; result = he->GetTitle (title); NS_ENSURE_TRUE (NS_SUCCEEDED (result) && title, NS_ERROR_FAILURE); return NS_OK; } nsresult EphyBrowser::GetSHUrlAtIndex (PRInt32 index, nsCString &url) { nsCOMPtr SessionHistory; GetSHistory (getter_AddRefs(SessionHistory)); NS_ENSURE_TRUE (SessionHistory, NS_ERROR_FAILURE); nsCOMPtr he; SessionHistory->GetEntryAtIndex (index, PR_FALSE, getter_AddRefs (he)); NS_ENSURE_TRUE (he, NS_ERROR_FAILURE); nsCOMPtr uri; he->GetURI (getter_AddRefs(uri)); NS_ENSURE_TRUE (uri, NS_ERROR_FAILURE); nsresult result; result = uri->GetSpec(url); NS_ENSURE_TRUE (NS_SUCCEEDED (result) && !url.IsEmpty(), NS_ERROR_FAILURE); return NS_OK; } nsresult EphyBrowser::FindSetProperties (const PRUnichar *search_string, PRBool case_sensitive, PRBool wrap_around) { NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE); nsCOMPtr finder (do_GetInterface(mWebBrowser)); NS_ENSURE_TRUE (finder, NS_ERROR_FAILURE); finder->SetSearchString (search_string); finder->SetMatchCase (case_sensitive); finder->SetWrapFind (wrap_around); return NS_OK; } nsresult EphyBrowser::Find (PRBool backwards, PRBool *didFind) { NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE); nsCOMPtr finder (do_GetInterface(mWebBrowser)); NS_ENSURE_TRUE (finder, NS_ERROR_FAILURE); finder->SetFindBackwards (backwards); return finder->FindNext(didFind); } nsresult EphyBrowser::GetPageDescriptor(nsISupports **aPageDescriptor) { NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE); nsCOMPtr ds = do_GetInterface (mWebBrowser); nsCOMPtr wpd = do_QueryInterface (ds); NS_ENSURE_TRUE (wpd, NS_ERROR_FAILURE); *aPageDescriptor = wpd.get(); NS_IF_ADDREF (*aPageDescriptor); return NS_OK; } nsresult EphyBrowser::GetDocumentUrl (nsCString &url) { if (!mDOMWindow) return NS_ERROR_FAILURE; nsCOMPtr DOMDocument; mDOMWindow->GetDocument (getter_AddRefs(DOMDocument)); NS_ENSURE_TRUE (DOMDocument, NS_ERROR_FAILURE); nsCOMPtr doc = do_QueryInterface(DOMDocument); NS_ENSURE_TRUE (doc, NS_ERROR_FAILURE); #if MOZILLA_SNAPSHOT > 13 nsIURI *uri; uri = doc->GetDocumentURI (); #elif MOZILLA_SNAPSHOT > 11 nsIURI *uri; uri = doc->GetDocumentURL (); #endif NS_ENSURE_TRUE (uri, NS_ERROR_FAILURE); return uri->GetSpec (url); } nsresult EphyBrowser::GetTargetDocumentUrl (nsCString &url) { nsCOMPtr DOMDocument; GetTargetDocument (getter_AddRefs(DOMDocument)); NS_ENSURE_TRUE (DOMDocument, NS_ERROR_FAILURE); nsCOMPtr doc = do_QueryInterface(DOMDocument); NS_ENSURE_TRUE (doc, NS_ERROR_FAILURE); #if MOZILLA_SNAPSHOT > 13 nsIURI *uri; uri = doc->GetDocumentURI (); #elif MOZILLA_SNAPSHOT > 11 nsIURI *uri; uri = doc->GetDocumentURL (); #endif NS_ENSURE_TRUE (uri, NS_ERROR_FAILURE); return uri->GetSpec (url); } nsresult EphyBrowser::ForceEncoding (const char *encoding) { NS_ENSURE_TRUE (mInitialized, NS_ERROR_FAILURE); nsCOMPtr contentViewer; GetContentViewer (getter_AddRefs(contentViewer)); NS_ENSURE_TRUE (contentViewer, NS_ERROR_FAILURE); nsCOMPtr mdv = do_QueryInterface(contentViewer); NS_ENSURE_TRUE (mdv, NS_ERROR_FAILURE); return mdv->SetForceCharacterSet (nsDependentCString(encoding)); } nsresult EphyBrowser::GetEncoding (nsACString &encoding) { NS_ENSURE_TRUE (mInitialized, NS_ERROR_FAILURE); nsCOMPtr domDoc; GetTargetDocument (getter_AddRefs(domDoc)); NS_ENSURE_TRUE (domDoc, NS_ERROR_FAILURE); nsCOMPtr doc = do_QueryInterface(domDoc); NS_ENSURE_TRUE (doc, NS_ERROR_FAILURE); encoding = doc->GetDocumentCharacterSet (); NS_ENSURE_TRUE (!encoding.IsEmpty(), NS_ERROR_FAILURE); return NS_OK; } nsresult EphyBrowser::GetForcedEncoding (nsACString &encoding) { NS_ENSURE_TRUE (mInitialized, NS_ERROR_FAILURE); nsCOMPtr contentViewer; GetContentViewer (getter_AddRefs(contentViewer)); NS_ENSURE_TRUE (contentViewer, NS_ERROR_FAILURE); nsCOMPtr mdv = do_QueryInterface(contentViewer); NS_ENSURE_TRUE (mdv, NS_ERROR_FAILURE); nsresult result = mdv->GetForceCharacterSet (encoding); NS_ENSURE_SUCCESS (result, NS_ERROR_FAILURE); return NS_OK; } nsresult EphyBrowser::PushTargetDocument (nsIDOMDocument *domDoc) { mTargetDocument = domDoc; return NS_OK; } nsresult EphyBrowser::PopTargetDocument () { mTargetDocument = nsnull; return NS_OK; } nsresult EphyBrowser::DoCommand (const char *command) { nsCOMPtr cmdManager; NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE); cmdManager = do_GetInterface (mWebBrowser); NS_ENSURE_TRUE (cmdManager, NS_ERROR_FAILURE); return cmdManager->DoCommand (command, nsnull, nsnull); } nsresult EphyBrowser::GetCommandState (const char *command, PRBool *enabled) { nsCOMPtr cmdManager; NS_ENSURE_TRUE (mWebBrowser, NS_ERROR_FAILURE); cmdManager = do_GetInterface (mWebBrowser); NS_ENSURE_TRUE (cmdManager, NS_ERROR_FAILURE); return cmdManager->IsCommandEnabled (command, nsnull, enabled); } #define NUM_MODIFIED_TEXTFIELDS_REQUIRED 2 nsresult EphyBrowser::GetDocumentHasModifiedForms (nsIDOMDocument *aDomDoc, PRUint32 *aNumTextFields, PRBool *aHasTextArea) { nsCOMPtr htmlDoc = do_QueryInterface(aDomDoc); /* it's okay not to be a HTML doc (happens for XUL documents, like about:config) */ if (!htmlDoc) return NS_OK; nsCOMPtr 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 formNode; forms->Item (formIndex, getter_AddRefs (formNode)); if (!formNode) continue; nsCOMPtr formElement = do_QueryInterface (formNode); if (!formElement) continue; nsCOMPtr 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 domNode; formElements->Item (elementIndex, getter_AddRefs (domNode)); if (!domNode) continue; nsCOMPtr areaElement = do_QueryInterface (domNode); if (areaElement) { nsAutoString 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)) { *aHasTextArea = PR_TRUE; return NS_OK; } continue; } nsCOMPtr inputElement = do_QueryInterface(domNode); if (!inputElement) continue; nsAutoString type; inputElement->GetType(type); if (type.EqualsIgnoreCase("text")) { nsAutoString 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) * Mozilla bug 232057 */ if (default_text.Length() > (PRUint32)max_length) { default_text.Truncate (max_length); } /* Mozilla Bug 218277, 195946 and others */ default_text.ReplaceChar(0xa0, ' '); if (!user_text.Equals (default_text)) { (*aNumTextFields)++; if (*aNumTextFields >= NUM_MODIFIED_TEXTFIELDS_REQUIRED) { return NS_OK; } } } } } return NS_OK; } nsresult EphyBrowser::GetHasModifiedForms (PRBool *modified) { *modified = PR_FALSE; nsCOMPtr rootDocShell = do_GetInterface (mWebBrowser); NS_ENSURE_TRUE (rootDocShell, NS_ERROR_FAILURE); nsCOMPtr enumerator; rootDocShell->GetDocShellEnumerator(nsIDocShellTreeItem::typeContent, nsIDocShell::ENUMERATE_FORWARDS, getter_AddRefs(enumerator)); NS_ENSURE_TRUE (enumerator, NS_ERROR_FAILURE); PRBool hasMore; PRBool hasTextArea = PR_FALSE; PRUint32 numTextFields = 0; while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore) { nsCOMPtr element; enumerator->GetNext (getter_AddRefs(element)); if (!element) continue; nsCOMPtr docShell = do_QueryInterface (element); if (!docShell) continue; nsCOMPtr contentViewer; docShell->GetContentViewer (getter_AddRefs(contentViewer)); if (!contentViewer) continue; nsCOMPtr domDoc; contentViewer->GetDOMDocument (getter_AddRefs (domDoc)); nsresult result; result = GetDocumentHasModifiedForms (domDoc, &numTextFields, &hasTextArea); if (NS_SUCCEEDED (result) && (numTextFields >= NUM_MODIFIED_TEXTFIELDS_REQUIRED || hasTextArea)) { *modified = PR_TRUE; break; } } return NS_OK; }