From 2fb0fc711a46e4fb8e74922b69cd8814cc534095 Mon Sep 17 00:00:00 2001 From: "peterv@propagandism.org" Date: Wed, 11 Jul 2007 06:05:05 -0700 Subject: [PATCH] Fix for bug 386496 (Clicking on link in designMode document does follow that link now). r/sr=bz. --- content/base/public/nsContentUtils.h | 19 +++++ content/base/public/nsINode.h | 19 ++++- content/base/src/nsContentUtils.cpp | 43 ++++++++++++ content/base/src/nsGenericElement.cpp | 69 ++++++------------- content/base/src/nsGenericElement.h | 20 ------ .../html/content/src/nsHTMLFormElement.cpp | 2 +- content/xml/content/src/nsXMLElement.cpp | 3 +- docshell/base/nsWebShell.cpp | 6 +- .../activex/src/plugin/XPCDocument.cpp | 2 + layout/forms/nsIsIndexFrame.cpp | 4 ++ layout/generic/nsImageFrame.cpp | 44 ++---------- layout/generic/nsImageFrame.h | 8 +-- layout/generic/nsObjectFrame.cpp | 4 ++ 13 files changed, 119 insertions(+), 124 deletions(-) diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index 05b80825ec4..7a36c730b59 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -1068,6 +1068,25 @@ public: const nsACString& aMimeGuess = EmptyCString(), nsISupports* aExtra = nsnull); + /** + * Trigger a link with uri aLinkURI. If aClick is false, this triggers a + * mouseover on the link, otherwise it triggers a load after doing a + * security check using aContent's principal. + * + * @param aContent the node on which a link was triggered. + * @param aPresContext the pres context, must be non-null. + * @param aLinkURI the URI of the link, must be non-null. + * @param aTargetSpec the target (like target=, may be empty). + * @param aClick whether this was a click or not (if false, this method + * assumes you just hovered over the link). + * @param aIsUserTriggered whether the user triggered the link. This would be + * false for loads from auto XLinks or from the + * click() method if we ever implement it. + */ + static void TriggerLink(nsIContent *aContent, nsPresContext *aPresContext, + nsIURI *aLinkURI, const nsString& aTargetSpec, + PRBool aClick, PRBool aIsUserTriggered); + private: static PRBool InitializeEventTable(); diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index c7bc6ea2900..87f7a3617f3 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -118,8 +118,8 @@ inline nsINode* NODE_FROM(C& aContent, D& aDocument) // IID for the nsINode interface #define NS_INODE_IID \ -{ 0xd3e63f80, 0x9e98, 0x47d7, \ - { 0xac, 0x8d, 0xad, 0x6f, 0x20, 0x6c, 0xe7, 0xc6 } } +{ 0x8cef8b4e, 0x4b7f, 0x4f86, \ + { 0xba, 0x64, 0x75, 0xdf, 0xed, 0x0d, 0xa2, 0x3e } } // hack to make egcs / gcc 2.95.2 happy class nsINode_base : public nsPIDOMEventTarget { @@ -619,6 +619,15 @@ public: } } + PRBool IsEditable() const + { +#ifdef _IMPL_NS_LAYOUT + return IsEditableInternal(); +#else + return IsEditableExternal(); +#endif + } + protected: // Override this function to create a custom slots class. @@ -654,6 +663,12 @@ protected: return slots; } + PRBool IsEditableInternal() const; + virtual PRBool IsEditableExternal() const + { + return IsEditableInternal(); + } + nsCOMPtr mNodeInfo; enum { PARENT_BIT_INDOCUMENT = 1 << 0, PARENT_BIT_PARENT_IS_CONTENT = 1 << 1 }; diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index ad8bc36d17f..2090433b643 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -3623,3 +3623,46 @@ nsContentUtils::CheckSecurityBeforeLoad(nsIURI* aURIToLoad, } return sSecurityManager->CheckSameOriginURI(loadingURI, aURIToLoad); } + +/* static */ +void +nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext, + nsIURI *aLinkURI, const nsString &aTargetSpec, + PRBool aClick, PRBool aIsUserTriggered) +{ + NS_ASSERTION(aPresContext, "Need a nsPresContext"); + NS_PRECONDITION(aLinkURI, "No link URI"); + + if (aContent->IsEditable()) { + return; + } + + nsILinkHandler *handler = aPresContext->GetLinkHandler(); + if (!handler) { + return; + } + + if (!aClick) { + handler->OnOverLink(aContent, aLinkURI, aTargetSpec.get()); + + return; + } + + // Check that this page is allowed to load this URI. + nsresult proceed = NS_OK; + + if (sSecurityManager) { + PRUint32 flag = + aIsUserTriggered ? + (PRUint32)nsIScriptSecurityManager::STANDARD : + (PRUint32)nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT; + proceed = + sSecurityManager->CheckLoadURIWithPrincipal(aContent->NodePrincipal(), + aLinkURI, flag); + } + + // Only pass off the click event if the script security manager says it's ok. + if (NS_SUCCEEDED(proceed)) { + handler->OnLinkClick(aContent, aLinkURI, aTargetSpec.get()); + } +} diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index ba9069a3113..e9027d92b45 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -291,6 +291,20 @@ nsINode::RemoveMutationObserver(nsIMutationObserver* aMutationObserver) } } +PRBool +nsINode::IsEditableInternal() const +{ + if (HasFlag(NODE_IS_EDITABLE)) { + // The node is in an editable contentEditable subtree. + return PR_TRUE; + } + + nsIDocument *doc = GetCurrentDoc(); + + // Check if the node is in a document and the document is in designMode. + return doc && doc->HasFlag(NODE_IS_EDITABLE); +} + //---------------------------------------------------------------------- void @@ -308,15 +322,8 @@ nsIContent::SetNativeAnonymous(PRBool aAnonymous) PRInt32 nsIContent::IntrinsicState() const { - PRBool editable = HasFlag(NODE_IS_EDITABLE); - if (!editable) { - nsIDocument *doc = GetCurrentDoc(); - if (doc) { - editable = doc->HasFlag(NODE_IS_EDITABLE); - } - } - - return editable ? NS_EVENT_STATE_MOZ_READWRITE : NS_EVENT_STATE_MOZ_READONLY; + return IsEditable() ? NS_EVENT_STATE_MOZ_READWRITE : + NS_EVENT_STATE_MOZ_READONLY; } void @@ -3414,44 +3421,6 @@ nsGenericElement::LeaveLink(nsPresContext* aPresContext) return handler->OnLeaveLink(); } -nsresult -nsGenericElement::TriggerLink(nsPresContext* aPresContext, - nsIURI* aLinkURI, - const nsAFlatString& aTargetSpec, - PRBool aClick, - PRBool aIsUserTriggered) -{ - NS_PRECONDITION(aLinkURI, "No link URI"); - nsresult rv = NS_OK; - - nsILinkHandler *handler = aPresContext->GetLinkHandler(); - if (!handler) return NS_OK; - - if (aClick) { - nsresult proceed = NS_OK; - // Check that this page is allowed to load this URI. - nsCOMPtr securityManager = - do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); - if (NS_SUCCEEDED(rv)) { - PRUint32 flag = - aIsUserTriggered ? - (PRUint32) nsIScriptSecurityManager::STANDARD : - (PRUint32) nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT; - proceed = - securityManager->CheckLoadURIWithPrincipal(NodePrincipal(), aLinkURI, - flag); - } - - // Only pass off the click event if the script security manager - // says it's ok. - if (NS_SUCCEEDED(proceed)) - handler->OnLinkClick(this, aLinkURI, aTargetSpec.get()); - } else { - handler->OnOverLink(this, aLinkURI, aTargetSpec.get()); - } - return rv; -} - nsresult nsGenericElement::AddScriptEventListener(nsIAtom* aEventName, const nsAString& aValue, @@ -4165,7 +4134,8 @@ nsGenericElement::PreHandleEventForLinks(nsEventChainPreVisitor& aVisitor) { nsAutoString target; GetLinkTarget(target); - rv = TriggerLink(aVisitor.mPresContext, absURI, target, PR_FALSE, PR_TRUE); + nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target, + PR_FALSE, PR_TRUE); } break; @@ -4269,7 +4239,8 @@ nsGenericElement::PostHandleEventForLinks(nsEventChainPostVisitor& aVisitor) { nsAutoString target; GetLinkTarget(target); - rv = TriggerLink(aVisitor.mPresContext, absURI, target, PR_TRUE, PR_TRUE); + nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target, + PR_TRUE, PR_TRUE); } break; diff --git a/content/base/src/nsGenericElement.h b/content/base/src/nsGenericElement.h index b6103e0e22f..3b8c9b835d5 100644 --- a/content/base/src/nsGenericElement.h +++ b/content/base/src/nsGenericElement.h @@ -553,26 +553,6 @@ public: const nsAString& aValue, PRBool aDefer = PR_TRUE); - /** - * Trigger a link with uri aLinkURI. If aClick is false, this triggers a - * mouseover on the link, otherwise it triggers a load, after doing a - * security check. The node principal of |this| is used for the security - * check. - * - * @param aPresContext the pres context. - * @param aLinkURI the URI of the link - * @param aTargetSpec the target (like target=, may be empty) - * @param aClick whether this was a click or not (if false, it assumes you - * just hovered over the link) - * @param aIsUserTriggered whether the user triggered the link. - * This would be false for loads from auto XLinks or from the - * click() method if we ever implement it. - */ - nsresult TriggerLink(nsPresContext* aPresContext, - nsIURI* aLinkURI, - const nsAFlatString& aTargetSpec, - PRBool aClick, - PRBool aIsUserTriggered); /** * Do whatever needs to be done when the mouse leaves a link */ diff --git a/content/html/content/src/nsHTMLFormElement.cpp b/content/html/content/src/nsHTMLFormElement.cpp index 68fd85bddf3..68b7a3b977e 100644 --- a/content/html/content/src/nsHTMLFormElement.cpp +++ b/content/html/content/src/nsHTMLFormElement.cpp @@ -981,7 +981,7 @@ nsHTMLFormElement::SubmitSubmission(nsIFormSubmission* aFormSubmission) nsIDocument* doc = GetCurrentDoc(); nsCOMPtr container = doc ? doc->GetContainer() : nsnull; nsCOMPtr linkHandler(do_QueryInterface(container)); - if (!linkHandler) { + if (!linkHandler || IsEditable()) { mIsSubmitting = PR_FALSE; return NS_OK; } diff --git a/content/xml/content/src/nsXMLElement.cpp b/content/xml/content/src/nsXMLElement.cpp index 803926d0439..5fb4f6765dd 100644 --- a/content/xml/content/src/nsXMLElement.cpp +++ b/content/xml/content/src/nsXMLElement.cpp @@ -188,8 +188,7 @@ nsXMLElement::MaybeTriggerAutoLink(nsIDocShell *aShell) nsresult rv = DocShellToPresContext(aShell, getter_AddRefs(pc)); NS_ENSURE_SUCCESS(rv, rv); - rv = TriggerLink(pc, absURI, target, PR_TRUE, PR_FALSE); - NS_ENSURE_SUCCESS(rv, rv); + nsContentUtils::TriggerLink(this, pc, absURI, target, PR_TRUE, PR_FALSE); return special_rv; // return GetLinkTargetAndAutoType's special rv! } diff --git a/docshell/base/nsWebShell.cpp b/docshell/base/nsWebShell.cpp index f7a94932fda..f86b94a1494 100644 --- a/docshell/base/nsWebShell.cpp +++ b/docshell/base/nsWebShell.cpp @@ -773,7 +773,7 @@ nsWebShell::OnLinkClick(nsIContent* aContent, return NS_OK; } - if (aContent->HasFlag(NODE_IS_EDITABLE)) { + if (aContent->IsEditable()) { return NS_OK; } @@ -804,7 +804,7 @@ nsWebShell::OnLinkClickSync(nsIContent *aContent, return NS_OK; } - if (aContent->HasFlag(NODE_IS_EDITABLE)) { + if (aContent->IsEditable()) { return NS_OK; } @@ -903,7 +903,7 @@ nsWebShell::OnOverLink(nsIContent* aContent, nsIURI* aURI, const PRUnichar* aTargetSpec) { - if (aContent->HasFlag(NODE_IS_EDITABLE)) { + if (aContent->IsEditable()) { return NS_OK; } diff --git a/embedding/browser/activex/src/plugin/XPCDocument.cpp b/embedding/browser/activex/src/plugin/XPCDocument.cpp index 0113364a3b3..1c6a9235ae0 100644 --- a/embedding/browser/activex/src/plugin/XPCDocument.cpp +++ b/embedding/browser/activex/src/plugin/XPCDocument.cpp @@ -1842,6 +1842,8 @@ END_COM_MAP() nsCOMPtr content(do_QueryInterface(mDOMElement)); + // XXX Not checking whether content is editable, + // should we? lh->OnLinkClick(content, uri, szTargetFrame ? szTargetFrame : mUseTarget); } diff --git a/layout/forms/nsIsIndexFrame.cpp b/layout/forms/nsIsIndexFrame.cpp index ba7b36a2027..a3e0309a0b7 100644 --- a/layout/forms/nsIsIndexFrame.cpp +++ b/layout/forms/nsIsIndexFrame.cpp @@ -325,6 +325,10 @@ nsIsIndexFrame::OnSubmit(nsPresContext* aPresContext) return NS_ERROR_UNEXPECTED; } + if (mContent->IsEditable()) { + return NS_OK; + } + nsresult result = NS_OK; // Begin ProcessAsURLEncoded diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index dfb1ba7540d..6338ab46993 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -1339,43 +1339,6 @@ nsImageFrame::GetImageMap(nsPresContext* aPresContext) return mImageMap; } -void -nsImageFrame::TriggerLink(nsPresContext* aPresContext, - nsIURI* aURI, - const nsString& aTargetSpec, - nsINode* aTriggerNode, - PRBool aClick) -{ - NS_PRECONDITION(aTriggerNode, "Must have triggering node"); - - // We get here with server side image map - nsILinkHandler *handler = aPresContext->GetLinkHandler(); - if (handler) { - if (aClick) { - // Check that the triggering node is allowed to load this URI. - // Almost a copy of the similarly named method in nsGenericElement - nsresult rv; - nsCOMPtr securityManager = - do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); - - if (NS_FAILED(rv)) - return; - - rv = securityManager-> - CheckLoadURIWithPrincipal(aTriggerNode->NodePrincipal(), aURI, - nsIScriptSecurityManager::STANDARD); - - // Only pass off the click event if the script security manager - // says it's ok. - if (NS_SUCCEEDED(rv)) - handler->OnLinkClick(mContent, aURI, aTargetSpec.get()); - } - else { - handler->OnOverLink(mContent, aURI, aTargetSpec.get()); - } - } -} - PRBool nsImageFrame::IsServerImageMap() { @@ -1404,7 +1367,7 @@ nsImageFrame::TranslateEventCoords(const nsPoint& aPoint, PRBool nsImageFrame::GetAnchorHREFTargetAndNode(nsIURI** aHref, nsString& aTarget, - nsINode** aNode) + nsIContent** aNode) { PRBool status = PR_FALSE; aTarget.Truncate(); @@ -1493,7 +1456,7 @@ nsImageFrame::HandleEvent(nsPresContext* aPresContext, // element to provide the basis for the destination url. nsCOMPtr uri; nsAutoString target; - nsCOMPtr anchorNode; + nsCOMPtr anchorNode; if (GetAnchorHREFTargetAndNode(getter_AddRefs(uri), target, getter_AddRefs(anchorNode))) { // XXX if the mouse is over/clicked in the border/padding area @@ -1513,7 +1476,8 @@ nsImageFrame::HandleEvent(nsPresContext* aPresContext, *aEventStatus = nsEventStatus_eConsumeDoDefault; clicked = PR_TRUE; } - TriggerLink(aPresContext, uri, target, anchorNode, clicked); + nsContentUtils::TriggerLink(anchorNode, aPresContext, uri, target, + clicked, PR_TRUE); } } } diff --git a/layout/generic/nsImageFrame.h b/layout/generic/nsImageFrame.h index 9645ca9800c..b8bef1d099c 100644 --- a/layout/generic/nsImageFrame.h +++ b/layout/generic/nsImageFrame.h @@ -187,19 +187,13 @@ protected: nsSize aMargin, nsSize aBorder, nsSize aPadding, PRBool aShrinkWrap); - void TriggerLink(nsPresContext* aPresContext, - nsIURI* aURI, - const nsString& aTargetSpec, - nsINode* aTriggerNode, - PRBool aClick); - PRBool IsServerImageMap(); void TranslateEventCoords(const nsPoint& aPoint, nsIntPoint& aResult); PRBool GetAnchorHREFTargetAndNode(nsIURI** aHref, nsString& aTarget, - nsINode** aNode); + nsIContent** aNode); /** * Computes the width of the string that fits into the available space * diff --git a/layout/generic/nsObjectFrame.cpp b/layout/generic/nsObjectFrame.cpp index f422b911a5d..d9704315f0f 100644 --- a/layout/generic/nsObjectFrame.cpp +++ b/layout/generic/nsObjectFrame.cpp @@ -1800,6 +1800,10 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL, const char *aTarge { NS_ENSURE_TRUE(mOwner,NS_ERROR_NULL_POINTER); + if (mContent->IsEditable()) { + return NS_OK; + } + // the container of the pres context will give us the link handler nsCOMPtr container = mOwner->PresContext()->GetContainer(); NS_ENSURE_TRUE(container,NS_ERROR_FAILURE);