Backed out 2 changesets (bug 1553705) for causing Bug1562142 . CLOSED TREE

Backed out changeset fbb26a04ec1f (bug 1553705)
Backed out changeset dd6e7c0970d5 (bug 1553705)
This commit is contained in:
Narcis Beleuzu
2019-06-29 02:39:01 +03:00
parent 94151dd643
commit edbd8aaa24
18 changed files with 129 additions and 236 deletions

View File

@@ -38,7 +38,6 @@
#include "nsPIDOMWindow.h" #include "nsPIDOMWindow.h"
#include "mozilla/dom/Document.h" #include "mozilla/dom/Document.h"
#include "mozilla/dom/HTMLFormElement.h"
#include "nsIContent.h" #include "nsIContent.h"
#include "nsIForm.h" #include "nsIForm.h"
#include "nsIFormControl.h" #include "nsIFormControl.h"
@@ -1731,7 +1730,8 @@ Relation Accessible::RelationByType(RelationType aType) const {
// HTML form controls implements nsIFormControl interface. // HTML form controls implements nsIFormControl interface.
nsCOMPtr<nsIFormControl> control(do_QueryInterface(mContent)); nsCOMPtr<nsIFormControl> control(do_QueryInterface(mContent));
if (control) { if (control) {
if (dom::HTMLFormElement* form = control->GetFormElement()) { nsCOMPtr<nsIForm> form(do_QueryInterface(control->GetFormElement()));
if (form) {
nsCOMPtr<nsIContent> formContent = nsCOMPtr<nsIContent> formContent =
do_QueryInterface(form->GetDefaultSubmitElement()); do_QueryInterface(form->GetDefaultSubmitElement());
return Relation(mDoc, formContent); return Relation(mDoc, formContent);

View File

@@ -1338,9 +1338,7 @@ Document::Document(const char* aContentType)
mPendingInitialTranslation(false), mPendingInitialTranslation(false),
mGeneration(0), mGeneration(0),
mCachedTabSizeGeneration(0), mCachedTabSizeGeneration(0),
mInRDMPane(false), mInRDMPane(false) {
mNextFormNumber(0),
mNextControlNumber(0) {
MOZ_LOG(gDocumentLeakPRLog, LogLevel::Debug, ("DOCUMENT %p created", this)); MOZ_LOG(gDocumentLeakPRLog, LogLevel::Debug, ("DOCUMENT %p created", this));
SetIsInDocument(); SetIsInDocument();

View File

@@ -1697,18 +1697,6 @@ class Document : public nsINode,
void SetKeyPressEventModel(uint16_t aKeyPressEventModel); void SetKeyPressEventModel(uint16_t aKeyPressEventModel);
// Gets the next form number.
//
// Used by nsContentUtils::GenerateStateKey to get a unique number for each
// parser inserted form element.
int32_t GetNextFormNumber() { return mNextFormNumber++; }
// Gets the next form control number.
//
// Used by nsContentUtils::GenerateStateKey to get a unique number for each
// parser inserted form control element.
int32_t GetNextControlNumber() { return mNextControlNumber++; }
protected: protected:
friend class nsUnblockOnloadEvent; friend class nsUnblockOnloadEvent;
@@ -5209,10 +5197,6 @@ class Document : public nsINode,
// The principal to use for the storage area of this document. // The principal to use for the storage area of this document.
nsCOMPtr<nsIPrincipal> mIntrinsicStoragePrincipal; nsCOMPtr<nsIPrincipal> mIntrinsicStoragePrincipal;
// See GetNextFormNumber and GetNextControlNumber.
int32_t mNextFormNumber;
int32_t mNextControlNumber;
public: public:
// Needs to be public because the bindings code pokes at it. // Needs to be public because the bindings code pokes at it.
js::ExpandoAndGeneration mExpandoAndGeneration; js::ExpandoAndGeneration mExpandoAndGeneration;

View File

@@ -2668,21 +2668,23 @@ static inline bool IsAutocompleteOff(const nsIContent* aContent) {
} }
/*static*/ /*static*/
void nsContentUtils::GenerateStateKey(nsIContent* aContent, Document* aDocument, nsresult nsContentUtils::GenerateStateKey(nsIContent* aContent,
nsACString& aKey) { Document* aDocument,
MOZ_ASSERT(aContent); nsACString& aKey) {
aKey.Truncate(); aKey.Truncate();
uint32_t partID = aDocument ? aDocument->GetPartID() : 0; uint32_t partID = aDocument ? aDocument->GetPartID() : 0;
// We must have content if we're not using a special state id
NS_ENSURE_TRUE(aContent, NS_ERROR_FAILURE);
// Don't capture state for anonymous content // Don't capture state for anonymous content
if (aContent->IsInAnonymousSubtree()) { if (aContent->IsInAnonymousSubtree()) {
return; return NS_OK;
} }
if (IsAutocompleteOff(aContent)) { if (IsAutocompleteOff(aContent)) {
return; return NS_OK;
} }
RefPtr<Document> doc = aContent->GetUncomposedDoc(); RefPtr<Document> doc = aContent->GetUncomposedDoc();
@@ -2692,6 +2694,10 @@ void nsContentUtils::GenerateStateKey(nsIContent* aContent, Document* aDocument,
if (doc && doc->IsHTMLOrXHTML()) { if (doc && doc->IsHTMLOrXHTML()) {
nsHTMLDocument* htmlDoc = doc->AsHTMLDocument(); nsHTMLDocument* htmlDoc = doc->AsHTMLDocument();
RefPtr<nsContentList> htmlForms;
RefPtr<nsContentList> htmlFormControls;
htmlDoc->GetFormsAndFormControls(getter_AddRefs(htmlForms),
getter_AddRefs(htmlFormControls));
// If we have a form control and can calculate form information, use that // If we have a form control and can calculate form information, use that
// as the key - it is more reliable than just recording position in the // as the key - it is more reliable than just recording position in the
@@ -2699,84 +2705,47 @@ void nsContentUtils::GenerateStateKey(nsIContent* aContent, Document* aDocument,
// XXXbz Is it, really? We have bugs on this, I think... // XXXbz Is it, really? We have bugs on this, I think...
// Important to have a unique key, and tag/type/name may not be. // Important to have a unique key, and tag/type/name may not be.
// //
// The format of the key depends on whether the control has a form, // If the control has a form, the format of the key is:
// and whether the element was parser inserted: // f>type>IndOfFormInDoc>IndOfControlInForm>FormName>name
// // else:
// [Has Form, Parser Inserted]: // d>type>IndOfControlInDoc>name
// fp>type>FormNum>IndOfControlInForm>FormName>name
//
// [No Form, Parser Inserted]:
// dp>type>ControlNum>name
//
// [Has Form, Not Parser Inserted]:
// fn>type>IndOfFormInDoc>IndOfControlInForm>FormName>name
//
// [No Form, Not Parser Inserted]:
// dn>type>IndOfControlInDoc>name
// //
// XXX We don't need to use index if name is there // XXX We don't need to use index if name is there
// XXXbz We don't? Why not? I don't follow. // XXXbz We don't? Why not? I don't follow.
// //
nsCOMPtr<nsIFormControl> control(do_QueryInterface(aContent)); nsCOMPtr<nsIFormControl> control(do_QueryInterface(aContent));
if (control) { if (control) {
// Get the control number if this was a parser inserted element from the
// network.
int32_t controlNumber =
control->GetParserInsertedControlNumberForStateKey();
bool parserInserted = controlNumber != -1;
RefPtr<nsContentList> htmlForms;
RefPtr<nsContentList> htmlFormControls;
if (!parserInserted) {
// Getting these lists is expensive, as we need to keep them up to date
// as the document loads, so we avoid it if we don't need them.
htmlDoc->GetFormsAndFormControls(getter_AddRefs(htmlForms),
getter_AddRefs(htmlFormControls));
}
// Append the control type // Append the control type
KeyAppendInt(control->ControlType(), aKey); KeyAppendInt(control->ControlType(), aKey);
// If in a form, add form name / index of form / index in form // If in a form, add form name / index of form / index in form
HTMLFormElement* formElement = control->GetFormElement(); Element* formElement = control->GetFormElement();
if (formElement) { if (formElement) {
if (IsAutocompleteOff(formElement)) { if (IsAutocompleteOff(formElement)) {
aKey.Truncate(); aKey.Truncate();
return; return NS_OK;
} }
// Append the form number, if this is a parser inserted control, or KeyAppendString(NS_LITERAL_CSTRING("f"), aKey);
// the index of the form in the document otherwise.
bool appendedForm = false; // Append the index of the form in the document
if (parserInserted) { int32_t index = htmlForms->IndexOf(formElement, false);
MOZ_ASSERT(formElement->GetFormNumberForStateKey() != -1, if (index <= -1) {
"when generating a state key for a parser inserted form " //
"control we should have a parser inserted <form> element"); // XXX HACK this uses some state that was dumped into the document
KeyAppendString(NS_LITERAL_CSTRING("fp"), aKey); // specifically to fix bug 138892. What we are trying to do is
KeyAppendInt(formElement->GetFormNumberForStateKey(), aKey); // *guess* which form this control's state is found in, with the
appendedForm = true; // highly likely guess that the highest form parsed so far is the one.
} else { // This code should not be on trunk, only branch.
KeyAppendString(NS_LITERAL_CSTRING("fn"), aKey); //
int32_t index = htmlForms->IndexOf(formElement, false); index = htmlDoc->GetNumFormsSynchronous() - 1;
if (index <= -1) { }
// if (index > -1) {
// XXX HACK this uses some state that was dumped into the document KeyAppendInt(index, aKey);
// specifically to fix bug 138892. What we are trying to do is
// *guess* which form this control's state is found in, with the
// highly likely guess that the highest form parsed so far is the
// one. This code should not be on trunk, only branch.
//
index = htmlDoc->GetNumFormsSynchronous() - 1;
}
if (index > -1) {
KeyAppendInt(index, aKey);
appendedForm = true;
}
}
if (appendedForm) {
// Append the index of the control in the form // Append the index of the control in the form
int32_t index = formElement->IndexOfControl(control); nsCOMPtr<nsIForm> form(do_QueryInterface(formElement));
index = form->IndexOfControl(control);
if (index > -1) { if (index > -1) {
KeyAppendInt(index, aKey); KeyAppendInt(index, aKey);
@@ -2788,30 +2757,29 @@ void nsContentUtils::GenerateStateKey(nsIContent* aContent, Document* aDocument,
nsAutoString formName; nsAutoString formName;
formElement->GetAttr(kNameSpaceID_None, nsGkAtoms::name, formName); formElement->GetAttr(kNameSpaceID_None, nsGkAtoms::name, formName);
KeyAppendString(formName, aKey); KeyAppendString(formName, aKey);
} else {
// Not in a form. Append the control number, if this is a parser
// inserted control, or the index of the control in the document
// otherwise.
if (parserInserted) {
KeyAppendString(NS_LITERAL_CSTRING("dp"), aKey);
KeyAppendInt(control->GetParserInsertedControlNumberForStateKey(),
aKey);
generatedUniqueKey = true;
} else {
KeyAppendString(NS_LITERAL_CSTRING("dn"), aKey);
int32_t index = htmlFormControls->IndexOf(aContent, true);
if (index > -1) {
KeyAppendInt(index, aKey);
generatedUniqueKey = true;
}
}
// Append the control name } else {
nsAutoString name; KeyAppendString(NS_LITERAL_CSTRING("d"), aKey);
aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::name,
name); // If not in a form, add index of control in document
KeyAppendString(name, aKey); // Less desirable than indexing by form info.
// Hash by index of control in doc (we are not in a form)
// These are important as they are unique, and type/name may not be.
// We have to flush sink notifications at this point to make
// sure that htmlFormControls is up to date.
int32_t index = htmlFormControls->IndexOf(aContent, true);
if (index > -1) {
KeyAppendInt(index, aKey);
generatedUniqueKey = true;
}
} }
// Append the control name
nsAutoString name;
aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
KeyAppendString(name, aKey);
} }
} }
@@ -2839,6 +2807,8 @@ void nsContentUtils::GenerateStateKey(nsIContent* aContent, Document* aDocument,
parent = content->GetParentNode(); parent = content->GetParentNode();
} }
} }
return NS_OK;
} }
// static // static

View File

@@ -723,8 +723,8 @@ class nsContentUtils {
// with a single realm. // with a single realm.
static nsIPrincipal* ObjectPrincipal(JSObject* aObj); static nsIPrincipal* ObjectPrincipal(JSObject* aObj);
static void GenerateStateKey(nsIContent* aContent, Document* aDocument, static nsresult GenerateStateKey(nsIContent* aContent, Document* aDocument,
nsACString& aKey); nsACString& aKey);
/** /**
* Create a new nsIURI from aSpec, using aBaseURI as the base. The * Create a new nsIURI from aSpec, using aBaseURI as the base. The

View File

@@ -54,7 +54,7 @@ static const nsAttrValue::EnumTable* kButtonDefaultType = &kButtonTypeTable[2];
HTMLButtonElement::HTMLButtonElement( HTMLButtonElement::HTMLButtonElement(
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
FromParser aFromParser) FromParser aFromParser)
: nsGenericHTMLFormElementWithState(std::move(aNodeInfo), aFromParser, : nsGenericHTMLFormElementWithState(std::move(aNodeInfo),
kButtonDefaultType->value), kButtonDefaultType->value),
mDisabledChanged(false), mDisabledChanged(false),
mInInternalActivate(false), mInInternalActivate(false),
@@ -345,9 +345,11 @@ HTMLButtonElement::SubmitNamesValues(HTMLFormSubmission* aFormSubmission) {
} }
void HTMLButtonElement::DoneCreatingElement() { void HTMLButtonElement::DoneCreatingElement() {
GenerateStateKey();
if (!mInhibitStateRestoration) { if (!mInhibitStateRestoration) {
RestoreFormControlState(); nsresult rv = GenerateStateKey();
if (NS_SUCCEEDED(rv)) {
RestoreFormControlState();
}
} }
} }

View File

@@ -110,7 +110,6 @@ HTMLFormElement::HTMLFormElement(
mPastNameLookupTable(FORM_CONTROL_LIST_HASHTABLE_LENGTH), mPastNameLookupTable(FORM_CONTROL_LIST_HASHTABLE_LENGTH),
mSubmitPopupState(PopupBlocker::openAbused), mSubmitPopupState(PopupBlocker::openAbused),
mInvalidElementsCount(0), mInvalidElementsCount(0),
mFormNumber(-1),
mGeneratingSubmit(false), mGeneratingSubmit(false),
mGeneratingReset(false), mGeneratingReset(false),
mIsSubmitting(false), mIsSubmitting(false),
@@ -2313,26 +2312,5 @@ JSObject* HTMLFormElement::WrapNode(JSContext* aCx,
return HTMLFormElement_Binding::Wrap(aCx, this, aGivenProto); return HTMLFormElement_Binding::Wrap(aCx, this, aGivenProto);
} }
int32_t HTMLFormElement::GetFormNumberForStateKey() {
if (mFormNumber == -1) {
mFormNumber = OwnerDoc()->GetNextFormNumber();
}
return mFormNumber;
}
void HTMLFormElement::NodeInfoChanged(Document* aOldDoc) {
nsGenericHTMLElement::NodeInfoChanged(aOldDoc);
// When a <form> element is adopted into a new document, we want any state
// keys generated from it to no longer consider this element to be parser
// inserted, and so have state keys based on the position of the <form>
// element in the document, rather than the order it was inserted in.
//
// This is not strictly necessary, since we only ever look at the form number
// for parser inserted form controls, and we do that at the time the form
// control element is inserted into its original document by the parser.
mFormNumber = -1;
}
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

View File

@@ -520,17 +520,6 @@ class HTMLFormElement final : public nsGenericHTMLElement,
*/ */
nsresult GetActionURL(nsIURI** aActionURL, Element* aOriginatingElement); nsresult GetActionURL(nsIURI** aActionURL, Element* aOriginatingElement);
// Returns a number for this form that is unique within its owner document.
// This is used by nsContentUtils::GenerateStateKey to identify form controls
// that are inserted into the document by the parser.
int32_t GetFormNumberForStateKey();
/**
* Called when we have been cloned and adopted, and the information of the
* node has been changed.
*/
void NodeInfoChanged(Document* aOldDoc) override;
protected: protected:
// //
// Data members // Data members
@@ -591,9 +580,6 @@ class HTMLFormElement final : public nsGenericHTMLElement,
*/ */
int32_t mInvalidElementsCount; int32_t mInvalidElementsCount;
// See GetFormNumberForStateKey.
int32_t mFormNumber;
/** Whether we are currently processing a submit event or not */ /** Whether we are currently processing a submit event or not */
bool mGeneratingSubmit; bool mGeneratingSubmit;
/** Whether we are currently processing a reset event or not */ /** Whether we are currently processing a reset event or not */

View File

@@ -939,7 +939,7 @@ void HTMLInputElement::Shutdown() {
HTMLInputElement::HTMLInputElement( HTMLInputElement::HTMLInputElement(
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
FromParser aFromParser, FromClone aFromClone) FromParser aFromParser, FromClone aFromClone)
: nsGenericHTMLFormElementWithState(std::move(aNodeInfo), aFromParser, : nsGenericHTMLFormElementWithState(std::move(aNodeInfo),
kInputDefaultType->value), kInputDefaultType->value),
mAutocompleteAttrState(nsContentUtils::eAutocompleteAttrState_Unknown), mAutocompleteAttrState(nsContentUtils::eAutocompleteAttrState_Unknown),
mAutocompleteInfoState(nsContentUtils::eAutocompleteAttrState_Unknown), mAutocompleteInfoState(nsContentUtils::eAutocompleteAttrState_Unknown),
@@ -5894,8 +5894,9 @@ void HTMLInputElement::DoneCreatingElement() {
// Restore state as needed. Note that disabled state applies to all control // Restore state as needed. Note that disabled state applies to all control
// types. // types.
// //
GenerateStateKey(); bool restoredCheckedState = !mInhibitRestoration &&
bool restoredCheckedState = !mInhibitRestoration && RestoreFormControlState(); NS_SUCCEEDED(GenerateStateKey()) &&
RestoreFormControlState();
// //
// If restore does not occur, we initialize .checked using the CHECKED // If restore does not occur, we initialize .checked using the CHECKED

View File

@@ -111,8 +111,7 @@ SafeOptionListMutation::~SafeOptionListMutation() {
HTMLSelectElement::HTMLSelectElement( HTMLSelectElement::HTMLSelectElement(
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
FromParser aFromParser) FromParser aFromParser)
: nsGenericHTMLFormElementWithState(std::move(aNodeInfo), aFromParser, : nsGenericHTMLFormElementWithState(std::move(aNodeInfo), NS_FORM_SELECT),
NS_FORM_SELECT),
mOptions(new HTMLOptionsCollection(this)), mOptions(new HTMLOptionsCollection(this)),
mAutocompleteAttrState(nsContentUtils::eAutocompleteAttrState_Unknown), mAutocompleteAttrState(nsContentUtils::eAutocompleteAttrState_Unknown),
mAutocompleteInfoState(nsContentUtils::eAutocompleteAttrState_Unknown), mAutocompleteInfoState(nsContentUtils::eAutocompleteAttrState_Unknown),
@@ -1113,9 +1112,11 @@ void HTMLSelectElement::DoneAddingChildren(bool aHaveNotified) {
selectFrame->DoneAddingChildren(true); selectFrame->DoneAddingChildren(true);
} }
GenerateStateKey();
if (!mInhibitStateRestoration) { if (!mInhibitStateRestoration) {
RestoreFormControlState(); nsresult rv = GenerateStateKey();
if (NS_SUCCEEDED(rv)) {
RestoreFormControlState();
}
} }
// Now that we're done, select something (if it's a single select something // Now that we're done, select something (if it's a single select something

View File

@@ -51,8 +51,7 @@ namespace dom {
HTMLTextAreaElement::HTMLTextAreaElement( HTMLTextAreaElement::HTMLTextAreaElement(
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
FromParser aFromParser) FromParser aFromParser)
: nsGenericHTMLFormElementWithState(std::move(aNodeInfo), aFromParser, : nsGenericHTMLFormElementWithState(std::move(aNodeInfo), NS_FORM_TEXTAREA),
NS_FORM_TEXTAREA),
mValueChanged(false), mValueChanged(false),
mLastValueChangeWasInteractive(false), mLastValueChangeWasInteractive(false),
mHandlingSelect(false), mHandlingSelect(false),
@@ -518,9 +517,11 @@ void HTMLTextAreaElement::DoneAddingChildren(bool aHaveNotified) {
Reset(); Reset();
} }
GenerateStateKey();
if (!mInhibitStateRestoration) { if (!mInhibitStateRestoration) {
RestoreFormControlState(); nsresult rv = GenerateStateKey();
if (NS_SUCCEEDED(rv)) {
RestoreFormControlState();
}
} }
} }

View File

@@ -1611,7 +1611,7 @@ void nsGenericHTMLFormElement::ClearForm(bool aRemoveFromForm,
AfterClearForm(aUnbindOrDelete); AfterClearForm(aUnbindOrDelete);
} }
HTMLFormElement* nsGenericHTMLFormElement::GetFormElement() { return mForm; } Element* nsGenericHTMLFormElement::GetFormElement() { return mForm; }
HTMLFieldSetElement* nsGenericHTMLFormElement::GetFieldSet() { HTMLFieldSetElement* nsGenericHTMLFormElement::GetFieldSet() {
return mFieldSet; return mFieldSet;
@@ -2520,29 +2520,29 @@ void nsGenericHTMLElement::ChangeEditableState(int32_t aChange) {
//---------------------------------------------------------------------- //----------------------------------------------------------------------
nsGenericHTMLFormElementWithState::nsGenericHTMLFormElementWithState( nsGenericHTMLFormElementWithState::nsGenericHTMLFormElementWithState(
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, uint8_t aType)
FromParser aFromParser, uint8_t aType) : nsGenericHTMLFormElement(std::move(aNodeInfo), aType) {
: nsGenericHTMLFormElement(std::move(aNodeInfo), aType),
mControlNumber(!!(aFromParser & FROM_PARSER_NETWORK)
? OwnerDoc()->GetNextControlNumber()
: -1) {
mStateKey.SetIsVoid(true); mStateKey.SetIsVoid(true);
} }
void nsGenericHTMLFormElementWithState::GenerateStateKey() { nsresult nsGenericHTMLFormElementWithState::GenerateStateKey() {
// Keep the key if already computed // Keep the key if already computed
if (!mStateKey.IsVoid()) { if (!mStateKey.IsVoid()) {
return; return NS_OK;
} }
Document* doc = GetUncomposedDoc(); Document* doc = GetUncomposedDoc();
if (!doc) { if (!doc) {
mStateKey.Truncate(); return NS_OK;
return;
} }
// Generate the state key // Generate the state key
nsContentUtils::GenerateStateKey(this, doc, mStateKey); nsresult rv = nsContentUtils::GenerateStateKey(this, doc, mStateKey);
if (NS_FAILED(rv)) {
mStateKey.SetIsVoid(true);
return rv;
}
// If the state key is blank, this is anonymous content or for whatever // If the state key is blank, this is anonymous content or for whatever
// reason we are not supposed to save/restore state: keep it as such. // reason we are not supposed to save/restore state: keep it as such.
@@ -2550,6 +2550,7 @@ void nsGenericHTMLFormElementWithState::GenerateStateKey() {
// Add something unique to content so layout doesn't muck us up. // Add something unique to content so layout doesn't muck us up.
mStateKey += "-C"; mStateKey += "-C";
} }
return NS_OK;
} }
PresState* nsGenericHTMLFormElementWithState::GetPrimaryPresState() { PresState* nsGenericHTMLFormElementWithState::GetPrimaryPresState() {
@@ -2597,9 +2598,6 @@ nsGenericHTMLFormElementWithState::GetLayoutHistory(bool aRead) {
} }
bool nsGenericHTMLFormElementWithState::RestoreFormControlState() { bool nsGenericHTMLFormElementWithState::RestoreFormControlState() {
MOZ_ASSERT(!mStateKey.IsVoid(),
"GenerateStateKey must already have been called");
if (mStateKey.IsEmpty()) { if (mStateKey.IsEmpty()) {
return false; return false;
} }
@@ -2622,12 +2620,6 @@ bool nsGenericHTMLFormElementWithState::RestoreFormControlState() {
void nsGenericHTMLFormElementWithState::NodeInfoChanged(Document* aOldDoc) { void nsGenericHTMLFormElementWithState::NodeInfoChanged(Document* aOldDoc) {
nsGenericHTMLElement::NodeInfoChanged(aOldDoc); nsGenericHTMLElement::NodeInfoChanged(aOldDoc);
// We need to regenerate the state key now we're in a new document. Clearing
// mControlNumber means we stop considering this control to be parser
// inserted, and we'll generate a state key based on its position in the
// document rather than the order it was inserted into the document.
mControlNumber = -1;
mStateKey.SetIsVoid(true); mStateKey.SetIsVoid(true);
} }

View File

@@ -930,7 +930,7 @@ class nsGenericHTMLFormElement : public nsGenericHTMLElement,
// nsIFormControl // nsIFormControl
virtual mozilla::dom::HTMLFieldSetElement* GetFieldSet() override; virtual mozilla::dom::HTMLFieldSetElement* GetFieldSet() override;
virtual mozilla::dom::HTMLFormElement* GetFormElement() override; virtual mozilla::dom::Element* GetFormElement() override;
mozilla::dom::HTMLFormElement* GetForm() const { return mForm; } mozilla::dom::HTMLFormElement* GetForm() const { return mForm; }
virtual void SetForm(mozilla::dom::HTMLFormElement* aForm) override; virtual void SetForm(mozilla::dom::HTMLFormElement* aForm) override;
virtual void ClearForm(bool aRemoveFromForm, bool aUnbindOrDelete) override; virtual void ClearForm(bool aRemoveFromForm, bool aUnbindOrDelete) override;
@@ -1083,8 +1083,7 @@ class nsGenericHTMLFormElement : public nsGenericHTMLElement,
class nsGenericHTMLFormElementWithState : public nsGenericHTMLFormElement { class nsGenericHTMLFormElementWithState : public nsGenericHTMLFormElement {
public: public:
nsGenericHTMLFormElementWithState( nsGenericHTMLFormElementWithState(
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, uint8_t aType);
mozilla::dom::FromParser aFromParser, uint8_t aType);
/** /**
* Get the presentation state for a piece of content, or create it if it does * Get the presentation state for a piece of content, or create it if it does
@@ -1102,40 +1101,28 @@ class nsGenericHTMLFormElementWithState : public nsGenericHTMLFormElement {
already_AddRefed<nsILayoutHistoryState> GetLayoutHistory(bool aRead); already_AddRefed<nsILayoutHistoryState> GetLayoutHistory(bool aRead);
/** /**
* Called when we have been cloned and adopted, and the information of the * Restore the state for a form control. Ends up calling
* node has been changed.
*/
virtual void NodeInfoChanged(Document* aOldDoc) override;
protected:
/**
* Restore the state for a form control in response to the element being
* inserted into the document by the parser. Ends up calling
* nsIFormControl::RestoreState(). * nsIFormControl::RestoreState().
* *
* GenerateStateKey() must already have been called.
*
* @return false if RestoreState() was not called, the return * @return false if RestoreState() was not called, the return
* value of RestoreState() otherwise. * value of RestoreState() otherwise.
*/ */
bool RestoreFormControlState(); bool RestoreFormControlState();
/* Generates the state key for saving the form state in the session if not /**
computed already. The result is stored in mStateKey. */ * Called when we have been cloned and adopted, and the information of the
void GenerateStateKey(); * node has been changed.
*/
virtual void NodeInfoChanged(Document* aOldDoc) override;
int32_t GetParserInsertedControlNumberForStateKey() const override { protected:
return mControlNumber; /* Generates the state key for saving the form state in the session if not
} computed already. The result is stored in mStateKey on success */
nsresult GenerateStateKey();
/* Used to store the key to that element in the session. Is void until /* Used to store the key to that element in the session. Is void until
GenerateStateKey has been used */ GenerateStateKey has been used */
nsCString mStateKey; nsCString mStateKey;
// A number for this form control that is unique within its owner document.
// This is only set to a number for elements inserted into the document by
// the parser from the network. Otherwise, it is -1.
int32_t mControlNumber;
}; };
#define NS_INTERFACE_MAP_ENTRY_IF_TAG(_interface, _tag) \ #define NS_INTERFACE_MAP_ENTRY_IF_TAG(_interface, _tag) \

View File

@@ -107,7 +107,7 @@ class nsIFormControl : public nsISupports {
* Get the form for this form control. * Get the form for this form control.
* @return the form * @return the form
*/ */
virtual mozilla::dom::HTMLFormElement* GetFormElement() = 0; virtual mozilla::dom::Element* GetFormElement() = 0;
/** /**
* Set the form for this form control. * Set the form for this form control.
@@ -222,16 +222,6 @@ class nsIFormControl : public nsISupports {
return false; return false;
} }
// Returns a number for this form control that is unique within its
// owner document. This is used by nsContentUtils::GenerateStateKey
// to identify form controls that are inserted into the document by
// the parser. -1 is returned for form controls with no state or
// which were inserted into the document by some other means than
// the parser from the network.
virtual int32_t GetParserInsertedControlNumberForStateKey() const {
return -1;
};
protected: protected:
/** /**
* Returns whether mType corresponds to a single line text control type. * Returns whether mType corresponds to a single line text control type.

View File

@@ -146,8 +146,8 @@ void nsFrameManager::CaptureFrameStateFor(nsIFrame* aFrame,
nsAutoCString stateKey; nsAutoCString stateKey;
nsIContent* content = aFrame->GetContent(); nsIContent* content = aFrame->GetContent();
Document* doc = content ? content->GetUncomposedDoc() : nullptr; Document* doc = content ? content->GetUncomposedDoc() : nullptr;
statefulFrame->GenerateStateKey(content, doc, stateKey); nsresult rv = statefulFrame->GenerateStateKey(content, doc, stateKey);
if (stateKey.IsEmpty()) { if (NS_FAILED(rv) || stateKey.IsEmpty()) {
return; return;
} }
@@ -207,8 +207,8 @@ void nsFrameManager::RestoreFrameStateFor(nsIFrame* aFrame,
nsAutoCString stateKey; nsAutoCString stateKey;
Document* doc = content->GetUncomposedDoc(); Document* doc = content->GetUncomposedDoc();
statefulFrame->GenerateStateKey(content, doc, stateKey); nsresult rv = statefulFrame->GenerateStateKey(content, doc, stateKey);
if (stateKey.IsEmpty()) { if (NS_FAILED(rv) || stateKey.IsEmpty()) {
return; return;
} }
@@ -219,7 +219,7 @@ void nsFrameManager::RestoreFrameStateFor(nsIFrame* aFrame,
} }
// Restore it // Restore it
nsresult rv = statefulFrame->RestoreState(frameState); rv = statefulFrame->RestoreState(frameState);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return; return;
} }

View File

@@ -1569,14 +1569,16 @@ nsComboboxControlFrame::RestoreState(PresState* aState) {
// Append a suffix so that the state key for the combobox is different // Append a suffix so that the state key for the combobox is different
// from the state key the list control uses to sometimes save the scroll // from the state key the list control uses to sometimes save the scroll
// position for the same Element // position for the same Element
void nsComboboxControlFrame::GenerateStateKey(nsIContent* aContent, NS_IMETHODIMP
Document* aDocument, nsComboboxControlFrame::GenerateStateKey(nsIContent* aContent,
nsACString& aKey) { Document* aDocument,
nsContentUtils::GenerateStateKey(aContent, aDocument, aKey); nsACString& aKey) {
if (aKey.IsEmpty()) { nsresult rv = nsContentUtils::GenerateStateKey(aContent, aDocument, aKey);
return; if (NS_FAILED(rv) || aKey.IsEmpty()) {
return rv;
} }
aKey.AppendLiteral("CCF"); aKey.AppendLiteral("CCF");
return NS_OK;
} }
// Fennec uses a custom combobox built-in widget. // Fennec uses a custom combobox built-in widget.

View File

@@ -209,8 +209,9 @@ class nsComboboxControlFrame final : public nsBlockFrame,
mozilla::UniquePtr<mozilla::PresState> SaveState() override; mozilla::UniquePtr<mozilla::PresState> SaveState() override;
MOZ_CAN_RUN_SCRIPT_BOUNDARY MOZ_CAN_RUN_SCRIPT_BOUNDARY
NS_IMETHOD RestoreState(mozilla::PresState* aState) override; NS_IMETHOD RestoreState(mozilla::PresState* aState) override;
void GenerateStateKey(nsIContent* aContent, mozilla::dom::Document* aDocument, NS_IMETHOD GenerateStateKey(nsIContent* aContent,
nsACString& aKey) override; mozilla::dom::Document* aDocument,
nsACString& aKey) override;
static bool ToolkitHasNativePopup(); static bool ToolkitHasNativePopup();

View File

@@ -30,10 +30,10 @@ class nsIStatefulFrame {
NS_IMETHOD RestoreState(mozilla::PresState* aState) = 0; NS_IMETHOD RestoreState(mozilla::PresState* aState) = 0;
// Generate a key for this stateful frame // Generate a key for this stateful frame
virtual void GenerateStateKey(nsIContent* aContent, NS_IMETHOD GenerateStateKey(nsIContent* aContent,
mozilla::dom::Document* aDocument, mozilla::dom::Document* aDocument,
nsACString& aKey) { nsACString& aKey) {
nsContentUtils::GenerateStateKey(aContent, aDocument, aKey); return nsContentUtils::GenerateStateKey(aContent, aDocument, aKey);
}; };
}; };