Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/editor/libeditor/HTMLAnonymousNodeEditor.cpp
Line
Count
Source (jump to first uncovered line)
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/. */
4
5
#include "mozilla/HTMLEditor.h"
6
7
#include "mozilla/Attributes.h"
8
#include "mozilla/dom/Element.h"
9
#include "mozilla/dom/EventTarget.h"
10
#include "mozilla/mozalloc.h"
11
#include "nsAString.h"
12
#include "nsCOMPtr.h"
13
#include "nsComputedDOMStyle.h"
14
#include "nsDebug.h"
15
#include "nsError.h"
16
#include "nsGenericHTMLElement.h"
17
#include "nsGkAtoms.h"
18
#include "nsAtom.h"
19
#include "nsIContent.h"
20
#include "nsID.h"
21
#include "nsIDOMWindow.h"
22
#include "nsIDocument.h"
23
#include "nsIDocumentObserver.h"
24
#include "nsIHTMLAbsPosEditor.h"
25
#include "nsIHTMLInlineTableEditor.h"
26
#include "nsIHTMLObjectResizer.h"
27
#include "nsStubMutationObserver.h"
28
#include "nsINode.h"
29
#include "nsIPresShell.h"
30
#include "nsISupportsImpl.h"
31
#include "nsISupportsUtils.h"
32
#include "nsLiteralString.h"
33
#include "nsPresContext.h"
34
#include "nsReadableUtils.h"
35
#include "nsString.h"
36
#include "nsStringFwd.h"
37
#include "nsUnicharUtils.h"
38
#include "nscore.h"
39
#include "nsContentUtils.h" // for nsAutoScriptBlocker
40
#include "nsROCSSPrimitiveValue.h"
41
42
class nsIDOMEventListener;
43
44
namespace mozilla {
45
46
using namespace dom;
47
48
// Retrieve the rounded number of CSS pixels from a computed CSS property.
49
//
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, ...).
53
//
54
// See: https://drafts.csswg.org/cssom/#resolved-values
55
static int32_t
56
GetCSSFloatValue(nsComputedDOMStyle* aComputedStyle,
57
                 const nsAString& aProperty)
58
0
{
59
0
  MOZ_ASSERT(aComputedStyle);
60
0
61
0
  // get the computed CSSValue of the property
62
0
  nsAutoString value;
63
0
  nsresult rv = aComputedStyle->GetPropertyValue(aProperty, value);
64
0
  if (NS_FAILED(rv)) {
65
0
    return 0;
66
0
  }
67
0
68
0
  // We only care about resolved values, not a big deal if the element is
69
0
  // undisplayed, for example, and the value is "auto" or what not.
70
0
  int32_t val = value.ToInteger(&rv);
71
0
  return NS_SUCCEEDED(rv) ? val : 0;
72
0
}
73
74
class ElementDeletionObserver final : public nsStubMutationObserver
75
{
76
public:
77
  ElementDeletionObserver(nsIContent* aNativeAnonNode,
78
                          nsIContent* aObservedNode)
79
    : mNativeAnonNode(aNativeAnonNode)
80
    , mObservedNode(aObservedNode)
81
0
  {}
82
83
  NS_DECL_ISUPPORTS
84
  NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED
85
  NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
86
87
protected:
88
0
  ~ElementDeletionObserver() {}
89
  nsIContent* mNativeAnonNode;
90
  nsIContent* mObservedNode;
91
};
92
93
NS_IMPL_ISUPPORTS(ElementDeletionObserver, nsIMutationObserver)
94
95
void
96
ElementDeletionObserver::ParentChainChanged(nsIContent* aContent)
97
0
{
98
0
  // If the native anonymous content has been unbound already in
99
0
  // DeleteRefToAnonymousNode, mNativeAnonNode's parentNode is null.
100
0
  if (aContent == mObservedNode && mNativeAnonNode &&
101
0
      mNativeAnonNode->GetParentNode() == aContent) {
102
0
    // If the observed node has been moved to another document, there isn't much
103
0
    // we can do easily. But at least be safe and unbind the native anonymous
104
0
    // content and stop observing changes.
105
0
    if (mNativeAnonNode->OwnerDoc() != mObservedNode->OwnerDoc()) {
106
0
      mObservedNode->RemoveMutationObserver(this);
107
0
      mObservedNode = nullptr;
108
0
      mNativeAnonNode->RemoveMutationObserver(this);
109
0
      mNativeAnonNode->UnbindFromTree();
110
0
      mNativeAnonNode = nullptr;
111
0
      NS_RELEASE_THIS();
112
0
      return;
113
0
    }
114
0
115
0
    // We're staying in the same document, just rebind the native anonymous
116
0
    // node so that the subtree root points to the right object etc.
117
0
    mNativeAnonNode->UnbindFromTree();
118
0
    mNativeAnonNode->BindToTree(mObservedNode->GetUncomposedDoc(),
119
0
                                mObservedNode,
120
0
                                mObservedNode);
121
0
  }
122
0
}
123
124
void
125
ElementDeletionObserver::NodeWillBeDestroyed(const nsINode* aNode)
126
0
{
127
0
  NS_ASSERTION(aNode == mNativeAnonNode || aNode == mObservedNode,
128
0
               "Wrong aNode!");
129
0
  if (aNode == mNativeAnonNode) {
130
0
    mObservedNode->RemoveMutationObserver(this);
131
0
    mObservedNode = nullptr;
132
0
  } else {
133
0
    mNativeAnonNode->RemoveMutationObserver(this);
134
0
    mNativeAnonNode->UnbindFromTree();
135
0
    mNativeAnonNode = nullptr;
136
0
  }
137
0
138
0
  NS_RELEASE_THIS();
139
0
}
140
141
ManualNACPtr
142
HTMLEditor::CreateAnonymousElement(nsAtom* aTag,
143
                                   nsIContent& aParentContent,
144
                                   const nsAString& aAnonClass,
145
                                   bool aIsCreatedHidden)
