Bug 1772588 [wpt PR 34302] - [wpt] Add test for block-in-inline offsetParent., a...
[gecko.git] / editor / libeditor / HTMLAnonymousNodeEditor.cpp
blobbc80472d6e7975cde4df1255141ad02fec1db60d
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 "HTMLEditUtils.h"
8 #include "mozilla/Attributes.h"
9 #include "mozilla/PresShell.h"
10 #include "mozilla/PresShellInlines.h"
11 #include "mozilla/dom/BindContext.h"
12 #include "mozilla/dom/Element.h"
13 #include "mozilla/dom/EventTarget.h"
14 #include "mozilla/mozalloc.h"
15 #include "nsAString.h"
16 #include "nsCOMPtr.h"
17 #include "nsComputedDOMStyle.h"
18 #include "nsDebug.h"
19 #include "nsError.h"
20 #include "nsGenericHTMLElement.h"
21 #include "nsGkAtoms.h"
22 #include "nsAtom.h"
23 #include "nsIContent.h"
24 #include "nsID.h"
25 #include "mozilla/dom/Document.h"
26 #include "nsIDocumentObserver.h"
27 #include "nsStubMutationObserver.h"
28 #include "nsINode.h"
29 #include "nsISupportsImpl.h"
30 #include "nsISupportsUtils.h"
31 #include "nsLiteralString.h"
32 #include "nsPresContext.h"
33 #include "nsReadableUtils.h"
34 #include "nsString.h"
35 #include "nsStringFwd.h"
36 #include "nsStyledElement.h"
37 #include "nsUnicharUtils.h"
38 #include "nscore.h"
39 #include "nsContentUtils.h" // for nsAutoScriptBlocker
40 #include "nsROCSSPrimitiveValue.h"
42 class nsIDOMEventListener;
44 namespace mozilla {
46 using namespace dom;
48 // Retrieve the rounded number of CSS pixels from a computed CSS property.
50 // Note that this should only be called for properties whose resolved value
51 // is CSS pixels (like width, height, left, top, right, bottom, margin, padding,
52 // border-*-width, ...).
54 // See: https://drafts.csswg.org/cssom/#resolved-values
55 static int32_t GetCSSFloatValue(nsComputedDOMStyle* aComputedStyle,
56 const nsACString& aProperty) {
57 MOZ_ASSERT(aComputedStyle);
59 // get the computed CSSValue of the property
60 nsAutoCString value;
61 nsresult rv = aComputedStyle->GetPropertyValue(aProperty, value);
62 if (NS_FAILED(rv)) {
63 NS_WARNING("nsComputedDOMStyle::GetPropertyValue() failed");
64 return 0;
67 // We only care about resolved values, not a big deal if the element is
68 // undisplayed, for example, and the value is "auto" or what not.
69 int32_t val = value.ToInteger(&rv);
70 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "nsAString::ToInteger() failed");
71 return NS_SUCCEEDED(rv) ? val : 0;
74 class ElementDeletionObserver final : public nsStubMutationObserver {
75 public:
76 ElementDeletionObserver(nsIContent* aNativeAnonNode,
77 Element* aObservedElement)
78 : mNativeAnonNode(aNativeAnonNode), mObservedElement(aObservedElement) {}
80 NS_DECL_ISUPPORTS
81 NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED
82 NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
84 protected:
85 ~ElementDeletionObserver() = default;
86 nsIContent* mNativeAnonNode;
87 Element* mObservedElement;
90 NS_IMPL_ISUPPORTS(ElementDeletionObserver, nsIMutationObserver)
92 void ElementDeletionObserver::ParentChainChanged(nsIContent* aContent) {
93 // If the native anonymous content has been unbound already in
94 // DeleteRefToAnonymousNode, mNativeAnonNode's parentNode is null.
95 if (aContent != mObservedElement || !mNativeAnonNode ||
96 mNativeAnonNode->GetParent() != aContent) {
97 return;
100 ManualNACPtr::RemoveContentFromNACArray(mNativeAnonNode);
102 mObservedElement->RemoveMutationObserver(this);
103 mObservedElement = nullptr;
104 mNativeAnonNode->RemoveMutationObserver(this);
105 mNativeAnonNode = nullptr;
106 NS_RELEASE_THIS();
109 void ElementDeletionObserver::NodeWillBeDestroyed(const nsINode* aNode) {
110 NS_ASSERTION(aNode == mNativeAnonNode || aNode == mObservedElement,
111 "Wrong aNode!");
112 if (aNode == mNativeAnonNode) {
113 mObservedElement->RemoveMutationObserver(this);
114 mObservedElement = nullptr;
115 } else {
116 mNativeAnonNode->RemoveMutationObserver(this);
117 mNativeAnonNode->UnbindFromTree();
118 mNativeAnonNode = nullptr;
121 NS_RELEASE_THIS();
124 ManualNACPtr HTMLEditor::CreateAnonymousElement(nsAtom* aTag,
125 nsIContent& aParentContent,
126 const nsAString& aAnonClass,
127 bool aIsCreatedHidden) {
128 // Don't put anonymous editor element into non-HTML element.
129 // It is mainly for avoiding other anonymous element being inserted
130 // into <svg:use>, but in general we probably don't want to insert
131 // some random HTML anonymous element into a non-HTML element.
132 if (!aParentContent.IsHTMLElement()) {
133 return nullptr;
136 if (NS_WARN_IF(!GetDocument())) {
137 return nullptr;
140 RefPtr<PresShell> presShell = GetPresShell();
141 if (NS_WARN_IF(!presShell)) {
142 return nullptr;
145 // Create a new node through the element factory
146 RefPtr<Element> newElement = CreateHTMLContent(aTag);
147 if (!newElement) {
148 NS_WARNING("EditorBase::CreateHTMLContent() failed");
149 return nullptr;
152 // add the "hidden" class if needed
153 if (aIsCreatedHidden) {
154 nsresult rv = newElement->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
155 u"hidden"_ns, true);
156 if (NS_FAILED(rv)) {
157 NS_WARNING("Element::SetAttr(nsGkAtoms::_class, hidden) failed");
158 return nullptr;
162 // add an _moz_anonclass attribute if needed
163 if (!aAnonClass.IsEmpty()) {
164 nsresult rv = newElement->SetAttr(
165 kNameSpaceID_None, nsGkAtoms::_moz_anonclass, aAnonClass, true);
166 if (NS_FAILED(rv)) {
167 NS_WARNING("Element::SetAttr(nsGkAtoms::_moz_anonclass) failed");
168 return nullptr;
173 nsAutoScriptBlocker scriptBlocker;
175 // establish parenthood of the element
176 newElement->SetIsNativeAnonymousRoot();
177 BindContext context(*aParentContent.AsElement(),
178 BindContext::ForNativeAnonymous);
179 nsresult rv = newElement->BindToTree(context, aParentContent);
180 if (NS_FAILED(rv)) {
181 NS_WARNING("Element::BindToTree(BindContext::ForNativeAnonymous) failed");
182 newElement->UnbindFromTree();
183 return nullptr;
187 ManualNACPtr newNativeAnonymousContent(newElement.forget());
189 // Must style the new element, otherwise the PostRecreateFramesFor call
190 // below will do nothing.
191 ServoStyleSet* styleSet = presShell->StyleSet();
192 // Sometimes editor likes to append anonymous content to elements
193 // in display:none subtrees, so avoid styling in those cases.
194 if (ServoStyleSet::MayTraverseFrom(newNativeAnonymousContent)) {
195 styleSet->StyleNewSubtree(newNativeAnonymousContent);
198 auto* observer = new ElementDeletionObserver(newNativeAnonymousContent,
199 aParentContent.AsElement());
200 NS_ADDREF(observer); // NodeWillBeDestroyed releases.
201 aParentContent.AddMutationObserver(observer);
202 newNativeAnonymousContent->AddMutationObserver(observer);
204 #ifdef DEBUG
205 // Editor anonymous content gets passed to PostRecreateFramesFor... which
206 // can't _really_ deal with anonymous content (because it can't get the frame
207 // tree ordering right). But for us the ordering doesn't matter so this is
208 // sort of ok.
209 newNativeAnonymousContent->SetProperty(nsGkAtoms::restylableAnonymousNode,
210 reinterpret_cast<void*>(true));
211 #endif // DEBUG
213 // display the element
214 presShell->PostRecreateFramesFor(newNativeAnonymousContent);
216 return newNativeAnonymousContent;
219 // Removes event listener and calls DeleteRefToAnonymousNode.
220 void HTMLEditor::RemoveListenerAndDeleteRef(const nsAString& aEvent,
221 nsIDOMEventListener* aListener,
222 bool aUseCapture,
223 ManualNACPtr aElement,
224 PresShell* aPresShell) {
225 if (aElement) {
226 aElement->RemoveEventListener(aEvent, aListener, aUseCapture);
228 DeleteRefToAnonymousNode(std::move(aElement), aPresShell);
231 // Deletes all references to an anonymous element
232 void HTMLEditor::DeleteRefToAnonymousNode(ManualNACPtr aContent,
233 PresShell* aPresShell) {
234 // call ContentRemoved() for the anonymous content
235 // node so its references get removed from the frame manager's
236 // undisplay map, and its layout frames get destroyed!
238 if (NS_WARN_IF(!aContent)) {
239 return;
242 if (NS_WARN_IF(!aContent->GetParent())) {
243 // aContent was already removed?
244 return;
247 nsAutoScriptBlocker scriptBlocker;
248 // Need to check whether aPresShell has been destroyed (but not yet deleted).
249 // See bug 338129.
250 if (aContent->IsInComposedDoc() && aPresShell &&
251 !aPresShell->IsDestroying()) {
252 MOZ_ASSERT(aContent->IsRootOfNativeAnonymousSubtree());
253 MOZ_ASSERT(!aContent->GetPreviousSibling(), "NAC has no siblings");
255 // FIXME(emilio): This is the only caller to PresShell::ContentRemoved that
256 // passes NAC into it. This is not great!
257 aPresShell->ContentRemoved(aContent, nullptr);
260 // The ManualNACPtr destructor will invoke UnbindFromTree.
263 void HTMLEditor::HideAnonymousEditingUIs() {
264 if (mAbsolutelyPositionedObject) {
265 HideGrabberInternal();
266 NS_ASSERTION(!mAbsolutelyPositionedObject,
267 "HTMLEditor::HideGrabberInternal() failed, but ignored");
269 if (mInlineEditedCell) {
270 HideInlineTableEditingUIInternal();
271 NS_ASSERTION(
272 !mInlineEditedCell,
273 "HTMLEditor::HideInlineTableEditingUIInternal() failed, but ignored");
275 if (mResizedObject) {
276 DebugOnly<nsresult> rvIgnored = HideResizersInternal();
277 NS_WARNING_ASSERTION(
278 NS_SUCCEEDED(rvIgnored),
279 "HTMLEditor::HideResizersInternal() failed, but ignored");
280 NS_ASSERTION(!mResizedObject,
281 "HTMLEditor::HideResizersInternal() failed, but ignored");
285 void HTMLEditor::HideAnonymousEditingUIsIfUnnecessary() {
286 // XXX Perhaps, this is wrong approach to hide multiple UIs because
287 // hiding one UI may causes overwriting existing UI with newly
288 // created one. In such case, we will leak ovewritten UI.
289 if (!IsAbsolutePositionEditorEnabled() && mAbsolutelyPositionedObject) {
290 // XXX If we're moving something, we need to cancel or commit the
291 // operation now.
292 HideGrabberInternal();
293 NS_ASSERTION(!mAbsolutelyPositionedObject,
294 "HTMLEditor::HideGrabberInternal() failed, but ignored");
296 if (!IsInlineTableEditorEnabled() && mInlineEditedCell) {
297 // XXX If we're resizing a table element, we need to cancel or commit the
298 // operation now.
299 HideInlineTableEditingUIInternal();
300 NS_ASSERTION(
301 !mInlineEditedCell,
302 "HTMLEditor::HideInlineTableEditingUIInternal() failed, but ignored");
304 if (!IsObjectResizerEnabled() && mResizedObject) {
305 // XXX If we're resizing something, we need to cancel or commit the
306 // operation now.
307 DebugOnly<nsresult> rvIgnored = HideResizersInternal();
308 NS_WARNING_ASSERTION(
309 NS_SUCCEEDED(rvIgnored),
310 "HTMLEditor::HideResizersInternal() failed, but ignored");
311 NS_ASSERTION(!mResizedObject,
312 "HTMLEditor::HideResizersInternal() failed, but ignored");
316 NS_IMETHODIMP HTMLEditor::CheckSelectionStateForAnonymousButtons() {
317 AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
318 if (NS_WARN_IF(!editActionData.CanHandle())) {
319 return NS_ERROR_NOT_INITIALIZED;
322 nsresult rv = RefreshEditingUI();
323 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
324 "HTMLEditor::RefereshEditingUI() failed");
325 return EditorBase::ToGenericNSResult(rv);
328 nsresult HTMLEditor::RefreshEditingUI() {
329 MOZ_ASSERT(IsEditActionDataAvailable());
331 // First, we need to remove unnecessary editing UI now since some of them
332 // may be disabled while them are visible.
333 HideAnonymousEditingUIsIfUnnecessary();
335 // early way out if all contextual UI extensions are disabled
336 if (!IsObjectResizerEnabled() && !IsAbsolutePositionEditorEnabled() &&
337 !IsInlineTableEditorEnabled()) {
338 return NS_OK;
341 // Don't change selection state if we're moving.
342 if (mIsMoving) {
343 return NS_OK;
346 // let's get the containing element of the selection
347 RefPtr<Element> selectionContainerElement = GetSelectionContainerElement();
348 if (NS_WARN_IF(!selectionContainerElement)) {
349 return NS_OK;
352 // If we're not in a document, don't try to add resizers
353 if (!selectionContainerElement->IsInUncomposedDoc()) {
354 return NS_OK;
357 // what's its tag?
358 RefPtr<Element> focusElement = std::move(selectionContainerElement);
359 nsAtom* focusTagAtom = focusElement->NodeInfo()->NameAtom();
361 RefPtr<Element> absPosElement;
362 if (IsAbsolutePositionEditorEnabled()) {
363 // Absolute Positioning support is enabled, is the selection contained
364 // in an absolutely positioned element ?
365 absPosElement = GetAbsolutelyPositionedSelectionContainer();
366 if (NS_WARN_IF(Destroyed())) {
367 return NS_ERROR_EDITOR_DESTROYED;
371 RefPtr<Element> cellElement;
372 if (IsObjectResizerEnabled() || IsInlineTableEditorEnabled()) {
373 // Resizing or Inline Table Editing is enabled, we need to check if the
374 // selection is contained in a table cell
375 cellElement = GetInclusiveAncestorByTagNameAtSelection(*nsGkAtoms::td);
378 if (IsObjectResizerEnabled() && cellElement) {
379 // we are here because Resizing is enabled AND selection is contained in
380 // a cell
382 // get the enclosing table
383 if (nsGkAtoms::img != focusTagAtom) {
384 // the element container of the selection is not an image, so we'll show
385 // the resizers around the table
386 // XXX There may be a bug. cellElement may be not in <table> in invalid
387 // tree. So, perhaps, GetClosestAncestorTableElement() returns
388 // nullptr, we should not set focusTagAtom to nsGkAtoms::table.
389 focusElement =
390 HTMLEditUtils::GetClosestAncestorTableElement(*cellElement);
391 focusTagAtom = nsGkAtoms::table;
395 // we allow resizers only around images, tables, and absolutely positioned
396 // elements. If we don't have image/table, let's look at the latter case.
397 if (nsGkAtoms::img != focusTagAtom && nsGkAtoms::table != focusTagAtom) {
398 focusElement = absPosElement;
401 // at this point, focusElement contains the element for Resizing,
402 // cellElement contains the element for InlineTableEditing
403 // absPosElement contains the element for Positioning
405 // Note: All the Hide/Show methods below may change attributes on real
406 // content which means a DOMAttrModified handler may cause arbitrary
407 // side effects while this code runs (bug 420439).
409 if (IsAbsolutePositionEditorEnabled() && mAbsolutelyPositionedObject &&
410 absPosElement != mAbsolutelyPositionedObject) {
411 HideGrabberInternal();
412 NS_ASSERTION(!mAbsolutelyPositionedObject,
413 "HTMLEditor::HideGrabberInternal() failed, but ignored");
416 if (IsObjectResizerEnabled() && mResizedObject &&
417 mResizedObject != focusElement) {
418 // Perhaps, even if HideResizersInternal() failed, we should try to hide
419 // inline table editing UI. However, it returns error only when we cannot
420 // do anything. So, it's okay for now.
421 nsresult rv = HideResizersInternal();
422 if (NS_FAILED(rv)) {
423 NS_WARNING("HTMLEditor::HideResizersInternal() failed");
424 return rv;
426 NS_ASSERTION(!mResizedObject,
427 "HTMLEditor::HideResizersInternal() failed, but ignored");
430 if (IsInlineTableEditorEnabled() && mInlineEditedCell &&
431 mInlineEditedCell != cellElement) {
432 HideInlineTableEditingUIInternal();
433 NS_ASSERTION(
434 !mInlineEditedCell,
435 "HTMLEditor::HideInlineTableEditingUIInternal failed, but ignored");
438 // now, let's display all contextual UI for good
439 nsIContent* hostContent = ComputeEditingHost();
441 if (IsObjectResizerEnabled() && focusElement &&
442 HTMLEditUtils::IsSimplyEditableNode(*focusElement) &&
443 focusElement != hostContent) {
444 if (nsGkAtoms::img == focusTagAtom) {
445 mResizedObjectIsAnImage = true;
447 if (mResizedObject) {
448 nsresult rv = RefreshResizersInternal();
449 if (NS_FAILED(rv)) {
450 NS_WARNING("HTMLEditor::RefreshResizersInternal() failed");
451 return rv;
453 } else {
454 nsresult rv = ShowResizersInternal(*focusElement);
455 if (NS_FAILED(rv)) {
456 NS_WARNING("HTMLEditor::ShowResizersInternal() failed");
457 return rv;
462 if (IsAbsolutePositionEditorEnabled() && absPosElement &&
463 HTMLEditUtils::IsSimplyEditableNode(*absPosElement) &&
464 absPosElement != hostContent) {
465 if (mAbsolutelyPositionedObject) {
466 nsresult rv = RefreshGrabberInternal();
467 if (NS_FAILED(rv)) {
468 NS_WARNING("HTMLEditor::RefreshGrabberInternal() failed");
469 return rv;
471 } else {
472 nsresult rv = ShowGrabberInternal(*absPosElement);
473 if (NS_FAILED(rv)) {
474 NS_WARNING("HTMLEditor::ShowGrabberInternal() failed");
475 return rv;
480 // XXX Shouldn't we check whether the `<table>` element is editable or not?
481 if (IsInlineTableEditorEnabled() && cellElement &&
482 HTMLEditUtils::IsSimplyEditableNode(*cellElement) &&
483 cellElement != hostContent) {
484 if (mInlineEditedCell) {
485 nsresult rv = RefreshInlineTableEditingUIInternal();
486 if (NS_FAILED(rv)) {
487 NS_WARNING("HTMLEditor::RefreshInlineTableEditingUIInternal() failed");
488 return rv;
490 } else {
491 nsresult rv = ShowInlineTableEditingUIInternal(*cellElement);
492 if (NS_FAILED(rv)) {
493 NS_WARNING("HTMLEditor::ShowInlineTableEditingUIInternal() failed");
494 return rv;
499 return NS_OK;
502 // Resizing and Absolute Positioning need to know everything about the
503 // containing box of the element: position, size, margins, borders
504 nsresult HTMLEditor::GetPositionAndDimensions(Element& aElement, int32_t& aX,
505 int32_t& aY, int32_t& aW,
506 int32_t& aH, int32_t& aBorderLeft,
507 int32_t& aBorderTop,
508 int32_t& aMarginLeft,
509 int32_t& aMarginTop) {
510 // Is the element positioned ? let's check the cheap way first...
511 bool isPositioned =
512 aElement.HasAttr(kNameSpaceID_None, nsGkAtoms::_moz_abspos);
513 if (!isPositioned) {
514 // hmmm... the expensive way now...
515 nsAutoString positionValue;
516 DebugOnly<nsresult> rvIgnored = CSSEditUtils::GetComputedProperty(
517 aElement, *nsGkAtoms::position, positionValue);
518 if (NS_WARN_IF(Destroyed())) {
519 return NS_ERROR_EDITOR_DESTROYED;
521 NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
522 "CSSEditUtils::GetComputedProperty(nsGkAtoms::"
523 "position) failed, but ignored");
524 isPositioned = positionValue.EqualsLiteral("absolute");
527 if (isPositioned) {
528 // Yes, it is absolutely positioned
529 mResizedObjectIsAbsolutelyPositioned = true;
531 // Get the all the computed css styles attached to the element node
532 RefPtr<nsComputedDOMStyle> computedDOMStyle =
533 CSSEditUtils::GetComputedStyle(&aElement);
534 if (NS_WARN_IF(!computedDOMStyle)) {
535 return NS_ERROR_FAILURE;
538 aBorderLeft = GetCSSFloatValue(computedDOMStyle, "border-left-width"_ns);
539 aBorderTop = GetCSSFloatValue(computedDOMStyle, "border-top-width"_ns);
540 aMarginLeft = GetCSSFloatValue(computedDOMStyle, "margin-left"_ns);
541 aMarginTop = GetCSSFloatValue(computedDOMStyle, "margin-top"_ns);
543 aX = GetCSSFloatValue(computedDOMStyle, "left"_ns) + aMarginLeft +
544 aBorderLeft;
545 aY = GetCSSFloatValue(computedDOMStyle, "top"_ns) + aMarginTop + aBorderTop;
546 aW = GetCSSFloatValue(computedDOMStyle, "width"_ns);
547 aH = GetCSSFloatValue(computedDOMStyle, "height"_ns);
548 } else {
549 mResizedObjectIsAbsolutelyPositioned = false;
550 RefPtr<nsGenericHTMLElement> htmlElement =
551 nsGenericHTMLElement::FromNode(aElement);
552 if (!htmlElement) {
553 return NS_ERROR_NULL_POINTER;
555 DebugOnly<nsresult> rvIgnored = GetElementOrigin(aElement, aX, aY);
556 NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
557 "HTMLEditor::GetElementOrigin() failed, but ignored");
559 aW = htmlElement->OffsetWidth();
560 aH = htmlElement->OffsetHeight();
562 aBorderLeft = 0;
563 aBorderTop = 0;
564 aMarginLeft = 0;
565 aMarginTop = 0;
567 return NS_OK;
570 nsresult HTMLEditor::SetAnonymousElementPositionWithoutTransaction(
571 nsStyledElement& aStyledElement, int32_t aX, int32_t aY) {
572 nsresult rv;
573 rv = mCSSEditUtils->SetCSSPropertyPixelsWithoutTransaction(
574 aStyledElement, *nsGkAtoms::left, aX);
575 if (rv == NS_ERROR_EDITOR_DESTROYED) {
576 NS_WARNING(
577 "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(nsGkAtoms::left) "
578 "destroyed the editor");
579 return NS_ERROR_EDITOR_DESTROYED;
581 NS_WARNING_ASSERTION(
582 NS_SUCCEEDED(rv),
583 "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(nsGkAtoms::left) "
584 "failed, but ignored");
585 rv = mCSSEditUtils->SetCSSPropertyPixelsWithoutTransaction(
586 aStyledElement, *nsGkAtoms::top, aY);
587 if (rv == NS_ERROR_EDITOR_DESTROYED) {
588 NS_WARNING(
589 "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(nsGkAtoms::top) "
590 "destroyed the editor");
591 return NS_ERROR_EDITOR_DESTROYED;
593 NS_WARNING_ASSERTION(
594 NS_SUCCEEDED(rv),
595 "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(nsGkAtoms::top) "
596 "failed, but ignored");
597 return NS_OK;
600 } // namespace mozilla