mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 821307. Ensure nsTextEditorState::SetValue does nothing when the new value equals the old value, even for password inputs. r=ehsan
If nsTextEditorState::SetValue is allowed to rebuild the editor DOM even when the new value is the same as the old value, then during PrepareEditor we can remove the content that's the current target of the event triggering the PrepareEditor, which prevents important code from running such as the code that focuses the text input. Normally this isn't a problem but nsTextEditorState::SetValue's code for getting the current value is broken for password controls when !mEditorInitialized. So we remove that broken code path. We have to make sure that the password text, if any, is set on the edit-rules during their initialization so the regular path for getting the current value returns the right thing. --HG-- extra : rebase_source : 81a01a957b4b1e0cf868505a1b23c9110a2f4b3a
This commit is contained in:
parent
2299300a51
commit
38c751230b
@ -1234,6 +1234,16 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
|
||||
newEditor = mEditor; // just pretend that we have a new editor!
|
||||
}
|
||||
|
||||
// Get the current value of the textfield from the content.
|
||||
// Note that if we've created a new editor, mEditor is null at this stage,
|
||||
// so we will get the real value from the content.
|
||||
nsAutoString defaultValue;
|
||||
if (aValue) {
|
||||
defaultValue = *aValue;
|
||||
} else {
|
||||
GetValue(defaultValue, true);
|
||||
}
|
||||
|
||||
if (!mEditorInitialized) {
|
||||
// Now initialize the editor.
|
||||
//
|
||||
@ -1254,7 +1264,8 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
|
||||
// already does the relevant security checks.
|
||||
AutoNoJSAPI nojsapi;
|
||||
|
||||
rv = newEditor->Init(domdoc, GetRootNode(), mSelCon, editorFlags);
|
||||
rv = newEditor->Init(domdoc, GetRootNode(), mSelCon, editorFlags,
|
||||
defaultValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
@ -1335,16 +1346,6 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
|
||||
newEditor->SetFlags(editorFlags);
|
||||
}
|
||||
|
||||
// Get the current value of the textfield from the content.
|
||||
// Note that if we've created a new editor, mEditor is null at this stage,
|
||||
// so we will get the real value from the content.
|
||||
nsAutoString defaultValue;
|
||||
if (aValue) {
|
||||
defaultValue = *aValue;
|
||||
} else {
|
||||
GetValue(defaultValue, true);
|
||||
}
|
||||
|
||||
if (shouldInitializeEditor) {
|
||||
// Hold on to the newly created editor
|
||||
preDestroyer.Swap(mEditor);
|
||||
@ -1780,18 +1781,7 @@ nsTextEditorState::SetValue(const nsAString& aValue, bool aUserInput,
|
||||
#endif
|
||||
|
||||
nsAutoString currentValue;
|
||||
if (!mEditorInitialized && IsSingleLineTextControl()) {
|
||||
// Grab the current value directly from the text node to make sure that we
|
||||
// deal with stale data correctly.
|
||||
NS_ASSERTION(mRootNode, "We should have a root node here");
|
||||
nsIContent *textContent = mRootNode->GetFirstChild();
|
||||
nsCOMPtr<nsIDOMCharacterData> textNode = do_QueryInterface(textContent);
|
||||
if (textNode) {
|
||||
textNode->GetData(currentValue);
|
||||
}
|
||||
} else {
|
||||
mBoundFrame->GetText(currentValue);
|
||||
}
|
||||
mBoundFrame->GetText(currentValue);
|
||||
|
||||
nsWeakFrame weakFrame(mBoundFrame);
|
||||
|
||||
|
@ -393,6 +393,7 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop spec
|
||||
[test_bug787134.html]
|
||||
[test_bug797113.html]
|
||||
[test_bug803677.html]
|
||||
[test_bug821307.html]
|
||||
[test_bug827126.html]
|
||||
[test_bug827426.html]
|
||||
[test_bug838582.html]
|
||||
|
41
content/html/content/test/test_bug821307.html
Normal file
41
content/html/content/test/test_bug821307.html
Normal file
@ -0,0 +1,41 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=821307
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 821307</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=821307">Mozilla Bug 821307</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
|
||||
<input id='dummy'></input>
|
||||
<input type="password" id='input' value='11111111111111111' style="width:40em; font-size:40px;"></input>
|
||||
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
var dummy = document.getElementById('dummy');
|
||||
dummy.focus();
|
||||
is(document.activeElement, dummy, "Check dummy element is now focused");
|
||||
|
||||
var input = document.getElementById('input');
|
||||
var rect = input.getBoundingClientRect();
|
||||
synthesizeMouse(input, 100, rect.height/2, {});
|
||||
is(document.activeElement, input, "Check input element is now focused");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -448,7 +448,7 @@ nsEditingSession::SetupEditorOnWindow(nsIDOMWindow *aWindow)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = editor->Init(domDoc, nullptr /* root content */,
|
||||
nullptr, mEditorFlags);
|
||||
nullptr, mEditorFlags, EmptyString());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
|
@ -21,7 +21,7 @@ interface nsIEditActionListener;
|
||||
interface nsIInlineSpellChecker;
|
||||
interface nsITransferable;
|
||||
|
||||
[scriptable, uuid(753b38d1-ee03-4e58-a650-1076ccccdb7f)]
|
||||
[scriptable, uuid(65523eab-db1f-44aa-893e-dfe57ad306f0)]
|
||||
|
||||
interface nsIEditor : nsISupports
|
||||
{
|
||||
@ -56,7 +56,8 @@ interface nsIEditor : nsISupports
|
||||
[noscript] void init(in nsIDOMDocument doc,
|
||||
in nsIContent aRoot,
|
||||
in nsISelectionController aSelCon,
|
||||
in unsigned long aFlags);
|
||||
in unsigned long aFlags,
|
||||
in AString initialValue);
|
||||
|
||||
void setAttributeOrEquivalent(in nsIDOMElement element,
|
||||
in AString sourceAttrName,
|
||||
|
@ -6,10 +6,9 @@
|
||||
#ifndef nsEditRules_h__
|
||||
#define nsEditRules_h__
|
||||
|
||||
// FB45AC36-E8F1-44ae-8FB7-466E1BE119B0
|
||||
#define NS_IEDITRULES_IID \
|
||||
{ 0x2cc50d11, 0x9909, 0x433f, \
|
||||
{ 0xb6, 0xfb, 0x4c, 0xf2, 0x56, 0xe5, 0xe5, 0x71 } }
|
||||
{ 0x3836386d, 0x806a, 0x488d, \
|
||||
{ 0x8b, 0xab, 0xaf, 0x42, 0xbb, 0x4c, 0x90, 0x66 } }
|
||||
|
||||
#include "nsEditor.h"
|
||||
|
||||
@ -43,6 +42,7 @@ public:
|
||||
//NOTE: Use NS_DECL_ISUPPORTS_INHERITED in any class inherited from nsIEditRules
|
||||
|
||||
NS_IMETHOD Init(nsPlaintextEditor *aEditor)=0;
|
||||
NS_IMETHOD SetInitialValue(const nsAString& aValue) = 0;
|
||||
NS_IMETHOD DetachEditor()=0;
|
||||
NS_IMETHOD BeforeEdit(EditAction action,
|
||||
nsIEditor::EDirection aDirection) = 0;
|
||||
|
@ -204,7 +204,9 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsEditor)
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::Init(nsIDOMDocument *aDoc, nsIContent *aRoot, nsISelectionController *aSelCon, uint32_t aFlags)
|
||||
nsEditor::Init(nsIDOMDocument *aDoc, nsIContent *aRoot,
|
||||
nsISelectionController *aSelCon, uint32_t aFlags,
|
||||
const nsAString& aValue)
|
||||
{
|
||||
NS_PRECONDITION(aDoc, "bad arg");
|
||||
if (!aDoc)
|
||||
|
@ -225,10 +225,12 @@ NS_IMETHODIMP
|
||||
nsHTMLEditor::Init(nsIDOMDocument *aDoc,
|
||||
nsIContent *aRoot,
|
||||
nsISelectionController *aSelCon,
|
||||
uint32_t aFlags)
|
||||
uint32_t aFlags,
|
||||
const nsAString& aInitialValue)
|
||||
{
|
||||
NS_PRECONDITION(aDoc && !aSelCon, "bad arg");
|
||||
NS_ENSURE_TRUE(aDoc, NS_ERROR_NULL_POINTER);
|
||||
MOZ_ASSERT(aInitialValue.IsEmpty(), "Non-empty initial values not supported");
|
||||
|
||||
nsresult result = NS_OK, rulesRes = NS_OK;
|
||||
|
||||
@ -238,7 +240,7 @@ nsHTMLEditor::Init(nsIDOMDocument *aDoc,
|
||||
nsAutoEditInitRulesTrigger rulesTrigger(static_cast<nsPlaintextEditor*>(this), rulesRes);
|
||||
|
||||
// Init the plaintext editor
|
||||
result = nsPlaintextEditor::Init(aDoc, aRoot, nullptr, aFlags);
|
||||
result = nsPlaintextEditor::Init(aDoc, aRoot, nullptr, aFlags, aInitialValue);
|
||||
if (NS_FAILED(result)) { return result; }
|
||||
|
||||
// Init mutation observer
|
||||
|
@ -249,7 +249,9 @@ public:
|
||||
nsresult EndUpdateViewBatch();
|
||||
|
||||
/** prepare the editor for use */
|
||||
NS_IMETHOD Init(nsIDOMDocument *aDoc, nsIContent *aRoot, nsISelectionController *aSelCon, uint32_t aFlags);
|
||||
NS_IMETHOD Init(nsIDOMDocument *aDoc, nsIContent *aRoot,
|
||||
nsISelectionController *aSelCon, uint32_t aFlags,
|
||||
const nsAString& aValue);
|
||||
NS_IMETHOD PreDestroy(bool aDestroyingFrames);
|
||||
|
||||
/** Internal, static version */
|
||||
|
@ -115,7 +115,8 @@ NS_INTERFACE_MAP_END_INHERITING(nsEditor)
|
||||
NS_IMETHODIMP nsPlaintextEditor::Init(nsIDOMDocument *aDoc,
|
||||
nsIContent *aRoot,
|
||||
nsISelectionController *aSelCon,
|
||||
uint32_t aFlags)
|
||||
uint32_t aFlags,
|
||||
const nsAString& aInitialValue)
|
||||
{
|
||||
NS_PRECONDITION(aDoc, "bad arg");
|
||||
NS_ENSURE_TRUE(aDoc, NS_ERROR_NULL_POINTER);
|
||||
@ -126,13 +127,12 @@ NS_IMETHODIMP nsPlaintextEditor::Init(nsIDOMDocument *aDoc,
|
||||
mRules = nullptr;
|
||||
}
|
||||
|
||||
if (1)
|
||||
{
|
||||
// block to scope nsAutoEditInitRulesTrigger
|
||||
nsAutoEditInitRulesTrigger rulesTrigger(this, rulesRes);
|
||||
|
||||
// Init the base editor
|
||||
res = nsEditor::Init(aDoc, aRoot, aSelCon, aFlags);
|
||||
res = nsEditor::Init(aDoc, aRoot, aSelCon, aFlags, aInitialValue);
|
||||
}
|
||||
|
||||
// check the "single line editor newline handling"
|
||||
@ -140,6 +140,13 @@ NS_IMETHODIMP nsPlaintextEditor::Init(nsIDOMDocument *aDoc,
|
||||
GetDefaultEditorPrefs(mNewlineHandling, mCaretStyle);
|
||||
|
||||
NS_ENSURE_SUCCESS(rulesRes, rulesRes);
|
||||
|
||||
// mRules may not have been initialized yet, when this is called via
|
||||
// nsHTMLEditor::Init.
|
||||
if (mRules) {
|
||||
mRules->SetInitialValue(aInitialValue);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,9 @@ public:
|
||||
bool aSuppressTransaction);
|
||||
|
||||
/** prepare the editor for use */
|
||||
NS_IMETHOD Init(nsIDOMDocument *aDoc, nsIContent *aRoot, nsISelectionController *aSelCon, uint32_t aFlags);
|
||||
NS_IMETHOD Init(nsIDOMDocument *aDoc, nsIContent *aRoot,
|
||||
nsISelectionController *aSelCon, uint32_t aFlags,
|
||||
const nsAString& aValue);
|
||||
|
||||
NS_IMETHOD GetDocumentIsEmpty(bool *aDocumentIsEmpty);
|
||||
NS_IMETHOD GetIsDocumentEditable(bool *aIsDocumentEditable);
|
||||
|
@ -135,6 +135,15 @@ nsTextEditRules::Init(nsPlaintextEditor *aEditor)
|
||||
return res;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::SetInitialValue(const nsAString& aValue)
|
||||
{
|
||||
if (IsPasswordEditor()) {
|
||||
mPasswordText = aValue;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::DetachEditor()
|
||||
{
|
||||
|
@ -47,6 +47,7 @@ public:
|
||||
|
||||
// nsIEditRules methods
|
||||
NS_IMETHOD Init(nsPlaintextEditor *aEditor);
|
||||
NS_IMETHOD SetInitialValue(const nsAString& aValue);
|
||||
NS_IMETHOD DetachEditor();
|
||||
NS_IMETHOD BeforeEdit(EditAction action,
|
||||
nsIEditor::EDirection aDirection);
|
||||
|
Loading…
Reference in New Issue
Block a user