146
0
{
147
0
  // Don't put anonymous editor element into non-HTML element.
148
0
  // It is mainly for avoiding other anonymous element being inserted
149
0
  // into <svg:use>, but in general we probably don't want to insert
150
0
  // some random HTML anonymous element into a non-HTML element.
151
0
  if (!aParentContent.IsHTMLElement()) {
152
0
    return nullptr;
153
0
  }
154
0
155
0
  nsCOMPtr<nsIDocument> doc = GetDocument();
156
0
  if (NS_WARN_IF(!doc)) {
157
0
    return nullptr;
158
0
  }
159
0
160
0
  // Get the pres shell
161
0
  nsCOMPtr<nsIPresShell> ps = GetPresShell();
162
0
  if (NS_WARN_IF(!ps)) {
163
0
    return nullptr;
164
0
  }
165
0
166
0
  // Create a new node through the element factory
167
0
  RefPtr<Element> newContentRaw = CreateHTMLContent(aTag);
168
0
  if (NS_WARN_IF(!newContentRaw)) {
169
0
    return nullptr;
170
0
  }
171
0
172
0
  // add the "hidden" class if needed
173
0
  if (aIsCreatedHidden) {
174
0
    nsresult rv =
175
0
      newContentRaw->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
176
0
                             NS_LITERAL_STRING("hidden"), true);
177
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
178
0
      return nullptr;
179
0
    }
180
0
  }
181
0
182
0
  // add an _moz_anonclass attribute if needed
183
0
  if (!aAnonClass.IsEmpty()) {
184
0
    nsresult rv =
185
0
      newContentRaw->SetAttr(kNameSpaceID_None, nsGkAtoms::_moz_anonclass,
186
0
                             aAnonClass, true);
187
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
188
0
      return nullptr;
189
0
    }
190
0
  }
191
0
192
0
  {
193
0
    nsAutoScriptBlocker scriptBlocker;
194
0
195
0
    // establish parenthood of the element
196
0
    newContentRaw->SetIsNativeAnonymousRoot();
197
0
    nsresult rv =
198
0
      newContentRaw->BindToTree(doc, &aParentContent, &aParentContent);
199
0
    if (NS_FAILED(rv)) {
200
0
      newContentRaw->UnbindFromTree();
201
0
      return nullptr;
202
0
    }
203
0
  }
204
0
205
0
  ManualNACPtr newContent(newContentRaw.forget());
206
0
207
0
  // Must style the new element, otherwise the PostRecreateFramesFor call
208
0
  // below will do nothing.
