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/DOMCollectedFramesBinding.h"
28 #include "mozilla/dom/Event.h"
29 #include "mozilla/dom/Touch.h"
30 #include "mozilla/dom/UserActivation.h"
31 #include "mozilla/EventStateManager.h"
32 #include "mozilla/PendingAnimationTracker.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"
140 # include <sys/stat.h>
147 using namespace mozilla
;
148 using namespace mozilla::dom
;
149 using namespace mozilla::ipc
;
150 using namespace mozilla::layers
;
151 using namespace mozilla::widget
;
152 using namespace mozilla::gfx
;
156 class OldWindowSize
: public LinkedListElement
<OldWindowSize
> {
158 static void Set(nsIWeakReference
* aWindowRef
, const nsSize
& aSize
) {
159 OldWindowSize
* item
= GetItem(aWindowRef
);
163 item
= new OldWindowSize(aWindowRef
, aSize
);
164 sList
.insertBack(item
);
168 static nsSize
GetAndRemove(nsIWeakReference
* aWindowRef
) {
170 if (OldWindowSize
* item
= GetItem(aWindowRef
)) {
171 result
= item
->mSize
;
178 explicit OldWindowSize(nsIWeakReference
* aWindowRef
, const nsSize
& aSize
)
179 : mWindowRef(aWindowRef
), mSize(aSize
) {}
180 ~OldWindowSize() = default;
183 static OldWindowSize
* GetItem(nsIWeakReference
* aWindowRef
) {
184 OldWindowSize
* item
= sList
.getFirst();
185 while (item
&& item
->mWindowRef
!= aWindowRef
) {
186 item
= item
->getNext();
191 static LinkedList
<OldWindowSize
> sList
;
192 nsWeakPtr mWindowRef
;
198 class NativeInputRunnable final
: public PrioritizableRunnable
{
199 explicit NativeInputRunnable(already_AddRefed
<nsIRunnable
>&& aEvent
);
200 ~NativeInputRunnable() = default;
203 static already_AddRefed
<nsIRunnable
> Create(
204 already_AddRefed
<nsIRunnable
>&& aEvent
);
207 NativeInputRunnable::NativeInputRunnable(already_AddRefed
<nsIRunnable
>&& aEvent
)
208 : PrioritizableRunnable(std::move(aEvent
),
209 nsIRunnablePriority::PRIORITY_INPUT_HIGH
) {}
212 already_AddRefed
<nsIRunnable
> NativeInputRunnable::Create(
213 already_AddRefed
<nsIRunnable
>&& aEvent
) {
214 MOZ_ASSERT(NS_IsMainThread());
215 nsCOMPtr
<nsIRunnable
> event(new NativeInputRunnable(std::move(aEvent
)));
216 return event
.forget();
219 } // unnamed namespace
221 LinkedList
<OldWindowSize
> OldWindowSize::sList
;
223 NS_INTERFACE_MAP_BEGIN(nsDOMWindowUtils
)
224 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDOMWindowUtils
)
225 NS_INTERFACE_MAP_ENTRY(nsIDOMWindowUtils
)
226 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
229 NS_IMPL_ADDREF(nsDOMWindowUtils
)
230 NS_IMPL_RELEASE(nsDOMWindowUtils
)
232 nsDOMWindowUtils::nsDOMWindowUtils(nsGlobalWindowOuter
* aWindow
) {
233 nsCOMPtr
<nsISupports
> supports
= do_QueryObject(aWindow
);
234 mWindow
= do_GetWeakReference(supports
);
237 nsDOMWindowUtils::~nsDOMWindowUtils() { OldWindowSize::GetAndRemove(mWindow
); }
239 nsIDocShell
* nsDOMWindowUtils::GetDocShell() {
240 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
244 return window
->GetDocShell();
247 PresShell
* nsDOMWindowUtils::GetPresShell() {
248 nsIDocShell
* docShell
= GetDocShell();
252 return docShell
->GetPresShell();
255 nsPresContext
* nsDOMWindowUtils::GetPresContext() {
256 nsIDocShell
* docShell
= GetDocShell();
260 return docShell
->GetPresContext();
263 Document
* nsDOMWindowUtils::GetDocument() {
264 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
268 return window
->GetExtantDoc();
271 WebRenderBridgeChild
* nsDOMWindowUtils::GetWebRenderBridge() {
272 if (nsIWidget
* widget
= GetWidget()) {
273 if (WindowRenderer
* renderer
= widget
->GetWindowRenderer()) {
274 if (WebRenderLayerManager
* wr
= renderer
->AsWebRender()) {
275 return wr
->WrBridge();
282 CompositorBridgeChild
* nsDOMWindowUtils::GetCompositorBridge() {
283 if (nsIWidget
* widget
= GetWidget()) {
284 if (WindowRenderer
* renderer
= widget
->GetWindowRenderer()) {
285 if (CompositorBridgeChild
* cbc
= renderer
->GetCompositorBridgeChild()) {
294 nsDOMWindowUtils::GetLastOverWindowPointerLocationInCSSPixels(float* aX
,
296 const PresShell
* presShell
= GetPresShell();
297 const nsPresContext
* presContext
= GetPresContext();
299 if (!presShell
|| !presContext
) {
300 return NS_ERROR_FAILURE
;
303 const nsPoint
& lastOverWindowPointerLocation
=
304 presShell
->GetLastOverWindowPointerLocation();
306 if (lastOverWindowPointerLocation
.X() == NS_UNCONSTRAINEDSIZE
&&
307 lastOverWindowPointerLocation
.Y() == NS_UNCONSTRAINEDSIZE
) {
311 const CSSPoint lastOverWindowPointerLocationInCSSPixels
=
312 CSSPoint::FromAppUnits(lastOverWindowPointerLocation
);
313 *aX
= lastOverWindowPointerLocationInCSSPixels
.X();
314 *aY
= lastOverWindowPointerLocationInCSSPixels
.Y();
321 nsDOMWindowUtils::SyncFlushCompositor() {
322 if (nsIWidget
* widget
= GetWidget()) {
323 if (WindowRenderer
* renderer
= widget
->GetWindowRenderer()) {
324 if (KnowsCompositor
* kc
= renderer
->AsKnowsCompositor()) {
325 kc
->SyncWithCompositor();
333 nsDOMWindowUtils::GetImageAnimationMode(uint16_t* aMode
) {
334 NS_ENSURE_ARG_POINTER(aMode
);
336 nsPresContext
* presContext
= GetPresContext();
338 *aMode
= presContext
->ImageAnimationMode();
341 return NS_ERROR_NOT_AVAILABLE
;
345 nsDOMWindowUtils::SetImageAnimationMode(uint16_t aMode
) {
346 nsPresContext
* presContext
= GetPresContext();
348 presContext
->SetImageAnimationMode(aMode
);
351 return NS_ERROR_NOT_AVAILABLE
;
355 nsDOMWindowUtils::GetDocCharsetIsForced(bool* aIsForced
) {
358 Document
* doc
= GetDocument();
360 auto source
= doc
->GetDocumentCharacterSetSource();
361 *aIsForced
= source
== kCharsetFromInitialUserForcedAutoDetection
||
362 source
== kCharsetFromFinalUserForcedAutoDetection
;
368 nsDOMWindowUtils::GetPhysicalMillimeterInCSSPixels(float* aPhysicalMillimeter
) {
369 nsPresContext
* presContext
= GetPresContext();
371 return NS_ERROR_NOT_AVAILABLE
;
374 *aPhysicalMillimeter
= nsPresContext::AppUnitsToFloatCSSPixels(
375 presContext
->PhysicalMillimetersToAppUnits(1));
380 nsDOMWindowUtils::GetDocumentMetadata(const nsAString
& aName
,
382 Document
* doc
= GetDocument();
384 RefPtr
<nsAtom
> name
= NS_Atomize(aName
);
385 doc
->GetHeaderData(name
, aValue
);
394 nsDOMWindowUtils::UpdateLayerTree() {
395 if (RefPtr
<PresShell
> presShell
= GetPresShell()) {
396 // Don't flush throttled animations since it might fire MozAfterPaint event
397 // (in WebRender it constantly does), thus the reftest harness can't take
398 // any snapshot until the throttled animations finished.
399 presShell
->FlushPendingNotifications(
400 ChangesToFlush(FlushType::Display
, false /* flush animations */));
401 RefPtr
<nsViewManager
> vm
= presShell
->GetViewManager();
402 if (nsView
* view
= vm
->GetRootView()) {
403 nsAutoScriptBlocker scriptBlocker
;
404 presShell
->PaintAndRequestComposite(view
,
405 PaintFlags::PaintSyncDecodeImages
);
406 presShell
->GetWindowRenderer()->WaitOnTransactionProcessed();
413 nsDOMWindowUtils::GetContentViewerSize(uint32_t* aDisplayWidth
,
414 uint32_t* aDisplayHeight
) {
415 PresShell
* presShell
= GetPresShell();
416 LayoutDeviceIntSize displaySize
;
418 if (!presShell
|| !nsLayoutUtils::GetContentViewerSize(
419 presShell
->GetPresContext(), displaySize
)) {
420 return NS_ERROR_FAILURE
;
423 *aDisplayWidth
= displaySize
.width
;
424 *aDisplayHeight
= displaySize
.height
;
430 nsDOMWindowUtils::GetViewportInfo(uint32_t aDisplayWidth
,
431 uint32_t aDisplayHeight
, double* aDefaultZoom
,
432 bool* aAllowZoom
, double* aMinZoom
,
433 double* aMaxZoom
, uint32_t* aWidth
,
434 uint32_t* aHeight
, bool* aAutoSize
) {
435 Document
* doc
= GetDocument();
436 NS_ENSURE_STATE(doc
);
438 nsViewportInfo info
=
439 doc
->GetViewportInfo(ScreenIntSize(aDisplayWidth
, aDisplayHeight
));
440 *aDefaultZoom
= info
.GetDefaultZoom().scale
;
441 *aAllowZoom
= info
.IsZoomAllowed();
442 *aMinZoom
= info
.GetMinZoom().scale
;
443 *aMaxZoom
= info
.GetMaxZoom().scale
;
444 CSSIntSize size
= gfx::RoundedToInt(info
.GetSize());
445 *aWidth
= size
.width
;
446 *aHeight
= size
.height
;
447 *aAutoSize
= info
.IsAutoSizeEnabled();
452 nsDOMWindowUtils::GetViewportFitInfo(nsAString
& aViewportFit
) {
453 Document
* doc
= GetDocument();
454 NS_ENSURE_STATE(doc
);
456 ViewportMetaData metaData
= doc
->GetViewportMetaData();
457 if (metaData
.mViewportFit
.EqualsLiteral("contain")) {
458 aViewportFit
.AssignLiteral("contain");
459 } else if (metaData
.mViewportFit
.EqualsLiteral("cover")) {
460 aViewportFit
.AssignLiteral("cover");
462 aViewportFit
.AssignLiteral("auto");
468 nsDOMWindowUtils::SetMousewheelAutodir(Element
* aElement
, bool aEnabled
,
470 aElement
->SetProperty(nsGkAtoms::forceMousewheelAutodir
,
471 reinterpret_cast<void*>(aEnabled
));
472 aElement
->SetProperty(nsGkAtoms::forceMousewheelAutodirHonourRoot
,
473 reinterpret_cast<void*>(aHonourRoot
));
478 nsDOMWindowUtils::SetDisplayPortForElement(float aXPx
, float aYPx
,
479 float aWidthPx
, float aHeightPx
,
481 uint32_t aPriority
) {
482 PresShell
* presShell
= GetPresShell();
484 return NS_ERROR_FAILURE
;
488 return NS_ERROR_INVALID_ARG
;
491 if (aElement
->GetUncomposedDoc() != presShell
->GetDocument()) {
492 return NS_ERROR_INVALID_ARG
;
495 bool hadDisplayPort
= false;
496 bool wasPainted
= false;
497 nsRect oldDisplayPort
;
499 DisplayPortPropertyData
* currentData
=
500 static_cast<DisplayPortPropertyData
*>(
501 aElement
->GetProperty(nsGkAtoms::DisplayPort
));
503 if (currentData
->mPriority
> aPriority
) {
506 hadDisplayPort
= true;
507 oldDisplayPort
= currentData
->mRect
;
508 wasPainted
= currentData
->mPainted
;
512 nsRect
displayport(nsPresContext::CSSPixelsToAppUnits(aXPx
),
513 nsPresContext::CSSPixelsToAppUnits(aYPx
),
514 nsPresContext::CSSPixelsToAppUnits(aWidthPx
),
515 nsPresContext::CSSPixelsToAppUnits(aHeightPx
));
517 aElement
->RemoveProperty(nsGkAtoms::MinimalDisplayPort
);
518 aElement
->SetProperty(
519 nsGkAtoms::DisplayPort
,
520 new DisplayPortPropertyData(displayport
, aPriority
, wasPainted
),
521 nsINode::DeleteProperty
<DisplayPortPropertyData
>);
523 DisplayPortUtils::InvalidateForDisplayPortChange(aElement
, hadDisplayPort
,
524 oldDisplayPort
, displayport
);
526 nsIFrame
* rootFrame
= presShell
->GetRootFrame();
528 rootFrame
->SchedulePaint();
530 // If we are hiding something that is a display root then send empty paint
531 // transaction in order to release retained layers because it won't get
532 // any more paint requests when it is hidden.
533 if (displayport
.IsEmpty() &&
534 rootFrame
== nsLayoutUtils::GetDisplayRootFrame(rootFrame
)) {
535 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
537 using PaintFrameFlags
= nsLayoutUtils::PaintFrameFlags
;
538 nsLayoutUtils::PaintFrame(
539 nullptr, rootFrame
, nsRegion(), NS_RGB(255, 255, 255),
540 nsDisplayListBuilderMode::Painting
, PaintFrameFlags::WidgetLayers
);
549 nsDOMWindowUtils::SetDisplayPortMarginsForElement(
550 float aLeftMargin
, float aTopMargin
, float aRightMargin
,
551 float aBottomMargin
, Element
* aElement
, uint32_t aPriority
) {
552 PresShell
* presShell
= GetPresShell();
554 return NS_ERROR_FAILURE
;
558 return NS_ERROR_INVALID_ARG
;
561 if (aElement
->GetUncomposedDoc() != presShell
->GetDocument()) {
562 return NS_ERROR_INVALID_ARG
;
565 // Note order change of arguments between our function signature and
566 // ScreenMargin constructor.
567 ScreenMargin
displayportMargins(aTopMargin
, aRightMargin
, aBottomMargin
,
570 DisplayPortUtils::SetDisplayPortMargins(
572 DisplayPortMargins::ForContent(aElement
, displayportMargins
),
573 DisplayPortUtils::ClearMinimalDisplayPortProperty::Yes
, aPriority
);
579 nsDOMWindowUtils::SetDisplayPortBaseForElement(int32_t aX
, int32_t aY
,
580 int32_t aWidth
, int32_t aHeight
,
582 PresShell
* presShell
= GetPresShell();
584 return NS_ERROR_FAILURE
;
588 return NS_ERROR_INVALID_ARG
;
591 if (aElement
->GetUncomposedDoc() != presShell
->GetDocument()) {
592 return NS_ERROR_INVALID_ARG
;
595 DisplayPortUtils::SetDisplayPortBase(aElement
,
596 nsRect(aX
, aY
, aWidth
, aHeight
));
602 nsDOMWindowUtils::GetScrollbarSizes(Element
* aElement
,
603 uint32_t* aOutVerticalScrollbarWidth
,
604 uint32_t* aOutHorizontalScrollbarHeight
) {
605 nsIScrollableFrame
* scrollFrame
=
606 nsLayoutUtils::FindScrollableFrameFor(aElement
);
608 return NS_ERROR_INVALID_ARG
;
611 CSSIntMargin scrollbarSizes
=
612 RoundedToInt(CSSMargin::FromAppUnits(scrollFrame
->GetActualScrollbarSizes(
613 nsIScrollableFrame::ScrollbarSizesOptions::
614 INCLUDE_VISUAL_VIEWPORT_SCROLLBARS
)));
615 *aOutVerticalScrollbarWidth
= scrollbarSizes
.LeftRight();
616 *aOutHorizontalScrollbarHeight
= scrollbarSizes
.TopBottom();
622 nsDOMWindowUtils::SetResolutionAndScaleTo(float aResolution
) {
623 PresShell
* presShell
= GetPresShell();
625 return NS_ERROR_FAILURE
;
628 presShell
->SetResolutionAndScaleTo(aResolution
, ResolutionChangeOrigin::Test
);
634 nsDOMWindowUtils::SetRestoreResolution(float aResolution
,
635 uint32_t aDisplayWidth
,
636 uint32_t aDisplayHeight
) {
637 PresShell
* presShell
= GetPresShell();
639 return NS_ERROR_FAILURE
;
642 presShell
->SetRestoreResolution(
643 aResolution
, LayoutDeviceIntSize(aDisplayWidth
, aDisplayHeight
));
649 nsDOMWindowUtils::GetResolution(float* aResolution
) {
650 PresShell
* presShell
= GetPresShell();
652 return NS_ERROR_FAILURE
;
655 *aResolution
= presShell
->GetResolution();
661 nsDOMWindowUtils::SetIsFirstPaint(bool aIsFirstPaint
) {
662 if (PresShell
* presShell
= GetPresShell()) {
663 presShell
->SetIsFirstPaint(aIsFirstPaint
);
666 return NS_ERROR_FAILURE
;
670 nsDOMWindowUtils::GetIsFirstPaint(bool* aIsFirstPaint
) {
671 if (PresShell
* presShell
= GetPresShell()) {
672 *aIsFirstPaint
= presShell
->GetIsFirstPaint();
675 return NS_ERROR_FAILURE
;
679 nsDOMWindowUtils::GetPresShellId(uint32_t* aPresShellId
) {
680 if (PresShell
* presShell
= GetPresShell()) {
681 *aPresShellId
= presShell
->GetPresShellId();
684 return NS_ERROR_FAILURE
;
688 nsDOMWindowUtils::SendMouseEvent(
689 const nsAString
& aType
, float aX
, float aY
, int32_t aButton
,
690 int32_t aClickCount
, int32_t aModifiers
, bool aIgnoreRootScrollFrame
,
691 float aPressure
, unsigned short aInputSourceArg
,
692 bool aIsDOMEventSynthesized
, bool aIsWidgetEventSynthesized
,
693 int32_t aButtons
, uint32_t aIdentifier
, uint8_t aOptionalArgCount
,
694 bool* aPreventDefault
) {
695 return SendMouseEventCommon(
696 aType
, aX
, aY
, aButton
, aClickCount
, aModifiers
, aIgnoreRootScrollFrame
,
697 aPressure
, aInputSourceArg
,
698 aOptionalArgCount
>= 7 ? aIdentifier
: DEFAULT_MOUSE_POINTER_ID
, false,
699 aPreventDefault
, aOptionalArgCount
>= 4 ? aIsDOMEventSynthesized
: true,
700 aOptionalArgCount
>= 5 ? aIsWidgetEventSynthesized
: false,
701 aOptionalArgCount
>= 6 ? aButtons
: MOUSE_BUTTONS_NOT_SPECIFIED
);
705 nsDOMWindowUtils::SendMouseEventToWindow(
706 const nsAString
& aType
, float aX
, float aY
, int32_t aButton
,
707 int32_t aClickCount
, int32_t aModifiers
, bool aIgnoreRootScrollFrame
,
708 float aPressure
, unsigned short aInputSourceArg
,
709 bool aIsDOMEventSynthesized
, bool aIsWidgetEventSynthesized
,
710 int32_t aButtons
, uint32_t aIdentifier
, uint8_t aOptionalArgCount
) {
711 AUTO_PROFILER_LABEL("nsDOMWindowUtils::SendMouseEventToWindow", OTHER
);
713 return SendMouseEventCommon(
714 aType
, aX
, aY
, aButton
, aClickCount
, aModifiers
, aIgnoreRootScrollFrame
,
715 aPressure
, aInputSourceArg
,
716 aOptionalArgCount
>= 7 ? aIdentifier
: DEFAULT_MOUSE_POINTER_ID
, true,
717 nullptr, aOptionalArgCount
>= 4 ? aIsDOMEventSynthesized
: true,
718 aOptionalArgCount
>= 5 ? aIsWidgetEventSynthesized
: false,
719 aOptionalArgCount
>= 6 ? aButtons
: MOUSE_BUTTONS_NOT_SPECIFIED
);
723 nsDOMWindowUtils::SendMouseEventCommon(
724 const nsAString
& aType
, float aX
, float aY
, int32_t aButton
,
725 int32_t aClickCount
, int32_t aModifiers
, bool aIgnoreRootScrollFrame
,
726 float aPressure
, unsigned short aInputSourceArg
, uint32_t aPointerId
,
727 bool aToWindow
, bool* aPreventDefault
, bool aIsDOMEventSynthesized
,
728 bool aIsWidgetEventSynthesized
, int32_t aButtons
) {
729 RefPtr
<PresShell
> presShell
= GetPresShell();
730 PreventDefaultResult preventDefaultResult
;
731 nsresult rv
= nsContentUtils::SendMouseEvent(
732 presShell
, aType
, aX
, aY
, aButton
, aButtons
, aClickCount
, aModifiers
,
733 aIgnoreRootScrollFrame
, aPressure
, aInputSourceArg
, aPointerId
, aToWindow
,
734 &preventDefaultResult
, aIsDOMEventSynthesized
, aIsWidgetEventSynthesized
);
736 if (aPreventDefault
) {
737 *aPreventDefault
= preventDefaultResult
!= PreventDefaultResult::No
;
744 nsDOMWindowUtils::IsCORSSafelistedRequestHeader(const nsACString
& aName
,
745 const nsACString
& aValue
,
747 NS_ENSURE_ARG_POINTER(aRetVal
);
748 *aRetVal
= nsContentUtils::IsCORSSafelistedRequestHeader(aName
, aValue
);
753 nsDOMWindowUtils::SendWheelEvent(float aX
, float aY
, double aDeltaX
,
754 double aDeltaY
, double aDeltaZ
,
755 uint32_t aDeltaMode
, int32_t aModifiers
,
756 int32_t aLineOrPageDeltaX
,
757 int32_t aLineOrPageDeltaY
, uint32_t aOptions
) {
758 // get the widget to send the event to
760 nsCOMPtr
<nsIWidget
> widget
= GetWidget(&offset
);
762 return NS_ERROR_NULL_POINTER
;
765 WidgetWheelEvent
wheelEvent(true, eWheel
, widget
);
766 wheelEvent
.mModifiers
= nsContentUtils::GetWidgetModifiers(aModifiers
);
767 wheelEvent
.mDeltaX
= aDeltaX
;
768 wheelEvent
.mDeltaY
= aDeltaY
;
769 wheelEvent
.mDeltaZ
= aDeltaZ
;
770 wheelEvent
.mDeltaMode
= aDeltaMode
;
771 wheelEvent
.mIsMomentum
= (aOptions
& WHEEL_EVENT_CAUSED_BY_MOMENTUM
) != 0;
772 wheelEvent
.mIsNoLineOrPageDelta
=
773 (aOptions
& WHEEL_EVENT_CAUSED_BY_NO_LINE_OR_PAGE_DELTA_DEVICE
) != 0;
774 wheelEvent
.mCustomizedByUserPrefs
=
775 (aOptions
& WHEEL_EVENT_CUSTOMIZED_BY_USER_PREFS
) != 0;
776 wheelEvent
.mLineOrPageDeltaX
= aLineOrPageDeltaX
;
777 wheelEvent
.mLineOrPageDeltaY
= aLineOrPageDeltaY
;
779 nsPresContext
* presContext
= GetPresContext();
780 NS_ENSURE_TRUE(presContext
, NS_ERROR_FAILURE
);
782 wheelEvent
.mRefPoint
=
783 nsContentUtils::ToWidgetPoint(CSSPoint(aX
, aY
), offset
, presContext
);
785 if (StaticPrefs::test_events_async_enabled() &&
786 StaticPrefs::test_events_async_wheel_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
.mModifiers
= nsContentUtils::GetWidgetModifiers(aModifiers
);
902 nsPresContext
* presContext
= GetPresContext();
904 return NS_ERROR_FAILURE
;
906 uint32_t count
= aIdentifiers
.Length();
907 if (aXs
.Length() != count
|| aYs
.Length() != count
||
908 aRxs
.Length() != count
|| aRys
.Length() != count
||
909 aRotationAngles
.Length() != count
|| aForces
.Length() != count
) {
910 return NS_ERROR_INVALID_ARG
;
912 event
.mTouches
.SetCapacity(count
);
913 for (uint32_t i
= 0; i
< count
; ++i
) {
914 LayoutDeviceIntPoint pt
= nsContentUtils::ToWidgetPoint(
915 CSSPoint(aXs
[i
], aYs
[i
]), offset
, presContext
);
916 LayoutDeviceIntPoint radius
= LayoutDeviceIntPoint::FromAppUnitsRounded(
917 CSSPoint::ToAppUnits(CSSPoint(aRxs
[i
], aRys
[i
])),
918 presContext
->AppUnitsPerDevPixel());
920 RefPtr
<Touch
> t
= new Touch(aIdentifiers
[i
], pt
, radius
, aRotationAngles
[i
],
921 aForces
[i
], aTiltXs
[i
], aTiltYs
[i
], aTwists
[i
]);
923 event
.mTouches
.AppendElement(t
);
926 nsEventStatus status
= nsEventStatus_eIgnore
;
928 RefPtr
<PresShell
> presShell
;
929 nsView
* view
= nsContentUtils::GetViewToDispatchEvent(
930 presContext
, getter_AddRefs(presShell
));
931 if (!presShell
|| !view
) {
932 return NS_ERROR_FAILURE
;
934 *aPreventDefault
= (status
== nsEventStatus_eConsumeNoDefault
);
935 return presShell
->HandleEvent(view
->GetFrame(), &event
, false, &status
);
938 if (StaticPrefs::test_events_async_enabled() &&
939 StaticPrefs::test_events_async_touch_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 nsCOMPtr
<Document
> doc
= GetDocument();
2812 PendingAnimationTracker
* tracker
= doc
->GetPendingAnimationTracker();
2814 tracker
->TriggerPendingAnimationsNow();
2818 nsPresContext
* presContext
= GetPresContext();
2820 RefPtr
<nsRefreshDriver
> driver
= presContext
->RefreshDriver();
2821 driver
->AdvanceTimeAndRefresh(aMilliseconds
);
2823 if (WebRenderBridgeChild
* wrbc
= GetWebRenderBridge()) {
2824 wrbc
->SendSetTestSampleTime(driver
->MostRecentRefresh());
2832 nsDOMWindowUtils::GetLastTransactionId(uint64_t* aLastTransactionId
) {
2833 nsCOMPtr
<nsIDocShell
> docShell
= GetDocShell();
2835 return NS_ERROR_UNEXPECTED
;
2838 nsCOMPtr
<nsIDocShellTreeItem
> rootTreeItem
;
2839 docShell
->GetInProcessRootTreeItem(getter_AddRefs(rootTreeItem
));
2840 docShell
= do_QueryInterface(rootTreeItem
);
2842 return NS_ERROR_UNEXPECTED
;
2845 nsPresContext
* presContext
= docShell
->GetPresContext();
2847 return NS_ERROR_UNEXPECTED
;
2850 nsRefreshDriver
* driver
= presContext
->RefreshDriver();
2851 *aLastTransactionId
= uint64_t(driver
->LastTransactionId());
2856 nsDOMWindowUtils::RestoreNormalRefresh() {
2857 // Kick the compositor out of test mode before the refresh driver, so that
2858 // the refresh driver doesn't send an update that gets ignored by the
2860 if (WebRenderBridgeChild
* wrbc
= GetWebRenderBridge()) {
2861 wrbc
->SendLeaveTestMode();
2864 if (nsPresContext
* pc
= GetPresContext()) {
2865 nsRefreshDriver
* driver
= pc
->RefreshDriver();
2866 driver
->RestoreNormalRefresh();
2873 nsDOMWindowUtils::GetIsTestControllingRefreshes(bool* aResult
) {
2874 nsPresContext
* pc
= GetPresContext();
2876 pc
? pc
->RefreshDriver()->IsTestControllingRefreshesEnabled() : false;
2882 nsDOMWindowUtils::GetAsyncPanZoomEnabled(bool* aResult
) {
2883 nsIWidget
* widget
= GetWidget();
2885 *aResult
= widget
->AsyncPanZoomEnabled();
2887 *aResult
= gfxPlatform::AsyncPanZoomEnabled();
2893 nsDOMWindowUtils::SetAsyncScrollOffset(Element
* aElement
, float aX
, float aY
) {
2895 return NS_ERROR_INVALID_ARG
;
2897 ScrollableLayerGuid::ViewID viewId
;
2898 if (!nsLayoutUtils::FindIDFor(aElement
, &viewId
)) {
2899 return NS_ERROR_UNEXPECTED
;
2901 nsIWidget
* widget
= GetWidget();
2903 return NS_ERROR_FAILURE
;
2905 WindowRenderer
* renderer
= widget
->GetWindowRenderer();
2907 return NS_ERROR_FAILURE
;
2909 if (WebRenderLayerManager
* wr
= renderer
->AsWebRender()) {
2910 WebRenderBridgeChild
* wrbc
= wr
->WrBridge();
2912 return NS_ERROR_UNEXPECTED
;
2914 wrbc
->SendSetAsyncScrollOffset(viewId
, aX
, aY
);
2917 return NS_ERROR_UNEXPECTED
;
2921 nsDOMWindowUtils::SetAsyncZoom(Element
* aRootElement
, float aValue
) {
2922 if (!aRootElement
) {
2923 return NS_ERROR_INVALID_ARG
;
2925 ScrollableLayerGuid::ViewID viewId
;
2926 if (!nsLayoutUtils::FindIDFor(aRootElement
, &viewId
)) {
2927 return NS_ERROR_UNEXPECTED
;
2929 nsIWidget
* widget
= GetWidget();
2931 return NS_ERROR_FAILURE
;
2933 WindowRenderer
* renderer
= widget
->GetWindowRenderer();
2935 return NS_ERROR_FAILURE
;
2937 if (WebRenderLayerManager
* wr
= renderer
->AsWebRender()) {
2938 WebRenderBridgeChild
* wrbc
= wr
->WrBridge();
2940 return NS_ERROR_UNEXPECTED
;
2942 wrbc
->SendSetAsyncZoom(viewId
, aValue
);
2945 return NS_ERROR_UNEXPECTED
;
2949 nsDOMWindowUtils::FlushApzRepaints(bool* aOutResult
) {
2950 nsIWidget
* widget
= GetWidget();
2952 *aOutResult
= false;
2955 // If APZ is not enabled, this function is a no-op.
2956 if (!widget
->AsyncPanZoomEnabled()) {
2957 *aOutResult
= false;
2960 WindowRenderer
* renderer
= widget
->GetWindowRenderer();
2962 *aOutResult
= false;
2965 if (WebRenderLayerManager
* wr
= renderer
->AsWebRender()) {
2966 WebRenderBridgeChild
* wrbc
= wr
->WrBridge();
2968 return NS_ERROR_UNEXPECTED
;
2970 wrbc
->SendFlushApzRepaints();
2974 *aOutResult
= false;
2979 nsDOMWindowUtils::DisableApzForElement(Element
* aElement
) {
2980 aElement
->SetProperty(nsGkAtoms::apzDisabled
, reinterpret_cast<void*>(true));
2981 nsIScrollableFrame
* sf
= nsLayoutUtils::FindScrollableFrameFor(aElement
);
2985 nsIFrame
* frame
= do_QueryFrame(sf
);
2989 frame
->SchedulePaint();
2993 static nsTArray
<nsIScrollableFrame
*> CollectScrollableAncestors(
2995 nsTArray
<nsIScrollableFrame
*> result
;
2996 nsIFrame
* frame
= aStart
;
2998 frame
= nsLayoutUtils::GetCrossDocParentFrame(frame
);
3002 nsIScrollableFrame
* scrollAncestor
=
3003 nsLayoutUtils::GetAsyncScrollableAncestorFrame(frame
);
3004 if (!scrollAncestor
) {
3007 result
.AppendElement(scrollAncestor
);
3008 frame
= do_QueryFrame(scrollAncestor
);
3014 nsDOMWindowUtils::ZoomToFocusedInput() {
3015 if (!Preferences::GetBool("apz.zoom-to-focused-input.enabled")) {
3019 nsIWidget
* widget
= GetWidget();
3024 // If APZ is not enabled, this function is a no-op.
3026 // FIXME(emilio): This is not quite true anymore now that we also
3027 // ScrollIntoView() too...
3028 if (!widget
->AsyncPanZoomEnabled()) {
3032 nsFocusManager
* fm
= nsFocusManager::GetFocusManager();
3037 RefPtr
<Element
> element
= fm
->GetFocusedElement();
3042 RefPtr
<PresShell
> presShell
=
3043 APZCCallbackHelper::GetRootContentDocumentPresShellForContent(element
);
3048 bool shouldSkip
= [&] {
3049 nsIFrame
* frame
= element
->GetPrimaryFrame();
3054 // Skip zooming to focused inputs in fixed subtrees, as we'd scroll to the
3055 // top unnecessarily, see bug 1627734.
3057 // We could try to teach apz to zoom to a rect only without panning, or
3058 // maybe we could give it a rect offsetted by the root scroll position, if
3059 // we wanted to do this.
3060 for (; frame
; frame
= nsLayoutUtils::GetCrossDocParentFrame(frame
)) {
3061 if (frame
->PresShell() == presShell
) {
3062 // Note that we only do this if the frame belongs to `presShell` (that
3063 // is, we still zoom in fixed elements in subdocuments, as they're not
3064 // fixed to the root content document).
3065 return nsLayoutUtils::IsInPositionFixedSubtree(frame
);
3067 frame
= frame
->PresShell()->GetRootFrame();
3073 // The content may be inside a scrollable subframe inside a non-scrollable
3074 // root content document. In this scenario, we want to ensure that the
3075 // main-thread side knows to scroll the content into view before we get
3076 // the bounding content rect and ask APZ to adjust the visual viewport.
3077 presShell
->ScrollContentIntoView(
3078 element
, ScrollAxis(WhereToScroll::Nearest
, WhenToScroll::IfNotVisible
),
3079 ScrollAxis(WhereToScroll::Nearest
, WhenToScroll::IfNotVisible
),
3080 ScrollFlags::ScrollOverflowHidden
);
3086 RefPtr
<Document
> document
= presShell
->GetDocument();
3091 uint32_t presShellId
;
3092 ScrollableLayerGuid::ViewID viewId
;
3093 if (!APZCCallbackHelper::GetOrCreateScrollIdentifiers(
3094 document
->GetDocumentElement(), &presShellId
, &viewId
)) {
3098 TouchBehaviorFlags tbf
=
3099 layers::TouchActionHelper::GetAllowedTouchBehaviorForFrame(
3100 element
->GetPrimaryFrame());
3102 uint32_t flags
= layers::DISABLE_ZOOM_OUT
| layers::ZOOM_TO_FOCUSED_INPUT
;
3103 if (!Preferences::GetBool("formhelper.autozoom") ||
3104 Preferences::GetBool("formhelper.autozoom.force-disable.test-only",
3105 /* aFallback = */ false) ||
3106 !(tbf
& AllowedTouchBehavior::ANIMATING_ZOOM
)) {
3107 flags
|= layers::PAN_INTO_VIEW_ONLY
;
3109 flags
|= layers::ONLY_ZOOM_TO_DEFAULT_SCALE
;
3112 nsIScrollableFrame
* rootScrollFrame
=
3113 presShell
->GetRootScrollFrameAsScrollable();
3114 if (!rootScrollFrame
) {
3119 if (element
->IsHTMLElement(nsGkAtoms::input
)) {
3120 bounds
= nsLayoutUtils::GetBoundingContentRect(element
, rootScrollFrame
);
3122 // When focused elment is content editable or <textarea> element,
3123 // focused element will have multi-line content.
3124 nsIFrame
* frame
= element
->GetPrimaryFrame();
3126 RefPtr
<nsCaret
> caret
= frame
->PresShell()->GetCaret();
3127 if (caret
&& caret
->IsVisible()) {
3129 if (nsIFrame
* frame
= caret
->GetGeometry(&rect
)) {
3130 bounds
= nsLayoutUtils::GetBoundingFrameRect(frame
, rootScrollFrame
);
3134 if (bounds
.IsEmpty()) {
3135 // Fallback if no caret frame.
3136 bounds
= nsLayoutUtils::GetBoundingContentRect(element
, rootScrollFrame
);
3140 if (bounds
.IsEmpty()) {
3141 // Do not zoom on empty bounds. Bail out.
3145 bool waitForRefresh
= false;
3146 for (nsIScrollableFrame
* scrollAncestor
:
3147 CollectScrollableAncestors(element
->GetPrimaryFrame())) {
3148 if (scrollAncestor
->HasScrollUpdates()) {
3149 waitForRefresh
= true;
3153 if (waitForRefresh
) {
3154 waitForRefresh
= false;
3155 if (nsPresContext
* presContext
= presShell
->GetPresContext()) {
3156 waitForRefresh
= true;
3157 presContext
->RegisterManagedPostRefreshObserver(
3158 new ManagedPostRefreshObserver(
3159 presContext
, [widget
= RefPtr
<nsIWidget
>(widget
), presShellId
,
3160 viewId
, bounds
, flags
](bool aWasCanceled
) {
3161 if (!aWasCanceled
) {
3162 widget
->ZoomToRect(presShellId
, viewId
, bounds
, flags
);
3164 return ManagedPostRefreshObserver::Unregister::Yes
;
3168 if (!waitForRefresh
) {
3169 widget
->ZoomToRect(presShellId
, viewId
, bounds
, flags
);
3176 nsDOMWindowUtils::ComputeAnimationDistance(Element
* aElement
,
3177 const nsAString
& aProperty
,
3178 const nsAString
& aValue1
,
3179 const nsAString
& aValue2
,
3181 NS_ENSURE_ARG_POINTER(aElement
);
3183 nsCSSPropertyID property
=
3184 nsCSSProps::LookupProperty(NS_ConvertUTF16toUTF8(aProperty
));
3185 if (property
== eCSSProperty_UNKNOWN
|| nsCSSProps::IsShorthand(property
)) {
3186 return NS_ERROR_ILLEGAL_VALUE
;
3189 AnimationValue v1
= AnimationValue::FromString(
3190 property
, NS_ConvertUTF16toUTF8(aValue1
), aElement
);
3191 AnimationValue v2
= AnimationValue::FromString(
3192 property
, NS_ConvertUTF16toUTF8(aValue2
), aElement
);
3193 if (v1
.IsNull() || v2
.IsNull()) {
3194 return NS_ERROR_ILLEGAL_VALUE
;
3197 *aResult
= v1
.ComputeDistance(property
, v2
);
3202 nsDOMWindowUtils::GetUnanimatedComputedStyle(Element
* aElement
,
3203 const nsAString
& aPseudoElement
,
3204 const nsAString
& aProperty
,
3206 nsAString
& aResult
) {
3208 return NS_ERROR_INVALID_ARG
;
3211 nsCSSPropertyID propertyID
=
3212 nsCSSProps::LookupProperty(NS_ConvertUTF16toUTF8(aProperty
));
3213 if (propertyID
== eCSSProperty_UNKNOWN
||
3214 nsCSSProps::IsShorthand(propertyID
)) {
3215 return NS_ERROR_INVALID_ARG
;
3218 switch (aFlushType
) {
3222 if (Document
* doc
= aElement
->GetComposedDoc()) {
3223 doc
->FlushPendingNotifications(FlushType::Style
);
3228 return NS_ERROR_INVALID_ARG
;
3231 RefPtr
<PresShell
> presShell
= GetPresShell();
3233 return NS_ERROR_FAILURE
;
3236 Maybe
<PseudoStyleType
> pseudo
=
3237 nsCSSPseudoElements::GetPseudoType(aPseudoElement
);
3239 return NS_ERROR_FAILURE
;
3241 RefPtr
<const ComputedStyle
> computedStyle
=
3242 nsComputedDOMStyle::GetUnanimatedComputedStyleNoFlush(aElement
, *pseudo
);
3243 if (!computedStyle
) {
3244 return NS_ERROR_FAILURE
;
3247 RefPtr
<StyleAnimationValue
> value
=
3248 Servo_ComputedValues_ExtractAnimationValue(computedStyle
, propertyID
)
3251 return NS_ERROR_FAILURE
;
3253 if (!aElement
->GetComposedDoc()) {
3254 return NS_ERROR_FAILURE
;
3256 nsAutoCString result
;
3257 Servo_AnimationValue_Serialize(value
, propertyID
,
3258 presShell
->StyleSet()->RawData(), &result
);
3259 CopyUTF8toUTF16(result
, aResult
);
3264 nsDOMWindowUtils::GetDisplayDPI(float* aDPI
) {
3265 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
3266 if (!widget
) return NS_ERROR_FAILURE
;
3268 *aDPI
= widget
->GetDPI();
3274 nsDOMWindowUtils::CheckAndClearPaintedState(Element
* aElement
, bool* aResult
) {
3276 return NS_ERROR_INVALID_ARG
;
3279 nsIFrame
* frame
= aElement
->GetPrimaryFrame();
3286 // Get the outermost frame for the content node, so that we can test
3287 // canvasframe invalidations by observing the documentElement.
3289 nsIFrame
* parentFrame
= frame
->GetParent();
3290 if (parentFrame
&& parentFrame
->GetContent() == aElement
) {
3291 frame
= parentFrame
;
3298 if (!frame
->CheckAndClearPaintedState()) {
3302 frame
= nsLayoutUtils::GetNextContinuationOrIBSplitSibling(frame
);
3309 nsDOMWindowUtils::CheckAndClearDisplayListState(Element
* aElement
,
3312 return NS_ERROR_INVALID_ARG
;
3315 nsIFrame
* frame
= aElement
->GetPrimaryFrame();
3322 // Get the outermost frame for the content node, so that we can test
3323 // canvasframe invalidations by observing the documentElement.
3325 nsIFrame
* parentFrame
= frame
->GetParent();
3326 if (parentFrame
&& parentFrame
->GetContent() == aElement
) {
3327 frame
= parentFrame
;
3334 if (!frame
->CheckAndClearDisplayListState()) {
3338 frame
= nsLayoutUtils::GetNextContinuationOrIBSplitSibling(frame
);
3345 nsDOMWindowUtils::IsPartOfOpaqueLayer(Element
* aElement
, bool* aResult
) {
3347 return NS_ERROR_INVALID_ARG
;
3350 nsIFrame
* frame
= aElement
->GetPrimaryFrame();
3352 return NS_ERROR_FAILURE
;
3355 return NS_ERROR_FAILURE
;
3359 nsDOMWindowUtils::NumberOfAssignedPaintedLayers(
3360 const nsTArray
<RefPtr
<Element
>>& aElements
, uint32_t* aResult
) {
3361 return NS_ERROR_FAILURE
;
3365 nsDOMWindowUtils::EnableDialogs() {
3366 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
3367 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
3369 nsGlobalWindowOuter::Cast(window
)->EnableDialogs();
3374 nsDOMWindowUtils::DisableDialogs() {
3375 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
3376 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
3378 nsGlobalWindowOuter::Cast(window
)->DisableDialogs();
3383 nsDOMWindowUtils::AreDialogsEnabled(bool* aResult
) {
3384 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
3385 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
3387 *aResult
= nsGlobalWindowOuter::Cast(window
)->AreDialogsEnabled();
3392 nsDOMWindowUtils::ResetDialogAbuseState() {
3393 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
3394 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
3396 nsGlobalWindowOuter::Cast(window
)
3397 ->GetBrowsingContextGroup()
3398 ->ResetDialogAbuseState();
3403 nsDOMWindowUtils::GetFileId(JS::Handle
<JS::Value
> aFile
, JSContext
* aCx
,
3405 if (aFile
.isPrimitive()) {
3410 JS::Rooted
<JSObject
*> obj(aCx
, aFile
.toObjectOrNull());
3412 Blob
* blob
= nullptr;
3413 if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob
, &obj
, blob
))) {
3414 *_retval
= blob
->GetFileId();
3423 nsDOMWindowUtils::GetFilePath(JS::Handle
<JS::Value
> aFile
, JSContext
* aCx
,
3424 nsAString
& _retval
) {
3425 if (aFile
.isPrimitive()) {
3430 JS::Rooted
<JSObject
*> obj(aCx
, aFile
.toObjectOrNull());
3432 File
* file
= nullptr;
3433 if (NS_SUCCEEDED(UNWRAP_OBJECT(File
, &obj
, file
))) {
3436 file
->GetMozFullPathInternal(filePath
, rv
);
3437 if (NS_WARN_IF(rv
.Failed())) {
3438 return rv
.StealNSResult();
3450 nsDOMWindowUtils::GetFileReferences(const nsAString
& aDatabaseName
, int64_t aId
,
3451 int32_t* aRefCnt
, int32_t* aDBRefCnt
,
3453 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
3454 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
3456 quota::PrincipalMetadata principalMetadata
;
3457 MOZ_TRY_VAR(principalMetadata
,
3458 quota::QuotaManager::GetInfoFromWindow(window
));
3460 RefPtr
<IndexedDatabaseManager
> mgr
= IndexedDatabaseManager::Get();
3462 nsresult rv
= mgr
->BlockAndGetFileReferences(
3463 principalMetadata
.mIsPrivate
? quota::PERSISTENCE_TYPE_PRIVATE
3464 : quota::PERSISTENCE_TYPE_DEFAULT
,
3465 principalMetadata
.mOrigin
, aDatabaseName
, aId
, aRefCnt
, aDBRefCnt
,
3468 NS_ENSURE_SUCCESS(rv
, rv
);
3470 *aRefCnt
= *aDBRefCnt
= -1;
3478 nsDOMWindowUtils::FlushPendingFileDeletions() {
3479 RefPtr
<IndexedDatabaseManager
> mgr
= IndexedDatabaseManager::Get();
3481 nsresult rv
= mgr
->FlushPendingFileDeletions();
3482 if (NS_WARN_IF(NS_FAILED(rv
))) {
3491 nsDOMWindowUtils::StartPCCountProfiling(JSContext
* cx
) {
3492 JS::StartPCCountProfiling(cx
);
3497 nsDOMWindowUtils::StopPCCountProfiling(JSContext
* cx
) {
3498 JS::StopPCCountProfiling(cx
);
3503 nsDOMWindowUtils::PurgePCCounts(JSContext
* cx
) {
3504 JS::PurgePCCounts(cx
);
3509 nsDOMWindowUtils::GetPCCountScriptCount(JSContext
* cx
, int32_t* result
) {
3510 *result
= JS::GetPCCountScriptCount(cx
);
3515 nsDOMWindowUtils::GetPCCountScriptSummary(int32_t script
, JSContext
* cx
,
3516 nsAString
& result
) {
3517 JSString
* text
= JS::GetPCCountScriptSummary(cx
, script
);
3518 if (!text
) return NS_ERROR_FAILURE
;
3520 if (!AssignJSString(cx
, result
, text
)) return NS_ERROR_FAILURE
;
3526 nsDOMWindowUtils::GetPCCountScriptContents(int32_t script
, JSContext
* cx
,
3527 nsAString
& result
) {
3528 JSString
* text
= JS::GetPCCountScriptContents(cx
, script
);
3529 if (!text
) return NS_ERROR_FAILURE
;
3531 if (!AssignJSString(cx
, result
, text
)) return NS_ERROR_FAILURE
;
3537 nsDOMWindowUtils::GetPaintingSuppressed(bool* aPaintingSuppressed
) {
3538 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
3539 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
3540 nsIDocShell
* docShell
= window
->GetDocShell();
3541 NS_ENSURE_TRUE(docShell
, NS_ERROR_FAILURE
);
3543 PresShell
* presShell
= docShell
->GetPresShell();
3544 NS_ENSURE_TRUE(presShell
, NS_ERROR_FAILURE
);
3546 *aPaintingSuppressed
= presShell
->IsPaintingSuppressed();
3551 nsDOMWindowUtils::SetVisualViewportSize(float aWidth
, float aHeight
) {
3552 if (!(aWidth
>= 0.0 && aHeight
>= 0.0)) {
3553 return NS_ERROR_ILLEGAL_VALUE
;
3556 PresShell
* presShell
= GetPresShell();
3558 return NS_ERROR_FAILURE
;
3561 presShell
->SetVisualViewportSize(nsPresContext::CSSPixelsToAppUnits(aWidth
),
3562 nsPresContext::CSSPixelsToAppUnits(aHeight
));
3567 nsresult
nsDOMWindowUtils::RemoteFrameFullscreenChanged(
3568 Element
* aFrameElement
) {
3569 nsCOMPtr
<Document
> doc
= GetDocument();
3570 NS_ENSURE_STATE(doc
);
3572 doc
->RemoteFrameFullscreenChanged(aFrameElement
);
3576 nsresult
nsDOMWindowUtils::RemoteFrameFullscreenReverted() {
3577 nsCOMPtr
<Document
> doc
= GetDocument();
3578 NS_ENSURE_STATE(doc
);
3580 doc
->RemoteFrameFullscreenReverted();
3584 static void PrepareForFullscreenChange(nsIDocShell
* aDocShell
,
3585 const nsSize
& aSize
,
3586 nsSize
* aOldSize
= nullptr) {
3590 PresShell
* presShell
= aDocShell
->GetPresShell();
3594 if (nsRefreshDriver
* rd
= presShell
->GetRefreshDriver()) {
3595 rd
->SetIsResizeSuppressed();
3596 // Since we are suppressing the resize reflow which would originally
3597 // be triggered by view manager, we need to ensure that the refresh
3598 // driver actually schedules a flush, otherwise it may get stuck.
3599 rd
->ScheduleViewManagerFlush();
3601 if (!aSize
.IsEmpty()) {
3602 nsCOMPtr
<nsIContentViewer
> cv
;
3603 aDocShell
->GetContentViewer(getter_AddRefs(cv
));
3606 cv
->GetBounds(cvBounds
);
3607 nscoord auPerDev
= presShell
->GetPresContext()->AppUnitsPerDevPixel();
3609 *aOldSize
= LayoutDeviceIntSize::ToAppUnits(
3610 LayoutDeviceIntSize::FromUnknownSize(cvBounds
.Size()), auPerDev
);
3612 LayoutDeviceIntSize newSize
=
3613 LayoutDeviceIntSize::FromAppUnitsRounded(aSize
, auPerDev
);
3615 cvBounds
.SizeTo(newSize
.width
, newSize
.height
);
3616 cv
->SetBounds(cvBounds
);
3622 nsDOMWindowUtils::HandleFullscreenRequests(bool* aRetVal
) {
3623 PROFILER_MARKER_UNTYPED("Enter fullscreen", DOM
);
3624 nsCOMPtr
<Document
> doc
= GetDocument();
3625 NS_ENSURE_STATE(doc
);
3627 // Notify the pres shell that we are starting fullscreen change, and
3628 // set the window dimensions in advance. Since the resize message
3629 // comes after the fullscreen change call, doing so could avoid an
3630 // extra resize reflow after this point.
3632 if (nsPresContext
* presContext
= GetPresContext()) {
3633 presContext
->DeviceContext()->GetRect(screenRect
);
3636 PrepareForFullscreenChange(GetDocShell(), screenRect
.Size(), &oldSize
);
3637 OldWindowSize::Set(mWindow
, oldSize
);
3639 *aRetVal
= Document::HandlePendingFullscreenRequests(doc
);
3643 nsresult
nsDOMWindowUtils::ExitFullscreen(bool aDontRestoreViewSize
) {
3644 PROFILER_MARKER_UNTYPED("Exit fullscreen", DOM
);
3645 nsCOMPtr
<Document
> doc
= GetDocument();
3646 NS_ENSURE_STATE(doc
);
3648 // Although we would not use the old size if we have already exited
3649 // fullscreen, we still want to cleanup in case we haven't.
3650 nsSize oldSize
= OldWindowSize::GetAndRemove(mWindow
);
3651 if (!doc
->GetFullscreenElement()) {
3655 // Notify the pres shell that we are starting fullscreen change, and
3656 // set the window dimensions in advance. Since the resize message
3657 // comes after the fullscreen change call, doing so could avoid an
3658 // extra resize reflow after this point.
3659 PrepareForFullscreenChange(GetDocShell(),
3660 aDontRestoreViewSize
? nsSize() : oldSize
);
3661 Document::ExitFullscreenInDocTree(doc
);
3666 nsDOMWindowUtils::SelectAtPoint(float aX
, float aY
, uint32_t aSelectBehavior
,
3670 nsSelectionAmount amount
;
3671 switch (aSelectBehavior
) {
3672 case nsIDOMWindowUtils::SELECT_CHARACTER
:
3673 amount
= eSelectCharacter
;
3675 case nsIDOMWindowUtils::SELECT_CLUSTER
:
3676 amount
= eSelectCluster
;
3678 case nsIDOMWindowUtils::SELECT_WORD
:
3679 amount
= eSelectWord
;
3681 case nsIDOMWindowUtils::SELECT_LINE
:
3682 amount
= eSelectLine
;
3684 case nsIDOMWindowUtils::SELECT_BEGINLINE
:
3685 amount
= eSelectBeginLine
;
3687 case nsIDOMWindowUtils::SELECT_ENDLINE
:
3688 amount
= eSelectEndLine
;
3690 case nsIDOMWindowUtils::SELECT_PARAGRAPH
:
3691 amount
= eSelectParagraph
;
3693 case nsIDOMWindowUtils::SELECT_WORDNOSPACE
:
3694 amount
= eSelectWordNoSpace
;
3697 return NS_ERROR_INVALID_ARG
;
3700 PresShell
* presShell
= GetPresShell();
3702 return NS_ERROR_UNEXPECTED
;
3705 // The root frame for this content window
3706 nsIFrame
* rootFrame
= presShell
->GetRootFrame();
3708 return NS_ERROR_UNEXPECTED
;
3711 // Get the target frame at the client coordinates passed to us
3713 nsCOMPtr
<nsIWidget
> widget
= GetWidget(&offset
);
3714 LayoutDeviceIntPoint pt
=
3715 nsContentUtils::ToWidgetPoint(CSSPoint(aX
, aY
), offset
, GetPresContext());
3716 nsPoint ptInRoot
= nsLayoutUtils::GetEventCoordinatesRelativeTo(
3717 widget
, pt
, RelativeTo
{rootFrame
});
3718 nsIFrame
* targetFrame
=
3719 nsLayoutUtils::GetFrameForPoint(RelativeTo
{rootFrame
}, ptInRoot
);
3720 // This can happen if the page hasn't loaded yet or if the point
3721 // is outside the frame.
3723 return NS_ERROR_INVALID_ARG
;
3726 // Convert point to coordinates relative to the target frame, which is
3727 // what targetFrame's SelectByTypeAtPoint expects.
3728 nsPoint relPoint
= nsLayoutUtils::GetEventCoordinatesRelativeTo(
3729 widget
, pt
, RelativeTo
{targetFrame
});
3731 const RefPtr
<nsPresContext
> pinnedPresContext
{GetPresContext()};
3732 nsresult rv
= targetFrame
->SelectByTypeAtPoint(
3733 pinnedPresContext
, relPoint
, amount
, amount
, nsIFrame::SELECT_ACCUMULATE
);
3734 *_retval
= !NS_FAILED(rv
);
3738 static Document::additionalSheetType
convertSheetType(uint32_t aSheetType
) {
3739 switch (aSheetType
) {
3740 case nsDOMWindowUtils::AGENT_SHEET
:
3741 return Document::eAgentSheet
;
3742 case nsDOMWindowUtils::USER_SHEET
:
3743 return Document::eUserSheet
;
3744 case nsDOMWindowUtils::AUTHOR_SHEET
:
3745 return Document::eAuthorSheet
;
3747 NS_ASSERTION(false, "wrong type");
3748 // we must return something although this should never happen
3749 return Document::AdditionalSheetTypeCount
;
3754 nsDOMWindowUtils::LoadSheet(nsIURI
* aSheetURI
, uint32_t aSheetType
) {
3755 NS_ENSURE_ARG_POINTER(aSheetURI
);
3756 NS_ENSURE_ARG(aSheetType
== AGENT_SHEET
|| aSheetType
== USER_SHEET
||
3757 aSheetType
== AUTHOR_SHEET
);
3759 nsCOMPtr
<Document
> doc
= GetDocument();
3760 NS_ENSURE_TRUE(doc
, NS_ERROR_FAILURE
);
3762 Document::additionalSheetType type
= convertSheetType(aSheetType
);
3764 return doc
->LoadAdditionalStyleSheet(type
, aSheetURI
);
3768 nsDOMWindowUtils::LoadSheetUsingURIString(const nsACString
& aSheetURI
,
3769 uint32_t aSheetType
) {
3770 nsCOMPtr
<nsIURI
> uri
;
3771 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), aSheetURI
);
3772 NS_ENSURE_SUCCESS(rv
, rv
);
3774 return LoadSheet(uri
, aSheetType
);
3778 nsDOMWindowUtils::AddSheet(nsIPreloadedStyleSheet
* aSheet
,
3779 uint32_t aSheetType
) {
3780 NS_ENSURE_ARG_POINTER(aSheet
);
3781 NS_ENSURE_ARG(aSheetType
== AGENT_SHEET
|| aSheetType
== USER_SHEET
||
3782 aSheetType
== AUTHOR_SHEET
);
3784 nsCOMPtr
<Document
> doc
= GetDocument();
3785 NS_ENSURE_TRUE(doc
, NS_ERROR_FAILURE
);
3787 StyleSheet
* sheet
= nullptr;
3788 auto* preloadedSheet
= static_cast<PreloadedStyleSheet
*>(aSheet
);
3789 nsresult rv
= preloadedSheet
->GetSheet(&sheet
);
3790 NS_ENSURE_SUCCESS(rv
, rv
);
3791 NS_ENSURE_TRUE(sheet
, NS_ERROR_FAILURE
);
3793 if (sheet
->GetAssociatedDocumentOrShadowRoot()) {
3794 return NS_ERROR_INVALID_ARG
;
3797 Document::additionalSheetType type
= convertSheetType(aSheetType
);
3798 return doc
->AddAdditionalStyleSheet(type
, sheet
);
3802 nsDOMWindowUtils::RemoveSheet(nsIURI
* aSheetURI
, uint32_t aSheetType
) {
3803 NS_ENSURE_ARG_POINTER(aSheetURI
);
3804 NS_ENSURE_ARG(aSheetType
== AGENT_SHEET
|| aSheetType
== USER_SHEET
||
3805 aSheetType
== AUTHOR_SHEET
);
3807 nsCOMPtr
<Document
> doc
= GetDocument();
3808 NS_ENSURE_TRUE(doc
, NS_ERROR_FAILURE
);
3810 Document::additionalSheetType type
= convertSheetType(aSheetType
);
3812 doc
->RemoveAdditionalStyleSheet(type
, aSheetURI
);
3817 nsDOMWindowUtils::RemoveSheetUsingURIString(const nsACString
& aSheetURI
,
3818 uint32_t aSheetType
) {
3819 nsCOMPtr
<nsIURI
> uri
;
3820 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), aSheetURI
);
3821 NS_ENSURE_SUCCESS(rv
, rv
);
3823 return RemoveSheet(uri
, aSheetType
);
3827 nsDOMWindowUtils::GetIsHandlingUserInput(bool* aHandlingUserInput
) {
3828 *aHandlingUserInput
= UserActivation::IsHandlingUserInput();
3834 nsDOMWindowUtils::GetMillisSinceLastUserInput(
3835 double* aMillisSinceLastUserInput
) {
3836 TimeStamp lastInput
= UserActivation::LatestUserInputStart();
3837 if (lastInput
.IsNull()) {
3838 *aMillisSinceLastUserInput
= -1.0f
;
3842 *aMillisSinceLastUserInput
= (TimeStamp::Now() - lastInput
).ToMilliseconds();
3847 nsDOMWindowUtils::AllowScriptsToClose() {
3848 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
3849 NS_ENSURE_STATE(window
);
3850 nsGlobalWindowOuter::Cast(window
)->AllowScriptsToClose();
3855 nsDOMWindowUtils::GetIsParentWindowMainWidgetVisible(bool* aIsVisible
) {
3856 if (!XRE_IsParentProcess()) {
3858 "IsParentWindowMainWidgetVisible is only available in the parent "
3862 // this should reflect the "is parent window visible" logic in
3863 // nsWindowWatcher::OpenWindowInternal()
3864 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
3865 NS_ENSURE_STATE(window
);
3867 nsCOMPtr
<nsIWidget
> parentWidget
;
3868 nsIDocShell
* docShell
= window
->GetDocShell();
3870 nsCOMPtr
<nsIDocShellTreeOwner
> parentTreeOwner
;
3871 docShell
->GetTreeOwner(getter_AddRefs(parentTreeOwner
));
3872 nsCOMPtr
<nsIBaseWindow
> parentWindow(do_GetInterface(parentTreeOwner
));
3874 parentWindow
->GetMainWidget(getter_AddRefs(parentWidget
));
3877 if (!parentWidget
) {
3878 return NS_ERROR_NOT_AVAILABLE
;
3881 *aIsVisible
= parentWidget
->IsVisible();
3886 nsDOMWindowUtils::IsNodeDisabledForEvents(nsINode
* aNode
, bool* aRetVal
) {
3888 nsINode
* node
= aNode
;
3890 if (node
->IsHTMLFormControlElement()) {
3891 nsGenericHTMLElement
* element
= nsGenericHTMLElement::FromNode(node
);
3892 WidgetEvent
event(true, eVoidEvent
);
3893 if (element
&& element
->IsDisabledForEvents(&event
)) {
3898 node
= node
->GetParentNode();
3905 nsDOMWindowUtils::DispatchEventToChromeOnly(EventTarget
* aTarget
, Event
* aEvent
,
3908 NS_ENSURE_STATE(aTarget
&& aEvent
);
3909 aEvent
->WidgetEventPtr()->mFlags
.mOnlyChromeDispatch
= true;
3911 aTarget
->DispatchEvent(*aEvent
, CallerType::System
, IgnoreErrors());
3915 static Result
<nsIFrame
*, nsresult
> GetTargetFrame(
3916 const Element
* aElement
, const nsAString
& aPseudoElement
) {
3917 nsIFrame
* frame
= aElement
->GetPrimaryFrame();
3918 if (!aPseudoElement
.IsEmpty()) {
3919 if (aPseudoElement
.EqualsLiteral("::before")) {
3920 frame
= nsLayoutUtils::GetBeforeFrame(aElement
);
3921 } else if (aPseudoElement
.EqualsLiteral("::after")) {
3922 frame
= nsLayoutUtils::GetAfterFrame(aElement
);
3924 return Err(NS_ERROR_INVALID_ARG
);
3930 static OMTAValue
GetOMTAValue(nsIFrame
* aFrame
, DisplayItemType aDisplayItemKey
,
3931 WebRenderBridgeChild
* aWebRenderBridgeChild
) {
3932 OMTAValue value
= mozilla::null_t();
3934 if (aWebRenderBridgeChild
) {
3935 RefPtr
<WebRenderAnimationData
> animationData
=
3936 GetWebRenderUserData
<WebRenderAnimationData
>(aFrame
,
3937 (uint32_t)aDisplayItemKey
);
3938 if (animationData
) {
3939 aWebRenderBridgeChild
->SendGetAnimationValue(
3940 animationData
->GetAnimationInfo().GetCompositorAnimationsId(),
3948 nsDOMWindowUtils::GetOMTAStyle(Element
* aElement
, const nsAString
& aProperty
,
3949 const nsAString
& aPseudoElement
,
3950 nsAString
& aResult
) {
3952 return NS_ERROR_INVALID_ARG
;
3955 auto frameOrError
= GetTargetFrame(aElement
, aPseudoElement
);
3956 if (frameOrError
.isErr()) {
3957 return frameOrError
.unwrapErr();
3959 nsIFrame
* frame
= frameOrError
.unwrap();
3961 RefPtr
<nsROCSSPrimitiveValue
> cssValue
= nullptr;
3962 if (frame
&& nsLayoutUtils::AreAsyncAnimationsEnabled()) {
3963 if (aProperty
.EqualsLiteral("opacity")) {
3964 OMTAValue value
= GetOMTAValue(frame
, DisplayItemType::TYPE_OPACITY
,
3965 GetWebRenderBridge());
3966 if (value
.type() == OMTAValue::Tfloat
) {
3967 cssValue
= new nsROCSSPrimitiveValue
;
3968 cssValue
->SetNumber(value
.get_float());
3970 } else if (aProperty
.EqualsLiteral("transform") ||
3971 aProperty
.EqualsLiteral("translate") ||
3972 aProperty
.EqualsLiteral("rotate") ||
3973 aProperty
.EqualsLiteral("scale") ||
3974 aProperty
.EqualsLiteral("offset-path") ||
3975 aProperty
.EqualsLiteral("offset-distance") ||
3976 aProperty
.EqualsLiteral("offset-rotate") ||
3977 aProperty
.EqualsLiteral("offset-anchor") ||
3978 aProperty
.EqualsLiteral("offset-position")) {
3979 OMTAValue value
= GetOMTAValue(frame
, DisplayItemType::TYPE_TRANSFORM
,
3980 GetWebRenderBridge());
3981 if (value
.type() == OMTAValue::TMatrix4x4
) {
3982 cssValue
= nsComputedDOMStyle::MatrixToCSSValue(value
.get_Matrix4x4());
3984 } else if (aProperty
.EqualsLiteral("background-color")) {
3985 OMTAValue value
= GetOMTAValue(
3986 frame
, DisplayItemType::TYPE_BACKGROUND_COLOR
, GetWebRenderBridge());
3987 if (value
.type() == OMTAValue::Tnscolor
) {
3988 nsStyleUtil::GetSerializedColorValue(value
.get_nscolor(), aResult
);
3995 cssValue
->GetCssText(aResult
);
4003 nsDOMWindowUtils::IsAnimationInPendingTracker(dom::Animation
* aAnimation
,
4005 MOZ_ASSERT(aRetVal
);
4008 return NS_ERROR_INVALID_ARG
;
4011 Document
* doc
= GetDocument();
4017 PendingAnimationTracker
* tracker
= doc
->GetPendingAnimationTracker();
4023 *aRetVal
= tracker
->IsWaitingToPlay(*aAnimation
) ||
4024 tracker
->IsWaitingToPause(*aAnimation
);
4030 class HandlingUserInputHelper final
: public nsIJSRAIIHelper
{
4032 explicit HandlingUserInputHelper(bool aHandlingUserInput
);
4035 NS_DECL_NSIJSRAIIHELPER
4038 ~HandlingUserInputHelper();
4040 bool mHandlingUserInput
;
4041 bool mDestructCalled
= false;
4044 NS_IMPL_ISUPPORTS(HandlingUserInputHelper
, nsIJSRAIIHelper
)
4046 HandlingUserInputHelper::HandlingUserInputHelper(bool aHandlingUserInput
)
4047 : mHandlingUserInput(aHandlingUserInput
) {
4048 if (aHandlingUserInput
) {
4049 UserActivation::StartHandlingUserInput(eVoidEvent
);
4053 HandlingUserInputHelper::~HandlingUserInputHelper() {
4054 // We assert, but just in case, make sure we notify the ESM.
4055 MOZ_ASSERT(mDestructCalled
);
4056 if (!mDestructCalled
) {
4062 HandlingUserInputHelper::Destruct() {
4063 if (NS_WARN_IF(mDestructCalled
)) {
4064 return NS_ERROR_FAILURE
;
4067 mDestructCalled
= true;
4068 if (mHandlingUserInput
) {
4069 UserActivation::StopHandlingUserInput(eVoidEvent
);
4075 } // unnamed namespace
4078 nsDOMWindowUtils::SetHandlingUserInput(bool aHandlingUserInput
,
4079 nsIJSRAIIHelper
** aHelper
) {
4080 if (aHandlingUserInput
) {
4081 if (Document
* doc
= GetDocument()) {
4082 doc
->NotifyUserGestureActivation();
4085 auto helper
= MakeRefPtr
<HandlingUserInputHelper
>(aHandlingUserInput
);
4086 helper
.forget(aHelper
);
4091 nsDOMWindowUtils::IsKeyboardEventUserActivity(Event
* aEvent
, bool* aResult
) {
4092 NS_ENSURE_STATE(aEvent
);
4093 if (!aEvent
->AsKeyboardEvent()) {
4094 return NS_ERROR_INVALID_ARG
;
4097 WidgetEvent
* internalEvent
= aEvent
->WidgetEventPtr();
4098 NS_ENSURE_STATE(internalEvent
);
4099 *aResult
= EventStateManager::IsKeyboardEventUserActivity(internalEvent
);
4104 nsDOMWindowUtils::GetContentAPZTestData(
4105 JSContext
* aContext
, JS::MutableHandle
<JS::Value
> aOutContentTestData
) {
4106 if (nsIWidget
* widget
= GetWidget()) {
4107 WindowRenderer
* renderer
= widget
->GetWindowRenderer();
4111 if (WebRenderLayerManager
* wr
= renderer
->AsWebRender()) {
4112 if (!wr
->GetAPZTestData().ToJS(aOutContentTestData
, aContext
)) {
4113 return NS_ERROR_FAILURE
;
4122 nsDOMWindowUtils::GetCompositorAPZTestData(
4123 JSContext
* aContext
, JS::MutableHandle
<JS::Value
> aOutCompositorTestData
) {
4124 if (nsIWidget
* widget
= GetWidget()) {
4125 WindowRenderer
* renderer
= widget
->GetWindowRenderer();
4129 APZTestData compositorSideData
;
4130 if (WebRenderLayerManager
* wr
= renderer
->AsWebRender()) {
4131 if (!wr
->WrBridge()) {
4132 return NS_ERROR_UNEXPECTED
;
4134 if (!wr
->WrBridge()->SendGetAPZTestData(&compositorSideData
)) {
4135 return NS_ERROR_FAILURE
;
4138 if (!compositorSideData
.ToJS(aOutCompositorTestData
, aContext
)) {
4139 return NS_ERROR_FAILURE
;
4147 nsDOMWindowUtils::PostRestyleSelfEvent(Element
* aElement
) {
4149 return NS_ERROR_INVALID_ARG
;
4152 nsLayoutUtils::PostRestyleEvent(aElement
, RestyleHint::RESTYLE_SELF
,
4158 nsDOMWindowUtils::SetChromeMargin(int32_t aTop
, int32_t aRight
, int32_t aBottom
,
4160 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
4162 nsCOMPtr
<nsIBaseWindow
> baseWindow
=
4163 do_QueryInterface(window
->GetDocShell());
4165 nsCOMPtr
<nsIWidget
> widget
;
4166 baseWindow
->GetMainWidget(getter_AddRefs(widget
));
4168 LayoutDeviceIntMargin
margins(aTop
, aRight
, aBottom
, aLeft
);
4169 return widget
->SetNonClientMargins(margins
);
4178 nsDOMWindowUtils::SetResizeMargin(int32_t aResizeMargin
) {
4179 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
4181 nsCOMPtr
<nsIBaseWindow
> baseWindow
=
4182 do_QueryInterface(window
->GetDocShell());
4184 nsCOMPtr
<nsIWidget
> widget
;
4185 baseWindow
->GetMainWidget(getter_AddRefs(widget
));
4187 CSSToLayoutDeviceScale scaleFactor
= widget
->GetDefaultScale();
4188 widget
->SetResizeMargin(
4189 (CSSCoord(float(aResizeMargin
)) * scaleFactor
).Rounded());
4198 nsDOMWindowUtils::GetFrameUniformityTestData(
4199 JSContext
* aContext
, JS::MutableHandle
<JS::Value
> aOutFrameUniformity
) {
4200 nsIWidget
* widget
= GetWidget();
4202 return NS_ERROR_NOT_AVAILABLE
;
4205 WindowRenderer
* renderer
= widget
->GetWindowRenderer();
4207 return NS_ERROR_NOT_AVAILABLE
;
4210 FrameUniformityData outData
;
4211 renderer
->GetFrameUniformity(&outData
);
4212 outData
.ToJS(aOutFrameUniformity
, aContext
);
4217 nsDOMWindowUtils::XpconnectArgument(nsISupports
* aObj
) {
4223 nsDOMWindowUtils::AskPermission(nsIContentPermissionRequest
* aRequest
) {
4224 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
4225 return nsContentPermissionUtils::AskPermission(
4226 aRequest
, window
->GetCurrentInnerWindow());
4230 nsDOMWindowUtils::GetRestyleGeneration(uint64_t* aResult
) {
4231 nsPresContext
* presContext
= GetPresContext();
4233 return NS_ERROR_NOT_AVAILABLE
;
4236 *aResult
= presContext
->GetRestyleGeneration();
4241 nsDOMWindowUtils::GetFramesConstructed(uint64_t* aResult
) {
4242 nsPresContext
* presContext
= GetPresContext();
4244 return NS_ERROR_NOT_AVAILABLE
;
4247 *aResult
= presContext
->FramesConstructedCount();
4252 nsDOMWindowUtils::GetFramesReflowed(uint64_t* aResult
) {
4253 nsPresContext
* presContext
= GetPresContext();
4255 return NS_ERROR_NOT_AVAILABLE
;
4258 *aResult
= presContext
->FramesReflowedCount();
4263 nsDOMWindowUtils::GetAnimationTriggeredRestyles(uint64_t* aResult
) {
4264 nsPresContext
* presContext
= GetPresContext();
4266 return NS_ERROR_NOT_AVAILABLE
;
4269 *aResult
= presContext
->AnimationTriggeredRestylesCount();
4274 nsDOMWindowUtils::GetRefreshDriverHasPendingTick(bool* aResult
) {
4275 nsPresContext
* presContext
= GetPresContext();
4277 return NS_ERROR_NOT_AVAILABLE
;
4280 *aResult
= presContext
->RefreshDriver()->HasPendingTick();
4285 nsDOMWindowUtils::EnterChaosMode() {
4286 ChaosMode::enterChaosMode();
4291 nsDOMWindowUtils::LeaveChaosMode() {
4292 ChaosMode::leaveChaosMode();
4297 nsDOMWindowUtils::TriggerDeviceReset() {
4298 if (!XRE_IsParentProcess()) {
4299 return NS_ERROR_NOT_AVAILABLE
;
4302 GPUProcessManager
* pm
= GPUProcessManager::Get();
4304 pm
->SimulateDeviceReset();
4310 nsDOMWindowUtils::HasRuleProcessorUsedByMultipleStyleSets(uint32_t aSheetType
,
4312 PresShell
* presShell
= GetPresShell();
4314 return NS_ERROR_FAILURE
;
4317 return presShell
->HasRuleProcessorUsedByMultipleStyleSets(aSheetType
,
4322 nsDOMWindowUtils::RespectDisplayPortSuppression(bool aEnabled
) {
4323 RefPtr
<PresShell
> presShell
= GetPresShell();
4324 presShell
->RespectDisplayportSuppression(aEnabled
);
4329 nsDOMWindowUtils::ForceReflowInterrupt() {
4330 nsPresContext
* pc
= GetPresContext();
4332 return NS_ERROR_NOT_AVAILABLE
;
4334 pc
->SetPendingInterruptFromTest();
4339 nsDOMWindowUtils::TerminateGPUProcess() {
4340 GPUProcessManager
* pm
= GPUProcessManager::Get();
4348 nsDOMWindowUtils::GetGpuProcessPid(int32_t* aPid
) {
4349 GPUProcessManager
* pm
= GPUProcessManager::Get();
4351 *aPid
= pm
->GPUProcessPid();
4359 struct StateTableEntry
{
4360 const char* mStateString
;
4361 ElementState mState
;
4364 static constexpr StateTableEntry kManuallyManagedStates
[] = {
4365 {"autofill", ElementState::AUTOFILL
},
4366 // :-moz-autofill-preview implies :autofill.
4367 {"-moz-autofill-preview",
4368 ElementState::AUTOFILL_PREVIEW
| ElementState::AUTOFILL
},
4369 {nullptr, ElementState()},
4372 static_assert(!kManuallyManagedStates
[ArrayLength(kManuallyManagedStates
) - 1]
4374 "last kManuallyManagedStates entry must be a sentinel with "
4375 "mStateString == nullptr");
4377 static ElementState
GetEventStateForString(const nsAString
& aStateString
) {
4378 for (const StateTableEntry
* entry
= kManuallyManagedStates
;
4379 entry
->mStateString
; ++entry
) {
4380 if (aStateString
.EqualsASCII(entry
->mStateString
)) {
4381 return entry
->mState
;
4384 return ElementState();
4388 nsDOMWindowUtils::AddManuallyManagedState(Element
* aElement
,
4389 const nsAString
& aStateString
) {
4391 return NS_ERROR_INVALID_ARG
;
4394 ElementState state
= GetEventStateForString(aStateString
);
4395 if (state
.IsEmpty()) {
4396 return NS_ERROR_INVALID_ARG
;
4399 aElement
->AddStates(state
);
4404 nsDOMWindowUtils::RemoveManuallyManagedState(Element
* aElement
,
4405 const nsAString
& aStateString
) {
4407 return NS_ERROR_INVALID_ARG
;
4410 ElementState state
= GetEventStateForString(aStateString
);
4411 if (state
.IsEmpty()) {
4412 return NS_ERROR_INVALID_ARG
;
4415 aElement
->RemoveStates(state
);
4420 nsDOMWindowUtils::GetStorageUsage(Storage
* aStorage
, int64_t* aRetval
) {
4422 return NS_ERROR_UNEXPECTED
;
4425 *aRetval
= aStorage
->GetOriginQuotaUsage();
4431 nsDOMWindowUtils::GetDirectionFromText(const nsAString
& aString
,
4433 Directionality dir
=
4434 ::GetDirectionFromText(aString
.BeginReading(), aString
.Length(), nullptr);
4437 *aRetval
= nsIDOMWindowUtils::DIRECTION_NOT_SET
;
4440 *aRetval
= nsIDOMWindowUtils::DIRECTION_RTL
;
4443 *aRetval
= nsIDOMWindowUtils::DIRECTION_LTR
;
4446 MOZ_ASSERT_UNREACHABLE(
4447 "GetDirectionFromText should never return this value");
4448 return NS_ERROR_FAILURE
;
4454 nsDOMWindowUtils::EnsureDirtyRootFrame() {
4455 Document
* doc
= GetDocument();
4456 PresShell
* presShell
= doc
? doc
->GetPresShell() : nullptr;
4459 return NS_ERROR_FAILURE
;
4462 nsIFrame
* frame
= presShell
->GetRootFrame();
4464 return NS_ERROR_FAILURE
;
4467 presShell
->FrameNeedsReflow(
4468 frame
, IntrinsicDirty::FrameAncestorsAndDescendants
, NS_FRAME_IS_DIRTY
);
4472 NS_INTERFACE_MAP_BEGIN(nsTranslationNodeList
)
4473 NS_INTERFACE_MAP_ENTRY(nsISupports
)
4474 NS_INTERFACE_MAP_ENTRY(nsITranslationNodeList
)
4475 NS_INTERFACE_MAP_END
4477 NS_IMPL_ADDREF(nsTranslationNodeList
)
4478 NS_IMPL_RELEASE(nsTranslationNodeList
)
4481 nsTranslationNodeList::Item(uint32_t aIndex
, nsINode
** aRetVal
) {
4482 NS_ENSURE_ARG_POINTER(aRetVal
);
4483 NS_IF_ADDREF(*aRetVal
= mNodes
.SafeElementAt(aIndex
));
4488 nsTranslationNodeList::IsTranslationRootAtIndex(uint32_t aIndex
,
4490 NS_ENSURE_ARG_POINTER(aRetVal
);
4491 if (aIndex
>= mLength
) {
4496 *aRetVal
= mNodeIsRoot
.ElementAt(aIndex
);
4501 nsTranslationNodeList::GetLength(uint32_t* aRetVal
) {
4502 NS_ENSURE_ARG_POINTER(aRetVal
);
4508 nsDOMWindowUtils::WrCapture() {
4509 if (WebRenderBridgeChild
* wrbc
= GetWebRenderBridge()) {
4516 nsDOMWindowUtils::WrStartCaptureSequence(const nsACString
& aPath
,
4518 if (WebRenderBridgeChild
* wrbc
= GetWebRenderBridge()) {
4519 wrbc
->StartCaptureSequence(nsCString(aPath
), aFlags
);
4525 nsDOMWindowUtils::WrStopCaptureSequence() {
4526 if (WebRenderBridgeChild
* wrbc
= GetWebRenderBridge()) {
4527 wrbc
->StopCaptureSequence();
4533 nsDOMWindowUtils::SetCompositionRecording(bool aValue
, Promise
** aOutPromise
) {
4534 return aValue
? StartCompositionRecording(aOutPromise
)
4535 : StopCompositionRecording(true, aOutPromise
);
4539 nsDOMWindowUtils::StartCompositionRecording(Promise
** aOutPromise
) {
4540 NS_ENSURE_ARG(aOutPromise
);
4541 *aOutPromise
= nullptr;
4543 nsCOMPtr
<nsPIDOMWindowOuter
> outer
= do_QueryReferent(mWindow
);
4544 NS_ENSURE_STATE(outer
);
4545 nsCOMPtr
<nsPIDOMWindowInner
> inner
= outer
->GetCurrentInnerWindow();
4546 NS_ENSURE_STATE(inner
);
4549 RefPtr
<Promise
> promise
= Promise::Create(inner
->AsGlobal(), err
);
4550 if (NS_WARN_IF(err
.Failed())) {
4551 return err
.StealNSResult();
4554 CompositorBridgeChild
* cbc
= GetCompositorBridge();
4555 if (NS_WARN_IF(!cbc
)) {
4556 promise
->MaybeReject(NS_ERROR_UNEXPECTED
);
4558 cbc
->SendBeginRecording(TimeStamp::Now())
4560 GetCurrentSerialEventTarget(), __func__
,
4561 [promise
](const bool& aSuccess
) {
4563 promise
->MaybeResolve(true);
4565 promise
->MaybeRejectWithInvalidStateError(
4566 "The composition recorder is already running.");
4569 [promise
](const mozilla::ipc::ResponseRejectReason
&) {
4570 promise
->MaybeRejectWithInvalidStateError(
4571 "Could not start the composition recorder.");
4575 promise
.forget(aOutPromise
);
4579 static bool WriteRecordingToDisk(const FrameRecording
& aRecording
,
4580 double aUnixStartMS
) {
4581 // The directory name contains the unix timestamp for when recording started,
4582 // because we want the consumer of these files to be able to compute an
4583 // absolute timestamp of each screenshot. That allows them to align
4584 // screenshots with timed data from other sources, such as Gecko profiler
4585 // information. The time of each screenshot is part of the screenshot's
4586 // filename, expressed as milliseconds from the recording start.
4587 std::stringstream recordingDirectory
;
4588 recordingDirectory
<< gfxVars::LayersWindowRecordingPath()
4589 << "windowrecording-" << int64_t(aUnixStartMS
);
4592 _mkdir(recordingDirectory
.str().c_str());
4594 mkdir(recordingDirectory
.str().c_str(), 0777);
4597 auto byteSpan
= aRecording
.bytes().AsSpan();
4601 for (const auto& frame
: aRecording
.frames()) {
4602 const uint32_t frameBufferLength
= frame
.length();
4603 if (frameBufferLength
> byteSpan
.Length()) {
4607 const auto frameSpan
= byteSpan
.To(frameBufferLength
);
4608 byteSpan
= byteSpan
.From(frameBufferLength
);
4610 const double frameTimeMS
=
4611 (frame
.timeOffset() - aRecording
.startTime()).ToMilliseconds();
4613 std::stringstream filename
;
4614 filename
<< recordingDirectory
.str() << "/frame-" << i
<< "-"
4615 << uint32_t(frameTimeMS
) << ".png";
4617 FILE* file
= fopen(filename
.str().c_str(), "wb");
4622 const size_t bytesWritten
=
4623 fwrite(frameSpan
.Elements(), sizeof(uint8_t), frameSpan
.Length(), file
);
4627 if (bytesWritten
< frameSpan
.Length()) {
4634 return byteSpan
.Length() == 0;
4637 static Maybe
<DOMCollectedFrames
> ConvertCompositionRecordingFramesToDom(
4638 const FrameRecording
& aRecording
, double aUnixStartMS
) {
4639 auto byteSpan
= aRecording
.bytes().AsSpan();
4641 nsTArray
<DOMCollectedFrame
> domFrames
;
4643 for (const auto& recordedFrame
: aRecording
.frames()) {
4644 const uint32_t frameBufferLength
= recordedFrame
.length();
4645 if (frameBufferLength
> byteSpan
.Length()) {
4649 const auto frameSpan
= byteSpan
.To(frameBufferLength
);
4650 byteSpan
= byteSpan
.From(frameBufferLength
);
4654 dataUri
.AppendLiteral("data:image/png;base64,");
4657 Base64EncodeAppend(reinterpret_cast<const char*>(frameSpan
.Elements()),
4658 frameSpan
.Length(), dataUri
);
4659 if (NS_FAILED(rv
)) {
4663 DOMCollectedFrame domFrame
;
4664 domFrame
.mTimeOffset
=
4665 (recordedFrame
.timeOffset() - aRecording
.startTime()).ToMilliseconds();
4666 domFrame
.mDataUri
= std::move(dataUri
);
4668 domFrames
.AppendElement(std::move(domFrame
));
4671 if (byteSpan
.Length() != 0) {
4675 DOMCollectedFrames result
;
4677 result
.mRecordingStart
= aUnixStartMS
;
4678 result
.mFrames
= std::move(domFrames
);
4680 return Some(std::move(result
));
4684 nsDOMWindowUtils::StopCompositionRecording(bool aWriteToDisk
,
4685 Promise
** aOutPromise
) {
4686 NS_ENSURE_ARG_POINTER(aOutPromise
);
4687 *aOutPromise
= nullptr;
4689 nsCOMPtr
<nsPIDOMWindowOuter
> outer
= do_QueryReferent(mWindow
);
4690 NS_ENSURE_STATE(outer
);
4691 nsCOMPtr
<nsPIDOMWindowInner
> inner
= outer
->GetCurrentInnerWindow();
4692 NS_ENSURE_STATE(inner
);
4695 RefPtr
<Promise
> promise
= Promise::Create(inner
->AsGlobal(), err
);
4696 if (NS_WARN_IF(err
.Failed())) {
4697 return err
.StealNSResult();
4700 RefPtr
<Promise
>(promise
).forget(aOutPromise
);
4702 CompositorBridgeChild
* cbc
= GetCompositorBridge();
4703 if (NS_WARN_IF(!cbc
)) {
4704 promise
->MaybeReject(NS_ERROR_UNEXPECTED
);
4708 cbc
->SendEndRecording()->Then(
4709 GetCurrentSerialEventTarget(), __func__
,
4710 [promise
, aWriteToDisk
](Maybe
<FrameRecording
>&& aRecording
) {
4712 promise
->MaybeRejectWithUnknownError("Failed to get frame recording");
4716 // We need to know when the recording started in Unix Time.
4717 // Unfortunately, the recording start time is an opaque Timestamp that
4718 // can only be used to calculate a duration.
4720 // This is not great, but we are going to get Now() twice in close
4721 // proximity, one in Unix Time and the other in Timestamp time. Then we
4722 // can subtract the length of the recording from the current Unix Time
4723 // to get the Unix start time.
4724 const TimeStamp timestampNow
= TimeStamp::Now();
4725 const int64_t unixNowUS
= PR_Now();
4727 const TimeDuration recordingLength
=
4728 timestampNow
- aRecording
->startTime();
4729 const double unixNowMS
= double(unixNowUS
) / 1000.0;
4730 const double unixStartMS
= unixNowMS
- recordingLength
.ToMilliseconds();
4733 if (!WriteRecordingToDisk(*aRecording
, unixStartMS
)) {
4734 promise
->MaybeRejectWithUnknownError(
4735 "Failed to write recording to disk");
4738 promise
->MaybeResolveWithUndefined();
4740 auto maybeDomFrames
=
4741 ConvertCompositionRecordingFramesToDom(*aRecording
, unixStartMS
);
4742 if (!maybeDomFrames
) {
4743 promise
->MaybeRejectWithUnknownError(
4744 "Unable to base64-encode recorded frames");
4747 promise
->MaybeResolve(*maybeDomFrames
);
4750 [promise
](const mozilla::ipc::ResponseRejectReason
&) {
4751 promise
->MaybeRejectWithUnknownError(
4752 "IPC failed getting composition recording");
4759 nsDOMWindowUtils::SetSystemFont(const nsACString
& aFontName
) {
4760 nsIWidget
* widget
= GetWidget();
4765 nsAutoCString
fontName(aFontName
);
4766 return widget
->SetSystemFont(fontName
);
4770 nsDOMWindowUtils::GetSystemFont(nsACString
& aFontName
) {
4771 nsIWidget
* widget
= GetWidget();
4776 nsAutoCString fontName
;
4777 widget
->GetSystemFont(fontName
);
4778 aFontName
.Assign(fontName
);
4783 nsDOMWindowUtils::IsCssPropertyRecordedInUseCounter(const nsACString
& aPropName
,
4787 Document
* doc
= GetDocument();
4788 if (!doc
|| !doc
->GetStyleUseCounters()) {
4789 return NS_ERROR_FAILURE
;
4792 bool knownProp
= false;
4793 *aRecorded
= Servo_IsCssPropertyRecordedInUseCounter(
4794 doc
->GetStyleUseCounters(), &aPropName
, &knownProp
);
4795 return knownProp
? NS_OK
: NS_ERROR_FAILURE
;
4799 nsDOMWindowUtils::IsCoepCredentialless(bool* aResult
) {
4800 Document
* doc
= GetDocument();
4802 return NS_ERROR_FAILURE
;
4805 *aResult
= net::IsCoepCredentiallessEnabled(
4806 doc
->Trials().IsEnabled(OriginTrial::CoepCredentialless
));
4811 nsDOMWindowUtils::GetLayersId(uint64_t* aOutLayersId
) {
4812 nsIWidget
* widget
= GetWidget();
4814 return NS_ERROR_FAILURE
;
4816 BrowserChild
* child
= widget
->GetOwningBrowserChild();
4818 return NS_ERROR_FAILURE
;
4820 *aOutLayersId
= (uint64_t)child
->GetLayersId();
4825 nsDOMWindowUtils::GetPaintCount(uint64_t* aPaintCount
) {
4826 auto* presShell
= GetPresShell();
4827 *aPaintCount
= presShell
? presShell
->GetPaintCount() : 0;
4832 nsDOMWindowUtils::GetWebrtcRawDeviceId(nsAString
& aRawDeviceId
) {
4833 if (!XRE_IsParentProcess()) {
4835 "GetWebrtcRawDeviceId is only available in the parent "
4839 nsIWidget
* widget
= GetWidget();
4841 return NS_ERROR_FAILURE
;
4844 int64_t rawDeviceId
=
4845 (int64_t)(widget
->GetNativeData(NS_NATIVE_WINDOW_WEBRTC_DEVICE_ID
));
4847 return NS_ERROR_FAILURE
;
4850 aRawDeviceId
.AppendInt(rawDeviceId
);
4855 nsDOMWindowUtils::GetEffectivelyThrottlesFrameRequests(bool* aResult
) {
4856 Document
* doc
= GetDocument();
4858 return NS_ERROR_FAILURE
;
4860 *aResult
= !doc
->WouldScheduleFrameRequestCallbacks() ||
4861 doc
->ShouldThrottleFrameRequests();
4866 nsDOMWindowUtils::ResetMobileViewportManager() {
4867 if (RefPtr
<PresShell
> presShell
= GetPresShell()) {
4868 if (auto mvm
= presShell
->GetMobileViewportManager()) {
4869 mvm
->SetInitialViewport();
4873 // Unable to reset, so let's error out
4874 return NS_ERROR_FAILURE
;
4878 nsDOMWindowUtils::GetSuspendedByBrowsingContextGroup(bool* aResult
) {
4879 nsCOMPtr
<nsPIDOMWindowOuter
> window
= do_QueryReferent(mWindow
);
4880 NS_ENSURE_TRUE(window
, NS_ERROR_FAILURE
);
4882 nsCOMPtr
<nsPIDOMWindowInner
> inner
= window
->GetCurrentInnerWindow();
4883 NS_ENSURE_TRUE(inner
, NS_ERROR_FAILURE
);
4885 *aResult
= inner
->GetWasSuspendedByGroup();
4890 nsDOMWindowUtils::GetHasScrollLinkedEffect(bool* aResult
) {
4891 Document
* doc
= GetDocument();
4893 return NS_ERROR_FAILURE
;
4895 *aResult
= doc
->HasScrollLinkedEffect();
4900 nsDOMWindowUtils::GetOrientationLock(uint32_t* aOrientationLock
) {
4901 NS_WARNING("nsDOMWindowUtils::GetOrientationLock");
4903 nsIDocShell
* docShell
= GetDocShell();
4905 return NS_ERROR_FAILURE
;
4908 BrowsingContext
* bc
= docShell
->GetBrowsingContext();
4909 bc
= bc
? bc
->Top() : nullptr;
4911 return NS_ERROR_FAILURE
;
4914 *aOrientationLock
= static_cast<uint32_t>(bc
->GetOrientationLock());
4919 nsDOMWindowUtils::GetWheelScrollTarget(Element
** aResult
) {
4921 if (nsIFrame
* targetFrame
= WheelTransaction::GetScrollTargetFrame()) {
4922 NS_IF_ADDREF(*aResult
= Element::FromNodeOrNull(targetFrame
->GetContent()));
4928 nsDOMWindowUtils::SetHiDPIMode(bool aHiDPI
) {
4930 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
4931 if (!widget
) return NS_ERROR_FAILURE
;
4933 return widget
->SetHiDPIMode(aHiDPI
);
4935 return NS_ERROR_NOT_AVAILABLE
;
4940 nsDOMWindowUtils::RestoreHiDPIMode() {
4942 nsCOMPtr
<nsIWidget
> widget
= GetWidget();
4943 if (!widget
) return NS_ERROR_FAILURE
;
4945 return widget
->RestoreHiDPIMode();
4947 return NS_ERROR_NOT_AVAILABLE
;