Bug 1776056 - Switch to the tab an animation is running and make sure the animation...
[gecko.git] / editor / libeditor / HTMLAnonymousNodeEditor.cpp
blob4c83c0a22e6b36c206bbca953c96c28fd88ba397
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "HTMLEditor.h"
7 #include "CSSEditUtils.h"
8 #include "HTMLEditUtils.h"
10 #include "mozilla/Attributes.h"
11 #include "mozilla/PresShell.h"
12 #include "mozilla/PresShellInlines.h"
13 #include "mozilla/dom/BindContext.h"
14 #include "mozilla/dom/Element.h"
15 #include "mozilla/dom/EventTarget.h"
16 #include "mozilla/mozalloc.h"
17 #include "nsAString.h"
18 #include "nsCOMPtr.h"
19 #include "nsComputedDOMStyle.h"
20 #include "nsDebug.h"
21 #include "nsError.h"
22 #include "nsGenericHTMLElement.h"
23 #include "nsGkAtoms.h"
24 #include "nsAtom.h"
25 #include "nsIContent.h"
26 #include "nsID.h"
27 #include "mozilla/dom/Document.h"
28 #include "nsIDocumentObserver.h"
29 #include "nsStubMutationObserver.h"
30 #include "nsINode.h"
31 #include "nsISupportsImpl.h"
32 #include "nsISupportsUtils.h"
33 #include "nsLiteralString.h"
34 #include "nsPresContext.h"
35 #include "nsReadableUtils.h"
36 #include "nsString.h"
37 #include "nsStringFwd.h"
38 #include "nsStyledElement.h"
39 #include "nsUnicharUtils.h"
40 #include "nscore.h"
41 #include "nsContentUtils.h" // for nsAutoScriptBlocker
42 #include "nsROCSSPrimitiveValue.h"
44 class nsIDOMEventListener;
46 namespace mozilla {
48 using namespace dom;
50 // Retrieve the rounded number of CSS pixels from a computed CSS property.
52 // Note that this should only be called for properties whose resolved value
53 // is CSS pixels (like width, height, left, top, right, bottom, margin, padding,
54 // border-*-width, ...).
56 // See: https://drafts.csswg.org/cssom/#resolved-values
57 static int32_t GetCSSFloatValue(nsComputedDOMStyle* aComputedStyle,
58 const nsACString& aProperty) {
59 MOZ_ASSERT(aComputedStyle);
61 // get the computed CSSValue of the property
62 nsAutoCString value;
63 nsresult rv = aComputedStyle->GetPropertyValue(aProperty, value);
64 if (NS_FAILED(rv)) {
65 NS_WARNING("nsComputedDOMStyle::GetPropertyValue() failed");
66 return 0;
69 // We only care about resolved values, not a big deal if the element is
70 // undisplayed, for example, and the value is "auto" or what not.
71 int32_t val = value.ToInteger(&rv);
72 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "nsAString::ToInteger() failed");
73 return NS_SUCCEEDED(rv) ? val : 0;
76 /******************************************************************************
77 * mozilla::ElementDeletionObserver
78 *****************************************************************************/
80 class ElementDeletionObserver final : public nsStubMultiMutationObserver {
81 public:
82 ElementDeletionObserver(nsIContent* aNativeAnonNode,
83 Element* aObservedElement)
84 : mNativeAnonNode(aNativeAnonNode), mObservedElement(aObservedElement) {
85 AddMutationObserverToNode(aNativeAnonNode);
86 AddMutationObserverToNode(aObservedElement);
89 NS_DECL_ISUPPORTS
90 NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED
91 NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
93 protected:
94 ~ElementDeletionObserver() = default;
95 nsIContent* mNativeAnonNode;
96 Element* mObservedElement;
99 NS_IMPL_ISUPPORTS(ElementDeletionObserver, nsIMutationObserver)
101 void ElementDeletionObserver::ParentChainChanged(nsIContent* aContent) {
102 // If the native anonymous content has been unbound already in
103 // DeleteRefToAnonymousNode, mNativeAnonNode's parentNode is null.
104 if (aContent != mObservedElement || !mNativeAnonNode ||
105 mNativeAnonNode->GetParent() != aContent) {
106 return;
109 ManualNACPtr::RemoveContentFromNACArray(mNativeAnonNode);
111 mObservedElement->RemoveMutationObserver(this);
112 mObservedElement = nullptr;
113 mNativeAnonNode->RemoveMutationObserver(this);
114 mNativeAnonNode = nullptr;
115 NS_RELEASE_THIS();
118 void ElementDeletionObserver::NodeWillBeDestroyed(nsINode* aNode) {
119 NS_ASSERTION(aNode == mNativeAnonNode || aNode == mObservedElement,
120 "Wrong aNode!");
121 if (aNode == mNativeAnonNode) {
122 mObservedElement->RemoveMutationObserver(this);
123 mObservedElement = nullptr;
124 } else {
125 mNativeAnonNode->RemoveMutationObserver(this);
126 mNativeAnonNode->UnbindFromTree();
127 mNativeAnonNode = nullptr;
130 NS_RELEASE_THIS();
133 /******************************************************************************
134 * mozilla::HTMLEditor
135 *****************************************************************************/
137 ManualNACPtr HTMLEditor::CreateAnonymousElement(nsAtom* aTag,
138 nsIContent& aParentContent,
139 const nsAString& aAnonClass,
140 bool aIsCreatedHidden) {
141 // Don't put anonymous editor element into non-HTML element.
142 // It is mainly for avoiding other anonymous element being inserted
143 // into <svg:use>, but in general we probably don't want to insert
144 // some random HTML anonymous element into a non-HTML element.
145 if (!aParentContent.IsHTMLElement()) {
146 return nullptr;
149 if (NS_WARN_IF(!GetDocument())) {
150 return nullptr;
153 RefPtr<PresShell> presShell = GetPresShell();
154 if (NS_WARN_IF(!presShell)) {
155 return nullptr;
158 // Create a new node through the element factory
159 RefPtr<Element> newElement = CreateHTMLContent(aTag);
160 if (!newElement) {
161 NS_WARNING("EditorBase::CreateHTMLContent() failed");
162 return nullptr;
165 // add the "hidden" class if needed
166 if (aIsCreatedHidden) {
167 nsresult rv = newElement->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
168 u"hidden"_ns, true);
169 if (NS_FAILED(rv)) {
170 NS_WARNING("Element::SetAttr(nsGkAtoms::_class, hidden) failed");
171 return nullptr;
175 // add an _moz_anonclass attribute if needed
176 if (!aAnonClass.IsEmpty()) {
177 nsresult rv = newElement->SetAttr(
178 kNameSpaceID_None, nsGkAtoms::_moz_anonclass, aAnonClass, true);
179 if (NS_FAILED(rv)) {
180 NS_WARNING("Element::SetAttr(nsGkAtoms::_moz_anonclass) failed");
181 return nullptr;
186 nsAutoScriptBlocker scriptBlocker;
188 // establish parenthood of the element
189 newElement->SetIsNativeAnonymousRoot();
190 BindContext context(*aParentContent.AsElement(),
191 BindContext::ForNativeAnonymous);
192 nsresult rv = newElement->BindToTree(context, aParentContent);
193 if (NS_FAILED(rv)) {
194 NS_WARNING("Element::BindToTree(BindContext::ForNativeAnonymous) failed");
195 newElement->UnbindFromTree();
196 return nullptr;
200 ManualNACPtr newNativeAnonymousContent(newElement.forget());
202 // Must style the new element, otherwise the PostRecreateFramesFor call
203 // below will do nothing.
204 ServoStyleSet* styleSet = presShell->StyleSet();
205 // Sometimes editor likes to append anonymous content to elements
206 // in display:none subtrees, so avoid styling in those cases.
207 if (ServoStyleSet::MayTraverseFrom(newNativeAnonymousContent)) {
208 styleSet->StyleNewSubtree(newNativeAnonymousContent);
211 auto* observer = new ElementDeletionObserver(newNativeAnonymousContent,
212 aParentContent.AsElement());
213 NS_ADDREF(observer); // NodeWillBeDestroyed releases.
215 #ifdef DEBUG
216 // Editor anonymous content gets passed to PostRecreateFramesFor... which
217 // can't _really_ deal with anonymous content (because it can't get the frame
218 // tree ordering right). But for us the ordering doesn't matter so this is
219 // sort of ok.
220 newNativeAnonymousContent->SetProperty(nsGkAtoms::restylableAnonymousNode,
221 reinterpret_cast<void*>(true));
222 #endif // DEBUG
224 // display the element
225 presShell->PostRecreateFramesFor(newNativeAnonymousContent);
227 return newNativeAnonymousContent;
230 // Removes event listener and calls DeleteRefToAnonymousNode.
231 void HTMLEditor::RemoveListenerAndDeleteRef(const nsAString& aEvent,
232 nsIDOMEventListener* aListener,
233 bool aUseCapture,
234 ManualNACPtr aElement,
235 PresShell* aPresShell) {
236 if (aElement) {
237 aElement->RemoveEventListener(aEvent, aListener, aUseCapture);
239 DeleteRefToAnonymousNode(std::move(aElement), aPresShell);
242 // Deletes all references to an anonymous element
243 void HTMLEditor::DeleteRefToAnonymousNode(ManualNACPtr aContent,
244 PresShell* aPresShell) {
245 // call ContentRemoved() for the anonymous content
246 // node so its references get removed from the frame manager's
247 // undisplay map, and its layout frames get destroyed!
249 if (NS_WARN_IF(!aContent)) {
250 return;
253 if (NS_WARN_IF(!aContent->GetParent())) {
254 // aContent was already removed?
255 return;
258 nsAutoScriptBlocker scriptBlocker;
259 // Need to check whether aPresShell has been destroyed (but not yet deleted).
260 // See bug 338129.
261 if (aContent->IsInComposedDoc() && aPresShell &&
262 !aPresShell->IsDestroying()) {
263 MOZ_ASSERT(aContent->IsRootOfNativeAnonymousSubtree());
264 MOZ_ASSERT(!aContent->GetPreviousSibling(), "NAC has no siblings");
266 // FIXME(emilio): This is the only caller to PresShell::ContentRemoved that
267 // passes NAC into it. This is not great!
268 aPresShell->ContentRemoved(aContent, nullptr);
271 // The ManualNACPtr destructor will invoke UnbindFromTree.
274 void HTMLEditor::HideAnonymousEditingUIs() {
275 if (mAbsolutelyPositionedObject) {
276 HideGrabberInternal();
277 NS_ASSERTION(!mAbsolutelyPositionedObject,
278 "HTMLEditor::HideGrabberInternal() failed, but ignored");
280 if (mInlineEditedCell) {
281 HideInlineTableEditingUIInternal();
282 NS_ASSERTION(
283 !mInlineEditedCell,
284 "HTMLEditor::HideInlineTableEditingUIInternal() failed, but ignored");
286 if (mResizedObject) {
287 DebugOnly<nsresult> rvIgnored = HideResizersInternal();
288 NS_WARNING_ASSERTION(
289 NS_SUCCEEDED(rvIgnored),
290 "HTMLEditor::HideResizersInternal() failed, but ignored");
291 NS_ASSERTION(!mResizedObject,
292 "HTMLEditor::HideResizersInternal() failed, but ignored");
296 void HTMLEditor::HideAnonymousEditingUIsIfUnnecessary() {
297 // XXX Perhaps, this is wrong approach to hide multiple UIs because
298 // hiding one UI may causes overwriting existing UI with newly
299 // created one. In such case, we will leak ovewritten UI.
300 if (!IsAbsolutePositionEditorEnabled() && mAbsolutelyPositionedObject) {
301 // XXX If we're moving something, we need to cancel or commit the
302 // operation now.
303 HideGrabberInternal();
304 NS_ASSERTION(!mAbsolutelyPositionedObject,
305 "HTMLEditor::HideGrabberInternal() failed, but ignored");
307 if (!IsInlineTableEditorEnabled() && mInlineEditedCell) {
308 // XXX If we're resizing a table element, we need to cancel or commit the
309 // operation now.
310 HideInlineTableEditingUIInternal();
311 NS_ASSERTION(
312 !mInlineEditedCell,
313 "HTMLEditor::HideInlineTableEditingUIInternal() failed, but ignored");
315 if (!IsObjectResizerEnabled() && mResizedObject) {
316 // XXX If we're resizing something, we need to cancel or commit the
317 // operation now.
318 DebugOnly<nsresult> rvIgnored = HideResizersInternal();
319 NS_WARNING_ASSERTION(
320 NS_SUCCEEDED(rvIgnored),
321 "HTMLEditor::HideResizersInternal() failed, but ignored");
322 NS_ASSERTION(!mResizedObject,
323 "HTMLEditor::HideResizersInternal() failed, but ignored");
327 NS_IMETHODIMP HTMLEditor::CheckSelectionStateForAnonymousButtons() {
328 AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
329 if (NS_WARN_IF(!editActionData.CanHandle())) {
330 return NS_ERROR_NOT_INITIALIZED;
333 nsresult rv = RefreshEditingUI();
334 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
335 "HTMLEditor::RefereshEditingUI() failed");
336 return EditorBase::ToGenericNSResult(rv);
339 nsresult HTMLEditor::RefreshEditingUI() {
340 MOZ_ASSERT(IsEditActionDataAvailable());
342 // First, we need to remove unnecessary editing UI now since some of them
343 // may be disabled while them are visible.
344 HideAnonymousEditingUIsIfUnnecessary();
346 // early way out if all contextual UI extensions are disabled
347 if (!IsObjectResizerEnabled() && !IsAbsolutePositionEditorEnabled() &&
348 !IsInlineTableEditorEnabled()) {
349 return NS_OK;
352 // Don't change selection state if we're moving.
353 if (mIsMoving) {
354 return NS_OK;
357 // let's get the containing element of the selection
358 RefPtr<Element> selectionContainerElement = GetSelectionContainerElement();
359 if (NS_WARN_IF(!selectionContainerElement)) {
360 return NS_OK;
363 // If we're not in a document, don't try to add resizers
364 if (!selectionContainerElement->IsInUncomposedDoc()) {
365 return NS_OK;
368 // what's its tag?
369 RefPtr<Element> focusElement = std::move(selectionContainerElement);
370 nsAtom* focusTagAtom = focusElement->NodeInfo()->NameAtom();
372 RefPtr<Element> absPosElement;
373 if (IsAbsolutePositionEditorEnabled()) {
374 // Absolute Positioning support is enabled, is the selection contained
375 // in an absolutely positioned element ?
376 absPosElement = GetAbsolutelyPositionedSelectionContainer();
377 if (NS_WARN_IF(Destroyed())) {
378 return NS_ERROR_EDITOR_DESTROYED;
382 RefPtr<Element> cellElement;
383 if (IsObjectResizerEnabled() || IsInlineTableEditorEnabled()) {
384 // Resizing or Inline Table Editing is enabled, we need to check if the
385 // selection is contained in a table cell
386 cellElement = GetInclusiveAncestorByTagNameAtSelection(*nsGkAtoms::td);
389 if (IsObjectResizerEnabled() && cellElement) {
390 // we are here because Resizing is enabled AND selection is contained in
391 // a cell
393 // get the enclosing table
394 if (nsGkAtoms::img != focusTagAtom) {
395 // the element container of the selection is not an image, so we'll show
396 // the resizers around the table
397 // XXX There may be a bug. cellElement may be not in <table> in invalid
398 // tree. So, perhaps, GetClosestAncestorTableElement() returns
399 // nullptr, we should not set focusTagAtom to nsGkAtoms::table.
400 focusElement =
401 HTMLEditUtils::GetClosestAncestorTableElement(*cellElement);
402 focusTagAtom = nsGkAtoms::table;
406 // we allow resizers only around images, tables, and absolutely positioned
407 // elements. If we don't have image/table, let's look at the latter case.
408 if (nsGkAtoms::img != focusTagAtom && nsGkAtoms::table != focusTagAtom) {
409 focusElement = absPosElement;
412 // at this point, focusElement contains the element for Resizing,
413 // cellElement contains the element for InlineTableEditing
414 // absPosElement contains the element for Positioning
416 // Note: All the Hide/Show methods below may change attributes on real
417 // content which means a DOMAttrModified handler may cause arbitrary
418 // side effects while this code runs (bug 420439).
420 if (IsAbsolutePositionEditorEnabled() && mAbsolutelyPositionedObject &&
421 absPosElement != mAbsolutelyPositionedObject) {
422 HideGrabberInternal();
423 NS_ASSERTION(!mAbsolutelyPositionedObject,
424 "HTMLEditor::HideGrabberInternal() failed, but ignored");
427 if (IsObjectResizerEnabled() && mResizedObject &&
428 mResizedObject != focusElement) {
429 // Perhaps, even if HideResizersInternal() failed, we should try to hide
430 // inline table editing UI. However, it returns error only when we cannot
431 // do anything. So, it's okay for now.
432 nsresult rv = HideResizersInternal();
433 if (NS_FAILED(rv)) {
434 NS_WARNING("HTMLEditor::HideResizersInternal() failed");
435 return rv;
437 NS_ASSERTION(!mResizedObject,
438 "HTMLEditor::HideResizersInternal() failed, but ignored");
441 if (IsInlineTableEditorEnabled() && mInlineEditedCell &&
442 mInlineEditedCell != cellElement) {
443 HideInlineTableEditingUIInternal();
444 NS_ASSERTION(
445 !mInlineEditedCell,
446 "HTMLEditor::HideInlineTableEditingUIInternal failed, but ignored");
449 // now, let's display all contextual UI for good
450 nsIContent* hostContent = ComputeEditingHost();
452 if (IsObjectResizerEnabled() && focusElement &&
453 HTMLEditUtils::IsSimplyEditableNode(*focusElement) &&
454 focusElement != hostContent) {
455 if (nsGkAtoms::img == focusTagAtom) {
456 mResizedObjectIsAnImage = true;
458 if (mResizedObject) {
459 nsresult rv = RefreshResizersInternal();
460 if (NS_FAILED(rv)) {
461 NS_WARNING("HTMLEditor::RefreshResizersInternal() failed");
462 return rv;
464 } else {
465 nsresult rv = ShowResizersInternal(*focusElement);
466 if (NS_FAILED(rv)) {
467 NS_WARNING("HTMLEditor::ShowResizersInternal() failed");
468 return rv;
473 if (IsAbsolutePositionEditorEnabled() && absPosElement &&
474 HTMLEditUtils::IsSimplyEditableNode(*absPosElement) &&
475 absPosElement != hostContent) {
476 if (mAbsolutelyPositionedObject) {
477 nsresult rv = RefreshGrabberInternal();
478 if (NS_FAILED(rv)) {
479 NS_WARNING("HTMLEditor::RefreshGrabberInternal() failed");
480 return rv;
482 } else {
483 nsresult rv = ShowGrabberInternal(*absPosElement);
484 if (NS_FAILED(rv)) {
485 NS_WARNING("HTMLEditor::ShowGrabberInternal() failed");
486 return rv;
491 // XXX Shouldn't we check whether the `<table>` element is editable or not?
492 if (IsInlineTableEditorEnabled() && cellElement &&
493 HTMLEditUtils::IsSimplyEditableNode(*cellElement) &&
494 cellElement != hostContent) {
495 if (mInlineEditedCell) {
496 nsresult rv = RefreshInlineTableEditingUIInternal();
497 if (NS_FAILED(rv)) {
498 NS_WARNING("HTMLEditor::RefreshInlineTableEditingUIInternal() failed");
499 return rv;
501 } else {
502 nsresult rv = ShowInlineTableEditingUIInternal(*cellElement);
503 if (NS_FAILED(rv)) {
504 NS_WARNING("HTMLEditor::ShowInlineTableEditingUIInternal() failed");
505 return rv;
510 return NS_OK;
513 // Resizing and Absolute Positioning need to know everything about the
514 // containing box of the element: position, size, margins, borders
515 nsresult HTMLEditor::GetPositionAndDimensions(Element& aElement, int32_t& aX,
516 int32_t& aY, int32_t& aW,
517 int32_t& aH, int32_t& aBorderLeft,
518 int32_t& aBorderTop,
519 int32_t& aMarginLeft,
520 int32_t& aMarginTop) {
521 // Is the element positioned ? let's check the cheap way first...
522 bool isPositioned =
523 aElement.HasAttr(kNameSpaceID_None, nsGkAtoms::_moz_abspos);
524 if (!isPositioned) {
525 // hmmm... the expensive way now...
526 nsAutoString positionValue;
527 DebugOnly<nsresult> rvIgnored = CSSEditUtils::GetComputedProperty(
528 aElement, *nsGkAtoms::position, positionValue);
529 if (NS_WARN_IF(Destroyed())) {
530 return NS_ERROR_EDITOR_DESTROYED;
532 NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
533 "CSSEditUtils::GetComputedProperty(nsGkAtoms::"
534 "position) failed, but ignored");
535 isPositioned = positionValue.EqualsLiteral("absolute");
538 if (isPositioned) {
539 // Yes, it is absolutely positioned
540 mResizedObjectIsAbsolutelyPositioned = true;
542 // Get the all the computed css styles attached to the element node
543 RefPtr<nsComputedDOMStyle> computedDOMStyle =
544 CSSEditUtils::GetComputedStyle(&aElement);
545 if (NS_WARN_IF(!computedDOMStyle)) {
546 return NS_ERROR_FAILURE;
549 aBorderLeft = GetCSSFloatValue(computedDOMStyle, "border-left-width"_ns);
550 aBorderTop = GetCSSFloatValue(computedDOMStyle, "border-top-width"_ns);
551 aMarginLeft = GetCSSFloatValue(computedDOMStyle, "margin-left"_ns);
552 aMarginTop = GetCSSFloatValue(computedDOMStyle, "margin-top"_ns);
554 aX = GetCSSFloatValue(computedDOMStyle, "left"_ns) + aMarginLeft +
555 aBorderLeft;
556 aY = GetCSSFloatValue(computedDOMStyle, "top"_ns) + aMarginTop + aBorderTop;
557 aW = GetCSSFloatValue(computedDOMStyle, "width"_ns);
558 aH = GetCSSFloatValue(computedDOMStyle, "height"_ns);
559 } else {
560 mResizedObjectIsAbsolutelyPositioned = false;
561 RefPtr<nsGenericHTMLElement> htmlElement =
562 nsGenericHTMLElement::FromNode(aElement);
563 if (!htmlElement) {
564 return NS_ERROR_NULL_POINTER;
566 DebugOnly<nsresult> rvIgnored = GetElementOrigin(aElement, aX, aY);
567 NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
568 "HTMLEditor::GetElementOrigin() failed, but ignored");
570 aW = htmlElement->OffsetWidth();
571 aH = htmlElement->OffsetHeight();
573 aBorderLeft = 0;
574 aBorderTop = 0;
575 aMarginLeft = 0;
576 aMarginTop = 0;
578 return NS_OK;
581 nsresult HTMLEditor::SetAnonymousElementPositionWithoutTransaction(
582 nsStyledElement& aStyledElement, int32_t aX, int32_t aY) {
583 nsresult rv;
584 rv = CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(
585 aStyledElement, *nsGkAtoms::left, aX);
586 if (rv == NS_ERROR_EDITOR_DESTROYED) {
587 NS_WARNING(
588 "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(nsGkAtoms::left) "
589 "destroyed the editor");
590 return NS_ERROR_EDITOR_DESTROYED;
592 NS_WARNING_ASSERTION(
593 NS_SUCCEEDED(rv),
594 "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(nsGkAtoms::left) "
595 "failed, but ignored");
596 rv = CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(
597 aStyledElement, *nsGkAtoms::top, aY);
598 if (rv == NS_ERROR_EDITOR_DESTROYED) {
599 NS_WARNING(
600 "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(nsGkAtoms::top) "
601 "destroyed the editor");
602 return NS_ERROR_EDITOR_DESTROYED;
604 NS_WARNING_ASSERTION(
605 NS_SUCCEEDED(rv),
606 "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(nsGkAtoms::top) "
607 "failed, but ignored");
608 return NS_OK;
611 } // namespace mozilla