/* * Copyright (C) 2000-2003 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 "ephy-embed.h" #include "ephy-string.h" #include #include #include "nsICommandManager.h" #include "nsIContentViewer.h" #include "nsIGlobalHistory.h" #include "nsIDocShellHistory.h" #include "nsIWebBrowserFind.h" #include "nsIWebBrowserFocus.h" #include "nsIDocument.h" #include "nsISHEntry.h" #include "nsISHistoryInternal.h" #include "nsIHistoryEntry.h" #include "nsIWebBrowserPrint.h" #include "nsIURI.h" #include "nsIMarkupDocumentViewer.h" #include "nsIComponentManager.h" #include "nsIScriptGlobalObject.h" #include "nsIDOMWindowInternal.h" #include "nsIInterfaceRequestor.h" #include "nsIFocusController.h" #include "nsIWebBrowserPersist.h" #include "nsCWebBrowserPersist.h" #include "nsNetUtil.h" #include "nsIChromeEventHandler.h" #include "nsIDOMDocument.h" #include "nsIDOMDocumentStyle.h" #include "nsIDOMEvent.h" #include "nsIDOMEventTarget.h" #include "nsIDOMNode.h" #include "nsIDOMElement.h" #include "nsIDOMPopupBlockedEvent.h" #include "nsIDocShellTreeItem.h" #include "nsIDocShellTreeNode.h" #include "nsIDocShellTreeOwner.h" #include "nsIHTMLContentContainer.h" #include "nsICSSLoader.h" #include "nsICSSStyleSheet.h" #include "nsICSSLoaderObserver.h" #include "nsIStyleSet.h" #include "nsIDocumentObserver.h" #include "nsCWebBrowser.h" #include "nsReadableUtils.h" #include "nsIDOMNSHTMLDocument.h" #include "nsIDOMHTMLDocument.h" #include "nsIDOMHTMLCollection.h" #include "nsIDOMHTMLElement.h" #include "nsIDOMHTMLFormElement.h" #include "nsIDOMHTMLInputElement.h" #include "nsIDOMHTMLTextAreaElement.h" #include "nsIDeviceContext.h" #include "nsIPresContext.h" #include "nsIAtom.h" #include "nsIDocumentCharsetInfo.h" #include "nsPromiseFlatString.h" #include "nsString.h" #include "nsUnicharUtils.h" #include "ContentHandler.h" EphyEventListener::EphyEventListener(void) { mOwner = nsnull; } EphyEventListener::~EphyEventListener() { } 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.Equals(NS_LITERAL_STRING("SHORTCUT ICON"), nsCaseInsensitiveStringComparator()) || value.Equals(NS_LITERAL_STRING("ICON"), nsCaseInsensitiveStringComparator())) { 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; result = node->GetOwnerDocument(getter_AddRefs(domDoc)); if (NS_FAILED(result) || !domDoc) return NS_ERROR_FAILURE; nsCOMPtr doc = do_QueryInterface (domDoc); if(!doc) return NS_ERROR_FAILURE; #if MOZILLA_SNAPSHOT > 11 nsIURI *uri; uri = doc->GetDocumentURL (); if (uri == NULL) return NS_ERROR_FAILURE; #else nsCOMPtr uri; result = doc->GetDocumentURL(getter_AddRefs(uri)); if (NS_FAILED (result)) return NS_ERROR_FAILURE; #endif const nsACString &link = NS_ConvertUCS2toUTF8(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)); nsresult result; nsCOMPtr node = do_QueryInterface(eventTarget, &result); if (NS_FAILED(result) || !node) return NS_ERROR_FAILURE; HandleFaviconLink (node); return NS_OK; } NS_IMETHODIMP EphyPopupEventListener::HandleEvent(nsIDOMEvent* aDOMEvent) { nsresult rv; nsCOMPtr popupEvent = do_QueryInterface(aDOMEvent, &rv); if (NS_FAILED(rv)) return NS_ERROR_FAILURE; if (popupEvent) { g_signal_emit_by_name (mOwner, "ge_popup_blocked"); } return NS_OK; } EphyBrowser::EphyBrowser () { mFaviconEventListener = nsnull; mPopupEventListener = nsnull; mEventReceiver = nsnull; } EphyBrowser::~EphyBrowser () { } nsresult EphyBrowser::Init (GtkMozEmbed *mozembed) { nsresult rv; gtk_moz_embed_get_nsIWebBrowser (mozembed, getter_AddRefs(mWebBrowser)); if (!mWebBrowser) return NS_ERROR_FAILURE; mWebBrowser->GetContentDOMWindow (getter_AddRefs (mDOMWindow)); /* This will instantiate an about:blank doc if necessary */ nsCOMPtr domDocument; rv = mDOMWindow->GetDocument (getter_AddRefs (domDocument)); if (NS_FAILED (rv)) return NS_ERROR_FAILURE; mFaviconEventListener = new EphyFaviconEventListener(); mPopupEventListener = new EphyPopupEventListener(); rv = mFaviconEventListener->Init (EPHY_EMBED (mozembed)); if (NS_FAILED (rv)) return NS_ERROR_FAILURE; rv = mPopupEventListener->Init (EPHY_EMBED (mozembed)); if (NS_FAILED (rv)) return NS_ERROR_FAILURE; rv = GetListener(); if (NS_FAILED (rv)) return NS_ERROR_FAILURE; 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)); if (!piWin) return NS_ERROR_FAILURE; nsCOMPtr chromeHandler; piWin->GetChromeEventHandler(getter_AddRefs(chromeHandler)); mEventReceiver = do_QueryInterface(chromeHandler); if (!mEventReceiver) return NS_ERROR_FAILURE; return NS_OK; } nsresult EphyBrowser::AttachListeners(void) { nsresult rv; if (!mEventReceiver) return NS_ERROR_FAILURE; nsCOMPtr target; target = do_QueryInterface (mEventReceiver); rv = target->AddEventListener(NS_LITERAL_STRING("DOMLinkAdded"), mFaviconEventListener, PR_FALSE); if (NS_FAILED (rv)) return NS_ERROR_FAILURE; return target->AddEventListener(NS_LITERAL_STRING("DOMPopupBlocked"), mPopupEventListener, PR_FALSE); } nsresult EphyBrowser::DetachListeners(void) { nsresult rv; if (!mEventReceiver) return NS_ERROR_FAILURE; nsCOMPtr target; target = do_QueryInterface (mEventReceiver); rv = target->RemoveEventListener(NS_LITERAL_STRING("DOMLinkAdded"), mFaviconEventListener, PR_FALSE); if (NS_FAILED (rv)) return NS_ERROR_FAILURE; return target->RemoveEventListener(NS_LITERAL_STRING("DOMPopupBlocked"), mPopupEventListener, PR_FALSE); } nsresult EphyBrowser::Print (nsIPrintSettings *options, PRBool preview) { nsresult result; g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE); nsCOMPtr print(do_GetInterface(mWebBrowser, &result)); if (NS_FAILED(result) || !print) return 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; g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE); nsCOMPtr print(do_GetInterface(mWebBrowser, &rv)); if (NS_FAILED(rv) || !print) return NS_ERROR_FAILURE; rv = print->GetDoingPrintPreview(&isPreview); if (NS_SUCCEEDED (rv) && isPreview == PR_TRUE) { rv = print->ExitPrintPreview(); } return rv; } nsresult EphyBrowser::PrintPreviewNumPages (int *numPages) { nsresult rv; g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE); nsCOMPtr print(do_GetInterface(mWebBrowser, &rv)); if (NS_FAILED(rv) || !print) return NS_ERROR_FAILURE; rv = print->GetPrintPreviewNumPages(numPages); return rv; } nsresult EphyBrowser::PrintPreviewNavigate(PRInt16 navType, PRInt32 pageNum) { nsresult rv; g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE); nsCOMPtr print(do_GetInterface(mWebBrowser, &rv)); if (NS_FAILED(rv) || !print) return NS_ERROR_FAILURE; rv = print->PrintPreviewNavigate(navType, pageNum); return rv; } nsresult EphyBrowser::GetPrintSettings (nsIPrintSettings **options) { nsresult result; g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE); nsCOMPtr print(do_GetInterface(mWebBrowser, &result)); if (NS_FAILED(result) || !print) return NS_ERROR_FAILURE; return print->GetGlobalPrintSettings(options); } nsresult EphyBrowser::GetSHistory (nsISHistory **aSHistory) { nsresult result; g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE); nsCOMPtr ContentNav = do_QueryInterface (mWebBrowser); if (!ContentNav) return NS_ERROR_FAILURE; nsCOMPtr SessionHistory; result = ContentNav->GetSessionHistory (getter_AddRefs (SessionHistory)); if (!SessionHistory) return 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) { nsresult result; g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE); nsCOMPtr ContentNav = do_QueryInterface (mWebBrowser); if (!ContentNav) return NS_ERROR_FAILURE; return ContentNav->GotoIndex (index); } nsresult EphyBrowser::SetZoom (float aZoom, PRBool reflow) { nsresult result; g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE); if (reflow) { nsCOMPtr contentViewer; result = GetContentViewer (getter_AddRefs(contentViewer)); if (!NS_SUCCEEDED (result) || !contentViewer) return NS_ERROR_FAILURE; nsCOMPtr mdv = do_QueryInterface(contentViewer, &result); if (NS_FAILED(result) || !mdv) return NS_ERROR_FAILURE; return mdv->SetTextZoom (aZoom); } else { nsCOMPtr DocShell; DocShell = do_GetInterface (mWebBrowser); if (!DocShell) return 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) { nsresult result; nsCOMPtr PresContext; result = DocShell->GetPresContext (getter_AddRefs(PresContext)); if (NS_FAILED(result) || !PresContext) return NS_ERROR_FAILURE; nsCOMPtr DeviceContext; result = PresContext->GetDeviceContext (getter_AddRefs(DeviceContext)); if (NS_FAILED(result) || !DeviceContext) return NS_ERROR_FAILURE; return DeviceContext->SetTextZoom (aZoom); } nsresult EphyBrowser::GetContentViewer (nsIContentViewer **aViewer) { g_return_val_if_fail (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) { nsresult result; nsCOMPtr contentViewer; result = GetContentViewer (getter_AddRefs(contentViewer)); if (!NS_SUCCEEDED (result) || !contentViewer) return NS_ERROR_FAILURE; nsCOMPtr mdv = do_QueryInterface(contentViewer, &result); if (NS_FAILED(result) || !mdv) return NS_ERROR_FAILURE; return mdv->GetTextZoom (aZoom); } nsresult EphyBrowser::GetDocument (nsIDOMDocument **aDOMDocument) { return mDOMWindow->GetDocument (aDOMDocument); } nsresult EphyBrowser::GetTargetDocument (nsIDOMDocument **aDOMDocument) { nsresult result; g_return_val_if_fail (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); if (!webBrowserFocus) return 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) { nsresult result; nsCOMPtr SessionHistory; result = GetSHistory (getter_AddRefs(SessionHistory)); if (NS_FAILED(result) || ! SessionHistory) return NS_ERROR_FAILURE; SessionHistory->GetCount (count); SessionHistory->GetIndex (index); return NS_OK; } nsresult EphyBrowser::GetSHTitleAtIndex (PRInt32 index, PRUnichar **title) { nsresult result; nsCOMPtr SessionHistory; result = GetSHistory (getter_AddRefs(SessionHistory)); if (NS_FAILED(result) || ! SessionHistory) return NS_ERROR_FAILURE; nsCOMPtr he; result = SessionHistory->GetEntryAtIndex (index, PR_FALSE, getter_AddRefs (he)); if (!NS_SUCCEEDED(result) || (!he)) return NS_ERROR_FAILURE; result = he->GetTitle (title); if (!NS_SUCCEEDED(result) || (!title)) return NS_ERROR_FAILURE; return NS_OK; } nsresult EphyBrowser::GetSHUrlAtIndex (PRInt32 index, nsCString &url) { nsresult result; nsCOMPtr SessionHistory; result = GetSHistory (getter_AddRefs(SessionHistory)); if (NS_FAILED(result) || ! SessionHistory) return NS_ERROR_FAILURE; nsCOMPtr he; result = SessionHistory->GetEntryAtIndex (index, PR_FALSE, getter_AddRefs (he)); if (NS_FAILED(result) || (!he)) return NS_ERROR_FAILURE; nsCOMPtr uri; result = he->GetURI (getter_AddRefs(uri)); if (NS_FAILED(result) || (!uri)) return NS_ERROR_FAILURE; result = uri->GetSpec(url); if (NS_FAILED(result) || url.IsEmpty()) return NS_ERROR_FAILURE; return NS_OK; } nsresult EphyBrowser::FindSetProperties (const PRUnichar *search_string, PRBool case_sensitive, PRBool wrap_around) { g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE); nsCOMPtr finder (do_GetInterface(mWebBrowser)); finder->SetSearchString (search_string); finder->SetMatchCase (case_sensitive); finder->SetWrapFind (wrap_around); return NS_OK; } nsresult EphyBrowser::Find (PRBool backwards, PRBool *didFind) { g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE); nsCOMPtr finder (do_GetInterface(mWebBrowser)); finder->SetFindBackwards (backwards); return finder->FindNext(didFind); } nsresult EphyBrowser::GetPageDescriptor(nsISupports **aPageDescriptor) { nsresult rv; g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE); nsCOMPtr ds; ds = do_GetInterface (mWebBrowser); nsCOMPtr wpd = do_QueryInterface (ds); if (!wpd) return NS_ERROR_FAILURE; *aPageDescriptor = wpd.get(); NS_IF_ADDREF (*aPageDescriptor); return NS_OK; } nsresult EphyBrowser::GetDocumentUrl (nsCString &url) { nsresult result; nsCOMPtr DOMDocument; result = mDOMWindow->GetDocument (getter_AddRefs(DOMDocument)); if (NS_FAILED(result) || !DOMDocument) return NS_ERROR_FAILURE; nsCOMPtr doc = do_QueryInterface(DOMDocument); if(!doc) return NS_ERROR_FAILURE; #if MOZILLA_SNAPSHOT > 11 nsIURI *uri; uri = doc->GetDocumentURL (); #else nsCOMPtr uri; doc->GetDocumentURL(getter_AddRefs(uri)); #endif if (!uri) return NS_ERROR_FAILURE; return uri->GetSpec (url); } nsresult EphyBrowser::GetTargetDocumentUrl (nsCString &url) { nsresult result; nsCOMPtr DOMDocument; result = GetTargetDocument (getter_AddRefs(DOMDocument)); if (NS_FAILED(result) || !DOMDocument) return NS_ERROR_FAILURE; nsCOMPtr doc = do_QueryInterface(DOMDocument); if(!doc) return NS_ERROR_FAILURE; #if MOZILLA_SNAPSHOT > 11 nsIURI *uri; uri = doc->GetDocumentURL (); #else nsCOMPtr uri; doc->GetDocumentURL(getter_AddRefs(uri)); #endif if (!uri) return NS_ERROR_FAILURE; return uri->GetSpec (url); } nsresult EphyBrowser::ForceEncoding (const char *encoding) { nsresult result; nsCOMPtr contentViewer; result = GetContentViewer (getter_AddRefs(contentViewer)); if (!NS_SUCCEEDED (result) || !contentViewer) return NS_ERROR_FAILURE; nsCOMPtr mdv = do_QueryInterface(contentViewer); if (!mdv) return NS_ERROR_FAILURE; #if MOZILLA_SNAPSHOT > 9 result = mdv->SetForceCharacterSet (nsDependentCString(encoding)); #else result = mdv->SetForceCharacterSet (NS_ConvertUTF8toUCS2(encoding).get()); #endif return result; } nsresult EphyBrowser::PushTargetDocument (nsIDOMDocument *domDoc) { mTargetDocument = domDoc; return NS_OK; } nsresult EphyBrowser::PopTargetDocument () { mTargetDocument = nsnull; return NS_OK; } nsresult EphyBrowser::GetEncodingInfo (EphyEncodingInfo **infoptr) { nsresult result; EphyEncodingInfo *info; nsCOMPtr domDoc; result = GetTargetDocument (getter_AddRefs(domDoc)); if (NS_FAILED (result) || !domDoc) return NS_ERROR_FAILURE; nsCOMPtr doc = do_QueryInterface(domDoc, &result); if (NS_FAILED (result) || !doc) return NS_ERROR_FAILURE; info = g_new0 (EphyEncodingInfo, 1); *infoptr = info; PRInt32 source; #if MOZILLA_SNAPSHOT > 11 source = doc->GetDocumentCharacterSetSource (); #else result = doc->GetDocumentCharacterSetSource (&source); if (NS_FAILED (result)) return NS_ERROR_FAILURE; #endif info->encoding_source = (EphyEncodingSource) source; nsCOMPtr ds; ds = do_GetInterface (mWebBrowser); if (!ds) return NS_ERROR_FAILURE; nsCOMPtr ci; result = ds->GetDocumentCharsetInfo (getter_AddRefs (ci)); if (NS_FAILED(result) || !ci) return NS_ERROR_FAILURE; nsCOMPtr atom; result = ci->GetForcedCharset (getter_AddRefs (atom)); if (NS_FAILED(result)) return NS_ERROR_FAILURE; if (atom) { nsCAutoString atomstr; atom->ToUTF8String (atomstr); info->forced_encoding = g_strdup (atomstr.get()); } result = ci->GetParentCharset (getter_AddRefs (atom)); if (NS_FAILED(result)) return NS_ERROR_FAILURE; if (atom) { nsCAutoString atomstr; atom->ToUTF8String (atomstr); info->parent_encoding = g_strdup (atomstr.get()); } result = ci->GetParentCharsetSource (&source); if (NS_FAILED (result)) return NS_ERROR_FAILURE; info->parent_encoding_source = (EphyEncodingSource) source; nsCOMPtr contentViewer; result = ds->GetContentViewer (getter_AddRefs(contentViewer)); if (!NS_SUCCEEDED (result) || !contentViewer) return NS_ERROR_FAILURE; nsCOMPtr mdv = do_QueryInterface(contentViewer, &result); if (NS_FAILED(result) || !mdv) return NS_ERROR_FAILURE; #if MOZILLA_SNAPSHOT > 11 const nsACString& charsetEnc = doc->GetDocumentCharacterSet (); if (charsetEnc.IsEmpty()) return NS_ERROR_FAILURE; info->encoding = g_strdup (PromiseFlatCString(charsetEnc).get()); #elif MOZILLA_SNAPSHOT >= 10 nsCAutoString charsetEnc; result = doc->GetDocumentCharacterSet (charsetEnc); if (NS_FAILED (result)) return NS_ERROR_FAILURE; info->encoding = g_strdup (charsetEnc.get()); #else nsAutoString charsetEnc; result = doc->GetDocumentCharacterSet (charsetEnc); if (NS_FAILED (result)) return NS_ERROR_FAILURE; info->encoding = g_strdup (NS_ConvertUCS2toUTF8(charsetEnc).get()); #endif #if MOZILLA_SNAPSHOT >= 10 nsCAutoString enc; result = mdv->GetDefaultCharacterSet (enc); if (NS_FAILED (result)) return NS_ERROR_FAILURE; info->default_encoding = g_strdup (enc.get()); result = mdv->GetForceCharacterSet (enc); if (NS_FAILED (result)) return NS_ERROR_FAILURE; info->forced_encoding = g_strdup (enc.get()); result = mdv->GetHintCharacterSet (enc); if (NS_FAILED (result)) return NS_ERROR_FAILURE; info->hint_encoding = g_strdup (enc.get()); result = mdv->GetPrevDocCharacterSet (enc); if (NS_FAILED (result)) return NS_ERROR_FAILURE; info->prev_doc_encoding = g_strdup (enc.get()); #else PRUnichar *str; result = mdv->GetDefaultCharacterSet (&str); if (NS_FAILED (result)) return NS_ERROR_FAILURE; info->default_encoding = g_strdup (NS_ConvertUCS2toUTF8(str).get()); result = mdv->GetForceCharacterSet (&str); if (NS_FAILED (result)) return NS_ERROR_FAILURE; info->forced_encoding = g_strdup (NS_ConvertUCS2toUTF8(str).get()); result = mdv->GetHintCharacterSet (&str); if (NS_FAILED (result)) return NS_ERROR_FAILURE; info->hint_encoding = g_strdup (NS_ConvertUCS2toUTF8(str).get()); result = mdv->GetPrevDocCharacterSet (&str); if (NS_FAILED (result)) return NS_ERROR_FAILURE; info->prev_doc_encoding = g_strdup (NS_ConvertUCS2toUTF8(str).get()); #endif mdv->GetHintCharacterSetSource (&source); if (NS_FAILED (result)) return NS_ERROR_FAILURE; info->hint_encoding_source = (EphyEncodingSource) source; return NS_OK; } nsresult EphyBrowser::DoCommand (const char *command) { nsCOMPtr cmdManager; g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE); cmdManager = do_GetInterface (mWebBrowser); if (!cmdManager) return NS_ERROR_FAILURE; return cmdManager->DoCommand (command, nsnull, nsnull); } nsresult EphyBrowser::GetCommandState (const char *command, PRBool *enabled) { nsCOMPtr cmdManager; g_return_val_if_fail (mWebBrowser, NS_ERROR_FAILURE); cmdManager = do_GetInterface (mWebBrowser); if (!cmdManager) return 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); NS_ENSURE_TRUE (htmlDoc, NS_ERROR_FAILURE); 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); if (Compare (user_text, default_text) != 0) { *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; inputElement->GetDefaultValue (default_text); inputElement->GetValue (user_text); if (Compare (user_text, default_text) != 0) { (*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; }