Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/dom/base/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 152 kB image not shown  

SSL nsDOMWindowUtils.cpp   Interaktion und
PortierbarkeitC

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "nsDOMWindowUtils.h"

#include "LayoutConstants.h"
#include "MobileViewportManager.h"
#include "mozilla/layers/CompositorBridgeChild.h"
#include "nsPresContext.h"
#include "nsCaret.h"
#include "nsContentList.h"
#include "nsError.h"
#include "nsQueryContentEventResult.h"
#include "nsGlobalWindowOuter.h"
#include "nsFocusManager.h"
#include "nsFrameManager.h"
#include "nsRefreshDriver.h"
#include "nsStyleUtil.h"
#include "mozilla/Base64.h"
#include "mozilla/dom/Animation.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/BlobBinding.h"
#include "mozilla/dom/DocumentInlines.h"
#include "mozilla/dom/DocumentTimeline.h"
#include "mozilla/dom/DOMCollectedFramesBinding.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/Touch.h"
#include "mozilla/dom/UserActivation.h"
#include "mozilla/EventStateManager.h"
#include "mozilla/ScrollContainerFrame.h"
#include "mozilla/ServoStyleSet.h"
#include "mozilla/SharedStyleSheetCache.h"
#include "mozilla/dom/SharedScriptCache.h"
#include "mozilla/StaticPrefs_test.h"
#include "mozilla/InputTaskManager.h"
#include "nsIObjectLoadingContent.h"
#include "nsIFrame.h"
#include "mozilla/layers/APZCCallbackHelper.h"
#include "mozilla/layers/PCompositorBridgeTypes.h"
#include "mozilla/layers/TouchActionHelper.h"
#include "mozilla/media/MediaUtils.h"
#include "nsQueryObject.h"
#include "CubebDeviceEnumerator.h"

#include "nsContentUtils.h"

#include "nsIWidget.h"
#include "nsCharsetSource.h"
#include "nsJSEnvironment.h"
#include "nsJSUtils.h"
#include "js/experimental/PCCountProfiling.h"  // JS::{Start,Stop}PCCountProfiling, JS::PurgePCCounts, JS::GetPCCountScript{Count,Summary,Contents}
#include "js/Object.h"                         // JS::GetClass

#include "mozilla/ChaosMode.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/MiscEvents.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/PresShell.h"
#include "mozilla/PresShellInlines.h"
#include "mozilla/Span.h"
#include "mozilla/StaticPrefs_layout.h"
#include "mozilla/TextEvents.h"
#include "mozilla/TextEventDispatcher.h"
#include "mozilla/TouchEvents.h"

#include "nsViewManager.h"

#include "nsLayoutUtils.h"
#include "nsComputedDOMStyle.h"
#include "nsCSSProps.h"
#include "nsIDocShell.h"
#include "mozilla/StyleAnimationValue.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FileBinding.h"
#include "mozilla/dom/DOMRect.h"
#include <algorithm>

#if defined(MOZ_WIDGET_GTK)
#  include <gdk/gdk.h>
#  if defined(MOZ_X11)
#    include <gdk/gdkx.h>
#    include "X11UndefineNone.h"
#  endif
#endif

#include "mozilla/dom/AudioDeviceInfo.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/dom/IDBFactoryBinding.h"
#include "mozilla/dom/IndexedDatabaseManager.h"
#include "mozilla/dom/PermissionMessageUtils.h"
#include "mozilla/dom/Text.h"
#include "mozilla/dom/quota/PersistenceType.h"
#include "mozilla/dom/quota/PrincipalUtils.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/layers/FrameUniformityData.h"
#include "nsPrintfCString.h"
#include "nsViewportInfo.h"
#include "nsIFormControl.h"
// #include "nsWidgetsCID.h"
#include "nsDisplayList.h"
#include "nsROCSSPrimitiveValue.h"
#include "nsIBaseWindow.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIInterfaceRequestorUtils.h"
#include "mozilla/Preferences.h"
#include "nsContentPermissionHelper.h"
#include "nsCSSPseudoElements.h"  // for PseudoStyleType
#include "nsNetUtil.h"
#include "HTMLImageElement.h"
#include "HTMLCanvasElement.h"
#include "mozilla/css/ImageLoader.h"
#include "mozilla/layers/IAPZCTreeManager.h"  // for layers::ZoomToRectBehavior
#include "mozilla/dom/Document.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/RDDProcessManager.h"
#include "mozilla/ServoBindings.h"
#include "mozilla/StyleSheetInlines.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/dom/TimeoutManager.h"
#include "mozilla/PreloadedStyleSheet.h"
#include "mozilla/ProfilerLabels.h"
#include "mozilla/ProfilerMarkers.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/layers/WebRenderLayerManager.h"
#include "mozilla/DisplayPortUtils.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/ViewportUtils.h"
#include "mozilla/dom/BrowsingContextGroup.h"
#include "mozilla/IMEStateManager.h"
#include "mozilla/IMEContentObserver.h"
#include "mozilla/WheelHandlingHelper.h"
#include "mozilla/AnimatedPropertyID.h"

#ifdef XP_WIN
#  include <direct.h>
#else
#  include <sys/stat.h>
#endif

#ifdef XP_WIN
#  undef GetClassName
#endif

using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::ipc;
using namespace mozilla::layers;
using namespace mozilla::widget;
using namespace mozilla::gfx;

class gfxContext;

class OldWindowSize : public LinkedListElement<OldWindowSize> {
 public:
  static void Set(nsIWeakReference* aWindowRef, const nsSize& aSize) {
    OldWindowSize* item = GetItem(aWindowRef);
    if (item) {
      item->mSize = aSize;
    } else {
      item = new OldWindowSize(aWindowRef, aSize);
      sList.insertBack(item);
    }
  }

  static nsSize GetAndRemove(nsIWeakReference* aWindowRef) {
    nsSize result;
    if (OldWindowSize* item = GetItem(aWindowRef)) {
      result = item->mSize;
      delete item;
    }
    return result;
  }

 private:
  explicit OldWindowSize(nsIWeakReference* aWindowRef, const nsSize& aSize)
      : mWindowRef(aWindowRef), mSize(aSize) {}
  ~OldWindowSize() = default;
  ;

  static OldWindowSize* GetItem(nsIWeakReference* aWindowRef) {
    OldWindowSize* item = sList.getFirst();
    while (item && item->mWindowRef != aWindowRef) {
      item = item->getNext();
    }
    return item;
  }

  static LinkedList<OldWindowSize> sList;
  nsWeakPtr mWindowRef;
  nsSize mSize;
};

namespace {

class NativeInputRunnable final : public PrioritizableRunnable {
  explicit NativeInputRunnable(already_AddRefed<nsIRunnable>&& aEvent);
  ~NativeInputRunnable() = default;

 public:
  static already_AddRefed<nsIRunnable> Create(
      already_AddRefed<nsIRunnable>&& aEvent);
};

NativeInputRunnable::NativeInputRunnable(already_AddRefed<nsIRunnable>&& aEvent)
    : PrioritizableRunnable(std::move(aEvent),
                            nsIRunnablePriority::PRIORITY_INPUT_HIGH) {}

/* static */
already_AddRefed<nsIRunnable> NativeInputRunnable::Create(
    already_AddRefed<nsIRunnable>&& aEvent) {
  MOZ_ASSERT(NS_IsMainThread());
  nsCOMPtr<nsIRunnable> event(new NativeInputRunnable(std::move(aEvent)));
  return event.forget();
}

}  // unnamed namespace

MOZ_RUNINIT LinkedList<OldWindowSize> OldWindowSize::sList;

NS_INTERFACE_MAP_BEGIN(nsDOMWindowUtils)
  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMWindowUtils)
  NS_INTERFACE_MAP_ENTRY(nsIDOMWindowUtils)
  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_END

NS_IMPL_ADDREF(nsDOMWindowUtils)
NS_IMPL_RELEASE(nsDOMWindowUtils)

nsDOMWindowUtils::nsDOMWindowUtils(nsGlobalWindowOuter* aWindow) {
  nsCOMPtr<nsISupports> supports = do_QueryObject(aWindow);
  mWindow = do_GetWeakReference(supports);
}

nsDOMWindowUtils::~nsDOMWindowUtils() { OldWindowSize::GetAndRemove(mWindow); }

nsIDocShell* nsDOMWindowUtils::GetDocShell() {
  nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
  if (!window) {
    return nullptr;
  }
  return window->GetDocShell();
}

PresShell* nsDOMWindowUtils::GetPresShell() {
  nsIDocShell* docShell = GetDocShell();
  if (!docShell) {
    return nullptr;
  }
  return docShell->GetPresShell();
}

nsPresContext* nsDOMWindowUtils::GetPresContext() {
  nsIDocShell* docShell = GetDocShell();
  if (!docShell) {
    return nullptr;
  }
  return docShell->GetPresContext();
}

Document* nsDOMWindowUtils::GetDocument() {
  nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
  if (!window) {
    return nullptr;
  }
  return window->GetExtantDoc();
}

WebRenderBridgeChild* nsDOMWindowUtils::GetWebRenderBridge() {
  if (nsIWidget* widget = GetWidget()) {
    if (WindowRenderer* renderer = widget->GetWindowRenderer()) {
      if (WebRenderLayerManager* wr = renderer->AsWebRender()) {
        return wr->WrBridge();
      }
    }
  }
  return nullptr;
}

