1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsDOMWindowUtils.h"
9 #include "LayoutConstants.h"
10 #include "MobileViewportManager.h"
11 #include "mozilla/layers/CompositorBridgeChild.h"
12 #include "nsPresContext.h"
14 #include "nsContentList.h"
16 #include "nsQueryContentEventResult.h"
17 #include "nsGlobalWindowOuter.h"
18 #include "nsFocusManager.h"
19 #include "nsFrameManager.h"
20 #include "nsRefreshDriver.h"
21 #include "nsStyleUtil.h"
22 #include "mozilla/Base64.h"
23 #include "mozilla/dom/Animation.h"
24 #include "mozilla/dom/BindingDeclarations.h"
25 #include "mozilla/dom/BlobBinding.h"
26 #include "mozilla/dom/DocumentInlines.h"
27 #include "mozilla/dom/DocumentTimeline.h"
28 #include "mozilla/dom/DOMCollectedFramesBinding.h"
29 #include "mozilla/dom/Event.h"
30 #include "mozilla/dom/Touch.h"
31 #include "mozilla/dom/UserActivation.h"
32 #include "mozilla/EventStateManager.h"
33 #include "mozilla/ServoStyleSet.h"
34 #include "mozilla/SharedStyleSheetCache.h"
35 #include "mozilla/StaticPrefs_test.h"
36 #include "mozilla/InputTaskManager.h"
37 #include "nsIObjectLoadingContent.h"
39 #include "mozilla/layers/APZCCallbackHelper.h"
40 #include "mozilla/layers/PCompositorBridgeTypes.h"
41 #include "mozilla/layers/TouchActionHelper.h"
42 #include "mozilla/media/MediaUtils.h"
43 #include "nsQueryObject.h"
44 #include "CubebDeviceEnumerator.h"
46 #include "nsIScrollableFrame.h"
48 #include "nsContentUtils.h"
50 #include "nsIWidget.h"
51 #include "nsCharsetSource.h"
52 #include "nsJSEnvironment.h"
53 #include "nsJSUtils.h"
54 #include "js/experimental/PCCountProfiling.h" // JS::{Start,Stop}PCCountProfiling, JS::PurgePCCounts, JS::GetPCCountScript{Count,Summary,Contents}
55 #include "js/Object.h" // JS::GetClass
57 #include "mozilla/ChaosMode.h"
58 #include "mozilla/CheckedInt.h"
59 #include "mozilla/MiscEvents.h"
60 #include "mozilla/MouseEvents.h"
61 #include "mozilla/PresShell.h"
62 #include "mozilla/PresShellInlines.h"
63 #include "mozilla/Span.h"
64 #include "mozilla/StaticPrefs_layout.h"
65 #include "mozilla/TextEvents.h"
66 #include "mozilla/TextEventDispatcher.h"
67 #include "mozilla/TouchEvents.h"
69 #include "nsViewManager.h"
71 #include "nsLayoutUtils.h"
72 #include "nsComputedDOMStyle.h"
73 #include "nsCSSProps.h"
74 #include "nsIDocShell.h"
75 #include "mozilla/StyleAnimationValue.h"
76 #include "mozilla/dom/File.h"
77 #include "mozilla/dom/FileBinding.h"
78 #include "mozilla/dom/DOMRect.h"
81 #if defined(MOZ_WIDGET_GTK)
84 # include <gdk/gdkx.h>
85 # include "X11UndefineNone.h"
89 #include "mozilla/dom/AudioDeviceInfo.h"
90 #include "mozilla/dom/Element.h"
91 #include "mozilla/dom/BrowserChild.h"
92 #include "mozilla/dom/IDBFactoryBinding.h"
93 #include "mozilla/dom/IndexedDatabaseManager.h"
94 #include "mozilla/dom/PermissionMessageUtils.h"
95 #include "mozilla/dom/Text.h"
96 #include "mozilla/dom/quota/PersistenceType.h"
97 #include "mozilla/dom/quota/QuotaManager.h"
98 #include "mozilla/dom/ContentChild.h"
99 #include "mozilla/layers/FrameUniformityData.h"
100 #include "nsPrintfCString.h"
101 #include "nsViewportInfo.h"
102 #include "nsIFormControl.h"
103 // #include "nsWidgetsCID.h"
104 #include "nsDisplayList.h"
105 #include "nsROCSSPrimitiveValue.h"
106 #include "nsIBaseWindow.h"
107 #include "nsIDocShellTreeOwner.h"
108 #include "nsIInterfaceRequestorUtils.h"
109 #include "mozilla/Preferences.h"
110 #include "nsContentPermissionHelper.h"
111 #include "nsCSSPseudoElements.h" // for PseudoStyleType
112 #include "nsNetUtil.h"
113 #include "HTMLImageElement.h"
114 #include "HTMLCanvasElement.h"
115 #include "mozilla/css/ImageLoader.h"
116 #include "mozilla/layers/IAPZCTreeManager.h" // for layers::ZoomToRectBehavior
117 #include "mozilla/dom/Document.h"
118 #include "mozilla/dom/Promise.h"
119 #include "mozilla/ServoBindings.h"
120 #include "mozilla/StyleSheetInlines.h"
121 #include "mozilla/gfx/gfxVars.h"
122 #include "mozilla/gfx/GPUProcessManager.h"
123 #include "mozilla/dom/TimeoutManager.h"
124 #include "mozilla/PreloadedStyleSheet.h"
125 #include "mozilla/ProfilerLabels.h"
126 #include "mozilla/ProfilerMarkers.h"
127 #include "mozilla/layers/WebRenderBridgeChild.h"
128 #include "mozilla/layers/WebRenderLayerManager.h"
129 #include "mozilla/DisplayPortUtils.h"
130 #include "mozilla/ResultExtensions.h"
131 #include "mozilla/ViewportUtils.h"
132 #include "mozilla/dom/BrowsingContextGroup.h"
133 #include "mozilla/IMEStateManager.h"
134 #include "mozilla/IMEContentObserver.h"
135 #include "mozilla/WheelHandlingHelper.h"
136 #include "mozilla/AnimatedPropertyID.h"
141 # include <sys/stat.h>
148 using namespace mozilla
;
149 using namespace mozilla::dom
;
150 using namespace mozilla::ipc
;
151 using namespace mozilla::layers
;
152 using namespace mozilla::widget
;
153 using namespace mozilla::gfx
;
157 class OldWindowSize
: public LinkedListElement
<OldWindowSize
> {
159 static void Set(nsIWeakReference
* aWindowRef
, const nsSize
& aSize
) {
160 OldWindowSize
* item
= GetItem(aWindowRef
);
164 item
= new OldWindowSize(aWindowRef
, aSize
);
165 sList
.insertBack(item
);
169 static nsSize
GetAndRemove(nsIWeakReference
* aWindowRef
) {
171 if (OldWindowSize
* item
= GetItem(aWindowRef
)) {
172 result
= item
->mSize
;
179 explicit OldWindowSize(nsIWeakReference
* aWindowRef
, const nsSize
& aSize
)
180 : mWindowRef(aWindowRef
), mSize(aSize
) {}
181 ~OldWindowSize() = default;
184 static OldWindowSize
* GetItem(nsIWeakReference
* aWindowRef
) {
185 OldWindowSize
* item
= sList
.getFirst();
186 while (item
&& item
->mWindowRef
!= aWindowRef
) {
187 item
= item
->getNext();
192 static LinkedList
<OldWindowSize
> sList
;
193 nsWeakPtr mWindowRef
;
199 class NativeInputRunnable final
: public PrioritizableRunnable
{
200 explicit NativeInputRunnable(already_AddRefed
<nsIRunnable
>&& aEvent
);
201 ~NativeInputRunnable() = default;
204 static already_AddRefed
<nsIRunnable
> Create(
205 already_AddRefed
<nsIRunnable
>&& aEvent
);
208 NativeInputRunnable::NativeInputRunnable(already_AddRefed
<nsIRunnable
>&& aEvent
)
209 : PrioritizableRunnable(std::move(aEvent
),
210 nsIRunnablePriority::PRIORITY_INPUT_HIGH
) {}
213 already_AddRefed
<nsIRunnable
> NativeInputRunnable::Create(
214 already_AddRefed
<nsIRunnable
>&& aEvent
) {
215 MOZ_ASSERT(NS_IsMainThread());
216 nsCOMPtr
<nsIRunnable
> event(new NativeInputRunnable(std::move(aEvent
)));
217 return event
.forget();
220 } // unnamed namespace
222 LinkedList
<OldWindowSize
> OldWindowSize::sList
;
224 NS_INTERFACE_MAP_BEGIN(nsDOMWindowUtils
)
225 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDOMWindowUtils
)
226 NS_INTERFACE_MAP_ENTRY(nsIDOMWindowUtils
)
227 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
230 NS_IMPL_ADDREF(nsDOMWindowUtils
)
231 NS_IMPL_RELEASE(nsDOMWindowUtils
)
233 nsDOMWindowUtils::nsDOMWindowUtils(nsGlobalWindowOuter
* aWindow
) {
234 nsCOMPtr
<nsISupports
> supports
= do_QueryObject(aWindow
);
235 mWindow
= do_GetWeakReference(supports
);
238 nsDOMWindowUtils::~nsDOMWindowUtils() { OldWindowSize::GetAndRemove(mWindow
); }
240 nsIDocShell
* nsDOMWindowUtils::GetDocShell() {
241 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
245 return window
->GetDocShell();
248 PresShell
* nsDOMWindowUtils::GetPresShell() {
249 nsIDocShell
* docShell
= GetDocShell();
253 return docShell
->GetPresShell();
256 nsPresContext
* nsDOMWindowUtils::GetPresContext() {
257 nsIDocShell
* docShell
= GetDocShell();
261 return docShell
->GetPresContext();
264 Document
* nsDOMWindowUtils::GetDocument() {
265 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
269 return window
->GetExtantDoc();
272 WebRenderBridgeChild
* nsDOMWindowUtils::GetWebRenderBridge() {
273 if (nsIWidget
* widget
= GetWidget()) {
274 if (WindowRenderer
* renderer
= widget
->GetWindowRenderer()) {
275 if (WebRenderLayerManager
* wr
= renderer
->AsWebRender()) {
276 return wr
->WrBridge();
283 CompositorBridgeChild
* nsDOMWindowUtils::GetCompositorBridge() {
284 if (nsIWidget
* widget
= GetWidget()) {
285 if (WindowRenderer
* renderer
= widget
->GetWindowRenderer()) {
286 if (CompositorBridgeChild
* cbc
= renderer
->GetCompositorBridgeChild()) {
295 nsDOMWindowUtils::GetLastOverWindowPointerLocationInCSSPixels(float* aX
,
297 const PresShell
* presShell
= GetPresShell();
298 const nsPresContext
* presContext
= GetPresContext();
300 if (!presShell
|| !presContext
) {
301 return NS_ERROR_FAILURE
;
304 const nsPoint
& lastOverWindowPointerLocation
=
305 presShell
->GetLastOverWindowPointerLocation();
307 if (lastOverWindowPointerLocation
.X() == NS_UNCONSTRAINEDSIZE
&&
308 lastOverWindowPointerLocation
.Y() == NS_UNCONSTRAINEDSIZE
) {
312 const CSSPoint lastOverWindowPointerLocationInCSSPixels
=
313 CSSPoint::FromAppUnits(lastOverWindowPointerLocation
);
314 *aX
= lastOverWindowPointerLocationInCSSPixels
.X();
315 *aY
= lastOverWindowPointerLocationInCSSPixels
.Y();
322 nsDOMWindowUtils::SyncFlushCompositor() {
323 if (nsIWidget
* widget
= GetWidget()) {
324 if (WindowRenderer
* renderer
= widget
->GetWindowRenderer()) {
325 if (KnowsCompositor
* kc
= renderer
->AsKnowsCompositor()) {
326 kc
->SyncWithCompositor();
334 nsDOMWindowUtils::GetImageAnimationMode(uint16_t* aMode
) {
335 NS_ENSURE_ARG_POINTER(aMode
);
337 nsPresContext
* presContext
= GetPresContext();
339 *aMode
= presContext
->ImageAnimationMode();
342 return NS_ERROR_NOT_AVAILABLE
;
346 nsDOMWindowUtils::SetImageAnimationMode(uint16_t aMode
) {
347 nsPresContext
* presContext
= GetPresContext();
349 presContext
->SetImageAnimationMode(aMode
);
352 return NS_ERROR_NOT_AVAILABLE
;
356 nsDOMWindowUtils::GetDocCharsetIsForced(bool* aIsForced
) {
359 Document
* doc
= GetDocument();
361 auto source
= doc
->GetDocumentCharacterSetSource();
362 *aIsForced
= source
== kCharsetFromInitialUserForcedAutoDetection
||
363 source
== kCharsetFromFinalUserForcedAutoDetection
;
369 nsDOMWindowUtils::GetPhysicalMillimeterInCSSPixels(float* aPhysicalMillimeter
) {
370 nsPresContext
* presContext
= GetPresContext();
372 return NS_ERROR_NOT_AVAILABLE
;
375 *aPhysicalMillimeter
= nsPresContext::AppUnitsToFloatCSSPixels(
376 presContext
->PhysicalMillimetersToAppUnits(1));
381 nsDOMWindowUtils::GetDocumentMetadata(const nsAString
& aName
,
383 Document
* doc
= GetDocument();
385 RefPtr
<nsAtom
> name
= NS_Atomize(aName
);
386 doc
->GetHeaderData(name
, aValue
);
395 nsDOMWindowUtils::UpdateLayerTree() {
396 if (RefPtr
<PresShell
> presShell
= GetPresShell()) {
397 // Don't flush throttled animations since it might fire MozAfterPaint event
398 // (in WebRender it constantly does), thus the reftest harness can't take
399 // any snapshot until the throttled animations finished.
400 presShell
->FlushPendingNotifications(
401 ChangesToFlush(FlushType::Display
, false /* flush animations */));
402 RefPtr
<nsViewManager
> vm
= presShell
->GetViewManager();
403 if (nsView
* view
= vm
->GetRootView()) {
404 nsAutoScriptBlocker scriptBlocker
;
405 presShell
->PaintAndRequestComposite(view
,
406 PaintFlags::PaintSyncDecodeImages
);
407 presShell
->GetWindowRenderer()->WaitOnTransactionProcessed();
414 nsDOMWindowUtils::GetDocumentViewerSize(uint32_t* aDisplayWidth
,
415 uint32_t* aDisplayHeight
) {
416 PresShell
* presShell
= GetPresShell();
417 LayoutDeviceIntSize displaySize
;
419 if (!presShell
|| !nsLayoutUtils::GetDocumentViewerSize(
420 presShell
->GetPresContext(), displaySize
)) {
421 return NS_ERROR_FAILURE
;
424 *aDisplayWidth
= displaySize
.width
;
425 *aDisplayHeight
= displaySize
.height
;
431 nsDOMWindowUtils::GetViewportInfo(uint32_t aDisplayWidth
,
432 uint32_t aDisplayHeight
, double* aDefaultZoom
,
433 bool* aAllowZoom
, double* aMinZoom
,
434 double* aMaxZoom
, uint32_t* aWidth
,
435 uint32_t* aHeight
, bool* aAutoSize
) {
436 Document
* doc
= GetDocument();
437 NS_ENSURE_STATE(doc
);
439 nsViewportInfo info
=
440 doc
->GetViewportInfo(ScreenIntSize(aDisplayWidth
, aDisplayHeight
));
441 *aDefaultZoom
= info
.GetDefaultZoom().scale
;
442 *aAllowZoom
= info
.IsZoomAllowed();
443 *aMinZoom
= info
.GetMinZoom().scale
;
444 *aMaxZoom
= info
.GetMaxZoom().scale
;
445 CSSIntSize size
= gfx::RoundedToInt(info
.GetSize());
446 *aWidth
= size
.width
;
447 *aHeight
= size
.height
;
448 *aAutoSize
= info
.IsAutoSizeEnabled();
453 nsDOMWindowUtils::GetViewportFitInfo(nsAString
& aViewportFit
) {
454 Document
* doc
= GetDocument();
455 NS_ENSURE_STATE(doc
);
457 ViewportMetaData metaData
= doc
->GetViewportMetaData();
458 if (metaData
.mViewportFit
.EqualsLiteral("contain")) {
459 aViewportFit
.AssignLiteral("contain");
460 } else if (metaData
.mViewportFit
.EqualsLiteral("cover")) {
461 aViewportFit
.AssignLiteral("cover");
463 aViewportFit
.AssignLiteral("auto");
469 nsDOMWindowUtils::SetMousewheelAutodir(Element
* aElement
, bool aEnabled
,
471 aElement
->SetProperty(nsGkAtoms::forceMousewheelAutodir
,
472 reinterpret_cast<void*>(aEnabled
));
473 aElement
->SetProperty(nsGkAtoms::forceMousewheelAutodirHonourRoot
,
474 reinterpret_cast<void*>(aHonourRoot
));
479 nsDOMWindowUtils::SetDisplayPortForElement(float aXPx
, float aYPx
,
480 float aWidthPx
, float aHeightPx
,
482 uint32_t aPriority
) {
483 PresShell
* presShell
= GetPresShell();
485 return NS_ERROR_FAILURE
;
489 return NS_ERROR_INVALID_ARG
;
492 if (aElement
->GetUncomposedDoc() != presShell
->GetDocument()) {
493 return NS_ERROR_INVALID_ARG
;
496 bool hadDisplayPort
= false;
497 bool wasPainted
= false;
498 nsRect oldDisplayPort
;
500 DisplayPortPropertyData
* currentData
=
501 static_cast<DisplayPortPropertyData
*>(
502 aElement
->GetProperty(nsGkAtoms::DisplayPort
));
504 if (currentData
->mPriority
> aPriority
) {
507 hadDisplayPort
= true;
508 oldDisplayPort
= currentData
->mRect
;
509 wasPainted
= currentData
->mPainted
;
513 nsRect
displayport(nsPresContext::CSSPixelsToAppUnits(aXPx
),
514 nsPresContext::CSSPixelsToAppUnits(aYPx
),
515 nsPresContext::CSSPixelsToAppUnits(aWidthPx
),
516 nsPresContext::CSSPixelsToAppUnits(aHeightPx
));
518 aElement
->RemoveProperty(nsGkAtoms::MinimalDisplayPort
);
519 aElement
->SetProperty(
520 nsGkAtoms::DisplayPort
,
521 new DisplayPortPropertyData(displayport
, aPriority
, wasPainted
),
522 nsINode::DeleteProperty
<DisplayPortPropertyData
>);
524 DisplayPortUtils::InvalidateForDisplayPortChange(aElement
, hadDisplayPort
,
525 oldDisplayPort
, displayport
);
527 nsIFrame
* rootFrame
= presShell
->GetRootFrame();
529 rootFrame
->SchedulePaint();
531 // If we are hiding something that is a display root then send empty paint
532 // transaction in order to release retained layers because it won't get
533 // any more paint requests when it is hidden.
534 if (displayport
.IsEmpty() &&
535 rootFrame
== nsLayoutUtils::GetDisplayRootFrame(rootFrame
)) {
536 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
538 using PaintFrameFlags
= nsLayoutUtils::PaintFrameFlags
;
539 nsLayoutUtils::PaintFrame(
540 nullptr, rootFrame
, nsRegion(), NS_RGB(255, 255, 255),
541 nsDisplayListBuilderMode::Painting
, PaintFrameFlags::WidgetLayers
);
550 nsDOMWindowUtils::SetDisplayPortMarginsForElement(
551 float aLeftMargin
, float aTopMargin
, float aRightMargin
,
552 float aBottomMargin
, Element
* aElement
, uint32_t aPriority
) {
553 PresShell
* presShell
= GetPresShell();
555 return NS_ERROR_FAILURE
;
559 return NS_ERROR_INVALID_ARG
;
562 if (aElement
->GetUncomposedDoc() != presShell
->GetDocument()) {
563 return NS_ERROR_INVALID_ARG
;
566 // Note order change of arguments between our function signature and
567 // ScreenMargin constructor.
568 ScreenMargin
displayportMargins(aTopMargin
, aRightMargin
, aBottomMargin
,
571 DisplayPortUtils::SetDisplayPortMargins(
573 DisplayPortMargins::ForContent(aElement
, displayportMargins
),
574 DisplayPortUtils::ClearMinimalDisplayPortProperty::Yes
, aPriority
);
580 nsDOMWindowUtils::SetDisplayPortBaseForElement(int32_t aX
, int32_t aY
,
581 int32_t aWidth
, int32_t aHeight
,
583 PresShell
* presShell
= GetPresShell();
585 return NS_ERROR_FAILURE
;
589 return NS_ERROR_INVALID_ARG
;
592 if (aElement
->GetUncomposedDoc() != presShell
->GetDocument()) {
593 return NS_ERROR_INVALID_ARG
;
596 DisplayPortUtils::SetDisplayPortBase(aElement
,
597 nsRect(aX
, aY
, aWidth
, aHeight
));
603 nsDOMWindowUtils::GetScrollbarSizes(Element
* aElement
,
604 uint32_t* aOutVerticalScrollbarWidth
,
605 uint32_t* aOutHorizontalScrollbarHeight
) {
606 nsIScrollableFrame
* scrollFrame
=
607 nsLayoutUtils::FindScrollableFrameFor(aElement
);
609 return NS_ERROR_INVALID_ARG
;
612 CSSIntMargin scrollbarSizes
=
613 RoundedToInt(CSSMargin::FromAppUnits(scrollFrame
->GetActualScrollbarSizes(
614 nsIScrollableFrame::ScrollbarSizesOptions::
615 INCLUDE_VISUAL_VIEWPORT_SCROLLBARS
)));
616 *aOutVerticalScrollbarWidth
= scrollbarSizes
.LeftRight();
617 *aOutHorizontalScrollbarHeight
= scrollbarSizes
.TopBottom();
623 nsDOMWindowUtils::SetResolutionAndScaleTo(float aResolution
) {
624 PresShell
* presShell
= GetPresShell();
626 return NS_ERROR_FAILURE
;
629 presShell
->SetResolutionAndScaleTo(aResolution
, ResolutionChangeOrigin::Test
);
635 nsDOMWindowUtils::SetRestoreResolution(float aResolution
,
636 uint32_t aDisplayWidth
,
637 uint32_t aDisplayHeight
) {
638 PresShell
* presShell
= GetPresShell();
640 return NS_ERROR_FAILURE
;
643 presShell
->SetRestoreResolution(
644 aResolution
, LayoutDeviceIntSize(aDisplayWidth
, aDisplayHeight
));
650 nsDOMWindowUtils::GetResolution(float* aResolution
) {
651 PresShell
* presShell
= GetPresShell();
653 return NS_ERROR_FAILURE
;
656 *aResolution
= presShell
->GetResolution();
662 nsDOMWindowUtils::SetIsFirstPaint(bool aIsFirstPaint
) {
663 if (PresShell
* presShell
= GetPresShell()) {
664 presShell
->SetIsFirstPaint(aIsFirstPaint
);
667 return NS_ERROR_FAILURE
;
671 nsDOMWindowUtils::GetIsFirstPaint(bool* aIsFirstPaint
) {
672 if (PresShell
* presShell
= GetPresShell()) {
673 *aIsFirstPaint
= presShell
->GetIsFirstPaint();
676 return NS_ERROR_FAILURE
;
680 nsDOMWindowUtils::GetPresShellId(uint32_t* aPresShellId
) {
681 if (PresShell
* presShell
= GetPresShell()) {
682 *aPresShellId
= presShell
->GetPresShellId();
685 return NS_ERROR_FAILURE
;
689 nsDOMWindowUtils::SendMouseEvent(
690 const nsAString
& aType
, float aX
, float aY
, int32_t aButton
,
691 int32_t aClickCount
, int32_t aModifiers
, bool aIgnoreRootScrollFrame
,
692 float aPressure
, unsigned short aInputSourceArg
,
693 bool aIsDOMEventSynthesized
, bool aIsWidgetEventSynthesized
,
694 int32_t aButtons
, uint32_t aIdentifier
, uint8_t aOptionalArgCount
,
695 bool* aPreventDefault
) {
696 return SendMouseEventCommon(
697 aType
, aX
, aY
, aButton
, aClickCount
, aModifiers
, aIgnoreRootScrollFrame
,
698 aPressure
, aInputSourceArg
,
699 aOptionalArgCount
>= 7 ? aIdentifier
: DEFAULT_MOUSE_POINTER_ID
, false,
700 aPreventDefault
, aOptionalArgCount
>= 4 ? aIsDOMEventSynthesized
: true,
701 aOptionalArgCount
>= 5 ? aIsWidgetEventSynthesized
: false,
702 aOptionalArgCount
>= 6 ? aButtons
: MOUSE_BUTTONS_NOT_SPECIFIED
);
706 nsDOMWindowUtils::SendMouseEventToWindow(
707 const nsAString
& aType
, float aX
, float aY
, int32_t aButton
,
708 int32_t aClickCount
, int32_t aModifiers
, bool aIgnoreRootScrollFrame
,
709 float aPressure
, unsigned short aInputSourceArg
,
710 bool aIsDOMEventSynthesized
, bool aIsWidgetEventSynthesized
,
711 int32_t aButtons
, uint32_t aIdentifier
, uint8_t aOptionalArgCount
) {
712 AUTO_PROFILER_LABEL("nsDOMWindowUtils::SendMouseEventToWindow", OTHER
);
714 return SendMouseEventCommon(
715 aType
, aX
, aY
, aButton
, aClickCount
, aModifiers
, aIgnoreRootScrollFrame
,
716 aPressure
, aInputSourceArg
,
717 aOptionalArgCount
>= 7 ? aIdentifier
: DEFAULT_MOUSE_POINTER_ID
, true,
718 nullptr, aOptionalArgCount
>= 4 ? aIsDOMEventSynthesized
: true,
719 aOptionalArgCount
>= 5 ? aIsWidgetEventSynthesized
: false,
720 aOptionalArgCount
>= 6 ? aButtons
: MOUSE_BUTTONS_NOT_SPECIFIED
);
724 nsDOMWindowUtils::SendMouseEventCommon(
725 const nsAString
& aType
, float aX
, float aY
, int32_t aButton
,
726 int32_t aClickCount
, int32_t aModifiers
, bool aIgnoreRootScrollFrame
,
727 float aPressure
, unsigned short aInputSourceArg
, uint32_t aPointerId
,
728 bool aToWindow
, bool* aPreventDefault
, bool aIsDOMEventSynthesized
,
729 bool aIsWidgetEventSynthesized
, int32_t aButtons
) {
730 RefPtr
<PresShell
> presShell
= GetPresShell();
731 PreventDefaultResult preventDefaultResult
;
732 nsresult rv
= nsContentUtils::SendMouseEvent(
733 presShell
, aType
, aX
, aY
, aButton
, aButtons
, aClickCount
, aModifiers
,
734 aIgnoreRootScrollFrame
, aPressure
, aInputSourceArg
, aPointerId
, aToWindow
,
735 &preventDefaultResult
, aIsDOMEventSynthesized
, aIsWidgetEventSynthesized
);
737 if (aPreventDefault
) {
738 *aPreventDefault
= preventDefaultResult
!= PreventDefaultResult::No
;
745 nsDOMWindowUtils::IsCORSSafelistedRequestHeader(const nsACString
& aName
,
746 const nsACString
& aValue
,
748 NS_ENSURE_ARG_POINTER(aRetVal
);
749 *aRetVal
= nsContentUtils::IsCORSSafelistedRequestHeader(aName
, aValue
);
754 nsDOMWindowUtils::SendWheelEvent(float aX
, float aY
, double aDeltaX
,
755 double aDeltaY
, double aDeltaZ
,
756 uint32_t aDeltaMode
, int32_t aModifiers
,
757 int32_t aLineOrPageDeltaX
,
758 int32_t aLineOrPageDeltaY
, uint32_t aOptions
) {
759 // get the widget to send the event to
761 nsCOMPtr
<nsIWidget
> widget
= GetWidget(&offset
);
763 return NS_ERROR_NULL_POINTER
;
766 WidgetWheelEvent
wheelEvent(true, eWheel
, widget
);
767 wheelEvent
.mModifiers
= nsContentUtils::GetWidgetModifiers(aModifiers
);
768 wheelEvent
.mDeltaX
= aDeltaX
;
769 wheelEvent
.mDeltaY
= aDeltaY
;
770 wheelEvent
.mDeltaZ
= aDeltaZ
;
771 wheelEvent
.mDeltaMode
= aDeltaMode
;
772 wheelEvent
.mIsMomentum
= (aOptions
& WHEEL_EVENT_CAUSED_BY_MOMENTUM
) != 0;
773 wheelEvent
.mIsNoLineOrPageDelta
=
774 (aOptions
& WHEEL_EVENT_CAUSED_BY_NO_LINE_OR_PAGE_DELTA_DEVICE
) != 0;
775 wheelEvent
.mCustomizedByUserPrefs
=
776 (aOptions
& WHEEL_EVENT_CUSTOMIZED_BY_USER_PREFS
) != 0;
777 wheelEvent
.mLineOrPageDeltaX
= aLineOrPageDeltaX
;
778 wheelEvent
.mLineOrPageDeltaY
= aLineOrPageDeltaY
;
780 nsPresContext
* presContext
= GetPresContext();
781 NS_ENSURE_TRUE(presContext
, NS_ERROR_FAILURE
);
783 wheelEvent
.mRefPoint
=
784 nsContentUtils::ToWidgetPoint(CSSPoint(aX
, aY
), offset
, presContext
);
786 if (StaticPrefs::test_events_async_enabled()) {
787 widget
->DispatchInputEvent(&wheelEvent
);
789 nsEventStatus status
= nsEventStatus_eIgnore
;
790 nsresult rv
= widget
->DispatchEvent(&wheelEvent
, status
);
791 NS_ENSURE_SUCCESS(rv
, rv
);
794 if (widget
->AsyncPanZoomEnabled()) {
795 // Computing overflow deltas is not compatible with APZ, so if APZ is
796 // enabled, we skip testing it.
800 bool failedX
= false;
801 if ((aOptions
& WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_X_ZERO
) &&
802 wheelEvent
.mOverflowDeltaX
!= 0) {
805 if ((aOptions
& WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_X_POSITIVE
) &&
806 wheelEvent
.mOverflowDeltaX
<= 0) {
809 if ((aOptions
& WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_X_NEGATIVE
) &&
810 wheelEvent
.mOverflowDeltaX
>= 0) {
813 bool failedY
= false;
814 if ((aOptions
& WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_Y_ZERO
) &&
815 wheelEvent
.mOverflowDeltaY
!= 0) {
818 if ((aOptions
& WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_Y_POSITIVE
) &&
819 wheelEvent
.mOverflowDeltaY
<= 0) {
822 if ((aOptions
& WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_Y_NEGATIVE
) &&
823 wheelEvent
.mOverflowDeltaY
>= 0) {
829 nsPrintfCString
debugMsg("SendWheelEvent(): unexpected mOverflowDeltaX: %f",
830 wheelEvent
.mOverflowDeltaX
);
831 NS_WARNING(debugMsg
.get());
834 nsPrintfCString
debugMsg("SendWheelEvent(): unexpected mOverflowDeltaY: %f",
835 wheelEvent
.mOverflowDeltaY
);
836 NS_WARNING(debugMsg
.get());
840 return (!failedX
&& !failedY
) ? NS_OK
: NS_ERROR_FAILURE
;
844 nsDOMWindowUtils::SendTouchEvent(
845 const nsAString
& aType
, const nsTArray
<uint32_t>& aIdentifiers
,
846 const nsTArray
<int32_t>& aXs
, const nsTArray
<int32_t>& aYs
,
847 const nsTArray
<uint32_t>& aRxs
, const nsTArray
<uint32_t>& aRys
,
848 const nsTArray
<float>& aRotationAngles
, const nsTArray
<float>& aForces
,
849 const nsTArray
<int32_t>& aTiltXs
, const nsTArray
<int32_t>& aTiltYs
,
850 const nsTArray
<int32_t>& aTwists
, int32_t aModifiers
,
851 bool aIgnoreRootScrollFrame
, bool* aPreventDefault
) {
852 return SendTouchEventCommon(aType
, aIdentifiers
, aXs
, aYs
, aRxs
, aRys
,
853 aRotationAngles
, aForces
, aTiltXs
, aTiltYs
,
854 aTwists
, aModifiers
, aIgnoreRootScrollFrame
,
855 false, aPreventDefault
);
859 nsDOMWindowUtils::SendTouchEventToWindow(
860 const nsAString
& aType
, const nsTArray
<uint32_t>& aIdentifiers
,
861 const nsTArray
<int32_t>& aXs
, const nsTArray
<int32_t>& aYs
,
862 const nsTArray
<uint32_t>& aRxs
, const nsTArray
<uint32_t>& aRys
,
863 const nsTArray
<float>& aRotationAngles
, const nsTArray
<float>& aForces
,
864 const nsTArray
<int32_t>& aTiltXs
, const nsTArray
<int32_t>& aTiltYs
,
865 const nsTArray
<int32_t>& aTwists
, int32_t aModifiers
,
866 bool aIgnoreRootScrollFrame
, bool* aPreventDefault
) {
867 return SendTouchEventCommon(aType
, aIdentifiers
, aXs
, aYs
, aRxs
, aRys
,
868 aRotationAngles
, aForces
, aTiltXs
, aTiltYs
,
869 aTwists
, aModifiers
, aIgnoreRootScrollFrame
, true,
873 nsresult
nsDOMWindowUtils::SendTouchEventCommon(
874 const nsAString
& aType
, const nsTArray
<uint32_t>& aIdentifiers
,
875 const nsTArray
<int32_t>& aXs
, const nsTArray
<int32_t>& aYs
,
876 const nsTArray
<uint32_t>& aRxs
, const nsTArray
<uint32_t>& aRys
,
877 const nsTArray
<float>& aRotationAngles
, const nsTArray
<float>& aForces
,
878 const nsTArray
<int32_t>& aTiltXs
, const nsTArray
<int32_t>& aTiltYs
,
879 const nsTArray
<int32_t>& aTwists
, int32_t aModifiers
,
880 bool aIgnoreRootScrollFrame
, bool aToWindow
, bool* aPreventDefault
) {
881 // get the widget to send the event to
883 nsCOMPtr
<nsIWidget
> widget
= GetWidget(&offset
);
885 return NS_ERROR_NULL_POINTER
;
888 if (aType
.EqualsLiteral("touchstart")) {
890 } else if (aType
.EqualsLiteral("touchmove")) {
892 } else if (aType
.EqualsLiteral("touchend")) {
894 } else if (aType
.EqualsLiteral("touchcancel")) {
897 return NS_ERROR_UNEXPECTED
;
899 WidgetTouchEvent
event(true, msg
, widget
);
900 event
.mFlags
.mIsSynthesizedForTests
= true;
901 event
.mModifiers
= nsContentUtils::GetWidgetModifiers(aModifiers
);
903 nsPresContext
* presContext
= GetPresContext();
905 return NS_ERROR_FAILURE
;
907 uint32_t count
= aIdentifiers
.Length();
908 if (aXs
.Length() != count
|| aYs
.Length() != count
||
909 aRxs
.Length() != count
|| aRys
.Length() != count
||
910 aRotationAngles
.Length() != count
|| aForces
.Length() != count
) {
911 return NS_ERROR_INVALID_ARG
;
913 event
.mTouches
.SetCapacity(count
);
914 for (uint32_t i
= 0; i
< count
; ++i
) {
915 LayoutDeviceIntPoint pt
= nsContentUtils::ToWidgetPoint(
916 CSSPoint(aXs
[i
], aYs
[i
]), offset
, presContext
);
917 LayoutDeviceIntPoint radius
= LayoutDeviceIntPoint::FromAppUnitsRounded(
918 CSSPoint::ToAppUnits(CSSPoint(aRxs
[i
], aRys
[i
])),
919 presContext
->AppUnitsPerDevPixel());
921 RefPtr
<Touch
> t
= new Touch(aIdentifiers
[i
], pt
, radius
, aRotationAngles
[i
],
922 aForces
[i
], aTiltXs
[i
], aTiltYs
[i
], aTwists
[i
]);
924 event
.mTouches
.AppendElement(t
);
927 nsEventStatus status
= nsEventStatus_eIgnore
;
929 RefPtr
<PresShell
> presShell
;
930 nsView
* view
= nsContentUtils::GetViewToDispatchEvent(
931 presContext
, getter_AddRefs(presShell
));
932 if (!presShell
|| !view
) {
933 return NS_ERROR_FAILURE
;
935 *aPreventDefault
= (status
== nsEventStatus_eConsumeNoDefault
);
936 return presShell
->HandleEvent(view
->GetFrame(), &event
, false, &status
);
939 if (StaticPrefs::test_events_async_enabled()) {
940 status
= widget
->DispatchInputEvent(&event
).mContentStatus
;
942 nsresult rv
= widget
->DispatchEvent(&event
, status
);
943 NS_ENSURE_SUCCESS(rv
, rv
);
946 if (aPreventDefault
) {
947 *aPreventDefault
= (status
== nsEventStatus_eConsumeNoDefault
);
953 static_cast<uint32_t>(nsIWidget::Modifiers::CAPS_LOCK
) ==
954 static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_CAPS_LOCK
),
955 "Need to sync CapsLock value between nsIWidget::Modifiers and "
956 "nsIDOMWindowUtils");
958 static_cast<uint32_t>(nsIWidget::Modifiers::NUM_LOCK
) ==
959 static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_NUM_LOCK
),
960 "Need to sync NumLock value between nsIWidget::Modifiers and "
961 "nsIDOMWindowUtils");
963 static_cast<uint32_t>(nsIWidget::Modifiers::SHIFT_L
) ==
964 static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_SHIFT_LEFT
),
965 "Need to sync ShiftLeft value between nsIWidget::Modifiers and "
966 "nsIDOMWindowUtils");
968 static_cast<uint32_t>(nsIWidget::Modifiers::SHIFT_R
) ==
969 static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_SHIFT_RIGHT
),
970 "Need to sync ShiftRight value between nsIWidget::Modifiers and "
971 "nsIDOMWindowUtils");
973 static_cast<uint32_t>(nsIWidget::Modifiers::CTRL_L
) ==
974 static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_CONTROL_LEFT
),
975 "Need to sync ControlLeft value between nsIWidget::Modifiers and "
976 "nsIDOMWindowUtils");
978 static_cast<uint32_t>(nsIWidget::Modifiers::CTRL_R
) ==
979 static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_CONTROL_RIGHT
),
980 "Need to sync ControlRight value between nsIWidget::Modifiers "
981 "and nsIDOMWindowUtils");
983 static_cast<uint32_t>(nsIWidget::Modifiers::ALT_L
) ==
984 static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_ALT_LEFT
),
985 "Need to sync AltLeft value between nsIWidget::Modifiers and "
986 "nsIDOMWindowUtils");
988 static_cast<uint32_t>(nsIWidget::Modifiers::ALT_R
) ==
989 static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_ALT_RIGHT
),
990 "Need to sync AltRight value between nsIWidget::Modifiers and "
991 "nsIDOMWindowUtils");
993 static_cast<uint32_t>(nsIWidget::Modifiers::COMMAND_L
) ==
994 static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_COMMAND_LEFT
),
995 "Need to sync CommandLeft value between nsIWidget::Modifiers and "
996 "nsIDOMWindowUtils");
998 static_cast<uint32_t>(nsIWidget::Modifiers::COMMAND_R
) ==
999 static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_COMMAND_RIGHT
),
1000 "Need to sync CommandRight value between nsIWidget::Modifiers "
1001 "and nsIDOMWindowUtils");
1003 static_cast<uint32_t>(nsIWidget::Modifiers::HELP
) ==
1004 static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_HELP
),
1005 "Need to sync Help value between nsIWidget::Modifiers and "
1006 "nsIDOMWindowUtils");
1008 static_cast<uint32_t>(nsIWidget::Modifiers::ALTGRAPH
) ==
1009 static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_ALT_GRAPH
),
1010 "Need to sync AltGraph value between nsIWidget::Modifiers and "
1011 "nsIDOMWindowUtils");
1013 static_cast<uint32_t>(nsIWidget::Modifiers::FUNCTION
) ==
1014 static_cast<uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_FUNCTION
),
1015 "Need to sync Function value between nsIWidget::Modifiers and "
1016 "nsIDOMWindowUtils");
1017 static_assert(static_cast<uint32_t>(nsIWidget::Modifiers::NUMERIC_KEY_PAD
) ==
1018 static_cast<uint32_t>(
1019 nsIDOMWindowUtils::NATIVE_MODIFIER_NUMERIC_KEY_PAD
),
1020 "Need to sync NumericKeyPad value between nsIWidget::Modifiers "
1021 "and nsIDOMWindowUtils");
1023 static nsIWidget::Modifiers
GetWidgetModifiers(uint32_t aNativeModifiers
) {
1024 nsIWidget::Modifiers widgetModifiers
= static_cast<nsIWidget::Modifiers
>(
1026 (nsIWidget::Modifiers::CAPS_LOCK
| nsIWidget::Modifiers::NUM_LOCK
|
1027 nsIWidget::Modifiers::SHIFT_L
| nsIWidget::Modifiers::SHIFT_R
|
1028 nsIWidget::Modifiers::CTRL_L
| nsIWidget::Modifiers::CTRL_R
|
1029 nsIWidget::Modifiers::ALT_L
| nsIWidget::Modifiers::ALT_R
|
1030 nsIWidget::Modifiers::COMMAND_L
| nsIWidget::Modifiers::COMMAND_R
|
1031 nsIWidget::Modifiers::HELP
| nsIWidget::Modifiers::ALTGRAPH
|
1032 nsIWidget::Modifiers::FUNCTION
| nsIWidget::Modifiers::NUMERIC_KEY_PAD
));
1033 NS_ASSERTION(static_cast<uint32_t>(widgetModifiers
) == aNativeModifiers
,
1034 "Invalid value is specified to the native modifiers");
1035 return widgetModifiers
;
1039 nsDOMWindowUtils::SendNativeKeyEvent(int32_t aNativeKeyboardLayout
,
1040 int32_t aNativeKeyCode
,
1041 uint32_t aModifiers
,
1042 const nsAString
& aCharacters
,
1043 const nsAString
& aUnmodifiedCharacters
,
1044 nsIObserver
* aObserver
) {
1045 // get the widget to send the event to
1046 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1047 if (!widget
) return NS_ERROR_FAILURE
;
1049 NS_DispatchToMainThread(NativeInputRunnable::Create(
1050 NewRunnableMethod
<int32_t, int32_t, uint32_t, nsString
, nsString
,
1052 "nsIWidget::SynthesizeNativeKeyEvent", widget
,
1053 &nsIWidget::SynthesizeNativeKeyEvent
, aNativeKeyboardLayout
,
1054 aNativeKeyCode
, static_cast<uint32_t>(GetWidgetModifiers(aModifiers
)),
1055 aCharacters
, aUnmodifiedCharacters
, aObserver
)));
1060 nsDOMWindowUtils::SendNativeMouseEvent(int32_t aScreenX
, int32_t aScreenY
,
1061 uint32_t aNativeMessage
, int16_t aButton
,
1062 uint32_t aModifierFlags
,
1063 Element
* aElementOnWidget
,
1064 nsIObserver
* aObserver
) {
1065 // get the widget to send the event to
1066 nsCOMPtr
<nsIWidget
> widget
= GetWidgetForElement(aElementOnWidget
);
1068 return NS_ERROR_FAILURE
;
1071 nsIWidget::NativeMouseMessage message
;
1072 switch (aNativeMessage
) {
1073 case NATIVE_MOUSE_MESSAGE_BUTTON_DOWN
:
1074 message
= nsIWidget::NativeMouseMessage::ButtonDown
;
1076 case NATIVE_MOUSE_MESSAGE_BUTTON_UP
:
1077 message
= nsIWidget::NativeMouseMessage::ButtonUp
;
1079 case NATIVE_MOUSE_MESSAGE_MOVE
:
1080 message
= nsIWidget::NativeMouseMessage::Move
;
1082 case NATIVE_MOUSE_MESSAGE_ENTER_WINDOW
:
1083 message
= nsIWidget::NativeMouseMessage::EnterWindow
;
1085 case NATIVE_MOUSE_MESSAGE_LEAVE_WINDOW
:
1086 message
= nsIWidget::NativeMouseMessage::LeaveWindow
;
1089 return NS_ERROR_INVALID_ARG
;
1092 NS_DispatchToMainThread(NativeInputRunnable::Create(
1093 NewRunnableMethod
<LayoutDeviceIntPoint
, nsIWidget::NativeMouseMessage
,
1094 MouseButton
, nsIWidget::Modifiers
, nsIObserver
*>(
1095 "nsIWidget::SynthesizeNativeMouseEvent", widget
,
1096 &nsIWidget::SynthesizeNativeMouseEvent
,
1097 LayoutDeviceIntPoint(aScreenX
, aScreenY
), message
,
1098 static_cast<MouseButton
>(aButton
), GetWidgetModifiers(aModifierFlags
),
1104 nsDOMWindowUtils::SendNativeMouseScrollEvent(
1105 int32_t aScreenX
, int32_t aScreenY
, uint32_t aNativeMessage
, double aDeltaX
,
1106 double aDeltaY
, double aDeltaZ
, uint32_t aModifierFlags
,
1107 uint32_t aAdditionalFlags
, Element
* aElement
, nsIObserver
* aObserver
) {
1108 // get the widget to send the event to
1109 nsCOMPtr
<nsIWidget
> widget
= GetWidgetForElement(aElement
);
1111 return NS_ERROR_FAILURE
;
1114 NS_DispatchToMainThread(NativeInputRunnable::Create(
1115 NewRunnableMethod
<mozilla::LayoutDeviceIntPoint
, uint32_t, double, double,
1116 double, uint32_t, uint32_t, nsIObserver
*>(
1117 "nsIWidget::SynthesizeNativeMouseScrollEvent", widget
,
1118 &nsIWidget::SynthesizeNativeMouseScrollEvent
,
1119 LayoutDeviceIntPoint(aScreenX
, aScreenY
), aNativeMessage
, aDeltaX
,
1120 aDeltaY
, aDeltaZ
, aModifierFlags
, aAdditionalFlags
, aObserver
)));
1125 nsDOMWindowUtils::SendNativeTouchPoint(uint32_t aPointerId
,
1126 uint32_t aTouchState
, int32_t aScreenX
,
1127 int32_t aScreenY
, double aPressure
,
1128 uint32_t aOrientation
,
1129 nsIObserver
* aObserver
) {
1130 // FYI: This was designed for automated tests, but currently, this is used by
1131 // DevTools to emulate touch events from mouse events in the responsive
1134 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1136 return NS_ERROR_FAILURE
;
1139 if (aPressure
< 0 || aPressure
> 1 || aOrientation
> 359) {
1140 return NS_ERROR_INVALID_ARG
;
1143 NS_DispatchToMainThread(NativeInputRunnable::Create(
1144 NewRunnableMethod
<uint32_t, nsIWidget::TouchPointerState
,
1145 LayoutDeviceIntPoint
, double, uint32_t, nsIObserver
*>(
1146 "nsIWidget::SynthesizeNativeTouchPoint", widget
,
1147 &nsIWidget::SynthesizeNativeTouchPoint
, aPointerId
,
1148 (nsIWidget::TouchPointerState
)aTouchState
,
1149 LayoutDeviceIntPoint(aScreenX
, aScreenY
), aPressure
, aOrientation
,
1155 nsDOMWindowUtils::SendNativeTouchpadPinch(uint32_t aEventPhase
, float aScale
,
1156 int32_t aScreenX
, int32_t aScreenY
,
1157 int32_t aModifierFlags
) {
1158 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1160 return NS_ERROR_FAILURE
;
1162 NS_DispatchToMainThread(NativeInputRunnable::Create(
1163 NewRunnableMethod
<nsIWidget::TouchpadGesturePhase
, float,
1164 LayoutDeviceIntPoint
, int32_t>(
1165 "nsIWidget::SynthesizeNativeTouchPadPinch", widget
,
1166 &nsIWidget::SynthesizeNativeTouchPadPinch
,
1167 (nsIWidget::TouchpadGesturePhase
)aEventPhase
, aScale
,
1168 LayoutDeviceIntPoint(aScreenX
, aScreenY
), aModifierFlags
)));
1173 nsDOMWindowUtils::SendNativeTouchTap(int32_t aScreenX
, int32_t aScreenY
,
1174 bool aLongTap
, nsIObserver
* aObserver
) {
1175 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1177 return NS_ERROR_FAILURE
;
1180 NS_DispatchToMainThread(NativeInputRunnable::Create(
1181 NewRunnableMethod
<LayoutDeviceIntPoint
, bool, nsIObserver
*>(
1182 "nsIWidget::SynthesizeNativeTouchTap", widget
,
1183 &nsIWidget::SynthesizeNativeTouchTap
,
1184 LayoutDeviceIntPoint(aScreenX
, aScreenY
), aLongTap
, aObserver
)));
1189 nsDOMWindowUtils::SendNativePenInput(uint32_t aPointerId
,
1190 uint32_t aPointerState
, int32_t aScreenX
,
1191 int32_t aScreenY
, double aPressure
,
1192 uint32_t aRotation
, int32_t aTiltX
,
1193 int32_t aTiltY
, int32_t aButton
,
1194 nsIObserver
* aObserver
) {
1195 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1197 return NS_ERROR_FAILURE
;
1200 if (aPressure
< 0 || aPressure
> 1 || aRotation
> 359 || aTiltX
< -90 ||
1201 aTiltX
> 90 || aTiltY
< -90 || aTiltY
> 90) {
1202 return NS_ERROR_INVALID_ARG
;
1205 NS_DispatchToMainThread(NativeInputRunnable::Create(
1206 NewRunnableMethod
<uint32_t, nsIWidget::TouchPointerState
,
1207 LayoutDeviceIntPoint
, double, uint32_t, int32_t,
1208 int32_t, int32_t, nsIObserver
*>(
1209 "nsIWidget::SynthesizeNativePenInput", widget
,
1210 &nsIWidget::SynthesizeNativePenInput
, aPointerId
,
1211 (nsIWidget::TouchPointerState
)aPointerState
,
1212 LayoutDeviceIntPoint(aScreenX
, aScreenY
), aPressure
, aRotation
,
1213 aTiltX
, aTiltY
, aButton
, aObserver
)));
1218 nsDOMWindowUtils::SendNativeTouchpadDoubleTap(int32_t aScreenX
,
1220 int32_t aModifierFlags
) {
1221 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1223 return NS_ERROR_FAILURE
;
1226 MOZ_ASSERT(aModifierFlags
>= 0);
1227 NS_DispatchToMainThread(NativeInputRunnable::Create(
1228 NewRunnableMethod
<LayoutDeviceIntPoint
, uint32_t>(
1229 "nsIWidget::SynthesizeNativeTouchpadDoubleTap", widget
,
1230 &nsIWidget::SynthesizeNativeTouchpadDoubleTap
,
1231 LayoutDeviceIntPoint(aScreenX
, aScreenY
), aModifierFlags
)));
1236 nsDOMWindowUtils::SendNativeTouchpadPan(uint32_t aEventPhase
, int32_t aScreenX
,
1237 int32_t aScreenY
, double aDeltaX
,
1238 double aDeltaY
, int32_t aModifierFlags
,
1239 nsIObserver
* aObserver
) {
1240 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1242 return NS_ERROR_FAILURE
;
1245 MOZ_ASSERT(aModifierFlags
>= 0);
1246 NS_DispatchToMainThread(NativeInputRunnable::Create(
1247 NewRunnableMethod
<nsIWidget::TouchpadGesturePhase
, LayoutDeviceIntPoint
,
1248 double, double, uint32_t, nsIObserver
*>(
1249 "nsIWidget::SynthesizeNativeTouchpadPan", widget
,
1250 &nsIWidget::SynthesizeNativeTouchpadPan
,
1251 (nsIWidget::TouchpadGesturePhase
)aEventPhase
,
1252 LayoutDeviceIntPoint(aScreenX
, aScreenY
), aDeltaX
, aDeltaY
,
1253 aModifierFlags
, aObserver
)));
1258 nsDOMWindowUtils::SuppressAnimation(bool aSuppress
) {
1259 nsIWidget
* widget
= GetWidget();
1261 widget
->SuppressAnimation(aSuppress
);
1267 nsDOMWindowUtils::ClearSharedStyleSheetCache() {
1268 SharedStyleSheetCache::Clear();
1273 nsDOMWindowUtils::GetParsedStyleSheets(uint32_t* aSheets
) {
1274 RefPtr
<Document
> doc
= GetDocument();
1276 return NS_ERROR_UNEXPECTED
;
1279 *aSheets
= doc
->CSSLoader()->ParsedSheetCount();
1284 nsDOMWindowUtils::ClearNativeTouchSequence(nsIObserver
* aObserver
) {
1285 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1287 return NS_ERROR_FAILURE
;
1290 NS_DispatchToMainThread(
1291 NativeInputRunnable::Create(NewRunnableMethod
<nsIObserver
*>(
1292 "nsIWidget::ClearNativeTouchSequence", widget
,
1293 &nsIWidget::ClearNativeTouchSequence
, aObserver
)));
1298 nsDOMWindowUtils::ActivateNativeMenuItemAt(const nsAString
& indexString
) {
1299 // get the widget to send the event to
1300 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1301 if (!widget
) return NS_ERROR_FAILURE
;
1303 return widget
->ActivateNativeMenuItemAt(indexString
);
1307 nsDOMWindowUtils::ForceUpdateNativeMenuAt(const nsAString
& indexString
) {
1308 // get the widget to send the event to
1309 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1310 if (!widget
) return NS_ERROR_FAILURE
;
1312 return widget
->ForceUpdateNativeMenuAt(indexString
);
1316 nsDOMWindowUtils::GetSelectionAsPlaintext(nsAString
& aResult
) {
1317 // Get the widget to send the event to.
1318 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1320 return NS_ERROR_FAILURE
;
1323 return widget
->GetSelectionAsPlaintext(aResult
);
1326 nsIWidget
* nsDOMWindowUtils::GetWidget(nsPoint
* aOffset
) {
1327 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
1329 nsIDocShell
* docShell
= window
->GetDocShell();
1331 return nsContentUtils::GetWidget(docShell
->GetPresShell(), aOffset
);
1338 nsIWidget
* nsDOMWindowUtils::GetWidgetForElement(Element
* aElement
) {
1342 if (Document
* doc
= aElement
->GetUncomposedDoc()) {
1343 if (PresShell
* presShell
= doc
->GetPresShell()) {
1344 nsIFrame
* frame
= aElement
->GetPrimaryFrame();
1346 frame
= presShell
->GetRootFrame();
1349 return frame
->GetNearestWidget();
1358 nsDOMWindowUtils::GarbageCollect(nsICycleCollectorListener
* aListener
) {
1359 AUTO_PROFILER_LABEL("nsDOMWindowUtils::GarbageCollect", GCCC
);
1361 nsJSContext::GarbageCollectNow(JS::GCReason::DOM_UTILS
);
1362 nsJSContext::CycleCollectNow(CCReason::API
, aListener
);
1368 nsDOMWindowUtils::CycleCollect(nsICycleCollectorListener
* aListener
) {
1369 nsJSContext::CycleCollectNow(CCReason::API
, aListener
);
1373 static bool ParseGCReason(const nsACString
& aStr
, JS::GCReason
* aReason
,
1374 JS::GCReason aDefault
) {
1375 if (aStr
.IsEmpty()) {
1376 *aReason
= aDefault
;
1379 #define CHECK_REASON(name, _) \
1380 if (aStr.EqualsIgnoreCase(#name)) { \
1381 *aReason = JS::GCReason::name; \
1384 GCREASONS(CHECK_REASON
);
1389 nsDOMWindowUtils::RunNextCollectorTimer(const nsACString
& aReason
) {
1390 JS::GCReason reason
;
1391 if (!ParseGCReason(aReason
, &reason
, JS::GCReason::DOM_WINDOW_UTILS
)) {
1392 return NS_ERROR_INVALID_ARG
;
1395 nsJSContext::RunNextCollectorTimer(reason
);
1401 nsDOMWindowUtils::PokeGC(const nsACString
& aReason
) {
1402 JS::GCReason reason
;
1403 if (!ParseGCReason(aReason
, &reason
, JS::GCReason::DOM_WINDOW_UTILS
)) {
1404 return NS_ERROR_INVALID_ARG
;
1407 nsJSContext::PokeGC(reason
, nullptr);
1413 nsDOMWindowUtils::SendSimpleGestureEvent(const nsAString
& aType
, float aX
,
1414 float aY
, uint32_t aDirection
,
1415 double aDelta
, int32_t aModifiers
,
1416 uint32_t aClickCount
) {
1417 // get the widget to send the event to
1419 nsCOMPtr
<nsIWidget
> widget
= GetWidget(&offset
);
1420 if (!widget
) return NS_ERROR_FAILURE
;
1423 if (aType
.EqualsLiteral("MozSwipeGestureMayStart")) {
1424 msg
= eSwipeGestureMayStart
;
1425 } else if (aType
.EqualsLiteral("MozSwipeGestureStart")) {
1426 msg
= eSwipeGestureStart
;
1427 } else if (aType
.EqualsLiteral("MozSwipeGestureUpdate")) {
1428 msg
= eSwipeGestureUpdate
;
1429 } else if (aType
.EqualsLiteral("MozSwipeGestureEnd")) {
1430 msg
= eSwipeGestureEnd
;
1431 } else if (aType
.EqualsLiteral("MozSwipeGesture")) {
1432 msg
= eSwipeGesture
;
1433 } else if (aType
.EqualsLiteral("MozMagnifyGestureStart")) {
1434 msg
= eMagnifyGestureStart
;
1435 } else if (aType
.EqualsLiteral("MozMagnifyGestureUpdate")) {
1436 msg
= eMagnifyGestureUpdate
;
1437 } else if (aType
.EqualsLiteral("MozMagnifyGesture")) {
1438 msg
= eMagnifyGesture
;
1439 } else if (aType
.EqualsLiteral("MozRotateGestureStart")) {
1440 msg
= eRotateGestureStart
;
1441 } else if (aType
.EqualsLiteral("MozRotateGestureUpdate")) {
1442 msg
= eRotateGestureUpdate
;
1443 } else if (aType
.EqualsLiteral("MozRotateGesture")) {
1444 msg
= eRotateGesture
;
1445 } else if (aType
.EqualsLiteral("MozTapGesture")) {
1447 } else if (aType
.EqualsLiteral("MozPressTapGesture")) {
1448 msg
= ePressTapGesture
;
1449 } else if (aType
.EqualsLiteral("MozEdgeUIStarted")) {
1450 msg
= eEdgeUIStarted
;
1451 } else if (aType
.EqualsLiteral("MozEdgeUICanceled")) {
1452 msg
= eEdgeUICanceled
;
1453 } else if (aType
.EqualsLiteral("MozEdgeUICompleted")) {
1454 msg
= eEdgeUICompleted
;
1456 return NS_ERROR_FAILURE
;
1459 WidgetSimpleGestureEvent
event(true, msg
, widget
);
1460 event
.mModifiers
= nsContentUtils::GetWidgetModifiers(aModifiers
);
1461 event
.mDirection
= aDirection
;
1462 event
.mDelta
= aDelta
;
1463 event
.mClickCount
= aClickCount
;
1465 nsPresContext
* presContext
= GetPresContext();
1466 if (!presContext
) return NS_ERROR_FAILURE
;
1469 nsContentUtils::ToWidgetPoint(CSSPoint(aX
, aY
), offset
, presContext
);
1471 nsEventStatus status
;
1472 return widget
->DispatchEvent(&event
, status
);
1476 nsDOMWindowUtils::ElementFromPoint(float aX
, float aY
,
1477 bool aIgnoreRootScrollFrame
,
1478 bool aFlushLayout
, Element
** aReturn
) {
1479 nsCOMPtr
<Document
> doc
= GetDocument();
1480 NS_ENSURE_STATE(doc
);
1482 RefPtr
<Element
> el
= doc
->ElementFromPointHelper(
1483 aX
, aY
, aIgnoreRootScrollFrame
, aFlushLayout
, ViewportType::Layout
);
1489 nsDOMWindowUtils::NodesFromRect(float aX
, float aY
, float aTopSize
,
1490 float aRightSize
, float aBottomSize
,
1491 float aLeftSize
, bool aIgnoreRootScrollFrame
,
1492 bool aFlushLayout
, bool aOnlyVisible
,
1493 float aVisibleThreshold
,
1494 nsINodeList
** aReturn
) {
1495 RefPtr
<Document
> doc
= GetDocument();
1496 NS_ENSURE_STATE(doc
);
1498 auto list
= MakeRefPtr
<nsSimpleContentList
>(doc
);
1500 // The visible threshold was omitted or given a zero value (which makes no
1501 // sense), so give a reasonable default.
1502 if (aVisibleThreshold
== 0.0f
) {
1503 aVisibleThreshold
= 1.0f
;
1506 AutoTArray
<RefPtr
<nsINode
>, 8> nodes
;
1507 doc
->NodesFromRect(aX
, aY
, aTopSize
, aRightSize
, aBottomSize
, aLeftSize
,
1508 aIgnoreRootScrollFrame
, aFlushLayout
, aOnlyVisible
,
1509 aVisibleThreshold
, nodes
);
1510 list
->SetCapacity(nodes
.Length());
1511 for (auto& node
: nodes
) {
1512 list
->AppendElement(node
->AsContent());
1515 list
.forget(aReturn
);
1520 nsDOMWindowUtils::GetTranslationNodes(nsINode
* aRoot
,
1521 nsITranslationNodeList
** aRetVal
) {
1522 NS_ENSURE_ARG_POINTER(aRetVal
);
1523 nsCOMPtr
<nsIContent
> root
= do_QueryInterface(aRoot
);
1524 NS_ENSURE_STATE(root
);
1525 nsCOMPtr
<Document
> doc
= GetDocument();
1526 NS_ENSURE_STATE(doc
);
1528 if (root
->OwnerDoc() != doc
) {
1529 return NS_ERROR_DOM_WRONG_DOCUMENT_ERR
;
1532 nsTHashSet
<nsIContent
*> translationNodesHash(500);
1533 RefPtr
<nsTranslationNodeList
> list
= new nsTranslationNodeList
;
1535 uint32_t limit
= 15000;
1537 // We begin iteration with content->GetNextNode because we want to explictly
1538 // skip the root tag from being a translation node.
1539 nsIContent
* content
= root
;
1540 while ((limit
> 0) && (content
= content
->GetNextNode(root
))) {
1541 if (!content
->IsHTMLElement()) {
1545 // Skip elements that usually contain non-translatable text content.
1546 if (content
->IsAnyOfHTMLElements(nsGkAtoms::script
, nsGkAtoms::iframe
,
1547 nsGkAtoms::frameset
, nsGkAtoms::frame
,
1548 nsGkAtoms::code
, nsGkAtoms::noscript
,
1549 nsGkAtoms::style
)) {
1553 // An element is a translation node if it contains
1554 // at least one text node that has meaningful data
1556 for (nsIContent
* child
= content
->GetFirstChild(); child
;
1557 child
= child
->GetNextSibling()) {
1558 if (child
->IsText() && child
->GetAsText()->HasTextForTranslation()) {
1559 translationNodesHash
.Insert(content
);
1561 nsIFrame
* frame
= content
->GetPrimaryFrame();
1562 bool isTranslationRoot
= frame
&& frame
->IsBlockFrameOrSubclass();
1563 if (!isTranslationRoot
) {
1564 // If an element is not a block element, it still
1565 // can be considered a translation root if the parent
1566 // of this element didn't make into the list of nodes
1567 // to be translated.
1568 bool parentInList
= false;
1569 nsIContent
* parent
= content
->GetParent();
1571 parentInList
= translationNodesHash
.Contains(parent
);
1573 isTranslationRoot
= !parentInList
;
1576 list
->AppendElement(content
, isTranslationRoot
);
1583 *aRetVal
= list
.forget().take();
1587 static already_AddRefed
<DataSourceSurface
> CanvasToDataSourceSurface(
1588 HTMLCanvasElement
* aCanvas
) {
1589 MOZ_ASSERT(aCanvas
);
1590 SurfaceFromElementResult result
= nsLayoutUtils::SurfaceFromElement(aCanvas
);
1592 MOZ_ASSERT(result
.GetSourceSurface());
1593 return result
.GetSourceSurface()->GetDataSurface();
1597 nsDOMWindowUtils::CompareCanvases(nsISupports
* aCanvas1
, nsISupports
* aCanvas2
,
1598 uint32_t* aMaxDifference
, uint32_t* retVal
) {
1599 nsCOMPtr
<nsIContent
> contentCanvas1
= do_QueryInterface(aCanvas1
);
1600 nsCOMPtr
<nsIContent
> contentCanvas2
= do_QueryInterface(aCanvas2
);
1601 auto* canvas1
= HTMLCanvasElement::FromNodeOrNull(contentCanvas1
);
1602 auto* canvas2
= HTMLCanvasElement::FromNodeOrNull(contentCanvas2
);
1604 if (NS_WARN_IF(!canvas1
) || NS_WARN_IF(!canvas2
)) {
1605 return NS_ERROR_FAILURE
;
1608 RefPtr
<DataSourceSurface
> img1
= CanvasToDataSourceSurface(canvas1
);
1609 RefPtr
<DataSourceSurface
> img2
= CanvasToDataSourceSurface(canvas2
);
1611 if (NS_WARN_IF(!img1
) || NS_WARN_IF(!img2
) ||
1612 NS_WARN_IF(img1
->GetSize() != img2
->GetSize())) {
1613 return NS_ERROR_FAILURE
;
1616 if (img1
->Equals(img2
)) {
1617 // They point to the same underlying content.
1621 DataSourceSurface::ScopedMap
map1(img1
, DataSourceSurface::READ
);
1622 DataSourceSurface::ScopedMap
map2(img2
, DataSourceSurface::READ
);
1624 if (NS_WARN_IF(!map1
.IsMapped()) || NS_WARN_IF(!map2
.IsMapped())) {
1625 return NS_ERROR_FAILURE
;
1629 IntSize size
= img1
->GetSize();
1630 int32_t stride1
= map1
.GetStride();
1631 int32_t stride2
= map2
.GetStride();
1633 // we can optimize for the common all-pass case
1634 if (stride1
== stride2
&& stride1
== size
.width
* 4) {
1635 v
= memcmp(map1
.GetData(), map2
.GetData(), size
.width
* size
.height
* 4);
1637 if (aMaxDifference
) *aMaxDifference
= 0;
1644 uint32_t different
= 0;
1646 for (int j
= 0; j
< size
.height
; j
++) {
1647 unsigned char* p1
= map1
.GetData() + j
* stride1
;
1648 unsigned char* p2
= map2
.GetData() + j
* stride2
;
1649 v
= memcmp(p1
, p2
, size
.width
* 4);
1652 for (int i
= 0; i
< size
.width
; i
++) {
1653 if (*(uint32_t*)p1
!= *(uint32_t*)p2
) {
1656 dc
= std::max((uint32_t)abs(p1
[0] - p2
[0]), dc
);
1657 dc
= std::max((uint32_t)abs(p1
[1] - p2
[1]), dc
);
1658 dc
= std::max((uint32_t)abs(p1
[2] - p2
[2]), dc
);
1659 dc
= std::max((uint32_t)abs(p1
[3] - p2
[3]), dc
);
1668 if (aMaxDifference
) *aMaxDifference
= dc
;
1670 *retVal
= different
;
1675 nsDOMWindowUtils::GetIsMozAfterPaintPending(bool* aResult
) {
1676 NS_ENSURE_ARG_POINTER(aResult
);
1678 nsPresContext
* presContext
= GetPresContext();
1679 if (!presContext
) return NS_OK
;
1680 *aResult
= presContext
->IsDOMPaintEventPending();
1685 nsDOMWindowUtils::GetIsInputTaskManagerSuspended(bool* aResult
) {
1686 *aResult
= InputTaskManager::Get()->IsSuspended();
1691 nsDOMWindowUtils::DisableNonTestMouseEvents(bool aDisable
) {
1692 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
1693 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
1694 nsIDocShell
* docShell
= window
->GetDocShell();
1695 NS_ENSURE_TRUE(docShell
, NS_ERROR_FAILURE
);
1696 PresShell
* presShell
= docShell
->GetPresShell();
1697 NS_ENSURE_TRUE(presShell
, NS_ERROR_FAILURE
);
1698 presShell
->DisableNonTestMouseEvents(aDisable
);
1703 nsDOMWindowUtils::SuppressEventHandling(bool aSuppress
) {
1704 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
1705 NS_ENSURE_STATE(window
);
1708 window
->SuppressEventHandling();
1710 window
->UnsuppressEventHandling();
1716 static nsresult
getScrollXYAppUnits(const nsWeakPtr
& aWindow
, bool aFlushLayout
,
1717 nsPoint
& aScrollPos
) {
1718 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(aWindow
);
1719 nsCOMPtr
<Document
> doc
= window
? window
->GetExtantDoc() : nullptr;
1720 NS_ENSURE_STATE(doc
);
1723 doc
->FlushPendingNotifications(FlushType::Layout
);
1726 if (PresShell
* presShell
= doc
->GetPresShell()) {
1727 nsIScrollableFrame
* sf
= presShell
->GetRootScrollFrameAsScrollable();
1729 aScrollPos
= sf
->GetScrollPosition();
1736 nsDOMWindowUtils::GetScrollXY(bool aFlushLayout
, int32_t* aScrollX
,
1737 int32_t* aScrollY
) {
1738 nsPoint
scrollPos(0, 0);
1739 nsresult rv
= getScrollXYAppUnits(mWindow
, aFlushLayout
, scrollPos
);
1740 NS_ENSURE_SUCCESS(rv
, rv
);
1741 *aScrollX
= nsPresContext::AppUnitsToIntCSSPixels(scrollPos
.x
);
1742 *aScrollY
= nsPresContext::AppUnitsToIntCSSPixels(scrollPos
.y
);
1748 nsDOMWindowUtils::GetScrollXYFloat(bool aFlushLayout
, float* aScrollX
,
1750 nsPoint
scrollPos(0, 0);
1751 nsresult rv
= getScrollXYAppUnits(mWindow
, aFlushLayout
, scrollPos
);
1752 NS_ENSURE_SUCCESS(rv
, rv
);
1753 *aScrollX
= nsPresContext::AppUnitsToFloatCSSPixels(scrollPos
.x
);
1754 *aScrollY
= nsPresContext::AppUnitsToFloatCSSPixels(scrollPos
.y
);
1760 nsDOMWindowUtils::ScrollToVisual(float aOffsetX
, float aOffsetY
,
1761 int32_t aUpdateType
, int32_t aScrollMode
) {
1762 nsCOMPtr
<Document
> doc
= GetDocument();
1763 NS_ENSURE_STATE(doc
);
1765 nsPresContext
* presContext
= doc
->GetPresContext();
1766 NS_ENSURE_TRUE(presContext
, NS_ERROR_NOT_AVAILABLE
);
1768 // This should only be called on the root content document.
1769 NS_ENSURE_TRUE(presContext
->IsRootContentDocumentCrossProcess(),
1770 NS_ERROR_INVALID_ARG
);
1772 FrameMetrics::ScrollOffsetUpdateType updateType
;
1773 switch (aUpdateType
) {
1774 case UPDATE_TYPE_RESTORE
:
1775 updateType
= FrameMetrics::eRestore
;
1777 case UPDATE_TYPE_MAIN_THREAD
:
1778 updateType
= FrameMetrics::eMainThread
;
1781 return NS_ERROR_INVALID_ARG
;
1784 ScrollMode scrollMode
;
1785 switch (aScrollMode
) {
1786 case SCROLL_MODE_INSTANT
:
1787 scrollMode
= ScrollMode::Instant
;
1789 case SCROLL_MODE_SMOOTH
:
1790 scrollMode
= ScrollMode::SmoothMsd
;
1793 return NS_ERROR_INVALID_ARG
;
1796 presContext
->PresShell()->ScrollToVisual(
1797 CSSPoint::ToAppUnits(CSSPoint(aOffsetX
, aOffsetY
)), updateType
,
1804 nsDOMWindowUtils::GetVisualViewportOffsetRelativeToLayoutViewport(
1805 float* aOffsetX
, float* aOffsetY
) {
1809 nsCOMPtr
<Document
> doc
= GetDocument();
1810 NS_ENSURE_STATE(doc
);
1812 PresShell
* presShell
= doc
->GetPresShell();
1813 NS_ENSURE_TRUE(presShell
, NS_ERROR_NOT_AVAILABLE
);
1815 nsPoint offset
= presShell
->GetVisualViewportOffsetRelativeToLayoutViewport();
1816 *aOffsetX
= nsPresContext::AppUnitsToFloatCSSPixels(offset
.x
);
1817 *aOffsetY
= nsPresContext::AppUnitsToFloatCSSPixels(offset
.y
);
1823 nsDOMWindowUtils::GetVisualViewportOffset(int32_t* aOffsetX
,
1824 int32_t* aOffsetY
) {
1828 nsCOMPtr
<Document
> doc
= GetDocument();
1829 NS_ENSURE_STATE(doc
);
1831 PresShell
* presShell
= doc
->GetPresShell();
1832 NS_ENSURE_TRUE(presShell
, NS_ERROR_NOT_AVAILABLE
);
1834 nsPoint offset
= presShell
->GetVisualViewportOffset();
1835 *aOffsetX
= nsPresContext::AppUnitsToIntCSSPixels(offset
.x
);
1836 *aOffsetY
= nsPresContext::AppUnitsToIntCSSPixels(offset
.y
);
1842 nsDOMWindowUtils::TransformRectLayoutToVisual(float aX
, float aY
, float aWidth
,
1844 DOMRect
** aResult
) {
1845 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
1846 NS_ENSURE_STATE(window
);
1848 PresShell
* presShell
= GetPresShell();
1849 NS_ENSURE_TRUE(presShell
, NS_ERROR_NOT_AVAILABLE
);
1851 CSSRect
rect(aX
, aY
, aWidth
, aHeight
);
1852 rect
= ViewportUtils::DocumentRelativeLayoutToVisual(rect
, presShell
);
1854 RefPtr
<DOMRect
> outRect
= new DOMRect(window
);
1855 outRect
->SetRect(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
1856 outRect
.forget(aResult
);
1860 Result
<mozilla::ScreenRect
, nsresult
> nsDOMWindowUtils::ConvertToScreenRect(
1861 float aX
, float aY
, float aWidth
, float aHeight
) {
1862 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
1864 return Err(NS_ERROR_NOT_AVAILABLE
);
1867 PresShell
* presShell
= GetPresShell();
1869 return Err(NS_ERROR_NOT_AVAILABLE
);
1872 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1874 return Err(NS_ERROR_NOT_AVAILABLE
);
1877 // Note that if the document is NOT in OOP iframes, i.e. it's in the top level
1878 // content subtree in the same process,
1879 // nsIWidget::WidgetToTopLevelWidgetTransform() doesn't include the desktop
1880 // zoom value, so for documents in the top level content document subtree,
1881 // this ViewportUtils::DocumentRelativeLayoutToVisual call applies the desktop
1882 // zoom value via PresShell::GetResolution() in the function.
1883 CSSRect
rect(aX
, aY
, aWidth
, aHeight
);
1884 rect
= ViewportUtils::DocumentRelativeLayoutToVisual(rect
, presShell
);
1886 nsPresContext
* presContext
= presShell
->GetPresContext();
1887 MOZ_ASSERT(presContext
);
1889 // For OOP iframe documents, we don't have desktop zoom value specifically in
1890 // each iframe documents (i.e. the in-process root presshell's resolution is
1891 // 1.0), instead nsIWidget::WidgetToTopLevelWidgetTransform() includes the
1892 // desktop zoom scale value along with translations by ancestor scroll
1893 // containers, ancestor CSS transforms, etc.
1894 nsRect appUnitsRect
= CSSPixel::ToAppUnits(rect
);
1895 LayoutDeviceRect devPixelsRect
= LayoutDeviceRect::FromAppUnits(
1896 appUnitsRect
, presContext
->AppUnitsPerDevPixel());
1898 widget
->WidgetToTopLevelWidgetTransform().TransformBounds(devPixelsRect
) +
1899 widget
->TopLevelWidgetToScreenOffset();
1901 return ViewAs
<ScreenPixel
>(
1902 devPixelsRect
, PixelCastJustification::ScreenIsParentLayerForRoot
);
1906 nsDOMWindowUtils::ToScreenRectInCSSUnits(float aX
, float aY
, float aWidth
,
1907 float aHeight
, DOMRect
** aResult
) {
1909 MOZ_TRY_VAR(rect
, ConvertToScreenRect(aX
, aY
, aWidth
, aHeight
));
1911 nsPresContext
* presContext
= GetPresContext();
1912 MOZ_ASSERT(presContext
);
1914 const auto devRect
= ViewAs
<LayoutDevicePixel
>(
1915 rect
, PixelCastJustification::ScreenIsParentLayerForRoot
);
1917 // We want to return the screen rect in CSS units of the browser chrome.
1919 // TODO(emilio): It'd be cleaner to convert callers to use plain toScreenRect,
1920 // and perform the screen -> CSS rect in the parent process instead, probably.
1921 const nsRect appUnitsRect
= LayoutDeviceRect::ToAppUnits(
1923 presContext
->DeviceContext()->AppUnitsPerDevPixelInTopLevelChromePage());
1925 RefPtr
<DOMRect
> outRect
= new DOMRect(mWindow
);
1926 outRect
->SetLayoutRect(appUnitsRect
);
1928 outRect
.forget(aResult
);
1933 nsDOMWindowUtils::ToScreenRect(float aX
, float aY
, float aWidth
, float aHeight
,
1934 DOMRect
** aResult
) {
1936 MOZ_TRY_VAR(rect
, ConvertToScreenRect(aX
, aY
, aWidth
, aHeight
));
1938 RefPtr
<DOMRect
> outRect
= new DOMRect(mWindow
);
1939 outRect
->SetRect(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
1940 outRect
.forget(aResult
);
1945 nsDOMWindowUtils::ConvertFromParentProcessWidgetToLocal(float aX
, float aY
,
1948 DOMRect
** aResult
) {
1949 if (!XRE_IsContentProcess()) {
1950 return NS_ERROR_NOT_AVAILABLE
;
1953 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
1955 return NS_ERROR_NOT_AVAILABLE
;
1958 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
1960 return NS_ERROR_NOT_AVAILABLE
;
1963 LayoutDeviceRect devPixelsRect
= LayoutDeviceRect(aX
, aY
, aWidth
, aHeight
);
1965 Maybe
<LayoutDeviceToLayoutDeviceMatrix4x4
> inverse
=
1966 widget
->WidgetToTopLevelWidgetTransform().MaybeInverse();
1968 Maybe
<LayoutDeviceRect
> rect
=
1969 UntransformBy(*inverse
, devPixelsRect
, LayoutDeviceRect::MaxIntRect());
1971 RefPtr
<DOMRect
> outRect
= new DOMRect(mWindow
);
1972 outRect
->SetRect(rect
->x
, rect
->y
, rect
->width
, rect
->height
);
1973 outRect
.forget(aResult
);
1978 RefPtr
<DOMRect
> outRect
= new DOMRect(mWindow
);
1979 outRect
->SetRect(0, 0, 0, 0);
1980 outRect
.forget(aResult
);
1981 return NS_ERROR_NOT_AVAILABLE
;
1985 nsDOMWindowUtils::SetDynamicToolbarMaxHeight(uint32_t aHeightInScreen
) {
1986 if (aHeightInScreen
> INT32_MAX
) {
1987 return NS_ERROR_INVALID_ARG
;
1990 RefPtr
<nsPresContext
> presContext
= GetPresContext();
1995 MOZ_ASSERT(presContext
->IsRootContentDocumentCrossProcess());
1997 presContext
->SetDynamicToolbarMaxHeight(ScreenIntCoord(aHeightInScreen
));
2003 nsDOMWindowUtils::GetScrollbarSize(bool aFlushLayout
, int32_t* aWidth
,
2008 nsCOMPtr
<Document
> doc
= GetDocument();
2009 NS_ENSURE_STATE(doc
);
2012 doc
->FlushPendingNotifications(FlushType::Layout
);
2015 PresShell
* presShell
= doc
->GetPresShell();
2016 NS_ENSURE_TRUE(presShell
, NS_ERROR_NOT_AVAILABLE
);
2018 nsIScrollableFrame
* scrollFrame
= presShell
->GetRootScrollFrameAsScrollable();
2019 NS_ENSURE_TRUE(scrollFrame
, NS_OK
);
2021 nsMargin sizes
= scrollFrame
->GetActualScrollbarSizes();
2022 *aWidth
= nsPresContext::AppUnitsToIntCSSPixels(sizes
.LeftRight());
2023 *aHeight
= nsPresContext::AppUnitsToIntCSSPixels(sizes
.TopBottom());
2029 nsDOMWindowUtils::GetBoundsWithoutFlushing(Element
* aElement
,
2030 DOMRect
** aResult
) {
2031 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
2032 NS_ENSURE_STATE(window
);
2034 NS_ENSURE_ARG_POINTER(aElement
);
2036 RefPtr
<DOMRect
> rect
= new DOMRect(window
);
2037 nsIFrame
* frame
= aElement
->GetPrimaryFrame();
2040 nsRect r
= nsLayoutUtils::GetAllInFlowRectsUnion(
2041 frame
, nsLayoutUtils::GetContainingBlockForClientRect(frame
),
2042 nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS
);
2043 rect
->SetLayoutRect(r
);
2046 rect
.forget(aResult
);
2051 nsDOMWindowUtils::NeedsFlush(int32_t aFlushType
, bool* aResult
) {
2052 MOZ_ASSERT(aResult
);
2054 nsCOMPtr
<Document
> doc
= GetDocument();
2055 NS_ENSURE_STATE(doc
);
2057 PresShell
* presShell
= doc
->GetPresShell();
2058 NS_ENSURE_STATE(presShell
);
2060 FlushType flushType
;
2061 switch (aFlushType
) {
2063 flushType
= FlushType::Style
;
2067 flushType
= FlushType::Layout
;
2071 flushType
= FlushType::Display
;
2075 return NS_ERROR_INVALID_ARG
;
2078 *aResult
= presShell
->NeedFlush(flushType
);
2083 nsDOMWindowUtils::FlushLayoutWithoutThrottledAnimations() {
2084 nsCOMPtr
<Document
> doc
= GetDocument();
2086 doc
->FlushPendingNotifications(
2087 ChangesToFlush(FlushType::Layout
, false /* flush animations */));
2094 nsDOMWindowUtils::GetRootBounds(DOMRect
** aResult
) {
2095 Document
* doc
= GetDocument();
2096 NS_ENSURE_STATE(doc
);
2098 nsRect
bounds(0, 0, 0, 0);
2099 PresShell
* presShell
= doc
->GetPresShell();
2101 nsIScrollableFrame
* sf
= presShell
->GetRootScrollFrameAsScrollable();
2103 bounds
= sf
->GetScrollRange();
2104 bounds
.SetWidth(bounds
.Width() + sf
->GetScrollPortRect().Width());
2105 bounds
.SetHeight(bounds
.Height() + sf
->GetScrollPortRect().Height());
2106 } else if (presShell
->GetRootFrame()) {
2107 bounds
= presShell
->GetRootFrame()->GetRect();
2111 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
2112 RefPtr
<DOMRect
> rect
= new DOMRect(window
);
2113 rect
->SetRect(nsPresContext::AppUnitsToFloatCSSPixels(bounds
.x
),
2114 nsPresContext::AppUnitsToFloatCSSPixels(bounds
.y
),
2115 nsPresContext::AppUnitsToFloatCSSPixels(bounds
.Width()),
2116 nsPresContext::AppUnitsToFloatCSSPixels(bounds
.Height()));
2117 rect
.forget(aResult
);
2122 nsDOMWindowUtils::GetIMEIsOpen(bool* aState
) {
2123 NS_ENSURE_ARG_POINTER(aState
);
2125 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2126 if (!widget
) return NS_ERROR_FAILURE
;
2128 // Open state should not be available when IME is not enabled.
2129 InputContext context
= widget
->GetInputContext();
2130 if (context
.mIMEState
.mEnabled
!= IMEEnabled::Enabled
) {
2131 return NS_ERROR_NOT_AVAILABLE
;
2134 if (context
.mIMEState
.mOpen
== IMEState::OPEN_STATE_NOT_SUPPORTED
) {
2135 return NS_ERROR_NOT_IMPLEMENTED
;
2137 *aState
= (context
.mIMEState
.mOpen
== IMEState::OPEN
);
2142 nsDOMWindowUtils::GetIMEStatus(uint32_t* aState
) {
2143 NS_ENSURE_ARG_POINTER(aState
);
2145 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2146 if (!widget
) return NS_ERROR_FAILURE
;
2148 InputContext context
= widget
->GetInputContext();
2149 *aState
= static_cast<uint32_t>(context
.mIMEState
.mEnabled
);
2154 nsDOMWindowUtils::GetInputContextURI(nsIURI
** aURI
) {
2155 NS_ENSURE_ARG_POINTER(aURI
);
2157 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2159 return NS_ERROR_FAILURE
;
2162 nsCOMPtr
<nsIURI
> documentURI
= widget
->GetInputContext().mURI
;
2163 documentURI
.forget(aURI
);
2168 nsDOMWindowUtils::GetInputContextOrigin(uint32_t* aOrigin
) {
2169 NS_ENSURE_ARG_POINTER(aOrigin
);
2171 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2173 return NS_ERROR_FAILURE
;
2176 InputContext context
= widget
->GetInputContext();
2177 static_assert(static_cast<uint32_t>(InputContext::Origin::ORIGIN_MAIN
) ==
2178 INPUT_CONTEXT_ORIGIN_MAIN
);
2179 static_assert(static_cast<uint32_t>(InputContext::Origin::ORIGIN_CONTENT
) ==
2180 INPUT_CONTEXT_ORIGIN_CONTENT
);
2181 MOZ_ASSERT(context
.mOrigin
== InputContext::Origin::ORIGIN_MAIN
||
2182 context
.mOrigin
== InputContext::Origin::ORIGIN_CONTENT
);
2183 *aOrigin
= static_cast<uint32_t>(context
.mOrigin
);
2188 nsDOMWindowUtils::GetNodeObservedByIMEContentObserver(nsINode
** aNode
) {
2189 NS_ENSURE_ARG_POINTER(aNode
);
2191 IMEContentObserver
* observer
= IMEStateManager::GetActiveContentObserver();
2196 *aNode
= do_AddRef(observer
->GetObservingElement()).take();
2201 nsDOMWindowUtils::GetCanvasBackgroundColor(nsAString
& aColor
) {
2202 if (RefPtr
<Document
> doc
= GetDocument()) {
2203 doc
->FlushPendingNotifications(FlushType::Frames
);
2205 nscolor color
= NS_RGB(255, 255, 255);
2206 if (PresShell
* presShell
= GetPresShell()) {
2207 color
= presShell
->ComputeCanvasBackground().mViewportColor
;
2209 nsStyleUtil::GetSerializedColorValue(color
, aColor
);
2214 nsDOMWindowUtils::GetFocusedInputType(nsAString
& aType
) {
2215 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2217 return NS_ERROR_FAILURE
;
2220 aType
= widget
->GetInputContext().mHTMLInputType
;
2225 nsDOMWindowUtils::GetFocusedActionHint(nsAString
& aType
) {
2226 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2228 return NS_ERROR_FAILURE
;
2231 aType
= widget
->GetInputContext().mActionHint
;
2236 nsDOMWindowUtils::GetFocusedInputMode(nsAString
& aInputMode
) {
2237 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2239 return NS_ERROR_FAILURE
;
2241 aInputMode
= widget
->GetInputContext().mHTMLInputMode
;
2246 nsDOMWindowUtils::GetFocusedAutocapitalize(nsAString
& aAutocapitalize
) {
2247 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2249 return NS_ERROR_FAILURE
;
2251 aAutocapitalize
= widget
->GetInputContext().mAutocapitalize
;
2256 nsDOMWindowUtils::GetViewId(Element
* aElement
, nsViewID
* aResult
) {
2257 if (aElement
&& nsLayoutUtils::FindIDFor(aElement
, aResult
)) {
2260 return NS_ERROR_NOT_AVAILABLE
;
2263 NS_IMETHODIMP
nsDOMWindowUtils::DispatchDOMEventViaPresShellForTesting(
2264 nsINode
* aTarget
, Event
* aEvent
, bool* aRetVal
) {
2265 NS_ENSURE_STATE(aEvent
);
2266 aEvent
->SetTrusted(true);
2267 WidgetEvent
* internalEvent
= aEvent
->WidgetEventPtr();
2268 NS_ENSURE_STATE(internalEvent
);
2269 // This API is currently used only by EventUtils.js. Thus we should always
2270 // set mIsSynthesizedForTests to true.
2271 internalEvent
->mFlags
.mIsSynthesizedForTests
= true;
2272 nsCOMPtr
<nsIContent
> content
= nsIContent::FromNodeOrNull(aTarget
);
2273 NS_ENSURE_STATE(content
);
2274 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
2275 if (content
->OwnerDoc()->GetWindow() != window
) {
2276 return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR
;
2278 nsCOMPtr
<Document
> targetDoc
= content
->GetUncomposedDoc();
2279 NS_ENSURE_STATE(targetDoc
);
2280 RefPtr
<PresShell
> targetPresShell
= targetDoc
->GetPresShell();
2281 NS_ENSURE_STATE(targetPresShell
);
2283 targetDoc
->FlushPendingNotifications(FlushType::Layout
);
2285 nsEventStatus status
= nsEventStatus_eIgnore
;
2286 targetPresShell
->HandleEventWithTarget(internalEvent
, nullptr, content
,
2288 *aRetVal
= (status
!= nsEventStatus_eConsumeNoDefault
);
2292 static void InitEvent(WidgetGUIEvent
& aEvent
,
2293 LayoutDeviceIntPoint
* aPt
= nullptr) {
2295 aEvent
.mRefPoint
= *aPt
;
2300 nsDOMWindowUtils::SendQueryContentEvent(uint32_t aType
, int64_t aOffset
,
2301 uint32_t aLength
, int32_t aX
,
2302 int32_t aY
, uint32_t aAdditionalFlags
,
2303 nsIQueryContentEventResult
** aResult
) {
2306 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
2307 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
2309 nsIDocShell
* docShell
= window
->GetDocShell();
2310 NS_ENSURE_TRUE(docShell
, NS_ERROR_FAILURE
);
2312 PresShell
* presShell
= docShell
->GetPresShell();
2313 NS_ENSURE_TRUE(presShell
, NS_ERROR_FAILURE
);
2315 nsPresContext
* presContext
= presShell
->GetPresContext();
2316 NS_ENSURE_TRUE(presContext
, NS_ERROR_FAILURE
);
2318 // get the widget to send the event to
2319 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2321 return NS_ERROR_FAILURE
;
2324 EventMessage message
;
2326 case QUERY_SELECTED_TEXT
:
2327 message
= eQuerySelectedText
;
2329 case QUERY_TEXT_CONTENT
:
2330 message
= eQueryTextContent
;
2332 case QUERY_CARET_RECT
:
2333 message
= eQueryCaretRect
;
2335 case QUERY_TEXT_RECT
:
2336 message
= eQueryTextRect
;
2338 case QUERY_EDITOR_RECT
:
2339 message
= eQueryEditorRect
;
2341 case QUERY_CHARACTER_AT_POINT
:
2342 message
= eQueryCharacterAtPoint
;
2344 case QUERY_TEXT_RECT_ARRAY
:
2345 message
= eQueryTextRectArray
;
2348 return NS_ERROR_INVALID_ARG
;
2351 SelectionType selectionType
= SelectionType::eNormal
;
2352 static const uint32_t kSelectionFlags
=
2353 QUERY_CONTENT_FLAG_SELECTION_SPELLCHECK
|
2354 QUERY_CONTENT_FLAG_SELECTION_IME_RAWINPUT
|
2355 QUERY_CONTENT_FLAG_SELECTION_IME_SELECTEDRAWTEXT
|
2356 QUERY_CONTENT_FLAG_SELECTION_IME_CONVERTEDTEXT
|
2357 QUERY_CONTENT_FLAG_SELECTION_IME_SELECTEDCONVERTEDTEXT
|
2358 QUERY_CONTENT_FLAG_SELECTION_ACCESSIBILITY
|
2359 QUERY_CONTENT_FLAG_SELECTION_FIND
|
2360 QUERY_CONTENT_FLAG_SELECTION_URLSECONDARY
|
2361 QUERY_CONTENT_FLAG_SELECTION_URLSTRIKEOUT
;
2362 switch (aAdditionalFlags
& kSelectionFlags
) {
2363 case QUERY_CONTENT_FLAG_SELECTION_SPELLCHECK
:
2364 selectionType
= SelectionType::eSpellCheck
;
2366 case QUERY_CONTENT_FLAG_SELECTION_IME_RAWINPUT
:
2367 selectionType
= SelectionType::eIMERawClause
;
2369 case QUERY_CONTENT_FLAG_SELECTION_IME_SELECTEDRAWTEXT
:
2370 selectionType
= SelectionType::eIMESelectedRawClause
;
2372 case QUERY_CONTENT_FLAG_SELECTION_IME_CONVERTEDTEXT
:
2373 selectionType
= SelectionType::eIMEConvertedClause
;
2375 case QUERY_CONTENT_FLAG_SELECTION_IME_SELECTEDCONVERTEDTEXT
:
2376 selectionType
= SelectionType::eIMESelectedClause
;
2378 case QUERY_CONTENT_FLAG_SELECTION_ACCESSIBILITY
:
2379 selectionType
= SelectionType::eAccessibility
;
2381 case QUERY_CONTENT_FLAG_SELECTION_FIND
:
2382 selectionType
= SelectionType::eFind
;
2384 case QUERY_CONTENT_FLAG_SELECTION_URLSECONDARY
:
2385 selectionType
= SelectionType::eURLSecondary
;
2387 case QUERY_CONTENT_FLAG_SELECTION_URLSTRIKEOUT
:
2388 selectionType
= SelectionType::eURLStrikeout
;
2393 return NS_ERROR_INVALID_ARG
;
2396 if (selectionType
!= SelectionType::eNormal
&&
2397 message
!= eQuerySelectedText
) {
2398 return NS_ERROR_INVALID_ARG
;
2401 nsCOMPtr
<nsIWidget
> targetWidget
= widget
;
2402 LayoutDeviceIntPoint
pt(aX
, aY
);
2404 WidgetQueryContentEvent::Options options
;
2405 options
.mUseNativeLineBreak
=
2406 !(aAdditionalFlags
& QUERY_CONTENT_FLAG_USE_XP_LINE_BREAK
);
2407 options
.mRelativeToInsertionPoint
=
2409 QUERY_CONTENT_FLAG_OFFSET_RELATIVE_TO_INSERTION_POINT
) != 0;
2410 if (options
.mRelativeToInsertionPoint
) {
2412 case eQueryTextContent
:
2413 case eQueryCaretRect
:
2414 case eQueryTextRect
:
2417 return NS_ERROR_INVALID_ARG
;
2419 } else if (aOffset
< 0) {
2420 return NS_ERROR_INVALID_ARG
;
2423 if (message
== eQueryCharacterAtPoint
) {
2424 // Looking for the widget at the point.
2425 nsIFrame
* popupFrame
= nsLayoutUtils::GetPopupFrameForPoint(
2426 presContext
->GetRootPresContext(), widget
, pt
);
2428 LayoutDeviceIntRect widgetBounds
= widget
->GetClientBounds();
2429 widgetBounds
.MoveTo(0, 0);
2431 // There is no popup frame at the point and the point isn't in our widget,
2432 // we cannot process this request.
2433 NS_ENSURE_TRUE(popupFrame
|| widgetBounds
.Contains(pt
), NS_ERROR_FAILURE
);
2435 // Fire the event on the widget at the point
2437 targetWidget
= popupFrame
->GetNearestWidget();
2441 pt
+= widget
->WidgetToScreenOffset() - targetWidget
->WidgetToScreenOffset();
2443 WidgetQueryContentEvent
queryEvent(true, message
, targetWidget
);
2444 InitEvent(queryEvent
, &pt
);
2447 case eQueryTextContent
:
2448 queryEvent
.InitForQueryTextContent(aOffset
, aLength
, options
);
2450 case eQueryCaretRect
:
2451 queryEvent
.InitForQueryCaretRect(aOffset
, options
);
2453 case eQueryTextRect
:
2454 queryEvent
.InitForQueryTextRect(aOffset
, aLength
, options
);
2456 case eQuerySelectedText
:
2457 queryEvent
.InitForQuerySelectedText(selectionType
, options
);
2459 case eQueryTextRectArray
:
2460 queryEvent
.InitForQueryTextRectArray(aOffset
, aLength
, options
);
2463 queryEvent
.Init(options
);
2467 nsEventStatus status
;
2468 nsresult rv
= targetWidget
->DispatchEvent(&queryEvent
, status
);
2469 NS_ENSURE_SUCCESS(rv
, rv
);
2471 auto* result
= new nsQueryContentEventResult(std::move(queryEvent
));
2472 result
->SetEventResult(widget
);
2473 NS_ADDREF(*aResult
= result
);
2478 nsDOMWindowUtils::SendSelectionSetEvent(uint32_t aOffset
, uint32_t aLength
,
2479 uint32_t aAdditionalFlags
,
2483 // get the widget to send the event to
2484 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2486 return NS_ERROR_FAILURE
;
2489 WidgetSelectionEvent
selectionEvent(true, eSetSelection
, widget
);
2490 InitEvent(selectionEvent
);
2492 selectionEvent
.mOffset
= aOffset
;
2493 selectionEvent
.mLength
= aLength
;
2494 selectionEvent
.mReversed
= (aAdditionalFlags
& SELECTION_SET_FLAG_REVERSE
);
2495 selectionEvent
.mUseNativeLineBreak
=
2496 !(aAdditionalFlags
& SELECTION_SET_FLAG_USE_XP_LINE_BREAK
);
2498 nsEventStatus status
;
2499 nsresult rv
= widget
->DispatchEvent(&selectionEvent
, status
);
2500 NS_ENSURE_SUCCESS(rv
, rv
);
2502 *aResult
= selectionEvent
.mSucceeded
;
2507 nsDOMWindowUtils::SendContentCommandEvent(const nsAString
& aType
,
2508 nsITransferable
* aTransferable
,
2509 const nsAString
& aString
) {
2510 // get the widget to send the event to
2511 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2512 if (!widget
) return NS_ERROR_FAILURE
;
2515 if (aType
.EqualsLiteral("cut")) {
2516 msg
= eContentCommandCut
;
2517 } else if (aType
.EqualsLiteral("copy")) {
2518 msg
= eContentCommandCopy
;
2519 } else if (aType
.EqualsLiteral("paste")) {
2520 msg
= eContentCommandPaste
;
2521 } else if (aType
.EqualsLiteral("delete")) {
2522 msg
= eContentCommandDelete
;
2523 } else if (aType
.EqualsLiteral("undo")) {
2524 msg
= eContentCommandUndo
;
2525 } else if (aType
.EqualsLiteral("redo")) {
2526 msg
= eContentCommandRedo
;
2527 } else if (aType
.EqualsLiteral("insertText")) {
2528 msg
= eContentCommandInsertText
;
2529 } else if (aType
.EqualsLiteral("pasteTransferable")) {
2530 msg
= eContentCommandPasteTransferable
;
2532 return NS_ERROR_FAILURE
;
2535 WidgetContentCommandEvent
event(true, msg
, widget
);
2536 if (msg
== eContentCommandInsertText
) {
2537 event
.mString
.emplace(aString
);
2539 if (msg
== eContentCommandPasteTransferable
) {
2540 event
.mTransferable
= aTransferable
;
2543 nsEventStatus status
;
2544 return widget
->DispatchEvent(&event
, status
);
2548 nsDOMWindowUtils::GetClassName(JS::Handle
<JS::Value
> aObject
, JSContext
* aCx
,
2550 // Our argument must be a non-null object.
2551 if (aObject
.isPrimitive()) {
2552 return NS_ERROR_XPC_BAD_CONVERT_JS
;
2555 *aName
= NS_xstrdup(JS::GetClass(aObject
.toObjectOrNull())->name
);
2560 nsDOMWindowUtils::GetVisitedDependentComputedStyle(
2561 Element
* aElement
, const nsAString
& aPseudoElement
,
2562 const nsAString
& aPropertyName
, nsAString
& aResult
) {
2565 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
2566 NS_ENSURE_STATE(window
&& aElement
);
2567 nsCOMPtr
<nsPIDOMWindowInner
> innerWindow
= window
->GetCurrentInnerWindow();
2568 NS_ENSURE_STATE(innerWindow
);
2570 nsCOMPtr
<nsICSSDeclaration
> decl
;
2573 decl
= innerWindow
->GetComputedStyle(*aElement
, aPseudoElement
, rv
);
2574 ENSURE_SUCCESS(rv
, rv
.StealNSResult());
2577 nsAutoCString result
;
2579 static_cast<nsComputedDOMStyle
*>(decl
.get())->SetExposeVisitedStyle(true);
2580 decl
->GetPropertyValue(NS_ConvertUTF16toUTF8(aPropertyName
), result
);
2581 static_cast<nsComputedDOMStyle
*>(decl
.get())->SetExposeVisitedStyle(false);
2583 CopyUTF8toUTF16(result
, aResult
);
2588 nsDOMWindowUtils::EnterModalState() {
2589 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
2590 NS_ENSURE_STATE(window
);
2592 window
->EnterModalState();
2597 nsDOMWindowUtils::LeaveModalState() {
2598 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
2599 NS_ENSURE_STATE(window
);
2601 window
->LeaveModalState();
2606 nsDOMWindowUtils::IsInModalState(bool* retval
) {
2607 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
2608 NS_ENSURE_STATE(window
);
2610 *retval
= nsGlobalWindowOuter::Cast(window
)->IsInModalState();
2615 nsDOMWindowUtils::SuspendTimeouts() {
2616 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
2617 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
2619 nsCOMPtr
<nsPIDOMWindowInner
> inner
= window
->GetCurrentInnerWindow();
2620 NS_ENSURE_TRUE(inner
, NS_ERROR_FAILURE
);
2628 nsDOMWindowUtils::ResumeTimeouts() {
2629 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
2630 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
2632 nsCOMPtr
<nsPIDOMWindowInner
> inner
= window
->GetCurrentInnerWindow();
2633 NS_ENSURE_TRUE(inner
, NS_ERROR_FAILURE
);
2641 nsDOMWindowUtils::GetLayerManagerType(nsAString
& aType
) {
2642 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2643 if (!widget
) return NS_ERROR_FAILURE
;
2645 WindowRenderer
* renderer
= widget
->GetWindowRenderer();
2646 if (!renderer
) return NS_ERROR_FAILURE
;
2648 renderer
->GetBackendName(aType
);
2654 nsDOMWindowUtils::GetLayerManagerRemote(bool* retval
) {
2655 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2656 if (!widget
) return NS_ERROR_FAILURE
;
2658 WindowRenderer
* renderer
= widget
->GetWindowRenderer();
2659 if (!renderer
) return NS_ERROR_FAILURE
;
2661 *retval
= !!renderer
->AsKnowsCompositor();
2666 nsDOMWindowUtils::GetIsWebRenderRequested(bool* retval
) {
2667 *retval
= gfxPlatform::WebRenderPrefEnabled() ||
2668 gfxPlatform::WebRenderEnvvarEnabled();
2673 nsDOMWindowUtils::GetCurrentAudioBackend(nsAString
& aBackend
) {
2674 CubebUtils::GetCurrentBackend(aBackend
);
2679 nsDOMWindowUtils::GetCurrentMaxAudioChannels(uint32_t* aChannels
) {
2680 *aChannels
= CubebUtils::MaxNumberOfChannels();
2685 nsDOMWindowUtils::GetCurrentPreferredSampleRate(uint32_t* aRate
) {
2686 nsCOMPtr
<Document
> doc
= GetDocument();
2687 *aRate
= CubebUtils::PreferredSampleRate(
2688 doc
? doc
->ShouldResistFingerprinting(RFPTarget::AudioSampleRate
)
2689 : nsContentUtils::ShouldResistFingerprinting(
2690 "Fallback", RFPTarget::AudioSampleRate
));
2695 nsDOMWindowUtils::DefaultDevicesRoundTripLatency(Promise
** aOutPromise
) {
2696 NS_ENSURE_ARG_POINTER(aOutPromise
);
2697 *aOutPromise
= nullptr;
2699 nsCOMPtr
<nsPIDOMWindowOuter
> outer
= do_QueryReferent(mWindow
);
2700 NS_ENSURE_STATE(outer
);
2701 nsCOMPtr
<nsPIDOMWindowInner
> inner
= outer
->GetCurrentInnerWindow();
2702 NS_ENSURE_STATE(inner
);
2705 RefPtr
<Promise
> promise
= Promise::Create(inner
->AsGlobal(), err
);
2706 if (NS_WARN_IF(err
.Failed())) {
2707 return err
.StealNSResult();
2710 NS_ADDREF(promise
.get());
2711 void* p
= reinterpret_cast<void*>(promise
.get());
2712 NS_DispatchBackgroundTask(
2713 NS_NewRunnableFunction("DefaultDevicesRoundTripLatency", [p
]() {
2714 double mean
, stddev
;
2716 CubebUtils::EstimatedRoundTripLatencyDefaultDevices(&mean
, &stddev
);
2718 NS_DispatchToMainThread(NS_NewRunnableFunction(
2719 "DefaultDevicesRoundTripLatency", [p
, success
, mean
, stddev
]() {
2720 Promise
* promise
= reinterpret_cast<Promise
*>(p
);
2722 promise
->MaybeReject(NS_ERROR_FAILURE
);
2723 NS_RELEASE(promise
);
2727 a
.AppendElement(mean
);
2728 a
.AppendElement(stddev
);
2729 promise
->MaybeResolve(a
);
2730 NS_RELEASE(promise
);
2734 promise
.forget(aOutPromise
);
2739 nsDOMWindowUtils::AudioDevices(uint16_t aSide
, nsIArray
** aDevices
) {
2740 NS_ENSURE_ARG_POINTER(aDevices
);
2741 NS_ENSURE_ARG((aSide
== AUDIO_INPUT
) || (aSide
== AUDIO_OUTPUT
));
2742 *aDevices
= nullptr;
2744 nsresult rv
= NS_OK
;
2745 nsCOMPtr
<nsIMutableArray
> devices
=
2746 do_CreateInstance(NS_ARRAY_CONTRACTID
, &rv
);
2747 NS_ENSURE_SUCCESS(rv
, rv
);
2749 RefPtr
<CubebDeviceEnumerator
> enumerator
= Enumerator::GetInstance();
2750 RefPtr
<const CubebDeviceEnumerator::AudioDeviceSet
> collection
;
2751 if (aSide
== AUDIO_INPUT
) {
2752 collection
= enumerator
->EnumerateAudioInputDevices();
2754 collection
= enumerator
->EnumerateAudioOutputDevices();
2757 for (const auto& device
: *collection
) {
2758 devices
->AppendElement(device
);
2761 devices
.forget(aDevices
);
2767 nsDOMWindowUtils::StartFrameTimeRecording(uint32_t* startIndex
) {
2768 NS_ENSURE_ARG_POINTER(startIndex
);
2770 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2771 if (!widget
) return NS_ERROR_FAILURE
;
2773 WindowRenderer
* renderer
= widget
->GetWindowRenderer();
2774 if (!renderer
) return NS_ERROR_FAILURE
;
2776 const uint32_t kRecordingMinSize
= 60 * 10; // 10 seconds @60 fps.
2777 const uint32_t kRecordingMaxSize
= 60 * 60 * 60; // One hour
2778 uint32_t bufferSize
=
2779 Preferences::GetUint("toolkit.framesRecording.bufferSize", uint32_t(0));
2780 bufferSize
= std::min(bufferSize
, kRecordingMaxSize
);
2781 bufferSize
= std::max(bufferSize
, kRecordingMinSize
);
2782 *startIndex
= renderer
->StartFrameTimeRecording(bufferSize
);
2788 nsDOMWindowUtils::StopFrameTimeRecording(uint32_t startIndex
,
2789 nsTArray
<float>& frameIntervals
) {
2790 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
2791 if (!widget
) return NS_ERROR_FAILURE
;
2793 WindowRenderer
* renderer
= widget
->GetWindowRenderer();
2794 if (!renderer
) return NS_ERROR_FAILURE
;
2796 renderer
->StopFrameTimeRecording(startIndex
, frameIntervals
);
2802 nsDOMWindowUtils::AdvanceTimeAndRefresh(int64_t aMilliseconds
) {
2803 // Before we advance the time, we should trigger any animations that are
2804 // waiting to start. This is because there are many tests that call this
2805 // which expect animations to start immediately. Ideally, we should make
2806 // all these tests do an asynchronous wait on the corresponding animation's
2807 // 'ready' promise before continuing. Then we could remove the special
2808 // handling here and the code path followed when testing would more closely
2809 // match the code path during regular operation. Filed as bug 1112957.
2810 nsPresContext
* presContext
= GetPresContext();
2812 presContext
->Document()->Timeline()->TriggerAllPendingAnimationsNow();
2814 RefPtr
<nsRefreshDriver
> driver
= presContext
->RefreshDriver();
2815 driver
->AdvanceTimeAndRefresh(aMilliseconds
);
2817 if (WebRenderBridgeChild
* wrbc
= GetWebRenderBridge()) {
2818 wrbc
->SendSetTestSampleTime(driver
->MostRecentRefresh());
2826 nsDOMWindowUtils::GetLastTransactionId(uint64_t* aLastTransactionId
) {
2827 nsCOMPtr
<nsIDocShell
> docShell
= GetDocShell();
2829 return NS_ERROR_UNEXPECTED
;
2832 nsCOMPtr
<nsIDocShellTreeItem
> rootTreeItem
;
2833 docShell
->GetInProcessRootTreeItem(getter_AddRefs(rootTreeItem
));
2834 docShell
= do_QueryInterface(rootTreeItem
);
2836 return NS_ERROR_UNEXPECTED
;
2839 nsPresContext
* presContext
= docShell
->GetPresContext();
2841 return NS_ERROR_UNEXPECTED
;
2844 nsRefreshDriver
* driver
= presContext
->RefreshDriver();
2845 *aLastTransactionId
= uint64_t(driver
->LastTransactionId());
2850 nsDOMWindowUtils::RestoreNormalRefresh() {
2851 // Kick the compositor out of test mode before the refresh driver, so that
2852 // the refresh driver doesn't send an update that gets ignored by the
2854 if (WebRenderBridgeChild
* wrbc
= GetWebRenderBridge()) {
2855 wrbc
->SendLeaveTestMode();
2858 if (nsPresContext
* pc
= GetPresContext()) {
2859 nsRefreshDriver
* driver
= pc
->RefreshDriver();
2860 driver
->RestoreNormalRefresh();
2867 nsDOMWindowUtils::GetIsTestControllingRefreshes(bool* aResult
) {
2868 nsPresContext
* pc
= GetPresContext();
2870 pc
? pc
->RefreshDriver()->IsTestControllingRefreshesEnabled() : false;
2876 nsDOMWindowUtils::GetAsyncPanZoomEnabled(bool* aResult
) {
2877 nsIWidget
* widget
= GetWidget();
2879 *aResult
= widget
->AsyncPanZoomEnabled();
2881 *aResult
= gfxPlatform::AsyncPanZoomEnabled();
2887 nsDOMWindowUtils::SetAsyncScrollOffset(Element
* aElement
, float aX
, float aY
) {
2889 return NS_ERROR_INVALID_ARG
;
2891 ScrollableLayerGuid::ViewID viewId
;
2892 if (!nsLayoutUtils::FindIDFor(aElement
, &viewId
)) {
2893 return NS_ERROR_UNEXPECTED
;
2895 nsIWidget
* widget
= GetWidget();
2897 return NS_ERROR_FAILURE
;
2899 WindowRenderer
* renderer
= widget
->GetWindowRenderer();
2901 return NS_ERROR_FAILURE
;
2903 if (WebRenderLayerManager
* wr
= renderer
->AsWebRender()) {
2904 WebRenderBridgeChild
* wrbc
= wr
->WrBridge();
2906 return NS_ERROR_UNEXPECTED
;
2908 wrbc
->SendSetAsyncScrollOffset(viewId
, aX
, aY
);
2911 return NS_ERROR_UNEXPECTED
;
2915 nsDOMWindowUtils::SetAsyncZoom(Element
* aRootElement
, float aValue
) {
2916 if (!aRootElement
) {
2917 return NS_ERROR_INVALID_ARG
;
2919 ScrollableLayerGuid::ViewID viewId
;
2920 if (!nsLayoutUtils::FindIDFor(aRootElement
, &viewId
)) {
2921 return NS_ERROR_UNEXPECTED
;
2923 nsIWidget
* widget
= GetWidget();
2925 return NS_ERROR_FAILURE
;
2927 WindowRenderer
* renderer
= widget
->GetWindowRenderer();
2929 return NS_ERROR_FAILURE
;
2931 if (WebRenderLayerManager
* wr
= renderer
->AsWebRender()) {
2932 WebRenderBridgeChild
* wrbc
= wr
->WrBridge();
2934 return NS_ERROR_UNEXPECTED
;
2936 wrbc
->SendSetAsyncZoom(viewId
, aValue
);
2939 return NS_ERROR_UNEXPECTED
;
2943 nsDOMWindowUtils::FlushApzRepaints(bool* aOutResult
) {
2944 nsIWidget
* widget
= GetWidget();
2946 *aOutResult
= false;
2949 // If APZ is not enabled, this function is a no-op.
2950 if (!widget
->AsyncPanZoomEnabled()) {
2951 *aOutResult
= false;
2954 WindowRenderer
* renderer
= widget
->GetWindowRenderer();
2956 *aOutResult
= false;
2959 if (WebRenderLayerManager
* wr
= renderer
->AsWebRender()) {
2960 WebRenderBridgeChild
* wrbc
= wr
->WrBridge();
2962 return NS_ERROR_UNEXPECTED
;
2964 wrbc
->SendFlushApzRepaints();
2968 *aOutResult
= false;
2973 nsDOMWindowUtils::DisableApzForElement(Element
* aElement
) {
2974 aElement
->SetProperty(nsGkAtoms::apzDisabled
, reinterpret_cast<void*>(true));
2975 nsIScrollableFrame
* sf
= nsLayoutUtils::FindScrollableFrameFor(aElement
);
2979 nsIFrame
* frame
= do_QueryFrame(sf
);
2983 frame
->SchedulePaint();
2987 static nsTArray
<nsIScrollableFrame
*> CollectScrollableAncestors(
2989 nsTArray
<nsIScrollableFrame
*> result
;
2990 nsIFrame
* frame
= aStart
;
2992 frame
= nsLayoutUtils::GetCrossDocParentFrame(frame
);
2996 nsIScrollableFrame
* scrollAncestor
=
2997 nsLayoutUtils::GetAsyncScrollableAncestorFrame(frame
);
2998 if (!scrollAncestor
) {
3001 result
.AppendElement(scrollAncestor
);
3002 frame
= do_QueryFrame(scrollAncestor
);
3008 nsDOMWindowUtils::ZoomToFocusedInput() {
3009 if (!Preferences::GetBool("apz.zoom-to-focused-input.enabled")) {
3013 nsIWidget
* widget
= GetWidget();
3018 // If APZ is not enabled, this function is a no-op.
3020 // FIXME(emilio): This is not quite true anymore now that we also
3021 // ScrollIntoView() too...
3022 if (!widget
->AsyncPanZoomEnabled()) {
3026 nsFocusManager
* fm
= nsFocusManager::GetFocusManager();
3031 RefPtr
<Element
> element
= fm
->GetFocusedElement();
3036 RefPtr
<PresShell
> presShell
=
3037 APZCCallbackHelper::GetRootContentDocumentPresShellForContent(element
);
3042 // The content may be inside a scrollable subframe inside a non-scrollable
3043 // root content document. In this scenario, we want to ensure that the
3044 // main-thread side knows to scroll the content into view before we get
3045 // the bounding content rect and ask APZ to adjust the visual viewport.
3046 presShell
->ScrollContentIntoView(
3047 element
, ScrollAxis(WhereToScroll::Nearest
, WhenToScroll::IfNotVisible
),
3048 ScrollAxis(WhereToScroll::Nearest
, WhenToScroll::IfNotVisible
),
3049 ScrollFlags::ScrollOverflowHidden
);
3051 RefPtr
<Document
> document
= presShell
->GetDocument();
3056 uint32_t presShellId
;
3057 ScrollableLayerGuid::ViewID viewId
;
3058 if (!APZCCallbackHelper::GetOrCreateScrollIdentifiers(
3059 document
->GetDocumentElement(), &presShellId
, &viewId
)) {
3063 TouchBehaviorFlags tbf
=
3064 layers::TouchActionHelper::GetAllowedTouchBehaviorForFrame(
3065 element
->GetPrimaryFrame());
3067 uint32_t flags
= layers::DISABLE_ZOOM_OUT
| layers::ZOOM_TO_FOCUSED_INPUT
;
3068 if (!Preferences::GetBool("formhelper.autozoom") ||
3069 Preferences::GetBool("formhelper.autozoom.force-disable.test-only",
3070 /* aFallback = */ false) ||
3071 !(tbf
& AllowedTouchBehavior::ANIMATING_ZOOM
)) {
3072 flags
|= layers::PAN_INTO_VIEW_ONLY
;
3074 flags
|= layers::ONLY_ZOOM_TO_DEFAULT_SCALE
;
3077 nsIScrollableFrame
* rootScrollFrame
=
3078 presShell
->GetRootScrollFrameAsScrollable();
3079 if (!rootScrollFrame
) {
3084 if (element
->IsHTMLElement(nsGkAtoms::input
)) {
3085 bounds
= nsLayoutUtils::GetBoundingContentRect(element
, rootScrollFrame
);
3087 // When focused elment is content editable or <textarea> element,
3088 // focused element will have multi-line content.
3089 nsIFrame
* frame
= element
->GetPrimaryFrame();
3091 RefPtr
<nsCaret
> caret
= frame
->PresShell()->GetCaret();
3092 if (caret
&& caret
->IsVisible()) {
3094 if (nsIFrame
* frame
= caret
->GetGeometry(&rect
)) {
3095 bounds
= nsLayoutUtils::GetBoundingFrameRect(frame
, rootScrollFrame
);
3099 if (bounds
.IsEmpty()) {
3100 // Fallback if no caret frame.
3101 bounds
= nsLayoutUtils::GetBoundingContentRect(element
, rootScrollFrame
);
3105 if (bounds
.IsEmpty()) {
3106 // Do not zoom on empty bounds. Bail out.
3110 bounds
-= CSSPoint::FromAppUnits(rootScrollFrame
->GetScrollPosition());
3112 bool waitForRefresh
= false;
3113 for (nsIScrollableFrame
* scrollAncestor
:
3114 CollectScrollableAncestors(element
->GetPrimaryFrame())) {
3115 if (scrollAncestor
->HasScrollUpdates()) {
3116 waitForRefresh
= true;
3120 if (waitForRefresh
) {
3121 waitForRefresh
= false;
3122 if (nsPresContext
* presContext
= presShell
->GetPresContext()) {
3123 waitForRefresh
= true;
3124 presContext
->RegisterManagedPostRefreshObserver(
3125 new ManagedPostRefreshObserver(
3126 presContext
, [widget
= RefPtr
<nsIWidget
>(widget
), presShellId
,
3127 viewId
, bounds
, flags
](bool aWasCanceled
) {
3128 if (!aWasCanceled
) {
3129 widget
->ZoomToRect(presShellId
, viewId
, bounds
, flags
);
3131 return ManagedPostRefreshObserver::Unregister::Yes
;
3135 if (!waitForRefresh
) {
3136 widget
->ZoomToRect(presShellId
, viewId
, bounds
, flags
);
3143 nsDOMWindowUtils::ComputeAnimationDistance(Element
* aElement
,
3144 const nsAString
& aProperty
,
3145 const nsAString
& aValue1
,
3146 const nsAString
& aValue2
,
3148 NS_ENSURE_ARG_POINTER(aElement
);
3150 nsCSSPropertyID propertyID
=
3151 nsCSSProps::LookupProperty(NS_ConvertUTF16toUTF8(aProperty
));
3152 if (propertyID
== eCSSProperty_UNKNOWN
||
3153 nsCSSProps::IsShorthand(propertyID
)) {
3154 return NS_ERROR_ILLEGAL_VALUE
;
3157 AnimatedPropertyID property
= propertyID
== eCSSPropertyExtra_variable
3158 ? AnimatedPropertyID(NS_Atomize(aProperty
))
3159 : AnimatedPropertyID(propertyID
);
3161 AnimationValue v1
= AnimationValue::FromString(
3162 property
, NS_ConvertUTF16toUTF8(aValue1
), aElement
);
3163 AnimationValue v2
= AnimationValue::FromString(
3164 property
, NS_ConvertUTF16toUTF8(aValue2
), aElement
);
3165 if (v1
.IsNull() || v2
.IsNull()) {
3166 return NS_ERROR_ILLEGAL_VALUE
;
3169 *aResult
= v1
.ComputeDistance(v2
);
3174 nsDOMWindowUtils::GetUnanimatedComputedStyle(Element
* aElement
,
3175 const nsAString
& aPseudoElement
,
3176 const nsAString
& aProperty
,
3178 nsAString
& aResult
) {
3180 return NS_ERROR_INVALID_ARG
;
3183 nsCSSPropertyID propertyID
=
3184 nsCSSProps::LookupProperty(NS_ConvertUTF16toUTF8(aProperty
));
3185 if (propertyID
== eCSSProperty_UNKNOWN
||
3186 nsCSSProps::IsShorthand(propertyID
)) {
3187 return NS_ERROR_INVALID_ARG
;
3189 AnimatedPropertyID property
=
3190 propertyID
== eCSSPropertyExtra_variable
3191 ? AnimatedPropertyID(
3192 NS_Atomize(Substring(aProperty
, 2, aProperty
.Length() - 2)))
3193 : AnimatedPropertyID(propertyID
);
3195 switch (aFlushType
) {
3199 if (Document
* doc
= aElement
->GetComposedDoc()) {
3200 doc
->FlushPendingNotifications(FlushType::Style
);
3205 return NS_ERROR_INVALID_ARG
;
3208 RefPtr
<PresShell
> presShell
= GetPresShell();
3210 return NS_ERROR_FAILURE
;
3213 Maybe
<PseudoStyleType
> pseudo
=
3214 nsCSSPseudoElements::GetPseudoType(aPseudoElement
);
3216 return NS_ERROR_FAILURE
;
3218 RefPtr
<const ComputedStyle
> computedStyle
=
3219 nsComputedDOMStyle::GetUnanimatedComputedStyleNoFlush(aElement
, *pseudo
);
3220 if (!computedStyle
) {
3221 return NS_ERROR_FAILURE
;
3224 RefPtr
<StyleAnimationValue
> value
=
3225 Servo_ComputedValues_ExtractAnimationValue(computedStyle
, &property
)
3228 return NS_ERROR_FAILURE
;
3230 if (!aElement
->GetComposedDoc()) {
3231 return NS_ERROR_FAILURE
;
3233 nsAutoCString result
;
3234 Servo_AnimationValue_Serialize(value
, &property
,
3235 presShell
->StyleSet()->RawData(), &result
);
3236 CopyUTF8toUTF16(result
, aResult
);
3241 nsDOMWindowUtils::GetDisplayDPI(float* aDPI
) {
3242 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
3243 if (!widget
) return NS_ERROR_FAILURE
;
3245 *aDPI
= widget
->GetDPI();
3251 nsDOMWindowUtils::CheckAndClearPaintedState(Element
* aElement
, bool* aResult
) {
3253 return NS_ERROR_INVALID_ARG
;
3256 nsIFrame
* frame
= aElement
->GetPrimaryFrame();
3263 // Get the outermost frame for the content node, so that we can test
3264 // canvasframe invalidations by observing the documentElement.
3266 nsIFrame
* parentFrame
= frame
->GetParent();
3267 if (parentFrame
&& parentFrame
->GetContent() == aElement
) {
3268 frame
= parentFrame
;
3275 if (!frame
->CheckAndClearPaintedState()) {
3279 frame
= nsLayoutUtils::GetNextContinuationOrIBSplitSibling(frame
);
3286 nsDOMWindowUtils::CheckAndClearDisplayListState(Element
* aElement
,
3289 return NS_ERROR_INVALID_ARG
;
3292 nsIFrame
* frame
= aElement
->GetPrimaryFrame();
3299 // Get the outermost frame for the content node, so that we can test
3300 // canvasframe invalidations by observing the documentElement.
3302 nsIFrame
* parentFrame
= frame
->GetParent();
3303 if (parentFrame
&& parentFrame
->GetContent() == aElement
) {
3304 frame
= parentFrame
;
3311 if (!frame
->CheckAndClearDisplayListState()) {
3315 frame
= nsLayoutUtils::GetNextContinuationOrIBSplitSibling(frame
);
3322 nsDOMWindowUtils::IsPartOfOpaqueLayer(Element
* aElement
, bool* aResult
) {
3324 return NS_ERROR_INVALID_ARG
;
3327 nsIFrame
* frame
= aElement
->GetPrimaryFrame();
3329 return NS_ERROR_FAILURE
;
3332 return NS_ERROR_FAILURE
;
3336 nsDOMWindowUtils::NumberOfAssignedPaintedLayers(
3337 const nsTArray
<RefPtr
<Element
>>& aElements
, uint32_t* aResult
) {
3338 return NS_ERROR_FAILURE
;
3342 nsDOMWindowUtils::EnableDialogs() {
3343 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
3344 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
3346 nsGlobalWindowOuter::Cast(window
)->EnableDialogs();
3351 nsDOMWindowUtils::DisableDialogs() {
3352 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
3353 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
3355 nsGlobalWindowOuter::Cast(window
)->DisableDialogs();
3360 nsDOMWindowUtils::AreDialogsEnabled(bool* aResult
) {
3361 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
3362 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
3364 *aResult
= nsGlobalWindowOuter::Cast(window
)->AreDialogsEnabled();
3369 nsDOMWindowUtils::ResetDialogAbuseState() {
3370 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
3371 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
3373 nsGlobalWindowOuter::Cast(window
)
3374 ->GetBrowsingContextGroup()
3375 ->ResetDialogAbuseState();
3380 nsDOMWindowUtils::GetFileId(JS::Handle
<JS::Value
> aFile
, JSContext
* aCx
,
3382 if (aFile
.isPrimitive()) {
3387 JS::Rooted
<JSObject
*> obj(aCx
, aFile
.toObjectOrNull());
3389 Blob
* blob
= nullptr;
3390 if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob
, &obj
, blob
))) {
3391 *_retval
= blob
->GetFileId();
3400 nsDOMWindowUtils::GetFilePath(JS::Handle
<JS::Value
> aFile
, JSContext
* aCx
,
3401 nsAString
& _retval
) {
3402 if (aFile
.isPrimitive()) {
3407 JS::Rooted
<JSObject
*> obj(aCx
, aFile
.toObjectOrNull());
3409 File
* file
= nullptr;
3410 if (NS_SUCCEEDED(UNWRAP_OBJECT(File
, &obj
, file
))) {
3413 file
->GetMozFullPathInternal(filePath
, rv
);
3414 if (NS_WARN_IF(rv
.Failed())) {
3415 return rv
.StealNSResult();
3427 nsDOMWindowUtils::GetFileReferences(const nsAString
& aDatabaseName
, int64_t aId
,
3428 int32_t* aRefCnt
, int32_t* aDBRefCnt
,
3430 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
3431 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
3433 quota::PrincipalMetadata principalMetadata
;
3434 MOZ_TRY_VAR(principalMetadata
,
3435 quota::QuotaManager::GetInfoFromWindow(window
));
3437 RefPtr
<IndexedDatabaseManager
> mgr
= IndexedDatabaseManager::Get();
3439 nsresult rv
= mgr
->BlockAndGetFileReferences(
3440 principalMetadata
.mIsPrivate
? quota::PERSISTENCE_TYPE_PRIVATE
3441 : quota::PERSISTENCE_TYPE_DEFAULT
,
3442 principalMetadata
.mOrigin
, aDatabaseName
, aId
, aRefCnt
, aDBRefCnt
,
3445 NS_ENSURE_SUCCESS(rv
, rv
);
3447 *aRefCnt
= *aDBRefCnt
= -1;
3455 nsDOMWindowUtils::FlushPendingFileDeletions() {
3456 RefPtr
<IndexedDatabaseManager
> mgr
= IndexedDatabaseManager::Get();
3458 nsresult rv
= mgr
->FlushPendingFileDeletions();
3459 if (NS_WARN_IF(NS_FAILED(rv
))) {
3468 nsDOMWindowUtils::StartPCCountProfiling(JSContext
* cx
) {
3469 JS::StartPCCountProfiling(cx
);
3474 nsDOMWindowUtils::StopPCCountProfiling(JSContext
* cx
) {
3475 JS::StopPCCountProfiling(cx
);
3480 nsDOMWindowUtils::PurgePCCounts(JSContext
* cx
) {
3481 JS::PurgePCCounts(cx
);
3486 nsDOMWindowUtils::GetPCCountScriptCount(JSContext
* cx
, int32_t* result
) {
3487 *result
= JS::GetPCCountScriptCount(cx
);
3492 nsDOMWindowUtils::GetPCCountScriptSummary(int32_t script
, JSContext
* cx
,
3493 nsAString
& result
) {
3494 JSString
* text
= JS::GetPCCountScriptSummary(cx
, script
);
3495 if (!text
) return NS_ERROR_FAILURE
;
3497 if (!AssignJSString(cx
, result
, text
)) return NS_ERROR_FAILURE
;
3503 nsDOMWindowUtils::GetPCCountScriptContents(int32_t script
, JSContext
* cx
,
3504 nsAString
& result
) {
3505 JSString
* text
= JS::GetPCCountScriptContents(cx
, script
);
3506 if (!text
) return NS_ERROR_FAILURE
;
3508 if (!AssignJSString(cx
, result
, text
)) return NS_ERROR_FAILURE
;
3514 nsDOMWindowUtils::GetPaintingSuppressed(bool* aPaintingSuppressed
) {
3515 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
3516 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
3517 nsIDocShell
* docShell
= window
->GetDocShell();
3518 NS_ENSURE_TRUE(docShell
, NS_ERROR_FAILURE
);
3520 PresShell
* presShell
= docShell
->GetPresShell();
3521 NS_ENSURE_TRUE(presShell
, NS_ERROR_FAILURE
);
3523 *aPaintingSuppressed
= presShell
->IsPaintingSuppressed();
3528 nsDOMWindowUtils::SetVisualViewportSize(float aWidth
, float aHeight
) {
3529 if (!(aWidth
>= 0.0 && aHeight
>= 0.0)) {
3530 return NS_ERROR_ILLEGAL_VALUE
;
3533 PresShell
* presShell
= GetPresShell();
3535 return NS_ERROR_FAILURE
;
3538 presShell
->SetVisualViewportSize(nsPresContext::CSSPixelsToAppUnits(aWidth
),
3539 nsPresContext::CSSPixelsToAppUnits(aHeight
));
3544 nsresult
nsDOMWindowUtils::RemoteFrameFullscreenChanged(
3545 Element
* aFrameElement
) {
3546 nsCOMPtr
<Document
> doc
= GetDocument();
3547 NS_ENSURE_STATE(doc
);
3549 doc
->RemoteFrameFullscreenChanged(aFrameElement
);
3553 nsresult
nsDOMWindowUtils::RemoteFrameFullscreenReverted() {
3554 nsCOMPtr
<Document
> doc
= GetDocument();
3555 NS_ENSURE_STATE(doc
);
3557 doc
->RemoteFrameFullscreenReverted();
3561 static void PrepareForFullscreenChange(nsIDocShell
* aDocShell
,
3562 const nsSize
& aSize
,
3563 nsSize
* aOldSize
= nullptr) {
3567 PresShell
* presShell
= aDocShell
->GetPresShell();
3571 if (nsRefreshDriver
* rd
= presShell
->GetRefreshDriver()) {
3572 rd
->SetIsResizeSuppressed();
3573 // Since we are suppressing the resize reflow which would originally
3574 // be triggered by view manager, we need to ensure that the refresh
3575 // driver actually schedules a flush, otherwise it may get stuck.
3576 rd
->ScheduleViewManagerFlush();
3578 if (!aSize
.IsEmpty()) {
3579 nsCOMPtr
<nsIDocumentViewer
> viewer
;
3580 aDocShell
->GetDocViewer(getter_AddRefs(viewer
));
3582 nsIntRect viewerBounds
;
3583 viewer
->GetBounds(viewerBounds
);
3584 nscoord auPerDev
= presShell
->GetPresContext()->AppUnitsPerDevPixel();
3586 *aOldSize
= LayoutDeviceIntSize::ToAppUnits(
3587 LayoutDeviceIntSize::FromUnknownSize(viewerBounds
.Size()),
3590 LayoutDeviceIntSize newSize
=
3591 LayoutDeviceIntSize::FromAppUnitsRounded(aSize
, auPerDev
);
3593 viewerBounds
.SizeTo(newSize
.width
, newSize
.height
);
3594 viewer
->SetBounds(viewerBounds
);
3600 nsDOMWindowUtils::HandleFullscreenRequests(bool* aRetVal
) {
3601 PROFILER_MARKER_UNTYPED("Enter fullscreen", DOM
);
3602 nsCOMPtr
<Document
> doc
= GetDocument();
3603 NS_ENSURE_STATE(doc
);
3605 // Notify the pres shell that we are starting fullscreen change, and
3606 // set the window dimensions in advance. Since the resize message
3607 // comes after the fullscreen change call, doing so could avoid an
3608 // extra resize reflow after this point.
3610 if (nsPresContext
* presContext
= GetPresContext()) {
3611 presContext
->DeviceContext()->GetRect(screenRect
);
3614 PrepareForFullscreenChange(GetDocShell(), screenRect
.Size(), &oldSize
);
3615 OldWindowSize::Set(mWindow
, oldSize
);
3617 *aRetVal
= Document::HandlePendingFullscreenRequests(doc
);
3621 nsresult
nsDOMWindowUtils::ExitFullscreen(bool aDontRestoreViewSize
) {
3622 PROFILER_MARKER_UNTYPED("Exit fullscreen", DOM
);
3623 nsCOMPtr
<Document
> doc
= GetDocument();
3624 NS_ENSURE_STATE(doc
);
3626 // Although we would not use the old size if we have already exited
3627 // fullscreen, we still want to cleanup in case we haven't.
3628 nsSize oldSize
= OldWindowSize::GetAndRemove(mWindow
);
3629 if (!doc
->GetFullscreenElement()) {
3633 // Notify the pres shell that we are starting fullscreen change, and
3634 // set the window dimensions in advance. Since the resize message
3635 // comes after the fullscreen change call, doing so could avoid an
3636 // extra resize reflow after this point.
3637 PrepareForFullscreenChange(GetDocShell(),
3638 aDontRestoreViewSize
? nsSize() : oldSize
);
3639 Document::ExitFullscreenInDocTree(doc
);
3644 nsDOMWindowUtils::SelectAtPoint(float aX
, float aY
, uint32_t aSelectBehavior
,
3648 nsSelectionAmount amount
;
3649 switch (aSelectBehavior
) {
3650 case nsIDOMWindowUtils::SELECT_CHARACTER
:
3651 amount
= eSelectCharacter
;
3653 case nsIDOMWindowUtils::SELECT_CLUSTER
:
3654 amount
= eSelectCluster
;
3656 case nsIDOMWindowUtils::SELECT_WORD
:
3657 amount
= eSelectWord
;
3659 case nsIDOMWindowUtils::SELECT_LINE
:
3660 amount
= eSelectLine
;
3662 case nsIDOMWindowUtils::SELECT_BEGINLINE
:
3663 amount
= eSelectBeginLine
;
3665 case nsIDOMWindowUtils::SELECT_ENDLINE
:
3666 amount
= eSelectEndLine
;
3668 case nsIDOMWindowUtils::SELECT_PARAGRAPH
:
3669 amount
= eSelectParagraph
;
3671 case nsIDOMWindowUtils::SELECT_WORDNOSPACE
:
3672 amount
= eSelectWordNoSpace
;
3675 return NS_ERROR_INVALID_ARG
;
3678 PresShell
* presShell
= GetPresShell();
3680 return NS_ERROR_UNEXPECTED
;
3683 // The root frame for this content window
3684 nsIFrame
* rootFrame
= presShell
->GetRootFrame();
3686 return NS_ERROR_UNEXPECTED
;
3689 // Get the target frame at the client coordinates passed to us
3691 nsCOMPtr
<nsIWidget
> widget
= GetWidget(&offset
);
3692 LayoutDeviceIntPoint pt
=
3693 nsContentUtils::ToWidgetPoint(CSSPoint(aX
, aY
), offset
, GetPresContext());
3694 nsPoint ptInRoot
= nsLayoutUtils::GetEventCoordinatesRelativeTo(
3695 widget
, pt
, RelativeTo
{rootFrame
});
3696 nsIFrame
* targetFrame
=
3697 nsLayoutUtils::GetFrameForPoint(RelativeTo
{rootFrame
}, ptInRoot
);
3698 // This can happen if the page hasn't loaded yet or if the point
3699 // is outside the frame.
3701 return NS_ERROR_INVALID_ARG
;
3704 // Convert point to coordinates relative to the target frame, which is
3705 // what targetFrame's SelectByTypeAtPoint expects.
3706 nsPoint relPoint
= nsLayoutUtils::GetEventCoordinatesRelativeTo(
3707 widget
, pt
, RelativeTo
{targetFrame
});
3709 const RefPtr
<nsPresContext
> pinnedPresContext
{GetPresContext()};
3710 nsresult rv
= targetFrame
->SelectByTypeAtPoint(
3711 pinnedPresContext
, relPoint
, amount
, amount
, nsIFrame::SELECT_ACCUMULATE
);
3712 *_retval
= !NS_FAILED(rv
);
3716 static Document::additionalSheetType
convertSheetType(uint32_t aSheetType
) {
3717 switch (aSheetType
) {
3718 case nsDOMWindowUtils::AGENT_SHEET
:
3719 return Document::eAgentSheet
;
3720 case nsDOMWindowUtils::USER_SHEET
:
3721 return Document::eUserSheet
;
3722 case nsDOMWindowUtils::AUTHOR_SHEET
:
3723 return Document::eAuthorSheet
;
3725 NS_ASSERTION(false, "wrong type");
3726 // we must return something although this should never happen
3727 return Document::AdditionalSheetTypeCount
;
3732 nsDOMWindowUtils::LoadSheet(nsIURI
* aSheetURI
, uint32_t aSheetType
) {
3733 NS_ENSURE_ARG_POINTER(aSheetURI
);
3734 NS_ENSURE_ARG(aSheetType
== AGENT_SHEET
|| aSheetType
== USER_SHEET
||
3735 aSheetType
== AUTHOR_SHEET
);
3737 nsCOMPtr
<Document
> doc
= GetDocument();
3738 NS_ENSURE_TRUE(doc
, NS_ERROR_FAILURE
);
3740 Document::additionalSheetType type
= convertSheetType(aSheetType
);
3742 return doc
->LoadAdditionalStyleSheet(type
, aSheetURI
);
3746 nsDOMWindowUtils::LoadSheetUsingURIString(const nsACString
& aSheetURI
,
3747 uint32_t aSheetType
) {
3748 nsCOMPtr
<nsIURI
> uri
;
3749 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), aSheetURI
);
3750 NS_ENSURE_SUCCESS(rv
, rv
);
3752 return LoadSheet(uri
, aSheetType
);
3756 nsDOMWindowUtils::AddSheet(nsIPreloadedStyleSheet
* aSheet
,
3757 uint32_t aSheetType
) {
3758 NS_ENSURE_ARG_POINTER(aSheet
);
3759 NS_ENSURE_ARG(aSheetType
== AGENT_SHEET
|| aSheetType
== USER_SHEET
||
3760 aSheetType
== AUTHOR_SHEET
);
3762 nsCOMPtr
<Document
> doc
= GetDocument();
3763 NS_ENSURE_TRUE(doc
, NS_ERROR_FAILURE
);
3765 StyleSheet
* sheet
= nullptr;
3766 auto* preloadedSheet
= static_cast<PreloadedStyleSheet
*>(aSheet
);
3767 nsresult rv
= preloadedSheet
->GetSheet(&sheet
);
3768 NS_ENSURE_SUCCESS(rv
, rv
);
3769 NS_ENSURE_TRUE(sheet
, NS_ERROR_FAILURE
);
3771 if (sheet
->GetAssociatedDocumentOrShadowRoot()) {
3772 return NS_ERROR_INVALID_ARG
;
3775 Document::additionalSheetType type
= convertSheetType(aSheetType
);
3776 return doc
->AddAdditionalStyleSheet(type
, sheet
);
3780 nsDOMWindowUtils::RemoveSheet(nsIURI
* aSheetURI
, uint32_t aSheetType
) {
3781 NS_ENSURE_ARG_POINTER(aSheetURI
);
3782 NS_ENSURE_ARG(aSheetType
== AGENT_SHEET
|| aSheetType
== USER_SHEET
||
3783 aSheetType
== AUTHOR_SHEET
);
3785 nsCOMPtr
<Document
> doc
= GetDocument();
3786 NS_ENSURE_TRUE(doc
, NS_ERROR_FAILURE
);
3788 Document::additionalSheetType type
= convertSheetType(aSheetType
);
3790 doc
->RemoveAdditionalStyleSheet(type
, aSheetURI
);
3795 nsDOMWindowUtils::RemoveSheetUsingURIString(const nsACString
& aSheetURI
,
3796 uint32_t aSheetType
) {
3797 nsCOMPtr
<nsIURI
> uri
;
3798 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), aSheetURI
);
3799 NS_ENSURE_SUCCESS(rv
, rv
);
3801 return RemoveSheet(uri
, aSheetType
);
3805 nsDOMWindowUtils::GetIsHandlingUserInput(bool* aHandlingUserInput
) {
3806 *aHandlingUserInput
= UserActivation::IsHandlingUserInput();
3812 nsDOMWindowUtils::GetMillisSinceLastUserInput(
3813 double* aMillisSinceLastUserInput
) {
3814 TimeStamp lastInput
= UserActivation::LatestUserInputStart();
3815 if (lastInput
.IsNull()) {
3816 *aMillisSinceLastUserInput
= -1.0f
;
3820 *aMillisSinceLastUserInput
= (TimeStamp::Now() - lastInput
).ToMilliseconds();
3825 nsDOMWindowUtils::AllowScriptsToClose() {
3826 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
3827 NS_ENSURE_STATE(window
);
3828 nsGlobalWindowOuter::Cast(window
)->AllowScriptsToClose();
3833 nsDOMWindowUtils::GetIsParentWindowMainWidgetVisible(bool* aIsVisible
) {
3834 if (!XRE_IsParentProcess()) {
3836 "IsParentWindowMainWidgetVisible is only available in the parent "
3840 // this should reflect the "is parent window visible" logic in
3841 // nsWindowWatcher::OpenWindowInternal()
3842 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
3843 NS_ENSURE_STATE(window
);
3845 nsCOMPtr
<nsIWidget
> parentWidget
;
3846 nsIDocShell
* docShell
= window
->GetDocShell();
3848 nsCOMPtr
<nsIDocShellTreeOwner
> parentTreeOwner
;
3849 docShell
->GetTreeOwner(getter_AddRefs(parentTreeOwner
));
3850 nsCOMPtr
<nsIBaseWindow
> parentWindow(do_GetInterface(parentTreeOwner
));
3852 parentWindow
->GetMainWidget(getter_AddRefs(parentWidget
));
3855 if (!parentWidget
) {
3856 return NS_ERROR_NOT_AVAILABLE
;
3859 *aIsVisible
= parentWidget
->IsVisible();
3864 nsDOMWindowUtils::IsNodeDisabledForEvents(nsINode
* aNode
, bool* aRetVal
) {
3866 nsINode
* node
= aNode
;
3868 if (node
->IsHTMLFormControlElement()) {
3869 nsGenericHTMLElement
* element
= nsGenericHTMLElement::FromNode(node
);
3870 WidgetEvent
event(true, eVoidEvent
);
3871 if (element
&& element
->IsDisabledForEvents(&event
)) {
3876 node
= node
->GetParentNode();
3883 nsDOMWindowUtils::DispatchEventToChromeOnly(EventTarget
* aTarget
, Event
* aEvent
,
3886 NS_ENSURE_STATE(aTarget
&& aEvent
);
3887 aEvent
->WidgetEventPtr()->mFlags
.mOnlyChromeDispatch
= true;
3889 aTarget
->DispatchEvent(*aEvent
, CallerType::System
, IgnoreErrors());
3893 static Result
<nsIFrame
*, nsresult
> GetTargetFrame(
3894 const Element
* aElement
, const nsAString
& aPseudoElement
) {
3895 nsIFrame
* frame
= aElement
->GetPrimaryFrame();
3896 if (!aPseudoElement
.IsEmpty()) {
3897 if (aPseudoElement
.EqualsLiteral("::before")) {
3898 frame
= nsLayoutUtils::GetBeforeFrame(aElement
);
3899 } else if (aPseudoElement
.EqualsLiteral("::after")) {
3900 frame
= nsLayoutUtils::GetAfterFrame(aElement
);
3902 return Err(NS_ERROR_INVALID_ARG
);
3908 static OMTAValue
GetOMTAValue(nsIFrame
* aFrame
, DisplayItemType aDisplayItemKey
,
3909 WebRenderBridgeChild
* aWebRenderBridgeChild
) {
3910 OMTAValue value
= mozilla::null_t();
3912 if (aWebRenderBridgeChild
) {
3913 RefPtr
<WebRenderAnimationData
> animationData
=
3914 GetWebRenderUserData
<WebRenderAnimationData
>(aFrame
,
3915 (uint32_t)aDisplayItemKey
);
3916 if (animationData
) {
3917 aWebRenderBridgeChild
->SendGetAnimationValue(
3918 animationData
->GetAnimationInfo().GetCompositorAnimationsId(),
3926 nsDOMWindowUtils::GetOMTAStyle(Element
* aElement
, const nsAString
& aProperty
,
3927 const nsAString
& aPseudoElement
,
3928 nsAString
& aResult
) {
3930 return NS_ERROR_INVALID_ARG
;
3933 auto frameOrError
= GetTargetFrame(aElement
, aPseudoElement
);
3934 if (frameOrError
.isErr()) {
3935 return frameOrError
.unwrapErr();
3937 nsIFrame
* frame
= frameOrError
.unwrap();
3939 RefPtr
<nsROCSSPrimitiveValue
> cssValue
= nullptr;
3940 if (frame
&& nsLayoutUtils::AreAsyncAnimationsEnabled()) {
3941 if (aProperty
.EqualsLiteral("opacity")) {
3942 OMTAValue value
= GetOMTAValue(frame
, DisplayItemType::TYPE_OPACITY
,
3943 GetWebRenderBridge());
3944 if (value
.type() == OMTAValue::Tfloat
) {
3945 cssValue
= new nsROCSSPrimitiveValue
;
3946 cssValue
->SetNumber(value
.get_float());
3948 } else if (aProperty
.EqualsLiteral("transform") ||
3949 aProperty
.EqualsLiteral("translate") ||
3950 aProperty
.EqualsLiteral("rotate") ||
3951 aProperty
.EqualsLiteral("scale") ||
3952 aProperty
.EqualsLiteral("offset-path") ||
3953 aProperty
.EqualsLiteral("offset-distance") ||
3954 aProperty
.EqualsLiteral("offset-rotate") ||
3955 aProperty
.EqualsLiteral("offset-anchor") ||
3956 aProperty
.EqualsLiteral("offset-position")) {
3957 OMTAValue value
= GetOMTAValue(frame
, DisplayItemType::TYPE_TRANSFORM
,
3958 GetWebRenderBridge());
3959 if (value
.type() == OMTAValue::TMatrix4x4
) {
3960 cssValue
= nsComputedDOMStyle::MatrixToCSSValue(value
.get_Matrix4x4());
3962 } else if (aProperty
.EqualsLiteral("background-color")) {
3963 OMTAValue value
= GetOMTAValue(
3964 frame
, DisplayItemType::TYPE_BACKGROUND_COLOR
, GetWebRenderBridge());
3965 if (value
.type() == OMTAValue::Tnscolor
) {
3966 nsStyleUtil::GetSerializedColorValue(value
.get_nscolor(), aResult
);
3973 cssValue
->GetCssText(aResult
);
3982 class HandlingUserInputHelper final
: public nsIJSRAIIHelper
{
3984 explicit HandlingUserInputHelper(bool aHandlingUserInput
);
3987 NS_DECL_NSIJSRAIIHELPER
3990 ~HandlingUserInputHelper();
3992 bool mHandlingUserInput
;
3993 bool mDestructCalled
= false;
3996 NS_IMPL_ISUPPORTS(HandlingUserInputHelper
, nsIJSRAIIHelper
)
3998 HandlingUserInputHelper::HandlingUserInputHelper(bool aHandlingUserInput
)
3999 : mHandlingUserInput(aHandlingUserInput
) {
4000 if (aHandlingUserInput
) {
4001 UserActivation::StartHandlingUserInput(eVoidEvent
);
4005 HandlingUserInputHelper::~HandlingUserInputHelper() {
4006 // We assert, but just in case, make sure we notify the ESM.
4007 MOZ_ASSERT(mDestructCalled
);
4008 if (!mDestructCalled
) {
4014 HandlingUserInputHelper::Destruct() {
4015 if (NS_WARN_IF(mDestructCalled
)) {
4016 return NS_ERROR_FAILURE
;
4019 mDestructCalled
= true;
4020 if (mHandlingUserInput
) {
4021 UserActivation::StopHandlingUserInput(eVoidEvent
);
4027 } // unnamed namespace
4030 nsDOMWindowUtils::SetHandlingUserInput(bool aHandlingUserInput
,
4031 nsIJSRAIIHelper
** aHelper
) {
4032 if (aHandlingUserInput
) {
4033 if (Document
* doc
= GetDocument()) {
4034 doc
->NotifyUserGestureActivation();
4037 auto helper
= MakeRefPtr
<HandlingUserInputHelper
>(aHandlingUserInput
);
4038 helper
.forget(aHelper
);
4043 nsDOMWindowUtils::IsKeyboardEventUserActivity(Event
* aEvent
, bool* aResult
) {
4044 NS_ENSURE_STATE(aEvent
);
4045 if (!aEvent
->AsKeyboardEvent()) {
4046 return NS_ERROR_INVALID_ARG
;
4049 WidgetEvent
* internalEvent
= aEvent
->WidgetEventPtr();
4050 NS_ENSURE_STATE(internalEvent
);
4051 *aResult
= EventStateManager::IsKeyboardEventUserActivity(internalEvent
);
4056 nsDOMWindowUtils::GetContentAPZTestData(
4057 JSContext
* aContext
, JS::MutableHandle
<JS::Value
> aOutContentTestData
) {
4058 if (nsIWidget
* widget
= GetWidget()) {
4059 WindowRenderer
* renderer
= widget
->GetWindowRenderer();
4063 if (WebRenderLayerManager
* wr
= renderer
->AsWebRender()) {
4064 if (!wr
->GetAPZTestData().ToJS(aOutContentTestData
, aContext
)) {
4065 return NS_ERROR_FAILURE
;
4074 nsDOMWindowUtils::GetCompositorAPZTestData(
4075 JSContext
* aContext
, JS::MutableHandle
<JS::Value
> aOutCompositorTestData
) {
4076 if (nsIWidget
* widget
= GetWidget()) {
4077 WindowRenderer
* renderer
= widget
->GetWindowRenderer();
4081 APZTestData compositorSideData
;
4082 if (WebRenderLayerManager
* wr
= renderer
->AsWebRender()) {
4083 if (!wr
->WrBridge()) {
4084 return NS_ERROR_UNEXPECTED
;
4086 if (!wr
->WrBridge()->SendGetAPZTestData(&compositorSideData
)) {
4087 return NS_ERROR_FAILURE
;
4090 if (!compositorSideData
.ToJS(aOutCompositorTestData
, aContext
)) {
4091 return NS_ERROR_FAILURE
;
4099 nsDOMWindowUtils::PostRestyleSelfEvent(Element
* aElement
) {
4101 return NS_ERROR_INVALID_ARG
;
4104 nsLayoutUtils::PostRestyleEvent(aElement
, RestyleHint::RESTYLE_SELF
,
4110 nsDOMWindowUtils::SetChromeMargin(int32_t aTop
, int32_t aRight
, int32_t aBottom
,
4112 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
4114 nsCOMPtr
<nsIBaseWindow
> baseWindow
=
4115 do_QueryInterface(window
->GetDocShell());
4117 nsCOMPtr
<nsIWidget
> widget
;
4118 baseWindow
->GetMainWidget(getter_AddRefs(widget
));
4120 LayoutDeviceIntMargin
margins(aTop
, aRight
, aBottom
, aLeft
);
4121 return widget
->SetNonClientMargins(margins
);
4130 nsDOMWindowUtils::SetResizeMargin(int32_t aResizeMargin
) {
4131 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
4133 nsCOMPtr
<nsIBaseWindow
> baseWindow
=
4134 do_QueryInterface(window
->GetDocShell());
4136 nsCOMPtr
<nsIWidget
> widget
;
4137 baseWindow
->GetMainWidget(getter_AddRefs(widget
));
4139 CSSToLayoutDeviceScale scaleFactor
= widget
->GetDefaultScale();
4140 widget
->SetResizeMargin(
4141 (CSSCoord(float(aResizeMargin
)) * scaleFactor
).Rounded());
4150 nsDOMWindowUtils::GetFrameUniformityTestData(
4151 JSContext
* aContext
, JS::MutableHandle
<JS::Value
> aOutFrameUniformity
) {
4152 nsIWidget
* widget
= GetWidget();
4154 return NS_ERROR_NOT_AVAILABLE
;
4157 WindowRenderer
* renderer
= widget
->GetWindowRenderer();
4159 return NS_ERROR_NOT_AVAILABLE
;
4162 FrameUniformityData outData
;
4163 renderer
->GetFrameUniformity(&outData
);
4164 outData
.ToJS(aOutFrameUniformity
, aContext
);
4169 nsDOMWindowUtils::XpconnectArgument(nsISupports
* aObj
) {
4175 nsDOMWindowUtils::AskPermission(nsIContentPermissionRequest
* aRequest
) {
4176 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
4177 return nsContentPermissionUtils::AskPermission(
4178 aRequest
, window
->GetCurrentInnerWindow());
4182 nsDOMWindowUtils::GetRestyleGeneration(uint64_t* aResult
) {
4183 nsPresContext
* presContext
= GetPresContext();
4185 return NS_ERROR_NOT_AVAILABLE
;
4188 *aResult
= presContext
->GetRestyleGeneration();
4193 nsDOMWindowUtils::GetFramesConstructed(uint64_t* aResult
) {
4194 nsPresContext
* presContext
= GetPresContext();
4196 return NS_ERROR_NOT_AVAILABLE
;
4199 *aResult
= presContext
->FramesConstructedCount();
4204 nsDOMWindowUtils::GetFramesReflowed(uint64_t* aResult
) {
4205 nsPresContext
* presContext
= GetPresContext();
4207 return NS_ERROR_NOT_AVAILABLE
;
4210 *aResult
= presContext
->FramesReflowedCount();
4215 nsDOMWindowUtils::GetAnimationTriggeredRestyles(uint64_t* aResult
) {
4216 nsPresContext
* presContext
= GetPresContext();
4218 return NS_ERROR_NOT_AVAILABLE
;
4221 *aResult
= presContext
->AnimationTriggeredRestylesCount();
4226 nsDOMWindowUtils::GetRefreshDriverHasPendingTick(bool* aResult
) {
4227 nsPresContext
* presContext
= GetPresContext();
4229 return NS_ERROR_NOT_AVAILABLE
;
4232 *aResult
= presContext
->RefreshDriver()->HasPendingTick();
4237 nsDOMWindowUtils::EnterChaosMode() {
4238 ChaosMode::enterChaosMode();
4243 nsDOMWindowUtils::LeaveChaosMode() {
4244 ChaosMode::leaveChaosMode();
4249 nsDOMWindowUtils::TriggerDeviceReset() {
4250 if (!XRE_IsParentProcess()) {
4251 return NS_ERROR_NOT_AVAILABLE
;
4254 GPUProcessManager
* pm
= GPUProcessManager::Get();
4256 pm
->SimulateDeviceReset();
4262 nsDOMWindowUtils::HasRuleProcessorUsedByMultipleStyleSets(uint32_t aSheetType
,
4264 PresShell
* presShell
= GetPresShell();
4266 return NS_ERROR_FAILURE
;
4269 return presShell
->HasRuleProcessorUsedByMultipleStyleSets(aSheetType
,
4274 nsDOMWindowUtils::RespectDisplayPortSuppression(bool aEnabled
) {
4275 RefPtr
<PresShell
> presShell
= GetPresShell();
4276 presShell
->RespectDisplayportSuppression(aEnabled
);
4281 nsDOMWindowUtils::ForceReflowInterrupt() {
4282 nsPresContext
* pc
= GetPresContext();
4284 return NS_ERROR_NOT_AVAILABLE
;
4286 pc
->SetPendingInterruptFromTest();
4291 nsDOMWindowUtils::TerminateGPUProcess() {
4292 GPUProcessManager
* pm
= GPUProcessManager::Get();
4300 nsDOMWindowUtils::GetGpuProcessPid(int32_t* aPid
) {
4301 GPUProcessManager
* pm
= GPUProcessManager::Get();
4303 *aPid
= pm
->GPUProcessPid();
4311 struct StateTableEntry
{
4312 const char* mStateString
;
4313 ElementState mState
;
4316 static constexpr StateTableEntry kManuallyManagedStates
[] = {
4317 {"autofill", ElementState::AUTOFILL
},
4318 // :-moz-autofill-preview implies :autofill.
4319 {"-moz-autofill-preview",
4320 ElementState::AUTOFILL_PREVIEW
| ElementState::AUTOFILL
},
4321 {nullptr, ElementState()},
4324 static_assert(!kManuallyManagedStates
[ArrayLength(kManuallyManagedStates
) - 1]
4326 "last kManuallyManagedStates entry must be a sentinel with "
4327 "mStateString == nullptr");
4329 static ElementState
GetEventStateForString(const nsAString
& aStateString
) {
4330 for (const StateTableEntry
* entry
= kManuallyManagedStates
;
4331 entry
->mStateString
; ++entry
) {
4332 if (aStateString
.EqualsASCII(entry
->mStateString
)) {
4333 return entry
->mState
;
4336 return ElementState();
4340 nsDOMWindowUtils::AddManuallyManagedState(Element
* aElement
,
4341 const nsAString
& aStateString
) {
4343 return NS_ERROR_INVALID_ARG
;
4346 ElementState state
= GetEventStateForString(aStateString
);
4347 if (state
.IsEmpty()) {
4348 return NS_ERROR_INVALID_ARG
;
4351 aElement
->AddStates(state
);
4356 nsDOMWindowUtils::RemoveManuallyManagedState(Element
* aElement
,
4357 const nsAString
& aStateString
) {
4359 return NS_ERROR_INVALID_ARG
;
4362 ElementState state
= GetEventStateForString(aStateString
);
4363 if (state
.IsEmpty()) {
4364 return NS_ERROR_INVALID_ARG
;
4367 aElement
->RemoveStates(state
);
4372 nsDOMWindowUtils::GetStorageUsage(Storage
* aStorage
, int64_t* aRetval
) {
4374 return NS_ERROR_UNEXPECTED
;
4377 *aRetval
= aStorage
->GetOriginQuotaUsage();
4383 nsDOMWindowUtils::GetDirectionFromText(const nsAString
& aString
,
4385 Directionality dir
=
4386 ::GetDirectionFromText(aString
.BeginReading(), aString
.Length(), nullptr);
4388 case Directionality::Unset
:
4389 *aRetval
= nsIDOMWindowUtils::DIRECTION_NOT_SET
;
4391 case Directionality::Rtl
:
4392 *aRetval
= nsIDOMWindowUtils::DIRECTION_RTL
;
4394 case Directionality::Ltr
:
4395 *aRetval
= nsIDOMWindowUtils::DIRECTION_LTR
;
4397 case Directionality::Auto
:
4398 MOZ_ASSERT_UNREACHABLE(
4399 "GetDirectionFromText should never return this value");
4400 return NS_ERROR_FAILURE
;
4406 nsDOMWindowUtils::EnsureDirtyRootFrame() {
4407 Document
* doc
= GetDocument();
4408 PresShell
* presShell
= doc
? doc
->GetPresShell() : nullptr;
4411 return NS_ERROR_FAILURE
;
4414 nsIFrame
* frame
= presShell
->GetRootFrame();
4416 return NS_ERROR_FAILURE
;
4419 presShell
->FrameNeedsReflow(
4420 frame
, IntrinsicDirty::FrameAncestorsAndDescendants
, NS_FRAME_IS_DIRTY
);
4424 NS_INTERFACE_MAP_BEGIN(nsTranslationNodeList
)
4425 NS_INTERFACE_MAP_ENTRY(nsISupports
)
4426 NS_INTERFACE_MAP_ENTRY(nsITranslationNodeList
)
4427 NS_INTERFACE_MAP_END
4429 NS_IMPL_ADDREF(nsTranslationNodeList
)
4430 NS_IMPL_RELEASE(nsTranslationNodeList
)
4433 nsTranslationNodeList::Item(uint32_t aIndex
, nsINode
** aRetVal
) {
4434 NS_ENSURE_ARG_POINTER(aRetVal
);
4435 NS_IF_ADDREF(*aRetVal
= mNodes
.SafeElementAt(aIndex
));
4440 nsTranslationNodeList::IsTranslationRootAtIndex(uint32_t aIndex
,
4442 NS_ENSURE_ARG_POINTER(aRetVal
);
4443 if (aIndex
>= mLength
) {
4448 *aRetVal
= mNodeIsRoot
.ElementAt(aIndex
);
4453 nsTranslationNodeList::GetLength(uint32_t* aRetVal
) {
4454 NS_ENSURE_ARG_POINTER(aRetVal
);
4460 nsDOMWindowUtils::WrCapture() {
4461 if (WebRenderBridgeChild
* wrbc
= GetWebRenderBridge()) {
4468 nsDOMWindowUtils::WrStartCaptureSequence(const nsACString
& aPath
,
4470 if (WebRenderBridgeChild
* wrbc
= GetWebRenderBridge()) {
4471 wrbc
->StartCaptureSequence(nsCString(aPath
), aFlags
);
4477 nsDOMWindowUtils::WrStopCaptureSequence() {
4478 if (WebRenderBridgeChild
* wrbc
= GetWebRenderBridge()) {
4479 wrbc
->StopCaptureSequence();
4485 nsDOMWindowUtils::SetCompositionRecording(bool aValue
, Promise
** aOutPromise
) {
4486 return aValue
? StartCompositionRecording(aOutPromise
)
4487 : StopCompositionRecording(true, aOutPromise
);
4491 nsDOMWindowUtils::StartCompositionRecording(Promise
** aOutPromise
) {
4492 NS_ENSURE_ARG(aOutPromise
);
4493 *aOutPromise
= nullptr;
4495 nsCOMPtr
<nsPIDOMWindowOuter
> outer
= do_QueryReferent(mWindow
);
4496 NS_ENSURE_STATE(outer
);
4497 nsCOMPtr
<nsPIDOMWindowInner
> inner
= outer
->GetCurrentInnerWindow();
4498 NS_ENSURE_STATE(inner
);
4501 RefPtr
<Promise
> promise
= Promise::Create(inner
->AsGlobal(), err
);
4502 if (NS_WARN_IF(err
.Failed())) {
4503 return err
.StealNSResult();
4506 CompositorBridgeChild
* cbc
= GetCompositorBridge();
4507 if (NS_WARN_IF(!cbc
)) {
4508 promise
->MaybeReject(NS_ERROR_UNEXPECTED
);
4510 cbc
->SendBeginRecording(TimeStamp::Now())
4512 GetCurrentSerialEventTarget(), __func__
,
4513 [promise
](const bool& aSuccess
) {
4515 promise
->MaybeResolve(true);
4517 promise
->MaybeRejectWithInvalidStateError(
4518 "The composition recorder is already running.");
4521 [promise
](const mozilla::ipc::ResponseRejectReason
&) {
4522 promise
->MaybeRejectWithInvalidStateError(
4523 "Could not start the composition recorder.");
4527 promise
.forget(aOutPromise
);
4531 static bool WriteRecordingToDisk(const FrameRecording
& aRecording
,
4532 double aUnixStartMS
) {
4533 // The directory name contains the unix timestamp for when recording started,
4534 // because we want the consumer of these files to be able to compute an
4535 // absolute timestamp of each screenshot. That allows them to align
4536 // screenshots with timed data from other sources, such as Gecko profiler
4537 // information. The time of each screenshot is part of the screenshot's
4538 // filename, expressed as milliseconds from the recording start.
4539 std::stringstream recordingDirectory
;
4540 recordingDirectory
<< gfxVars::LayersWindowRecordingPath()
4541 << "windowrecording-" << int64_t(aUnixStartMS
);
4544 _mkdir(recordingDirectory
.str().c_str());
4546 mkdir(recordingDirectory
.str().c_str(), 0777);
4549 auto byteSpan
= aRecording
.bytes().AsSpan();
4553 for (const auto& frame
: aRecording
.frames()) {
4554 const uint32_t frameBufferLength
= frame
.length();
4555 if (frameBufferLength
> byteSpan
.Length()) {
4559 const auto frameSpan
= byteSpan
.To(frameBufferLength
);
4560 byteSpan
= byteSpan
.From(frameBufferLength
);
4562 const double frameTimeMS
=
4563 (frame
.timeOffset() - aRecording
.startTime()).ToMilliseconds();
4565 std::stringstream filename
;
4566 filename
<< recordingDirectory
.str() << "/frame-" << i
<< "-"
4567 << uint32_t(frameTimeMS
) << ".png";
4569 FILE* file
= fopen(filename
.str().c_str(), "wb");
4574 const size_t bytesWritten
=
4575 fwrite(frameSpan
.Elements(), sizeof(uint8_t), frameSpan
.Length(), file
);
4579 if (bytesWritten
< frameSpan
.Length()) {
4586 return byteSpan
.Length() == 0;
4589 static Maybe
<DOMCollectedFrames
> ConvertCompositionRecordingFramesToDom(
4590 const FrameRecording
& aRecording
, double aUnixStartMS
) {
4591 auto byteSpan
= aRecording
.bytes().AsSpan();
4593 nsTArray
<DOMCollectedFrame
> domFrames
;
4595 for (const auto& recordedFrame
: aRecording
.frames()) {
4596 const uint32_t frameBufferLength
= recordedFrame
.length();
4597 if (frameBufferLength
> byteSpan
.Length()) {
4601 const auto frameSpan
= byteSpan
.To(frameBufferLength
);
4602 byteSpan
= byteSpan
.From(frameBufferLength
);
4606 dataUri
.AppendLiteral("data:image/png;base64,");
4609 Base64EncodeAppend(reinterpret_cast<const char*>(frameSpan
.Elements()),
4610 frameSpan
.Length(), dataUri
);
4611 if (NS_FAILED(rv
)) {
4615 DOMCollectedFrame domFrame
;
4616 domFrame
.mTimeOffset
=
4617 (recordedFrame
.timeOffset() - aRecording
.startTime()).ToMilliseconds();
4618 domFrame
.mDataUri
= std::move(dataUri
);
4620 domFrames
.AppendElement(std::move(domFrame
));
4623 if (byteSpan
.Length() != 0) {
4627 DOMCollectedFrames result
;
4629 result
.mRecordingStart
= aUnixStartMS
;
4630 result
.mFrames
= std::move(domFrames
);
4632 return Some(std::move(result
));
4636 nsDOMWindowUtils::StopCompositionRecording(bool aWriteToDisk
,
4637 Promise
** aOutPromise
) {
4638 NS_ENSURE_ARG_POINTER(aOutPromise
);
4639 *aOutPromise
= nullptr;
4641 nsCOMPtr
<nsPIDOMWindowOuter
> outer
= do_QueryReferent(mWindow
);
4642 NS_ENSURE_STATE(outer
);
4643 nsCOMPtr
<nsPIDOMWindowInner
> inner
= outer
->GetCurrentInnerWindow();
4644 NS_ENSURE_STATE(inner
);
4647 RefPtr
<Promise
> promise
= Promise::Create(inner
->AsGlobal(), err
);
4648 if (NS_WARN_IF(err
.Failed())) {
4649 return err
.StealNSResult();
4652 RefPtr
<Promise
>(promise
).forget(aOutPromise
);
4654 CompositorBridgeChild
* cbc
= GetCompositorBridge();
4655 if (NS_WARN_IF(!cbc
)) {
4656 promise
->MaybeReject(NS_ERROR_UNEXPECTED
);
4660 cbc
->SendEndRecording()->Then(
4661 GetCurrentSerialEventTarget(), __func__
,
4662 [promise
, aWriteToDisk
](Maybe
<FrameRecording
>&& aRecording
) {
4664 promise
->MaybeRejectWithUnknownError("Failed to get frame recording");
4668 // We need to know when the recording started in Unix Time.
4669 // Unfortunately, the recording start time is an opaque Timestamp that
4670 // can only be used to calculate a duration.
4672 // This is not great, but we are going to get Now() twice in close
4673 // proximity, one in Unix Time and the other in Timestamp time. Then we
4674 // can subtract the length of the recording from the current Unix Time
4675 // to get the Unix start time.
4676 const TimeStamp timestampNow
= TimeStamp::Now();
4677 const int64_t unixNowUS
= PR_Now();
4679 const TimeDuration recordingLength
=
4680 timestampNow
- aRecording
->startTime();
4681 const double unixNowMS
= double(unixNowUS
) / 1000.0;
4682 const double unixStartMS
= unixNowMS
- recordingLength
.ToMilliseconds();
4685 if (!WriteRecordingToDisk(*aRecording
, unixStartMS
)) {
4686 promise
->MaybeRejectWithUnknownError(
4687 "Failed to write recording to disk");
4690 promise
->MaybeResolveWithUndefined();
4692 auto maybeDomFrames
=
4693 ConvertCompositionRecordingFramesToDom(*aRecording
, unixStartMS
);
4694 if (!maybeDomFrames
) {
4695 promise
->MaybeRejectWithUnknownError(
4696 "Unable to base64-encode recorded frames");
4699 promise
->MaybeResolve(*maybeDomFrames
);
4702 [promise
](const mozilla::ipc::ResponseRejectReason
&) {
4703 promise
->MaybeRejectWithUnknownError(
4704 "IPC failed getting composition recording");
4711 nsDOMWindowUtils::SetSystemFont(const nsACString
& aFontName
) {
4712 nsIWidget
* widget
= GetWidget();
4717 nsAutoCString
fontName(aFontName
);
4718 return widget
->SetSystemFont(fontName
);
4722 nsDOMWindowUtils::GetSystemFont(nsACString
& aFontName
) {
4723 nsIWidget
* widget
= GetWidget();
4728 nsAutoCString fontName
;
4729 widget
->GetSystemFont(fontName
);
4730 aFontName
.Assign(fontName
);
4735 nsDOMWindowUtils::IsCssPropertyRecordedInUseCounter(const nsACString
& aPropName
,
4739 Document
* doc
= GetDocument();
4740 if (!doc
|| !doc
->GetStyleUseCounters()) {
4741 return NS_ERROR_FAILURE
;
4744 bool knownProp
= false;
4745 *aRecorded
= Servo_IsCssPropertyRecordedInUseCounter(
4746 doc
->GetStyleUseCounters(), &aPropName
, &knownProp
);
4747 return knownProp
? NS_OK
: NS_ERROR_FAILURE
;
4751 nsDOMWindowUtils::IsCoepCredentialless(bool* aResult
) {
4752 Document
* doc
= GetDocument();
4754 return NS_ERROR_FAILURE
;
4757 *aResult
= net::IsCoepCredentiallessEnabled(
4758 doc
->Trials().IsEnabled(OriginTrial::CoepCredentialless
));
4763 nsDOMWindowUtils::GetLayersId(uint64_t* aOutLayersId
) {
4764 nsIWidget
* widget
= GetWidget();
4766 return NS_ERROR_FAILURE
;
4768 BrowserChild
* child
= widget
->GetOwningBrowserChild();
4770 return NS_ERROR_FAILURE
;
4772 *aOutLayersId
= (uint64_t)child
->GetLayersId();
4777 nsDOMWindowUtils::GetPaintCount(uint64_t* aPaintCount
) {
4778 auto* presShell
= GetPresShell();
4779 *aPaintCount
= presShell
? presShell
->GetPaintCount() : 0;
4784 nsDOMWindowUtils::GetWebrtcRawDeviceId(nsAString
& aRawDeviceId
) {
4785 if (!XRE_IsParentProcess()) {
4787 "GetWebrtcRawDeviceId is only available in the parent "
4791 nsIWidget
* widget
= GetWidget();
4793 return NS_ERROR_FAILURE
;
4796 int64_t rawDeviceId
=
4797 (int64_t)(widget
->GetNativeData(NS_NATIVE_WINDOW_WEBRTC_DEVICE_ID
));
4799 return NS_ERROR_FAILURE
;
4802 aRawDeviceId
.AppendInt(rawDeviceId
);
4807 nsDOMWindowUtils::GetEffectivelyThrottlesFrameRequests(bool* aResult
) {
4808 Document
* doc
= GetDocument();
4810 return NS_ERROR_FAILURE
;
4812 *aResult
= !doc
->WouldScheduleFrameRequestCallbacks() ||
4813 doc
->ShouldThrottleFrameRequests();
4818 nsDOMWindowUtils::ResetMobileViewportManager() {
4819 if (RefPtr
<PresShell
> presShell
= GetPresShell()) {
4820 if (auto mvm
= presShell
->GetMobileViewportManager()) {
4821 mvm
->SetInitialViewport();
4825 // Unable to reset, so let's error out
4826 return NS_ERROR_FAILURE
;
4830 nsDOMWindowUtils::GetSuspendedByBrowsingContextGroup(bool* aResult
) {
4831 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
4832 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
4834 nsCOMPtr
<nsPIDOMWindowInner
> inner
= window
->GetCurrentInnerWindow();
4835 NS_ENSURE_TRUE(inner
, NS_ERROR_FAILURE
);
4837 *aResult
= inner
->GetWasSuspendedByGroup();
4842 nsDOMWindowUtils::GetHasScrollLinkedEffect(bool* aResult
) {
4843 Document
* doc
= GetDocument();
4845 return NS_ERROR_FAILURE
;
4847 *aResult
= doc
->HasScrollLinkedEffect();
4852 nsDOMWindowUtils::GetOrientationLock(uint32_t* aOrientationLock
) {
4853 NS_WARNING("nsDOMWindowUtils::GetOrientationLock");
4855 nsIDocShell
* docShell
= GetDocShell();
4857 return NS_ERROR_FAILURE
;
4860 BrowsingContext
* bc
= docShell
->GetBrowsingContext();
4861 bc
= bc
? bc
->Top() : nullptr;
4863 return NS_ERROR_FAILURE
;
4866 *aOrientationLock
= static_cast<uint32_t>(bc
->GetOrientationLock());
4871 nsDOMWindowUtils::GetWheelScrollTarget(Element
** aResult
) {
4873 if (nsIFrame
* targetFrame
= WheelTransaction::GetScrollTargetFrame()) {
4874 NS_IF_ADDREF(*aResult
= Element::FromNodeOrNull(targetFrame
->GetContent()));
4880 nsDOMWindowUtils::SetHiDPIMode(bool aHiDPI
) {
4882 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
4883 if (!widget
) return NS_ERROR_FAILURE
;
4885 return widget
->SetHiDPIMode(aHiDPI
);
4887 return NS_ERROR_NOT_AVAILABLE
;
4892 nsDOMWindowUtils::RestoreHiDPIMode() {
4894 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
4895 if (!widget
) return NS_ERROR_FAILURE
;
4897 return widget
->RestoreHiDPIMode();
4899 return NS_ERROR_NOT_AVAILABLE
;