209
0
  ServoStyleSet* styleSet = ps->StyleSet();
210
0
  // Sometimes editor likes to append anonymous content to elements
211
0
  // in display:none subtrees, so avoid styling in those cases.
212
0
  if (ServoStyleSet::MayTraverseFrom(newContent)) {
213
0
    styleSet->StyleNewSubtree(newContent);
214
0
  }
215
0
216
0
  ElementDeletionObserver* observer =
217
0
    new ElementDeletionObserver(newContent, &aParentContent);
218
0
  NS_ADDREF(observer); // NodeWillBeDestroyed releases.
219
0
  aParentContent.AddMutationObserver(observer);
220
0
  newContent->AddMutationObserver(observer);
221
0
222
#ifdef DEBUG
223
  // Editor anonymous content gets passed to PostRecreateFramesFor... which
224
  // can't _really_ deal with anonymous content (because it can't get the frame
225
  // tree ordering right).  But for us the ordering doesn't matter so this is
226
  // sort of ok.
227
  newContent->SetProperty(nsGkAtoms::restylableAnonymousNode,
228
        reinterpret_cast<void*>(true));
229
#endif // DEBUG
230
231
0
  // display the element
232
0
  ps->PostRecreateFramesFor(newContent);
233
0
234
0
  return newContent;
235
0
}
236
237
// Removes event listener and calls DeleteRefToAnonymousNode.
238
void
239
HTMLEditor::RemoveListenerAndDeleteRef(const nsAString& aEvent,
240
                                       nsIDOMEventListener* aListener,
241
                                       bool aUseCapture,
242
                                       ManualNACPtr aElement,
243
                                       nsIPresShell* aShell)
244
0
{
245
0
  if (aElement) {
246
0
    aElement->RemoveEventListener(aEvent, aListener, aUseCapture);
247
0
  }
248
0
  DeleteRefToAnonymousNode(std::move(aElement), aShell);
249
0
}
250
251
// Deletes all references to an anonymous element
252
void
253
HTMLEditor::DeleteRefToAnonymousNode(ManualNACPtr aContent,
254
                                     nsIPresShell* aShell)
255
0
{
256
0
  // call ContentRemoved() for the anonymous content
257
0
  // node so its references get removed from the frame manager's
258
0
  // undisplay map, and its layout frames get destroyed!
259
0
260
0
  if (NS_WARN_IF(!aContent)) {
261
0
    return;
262
0
  }
263
0
264
0
  nsIContent* parentContent = aContent->GetParent();
265
0
  if (NS_WARN_IF(!parentContent)) {
266
0
    // aContent was already removed?
267
0
    return;
268
0
  }
269
0
270
0
  nsAutoScriptBlocker scriptBlocker;
271
0
  // Need to check whether aShell has been destroyed (but not yet deleted).
272
0
  // See bug 338129.
273
0
  if (aContent->IsInComposedDoc() && aShell && !aShell->IsDestroying()) {
274
0
    MOZ_ASSERT(aContent->IsRootOfAnonymousSubtree());
275
0
    MOZ_ASSERT(!aContent->GetPreviousSibling(), "NAC has no siblings");
276
0
277
0
    // FIXME(emilio): This is the only caller to PresShell::ContentRemoved that
278
0
    // passes NAC into it. This is not great!
279
0
    aShell->ContentRemoved(aContent, nullptr);
280
0
  }
281
0
282
0
  // The ManualNACPtr destructor will invoke UnbindFromTree.
283
0
}
284
285
void
286
HTMLEditor::HideAnonymousEditingUIs()
287
0
{
288
0
  if (mAbsolutelyPositionedObject) {
289
0
    HideGrabberInternal();
290
0
    NS_ASSERTION(!mAbsolutelyPositionedObject, "HideGrabber failed");
291
0
  }
292
0
  if (mInlineEditedCell) {
293
0
    HideInlineTableEditingUIInternal();
294
0
    NS_ASSERTION(!mInlineEditedCell, "HideInlineTableEditingUIInternal failed");
295
0
  }
296
0
  if (mResizedObject) {
297
0
    DebugOnly<nsresult> rv = HideResizersInternal();
298
0
    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "HideResizersInternal() failed");
299
0
    NS_ASSERTION(!mResizedObject, "HideResizersInternal() failed");
300
0
  }
