diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index e88523336a98..72c40c51f3c6 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -1789,37 +1789,6 @@ nsGenericHTMLElement::MapCommonAttributesInto(const nsMappedAttributes* aAttribu } } -void -nsGenericHTMLFormElement::UpdateEditableFormControlState(PRBool aNotify) -{ - // nsCSSFrameConstructor::MaybeConstructLazily is based on the logic of this - // function, so should be kept in sync with that. - - ContentEditableTristate value = GetContentEditableValue(); - if (value != eInherit) { - DoSetEditableFlag(!!value, aNotify); - return; - } - - nsIContent *parent = GetParent(); - - if (parent && parent->HasFlag(NODE_IS_EDITABLE)) { - DoSetEditableFlag(PR_TRUE, aNotify); - return; - } - - if (!IsTextControl(PR_FALSE)) { - DoSetEditableFlag(PR_FALSE, aNotify); - return; - } - - // If not contentEditable we still need to check the readonly attribute. - PRBool roState; - GetBoolAttr(nsGkAtoms::readonly, &roState); - - DoSetEditableFlag(!roState, aNotify); -} - /* static */ const nsGenericHTMLElement::MappedAttributeEntry nsGenericHTMLElement::sCommonAttributeMap[] = { @@ -2912,6 +2881,18 @@ nsGenericHTMLFormElement::IntrinsicState() const state |= NS_EVENT_STATE_DEFAULT; } + // Make the text controls read-write + if (!state.HasState(NS_EVENT_STATE_MOZ_READWRITE) && + IsTextControl(PR_FALSE)) { + PRBool roState; + GetBoolAttr(nsGkAtoms::readonly, &roState); + + if (!roState) { + state |= NS_EVENT_STATE_MOZ_READWRITE; + state &= ~NS_EVENT_STATE_MOZ_READONLY; + } + } + return state; } diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index f152e1df360f..b4d1ccfb21cf 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -928,8 +928,6 @@ protected: virtual nsresult AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, const nsAString* aValue, PRBool aNotify); - void UpdateEditableFormControlState(PRBool aNotify); - /** * This method will update the form owner, using @form or looking to a parent. * diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index 2895a9855f8c..c292fd9e5cc2 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -848,7 +848,6 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, UpdateTypeMismatchValidityState(); } - UpdateEditableState(aNotify); UpdateState(aNotify); } diff --git a/content/html/content/src/nsHTMLInputElement.h b/content/html/content/src/nsHTMLInputElement.h index cd40e7db9069..5c5108adb79d 100644 --- a/content/html/content/src/nsHTMLInputElement.h +++ b/content/html/content/src/nsHTMLInputElement.h @@ -235,11 +235,6 @@ public: NS_IMETHOD FireAsyncClickHandler(); - virtual void UpdateEditableState(PRBool aNotify) - { - return UpdateEditableFormControlState(aNotify); - } - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLInputElement, nsGenericHTMLFormElement) diff --git a/content/html/content/src/nsHTMLTextAreaElement.cpp b/content/html/content/src/nsHTMLTextAreaElement.cpp index 40ba9795e542..4d3c5d03953e 100644 --- a/content/html/content/src/nsHTMLTextAreaElement.cpp +++ b/content/html/content/src/nsHTMLTextAreaElement.cpp @@ -200,11 +200,6 @@ public: NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED - virtual void UpdateEditableState(PRBool aNotify) - { - return UpdateEditableFormControlState(aNotify); - } - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLTextAreaElement, nsGenericHTMLFormElement) @@ -1267,9 +1262,6 @@ nsHTMLTextAreaElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, UpdateTooLongValidityState(); } - if (aName == nsGkAtoms::readonly) { - UpdateEditableState(aNotify); - } UpdateState(aNotify); } diff --git a/content/html/content/src/nsTextEditorState.cpp b/content/html/content/src/nsTextEditorState.cpp index 28b24cf6ef24..2c686b0f5774 100644 --- a/content/html/content/src/nsTextEditorState.cpp +++ b/content/html/content/src/nsTextEditorState.cpp @@ -1559,6 +1559,9 @@ nsTextEditorState::CreateRootNode() nsresult nsTextEditorState::InitializeRootNode() { + // Make our root node editable + mRootNode->SetFlags(NODE_IS_EDITABLE); + // Set the necessary classes on the text control. We use class values // instead of a 'style' attribute so that the style comes from a user-agent // style sheet and is still applied even if author styles are disabled. diff --git a/editor/libeditor/base/crashtests/382527-1.html b/editor/libeditor/base/crashtests/382527-1.html index ff33a141794f..2441dcd87b52 100644 --- a/editor/libeditor/base/crashtests/382527-1.html +++ b/editor/libeditor/base/crashtests/382527-1.html @@ -36,7 +36,9 @@ function init3() rng.setEnd(textNode, 1); targetWindow.getSelection().addRange(rng); - targetDocument.execCommand("inserthtml", false, "
"); + try { + targetDocument.execCommand("inserthtml", false, "
");
+ } catch(e) {}
document.documentElement.removeAttribute("class");
}
diff --git a/editor/libeditor/base/nsEditor.h b/editor/libeditor/base/nsEditor.h
index 078607ec3041..86909949afef 100644
--- a/editor/libeditor/base/nsEditor.h
+++ b/editor/libeditor/base/nsEditor.h
@@ -548,7 +548,7 @@ public:
virtual PRBool IsContainer(nsIDOMNode *aNode);
/** returns PR_TRUE if aNode is an editable node */
- PRBool IsEditable(nsIDOMNode *aNode);
+ virtual PRBool IsEditable(nsIDOMNode *aNode);
virtual PRBool IsTextInDirtyFrameVisible(nsIDOMNode *aNode);
diff --git a/editor/libeditor/base/nsEditorCommands.cpp b/editor/libeditor/base/nsEditorCommands.cpp
index 590e4cc48bd6..2e1c4757a27b 100644
--- a/editor/libeditor/base/nsEditorCommands.cpp
+++ b/editor/libeditor/base/nsEditorCommands.cpp
@@ -661,13 +661,8 @@ nsSelectAllCommand::IsCommandEnabled(const char * aCommandName,
{
NS_ENSURE_ARG_POINTER(outCmdEnabled);
- // you can select all if there is an editor (and potentially no contents)
- // some day we may want to change this
- nsCOMPtr
+
+
+
+
diff --git a/editor/libeditor/html/tests/test_bug676401.html b/editor/libeditor/html/tests/test_bug676401.html
index ba60753f7579..e1915c7b9b8a 100644
--- a/editor/libeditor/html/tests/test_bug676401.html
+++ b/editor/libeditor/html/tests/test_bug676401.html
@@ -35,10 +35,17 @@ var gBlock1, gBlock2;
function IsCommandEnabled(command) {
var enabled;
+ var resultInNonEditableRegion = false;
+ if (command == "selectAll") {
+ // The select all command is sort of exceptional, as it needs to be enabled
+ // everywhere.
+ resultInNonEditableRegion = true;
+ }
+
// non-editable div: should return false
window.getSelection().selectAllChildren(gBlock1);
enabled = document.queryCommandEnabled(command);
- is(enabled, false, "'" + command + "' should not be enabled on a non-editable block.");
+ is(enabled, resultInNonEditableRegion, "'" + command + "' should not be enabled on a non-editable block.");
// editable div: should return true
window.getSelection().selectAllChildren(gBlock2);
diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp
index fc2d939f0598..ed61f782ca01 100644
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -3883,6 +3883,31 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsFrameConstructorState& aState,
return NS_OK;
}
+static void
+SetFlagsOnSubtree(nsIContent *aNode, PtrBits aFlagsToSet)
+{
+#ifdef DEBUG
+ // Make sure that the node passed to us doesn't have any XBL children
+ {
+ nsIDocument *doc = aNode->GetOwnerDoc();
+ NS_ASSERTION(doc, "The node must be in a document");
+ NS_ASSERTION(!doc->BindingManager()->GetXBLChildNodesFor(aNode),
+ "The node should not have any XBL children");
+ }
+#endif
+
+ // Set the flag on the node itself
+ aNode->SetFlags(aFlagsToSet);
+
+ // Set the flag on all of its children recursively
+ PRUint32 count;
+ nsIContent * const *children = aNode->GetChildArray(&count);
+
+ for (PRUint32 index = 0; index < count; ++index) {
+ SetFlagsOnSubtree(children[index], aFlagsToSet);
+ }
+}
+
nsresult
nsCSSFrameConstructor::GetAnonymousContent(nsIContent* aParent,
nsIFrame* aParentFrame,
@@ -3910,7 +3935,17 @@ nsCSSFrameConstructor::GetAnonymousContent(nsIContent* aParent,
content->SetNativeAnonymous();
}
+ PRBool anonContentIsEditable = content->HasFlag(NODE_IS_EDITABLE);
rv = content->BindToTree(mDocument, aParent, aParent, PR_TRUE);
+ // If the anonymous content creator requested that the content should be
+ // editable, honor its request.
+ // We need to set the flag on the whole subtree, because existing
+ // children's flags have already been set as part of the BindToTree operation.
+ if (anonContentIsEditable) {
+ NS_ASSERTION(aParentFrame->GetType() == nsGkAtoms::textInputFrame,
+ "We only expect this for anonymous content under a text control frame");
+ SetFlagsOnSubtree(content, NODE_IS_EDITABLE);
+ }
if (NS_FAILED(rv)) {
content->UnbindFromTree();
return rv;
@@ -6137,25 +6172,6 @@ nsCSSFrameConstructor::ReframeTextIfNeeded(nsIContent* aParentContent,
ContentInserted(aParentContent, aContent, nsnull, PR_FALSE);
}
-// We want to disable lazy frame construction for nodes that are under an
-// editor. We use nsINode::IsEditable, but that includes inputs with type text
-// and password and textareas, which are common and aren't really editable (the
-// native anonymous content under them is what is actually editable) so we want
-// to construct frames for those lazily.
-// The logic for this check is based on
-// nsGenericHTMLFormElement::UpdateEditableFormControlState and so must be kept
-// in sync with that. MayHaveContentEditableAttr() being true only indicates
-// a contenteditable attribute, it doesn't indicate whether it is true or false,
-// so we force eager construction in some cases when the node is not editable,
-// but that should be rare.
-static inline PRBool
-IsActuallyEditable(nsIContent* aContainer, nsIContent* aChild)
-{
- return (aChild->IsEditable() &&
- (aContainer->IsEditable() ||
- aChild->MayHaveContentEditableAttr()));
-}
-
// For inserts aChild should be valid, for appends it should be null.
// Returns true if this operation can be lazy, false if not.
PRBool
@@ -6170,7 +6186,7 @@ nsCSSFrameConstructor::MaybeConstructLazily(Operation aOperation,
if (aOperation == CONTENTINSERT) {
if (aChild->IsRootOfAnonymousSubtree() ||
- aChild->IsXUL() || IsActuallyEditable(aContainer, aChild)) {
+ aChild->IsEditable() || aChild->IsXUL()) {
return PR_FALSE;
}
} else { // CONTENTAPPEND
@@ -6179,7 +6195,7 @@ nsCSSFrameConstructor::MaybeConstructLazily(Operation aOperation,
for (nsIContent* child = aChild; child; child = child->GetNextSibling()) {
NS_ASSERTION(!child->IsRootOfAnonymousSubtree(),
"Should be coming through the CONTENTAPPEND case");
- if (child->IsXUL() || IsActuallyEditable(aContainer, child)) {
+ if (child->IsXUL() || child->IsEditable()) {
return PR_FALSE;
}
}
diff --git a/layout/generic/nsIAnonymousContentCreator.h b/layout/generic/nsIAnonymousContentCreator.h
index b1e84dc53057..4c351a99b698 100644
--- a/layout/generic/nsIAnonymousContentCreator.h
+++ b/layout/generic/nsIAnonymousContentCreator.h
@@ -79,6 +79,10 @@ public:
* Creates "native" anonymous content and adds the created content to
* the aElements array. None of the returned elements can be nsnull.
*
+ * If the anonymous content creator sets the editable flag on some
+ * of the elements that it creates, the flag will be applied to the node
+ * upon being bound to the document.
+ *
* @note The returned elements are owned by this object. This object is
* responsible for calling UnbindFromTree on the elements it returned
* from CreateAnonymousContent when appropriate (i.e. before releasing
diff --git a/layout/reftests/editor/readonly-editable-ref.html b/layout/reftests/editor/readonly-editable-ref.html
new file mode 100644
index 000000000000..99f1e5101739
--- /dev/null
+++ b/layout/reftests/editor/readonly-editable-ref.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/layout/reftests/editor/readonly-editable.html b/layout/reftests/editor/readonly-editable.html
new file mode 100644
index 000000000000..49210e581472
--- /dev/null
+++ b/layout/reftests/editor/readonly-editable.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+ hide me
+ hide me
+ hide me
+ hide me
+ hide me
+ hide me
+ hide me
+ hide me
+
+
diff --git a/layout/reftests/editor/readonly-non-editable-ref.html b/layout/reftests/editor/readonly-non-editable-ref.html
new file mode 100644
index 000000000000..a91071e42c33
--- /dev/null
+++ b/layout/reftests/editor/readonly-non-editable-ref.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ hide me
+
+ hide me
+
+ hide me
+
+ hide me
+
+
+
diff --git a/layout/reftests/editor/readonly-non-editable.html b/layout/reftests/editor/readonly-non-editable.html
new file mode 100644
index 000000000000..9766045ed73d
--- /dev/null
+++ b/layout/reftests/editor/readonly-non-editable.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+ hide me
+ hide me
+ hide me
+ hide me
+ hide me
+ hide me
+ hide me
+ hide me
+
+
diff --git a/layout/reftests/editor/readwrite-editable-ref.html b/layout/reftests/editor/readwrite-editable-ref.html
new file mode 100644
index 000000000000..99f1e5101739
--- /dev/null
+++ b/layout/reftests/editor/readwrite-editable-ref.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/layout/reftests/editor/readwrite-editable.html b/layout/reftests/editor/readwrite-editable.html
new file mode 100644
index 000000000000..49210e581472
--- /dev/null
+++ b/layout/reftests/editor/readwrite-editable.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+ hide me
+ hide me
+ hide me
+ hide me
+ hide me
+ hide me
+ hide me
+ hide me
+
+
diff --git a/layout/reftests/editor/readwrite-non-editable-ref.html b/layout/reftests/editor/readwrite-non-editable-ref.html
new file mode 100644
index 000000000000..12e1c46c0aef
--- /dev/null
+++ b/layout/reftests/editor/readwrite-non-editable-ref.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+ hide me
+
+ hide me
+
+ hide me
+
+ hide me
+
+
diff --git a/layout/reftests/editor/readwrite-non-editable.html b/layout/reftests/editor/readwrite-non-editable.html
new file mode 100644
index 000000000000..535f21f1aa0e
--- /dev/null
+++ b/layout/reftests/editor/readwrite-non-editable.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+ hide me
+ hide me
+ hide me
+ hide me
+ hide me
+ hide me
+ hide me
+ hide me
+
+
diff --git a/layout/reftests/editor/reftest.list b/layout/reftests/editor/reftest.list
index 4c51f4040478..b9f7c12a75f2 100644
--- a/layout/reftests/editor/reftest.list
+++ b/layout/reftests/editor/reftest.list
@@ -69,4 +69,8 @@ skip-if(Android) == 674212-spellcheck.html 674212-spellcheck-ref.html
skip-if(Android) == 338427-2.html 338427-2-ref.html
skip-if(Android) == 338427-3.html 338427-3-ref.html
skip-if(Android) == 462758-grabbers-resizers.html 462758-grabbers-resizers-ref.html
+== readwrite-non-editable.html readwrite-non-editable-ref.html
+== readwrite-editable.html readwrite-editable-ref.html
+== readonly-non-editable.html readonly-non-editable-ref.html
+== readonly-editable.html readonly-editable-ref.html
== dynamic-overflow-change.html dynamic-overflow-change-ref.html