mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-06 00:10:25 +00:00
Bug 1460509 - part 17: Make HTMLEditRules::WillAbsolutePosition() return NS_ERROR_EDITOR_DESTROYED if it causes destroying the HTML editor r=m_kato
MozReview-Commit-ID: EGqb0hNpNnc --HG-- extra : rebase_source : 97eeaca8b9386afe9ec320cd549d278955b69167
This commit is contained in:
parent
44d0e05143
commit
dd74573897
@ -9969,6 +9969,30 @@ HTMLEditRules::WillAbsolutePosition(bool* aCancel,
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = PrepareToMakeElementAbsolutePosition(aHandled, address_of(mNewBlock));
|
||||
// PrepareToMakeElementAbsolutePosition() may restore selection with
|
||||
// AutoSelectionRestorer. Therefore, the editor might have already been
|
||||
// destroyed now.
|
||||
if (NS_WARN_IF(!CanHandleEditAction())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLEditRules::PrepareToMakeElementAbsolutePosition(
|
||||
bool* aHandled,
|
||||
RefPtr<Element>* aTargetElement)
|
||||
{
|
||||
MOZ_ASSERT(IsEditorDataAvailable());
|
||||
|
||||
MOZ_ASSERT(aHandled);
|
||||
MOZ_ASSERT(aTargetElement);
|
||||
|
||||
AutoSelectionRestorer selectionRestorer(&SelectionRef(), &HTMLEditorRef());
|
||||
|
||||
// Convert the selection ranges into "promoted" selection ranges: this
|
||||
@ -9981,8 +10005,8 @@ HTMLEditRules::WillAbsolutePosition(bool* aCancel,
|
||||
|
||||
// Use these ranges to contruct a list of nodes to act on.
|
||||
nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
|
||||
rv = GetNodesForOperation(arrayOfRanges, arrayOfNodes,
|
||||
EditAction::setAbsolutePosition);
|
||||
nsresult rv = GetNodesForOperation(arrayOfRanges, arrayOfNodes,
|
||||
EditAction::setAbsolutePosition);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
@ -10009,15 +10033,21 @@ HTMLEditRules::WillAbsolutePosition(bool* aCancel,
|
||||
RefPtr<Element> positionedDiv =
|
||||
HTMLEditorRef().CreateNodeWithTransaction(*nsGkAtoms::div,
|
||||
splitNodeResult.SplitPoint());
|
||||
if (NS_WARN_IF(!CanHandleEditAction())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
if (NS_WARN_IF(!positionedDiv)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// Remember our new block for postprocessing
|
||||
mNewBlock = positionedDiv;
|
||||
*aTargetElement = positionedDiv;
|
||||
// Delete anything that was in the list of nodes
|
||||
while (!arrayOfNodes.IsEmpty()) {
|
||||
OwningNonNull<nsINode> curNode = arrayOfNodes[0];
|
||||
rv = HTMLEditorRef().DeleteNodeWithTransaction(*curNode);
|
||||
if (NS_WARN_IF(!CanHandleEditAction())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
@ -10025,10 +10055,14 @@ HTMLEditRules::WillAbsolutePosition(bool* aCancel,
|
||||
}
|
||||
// Put selection in new block
|
||||
*aHandled = true;
|
||||
ErrorResult error;
|
||||
SelectionRef().Collapse(RawRangeBoundary(positionedDiv, 0), error);
|
||||
// Don't restore the selection
|
||||
selectionRestorer.Abort();
|
||||
ErrorResult error;
|
||||
SelectionRef().Collapse(RawRangeBoundary(positionedDiv, 0), error);
|
||||
if (NS_WARN_IF(!CanHandleEditAction())) {
|
||||
error.SuppressException();
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
@ -10074,15 +10108,21 @@ HTMLEditRules::WillAbsolutePosition(bool* aCancel,
|
||||
curPositionedDiv =
|
||||
HTMLEditorRef().CreateNodeWithTransaction(
|
||||
*nsGkAtoms::div, splitNodeResult.SplitPoint());
|
||||
if (NS_WARN_IF(!CanHandleEditAction())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
NS_WARNING_ASSERTION(curPositionedDiv,
|
||||
"Failed to create current positioned div element");
|
||||
mNewBlock = curPositionedDiv;
|
||||
*aTargetElement = curPositionedDiv;
|
||||
}
|
||||
EditorRawDOMPoint atEndOfCurPositionedDiv;
|
||||
atEndOfCurPositionedDiv.SetToEndOf(curPositionedDiv);
|
||||
curList =
|
||||
HTMLEditorRef().CreateNodeWithTransaction(*containerName,
|
||||
atEndOfCurPositionedDiv);
|
||||
if (NS_WARN_IF(!CanHandleEditAction())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
if (NS_WARN_IF(!curList)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -10092,6 +10132,9 @@ HTMLEditRules::WillAbsolutePosition(bool* aCancel,
|
||||
// Tuck the node into the end of the active list
|
||||
rv = HTMLEditorRef().MoveNodeToEndWithTransaction(*curNode->AsContent(),
|
||||
*curList);
|
||||
if (NS_WARN_IF(!CanHandleEditAction())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
@ -10135,20 +10178,29 @@ HTMLEditRules::WillAbsolutePosition(bool* aCancel,
|
||||
curPositionedDiv =
|
||||
HTMLEditorRef().CreateNodeWithTransaction(*nsGkAtoms::div,
|
||||
atListItemParent);
|
||||
if (NS_WARN_IF(!CanHandleEditAction())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
NS_WARNING_ASSERTION(curPositionedDiv,
|
||||
"Failed to create current positioned div element");
|
||||
mNewBlock = curPositionedDiv;
|
||||
*aTargetElement = curPositionedDiv;
|
||||
}
|
||||
EditorRawDOMPoint atEndOfCurPositionedDiv;
|
||||
atEndOfCurPositionedDiv.SetToEndOf(curPositionedDiv);
|
||||
curList =
|
||||
HTMLEditorRef().CreateNodeWithTransaction(*containerName,
|
||||
atEndOfCurPositionedDiv);
|
||||
if (NS_WARN_IF(!CanHandleEditAction())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
if (NS_WARN_IF(!curList)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
rv = HTMLEditorRef().MoveNodeToEndWithTransaction(*listItem, *curList);
|
||||
if (NS_WARN_IF(!CanHandleEditAction())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
@ -10161,7 +10213,7 @@ HTMLEditRules::WillAbsolutePosition(bool* aCancel,
|
||||
if (!curPositionedDiv) {
|
||||
if (curNode->IsHTMLElement(nsGkAtoms::div)) {
|
||||
curPositionedDiv = curNode->AsElement();
|
||||
mNewBlock = curPositionedDiv;
|
||||
*aTargetElement = curPositionedDiv;
|
||||
curList = nullptr;
|
||||
continue;
|
||||
}
|
||||
@ -10174,17 +10226,23 @@ HTMLEditRules::WillAbsolutePosition(bool* aCancel,
|
||||
curPositionedDiv =
|
||||
HTMLEditorRef().CreateNodeWithTransaction(*nsGkAtoms::div,
|
||||
splitNodeResult.SplitPoint());
|
||||
if (NS_WARN_IF(!CanHandleEditAction())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
if (NS_WARN_IF(!curPositionedDiv)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// Remember our new block for postprocessing
|
||||
mNewBlock = curPositionedDiv;
|
||||
*aTargetElement = curPositionedDiv;
|
||||
// curPositionedDiv is now the correct thing to put curNode in
|
||||
}
|
||||
|
||||
// Tuck the node into the end of the active blockquote
|
||||
rv = HTMLEditorRef().MoveNodeToEndWithTransaction(*curNode->AsContent(),
|
||||
*curPositionedDiv);
|
||||
if (NS_WARN_IF(!CanHandleEditAction())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -258,7 +258,6 @@ protected:
|
||||
nsresult WillOutdent(bool* aCancel, bool* aHandled);
|
||||
nsresult WillAlign(const nsAString& aAlignType,
|
||||
bool* aCancel, bool* aHandled);
|
||||
nsresult WillAbsolutePosition(bool* aCancel, bool* aHandled);
|
||||
|
||||
/**
|
||||
* Called before changing absolute positioned element to static positioned.
|
||||
@ -292,6 +291,32 @@ protected:
|
||||
nsresult MakeBasicBlock(nsAtom& aBlockType);
|
||||
nsresult DidMakeBasicBlock(RulesInfo* aInfo, nsresult aResult);
|
||||
|
||||
/**
|
||||
* Called before changing an element to absolute positioned.
|
||||
* This method only prepares the operation since DidAbsolutePosition() will
|
||||
* change it actually later. mNewBlock is set to the target element and
|
||||
* if necessary, some ancestor nodes of selection may be split.
|
||||
*
|
||||
* @param aCancel Returns true if the operation is canceled.
|
||||
* @param aHandled Returns true if the edit action is handled.
|
||||
*/
|
||||
MOZ_MUST_USE nsresult WillAbsolutePosition(bool* aCancel, bool* aHandled);
|
||||
|
||||
/**
|
||||
* PrepareToMakeElementAbsolutePosition() is helper method of
|
||||
* WillAbsolutePosition() since in some cases, needs to restore selection
|
||||
* with AutoSelectionRestorer. So, all callers have to check if
|
||||
* CanHandleEditAction() still returns true after a call of this method.
|
||||
* XXX Should be documented outline of this method.
|
||||
*
|
||||
* @param aHandled Returns true if the edit action is handled.
|
||||
* @param aTargetElement Returns target element which should be
|
||||
* changed to absolute positioned.
|
||||
*/
|
||||
MOZ_MUST_USE nsresult
|
||||
PrepareToMakeElementAbsolutePosition(bool* aHandled,
|
||||
RefPtr<Element>* aTargetElement);
|
||||
|
||||
/**
|
||||
* Called if nobody handles the edit action to make an element absolute
|
||||
* positioned.
|
||||
@ -596,7 +621,7 @@ protected:
|
||||
RefPtr<nsRange> mUtilRange;
|
||||
// Need to remember an int across willJoin/didJoin...
|
||||
uint32_t mJoinOffset;
|
||||
nsCOMPtr<Element> mNewBlock;
|
||||
RefPtr<Element> mNewBlock;
|
||||
RefPtr<RangeItem> mRangeItem;
|
||||
|
||||
// XXX In strict speaking, mCachedStyles isn't enough to cache inline styles
|
||||
|
Loading…
Reference in New Issue
Block a user