301
0
}
302
303
void
304
HTMLEditor::HideAnonymousEditingUIsIfUnnecessary()
305
0
{
306
0
  // XXX Perhaps, this is wrong approach to hide multiple UIs because
307
0
  //     hiding one UI may causes overwriting existing UI with newly
308
0
  //     created one.  In such case, we will leak ovewritten UI.
309
0
  if (!IsAbsolutePositionEditorEnabled() && mAbsolutelyPositionedObject) {
310
0
    // XXX If we're moving something, we need to cancel or commit the
311
0
    //     operation now.
312
0
    HideGrabberInternal();
313
0
    NS_ASSERTION(!mAbsolutelyPositionedObject, "HideGrabber failed");
314
0
  }
315
0
  if (!IsInlineTableEditorEnabled() && mInlineEditedCell) {
316
0
    // XXX If we're resizing a table element, we need to cancel or commit the
317
0
    //     operation now.
318
0
    HideInlineTableEditingUIInternal();
319
0
    NS_ASSERTION(!mInlineEditedCell, "HideInlineTableEditingUIInternal failed");
320
0
  }
321
0
  if (!IsObjectResizerEnabled() && mResizedObject) {
322
0
    // XXX If we're resizing something, we need to cancel or commit the
323
0
    //     operation now.
324
0
    DebugOnly<nsresult> rv = HideResizersInternal();
325
0
    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "HideResizersInternal() failed");
326
0
    NS_ASSERTION(!mResizedObject, "HideResizersInternal() failed");
327
0
  }
328
0
}
329
330
NS_IMETHODIMP
331
HTMLEditor::CheckSelectionStateForAnonymousButtons(Selection* aSelection)
332
0
{
333
0
  if (NS_WARN_IF(!aSelection)) {
334
0
    return NS_ERROR_INVALID_ARG;
335
0
  }
336
0
  nsresult rv = RefereshEditingUI(*aSelection);
337
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
338
0
    return rv;
339
0
  }
340
0
  return NS_OK;
