Bug 1890689 accumulate input in LargerReceiverBlockSizeThanDesiredBuffering GTest...
[gecko.git] / editor / libeditor / HTMLAnonymousNodeEditor.cpp
blobf89b4e334ab7cb8fd70915299fe0c3c555aef07c
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 aComputedStyle->GetPropertyValue(aProperty, value);
64 // We only care about resolved values, not a big deal if the element is
65 // undisplayed, for example, and the value is "auto" or what not.
66 nsresult rv = NS_OK;
67 int32_t val = value.ToInteger(&rv);
68 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "nsAString::ToInteger() failed");
69 return NS_SUCCEEDED(rv) ? val : 0;
72 /******************************************************************************
73 * mozilla::ElementDeletionObserver
74 *****************************************************************************/
76 class ElementDeletionObserver final : public nsStubMultiMutationObserver {
77 public:
78 ElementDeletionObserver(nsIContent* aNativeAnonNode,
79 Element* aObservedElement)
80 : mNativeAnonNode(aNativeAnonNode), mObservedElement(aObservedElement) {
81 AddMutationObserverToNode(aNativeAnonNode);
82 AddMutationObserverToNode(aObservedElement);
85 NS_DECL_ISUPPORTS
86 NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED
87 NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
89 protected:
90 ~ElementDeletionObserver() = default;
91 nsIContent* mNativeAnonNode;
92 Element* mObservedElement;
95 NS_IMPL_ISUPPORTS(ElementDeletionObserver, nsIMutationObserver)
97 void ElementDeletionObserver::ParentChainChanged(nsIContent* aContent) {
98 // If the native anonymous content has been unbound already in
99 // DeleteRefToAnonymousNode, mNativeAnonNode's parentNode is null.
100 if (aContent != mObservedElement || !mNativeAnonNode ||
101 mNativeAnonNode->GetParent() != aContent) {
102 return;
105 ManualNACPtr::RemoveContentFromNACArray(mNativeAnonNode);
107 mObservedElement->RemoveMutationObserver(this);
108 mObservedElement = nullptr;
109 mNativeAnonNode->RemoveMutationObserver(this);
110 mNativeAnonNode = nullptr;
111 NS_RELEASE_THIS();
114 void ElementDeletionObserver::NodeWillBeDestroyed(nsINode* aNode) {
115 NS_ASSERTION(aNode == mNativeAnonNode || aNode == mObservedElement,
116 "Wrong aNode!");
117 if (aNode == mNativeAnonNode) {
118 mObservedElement->RemoveMutationObserver(this);
119 mObservedElement = nullptr;
120 } else {
121 mNativeAnonNode->RemoveMutationObserver(this);
122 mNativeAnonNode->UnbindFromTree();
123 mNativeAnonNode = nullptr;
126 NS_RELEASE_THIS();
129 /******************************************************************************
130 * mozilla::HTMLEditor
131 *****************************************************************************/
133 ManualNACPtr HTMLEditor::CreateAnonymousElement(nsAtom* aTag,
134 nsIContent& aParentContent,
135 const nsAString& aAnonClass,
136 bool aIsCreatedHidden) {
137 // Don't put anonymous editor element into non-HTML element.
138 // It is mainly for avoiding other anonymous element being inserted
139 // into <svg:use>, but in general we probably don't want to insert
140 // some random HTML anonymous element into a non-HTML element.
141 if (!aParentContent.IsHTMLElement()) {
142 return nullptr;
145 if (NS_WARN_IF(!GetDocument())) {
146 return nullptr;
149 RefPtr<PresShell> presShell = GetPresShell();
150 if (NS_WARN_IF(!presShell)) {
151 return nullptr;
154 // Create a new node through the element factory
155 RefPtr<Element> newElement = CreateHTMLContent(aTag);
156 if (!newElement) {
157 NS_WARNING("EditorBase::CreateHTMLContent() failed");
158 return nullptr;
161 // add the "hidden" class if needed
162 if (aIsCreatedHidden) {
163 nsresult rv = newElement->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
164 u"hidden"_ns, true);
165 if (NS_FAILED(rv)) {
166 NS_WARNING("Element::SetAttr(nsGkAtoms::_class, hidden) failed");
167 return nullptr;
171 // add an _moz_anonclass attribute if needed
172 if (!aAnonClass.IsEmpty()) {
173 nsresult rv = newElement->SetAttr(
174 kNameSpaceID_None, nsGkAtoms::_moz_anonclass, aAnonClass, true);
175 if (NS_FAILED(rv)) {
176 NS_WARNING("Element::SetAttr(nsGkAtoms::_moz_anonclass) failed");
177 return nullptr;
182 nsAutoScriptBlocker scriptBlocker;
184 // establish parenthood of the element
185 newElement->SetIsNativeAnonymousRoot();
186 BindContext context(*aParentContent.AsElement(),
187 BindContext::ForNativeAnonymous);
188 nsresult rv = newElement->BindToTree(context, aParentContent);
189 if (NS_FAILED(rv)) {
190 NS_WARNING("Element::BindToTree(BindContext::ForNativeAnonymous) failed");
191 newElement->UnbindFromTree();
192 return nullptr;
196 ManualNACPtr newNativeAnonymousContent(newElement.forget());
198 // Must style the new element, otherwise the PostRecreateFramesFor call
199 // below will do nothing.
200 ServoStyleSet* styleSet = presShell->StyleSet();
201 // Sometimes editor likes to append anonymous content to elements
202 // in display:none subtrees, so avoid styling in those cases.
203 if (ServoStyleSet::MayTraverseFrom(newNativeAnonymousContent)) {
204 styleSet->StyleNewSubtree(newNativeAnonymousContent);
207 auto* observer = new ElementDeletionObserver(newNativeAnonymousContent,
208 aParentContent.AsElement());
209 NS_ADDREF(observer); // NodeWillBeDestroyed releases.
211 #ifdef DEBUG
212 // Editor anonymous content gets passed to PostRecreateFramesFor... which
213 // can't _really_ deal with anonymous content (because it can't get the frame
214 // tree ordering right). But for us the ordering doesn't matter so this is
215 // sort of ok.
216 newNativeAnonymousContent->SetProperty(nsGkAtoms::restylableAnonymousNode,
217 reinterpret_cast<void*>(true));
218 #endif // DEBUG
220 // display the element
221 presShell->PostRecreateFramesFor(newNativeAnonymousContent);
223 return newNativeAnonymousContent;
226 // Removes event listener and calls DeleteRefToAnonymousNode.
227 void HTMLEditor::RemoveListenerAndDeleteRef(const nsAString& aEvent,
228 nsIDOMEventListener* aListener,
229 bool aUseCapture,
230 ManualNACPtr aElement,
231 PresShell* aPresShell) {
232 if (aElement) {
233 aElement->RemoveEventListener(aEvent, aListener, aUseCapture);
235 DeleteRefToAnonymousNode(std::move(aElement), aPresShell);
238 // Deletes all references to an anonymous element
239 void HTMLEditor::DeleteRefToAnonymousNode(ManualNACPtr aContent,
240 PresShell* aPresShell) {
241 // call ContentRemoved() for the anonymous content
242 // node so its references get removed from the frame manager's
243 // undisplay map, and its layout frames get destroyed!
245 if (NS_WARN_IF(!aContent)) {
246 return;
249 if (NS_WARN_IF(!aContent->GetParent())) {
250 // aContent was already removed?
251 return;
254 nsAutoScriptBlocker scriptBlocker;
255 // Need to check whether aPresShell has been destroyed (but not yet deleted).
256 // See bug 338129.
257 if (aContent->IsInComposedDoc() && aPresShell &&
258 !aPresShell->IsDestroying()) {
259 MOZ_ASSERT(aContent->IsRootOfNativeAnonymousSubtree());
260 MOZ_ASSERT(!aContent->GetPreviousSibling(), "NAC has no siblings");
262 // FIXME(emilio): This is the only caller to PresShell::ContentRemoved that
263 // passes NAC into it. This is not great!
264 aPresShell->ContentRemoved(aContent, nullptr);
267 // The ManualNACPtr destructor will invoke UnbindFromTree.
270 void HTMLEditor::HideAnonymousEditingUIs() {
271 if (mAbsolutelyPositionedObject) {
272 HideGrabberInternal();
273 NS_ASSERTION(!mAbsolutelyPositionedObject,
274 "HTMLEditor::HideGrabberInternal() failed, but ignored");
276 if (mInlineEditedCell) {
277 HideInlineTableEditingUIInternal();
278 NS_ASSERTION(
279 !mInlineEditedCell,
280 "HTMLEditor::HideInlineTableEditingUIInternal() failed, but ignored");
282 if (mResizedObject) {
283 DebugOnly<nsresult> rvIgnored = HideResizersInternal();
284 NS_WARNING_ASSERTION(
285 NS_SUCCEEDED(rvIgnored),
286 "HTMLEditor::HideResizersInternal() failed, but ignored");
287 NS_ASSERTION(!mResizedObject,
288 "HTMLEditor::HideResizersInternal() failed, but ignored");
292 void HTMLEditor::HideAnonymousEditingUIsIfUnnecessary() {
293 // XXX Perhaps, this is wrong approach to hide multiple UIs because
294 // hiding one UI may causes overwriting existing UI with newly
295 // created one. In such case, we will leak ovewritten UI.
296 if (!IsAbsolutePositionEditorEnabled() && mAbsolutelyPositionedObject) {
297 // XXX If we're moving something, we need to cancel or commit the
298 // operation now.
299 HideGrabberInternal();
300 NS_ASSERTION(!mAbsolutelyPositionedObject,
301 "HTMLEditor::HideGrabberInternal() failed, but ignored");
303 if (!IsInlineTableEditorEnabled() && mInlineEditedCell) {
304 // XXX If we're resizing a table element, we need to cancel or commit the
305 // operation now.
306 HideInlineTableEditingUIInternal();
307 NS_ASSERTION(
308 !mInlineEditedCell,
309 "HTMLEditor::HideInlineTableEditingUIInternal() failed, but ignored");
311 if (!IsObjectResizerEnabled() && mResizedObject) {
312 // XXX If we're resizing something, we need to cancel or commit the
313 // operation now.
314 DebugOnly<nsresult> rvIgnored = HideResizersInternal();
315 NS_WARNING_ASSERTION(
316 NS_SUCCEEDED(rvIgnored),
317 "HTMLEditor::HideResizersInternal() failed, but ignored");
318 NS_ASSERTION(!mResizedObject,
319 "HTMLEditor::HideResizersInternal() failed, but ignored");
323 NS_IMETHODIMP HTMLEditor::CheckSelectionStateForAnonymousButtons() {
324 AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
325 if (NS_WARN_IF(!editActionData.CanHandle())) {
326 return NS_ERROR_NOT_INITIALIZED;
329 nsresult rv = RefreshEditingUI();
330 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
331 "HTMLEditor::RefereshEditingUI() failed");
332 return EditorBase::ToGenericNSResult(rv);
335 nsresult HTMLEditor::RefreshEditingUI() {
336 MOZ_ASSERT(IsEditActionDataAvailable());
338 // First, we need to remove unnecessary editing UI now since some of them
339 // may be disabled while them are visible.
340 HideAnonymousEditingUIsIfUnnecessary();
342 // early way out if all contextual UI extensions are disabled
343 if (!IsObjectResizerEnabled() && !IsAbsolutePositionEditorEnabled() &&
344 !IsInlineTableEditorEnabled()) {
345 return NS_OK;
348 // Don't change selection state if we're moving.
349 if (mIsMoving) {
350 return NS_OK;
353 // let's get the containing element of the selection
354 RefPtr<Element> selectionContainerElement = GetSelectionContainerElement();
355 if (NS_WARN_IF(!selectionContainerElement)) {
356 return NS_OK;
359 // If we're not in a document, don't try to add resizers
360 if (!selectionContainerElement->IsInComposedDoc()) {
361 return NS_OK;
364 // what's its tag?
365 RefPtr<Element> focusElement = std::move(selectionContainerElement);
366 nsAtom* focusTagAtom = focusElement->NodeInfo()->NameAtom();
368 RefPtr<Element> absPosElement;
369 if (IsAbsolutePositionEditorEnabled()) {
370 // Absolute Positioning support is enabled, is the selection contained
371 // in an absolutely positioned element ?
372 absPosElement = GetAbsolutelyPositionedSelectionContainer();
373 if (NS_WARN_IF(Destroyed())) {
374 return NS_ERROR_EDITOR_DESTROYED;
378 RefPtr<Element> cellElement;
379 if (IsObjectResizerEnabled() || IsInlineTableEditorEnabled()) {
380 // Resizing or Inline Table Editing is enabled, we need to check if the
381 // selection is contained in a table cell
382 cellElement = GetInclusiveAncestorByTagNameAtSelection(*nsGkAtoms::td);
385 if (IsObjectResizerEnabled() && cellElement) {
386 // we are here because Resizing is enabled AND selection is contained in
387 // a cell
389 // get the enclosing table
390 if (nsGkAtoms::img != focusTagAtom) {
391 // the element container of the selection is not an image, so we'll show
392 // the resizers around the table
393 // XXX There may be a bug. cellElement may be not in <table> in invalid
394 // tree. So, perhaps, GetClosestAncestorTableElement() returns
395 // nullptr, we should not set focusTagAtom to nsGkAtoms::table.
396 focusElement =
397 HTMLEditUtils::GetClosestAncestorTableElement(*cellElement);
398 focusTagAtom = nsGkAtoms::table;
402 // we allow resizers only around images, tables, and absolutely positioned
403 // elements. If we don't have image/table, let's look at the latter case.
404 if (nsGkAtoms::img != focusTagAtom && nsGkAtoms::table != focusTagAtom) {
405 focusElement = absPosElement;
408 // at this point, focusElement contains the element for Resizing,
409 // cellElement contains the element for InlineTableEditing
410 // absPosElement contains the element for Positioning
412 // Note: All the Hide/Show methods below may change attributes on real
413 // content which means a DOMAttrModified handler may cause arbitrary
414 // side effects while this code runs (bug 420439).
416 if (IsAbsolutePositionEditorEnabled() && mAbsolutelyPositionedObject &&
417 absPosElement != mAbsolutelyPositionedObject) {
418 HideGrabberInternal();
419 NS_ASSERTION(!mAbsolutelyPositionedObject,
420 "HTMLEditor::HideGrabberInternal() failed, but ignored");
423 if (IsObjectResizerEnabled() && mResizedObject &&
424 mResizedObject != focusElement) {
425 // Perhaps, even if HideResizersInternal() failed, we should try to hide
426 // inline table editing UI. However, it returns error only when we cannot
427 // do anything. So, it's okay for now.
428 nsresult rv = HideResizersInternal();
429 if (NS_FAILED(rv)) {
430 NS_WARNING("HTMLEditor::HideResizersInternal() failed");
431 return rv;
433 NS_ASSERTION(!mResizedObject,
434 "HTMLEditor::HideResizersInternal() failed, but ignored");
437 if (IsInlineTableEditorEnabled() && mInlineEditedCell &&
438 mInlineEditedCell != cellElement) {
439 HideInlineTableEditingUIInternal();
440 NS_ASSERTION(
441 !mInlineEditedCell,
442 "HTMLEditor::HideInlineTableEditingUIInternal failed, but ignored");
445 // now, let's display all contextual UI for good
446 nsIContent* hostContent = ComputeEditingHost();
448 if (IsObjectResizerEnabled() && focusElement &&
449 HTMLEditUtils::IsSimplyEditableNode(*focusElement) &&
450 focusElement != hostContent) {
451 if (nsGkAtoms::img == focusTagAtom) {
452 mResizedObjectIsAnImage = true;
454 if (mResizedObject) {
455 nsresult rv = RefreshResizersInternal();
456 if (NS_FAILED(rv)) {
457 NS_WARNING("HTMLEditor::RefreshResizersInternal() failed");
458 return rv;
460 } else {
461 nsresult rv = ShowResizersInternal(*focusElement);
462 if (NS_FAILED(rv)) {
463 NS_WARNING("HTMLEditor::ShowResizersInternal() failed");
464 return rv;
469 if (IsAbsolutePositionEditorEnabled() && absPosElement &&
470 HTMLEditUtils::IsSimplyEditableNode(*absPosElement) &&
471 absPosElement != hostContent) {
472 if (mAbsolutelyPositionedObject) {
473 nsresult rv = RefreshGrabberInternal();
474 if (NS_FAILED(rv)) {
475 NS_WARNING("HTMLEditor::RefreshGrabberInternal() failed");
476 return rv;
478 } else {
479 nsresult rv = ShowGrabberInternal(*absPosElement);
480 if (NS_FAILED(rv)) {
481 NS_WARNING("HTMLEditor::ShowGrabberInternal() failed");
482 return rv;
487 // XXX Shouldn't we check whether the `<table>` element is editable or not?
488 if (IsInlineTableEditorEnabled() && cellElement &&
489 HTMLEditUtils::IsSimplyEditableNode(*cellElement) &&
490 cellElement != hostContent) {
491 if (mInlineEditedCell) {
492 nsresult rv = RefreshInlineTableEditingUIInternal();
493 if (NS_FAILED(rv)) {
494 NS_WARNING("HTMLEditor::RefreshInlineTableEditingUIInternal() failed");
495 return rv;
497 } else {
498 nsresult rv = ShowInlineTableEditingUIInternal(*cellElement);
499 if (NS_FAILED(rv)) {
500 NS_WARNING("HTMLEditor::ShowInlineTableEditingUIInternal() failed");
501 return rv;
506 return NS_OK;
509 // Resizing and Absolute Positioning need to know everything about the
510 // containing box of the element: position, size, margins, borders
511 nsresult HTMLEditor::GetPositionAndDimensions(Element& aElement, int32_t& aX,
512 int32_t& aY, int32_t& aW,
513 int32_t& aH, int32_t& aBorderLeft,
514 int32_t& aBorderTop,
515 int32_t& aMarginLeft,
516 int32_t& aMarginTop) {
517 // Is the element positioned ? let's check the cheap way first...
518 bool isPositioned = aElement.HasAttr(nsGkAtoms::_moz_abspos);
519 if (!isPositioned) {
520 // hmmm... the expensive way now...
521 nsAutoString positionValue;
522 DebugOnly<nsresult> rvIgnored = CSSEditUtils::GetComputedProperty(
523 aElement, *nsGkAtoms::position, positionValue);
524 if (NS_WARN_IF(Destroyed())) {
525 return NS_ERROR_EDITOR_DESTROYED;
527 NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
528 "CSSEditUtils::GetComputedProperty(nsGkAtoms::"
529 "position) failed, but ignored");
530 isPositioned = positionValue.EqualsLiteral("absolute");
533 if (isPositioned) {
534 // Yes, it is absolutely positioned
535 mResizedObjectIsAbsolutelyPositioned = true;
537 // Get the all the computed css styles attached to the element node
538 RefPtr<nsComputedDOMStyle> computedDOMStyle =
539 CSSEditUtils::GetComputedStyle(&aElement);
540 if (NS_WARN_IF(!computedDOMStyle)) {
541 return NS_ERROR_FAILURE;
544 aBorderLeft = GetCSSFloatValue(computedDOMStyle, "border-left-width"_ns);
545 aBorderTop = GetCSSFloatValue(computedDOMStyle, "border-top-width"_ns);
546 aMarginLeft = GetCSSFloatValue(computedDOMStyle, "margin-left"_ns);
547 aMarginTop = GetCSSFloatValue(computedDOMStyle, "margin-top"_ns);
549 aX = GetCSSFloatValue(computedDOMStyle, "left"_ns) + aMarginLeft +
550 aBorderLeft;
551 aY = GetCSSFloatValue(computedDOMStyle, "top"_ns) + aMarginTop + aBorderTop;
552 aW = GetCSSFloatValue(computedDOMStyle, "width"_ns);
553 aH = GetCSSFloatValue(computedDOMStyle, "height"_ns);
554 } else {
555 mResizedObjectIsAbsolutelyPositioned = false;
556 RefPtr<nsGenericHTMLElement> htmlElement =
557 nsGenericHTMLElement::FromNode(aElement);
558 if (!htmlElement) {
559 return NS_ERROR_NULL_POINTER;
561 DebugOnly<nsresult> rvIgnored = GetElementOrigin(aElement, aX, aY);
562 NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
563 "HTMLEditor::GetElementOrigin() failed, but ignored");
565 aW = htmlElement->OffsetWidth();
566 aH = htmlElement->OffsetHeight();
568 aBorderLeft = 0;
569 aBorderTop = 0;
570 aMarginLeft = 0;
571 aMarginTop = 0;
573 return NS_OK;
576 nsresult HTMLEditor::SetAnonymousElementPositionWithoutTransaction(
577 nsStyledElement& aStyledElement, int32_t aX, int32_t aY) {
578 nsresult rv;
579 rv = CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(
580 aStyledElement, *nsGkAtoms::left, aX);
581 if (rv == NS_ERROR_EDITOR_DESTROYED) {
582 NS_WARNING(
583 "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(nsGkAtoms::left) "
584 "destroyed the editor");
585 return NS_ERROR_EDITOR_DESTROYED;
587 NS_WARNING_ASSERTION(
588 NS_SUCCEEDED(rv),
589 "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(nsGkAtoms::left) "
590 "failed, but ignored");
591 rv = CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(
592 aStyledElement, *nsGkAtoms::top, aY);
593 if (rv == NS_ERROR_EDITOR_DESTROYED) {
594 NS_WARNING(
595 "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(nsGkAtoms::top) "
596 "destroyed the editor");
597 return NS_ERROR_EDITOR_DESTROYED;
599 NS_WARNING_ASSERTION(
600 NS_SUCCEEDED(rv),
601 "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(nsGkAtoms::top) "
602 "failed, but ignored");
603 return NS_OK;
606 } // namespace mozilla