Fix for bug 386496 (Clicking on link in designMode document does follow that link now). r/sr=bz.

This commit is contained in:
peterv@propagandism.org 2007-07-11 06:05:05 -07:00
parent 62041b8d2e
commit 2fb0fc711a
13 changed files with 119 additions and 124 deletions

View File

@ -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();

View File

@ -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<nsINodeInfo> mNodeInfo;
enum { PARENT_BIT_INDOCUMENT = 1 << 0, PARENT_BIT_PARENT_IS_CONTENT = 1 << 1 };

View File

@ -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());
}
}

View File

@ -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<nsIScriptSecurityManager> 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;

View File

@ -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
*/

View File

@ -981,7 +981,7 @@ nsHTMLFormElement::SubmitSubmission(nsIFormSubmission* aFormSubmission)
nsIDocument* doc = GetCurrentDoc();
nsCOMPtr<nsISupports> container = doc ? doc->GetContainer() : nsnull;
nsCOMPtr<nsILinkHandler> linkHandler(do_QueryInterface(container));
if (!linkHandler) {
if (!linkHandler || IsEditable()) {
mIsSubmitting = PR_FALSE;
return NS_OK;
}

View File

@ -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!
}

View File

@ -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;
}

View File

@ -1842,6 +1842,8 @@ END_COM_MAP()
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMElement));
// XXX Not checking whether content is editable,
// should we?
lh->OnLinkClick(content, uri,
szTargetFrame ? szTargetFrame : mUseTarget);
}

View File

@ -325,6 +325,10 @@ nsIsIndexFrame::OnSubmit(nsPresContext* aPresContext)
return NS_ERROR_UNEXPECTED;
}
if (mContent->IsEditable()) {
return NS_OK;
}
nsresult result = NS_OK;
// Begin ProcessAsURLEncoded

View File

@ -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<nsIScriptSecurityManager> 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<nsIURI> uri;
nsAutoString target;
nsCOMPtr<nsINode> anchorNode;
nsCOMPtr<nsIContent> 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);
}
}
}

View File

@ -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
*

View File

@ -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<nsISupports> container = mOwner->PresContext()->GetContainer();
NS_ENSURE_TRUE(container,NS_ERROR_FAILURE);