341
0
}
342
343
nsresult
344
HTMLEditor::RefereshEditingUI(Selection& aSelection)
345
0
{
346
0
  // First, we need to remove unnecessary editing UI now since some of them
347
0
  // may be disabled while them are visible.
348
0
  HideAnonymousEditingUIsIfUnnecessary();
349
0
350
0
  // early way out if all contextual UI extensions are disabled
351
0
  if (!IsObjectResizerEnabled() &&
352
0
      !IsAbsolutePositionEditorEnabled() &&
353
0
      !IsInlineTableEditorEnabled()) {
354
0
    return NS_OK;
355
0
  }
356
0
357
0
  // Don't change selection state if we're moving.
358
0
  if (mIsMoving) {
359
0
    return NS_OK;
360
0
  }
361
0
362
0
  // let's get the containing element of the selection
363
0
  RefPtr<Element> focusElement = GetSelectionContainerElement(aSelection);
364
0
  if (NS_WARN_IF(!focusElement)) {
365
0
    return NS_OK;
366
0
  }
367
0
368
0
  // If we're not in a document, don't try to add resizers
369
0
  if (!focusElement->IsInUncomposedDoc()) {
370
0
    return NS_OK;
371
0
  }
372
0
373
0
  // what's its tag?
374
0
  nsAtom* focusTagAtom = focusElement->NodeInfo()->NameAtom();
375
0
376
0
  RefPtr<Element> absPosElement;
377
0
  if (IsAbsolutePositionEditorEnabled()) {
378
0
    // Absolute Positioning support is enabled, is the selection contained
379
0
    // in an absolutely positioned element ?
380
0
    absPosElement = GetAbsolutelyPositionedSelectionContainer();
381
0
  }
382
0
383
0
  RefPtr<Element> cellElement;
384
0
  if (IsObjectResizerEnabled() || IsInlineTableEditorEnabled()) {
385
0
    // Resizing or Inline Table Editing is enabled, we need to check if the
386
0
    // selection is contained in a table cell
387
0
    cellElement =
388
0
      GetElementOrParentByTagNameAtSelection(aSelection, *nsGkAtoms::td);
389
0
  }
390
0
391
0
  if (IsObjectResizerEnabled() && cellElement) {
392
0
    // we are here because Resizing is enabled AND selection is contained in
393
0
    // a cell
394
0
395
0
    // get the enclosing table
396
0
    if (nsGkAtoms::img != focusTagAtom) {
397
0
      // the element container of the selection is not an image, so we'll show
398
0
      // the resizers around the table
399
0
      // XXX There may be a bug.  cellElement may be not in <table> in invalid
400
0
      //     tree.  So, perhaps, GetEnclosingTable() returns nullptr, we should
401
0
      //     not set focusTagAtom to nsGkAtoms::table.
402
0
      focusElement = GetEnclosingTable(cellElement);
403
0
      focusTagAtom = nsGkAtoms::table;
404
0
    }
405
0
  }
406
0
407
0
  // we allow resizers only around images, tables, and absolutely positioned
408
0
  // elements. If we don't have image/table, let's look at the latter case.
409
0
  if (nsGkAtoms::img != focusTagAtom && nsGkAtoms::table != focusTagAtom) {
410
0
    focusElement = absPosElement;
411
0
  }
412
0
413
0
  // at this point, focusElement  contains the element for Resizing,
414
0
  //                cellElement   contains the element for InlineTableEditing
415
0
  //                absPosElement contains the element for Positioning
416
0
417
0
  // Note: All the Hide/Show methods below may change attributes on real
418
0
  // content which means a DOMAttrModified handler may cause arbitrary
419
0
  // side effects while this code runs (bug 420439).
420
0
421
0
  if (IsAbsolutePositionEditorEnabled() && mAbsolutelyPositionedObject &&
422
0
      absPosElement != mAbsolutelyPositionedObject) {
423
0
    HideGrabberInternal();
424
0
    NS_ASSERTION(!mAbsolutelyPositionedObject, "HideGrabber failed");
425
0
  }
426
0
427
0
  if (IsObjectResizerEnabled() && mResizedObject &&
428
0
      mResizedObject != focusElement) {
429
0
    // Perhaps, even if HideResizersInternal() failed, we should try to hide
430
0
    // inline table editing UI.  However, it returns error only when we cannot
431
0
    // do anything.  So, it's okay for now.
432
0
    nsresult rv = HideResizersInternal();
433
0
    if (NS_WARN_IF(NS_FAILED(rv))) {
434
0
      return rv;
435
0
    }
436
0
    NS_ASSERTION(!mResizedObject, "HideResizersInternal() failed");
437
0
  }
438
0
439
0
  if (IsInlineTableEditorEnabled() && mInlineEditedCell &&
440
0
      mInlineEditedCell != cellElement) {
441
0
    HideInlineTableEditingUIInternal();
442
0
    NS_ASSERTION(!mInlineEditedCell, "HideInlineTableEditingUIInternal failed");
443
0
  }
444
0
445
0
  // now, let's display all contextual UI for good
446
0
  nsIContent* hostContent = GetActiveEditingHost();
447
0
448
0
  if (IsObjectResizerEnabled() && focusElement &&
449
0
      IsModifiableNode(*focusElement) && focusElement != hostContent) {
450
0
    if (nsGkAtoms::img == focusTagAtom) {
451
0
      mResizedObjectIsAnImage = true;
452
0
    }
453
0
    if (mResizedObject) {
454
0
      nsresult rv = RefreshResizersInternal();
455
0
      if (NS_WARN_IF(NS_FAILED(rv))) {
456
0
        return rv;
457
0
      }
458
0
    } else {
459
0
      nsresult rv = ShowResizersInternal(*focusElement);
460
0
      if (NS_WARN_IF(NS_FAILED(rv))) {
461
0
        return rv;
462
0
      }
463
0
    }
464
0
  }
465
0
466
0
  if (IsAbsolutePositionEditorEnabled() && absPosElement &&
467
0
      IsModifiableNode(*absPosElement) && absPosElement != hostContent) {
468
0
    if (mAbsolutelyPositionedObject) {
469
0
      nsresult rv = RefreshGrabberInternal();
470
0
      if (NS_WARN_IF(NS_FAILED(rv))) {
471
0
        return rv;
472
0
      }
473
0
    } else {
474
0
      nsresult rv = ShowGrabberInternal(*absPosElement);
475
0
      if (NS_WARN_IF(NS_FAILED(rv))) {
476
0
        return rv;
477
0
      }
478
0
    }
479
0
  }
480
0
481
0
  if (IsInlineTableEditorEnabled() && cellElement &&
482
0
      IsModifiableNode(*cellElement) && cellElement != hostContent) {
483
0
    if (mInlineEditedCell) {
484
0
      nsresult rv = RefreshInlineTableEditingUIInternal();
485
0
      if (NS_WARN_IF(NS_FAILED(rv))) {
486
0
        return rv;
487
0
      }
488
0
    } else {
489
0
      nsresult rv = ShowInlineTableEditingUIInternal(*cellElement);
490
0
      if (NS_WARN_IF(NS_FAILED(rv))) {
491
0
        return rv;
492
0
      }
493
0
    }
494
0
  }
495
0
496
0
  return NS_OK;
497
0
}
498
499
// Resizing and Absolute Positioning need to know everything about the
500
// containing box of the element: position, size, margins, borders
501
nsresult
502
HTMLEditor::GetPositionAndDimensions(Element& aElement,
503
                                     int32_t& aX,
504
                                     int32_t& aY,
505
                                     int32_t& aW,
506
                                     int32_t& aH,
507
                                     int32_t& aBorderLeft,
508
                                     int32_t& aBorderTop,
509
                                     int32_t& aMarginLeft,
510
                                     int32_t& aMarginTop)
511
0
{
512
0
  // Is the element positioned ? let's check the cheap way first...
513
0
  bool isPositioned =
514
0
    aElement.HasAttr(kNameSpaceID_None, nsGkAtoms::_moz_abspos);
515
0
  if (!isPositioned) {
516
0
    // hmmm... the expensive way now...
517
0
    nsAutoString positionStr;
518
0
    CSSEditUtils::GetComputedProperty(aElement, *nsGkAtoms::position,
519
0
                                       positionStr);
520
0
    isPositioned = positionStr.EqualsLiteral("absolute");
521
0
  }
522
0
523
0
  if (isPositioned) {
524
0
    // Yes, it is absolutely positioned
525
0
    mResizedObjectIsAbsolutelyPositioned = true;
526
0
527
0
    // Get the all the computed css styles attached to the element node
528
0
    RefPtr<nsComputedDOMStyle> cssDecl =
529
0
      CSSEditUtils::GetComputedStyle(&aElement);
530
0
    NS_ENSURE_STATE(cssDecl);
531
0
532
0
    aBorderLeft = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("border-left-width"));
533
0
    aBorderTop  = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("border-top-width"));
534
0
    aMarginLeft = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("margin-left"));
535
0
    aMarginTop  = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("margin-top"));
536
0
537
0
    aX = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("left")) +
538
0
         aMarginLeft + aBorderLeft;
539
0
    aY = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("top")) +
540
0
         aMarginTop + aBorderTop;
541
0
    aW = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("width"));
542
0
    aH = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("height"));
543
0
  } else {
544
0
    mResizedObjectIsAbsolutelyPositioned = false;
545
0
    RefPtr<nsGenericHTMLElement> htmlElement =
546
0
      nsGenericHTMLElement::FromNode(aElement);
547
0
    if (!htmlElement) {
548
0
      return NS_ERROR_NULL_POINTER;
549
0
    }
550
0
    GetElementOrigin(aElement, aX, aY);
551
0
552
0
    aW = htmlElement->OffsetWidth();
553
0
    aH = htmlElement->OffsetHeight();
554
0
555
0
    aBorderLeft = 0;
556
0
    aBorderTop  = 0;
557
0
    aMarginLeft = 0;
558
0
    aMarginTop = 0;
559
0
  }
560
0
  return NS_OK;
561
0
}
562
563
// self-explanatory
564
void
565
HTMLEditor::SetAnonymousElementPosition(int32_t aX,
566
                                        int32_t aY,
567
                                        Element* aElement)
568
0
{
569
0
  mCSSEditUtils->SetCSSPropertyPixels(*aElement, *nsGkAtoms::left, aX);
570
0
  mCSSEditUtils->SetCSSPropertyPixels(*aElement, *nsGkAtoms::top, aY);
571
0
}
572
573
} // namespace mozilla