CompositorBridgeChild* nsDOMWindowUtils::GetCompositorBridge() {
  if (nsIWidget* widget = GetWidget()) {
    if (WindowRenderer* renderer = widget->GetWindowRenderer()) {
      if (CompositorBridgeChild* cbc = renderer->GetCompositorBridgeChild()) {
        return cbc;
      }
    }
  }
  return nullptr;
}

nsresult nsDOMWindowUtils::GetWidgetOpaqueRegion(
    nsTArray<RefPtr<DOMRect>>& aRects) {
  nsIWidget* widget = GetWidget();
  if (!widget) {
    return NS_ERROR_FAILURE;
  }
  auto AddRect = [&](const LayoutDeviceIntRect& aRect) {
    RefPtr rect = new DOMRect(mWindow);
    CSSRect cssRect = aRect / widget->GetDefaultScale();
    rect->SetRect(cssRect.x, cssRect.y, cssRect.width, cssRect.height);
    aRects.AppendElement(std::move(rect));
  };
  if (widget->GetTransparencyMode() == TransparencyMode::Opaque) {
    AddRect(
        LayoutDeviceIntRect(LayoutDeviceIntPoint(), widget->GetClientSize()));
    return NS_OK;
  }
  auto region = widget->GetOpaqueRegionForTesting();
  for (auto iter = region.RectIter(); !iter.Done(); iter.Next()) {
    AddRect(iter.Get());
  }
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetLastOverWindowPointerLocationInCSSPixels(float* aX,
                                                              float* aY) {
  const PresShell* presShell = GetPresShell();
  const nsPresContext* presContext = GetPresContext();

  if (!presShell || !presContext) {
    return NS_ERROR_FAILURE;
  }

  const nsPoint& lastOverWindowPointerLocation =
      presShell->GetLastOverWindowPointerLocation();

  if (lastOverWindowPointerLocation.X() == NS_UNCONSTRAINEDSIZE &&
      lastOverWindowPointerLocation.Y() == NS_UNCONSTRAINEDSIZE) {
    *aX = 0;
    *aY = 0;
  } else {
    const CSSPoint lastOverWindowPointerLocationInCSSPixels =
        CSSPoint::FromAppUnits(lastOverWindowPointerLocation);
    *aX = lastOverWindowPointerLocationInCSSPixels.X();
    *aY = lastOverWindowPointerLocationInCSSPixels.Y();
  }

  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::SyncFlushCompositor() {
  if (nsIWidget* widget = GetWidget()) {
    if (WindowRenderer* renderer = widget->GetWindowRenderer()) {
      if (KnowsCompositor* kc = renderer->AsKnowsCompositor()) {
        kc->SyncWithCompositor();
      }
    }
  }
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetImageAnimationMode(uint16_t* aMode) {
  NS_ENSURE_ARG_POINTER(aMode);
  *aMode = 0;
  nsPresContext* presContext = GetPresContext();
  if (presContext) {
    *aMode = presContext->ImageAnimationMode();
    return NS_OK;
  }
  return NS_ERROR_NOT_AVAILABLE;
}

NS_IMETHODIMP
nsDOMWindowUtils::SetImageAnimationMode(uint16_t aMode) {
  nsPresContext* presContext = GetPresContext();
  if (presContext) {
    presContext->SetImageAnimationMode(aMode);
    return NS_OK;
  }
  return NS_ERROR_NOT_AVAILABLE;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetDocCharsetIsForced(bool* aIsForced) {
  *aIsForced = false;

  Document* doc = GetDocument();
  if (doc) {
    auto source = doc->GetDocumentCharacterSetSource();
    *aIsForced = source == kCharsetFromInitialUserForcedAutoDetection ||
                 source == kCharsetFromFinalUserForcedAutoDetection;
  }
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetPhysicalMillimeterInCSSPixels(float* aPhysicalMillimeter) {
  nsPresContext* presContext = GetPresContext();
  if (!presContext) {
    return NS_ERROR_NOT_AVAILABLE;
  }

  *aPhysicalMillimeter = nsPresContext::AppUnitsToFloatCSSPixels(
      presContext->PhysicalMillimetersToAppUnits(1));
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetDocumentMetadata(const nsAString& aName,
                                      nsAString& aValue) {
  Document* doc = GetDocument();
  if (doc) {
    RefPtr<nsAtom> name = NS_Atomize(aName);
    doc->GetHeaderData(name, aValue);
    return NS_OK;
  }

  aValue.Truncate();
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::UpdateLayerTree() {
  if (RefPtr<PresShell> presShell = GetPresShell()) {
    // Don't flush throttled animations since it might fire MozAfterPaint event
    // (in WebRender it constantly does), thus the reftest harness can't take
    // any snapshot until the throttled animations finished.
    presShell->FlushPendingNotifications(
        ChangesToFlush(FlushType::Layout, false /* flush animations */));
    RefPtr<nsViewManager> vm = presShell->GetViewManager();
    if (nsView* view = vm->GetRootView()) {
      nsAutoScriptBlocker scriptBlocker;
      presShell->PaintAndRequestComposite(view,
                                          PaintFlags::PaintSyncDecodeImages);
      presShell->GetWindowRenderer()->WaitOnTransactionProcessed();
    }
  }
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetDocumentViewerSize(uint32_t* aDisplayWidth,
                                        uint32_t* aDisplayHeight) {
  PresShell* presShell = GetPresShell();
  LayoutDeviceIntSize displaySize;

  if (!presShell || !nsLayoutUtils::GetDocumentViewerSize(
                        presShell->GetPresContext(), displaySize)) {
    return NS_ERROR_FAILURE;
  }

  *aDisplayWidth = displaySize.width;
  *aDisplayHeight = displaySize.height;

  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetViewportInfo(uint32_t aDisplayWidth,
                                  uint32_t aDisplayHeight, double* aDefaultZoom,
                                  bool* aAllowZoom, double* aMinZoom,
                                  double* aMaxZoom, uint32_t* aWidth,
                                  uint32_t* aHeight, bool* aAutoSize) {
  Document* doc = GetDocument();
  NS_ENSURE_STATE(doc);

  nsViewportInfo info =
      doc->GetViewportInfo(ScreenIntSize(aDisplayWidth, aDisplayHeight));
  *aDefaultZoom = info.GetDefaultZoom().scale;
  *aAllowZoom = info.IsZoomAllowed();
  *aMinZoom = info.GetMinZoom().scale;
  *aMaxZoom = info.GetMaxZoom().scale;
  CSSIntSize size = gfx::RoundedToInt(info.GetSize());
  *aWidth = size.width;
  *aHeight = size.height;
  *aAutoSize = info.IsAutoSizeEnabled();
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetViewportFitInfo(nsAString& aViewportFit) {
  Document* doc = GetDocument();
  NS_ENSURE_STATE(doc);

  ViewportMetaData metaData = doc->GetViewportMetaData();
  if (metaData.mViewportFit.EqualsLiteral("contain")) {
    aViewportFit.AssignLiteral("contain");
  } else if (metaData.mViewportFit.EqualsLiteral("cover")) {
    aViewportFit.AssignLiteral("cover");
  } else {
    aViewportFit.AssignLiteral("auto");
  }
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::SetMousewheelAutodir(Element* aElement, bool aEnabled,
                                       bool aHonourRoot) {
  aElement->SetProperty(nsGkAtoms::forceMousewheelAutodir,
                        reinterpret_cast<void*>(aEnabled));
  aElement->SetProperty(nsGkAtoms::forceMousewheelAutodirHonourRoot,
                        reinterpret_cast<void*>(aHonourRoot));
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::SetDisplayPortForElement(float aXPx, float aYPx,
                                           float aWidthPx, float aHeightPx,
                                           Element* aElement,
                                           uint32_t aPriority) {
  PresShell* presShell = GetPresShell();
  if (!presShell) {
    return NS_ERROR_FAILURE;
  }

  if (!aElement) {
    return NS_ERROR_INVALID_ARG;
  }

  if (aElement->GetUncomposedDoc() != presShell->GetDocument()) {
    return NS_ERROR_INVALID_ARG;
  }

  bool hadDisplayPort = false;
  bool wasPainted = false;
  nsRect oldDisplayPort;
  {
    DisplayPortPropertyData* currentData =
        static_cast<DisplayPortPropertyData*>(
            aElement->GetProperty(nsGkAtoms::DisplayPort));
    if (currentData) {
      if (currentData->mPriority > aPriority) {
        return NS_OK;
      }
      hadDisplayPort = true;
      oldDisplayPort = currentData->mRect;
      wasPainted = currentData->mPainted;
    }
  }

  nsRect displayport(nsPresContext::CSSPixelsToAppUnits(aXPx),
                     nsPresContext::CSSPixelsToAppUnits(aYPx),
                     nsPresContext::CSSPixelsToAppUnits(aWidthPx),
                     nsPresContext::CSSPixelsToAppUnits(aHeightPx));

  aElement->RemoveProperty(nsGkAtoms::MinimalDisplayPort);
  aElement->SetProperty(
      nsGkAtoms::DisplayPort,
      new DisplayPortPropertyData(displayport, aPriority, wasPainted),
      nsINode::DeleteProperty<DisplayPortPropertyData>);

  DisplayPortUtils::InvalidateForDisplayPortChange(aElement, hadDisplayPort,
                                                   oldDisplayPort, displayport);

  nsIFrame* rootFrame = presShell->GetRootFrame();
  if (rootFrame) {
    rootFrame->SchedulePaint();

    // If we are hiding something that is a display root then send empty paint
    // transaction in order to release retained layers because it won't get
    // any more paint requests when it is hidden.
    if (displayport.IsEmpty() &&
        rootFrame == nsLayoutUtils::GetDisplayRootFrame(rootFrame)) {
      nsCOMPtr<nsIWidget> widget = GetWidget();
      if (widget) {
        using PaintFrameFlags = nsLayoutUtils::PaintFrameFlags;
        nsLayoutUtils::PaintFrame(
            nullptr, rootFrame, nsRegion(), NS_RGB(255, 255, 255),
            nsDisplayListBuilderMode::Painting, PaintFrameFlags::WidgetLayers);
      }
    }
  }

  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::SetDisplayPortMarginsForElement(
    float aLeftMargin, float aTopMargin, float aRightMargin,
    float aBottomMargin, Element* aElement, uint32_t aPriority) {
  PresShell* presShell = GetPresShell();
  if (!presShell) {
    return NS_ERROR_FAILURE;
  }

  if (!aElement) {
    return NS_ERROR_INVALID_ARG;
  }

  if (aElement->GetUncomposedDoc() != presShell->GetDocument()) {
    return NS_ERROR_INVALID_ARG;
  }

  // Note order change of arguments between our function signature and
  // ScreenMargin constructor.
  ScreenMargin displayportMargins(aTopMargin, aRightMargin, aBottomMargin,
                                  aLeftMargin);

  DisplayPortUtils::SetDisplayPortMargins(
      aElement, presShell,
      DisplayPortMargins::ForContent(aElement, displayportMargins),
      DisplayPortUtils::ClearMinimalDisplayPortProperty::Yes, aPriority);

  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::SetDisplayPortBaseForElement(int32_t aX, int32_t aY,
                                               int32_t aWidth, int32_t aHeight,
                                               Element* aElement) {
  PresShell* presShell = GetPresShell();
  if (!presShell) {
    return NS_ERROR_FAILURE;
  }

  if (!aElement) {
    return NS_ERROR_INVALID_ARG;
  }

  if (aElement->GetUncomposedDoc() != presShell->GetDocument()) {
    return NS_ERROR_INVALID_ARG;
  }

  DisplayPortUtils::SetDisplayPortBase(aElement,
                                       nsRect(aX, aY, aWidth, aHeight));

  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetScrollbarSizes(Element* aElement,
                                    uint32_t* aOutVerticalScrollbarWidth,
                                    uint32_t* aOutHorizontalScrollbarHeight) {
  ScrollContainerFrame* scrollContainerFrame =
      nsLayoutUtils::FindScrollContainerFrameFor(aElement);
  if (!scrollContainerFrame) {
    return NS_ERROR_INVALID_ARG;
  }

  CSSIntMargin scrollbarSizes = RoundedToInt(
      CSSMargin::FromAppUnits(scrollContainerFrame->GetActualScrollbarSizes(
          ScrollContainerFrame::ScrollbarSizesOptions::
              INCLUDE_VISUAL_VIEWPORT_SCROLLBARS)));
  *aOutVerticalScrollbarWidth = scrollbarSizes.LeftRight();
  *aOutHorizontalScrollbarHeight = scrollbarSizes.TopBottom();

  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::SetResolutionAndScaleTo(float aResolution) {
  PresShell* presShell = GetPresShell();
  if (!presShell) {
    return NS_ERROR_FAILURE;
  }

  presShell->SetResolutionAndScaleTo(aResolution, ResolutionChangeOrigin::Test);

  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::SetRestoreResolution(float aResolution,
                                       uint32_t aDisplayWidth,
                                       uint32_t aDisplayHeight) {
  PresShell* presShell = GetPresShell();
  if (!presShell) {
    return NS_ERROR_FAILURE;
  }

  presShell->SetRestoreResolution(
      aResolution, LayoutDeviceIntSize(aDisplayWidth, aDisplayHeight));

  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetResolution(float* aResolution) {
  PresShell* presShell = GetPresShell();
  if (!presShell) {
    return NS_ERROR_FAILURE;
  }

  *aResolution = presShell->GetResolution();

  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::SetIsFirstPaint(bool aIsFirstPaint) {
  if (PresShell* presShell = GetPresShell()) {
    presShell->SetIsFirstPaint(aIsFirstPaint);
    return NS_OK;
  }
  return NS_ERROR_FAILURE;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetIsFirstPaint(bool* aIsFirstPaint) {
  if (PresShell* presShell = GetPresShell()) {
    *aIsFirstPaint = presShell->GetIsFirstPaint();
    return NS_OK;
  }
  return NS_ERROR_FAILURE;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetPresShellId(uint32_t* aPresShellId) {
  if (PresShell* presShell = GetPresShell()) {
    *aPresShellId = presShell->GetPresShellId();
    return NS_OK;
  }
  return NS_ERROR_FAILURE;
}

NS_IMETHODIMP
nsDOMWindowUtils::SendMouseEvent(
    const nsAString& aType, float aX, float aY, int32_t aButton,
    int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame,
    float aPressure, unsigned short aInputSourceArg,
    bool aIsDOMEventSynthesized, bool aIsWidgetEventSynthesized,
    int32_t aButtons, uint32_t aIdentifier, uint8_t aOptionalArgCount,
    bool* aPreventDefault) {
  return SendMouseEventCommon(
      aType, aX, aY, aButton, aClickCount, aModifiers, aIgnoreRootScrollFrame,
      aPressure, aInputSourceArg,
      aOptionalArgCount >= 7 ? aIdentifier : DEFAULT_MOUSE_POINTER_ID, false,
      aPreventDefault, aOptionalArgCount >= 4 ? aIsDOMEventSynthesized : true,
      aOptionalArgCount >= 5 ? aIsWidgetEventSynthesized : false,
      aOptionalArgCount >= 6 ? aButtons : MOUSE_BUTTONS_NOT_SPECIFIED);
}

NS_IMETHODIMP
nsDOMWindowUtils::SendMouseEventToWindow(
    const nsAString& aType, float aX, float aY, int32_t aButton,
    int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame,
    float aPressure, unsigned short aInputSourceArg,
    bool aIsDOMEventSynthesized, bool aIsWidgetEventSynthesized,
    int32_t aButtons, uint32_t aIdentifier, uint8_t aOptionalArgCount) {
  AUTO_PROFILER_LABEL("nsDOMWindowUtils::SendMouseEventToWindow", OTHER);

  return SendMouseEventCommon(
      aType, aX, aY, aButton, aClickCount, aModifiers, aIgnoreRootScrollFrame,
      aPressure, aInputSourceArg,
      aOptionalArgCount >= 7 ? aIdentifier : DEFAULT_MOUSE_POINTER_ID, true,
      nullptr, aOptionalArgCount >= 4 ? aIsDOMEventSynthesized : true,
      aOptionalArgCount >= 5 ? aIsWidgetEventSynthesized : false,
      aOptionalArgCount >= 6 ? aButtons : MOUSE_BUTTONS_NOT_SPECIFIED);
}

NS_IMETHODIMP
nsDOMWindowUtils::SendMouseEventCommon(
    const nsAString& aType, float aX, float aY, int32_t aButton,
    int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame,
    float aPressure, unsigned short aInputSourceArg, uint32_t aPointerId,
    bool aToWindow, bool* aPreventDefault, bool aIsDOMEventSynthesized,
    bool aIsWidgetEventSynthesized, int32_t aButtons) {
  RefPtr<PresShell> presShell = GetPresShell();
  return nsContentUtils::SendMouseEvent(
      presShell, aType, aX, aY, aButton, aButtons, aClickCount, aModifiers,
      aIgnoreRootScrollFrame, aPressure, aInputSourceArg, aPointerId, aToWindow,
      aPreventDefault, aIsDOMEventSynthesized, aIsWidgetEventSynthesized);
}

NS_IMETHODIMP
nsDOMWindowUtils::IsCORSSafelistedRequestHeader(const nsACString& aName,
                                                const nsACString& aValue,
                                                bool* aRetVal) {
  NS_ENSURE_ARG_POINTER(aRetVal);
  *aRetVal = nsContentUtils::IsCORSSafelistedRequestHeader(aName, aValue);
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::SendWheelEvent(float aX, float aY, double aDeltaX,
                                 double aDeltaY, double aDeltaZ,
                                 uint32_t aDeltaMode, int32_t aModifiers,
                                 int32_t aLineOrPageDeltaX,
                                 int32_t aLineOrPageDeltaY, uint32_t aOptions) {
  // get the widget to send the event to
  nsPoint offset;
  nsCOMPtr<nsIWidget> widget = GetWidget(&offset);
  if (!widget) {
    return NS_ERROR_NULL_POINTER;
  }

  WidgetWheelEvent wheelEvent(true, eWheel, widget);
  wheelEvent.mModifiers = nsContentUtils::GetWidgetModifiers(aModifiers);
  wheelEvent.mDeltaX = aDeltaX;
  wheelEvent.mDeltaY = aDeltaY;
  wheelEvent.mDeltaZ = aDeltaZ;
  wheelEvent.mDeltaMode = aDeltaMode;
  wheelEvent.mIsMomentum = (aOptions & WHEEL_EVENT_CAUSED_BY_MOMENTUM) != 0;
  wheelEvent.mIsNoLineOrPageDelta =
      (aOptions & WHEEL_EVENT_CAUSED_BY_NO_LINE_OR_PAGE_DELTA_DEVICE) != 0;
  wheelEvent.mCustomizedByUserPrefs =
      (aOptions & WHEEL_EVENT_CUSTOMIZED_BY_USER_PREFS) != 0;
  wheelEvent.mLineOrPageDeltaX = aLineOrPageDeltaX;
  wheelEvent.mLineOrPageDeltaY = aLineOrPageDeltaY;

  nsPresContext* presContext = GetPresContext();
  NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);

  wheelEvent.mRefPoint =
      nsContentUtils::ToWidgetPoint(CSSPoint(aX, aY), offset, presContext);

  if (StaticPrefs::test_events_async_enabled()) {
    widget->DispatchInputEvent(&wheelEvent);
  } else {
    nsEventStatus status = nsEventStatus_eIgnore;
    nsresult rv = widget->DispatchEvent(&wheelEvent, status);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  if (widget->AsyncPanZoomEnabled()) {
    // Computing overflow deltas is not compatible with APZ, so if APZ is
    // enabled, we skip testing it.
    return NS_OK;
  }

  bool failedX = false;
  if ((aOptions & WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_X_ZERO) &&
      wheelEvent.mOverflowDeltaX != 0) {
    failedX = true;
  }
  if ((aOptions & WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_X_POSITIVE) &&
      wheelEvent.mOverflowDeltaX <= 0) {
    failedX = true;
  }
  if ((aOptions & WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_X_NEGATIVE) &&
      wheelEvent.mOverflowDeltaX >= 0) {
    failedX = true;
  }
  bool failedY = false;
  if ((aOptions & WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_Y_ZERO) &&
      wheelEvent.mOverflowDeltaY != 0) {
    failedY = true;
  }
  if ((aOptions & WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_Y_POSITIVE) &&
      wheelEvent.mOverflowDeltaY <= 0) {
    failedY = true;
  }
  if ((aOptions & WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_Y_NEGATIVE) &&
      wheelEvent.mOverflowDeltaY >= 0) {
    failedY = true;
  }

#ifdef DEBUG
  if (failedX) {
    nsPrintfCString debugMsg("SendWheelEvent(): unexpected mOverflowDeltaX: %f",
                             wheelEvent.mOverflowDeltaX);
    NS_WARNING(debugMsg.get());
  }
  if (failedY) {
    nsPrintfCString debugMsg("SendWheelEvent(): unexpected mOverflowDeltaY: %f",
                             wheelEvent.mOverflowDeltaY);
    NS_WARNING(debugMsg.get());
  }
#endif

  return (!failedX && !failedY) ? NS_OK : NS_ERROR_FAILURE;
}

NS_IMETHODIMP
nsDOMWindowUtils::SendTouchEvent(
    const nsAString& aType, const nsTArray<uint32_t>& aIdentifiers,
    const nsTArray<int32_t>& aXs, const nsTArray<int32_t>& aYs,
    const nsTArray<uint32_t>& aRxs, const nsTArray<uint32_t>& aRys,
    const nsTArray<float>& aRotationAngles, const nsTArray<float>& aForces,
    const nsTArray<int32_t>& aTiltXs, const nsTArray<int32_t>& aTiltYs,
    const nsTArray<int32_t>& aTwists, int32_t aModifiers,
    bool aIgnoreRootScrollFrame, bool* aPreventDefault) {
  return SendTouchEventCommon(aType, aIdentifiers, aXs, aYs, aRxs, aRys,
                              aRotationAngles, aForces, aTiltXs, aTiltYs,
                              aTwists, aModifiers, aIgnoreRootScrollFrame,
                              /* aIsPen */ false,
                              /* aToWindow */ false, aPreventDefault);
}

NS_IMETHODIMP
nsDOMWindowUtils::SendTouchEventAsPen(
    const nsAString& aType, uint32_t aIdentifier, int32_t aX, int32_t aY,
    uint32_t aRx, uint32_t aRy, float aRotationAngle, float aForce,
    int32_t aTiltX, int32_t aTiltY, int32_t aTwist, int32_t aModifier,
    bool aIgnoreRootScrollFrame, bool* aPreventDefault) {
  return SendTouchEventCommon(
      aType, nsTArray{aIdentifier}, nsTArray{aX}, nsTArray{aY}, nsTArray{aRx},
      nsTArray{aRy}, nsTArray{aRotationAngle}, nsTArray{aForce},
      nsTArray{aTiltX}, nsTArray{aTiltY}, nsTArray{aTwist}, aModifier,
      aIgnoreRootScrollFrame,
      /* aIsPen */ true,
      /* aToWindow */ false, aPreventDefault);
}

NS_IMETHODIMP
nsDOMWindowUtils::SendTouchEventToWindow(
    const nsAString& aType, const nsTArray<uint32_t>& aIdentifiers,
    const nsTArray<int32_t>& aXs, const nsTArray<int32_t>& aYs,
    const nsTArray<uint32_t>& aRxs, const nsTArray<uint32_t>& aRys,
    const nsTArray<float>& aRotationAngles, const nsTArray<float>& aForces,
    const nsTArray<int32_t>& aTiltXs, const nsTArray<int32_t>& aTiltYs,
    const nsTArray<int32_t>& aTwists, int32_t aModifiers,
    bool aIgnoreRootScrollFrame, bool* aPreventDefault) {
  return SendTouchEventCommon(aType, aIdentifiers, aXs, aYs, aRxs, aRys,
                              aRotationAngles, aForces, aTiltXs, aTiltYs,
                              aTwists, aModifiers, aIgnoreRootScrollFrame,
                              /* aIsPen */ false,
                              /* aToWindow */ true, aPreventDefault);
}

nsresult nsDOMWindowUtils::SendTouchEventCommon(
    const nsAString& aType, const nsTArray<uint32_t>& aIdentifiers,
    const nsTArray<int32_t>& aXs, const nsTArray<int32_t>& aYs,
    const nsTArray<uint32_t>& aRxs, const nsTArray<uint32_t>& aRys,
    const nsTArray<float>& aRotationAngles, const nsTArray<float>& aForces,
    const nsTArray<int32_t>& aTiltXs, const nsTArray<int32_t>& aTiltYs,
    const nsTArray<int32_t>& aTwists, int32_t aModifiers,
    bool aIgnoreRootScrollFrame, bool aIsPen, bool aToWindow,
    bool* aPreventDefault) {
  // get the widget to send the event to
  nsPoint offset;
  nsCOMPtr<nsIWidget> widget = GetWidget(&offset);
  if (!widget) {
    return NS_ERROR_NULL_POINTER;
  }
  EventMessage msg;
  if (aType.EqualsLiteral("touchstart")) {
    msg = eTouchStart;
  } else if (aType.EqualsLiteral("touchmove")) {
    msg = eTouchMove;
  } else if (aType.EqualsLiteral("touchend")) {
    msg = eTouchEnd;
  } else if (aType.EqualsLiteral("touchcancel")) {
    msg = eTouchCancel;
  } else {
    return NS_ERROR_UNEXPECTED;
  }
  WidgetTouchEvent event(true, msg, widget);
  event.mFlags.mIsSynthesizedForTests = true;
  event.mModifiers = nsContentUtils::GetWidgetModifiers(aModifiers);
  if (aIsPen) {
    event.mInputSource = MouseEvent_Binding::MOZ_SOURCE_PEN;
  }

  nsPresContext* presContext = GetPresContext();
  if (!presContext) {
    return NS_ERROR_FAILURE;
  }
  uint32_t count = aIdentifiers.Length();
  if (aXs.Length() != count || aYs.Length() != count ||
      aRxs.Length() != count || aRys.Length() != count ||
      aRotationAngles.Length() != count || aForces.Length() != count) {
    return NS_ERROR_INVALID_ARG;
  }
  event.mTouches.SetCapacity(count);
  for (uint32_t i = 0; i < count; ++i) {
    LayoutDeviceIntPoint pt = nsContentUtils::ToWidgetPoint(
        CSSPoint(aXs[i], aYs[i]), offset, presContext);
    LayoutDeviceIntPoint radius = LayoutDeviceIntPoint::FromAppUnitsRounded(
        CSSPoint::ToAppUnits(CSSPoint(aRxs[i], aRys[i])),
        presContext->AppUnitsPerDevPixel());

    RefPtr<Touch> t = new Touch(aIdentifiers[i], pt, radius, aRotationAngles[i],
                                aForces[i], aTiltXs[i], aTiltYs[i], aTwists[i]);

    event.mTouches.AppendElement(t);
  }

  nsEventStatus status = nsEventStatus_eIgnore;
  if (aToWindow) {
    RefPtr<PresShell> presShell;
    nsView* view = nsContentUtils::GetViewToDispatchEvent(
        presContext, getter_AddRefs(presShell));
    if (!presShell || !view) {
      return NS_ERROR_FAILURE;
    }
    *aPreventDefault = (status == nsEventStatus_eConsumeNoDefault);
    return presShell->HandleEvent(view->GetFrame(), &event, false, &status);
  }

  if (StaticPrefs::test_events_async_enabled()) {
    status = widget->DispatchInputEvent(&event).mContentStatus;
  } else {
    nsresult rv = widget->DispatchEvent(&event, status);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  if (aPreventDefault) {
    *aPreventDefault = (status == nsEventStatus_eConsumeNoDefault);
  }
  return NS_OK;
}

static_assert(
    static_cast<uint32_t>(nsIWidget::Modifiers::CAPS_LOCK) ==
        static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_CAPS_LOCK),
    "Need to sync CapsLock value between nsIWidget::Modifiers and "
    "nsIDOMWindowUtils");
static_assert(
    static_cast<uint32_t>(nsIWidget::Modifiers::NUM_LOCK) ==
        static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_NUM_LOCK),
    "Need to sync NumLock value between nsIWidget::Modifiers and "
    "nsIDOMWindowUtils");
static_assert(
    static_cast<uint32_t>(nsIWidget::Modifiers::SHIFT_L) ==
        static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_SHIFT_LEFT),
    "Need to sync ShiftLeft value between nsIWidget::Modifiers and "
    "nsIDOMWindowUtils");
static_assert(
    static_cast<uint32_t>(nsIWidget::Modifiers::SHIFT_R) ==
        static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_SHIFT_RIGHT),
    "Need to sync ShiftRight value between nsIWidget::Modifiers and "
    "nsIDOMWindowUtils");
static_assert(
    static_cast<uint32_t>(nsIWidget::Modifiers::CTRL_L) ==
        static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_CONTROL_LEFT),
    "Need to sync ControlLeft value between nsIWidget::Modifiers and "
    "nsIDOMWindowUtils");
static_assert(
    static_cast<uint32_t>(nsIWidget::Modifiers::CTRL_R) ==
        static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_CONTROL_RIGHT),
    "Need to sync ControlRight value between nsIWidget::Modifiers "
    "and nsIDOMWindowUtils");
static_assert(
    static_cast<uint32_t>(nsIWidget::Modifiers::ALT_L) ==
        static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_ALT_LEFT),
    "Need to sync AltLeft value between nsIWidget::Modifiers and "
    "nsIDOMWindowUtils");
static_assert(
    static_cast<uint32_t>(nsIWidget::Modifiers::ALT_R) ==
        static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_ALT_RIGHT),
    "Need to sync AltRight value between nsIWidget::Modifiers and "
    "nsIDOMWindowUtils");
static_assert(
    static_cast<uint32_t>(nsIWidget::Modifiers::COMMAND_L) ==
        static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_COMMAND_LEFT),
    "Need to sync CommandLeft value between nsIWidget::Modifiers and "
    "nsIDOMWindowUtils");
static_assert(
    static_cast<uint32_t>(nsIWidget::Modifiers::COMMAND_R) ==
        static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_COMMAND_RIGHT),
    "Need to sync CommandRight value between nsIWidget::Modifiers "
    "and nsIDOMWindowUtils");
static_assert(
    static_cast<uint32_t>(nsIWidget::Modifiers::HELP) ==
        static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_HELP),
    "Need to sync Help value between nsIWidget::Modifiers and "
    "nsIDOMWindowUtils");
static_assert(
    static_cast<uint32_t>(nsIWidget::Modifiers::ALTGRAPH) ==
        static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_ALT_GRAPH),
    "Need to sync AltGraph value between nsIWidget::Modifiers and "
    "nsIDOMWindowUtils");
static_assert(
    static_cast<uint32_t>(nsIWidget::Modifiers::FUNCTION) ==
        static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_FUNCTION),
    "Need to sync Function value between nsIWidget::Modifiers and "
    "nsIDOMWindowUtils");
static_assert(static_cast<uint32_t>(nsIWidget::Modifiers::NUMERIC_KEY_PAD) ==
                  static_cast<uint32_t>(
                      nsIDOMWindowUtils::NATIVE_MODIFIER_NUMERIC_KEY_PAD),
              "Need to sync NumericKeyPad value between nsIWidget::Modifiers "
              "and nsIDOMWindowUtils");

static nsIWidget::Modifiers GetWidgetModifiers(uint32_t aNativeModifiers) {
  nsIWidget::Modifiers widgetModifiers = static_cast<nsIWidget::Modifiers>(
      aNativeModifiers &
      (nsIWidget::Modifiers::CAPS_LOCK | nsIWidget::Modifiers::NUM_LOCK |
       nsIWidget::Modifiers::SHIFT_L | nsIWidget::Modifiers::SHIFT_R |
       nsIWidget::Modifiers::CTRL_L | nsIWidget::Modifiers::CTRL_R |
       nsIWidget::Modifiers::ALT_L | nsIWidget::Modifiers::ALT_R |
       nsIWidget::Modifiers::COMMAND_L | nsIWidget::Modifiers::COMMAND_R |
       nsIWidget::Modifiers::HELP | nsIWidget::Modifiers::ALTGRAPH |
       nsIWidget::Modifiers::FUNCTION | nsIWidget::Modifiers::NUMERIC_KEY_PAD));
  NS_ASSERTION(static_cast<uint32_t>(widgetModifiers) == aNativeModifiers,
               "Invalid value is specified to the native modifiers");
  return widgetModifiers;
}

NS_IMETHODIMP
nsDOMWindowUtils::SendNativeKeyEvent(int32_t aNativeKeyboardLayout,
                                     int32_t aNativeKeyCode,
                                     uint32_t aModifiers,
                                     const nsAString& aCharacters,
                                     const nsAString& aUnmodifiedCharacters,
                                     nsIObserver* aObserver) {
  // get the widget to send the event to
  nsCOMPtr<nsIWidget> widget = GetWidget();
  if (!widget) return NS_ERROR_FAILURE;

  NS_DispatchToMainThread(NativeInputRunnable::Create(
      NewRunnableMethod<int32_t, int32_t, uint32_t, nsString, nsString,
                        nsIObserver*>(
          "nsIWidget::SynthesizeNativeKeyEvent", widget,
          &nsIWidget::SynthesizeNativeKeyEvent, aNativeKeyboardLayout,
          aNativeKeyCode, static_cast<uint32_t>(GetWidgetModifiers(aModifiers)),
          aCharacters, aUnmodifiedCharacters, aObserver)));
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::SendNativeMouseEvent(int32_t aScreenX, int32_t aScreenY,
                                       uint32_t aNativeMessage, int16_t aButton,
                                       uint32_t aModifierFlags,
                                       Element* aElementOnWidget,
                                       nsIObserver* aObserver) {
  // get the widget to send the event to
  nsCOMPtr<nsIWidget> widget = GetWidgetForElement(aElementOnWidget);
  if (!widget) {
    return NS_ERROR_FAILURE;
  }

  nsIWidget::NativeMouseMessage message;
  switch (aNativeMessage) {
    case NATIVE_MOUSE_MESSAGE_BUTTON_DOWN:
      message = nsIWidget::NativeMouseMessage::ButtonDown;
      break;
    case NATIVE_MOUSE_MESSAGE_BUTTON_UP:
      message = nsIWidget::NativeMouseMessage::ButtonUp;
      break;
    case NATIVE_MOUSE_MESSAGE_MOVE:
      message = nsIWidget::NativeMouseMessage::Move;
      break;
    case NATIVE_MOUSE_MESSAGE_ENTER_WINDOW:
      message = nsIWidget::NativeMouseMessage::EnterWindow;
      break;
    case NATIVE_MOUSE_MESSAGE_LEAVE_WINDOW:
      message = nsIWidget::NativeMouseMessage::LeaveWindow;
      break;
    default:
      return NS_ERROR_INVALID_ARG;
  }

  NS_DispatchToMainThread(NativeInputRunnable::Create(
      NewRunnableMethod<LayoutDeviceIntPoint, nsIWidget::NativeMouseMessage,
                        MouseButton, nsIWidget::Modifiers, nsIObserver*>(
          "nsIWidget::SynthesizeNativeMouseEvent", widget,
          &nsIWidget::SynthesizeNativeMouseEvent,
          LayoutDeviceIntPoint(aScreenX, aScreenY), message,
          static_cast<MouseButton>(aButton), GetWidgetModifiers(aModifierFlags),
          aObserver)));
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::SendNativeMouseScrollEvent(
    int32_t aScreenX, int32_t aScreenY, uint32_t aNativeMessage, double aDeltaX,
    double aDeltaY, double aDeltaZ, uint32_t aModifierFlags,
    uint32_t aAdditionalFlags, Element* aElement, nsIObserver* aObserver) {
  // get the widget to send the event to
  nsCOMPtr<nsIWidget> widget = GetWidgetForElement(aElement);
  if (!widget) {
    return NS_ERROR_FAILURE;
  }

  NS_DispatchToMainThread(NativeInputRunnable::Create(
      NewRunnableMethod<mozilla::LayoutDeviceIntPoint, uint32_t, doubledouble,
                        double, uint32_t, uint32_t, nsIObserver*>(
          "nsIWidget::SynthesizeNativeMouseScrollEvent", widget,
          &nsIWidget::SynthesizeNativeMouseScrollEvent,
          LayoutDeviceIntPoint(aScreenX, aScreenY), aNativeMessage, aDeltaX,
          aDeltaY, aDeltaZ, aModifierFlags, aAdditionalFlags, aObserver)));
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::SendNativeTouchPoint(uint32_t aPointerId,
                                       uint32_t aTouchState, int32_t aScreenX,
                                       int32_t aScreenY, double aPressure,
                                       uint32_t aOrientation,
                                       nsIObserver* aObserver,
                                       Element* aElement) {
  // FYI: This was designed for automated tests, but currently, this is used by
  //      DevTools to emulate touch events from mouse events in the responsive
  //      design mode.

  nsCOMPtr<nsIWidget> widget = GetWidgetForElement(aElement);
  if (!widget) {
    return NS_ERROR_FAILURE;
  }

  if (aPressure < 0 || aPressure > 1 || aOrientation > 359) {
    return NS_ERROR_INVALID_ARG;
  }

  NS_DispatchToMainThread(NativeInputRunnable::Create(
      NewRunnableMethod<uint32_t, nsIWidget::TouchPointerState,
                        LayoutDeviceIntPoint, double, uint32_t, nsIObserver*>(
          "nsIWidget::SynthesizeNativeTouchPoint", widget,
          &nsIWidget::SynthesizeNativeTouchPoint, aPointerId,
          (nsIWidget::TouchPointerState)aTouchState,
          LayoutDeviceIntPoint(aScreenX, aScreenY), aPressure, aOrientation,
          aObserver)));
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::SendNativeTouchpadPinch(uint32_t aEventPhase, float aScale,
                                          int32_t aScreenX, int32_t aScreenY,
                                          int32_t aModifierFlags) {
  nsCOMPtr<nsIWidget> widget = GetWidget();
  if (!widget) {
    return NS_ERROR_FAILURE;
  }
  NS_DispatchToMainThread(NativeInputRunnable::Create(
      NewRunnableMethod<nsIWidget::TouchpadGesturePhase, float,
                        LayoutDeviceIntPoint, int32_t>(
          "nsIWidget::SynthesizeNativeTouchPadPinch", widget,
          &nsIWidget::SynthesizeNativeTouchPadPinch,
          (nsIWidget::TouchpadGesturePhase)aEventPhase, aScale,
          LayoutDeviceIntPoint(aScreenX, aScreenY), aModifierFlags)));
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::SendNativeTouchTap(int32_t aScreenX, int32_t aScreenY,
                                     bool aLongTap, nsIObserver* aObserver) {
  nsCOMPtr<nsIWidget> widget = GetWidget();
  if (!widget) {
    return NS_ERROR_FAILURE;
  }

  NS_DispatchToMainThread(NativeInputRunnable::Create(
      NewRunnableMethod<LayoutDeviceIntPoint, bool, nsIObserver*>(
          "nsIWidget::SynthesizeNativeTouchTap", widget,
          &nsIWidget::SynthesizeNativeTouchTap,
          LayoutDeviceIntPoint(aScreenX, aScreenY), aLongTap, aObserver)));
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::SendNativePenInput(uint32_t aPointerId,
                                     uint32_t aPointerState, int32_t aScreenX,
                                     int32_t aScreenY, double aPressure,
                                     uint32_t aRotation, int32_t aTiltX,
                                     int32_t aTiltY, int32_t aButton,
                                     nsIObserver* aObserver,
                                     Element* aElement) {
  nsCOMPtr<nsIWidget> widget = GetWidgetForElement(aElement);
  if (!widget) {
    return NS_ERROR_FAILURE;
  }

  if (aPressure < 0 || aPressure > 1 || aRotation > 359 || aTiltX < -90 ||
      aTiltX > 90 || aTiltY < -90 || aTiltY > 90) {
    return NS_ERROR_INVALID_ARG;
  }

  NS_DispatchToMainThread(NativeInputRunnable::Create(
      NewRunnableMethod<uint32_t, nsIWidget::TouchPointerState,
                        LayoutDeviceIntPoint, double, uint32_t, int32_t,
                        int32_t, int32_t, nsIObserver*>(
          "nsIWidget::SynthesizeNativePenInput", widget,
          &nsIWidget::SynthesizeNativePenInput, aPointerId,
          (nsIWidget::TouchPointerState)aPointerState,
          LayoutDeviceIntPoint(aScreenX, aScreenY), aPressure, aRotation,
          aTiltX, aTiltY, aButton, aObserver)));
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::SendNativeTouchpadDoubleTap(int32_t aScreenX,
                                              int32_t aScreenY,
                                              int32_t aModifierFlags) {
  nsCOMPtr<nsIWidget> widget = GetWidget();
  if (!widget) {
    return NS_ERROR_FAILURE;
  }

  MOZ_ASSERT(aModifierFlags >= 0);
  NS_DispatchToMainThread(NativeInputRunnable::Create(
      NewRunnableMethod<LayoutDeviceIntPoint, uint32_t>(
          "nsIWidget::SynthesizeNativeTouchpadDoubleTap", widget,
          &nsIWidget::SynthesizeNativeTouchpadDoubleTap,
          LayoutDeviceIntPoint(aScreenX, aScreenY), aModifierFlags)));
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::SendNativeTouchpadPan(uint32_t aEventPhase, int32_t aScreenX,
                                        int32_t aScreenY, double aDeltaX,
                                        double aDeltaY, int32_t aModifierFlags,
                                        nsIObserver* aObserver) {
  nsCOMPtr<nsIWidget> widget = GetWidget();
  if (!widget) {
    return NS_ERROR_FAILURE;
  }

  MOZ_ASSERT(aModifierFlags >= 0);
  NS_DispatchToMainThread(NativeInputRunnable::Create(
      NewRunnableMethod<nsIWidget::TouchpadGesturePhase, LayoutDeviceIntPoint,
                        doubledouble, uint32_t, nsIObserver*>(
          "nsIWidget::SynthesizeNativeTouchpadPan", widget,
          &nsIWidget::SynthesizeNativeTouchpadPan,
          (nsIWidget::TouchpadGesturePhase)aEventPhase,
          LayoutDeviceIntPoint(aScreenX, aScreenY), aDeltaX, aDeltaY,
          aModifierFlags, aObserver)));
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::SuppressAnimation(bool aSuppress) {
  nsIWidget* widget = GetWidget();
  if (widget) {
    widget->SuppressAnimation(aSuppress);
  }
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::ClearSharedStyleSheetCache() {
  SharedStyleSheetCache::Clear();
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::ClearSharedScriptCache() {
  SharedScriptCache::Clear();
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetParsedStyleSheets(uint32_t* aSheets) {
  RefPtr<Document> doc = GetDocument();
  if (!doc) {
    return NS_ERROR_UNEXPECTED;
  }

  *aSheets = doc->CSSLoader()->ParsedSheetCount();
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::ClearNativeTouchSequence(nsIObserver* aObserver) {
  nsCOMPtr<nsIWidget> widget = GetWidget();
  if (!widget) {
    return NS_ERROR_FAILURE;
  }

  NS_DispatchToMainThread(
      NativeInputRunnable::Create(NewRunnableMethod<nsIObserver*>(
          "nsIWidget::ClearNativeTouchSequence", widget,
          &nsIWidget::ClearNativeTouchSequence, aObserver)));
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::ActivateNativeMenuItemAt(const nsAString& indexString) {
  // get the widget to send the event to
  nsCOMPtr<nsIWidget> widget = GetWidget();
  if (!widget) return NS_ERROR_FAILURE;

  return widget->ActivateNativeMenuItemAt(indexString);
}

NS_IMETHODIMP
nsDOMWindowUtils::ForceUpdateNativeMenuAt(const nsAString& indexString) {
  // get the widget to send the event to
  nsCOMPtr<nsIWidget> widget = GetWidget();
  if (!widget) return NS_ERROR_FAILURE;

  return widget->ForceUpdateNativeMenuAt(indexString);
}

NS_IMETHODIMP
nsDOMWindowUtils::GetSelectionAsPlaintext(nsAString& aResult) {
  // Get the widget to send the event to.
  nsCOMPtr<nsIWidget> widget = GetWidget();
  if (!widget) {
    return NS_ERROR_FAILURE;
  }

  return widget->GetSelectionAsPlaintext(aResult);
}

nsIWidget* nsDOMWindowUtils::GetWidget(nsPoint* aOffset) {
  nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
  if (window) {
    nsIDocShell* docShell = window->GetDocShell();
    if (docShell) {
      return nsContentUtils::GetWidget(docShell->GetPresShell(), aOffset);
    }
  }

  return nullptr;
}

nsIWidget* nsDOMWindowUtils::GetWidgetForElement(Element* aElement) {
  if (!aElement) {
    return GetWidget();
  }
  if (Document* doc = aElement->GetUncomposedDoc()) {
    if (PresShell* presShell = doc->GetPresShell()) {
      nsIFrame* frame = aElement->GetPrimaryFrame();
      if (!frame) {
        frame = presShell->GetRootFrame();
      }
      if (frame) {
        return frame->GetNearestWidget();
      }
    }
  }

  return nullptr;
}

NS_IMETHODIMP
nsDOMWindowUtils::GarbageCollect(nsICycleCollectorListener* aListener) {
  AUTO_PROFILER_LABEL("nsDOMWindowUtils::GarbageCollect", GCCC);

  nsJSContext::GarbageCollectNow(JS::GCReason::DOM_UTILS);
  nsJSContext::CycleCollectNow(CCReason::API, aListener);

  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::CycleCollect(nsICycleCollectorListener* aListener) {
  nsJSContext::CycleCollectNow(CCReason::API, aListener);
  return NS_OK;
}

static bool ParseGCReason(const nsACString& aStr, JS::GCReason* aReason,
                          JS::GCReason aDefault) {
  if (aStr.IsEmpty()) {
    *aReason = aDefault;
    return true;
  }
#define CHECK_REASON(name, _)         \
  if (aStr.EqualsIgnoreCase(#name)) { \
    *aReason = JS::GCReason::name;    \
    return true;                      \
  }
  GCREASONS(CHECK_REASON);
  return false;
}

NS_IMETHODIMP
nsDOMWindowUtils::RunNextCollectorTimer(const nsACString& aReason) {
  JS::GCReason reason;
  if (!ParseGCReason(aReason, &reason, JS::GCReason::DOM_WINDOW_UTILS)) {
    return NS_ERROR_INVALID_ARG;
  }

  nsJSContext::RunNextCollectorTimer(reason);

  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::PokeGC(const nsACString& aReason) {
  JS::GCReason reason;
  if (!ParseGCReason(aReason, &reason, JS::GCReason::DOM_WINDOW_UTILS)) {
    return NS_ERROR_INVALID_ARG;
  }

  nsJSContext::PokeGC(reason, nullptr);

  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::SendSimpleGestureEvent(const nsAString& aType, float aX,
                                         float aY, uint32_t aDirection,
                                         double aDelta, int32_t aModifiers,
                                         uint32_t aClickCount) {
  // get the widget to send the event to
  nsPoint offset;
  nsCOMPtr<nsIWidget> widget = GetWidget(&offset);
  if (!widget) return NS_ERROR_FAILURE;

  EventMessage msg;
  if (aType.EqualsLiteral("MozSwipeGestureMayStart")) {
    msg = eSwipeGestureMayStart;
  } else if (aType.EqualsLiteral("MozSwipeGestureStart")) {
    msg = eSwipeGestureStart;
  } else if (aType.EqualsLiteral("MozSwipeGestureUpdate")) {
    msg = eSwipeGestureUpdate;
  } else if (aType.EqualsLiteral("MozSwipeGestureEnd")) {
    msg = eSwipeGestureEnd;
  } else if (aType.EqualsLiteral("MozSwipeGesture")) {
    msg = eSwipeGesture;
  } else if (aType.EqualsLiteral("MozMagnifyGestureStart")) {
    msg = eMagnifyGestureStart;
  } else if (aType.EqualsLiteral("MozMagnifyGestureUpdate")) {
    msg = eMagnifyGestureUpdate;
  } else if (aType.EqualsLiteral("MozMagnifyGesture")) {
    msg = eMagnifyGesture;
  } else if (aType.EqualsLiteral("MozRotateGestureStart")) {
    msg = eRotateGestureStart;
  } else if (aType.EqualsLiteral("MozRotateGestureUpdate")) {
    msg = eRotateGestureUpdate;
  } else if (aType.EqualsLiteral("MozRotateGesture")) {
    msg = eRotateGesture;
  } else if (aType.EqualsLiteral("MozTapGesture")) {
    msg = eTapGesture;
  } else if (aType.EqualsLiteral("MozPressTapGesture")) {
    msg = ePressTapGesture;
  } else if (aType.EqualsLiteral("MozEdgeUIStarted")) {
    msg = eEdgeUIStarted;
  } else if (aType.EqualsLiteral("MozEdgeUICanceled")) {
    msg = eEdgeUICanceled;
  } else if (aType.EqualsLiteral("MozEdgeUICompleted")) {
    msg = eEdgeUICompleted;
  } else {
    return NS_ERROR_FAILURE;
  }

  WidgetSimpleGestureEvent event(true, msg, widget);
  event.mModifiers = nsContentUtils::GetWidgetModifiers(aModifiers);
  event.mDirection = aDirection;
  event.mDelta = aDelta;
  event.mClickCount = aClickCount;

  nsPresContext* presContext = GetPresContext();
  if (!presContext) return NS_ERROR_FAILURE;

  event.mRefPoint =
      nsContentUtils::ToWidgetPoint(CSSPoint(aX, aY), offset, presContext);

  nsEventStatus status;
  return widget->DispatchEvent(&event, status);
}

NS_IMETHODIMP
nsDOMWindowUtils::ElementFromPoint(float aX, float aY,
                                   bool aIgnoreRootScrollFrame,
                                   bool aFlushLayout, Element** aReturn) {
  nsCOMPtr<Document> doc = GetDocument();
  NS_ENSURE_STATE(doc);

  RefPtr<Element> el = doc->ElementFromPointHelper(
      aX, aY, aIgnoreRootScrollFrame, aFlushLayout, ViewportType::Layout);
  el.forget(aReturn);
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::NodesFromRect(float aX, float aY, float aTopSize,
                                float aRightSize, float aBottomSize,
                                float aLeftSize, bool aIgnoreRootScrollFrame,
                                bool aFlushLayout, bool aOnlyVisible,
                                float aVisibleThreshold,
                                nsINodeList** aReturn) {
  RefPtr<Document> doc = GetDocument();
  NS_ENSURE_STATE(doc);

  auto list = MakeRefPtr<nsSimpleContentList>(doc);

  // The visible threshold was omitted or given a zero value (which makes no
  // sense), so give a reasonable default.
  if (aVisibleThreshold == 0.0f) {
    aVisibleThreshold = 1.0f;
  }

  AutoTArray<RefPtr<nsINode>, 8> nodes;
  doc->NodesFromRect(aX, aY, aTopSize, aRightSize, aBottomSize, aLeftSize,
                     aIgnoreRootScrollFrame, aFlushLayout, aOnlyVisible,
                     aVisibleThreshold, nodes);
  list->SetCapacity(nodes.Length());
  for (auto& node : nodes) {
    list->AppendElement(node->AsContent());
  }

  list.forget(aReturn);
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetTranslationNodes(nsINode* aRoot,
                                      nsITranslationNodeList** aRetVal) {
  NS_ENSURE_ARG_POINTER(aRetVal);
  nsCOMPtr<nsIContent> root = do_QueryInterface(aRoot);
  NS_ENSURE_STATE(root);
  nsCOMPtr<Document> doc = GetDocument();
  NS_ENSURE_STATE(doc);

  if (root->OwnerDoc() != doc) {
    return NS_ERROR_DOM_WRONG_DOCUMENT_ERR;
  }

  nsTHashSet<nsIContent*> translationNodesHash(500);
  RefPtr<nsTranslationNodeList> list = new nsTranslationNodeList;

  uint32_t limit = 15000;

  // We begin iteration with content->GetNextNode because we want to explicitly
  // skip the root tag from being a translation node.
  nsIContent* content = root;
  while ((limit > 0) && (content = content->GetNextNode(root))) {
    if (!content->IsHTMLElement()) {
      continue;
    }

    // Skip elements that usually contain non-translatable text content.
    if (content->IsAnyOfHTMLElements(nsGkAtoms::script, nsGkAtoms::iframe,
                                     nsGkAtoms::frameset, nsGkAtoms::frame,
                                     nsGkAtoms::code, nsGkAtoms::noscript,
                                     nsGkAtoms::style)) {
      continue;
    }

    // An element is a translation node if it contains
    // at least one text node that has meaningful data
    // for translation
    for (nsIContent* child = content->GetFirstChild(); child;
         child = child->GetNextSibling()) {
      if (child->IsText() && child->GetAsText()->HasTextForTranslation()) {
        translationNodesHash.Insert(content);

        nsIFrame* frame = content->GetPrimaryFrame();
        bool isTranslationRoot = frame && frame->IsBlockFrameOrSubclass();
        if (!isTranslationRoot) {
          // If an element is not a block element, it still
          // can be considered a translation root if the parent
          // of this element didn't make into the list of nodes
          // to be translated.
          bool parentInList = false;
          nsIContent* parent = content->GetParent();
          if (parent) {
            parentInList = translationNodesHash.Contains(parent);
          }
          isTranslationRoot = !parentInList;
        }

        list->AppendElement(content, isTranslationRoot);
        --limit;
        break;
      }
    }
  }

  *aRetVal = list.forget().take();
  return NS_OK;
}

static already_AddRefed<DataSourceSurface> CanvasToDataSourceSurface(
    HTMLCanvasElement* aCanvas) {
  MOZ_ASSERT(aCanvas);
  SurfaceFromElementResult result = nsLayoutUtils::SurfaceFromElement(aCanvas);

  MOZ_ASSERT(result.GetSourceSurface());
  return result.GetSourceSurface()->GetDataSurface();
}

NS_IMETHODIMP
nsDOMWindowUtils::CompareCanvases(nsISupports* aCanvas1, nsISupports* aCanvas2,
                                  uint32_t* aMaxDifference, uint32_t* retVal) {
  nsCOMPtr<nsIContent> contentCanvas1 = do_QueryInterface(aCanvas1);
  nsCOMPtr<nsIContent> contentCanvas2 = do_QueryInterface(aCanvas2);
  auto* canvas1 = HTMLCanvasElement::FromNodeOrNull(contentCanvas1);
  auto* canvas2 = HTMLCanvasElement::FromNodeOrNull(contentCanvas2);

  if (NS_WARN_IF(!canvas1) || NS_WARN_IF(!canvas2)) {
    return NS_ERROR_FAILURE;
  }

  RefPtr<DataSourceSurface> img1 = CanvasToDataSourceSurface(canvas1);
  RefPtr<DataSourceSurface> img2 = CanvasToDataSourceSurface(canvas2);

  if (NS_WARN_IF(!img1) || NS_WARN_IF(!img2) ||
      NS_WARN_IF(img1->GetSize() != img2->GetSize())) {
    return NS_ERROR_FAILURE;
  }

  if (img1->Equals(img2)) {
    // They point to the same underlying content.
    return NS_OK;
  }

  DataSourceSurface::ScopedMap map1(img1, DataSourceSurface::READ);
  DataSourceSurface::ScopedMap map2(img2, DataSourceSurface::READ);

  if (NS_WARN_IF(!map1.IsMapped()) || NS_WARN_IF(!map2.IsMapped())) {
    return NS_ERROR_FAILURE;
  }

  int v;
  IntSize size = img1->GetSize();
  int32_t stride1 = map1.GetStride();
  int32_t stride2 = map2.GetStride();

  // we can optimize for the common all-pass case
  if (stride1 == stride2 && stride1 == size.width * 4) {
    v = memcmp(map1.GetData(), map2.GetData(), size.width * size.height * 4);
    if (v == 0) {
      if (aMaxDifference) *aMaxDifference = 0;
      *retVal = 0;
      return NS_OK;
    }
  }

  uint32_t dc = 0;
  uint32_t different = 0;

  for (int j = 0; j < size.height; j++) {
    unsigned char* p1 = map1.GetData() + j * stride1;
    unsigned char* p2 = map2.GetData() + j * stride2;
    v = memcmp(p1, p2, size.width * 4);

    if (v) {
      for (int i = 0; i < size.width; i++) {
        if (*(uint32_t*)p1 != *(uint32_t*)p2) {
          different++;

          dc = std::max((uint32_t)abs(p1[0] - p2[0]), dc);
          dc = std::max((uint32_t)abs(p1[1] - p2[1]), dc);
          dc = std::max((uint32_t)abs(p1[2] - p2[2]), dc);
          dc = std::max((uint32_t)abs(p1[3] - p2[3]), dc);
        }

        p1 += 4;
        p2 += 4;
      }
    }
  }

  if (aMaxDifference) *aMaxDifference = dc;

  *retVal = different;
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetIsMozAfterPaintPending(bool* aResult) {
  NS_ENSURE_ARG_POINTER(aResult);
  *aResult = false;
  nsPresContext* presContext = GetPresContext();
  if (!presContext) return NS_OK;
  *aResult = presContext->IsDOMPaintEventPending();
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetIsWindowFullyOccluded(bool* aResult) {
  NS_ENSURE_ARG_POINTER(aResult);
  *aResult = false;
  if (nsIWidget* widget = GetWidget()) {
    *aResult = widget->IsFullyOccluded();
  }
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetIsCompositorPaused(bool* aResult) {
  NS_ENSURE_ARG_POINTER(aResult);
  *aResult = false;
  CompositorBridgeChild* cbc = GetCompositorBridge();
  if (cbc) {
    *aResult = cbc->IsPaused();
  }
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetIsInputTaskManagerSuspended(bool* aResult) {
  *aResult = InputTaskManager::Get()->IsSuspended();
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::DisableNonTestMouseEvents(bool aDisable) {
  nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
  nsIDocShell* docShell = window->GetDocShell();
  NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
  PresShell* presShell = docShell->GetPresShell();
  NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
  presShell->DisableNonTestMouseEvents(aDisable);
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::SuppressEventHandling(bool aSuppress) {
  nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
  NS_ENSURE_STATE(window);

  if (aSuppress) {
    window->SuppressEventHandling();
  } else {
    window->UnsuppressEventHandling();
  }

  return NS_OK;
}

static nsresult getScrollXYAppUnits(const nsWeakPtr& aWindow, bool aFlushLayout,
                                    nsPoint& aScrollPos) {
  nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(aWindow);
  nsCOMPtr<Document> doc = window ? window->GetExtantDoc() : nullptr;
  NS_ENSURE_STATE(doc);

  if (aFlushLayout) {
    doc->FlushPendingNotifications(FlushType::Layout);
  }

  if (PresShell* presShell = doc->GetPresShell()) {
    ScrollContainerFrame* sf = presShell->GetRootScrollContainerFrame();
    if (sf) {
      aScrollPos = sf->GetScrollPosition();
    }
  }
  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetScrollXY(bool aFlushLayout, int32_t* aScrollX,
                              int32_t* aScrollY) {
  nsPoint scrollPos(0, 0);
  nsresult rv = getScrollXYAppUnits(mWindow, aFlushLayout, scrollPos);
  NS_ENSURE_SUCCESS(rv, rv);
  *aScrollX = nsPresContext::AppUnitsToIntCSSPixels(scrollPos.x);
  *aScrollY = nsPresContext::AppUnitsToIntCSSPixels(scrollPos.y);

  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetScrollXYFloat(bool aFlushLayout, float* aScrollX,
                                   float* aScrollY) {
  nsPoint scrollPos(0, 0);
  nsresult rv = getScrollXYAppUnits(mWindow, aFlushLayout, scrollPos);
  NS_ENSURE_SUCCESS(rv, rv);
  *aScrollX = nsPresContext::AppUnitsToFloatCSSPixels(scrollPos.x);
  *aScrollY = nsPresContext::AppUnitsToFloatCSSPixels(scrollPos.y);

  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::ScrollToVisual(float aOffsetX, float aOffsetY,
                                 int32_t aUpdateType, int32_t aScrollMode) {
  nsCOMPtr<Document> doc = GetDocument();
  NS_ENSURE_STATE(doc);

  nsPresContext* presContext = doc->GetPresContext();
  NS_ENSURE_TRUE(presContext, NS_ERROR_NOT_AVAILABLE);

  // This should only be called on the root content document.
  NS_ENSURE_TRUE(presContext->IsRootContentDocumentCrossProcess(),
                 NS_ERROR_INVALID_ARG);

  FrameMetrics::ScrollOffsetUpdateType updateType;
  switch (aUpdateType) {
    case UPDATE_TYPE_RESTORE:
      updateType = FrameMetrics::eRestore;
      break;
    case UPDATE_TYPE_MAIN_THREAD:
      updateType = FrameMetrics::eMainThread;
      break;
    default:
      return NS_ERROR_INVALID_ARG;
  }

  ScrollMode scrollMode;
  switch (aScrollMode) {
    case SCROLL_MODE_INSTANT:
      scrollMode = ScrollMode::Instant;
      break;
    case SCROLL_MODE_SMOOTH:
      scrollMode = ScrollMode::SmoothMsd;
      break;
    default:
      return NS_ERROR_INVALID_ARG;
  }

  presContext->PresShell()->ScrollToVisual(
      CSSPoint::ToAppUnits(CSSPoint(aOffsetX, aOffsetY)), updateType,
      scrollMode);

  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetVisualViewportOffsetRelativeToLayoutViewport(
    float* aOffsetX, float* aOffsetY) {
  *aOffsetX = 0;
  *aOffsetY = 0;

  nsCOMPtr<Document> doc = GetDocument();
  NS_ENSURE_STATE(doc);

  PresShell* presShell = doc->GetPresShell();
  NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_AVAILABLE);

  nsPoint offset = presShell->GetVisualViewportOffsetRelativeToLayoutViewport();
  *aOffsetX = nsPresContext::AppUnitsToFloatCSSPixels(offset.x);
  *aOffsetY = nsPresContext::AppUnitsToFloatCSSPixels(offset.y);

  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::GetVisualViewportOffset(int32_t* aOffsetX,
                                          int32_t* aOffsetY) {
  *aOffsetX = 0;
  *aOffsetY = 0;

  nsCOMPtr<Document> doc = GetDocument();
  NS_ENSURE_STATE(doc);

  PresShell* presShell = doc->GetPresShell();
  NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_AVAILABLE);

  nsPoint offset = presShell->GetVisualViewportOffset();
  *aOffsetX = nsPresContext::AppUnitsToIntCSSPixels(offset.x);
  *aOffsetY = nsPresContext::AppUnitsToIntCSSPixels(offset.y);

  return NS_OK;
}

NS_IMETHODIMP
nsDOMWindowUtils::TransformRectLayoutToVisual(float aX, float aY, float aWidth,
                                              float aHeight,
                                              DOMRect** aResult) {
  nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
  NS_ENSURE_STATE(window);

  PresShell* presShell = GetPresShell();
  NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_AVAILABLE);

--> --------------------

--> maximum size reached

--> --------------------

98%


¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.71Angebot  Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können  ¤

*Eine klare Vorstellung vom Zielzustand






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.