tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

HTMLAbsPositionEditor.cpp (36191B)


      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 "HTMLEditor.h"
      6 
      7 #include <math.h>
      8 
      9 #include "CSSEditUtils.h"
     10 #include "EditAction.h"
     11 #include "EditorDOMAPIWrapper.h"
     12 #include "EditorLineBreak.h"
     13 #include "HTMLEditHelpers.h"
     14 #include "HTMLEditorEventListener.h"
     15 #include "HTMLEditUtils.h"
     16 
     17 #include "mozilla/EventListenerManager.h"
     18 #include "mozilla/mozalloc.h"
     19 #include "mozilla/Preferences.h"
     20 #include "mozilla/PresShell.h"
     21 #include "mozilla/StaticPrefs_editor.h"
     22 #include "mozilla/dom/AncestorIterator.h"
     23 #include "mozilla/dom/Selection.h"
     24 #include "mozilla/dom/Element.h"
     25 #include "mozilla/dom/EventTarget.h"
     26 #include "nsAString.h"
     27 #include "nsCOMPtr.h"
     28 #include "nsComputedDOMStyle.h"
     29 #include "nsDebug.h"
     30 #include "nsError.h"
     31 #include "nsGkAtoms.h"
     32 #include "nsIContent.h"
     33 #include "nsROCSSPrimitiveValue.h"
     34 #include "nsINode.h"
     35 #include "nsIPrincipal.h"
     36 #include "nsISupportsImpl.h"
     37 #include "nsISupportsUtils.h"
     38 #include "nsLiteralString.h"
     39 #include "nsReadableUtils.h"
     40 #include "nsString.h"
     41 #include "nsStringFwd.h"
     42 #include "nsStyledElement.h"
     43 #include "nscore.h"
     44 #include <algorithm>
     45 
     46 namespace mozilla {
     47 
     48 using namespace dom;
     49 
     50 nsresult HTMLEditor::SetSelectionToAbsoluteOrStaticAsAction(
     51    bool aEnabled, nsIPrincipal* aPrincipal) {
     52  AutoEditActionDataSetter editActionData(
     53      *this, EditAction::eSetPositionToAbsoluteOrStatic, aPrincipal);
     54  nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
     55  if (NS_FAILED(rv)) {
     56    NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,
     57                         "CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
     58    return rv;
     59  }
     60 
     61  const RefPtr<Element> editingHost = ComputeEditingHost();
     62  if (!editingHost) {
     63    return NS_SUCCESS_DOM_NO_OPERATION;
     64  }
     65 
     66  if (aEnabled) {
     67    Result<EditActionResult, nsresult> result =
     68        SetSelectionToAbsoluteAsSubAction(*editingHost);
     69    if (MOZ_UNLIKELY(result.isErr())) {
     70      NS_WARNING("HTMLEditor::SetSelectionToAbsoluteAsSubAction() failed");
     71      return result.unwrapErr();
     72    }
     73    return NS_OK;
     74  }
     75  Result<EditActionResult, nsresult> result = SetSelectionToStaticAsSubAction();
     76  if (MOZ_UNLIKELY(result.isErr())) {
     77    NS_WARNING("HTMLEditor::SetSelectionToStaticAsSubAction() failed");
     78    return result.unwrapErr();
     79  }
     80  return NS_OK;
     81 }
     82 
     83 already_AddRefed<Element>
     84 HTMLEditor::GetAbsolutelyPositionedSelectionContainer() const {
     85  AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
     86  if (NS_WARN_IF(!editActionData.CanHandle())) {
     87    return nullptr;
     88  }
     89 
     90  Element* selectionContainerElement = GetSelectionContainerElement();
     91  if (NS_WARN_IF(!selectionContainerElement)) {
     92    return nullptr;
     93  }
     94 
     95  AutoTArray<RefPtr<Element>, 24> arrayOfParentElements;
     96  for (Element* element :
     97       selectionContainerElement->InclusiveAncestorsOfType<Element>()) {
     98    arrayOfParentElements.AppendElement(element);
     99  }
    100 
    101  nsAutoString positionValue;
    102  for (RefPtr<Element> element = selectionContainerElement; element;
    103       element = element->GetParentElement()) {
    104    if (element->IsHTMLElement(nsGkAtoms::html)) {
    105      NS_WARNING(
    106          "HTMLEditor::GetAbsolutelyPositionedSelectionContainer() reached "
    107          "<html> element");
    108      return nullptr;
    109    }
    110    nsCOMPtr<nsINode> parentNode = element->GetParentNode();
    111    nsresult rv = CSSEditUtils::GetComputedProperty(
    112        MOZ_KnownLive(*element), *nsGkAtoms::position, positionValue);
    113    if (NS_FAILED(rv)) {
    114      NS_WARNING(
    115          "CSSEditUtils::GetComputedProperty(nsGkAtoms::position) failed");
    116      return nullptr;
    117    }
    118    if (NS_WARN_IF(Destroyed()) ||
    119        NS_WARN_IF(parentNode != element->GetParentNode())) {
    120      return nullptr;
    121    }
    122    if (positionValue.EqualsLiteral("absolute")) {
    123      return element.forget();
    124    }
    125  }
    126  return nullptr;
    127 }
    128 
    129 NS_IMETHODIMP HTMLEditor::GetAbsolutePositioningEnabled(bool* aIsEnabled) {
    130  *aIsEnabled = IsAbsolutePositionEditorEnabled();
    131  return NS_OK;
    132 }
    133 
    134 NS_IMETHODIMP HTMLEditor::SetAbsolutePositioningEnabled(bool aIsEnabled) {
    135  EnableAbsolutePositionEditor(aIsEnabled);
    136  return NS_OK;
    137 }
    138 
    139 NS_IMETHODIMP HTMLEditor::GetIsAbsolutePositioningActive(bool* aIsActive) {
    140  MOZ_ASSERT(aIsActive);
    141  *aIsActive = !!mAbsolutelyPositionedObject;
    142  return NS_OK;
    143 }
    144 
    145 Result<int32_t, nsresult> HTMLEditor::AddZIndexWithTransaction(
    146    nsStyledElement& aStyledElement, int32_t aChange) {
    147  if (!aChange) {
    148    return 0;  // XXX Why don't we return current z-index value in this case?
    149  }
    150 
    151  int32_t zIndex = GetZIndex(aStyledElement);
    152  if (NS_WARN_IF(Destroyed())) {
    153    return Err(NS_ERROR_EDITOR_DESTROYED);
    154  }
    155  zIndex = std::max(zIndex + aChange, 0);
    156  nsresult rv = SetZIndexWithTransaction(aStyledElement, zIndex);
    157  if (rv == NS_ERROR_EDITOR_DESTROYED) {
    158    NS_WARNING("HTMLEditor::SetZIndexWithTransaction() destroyed the editor");
    159    return Err(NS_ERROR_EDITOR_DESTROYED);
    160  }
    161  NS_WARNING_ASSERTION(
    162      NS_SUCCEEDED(rv),
    163      "HTMLEditor::SetZIndexWithTransaction() failed, but ignored");
    164  return zIndex;
    165 }
    166 
    167 nsresult HTMLEditor::SetZIndexWithTransaction(nsStyledElement& aStyledElement,
    168                                              int32_t aZIndex) {
    169  nsAutoString zIndexValue;
    170  zIndexValue.AppendInt(aZIndex);
    171 
    172  nsresult rv = CSSEditUtils::SetCSSPropertyWithTransaction(
    173      *this, aStyledElement, *nsGkAtoms::z_index, zIndexValue);
    174  if (rv == NS_ERROR_EDITOR_DESTROYED) {
    175    NS_WARNING(
    176        "CSSEditUtils::SetCSSPropertyWithTransaction(nsGkAtoms::z_index) "
    177        "destroyed the editor");
    178    return NS_ERROR_EDITOR_DESTROYED;
    179  }
    180  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
    181                       "CSSEditUtils::SetCSSPropertyWithTransaction(nsGkAtoms::"
    182                       "z_index) failed, but ignored");
    183  return NS_OK;
    184 }
    185 
    186 nsresult HTMLEditor::AddZIndexAsAction(int32_t aChange,
    187                                       nsIPrincipal* aPrincipal) {
    188  MOZ_ASSERT(IsEditActionDataAvailable());
    189 
    190  AutoEditActionDataSetter editActionData(
    191      *this, EditAction::eIncreaseOrDecreaseZIndex, aPrincipal);
    192  nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
    193  if (NS_FAILED(rv)) {
    194    NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,
    195                         "CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
    196    return EditorBase::ToGenericNSResult(rv);
    197  }
    198 
    199  Result<EditActionResult, nsresult> result = AddZIndexAsSubAction(aChange);
    200  if (MOZ_UNLIKELY(result.isErr())) {
    201    NS_WARNING("HTMLEditor::AddZIndexAsSubAction() failed");
    202    return EditorBase::ToGenericNSResult(result.unwrapErr());
    203  }
    204  return NS_OK;
    205 }
    206 
    207 int32_t HTMLEditor::GetZIndex(Element& aElement) {
    208  AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
    209  if (NS_WARN_IF(!editActionData.CanHandle())) {
    210    return 0;
    211  }
    212 
    213  nsAutoString zIndexValue;
    214 
    215  nsresult rv = CSSEditUtils::GetSpecifiedProperty(
    216      aElement, *nsGkAtoms::z_index, zIndexValue);
    217  if (NS_FAILED(rv)) {
    218    NS_WARNING("CSSEditUtils::GetSpecifiedProperty(nsGkAtoms::z_index) failed");
    219    return 0;
    220  }
    221  if (zIndexValue.EqualsLiteral("auto")) {
    222    if (!aElement.GetParentElement()) {
    223      NS_WARNING("aElement was an orphan node or the root node");
    224      return 0;
    225    }
    226    // we have to look at the positioned ancestors
    227    // cf. CSS 2 spec section 9.9.1
    228    nsAutoString positionValue;
    229    for (RefPtr<Element> element = aElement.GetParentElement(); element;
    230         element = element->GetParentElement()) {
    231      if (element->IsHTMLElement(nsGkAtoms::body)) {
    232        return 0;
    233      }
    234      nsCOMPtr<nsINode> parentNode = element->GetParentElement();
    235      nsresult rv = CSSEditUtils::GetComputedProperty(
    236          *element, *nsGkAtoms::position, positionValue);
    237      if (NS_FAILED(rv)) {
    238        NS_WARNING(
    239            "CSSEditUtils::GetComputedProperty(nsGkAtoms::position) failed");
    240        return 0;
    241      }
    242      if (NS_WARN_IF(Destroyed()) ||
    243          NS_WARN_IF(parentNode != element->GetParentNode())) {
    244        return 0;
    245      }
    246      if (!positionValue.EqualsLiteral("absolute")) {
    247        continue;
    248      }
    249      // ah, we found one, what's its z-index ? If its z-index is auto,
    250      // we have to continue climbing the document's tree
    251      rv = CSSEditUtils::GetComputedProperty(*element, *nsGkAtoms::z_index,
    252                                             zIndexValue);
    253      if (NS_FAILED(rv)) {
    254        NS_WARNING(
    255            "CSSEditUtils::GetComputedProperty(nsGkAtoms::z_index) failed");
    256        return 0;
    257      }
    258      if (NS_WARN_IF(Destroyed()) ||
    259          NS_WARN_IF(parentNode != element->GetParentNode())) {
    260        return 0;
    261      }
    262      if (!zIndexValue.EqualsLiteral("auto")) {
    263        break;
    264      }
    265    }
    266  }
    267 
    268  if (zIndexValue.EqualsLiteral("auto")) {
    269    return 0;
    270  }
    271 
    272  nsresult rvIgnored;
    273  int32_t result = zIndexValue.ToInteger(&rvIgnored);
    274  NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
    275                       "nsAString::ToInteger() failed, but ignored");
    276  return result;
    277 }
    278 
    279 bool HTMLEditor::CreateGrabberInternal(nsIContent& aParentContent) {
    280  if (NS_WARN_IF(mGrabber)) {
    281    return false;
    282  }
    283 
    284  mGrabber = CreateAnonymousElement(nsGkAtoms::span, aParentContent,
    285                                    u"mozGrabber"_ns, false);
    286 
    287  // mGrabber may be destroyed during creation due to there may be
    288  // mutation event listener.
    289  if (!mGrabber) {
    290    NS_WARNING(
    291        "HTMLEditor::CreateAnonymousElement(nsGkAtoms::span, mozGrabber) "
    292        "failed");
    293    return false;
    294  }
    295 
    296  EventListenerManager* eventListenerManager =
    297      mGrabber->GetOrCreateListenerManager();
    298  eventListenerManager->AddEventListenerByType(
    299      mEventListener, u"mousedown"_ns, TrustedEventsAtSystemGroupBubble());
    300  MOZ_ASSERT(mGrabber);
    301  return true;
    302 }
    303 
    304 nsresult HTMLEditor::RefreshGrabberInternal() {
    305  MOZ_ASSERT(IsEditActionDataAvailable());
    306 
    307  if (!mAbsolutelyPositionedObject) {
    308    return NS_OK;
    309  }
    310 
    311  OwningNonNull<Element> absolutelyPositionedObject =
    312      *mAbsolutelyPositionedObject;
    313  nsresult rv = GetPositionAndDimensions(
    314      absolutelyPositionedObject, mPositionedObjectX, mPositionedObjectY,
    315      mPositionedObjectWidth, mPositionedObjectHeight,
    316      mPositionedObjectBorderLeft, mPositionedObjectBorderTop,
    317      mPositionedObjectMarginLeft, mPositionedObjectMarginTop);
    318  if (NS_FAILED(rv)) {
    319    NS_WARNING("HTMLEditor::GetPositionAndDimensions() failed");
    320    return rv;
    321  }
    322  if (NS_WARN_IF(absolutelyPositionedObject != mAbsolutelyPositionedObject)) {
    323    return NS_ERROR_FAILURE;
    324  }
    325 
    326  RefPtr<nsStyledElement> grabberStyledElement =
    327      nsStyledElement::FromNodeOrNull(mGrabber.get());
    328  if (!grabberStyledElement) {
    329    return NS_OK;
    330  }
    331  rv = SetAnonymousElementPositionWithoutTransaction(
    332      *grabberStyledElement, mPositionedObjectX + 12, mPositionedObjectY - 14);
    333  if (NS_WARN_IF(Destroyed())) {
    334    return NS_ERROR_EDITOR_DESTROYED;
    335  }
    336  if (NS_FAILED(rv)) {
    337    NS_WARNING(
    338        "HTMLEditor::SetAnonymousElementPositionWithoutTransaction() failed");
    339    return rv;
    340  }
    341  if (NS_WARN_IF(grabberStyledElement != mGrabber.get())) {
    342    return NS_ERROR_FAILURE;
    343  }
    344  return NS_OK;
    345 }
    346 
    347 void HTMLEditor::HideGrabberInternal() {
    348  if (NS_WARN_IF(!mAbsolutelyPositionedObject)) {
    349    return;
    350  }
    351 
    352  // Move all members to the local variables first since mutation event
    353  // listener may try to show grabber while we're hiding them.
    354  const RefPtr<Element> absolutePositioningObject =
    355      std::move(mAbsolutelyPositionedObject);
    356  ManualNACPtr grabber = std::move(mGrabber);
    357  ManualNACPtr positioningShadow = std::move(mPositioningShadow);
    358 
    359  // If we're still in dragging mode, it means that the dragging is canceled
    360  // by the web app.
    361  if (mGrabberClicked || mIsMoving) {
    362    mGrabberClicked = false;
    363    mIsMoving = false;
    364    if (mEventListener) {
    365      DebugOnly<nsresult> rvIgnored =
    366          static_cast<HTMLEditorEventListener*>(mEventListener.get())
    367              ->ListenToMouseMoveEventForGrabber(false);
    368      NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
    369                           "HTMLEditorEventListener::"
    370                           "ListenToMouseMoveEventForGrabber(false) failed");
    371    }
    372  }
    373 
    374  {
    375    AutoElementAttrAPIWrapper elementWrapper(*this, *absolutePositioningObject);
    376    if (NS_FAILED(elementWrapper.UnsetAttr(nsGkAtoms::_moz_abspos, true))) {
    377      NS_WARNING("AutoElementAttrAPIWrapper::UnsetAttr() failed, but ignored");
    378    } else {
    379      NS_WARNING_ASSERTION(
    380          elementWrapper.IsExpectedResult(EmptyString()),
    381          "Removing _moz_abspos attribute caused other mutations, but ignored");
    382    }
    383  }
    384 
    385  // We allow the pres shell to be null; when it is, we presume there
    386  // are no document observers to notify, but we still want to
    387  // UnbindFromTree.
    388  RefPtr<PresShell> presShell = GetPresShell();
    389  if (grabber) {
    390    DeleteRefToAnonymousNode(std::move(grabber), presShell);
    391  }
    392  if (positioningShadow) {
    393    DeleteRefToAnonymousNode(std::move(positioningShadow), presShell);
    394  }
    395 }
    396 
    397 nsresult HTMLEditor::ShowGrabberInternal(Element& aElement) {
    398  MOZ_ASSERT(IsEditActionDataAvailable());
    399 
    400  const RefPtr<Element> editingHost = ComputeEditingHost();
    401  if (NS_WARN_IF(!editingHost) ||
    402      NS_WARN_IF(!aElement.IsInclusiveDescendantOf(editingHost))) {
    403    return NS_ERROR_UNEXPECTED;
    404  }
    405 
    406  if (NS_WARN_IF(mGrabber)) {
    407    return NS_ERROR_UNEXPECTED;
    408  }
    409 
    410  nsAutoString classValue;
    411  nsresult rv =
    412      GetTemporaryStyleForFocusedPositionedElement(aElement, classValue);
    413  if (NS_FAILED(rv)) {
    414    NS_WARNING(
    415        "HTMLEditor::GetTemporaryStyleForFocusedPositionedElement() failed");
    416    return rv;
    417  }
    418 
    419  {
    420    AutoElementAttrAPIWrapper elementWrapper(*this, aElement);
    421    nsresult rv =
    422        elementWrapper.SetAttr(nsGkAtoms::_moz_abspos, classValue, true);
    423    if (NS_FAILED(rv)) {
    424      NS_WARNING("AutoElementAttrAPIWrapper::SetAttr() failed");
    425      return rv;
    426    }
    427    NS_WARNING_ASSERTION(
    428        elementWrapper.IsExpectedResult(classValue),
    429        "Setting _moz_abspos attribute caused other mutations, but ignored");
    430  }
    431 
    432  mAbsolutelyPositionedObject = &aElement;
    433 
    434  Element* parentElement = aElement.GetParentElement();
    435  if (NS_WARN_IF(!parentElement)) {
    436    return NS_ERROR_FAILURE;
    437  }
    438 
    439  if (!CreateGrabberInternal(*parentElement)) {
    440    NS_WARNING("HTMLEditor::CreateGrabberInternal() failed");
    441    return NS_ERROR_FAILURE;
    442  }
    443 
    444  // If we succeeded to create the grabber, HideGrabberInternal() hasn't been
    445  // called yet.  So, mAbsolutelyPositionedObject should be non-nullptr.
    446  MOZ_ASSERT(mAbsolutelyPositionedObject);
    447 
    448  // Finally, move the grabber to proper position.
    449  rv = RefreshGrabberInternal();
    450  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
    451                       "HTMLEditor::RefereshGrabberInternal() failed");
    452  return rv;
    453 }
    454 
    455 nsresult HTMLEditor::StartMoving() {
    456  MOZ_ASSERT(mGrabber);
    457 
    458  RefPtr<Element> parentElement = mGrabber->GetParentElement();
    459  if (NS_WARN_IF(!parentElement) || NS_WARN_IF(!mAbsolutelyPositionedObject)) {
    460    return NS_ERROR_FAILURE;
    461  }
    462 
    463  // now, let's create the resizing shadow
    464  mPositioningShadow =
    465      CreateShadow(*parentElement, *mAbsolutelyPositionedObject);
    466  if (!mPositioningShadow) {
    467    NS_WARNING("HTMLEditor::CreateShadow() failed");
    468    return NS_ERROR_FAILURE;
    469  }
    470  if (!mAbsolutelyPositionedObject) {
    471    NS_WARNING("The target has gone during HTMLEditor::CreateShadow()");
    472    return NS_ERROR_FAILURE;
    473  }
    474  RefPtr<Element> positioningShadow = mPositioningShadow.get();
    475  RefPtr<Element> absolutelyPositionedObject = mAbsolutelyPositionedObject;
    476  nsresult rv =
    477      SetShadowPosition(*positioningShadow, *absolutelyPositionedObject,
    478                        mPositionedObjectX, mPositionedObjectY);
    479  if (NS_FAILED(rv)) {
    480    NS_WARNING("HTMLEditor::SetShadowPosition() failed");
    481    return rv;
    482  }
    483 
    484  // make the shadow appear
    485  DebugOnly<nsresult> rvIgnored =
    486      mPositioningShadow->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_class, true);
    487  NS_WARNING_ASSERTION(
    488      NS_SUCCEEDED(rvIgnored),
    489      "Element::UnsetAttr(nsGkAtoms::_class) failed, but ignored");
    490 
    491  // position it
    492  if (RefPtr<nsStyledElement> positioningShadowStyledElement =
    493          nsStyledElement::FromNode(mPositioningShadow.get())) {
    494    nsresult rv;
    495    rv = CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(
    496        *this, *positioningShadowStyledElement, *nsGkAtoms::width,
    497        mPositionedObjectWidth);
    498    if (rv == NS_ERROR_EDITOR_DESTROYED) {
    499      NS_WARNING(
    500          "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction("
    501          "nsGkAtoms::width) destroyed the editor");
    502      return NS_ERROR_EDITOR_DESTROYED;
    503    }
    504    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
    505                         "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction("
    506                         "nsGkAtoms::width) failed, but ignored");
    507    rv = CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction(
    508        *this, *positioningShadowStyledElement, *nsGkAtoms::height,
    509        mPositionedObjectHeight);
    510    if (rv == NS_ERROR_EDITOR_DESTROYED) {
    511      NS_WARNING(
    512          "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction("
    513          "nsGkAtoms::height) destroyed the editor");
    514      return NS_ERROR_EDITOR_DESTROYED;
    515    }
    516    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
    517                         "CSSEditUtils::SetCSSPropertyPixelsWithoutTransaction("
    518                         "nsGkAtoms::height) failed, but ignored");
    519  }
    520 
    521  mIsMoving = true;
    522  return NS_OK;  // XXX Looks like nobody refers this result
    523 }
    524 
    525 void HTMLEditor::SnapToGrid(int32_t& newX, int32_t& newY) const {
    526  if (mSnapToGridEnabled && mGridSize) {
    527    newX = (int32_t)floor(((float)newX / (float)mGridSize) + 0.5f) * mGridSize;
    528    newY = (int32_t)floor(((float)newY / (float)mGridSize) + 0.5f) * mGridSize;
    529  }
    530 }
    531 
    532 nsresult HTMLEditor::GrabberClicked() {
    533  if (NS_WARN_IF(!mEventListener)) {
    534    return NS_ERROR_NOT_INITIALIZED;
    535  }
    536  nsresult rv = static_cast<HTMLEditorEventListener*>(mEventListener.get())
    537                    ->ListenToMouseMoveEventForGrabber(true);
    538  if (NS_FAILED(rv)) {
    539    NS_WARNING(
    540        "HTMLEditorEventListener::ListenToMouseMoveEventForGrabber(true) "
    541        "failed, but ignored");
    542    return NS_OK;
    543  }
    544  mGrabberClicked = true;
    545  return NS_OK;
    546 }
    547 
    548 nsresult HTMLEditor::EndMoving() {
    549  if (mPositioningShadow) {
    550    RefPtr<PresShell> presShell = GetPresShell();
    551    if (NS_WARN_IF(!presShell)) {
    552      return NS_ERROR_NOT_INITIALIZED;
    553    }
    554 
    555    DeleteRefToAnonymousNode(std::move(mPositioningShadow), presShell);
    556 
    557    mPositioningShadow = nullptr;
    558  }
    559 
    560  if (mEventListener) {
    561    DebugOnly<nsresult> rvIgnored =
    562        static_cast<HTMLEditorEventListener*>(mEventListener.get())
    563            ->ListenToMouseMoveEventForGrabber(false);
    564    NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
    565                         "HTMLEditorEventListener::"
    566                         "ListenToMouseMoveEventForGrabber(false) failed");
    567  }
    568 
    569  mGrabberClicked = false;
    570  mIsMoving = false;
    571  nsresult rv = RefreshEditingUI();
    572  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
    573                       "HTMLEditor::RefreshEditingUI() failed");
    574  return rv;
    575 }
    576 
    577 nsresult HTMLEditor::SetFinalPosition(int32_t aX, int32_t aY) {
    578  MOZ_ASSERT(IsEditActionDataAvailable());
    579 
    580  nsresult rv = EndMoving();
    581  if (NS_FAILED(rv)) {
    582    NS_WARNING("HTMLEditor::EndMoving() failed");
    583    return rv;
    584  }
    585 
    586  // we have now to set the new width and height of the resized object
    587  // we don't set the x and y position because we don't control that in
    588  // a normal HTML layout
    589  int32_t newX = mPositionedObjectX + aX - mOriginalX -
    590                 (mPositionedObjectBorderLeft + mPositionedObjectMarginLeft);
    591  int32_t newY = mPositionedObjectY + aY - mOriginalY -
    592                 (mPositionedObjectBorderTop + mPositionedObjectMarginTop);
    593 
    594  SnapToGrid(newX, newY);
    595 
    596  nsAutoString x, y;
    597  x.AppendInt(newX);
    598  y.AppendInt(newY);
    599 
    600  // we want one transaction only from a user's point of view
    601  AutoPlaceholderBatch treatAsOneTransaction(
    602      *this, ScrollSelectionIntoView::Yes, __FUNCTION__);
    603 
    604  if (NS_WARN_IF(!mAbsolutelyPositionedObject)) {
    605    return NS_ERROR_FAILURE;
    606  }
    607  if (RefPtr<nsStyledElement> styledAbsolutelyPositionedElement =
    608          nsStyledElement::FromNode(mAbsolutelyPositionedObject)) {
    609    nsresult rv;
    610    rv = CSSEditUtils::SetCSSPropertyPixelsWithTransaction(
    611        *this, *styledAbsolutelyPositionedElement, *nsGkAtoms::top, newY);
    612    if (rv == NS_ERROR_EDITOR_DESTROYED) {
    613      NS_WARNING(
    614          "CSSEditUtils::SetCSSPropertyPixelsWithTransaction(nsGkAtoms::top) "
    615          "destroyed the editor");
    616      return NS_ERROR_EDITOR_DESTROYED;
    617    }
    618    NS_WARNING_ASSERTION(
    619        NS_SUCCEEDED(rv),
    620        "CSSEditUtils::SetCSSPropertyPixelsWithTransaction(nsGkAtoms::top) "
    621        "failed, but ignored");
    622    rv = CSSEditUtils::SetCSSPropertyPixelsWithTransaction(
    623        *this, *styledAbsolutelyPositionedElement, *nsGkAtoms::left, newX);
    624    if (rv == NS_ERROR_EDITOR_DESTROYED) {
    625      NS_WARNING(
    626          "CSSEditUtils::SetCSSPropertyPixelsWithTransaction(nsGkAtoms::left) "
    627          "destroyed the editor");
    628      return NS_ERROR_EDITOR_DESTROYED;
    629    }
    630    NS_WARNING_ASSERTION(
    631        NS_SUCCEEDED(rv),
    632        "CSSEditUtils::SetCSSPropertyPixelsWithTransaction(nsGkAtoms::left) "
    633        "failed, but ignored");
    634  }
    635  // keep track of that size
    636  mPositionedObjectX = newX;
    637  mPositionedObjectY = newY;
    638 
    639  rv = RefreshResizersInternal();
    640  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
    641                       "HTMLEditor::RefreshResizersInternal() failed");
    642  return rv;
    643 }
    644 
    645 nsresult HTMLEditor::SetPositionToAbsoluteOrStatic(Element& aElement,
    646                                                   bool aEnabled) {
    647  nsAutoString positionValue;
    648  DebugOnly<nsresult> rvIgnored = CSSEditUtils::GetComputedProperty(
    649      aElement, *nsGkAtoms::position, positionValue);
    650  NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
    651                       "CSSEditUtils::GetComputedProperty(nsGkAtoms::position) "
    652                       "failed, but ignored");
    653  // nothing to do if the element is already in the state we want
    654  if (positionValue.EqualsLiteral("absolute") == aEnabled) {
    655    return NS_OK;
    656  }
    657 
    658  if (aEnabled) {
    659    nsresult rv = SetPositionToAbsolute(aElement);
    660    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
    661                         "HTMLEditor::SetPositionToAbsolute() failed");
    662    return rv;
    663  }
    664 
    665  nsresult rv = SetPositionToStatic(aElement);
    666  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
    667                       "HTMLEditor::SetPositionToStatic() failed");
    668  return rv;
    669 }
    670 
    671 nsresult HTMLEditor::SetPositionToAbsolute(Element& aElement) {
    672  MOZ_ASSERT(IsEditActionDataAvailable());
    673 
    674  AutoPlaceholderBatch treatAsOneTransaction(
    675      *this, ScrollSelectionIntoView::Yes, __FUNCTION__);
    676 
    677  int32_t x, y;
    678  DebugOnly<nsresult> rvIgnored = GetElementOrigin(aElement, x, y);
    679  NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
    680                       "HTMLEditor::GetElementOrigin() failed, but ignored");
    681 
    682  nsStyledElement* styledElement = nsStyledElement::FromNode(&aElement);
    683  if (styledElement) {
    684    // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
    685    // by the caller because of MOZ_CAN_RUN_SCRIPT method.
    686    nsresult rv = CSSEditUtils::SetCSSPropertyWithTransaction(
    687        *this, MOZ_KnownLive(*styledElement), *nsGkAtoms::position,
    688        u"absolute"_ns);
    689    if (rv == NS_ERROR_EDITOR_DESTROYED) {
    690      NS_WARNING(
    691          "CSSEditUtils::SetCSSProperyWithTransaction(nsGkAtoms::Position) "
    692          "destroyed the editor");
    693      return NS_ERROR_EDITOR_DESTROYED;
    694    }
    695    NS_WARNING_ASSERTION(
    696        NS_SUCCEEDED(rvIgnored),
    697        "CSSEditUtils::SetCSSPropertyWithTransaction(nsGkAtoms::position, "
    698        "absolute) failed, but ignored");
    699  }
    700 
    701  SnapToGrid(x, y);
    702  if (styledElement) {
    703    // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
    704    // by the caller because of MOZ_CAN_RUN_SCRIPT method.
    705    nsresult rv =
    706        SetTopAndLeftWithTransaction(MOZ_KnownLive(*styledElement), x, y);
    707    if (NS_FAILED(rv)) {
    708      NS_WARNING("HTMLEditor::SetTopAndLeftWithTransaction() failed");
    709      return rv;
    710    }
    711  }
    712 
    713  // we may need to create a br if the positioned element is alone in its
    714  // container
    715  nsINode* parentNode = aElement.GetParentNode();
    716  if (parentNode->GetChildCount() != 1) {
    717    return NS_OK;
    718  }
    719  Result<CreateLineBreakResult, nsresult> insertBRElementResultOrError =
    720      InsertLineBreak(WithTransaction::Yes, LineBreakType::BRElement,
    721                      EditorDOMPoint(parentNode, 0u));
    722  if (MOZ_UNLIKELY(insertBRElementResultOrError.isErr())) {
    723    NS_WARNING(
    724        "HTMLEditor::InsertLineBreak(WithTransaction::Yes, "
    725        "LineBreakType::BRElement) failed");
    726    return insertBRElementResultOrError.unwrapErr();
    727  }
    728  CreateLineBreakResult insertBRElementResult =
    729      insertBRElementResultOrError.unwrap();
    730  MOZ_ASSERT(insertBRElementResult.Handled());
    731  // XXX Is this intentional selection change?
    732  nsresult rv = insertBRElementResult.SuggestCaretPointTo(
    733      *this, {SuggestCaret::OnlyIfHasSuggestion,
    734              SuggestCaret::OnlyIfTransactionsAllowedToDoIt});
    735  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
    736                       "CreateElementResult::SuggestCaretPointTo() failed");
    737  return rv;
    738 }
    739 
    740 nsresult HTMLEditor::SetPositionToStatic(Element& aElement) {
    741  nsStyledElement* styledElement = nsStyledElement::FromNode(&aElement);
    742  if (NS_WARN_IF(!styledElement)) {
    743    return NS_ERROR_INVALID_ARG;
    744  }
    745 
    746  AutoPlaceholderBatch treatAsOneTransaction(
    747      *this, ScrollSelectionIntoView::Yes, __FUNCTION__);
    748 
    749  nsresult rv;
    750  // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
    751  // by the caller because of MOZ_CAN_RUN_SCRIPT method.
    752  rv = CSSEditUtils::RemoveCSSPropertyWithTransaction(
    753      *this, MOZ_KnownLive(*styledElement), *nsGkAtoms::position, u""_ns);
    754  if (rv == NS_ERROR_EDITOR_DESTROYED) {
    755    NS_WARNING(
    756        "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::position) "
    757        "destroyed the editor");
    758    return NS_ERROR_EDITOR_DESTROYED;
    759  }
    760  NS_WARNING_ASSERTION(
    761      NS_SUCCEEDED(rv),
    762      "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::position) "
    763      "failed, but ignored");
    764  // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
    765  // by the caller because of MOZ_CAN_RUN_SCRIPT method.
    766  rv = CSSEditUtils::RemoveCSSPropertyWithTransaction(
    767      *this, MOZ_KnownLive(*styledElement), *nsGkAtoms::top, u""_ns);
    768  if (rv == NS_ERROR_EDITOR_DESTROYED) {
    769    NS_WARNING(
    770        "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::top) "
    771        "destroyed the editor");
    772    return NS_ERROR_EDITOR_DESTROYED;
    773  }
    774  NS_WARNING_ASSERTION(
    775      NS_SUCCEEDED(rv),
    776      "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::top) "
    777      "failed, but ignored");
    778  // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
    779  // by the caller because of MOZ_CAN_RUN_SCRIPT method.
    780  rv = CSSEditUtils::RemoveCSSPropertyWithTransaction(
    781      *this, MOZ_KnownLive(*styledElement), *nsGkAtoms::left, u""_ns);
    782  if (rv == NS_ERROR_EDITOR_DESTROYED) {
    783    NS_WARNING(
    784        "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::left) "
    785        "destroyed the editor");
    786    return NS_ERROR_EDITOR_DESTROYED;
    787  }
    788  NS_WARNING_ASSERTION(
    789      NS_SUCCEEDED(rv),
    790      "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::left) "
    791      "failed, but ignored");
    792  // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
    793  // by the caller because of MOZ_CAN_RUN_SCRIPT method.
    794  rv = CSSEditUtils::RemoveCSSPropertyWithTransaction(
    795      *this, MOZ_KnownLive(*styledElement), *nsGkAtoms::z_index, u""_ns);
    796  if (rv == NS_ERROR_EDITOR_DESTROYED) {
    797    NS_WARNING(
    798        "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::z_index) "
    799        "destroyed the editor");
    800    return NS_ERROR_EDITOR_DESTROYED;
    801  }
    802  NS_WARNING_ASSERTION(
    803      NS_SUCCEEDED(rv),
    804      "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::z_index) "
    805      "failed, but ignored");
    806 
    807  if (!HTMLEditUtils::IsImageElement(*styledElement)) {
    808    // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
    809    // by the caller because of MOZ_CAN_RUN_SCRIPT method.
    810    rv = CSSEditUtils::RemoveCSSPropertyWithTransaction(
    811        *this, MOZ_KnownLive(*styledElement), *nsGkAtoms::width, u""_ns);
    812    if (rv == NS_ERROR_EDITOR_DESTROYED) {
    813      NS_WARNING(
    814          "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::width) "
    815          "destroyed the editor");
    816      return NS_ERROR_EDITOR_DESTROYED;
    817    }
    818    NS_WARNING_ASSERTION(
    819        NS_SUCCEEDED(rv),
    820        "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::width) "
    821        "failed, but ignored");
    822    // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
    823    // by the caller because of MOZ_CAN_RUN_SCRIPT method.
    824    rv = CSSEditUtils::RemoveCSSPropertyWithTransaction(
    825        *this, MOZ_KnownLive(*styledElement), *nsGkAtoms::height, u""_ns);
    826    if (rv == NS_ERROR_EDITOR_DESTROYED) {
    827      NS_WARNING(
    828          "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::height) "
    829          "destroyed the editor");
    830      return NS_ERROR_EDITOR_DESTROYED;
    831    }
    832    NS_WARNING_ASSERTION(
    833        NS_SUCCEEDED(rv),
    834        "CSSEditUtils::RemoveCSSPropertyWithTransaction(nsGkAtoms::height) "
    835        "failed, but ignored");
    836  }
    837 
    838  if (!styledElement->IsHTMLElement(nsGkAtoms::div) ||
    839      HTMLEditor::HasStyleOrIdOrClassAttribute(*styledElement)) {
    840    return NS_OK;
    841  }
    842 
    843  EditorDOMPoint pointToPutCaret;
    844  // Make sure the first fild and last child of aElement starts/ends hard
    845  // line(s) even after removing `aElement`.
    846  {
    847    // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
    848    // by the caller because of MOZ_CAN_RUN_SCRIPT method.
    849    Result<CreateElementResult, nsresult>
    850        maybeInsertBRElementBeforeFirstChildResult =
    851            EnsureHardLineBeginsWithFirstChildOf(MOZ_KnownLive(*styledElement));
    852    if (MOZ_UNLIKELY(maybeInsertBRElementBeforeFirstChildResult.isErr())) {
    853      NS_WARNING("HTMLEditor::EnsureHardLineBeginsWithFirstChildOf() failed");
    854      return maybeInsertBRElementBeforeFirstChildResult.unwrapErr();
    855    }
    856    CreateElementResult unwrappedResult =
    857        maybeInsertBRElementBeforeFirstChildResult.unwrap();
    858    if (unwrappedResult.HasCaretPointSuggestion()) {
    859      pointToPutCaret = unwrappedResult.UnwrapCaretPoint();
    860    }
    861  }
    862  {
    863    // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
    864    // by the caller because of MOZ_CAN_RUN_SCRIPT method.
    865    Result<CreateElementResult, nsresult>
    866        maybeInsertBRElementAfterLastChildResult =
    867            EnsureHardLineEndsWithLastChildOf(MOZ_KnownLive(*styledElement));
    868    if (MOZ_UNLIKELY(maybeInsertBRElementAfterLastChildResult.isErr())) {
    869      NS_WARNING("HTMLEditor::EnsureHardLineEndsWithLastChildOf() failed");
    870      return maybeInsertBRElementAfterLastChildResult.unwrapErr();
    871    }
    872    CreateElementResult unwrappedResult =
    873        maybeInsertBRElementAfterLastChildResult.unwrap();
    874    if (unwrappedResult.HasCaretPointSuggestion()) {
    875      pointToPutCaret = unwrappedResult.UnwrapCaretPoint();
    876    }
    877  }
    878  {
    879    // MOZ_KnownLive(*styledElement): aElement's lifetime must be guarantted
    880    // by the caller because of MOZ_CAN_RUN_SCRIPT method.
    881    Result<EditorDOMPoint, nsresult> unwrapStyledElementResult =
    882        RemoveContainerWithTransaction(MOZ_KnownLive(*styledElement));
    883    if (MOZ_UNLIKELY(unwrapStyledElementResult.isErr())) {
    884      NS_WARNING("HTMLEditor::RemoveContainerWithTransaction() failed");
    885      return unwrapStyledElementResult.unwrapErr();
    886    }
    887    if (unwrapStyledElementResult.inspect().IsSet()) {
    888      pointToPutCaret = unwrapStyledElementResult.unwrap();
    889    }
    890  }
    891  if (!AllowsTransactionsToChangeSelection() || !pointToPutCaret.IsSet()) {
    892    return NS_OK;
    893  }
    894  rv = CollapseSelectionTo(pointToPutCaret);
    895  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
    896                       "EditorBase::CollapseSelectionTo() failed");
    897  return rv;
    898 }
    899 
    900 NS_IMETHODIMP HTMLEditor::SetSnapToGridEnabled(bool aEnabled) {
    901  mSnapToGridEnabled = aEnabled;
    902  return NS_OK;
    903 }
    904 
    905 NS_IMETHODIMP HTMLEditor::GetSnapToGridEnabled(bool* aIsEnabled) {
    906  *aIsEnabled = mSnapToGridEnabled;
    907  return NS_OK;
    908 }
    909 
    910 NS_IMETHODIMP HTMLEditor::SetGridSize(uint32_t aSize) {
    911  mGridSize = aSize;
    912  return NS_OK;
    913 }
    914 
    915 NS_IMETHODIMP HTMLEditor::GetGridSize(uint32_t* aSize) {
    916  *aSize = mGridSize;
    917  return NS_OK;
    918 }
    919 
    920 nsresult HTMLEditor::SetTopAndLeftWithTransaction(
    921    nsStyledElement& aStyledElement, int32_t aX, int32_t aY) {
    922  AutoPlaceholderBatch treatAsOneTransaction(
    923      *this, ScrollSelectionIntoView::Yes, __FUNCTION__);
    924  nsresult rv;
    925  rv = CSSEditUtils::SetCSSPropertyPixelsWithTransaction(*this, aStyledElement,
    926                                                         *nsGkAtoms::left, aX);
    927  if (rv == NS_ERROR_EDITOR_DESTROYED) {
    928    NS_WARNING(
    929        "CSSEditUtils::SetCSSPropertyPixelsWithTransaction(nsGkAtoms::left) "
    930        "destroyed the editor");
    931    return NS_ERROR_EDITOR_DESTROYED;
    932  }
    933  NS_WARNING_ASSERTION(
    934      NS_SUCCEEDED(rv),
    935      "CSSEditUtils::SetCSSPropertyPixelsWithTransaction(nsGkAtoms::left) "
    936      "failed, but ignored");
    937  rv = CSSEditUtils::SetCSSPropertyPixelsWithTransaction(*this, aStyledElement,
    938                                                         *nsGkAtoms::top, aY);
    939  if (rv == NS_ERROR_EDITOR_DESTROYED) {
    940    NS_WARNING(
    941        "CSSEditUtils::SetCSSPropertyPixelsWithTransaction(nsGkAtoms::top) "
    942        "destroyed the editor");
    943    return NS_ERROR_EDITOR_DESTROYED;
    944  }
    945  NS_WARNING_ASSERTION(
    946      NS_SUCCEEDED(rv),
    947      "CSSEditUtils::SetCSSPropertyPixelsWithTransaction(nsGkAtoms::top) "
    948      "failed, but ignored");
    949  return NS_OK;
    950 }
    951 
    952 nsresult HTMLEditor::GetTemporaryStyleForFocusedPositionedElement(
    953    Element& aElement, nsAString& aReturn) {
    954  // we are going to outline the positioned element and bring it to the
    955  // front to overlap any other element intersecting with it. But
    956  // first, let's see what's the background and foreground colors of the
    957  // positioned element.
    958  // if background-image computed value is 'none,
    959  //   If the background color is 'auto' and R G B values of the foreground are
    960  //       each above #d0, use a black background
    961  //   If the background color is 'auto' and at least one of R G B values of
    962  //       the foreground is below #d0, use a white background
    963  // Otherwise don't change background/foreground
    964  aReturn.Truncate();
    965 
    966  nsAutoString backgroundImageValue;
    967  nsresult rv = CSSEditUtils::GetComputedProperty(
    968      aElement, *nsGkAtoms::background_image, backgroundImageValue);
    969  if (NS_FAILED(rv)) {
    970    NS_WARNING(
    971        "CSSEditUtils::GetComputedProperty(nsGkAtoms::background_image) "
    972        "failed");
    973    return rv;
    974  }
    975  if (!backgroundImageValue.EqualsLiteral("none")) {
    976    return NS_OK;
    977  }
    978 
    979  nsAutoString backgroundColorValue;
    980  rv = CSSEditUtils::GetComputedProperty(aElement, *nsGkAtoms::background_color,
    981                                         backgroundColorValue);
    982  if (NS_FAILED(rv)) {
    983    NS_WARNING(
    984        "CSSEditUtils::GetComputedProperty(nsGkAtoms::background_color) "
    985        "failed");
    986    return rv;
    987  }
    988  if (!backgroundColorValue.EqualsLiteral("rgba(0, 0, 0, 0)")) {
    989    return NS_OK;
    990  }
    991 
    992  RefPtr<const ComputedStyle> style =
    993      nsComputedDOMStyle::GetComputedStyle(&aElement);
    994  if (NS_WARN_IF(Destroyed())) {
    995    return NS_ERROR_EDITOR_DESTROYED;
    996  }
    997  if (!style) {
    998    NS_WARNING("nsComputedDOMStyle::GetComputedStyle() failed");
    999    return NS_ERROR_FAILURE;
   1000  }
   1001 
   1002  static const uint8_t kBlackBgTrigger = 0xd0;
   1003 
   1004  auto color = style->StyleText()->mColor.ToColor();
   1005  if (NS_GET_R(color) >= kBlackBgTrigger &&
   1006      NS_GET_G(color) >= kBlackBgTrigger &&
   1007      NS_GET_B(color) >= kBlackBgTrigger) {
   1008    aReturn.AssignLiteral("black");
   1009  } else {
   1010    aReturn.AssignLiteral("white");
   1011  }
   1012 
   1013  return NS_OK;
   1014 }
   1015 
   1016 }  // namespace mozilla