Bug 1485369 - part 1: HTMLEditor::HideResizers() should not stop cleaning up even if there is no window r=m_kato

Oddly, on 63 Beta simulation, nsIDocument::GetWindow() may return nullptr
when HTMLEditor is being destroyed by unload of the page.  I'm not sure if
this is an expected change.  However, HTMLEditor::HideResizers() should
not stop cleaning up even if it meets unexpected situation.

Additionally, this patch moves all HTMLEditor members related to resizers
to local variables since while HideResizers() is cleaning up old resizers,
the members may be overwritten by ShowResizers() if mutation event listener
or something does something.

Differential Revision: https://phabricator.services.mozilla.com/D4057

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Masayuki Nakano 2018-08-24 06:27:48 +00:00
parent 9eb175b4cb
commit 5bf1468b39
2 changed files with 60 additions and 32 deletions

View file

@ -1901,7 +1901,7 @@ protected:
ManualNACPtr mBottomHandle;
ManualNACPtr mBottomRightHandle;
nsCOMPtr<Element> mActivatedHandle;
RefPtr<Element> mActivatedHandle;
ManualNACPtr mResizingShadow;
ManualNACPtr mResizingInfo;

View file

@ -371,72 +371,100 @@ HTMLEditor::HideResizers()
NS_NAMED_LITERAL_STRING(mousedown, "mousedown");
// HTMLEditor should forget all members related to resizers first since
// removing a part of UI may cause showing the resizers again. In such
// case, the members may be overwritten by ShowResizers() and this will
// lose the chance to release the old resizers.
ManualNACPtr topLeftHandle(std::move(mTopLeftHandle));
ManualNACPtr topHandle(std::move(mTopHandle));
ManualNACPtr topRightHandle(std::move(mTopRightHandle));
ManualNACPtr leftHandle(std::move(mLeftHandle));
ManualNACPtr rightHandle(std::move(mRightHandle));
ManualNACPtr bottomLeftHandle(std::move(mBottomLeftHandle));
ManualNACPtr bottomHandle(std::move(mBottomHandle));
ManualNACPtr bottomRightHandle(std::move(mBottomRightHandle));
ManualNACPtr resizingShadow(std::move(mResizingShadow));
ManualNACPtr resizingInfo(std::move(mResizingInfo));
RefPtr<Element> activatedHandle(std::move(mActivatedHandle));
nsCOMPtr<nsIDOMEventListener> mouseMotionListener(
std::move(mMouseMotionListenerP));
nsCOMPtr<nsIDOMEventListener> resizeEventListener(
std::move(mResizeEventListenerP));
RefPtr<Element> resizedObject(std::move(mResizedObject));
// Remvoe all handles.
RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
std::move(mTopLeftHandle), presShell);
std::move(topLeftHandle), presShell);
RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
std::move(mTopHandle), presShell);
std::move(topHandle), presShell);
RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
std::move(mTopRightHandle), presShell);
std::move(topRightHandle), presShell);
RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
std::move(mLeftHandle), presShell);
std::move(leftHandle), presShell);
RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
std::move(mRightHandle), presShell);
std::move(rightHandle), presShell);
RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
std::move(mBottomLeftHandle), presShell);
std::move(bottomLeftHandle), presShell);
RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
std::move(mBottomHandle), presShell);
std::move(bottomHandle), presShell);
RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
std::move(mBottomRightHandle), presShell);
std::move(bottomRightHandle), presShell);
RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
std::move(mResizingShadow), presShell);
std::move(resizingShadow), presShell);
RemoveListenerAndDeleteRef(mousedown, mEventListener, true,
std::move(mResizingInfo), presShell);
std::move(resizingInfo), presShell);
if (mActivatedHandle) {
mActivatedHandle->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_moz_activated,
true);
mActivatedHandle = nullptr;
// Remove active state of a resizer.
if (activatedHandle) {
activatedHandle->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_moz_activated,
true);
}
// don't forget to remove the listeners !
// Remove resizing state of the target element.
resizedObject->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_moz_resizing, true);
// nsCOMPtr so we can do_QueryInterface into it.
// Remove mousemove event listener from the event target.
nsCOMPtr<EventTarget> target = GetDOMEventTarget();
NS_WARNING_ASSERTION(target, "GetDOMEventTarget() returned nullptr");
if (target && mMouseMotionListenerP) {
if (target && mouseMotionListener) {
target->RemoveEventListener(NS_LITERAL_STRING("mousemove"),
mMouseMotionListenerP, true);
mouseMotionListener, true);
}
// Remove resize event listener from the window.
if (!resizeEventListener) {
return NS_OK;
}
mMouseMotionListenerP = nullptr;
nsCOMPtr<nsIDocument> doc = GetDocument();
if (NS_WARN_IF(!doc)) {
return NS_ERROR_NULL_POINTER;
}
NS_WARNING_ASSERTION(doc->GetWindow(), "There should be a window");
target = do_QueryInterface(doc->GetWindow());
if (NS_WARN_IF(!target)) {
// nsIDocument::GetWindow() may return nullptr when HTMLEditor is destroyed
// while the document is being unloaded. If we cannot retrieve window as
// expected, let's ignore it.
nsPIDOMWindowOuter* window = doc->GetWindow();
if (NS_WARN_IF(!window)) {
return NS_OK;
}
nsCOMPtr<EventTarget> targetOfWindow = do_QueryInterface(window);
if (NS_WARN_IF(!targetOfWindow)) {
return NS_ERROR_NULL_POINTER;
}
if (mResizeEventListenerP) {
target->RemoveEventListener(NS_LITERAL_STRING("resize"),
mResizeEventListenerP, false);
}
mResizeEventListenerP = nullptr;
mResizedObject->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_moz_resizing, true);
mResizedObject = nullptr;
targetOfWindow->RemoveEventListener(NS_LITERAL_STRING("resize"),
resizeEventListener, false);
return NS_OK;
}