зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1220696 - part 5: Support "contentReadOnly" and "getHTML" commands in `<input>` and `<textarea>` r=smaug
Although these commands supported supported only by Gecko, we shouldn't stop supporting them unless we know the usage in the wild. Therefore, this patch adds the handling code for `TextEditor` too. Differential Revision: https://phabricator.services.mozilla.com/D108571
This commit is contained in:
Родитель
b2fd51c051
Коммит
fad3ed3447
|
@ -5376,7 +5376,8 @@ bool Document::QueryCommandEnabled(const nsAString& aHTMLCommandName,
|
|||
|
||||
RefPtr<nsPresContext> presContext = GetPresContext();
|
||||
AutoEditorCommandTarget editCommandTarget(presContext, commandData);
|
||||
if (!editCommandTarget.IsEditable(this)) {
|
||||
if (commandData.IsAvailableOnlyWhenEditable() &&
|
||||
!editCommandTarget.IsEditable(this)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -5415,7 +5416,8 @@ bool Document::QueryCommandIndeterm(const nsAString& aHTMLCommandName,
|
|||
|
||||
RefPtr<nsPresContext> presContext = GetPresContext();
|
||||
AutoEditorCommandTarget editCommandTarget(presContext, commandData);
|
||||
if (!editCommandTarget.IsEditable(this)) {
|
||||
if (commandData.IsAvailableOnlyWhenEditable() &&
|
||||
!editCommandTarget.IsEditable(this)) {
|
||||
return false;
|
||||
}
|
||||
RefPtr<nsCommandParams> params = new nsCommandParams();
|
||||
|
@ -5469,7 +5471,8 @@ bool Document::QueryCommandState(const nsAString& aHTMLCommandName,
|
|||
|
||||
RefPtr<nsPresContext> presContext = GetPresContext();
|
||||
AutoEditorCommandTarget editCommandTarget(presContext, commandData);
|
||||
if (!editCommandTarget.IsEditable(this)) {
|
||||
if (commandData.IsAvailableOnlyWhenEditable() &&
|
||||
!editCommandTarget.IsEditable(this)) {
|
||||
return false;
|
||||
}
|
||||
RefPtr<nsCommandParams> params = new nsCommandParams();
|
||||
|
@ -5600,7 +5603,8 @@ void Document::QueryCommandValue(const nsAString& aHTMLCommandName,
|
|||
|
||||
RefPtr<nsPresContext> presContext = GetPresContext();
|
||||
AutoEditorCommandTarget editCommandTarget(presContext, commandData);
|
||||
if (!editCommandTarget.IsEditable(this)) {
|
||||
if (commandData.IsAvailableOnlyWhenEditable() &&
|
||||
!editCommandTarget.IsEditable(this)) {
|
||||
return;
|
||||
}
|
||||
RefPtr<nsCommandParams> params = new nsCommandParams();
|
||||
|
|
|
@ -4170,7 +4170,9 @@ class Document : public nsINode,
|
|||
bool IsAvailableOnlyWhenEditable() const {
|
||||
return mCommand != mozilla::Command::Cut &&
|
||||
mCommand != mozilla::Command::Copy &&
|
||||
mCommand != mozilla::Command::Paste;
|
||||
mCommand != mozilla::Command::Paste &&
|
||||
mCommand != mozilla::Command::SetDocumentReadOnly &&
|
||||
mCommand != mozilla::Command::GetHTML;
|
||||
}
|
||||
bool IsCutOrCopyCommand() const {
|
||||
return mCommand == mozilla::Command::Cut ||
|
||||
|
|
|
@ -288,6 +288,12 @@ class EditorBase : public nsIEditor,
|
|||
*/
|
||||
Element* GetRoot() const { return mRootElement; }
|
||||
|
||||
/**
|
||||
* Likewise, but gets the text control element instead of the root for
|
||||
* plaintext editors.
|
||||
*/
|
||||
Element* GetExposedRoot() const;
|
||||
|
||||
/**
|
||||
* Set or unset TextInputListener. If setting non-nullptr when the editor
|
||||
* already has a TextInputListener, this will crash in debug build.
|
||||
|
@ -1861,12 +1867,6 @@ class EditorBase : public nsIEditor,
|
|||
*/
|
||||
virtual Element* GetEditorRoot() const;
|
||||
|
||||
/**
|
||||
* Likewise, but gets the text control element instead of the root for
|
||||
* plaintext editors.
|
||||
*/
|
||||
Element* GetExposedRoot() const;
|
||||
|
||||
/**
|
||||
* Whether the editor is active on the DOM window. Note that when this
|
||||
* returns true but GetFocusedContent() returns null, it means that this
|
||||
|
|
|
@ -5,16 +5,19 @@
|
|||
|
||||
#include "mozilla/EditorCommands.h"
|
||||
|
||||
#include "mozilla/HTMLEditor.h" // for HTMLEditor
|
||||
#include "mozilla/TextEditor.h" // for TextEditor
|
||||
#include "mozilla/dom/Document.h" // for Document
|
||||
#include "nsCommandParams.h" // for nsCommandParams
|
||||
#include "nsIEditingSession.h" // for nsIEditingSession, etc
|
||||
#include "nsIPrincipal.h" // for nsIPrincipal
|
||||
#include "nsISupportsImpl.h" // for nsPresContext::Release
|
||||
#include "nsISupportsUtils.h" // for NS_IF_ADDREF
|
||||
#include "nsIURI.h" // for nsIURI
|
||||
#include "nsPresContext.h" // for nsPresContext
|
||||
#include "mozilla/HTMLEditor.h" // for HTMLEditor
|
||||
#include "mozilla/TextEditor.h" // for TextEditor
|
||||
#include "mozilla/dom/Element.h" // for Element
|
||||
#include "mozilla/dom/Document.h" // for Document
|
||||
#include "mozilla/dom/HTMLInputElement.h" // for HTMLInputElement
|
||||
#include "mozilla/dom/HTMLTextAreaElement.h" // for HTMLTextAreaElement
|
||||
#include "nsCommandParams.h" // for nsCommandParams
|
||||
#include "nsIEditingSession.h" // for nsIEditingSession, etc
|
||||
#include "nsIPrincipal.h" // for nsIPrincipal
|
||||
#include "nsISupportsImpl.h" // for nsPresContext::Release
|
||||
#include "nsISupportsUtils.h" // for NS_IF_ADDREF
|
||||
#include "nsIURI.h" // for nsIURI
|
||||
#include "nsPresContext.h" // for nsPresContext
|
||||
|
||||
// defines
|
||||
#define STATE_ENABLED "state_enabled"
|
||||
|
@ -24,6 +27,8 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace dom;
|
||||
|
||||
/*****************************************************************************
|
||||
* mozilla::SetDocumentStateCommand
|
||||
*
|
||||
|
@ -38,7 +43,10 @@ StaticRefPtr<SetDocumentStateCommand> SetDocumentStateCommand::sInstance;
|
|||
|
||||
bool SetDocumentStateCommand::IsCommandEnabled(Command aCommand,
|
||||
TextEditor* aTextEditor) const {
|
||||
// These commands are always enabled if given editor is an HTMLEditor.
|
||||
if (aCommand == Command::SetDocumentReadOnly) {
|
||||
return !!aTextEditor;
|
||||
}
|
||||
// The other commands are always enabled if given editor is an HTMLEditor.
|
||||
return aTextEditor && aTextEditor->AsHTMLEditor();
|
||||
}
|
||||
|
||||
|
@ -55,7 +63,8 @@ nsresult SetDocumentStateCommand::DoCommandParam(
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!aTextEditor.AsHTMLEditor())) {
|
||||
if (aCommand != Command::SetDocumentReadOnly &&
|
||||
NS_WARN_IF(!aTextEditor.IsHTMLEditor())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -73,6 +82,39 @@ nsresult SetDocumentStateCommand::DoCommandParam(
|
|||
return rv;
|
||||
}
|
||||
case Command::SetDocumentReadOnly: {
|
||||
if (aTextEditor.IsTextEditor()) {
|
||||
Element* inputOrTextArea = aTextEditor.GetExposedRoot();
|
||||
if (NS_WARN_IF(!inputOrTextArea)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// Perhaps, this legacy command shouldn't work with
|
||||
// `<input type="file">` and `<input type="number">.
|
||||
if (inputOrTextArea->IsInNativeAnonymousSubtree()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (RefPtr<HTMLInputElement> inputElement =
|
||||
HTMLInputElement::FromNode(inputOrTextArea)) {
|
||||
if (inputElement->ReadOnly() == aBoolParam.value()) {
|
||||
return NS_SUCCESS_DOM_NO_OPERATION;
|
||||
}
|
||||
ErrorResult error;
|
||||
inputElement->SetReadOnly(aBoolParam.value(), error);
|
||||
return error.StealNSResult();
|
||||
}
|
||||
if (RefPtr<HTMLTextAreaElement> textAreaElement =
|
||||
HTMLTextAreaElement::FromNode(inputOrTextArea)) {
|
||||
if (textAreaElement->ReadOnly() == aBoolParam.value()) {
|
||||
return NS_SUCCESS_DOM_NO_OPERATION;
|
||||
}
|
||||
ErrorResult error;
|
||||
textAreaElement->SetReadOnly(aBoolParam.value(), error);
|
||||
return error.StealNSResult();
|
||||
}
|
||||
NS_ASSERTION(
|
||||
false,
|
||||
"Unexpected exposed root element, fallthrough to directly make the "
|
||||
"editor readonly");
|
||||
}
|
||||
ErrorResult error;
|
||||
if (aBoolParam.value()) {
|
||||
nsresult rv = aTextEditor.AddFlags(nsIEditor::eEditorReadonlyMask);
|
||||
|
@ -391,7 +433,7 @@ nsresult DocumentStateCommand::GetCommandStateParams(
|
|||
if (!aTextEditor) {
|
||||
return NS_OK;
|
||||
}
|
||||
dom::Document* document = aTextEditor->GetDocument();
|
||||
Document* document = aTextEditor->GetDocument();
|
||||
if (NS_WARN_IF(!document)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,4 @@
|
|||
[exec-command-with-text-editor.tentative.html]
|
||||
[In <input>, execCommand("getHTML", false, null), a[b\]c): The command should be enabled]
|
||||
expected: FAIL
|
||||
|
||||
[In <input>, execCommand("getHTML", false, null), a[b\]c): getHTML value should be "b" when <input> has focus]
|
||||
expected: FAIL
|
||||
|
||||
[In <input>, execCommand("getHTML", false, null), a[b\]c): getHTML value should be "ere <b>is</b> T" when <input> does not have focus]
|
||||
expected: FAIL
|
||||
|
||||
[In <input>, execCommand("cut", false, null), a[b\]c): The command should be enabled]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -56,24 +47,9 @@
|
|||
[In <input>, execCommand("inserthtml", false, <b>inserted</b>), a[b\]c): input.target should be [object HTMLInputElement\]]
|
||||
expected: FAIL
|
||||
|
||||
[In <input>, execCommand("contentReadOnly", false, true), a[b\]c): The command should be enabled]
|
||||
expected: FAIL
|
||||
|
||||
[In <input>, execCommand("contentReadOnly", false, true), a[b\]c): execCommand() should return true]
|
||||
expected: FAIL
|
||||
|
||||
[In <input>, execCommand("contentReadOnly", false, true), a[b\]c): contentReadOnly state should be true when <input> has focus]
|
||||
expected: FAIL
|
||||
|
||||
[In <input>, execCommand("contentReadOnly", false, true), a[b\]c): readonly property should be true]
|
||||
expected: FAIL
|
||||
|
||||
[In <input>, execCommand("contentReadOnly", false, false), a[b\]c): The command should be enabled]
|
||||
expected: FAIL
|
||||
|
||||
[In <input>, execCommand("contentReadOnly", false, false), a[b\]c): execCommand() should return true]
|
||||
expected: FAIL
|
||||
|
||||
[In <input>, execCommand("defaultParagraphSeparator", false, p), a[b\]c): defaultParagraphSeparator value should be "p" when <input> has focus]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -86,15 +62,6 @@
|
|||
[In <input>, execCommand("defaultParagraphSeparator", false, div), a[b\]c): defaultParagraphSeparator value should be "div" when <input> does not have focus]
|
||||
expected: FAIL
|
||||
|
||||
[In <textarea>, execCommand("getHTML", false, null), a[b\]c): The command should be enabled]
|
||||
expected: FAIL
|
||||
|
||||
[In <textarea>, execCommand("getHTML", false, null), a[b\]c): getHTML value should be "b" when <textarea> has focus]
|
||||
expected: FAIL
|
||||
|
||||
[In <textarea>, execCommand("getHTML", false, null), a[b\]c): getHTML value should be "ere <b>is</b> T" when <textarea> does not have focus]
|
||||
expected: FAIL
|
||||
|
||||
[In <textarea>, execCommand("cut", false, null), a[b\]c): The command should be enabled]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -173,24 +140,9 @@
|
|||
[In <textarea>, execCommand("insertlinebreak", false, null), a[b\]c): input.target should be [object HTMLTextAreaElement\]]
|
||||
expected: FAIL
|
||||
|
||||
[In <textarea>, execCommand("contentReadOnly", false, true), a[b\]c): The command should be enabled]
|
||||
expected: FAIL
|
||||
|
||||
[In <textarea>, execCommand("contentReadOnly", false, true), a[b\]c): execCommand() should return true]
|
||||
expected: FAIL
|
||||
|
||||
[In <textarea>, execCommand("contentReadOnly", false, true), a[b\]c): contentReadOnly state should be true when <textarea> has focus]
|
||||
expected: FAIL
|
||||
|
||||
[In <textarea>, execCommand("contentReadOnly", false, true), a[b\]c): readonly property should be true]
|
||||
expected: FAIL
|
||||
|
||||
[In <textarea>, execCommand("contentReadOnly", false, false), a[b\]c): The command should be enabled]
|
||||
expected: FAIL
|
||||
|
||||
[In <textarea>, execCommand("contentReadOnly", false, false), a[b\]c): execCommand() should return true]
|
||||
expected: FAIL
|
||||
|
||||
[In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b\]c): defaultParagraphSeparator value should be "p" when <textarea> has focus]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -248,9 +200,6 @@
|
|||
[In <input> in contenteditable, execCommand("contentReadOnly", false, true), a[b\]c): contentReadOnly state should be true when <input> has focus]
|
||||
expected: FAIL
|
||||
|
||||
[In <input> in contenteditable, execCommand("contentReadOnly", false, true), a[b\]c): readonly property should be true]
|
||||
expected: FAIL
|
||||
|
||||
[In <textarea> in contenteditable, execCommand("cut", false, null), a[b\]c): The command should be enabled]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -329,39 +278,12 @@
|
|||
[In <textarea> in contenteditable, execCommand("contentReadOnly", false, true), a[b\]c): contentReadOnly state should be true when <textarea> has focus]
|
||||
expected: FAIL
|
||||
|
||||
[In <textarea> in contenteditable, execCommand("contentReadOnly", false, true), a[b\]c): readonly property should be true]
|
||||
expected: FAIL
|
||||
|
||||
[In <input> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b\]c): The command should be enabled]
|
||||
expected: FAIL
|
||||
|
||||
[In <input> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b\]c): execCommand() should return true]
|
||||
expected: FAIL
|
||||
|
||||
[In <input> in contenteditable, execCommand("contentReadOnly", false, true), a[b\]c): The command should be enabled]
|
||||
expected: FAIL
|
||||
|
||||
[In <input> in contenteditable, execCommand("contentReadOnly", false, true), a[b\]c): execCommand() should return true]
|
||||
expected: FAIL
|
||||
|
||||
[In <input> in contenteditable, execCommand("contentReadOnly", false, false), a[b\]c): The command should be enabled]
|
||||
expected: FAIL
|
||||
|
||||
[In <input> in contenteditable, execCommand("contentReadOnly", false, false), a[b\]c): execCommand() should return true]
|
||||
expected: FAIL
|
||||
|
||||
[In <textarea> in contenteditable, execCommand("undo", false, null), a[b\]c): The command should be enabled]
|
||||
expected: FAIL
|
||||
|
||||
[In <textarea> in contenteditable, execCommand("contentReadOnly", false, true), a[b\]c): The command should be enabled]
|
||||
expected: FAIL
|
||||
|
||||
[In <textarea> in contenteditable, execCommand("contentReadOnly", false, true), a[b\]c): execCommand() should return true]
|
||||
expected: FAIL
|
||||
|
||||
[In <textarea> in contenteditable, execCommand("contentReadOnly", false, false), a[b\]c): The command should be enabled]
|
||||
expected: FAIL
|
||||
|
||||
[In <textarea> in contenteditable, execCommand("contentReadOnly", false, false), a[b\]c): execCommand() should return true]
|
||||
expected: FAIL
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче