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 "nsContentUtils.h"
9 #include "mozilla/dom/Document.h"
10 #include "nsGlobalWindowInner.h"
11 #include "nsGlobalWindowOuter.h"
12 #include "nsIDocShell.h"
13 #include "nsPresContext.h"
15 #include "nsIDocShellTreeItem.h"
16 #include "nsLayoutUtils.h"
17 #include "nsJSUtils.h"
18 #include "nsDeviceContext.h"
19 #include "mozilla/widget/ScreenManager.h"
21 using namespace mozilla
;
22 using namespace mozilla::dom
;
25 already_AddRefed
<nsScreen
> nsScreen::Create(nsPIDOMWindowInner
* aWindow
) {
28 if (!aWindow
->GetDocShell()) {
32 nsCOMPtr
<nsIScriptGlobalObject
> sgo
= do_QueryInterface(aWindow
);
33 NS_ENSURE_TRUE(sgo
, nullptr);
35 RefPtr
<nsScreen
> screen
= new nsScreen(aWindow
);
36 return screen
.forget();
39 nsScreen::nsScreen(nsPIDOMWindowInner
* aWindow
)
40 : DOMEventTargetHelper(aWindow
),
41 mScreenOrientation(new ScreenOrientation(aWindow
, this)) {}
43 nsScreen::~nsScreen() = default;
45 // QueryInterface implementation for nsScreen
46 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsScreen
)
47 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper
)
49 NS_IMPL_ADDREF_INHERITED(nsScreen
, DOMEventTargetHelper
)
50 NS_IMPL_RELEASE_INHERITED(nsScreen
, DOMEventTargetHelper
)
52 NS_IMPL_CYCLE_COLLECTION_INHERITED(nsScreen
, DOMEventTargetHelper
,
55 int32_t nsScreen::GetPixelDepth(ErrorResult
& aRv
) {
56 // Return 24 to prevent fingerprinting.
57 if (ShouldResistFingerprinting(RFPTarget::ScreenPixelDepth
)) {
61 nsDeviceContext
* context
= GetDeviceContext();
64 aRv
.Throw(NS_ERROR_FAILURE
);
68 return context
->GetDepth();
71 nsPIDOMWindowOuter
* nsScreen::GetOuter() const {
72 if (nsPIDOMWindowInner
* inner
= GetOwner()) {
73 return inner
->GetOuterWindow();
79 nsDeviceContext
* nsScreen::GetDeviceContext() const {
80 return nsLayoutUtils::GetDeviceContextForScreenInfo(GetOuter());
83 nsresult
nsScreen::GetRect(CSSIntRect
& aRect
) {
84 // Return window inner rect to prevent fingerprinting.
85 if (ShouldResistFingerprinting(RFPTarget::ScreenRect
)) {
86 return GetWindowInnerRect(aRect
);
89 // Here we manipulate the value of aRect to represent the screen size,
91 if (nsCOMPtr
<nsPIDOMWindowInner
> owner
= GetOwner()) {
92 if (Document
* doc
= owner
->GetExtantDoc()) {
93 Maybe
<CSSIntSize
> deviceSize
=
94 nsGlobalWindowOuter::GetRDMDeviceSize(*doc
);
95 if (deviceSize
.isSome()) {
96 const CSSIntSize
& size
= deviceSize
.value();
97 aRect
.SetRect(0, 0, size
.width
, size
.height
);
103 nsDeviceContext
* context
= GetDeviceContext();
106 return NS_ERROR_FAILURE
;
111 aRect
= CSSIntRect::FromAppUnitsRounded(r
);
115 nsresult
nsScreen::GetAvailRect(CSSIntRect
& aRect
) {
116 // Return window inner rect to prevent fingerprinting.
117 if (ShouldResistFingerprinting(RFPTarget::ScreenAvailRect
)) {
118 return GetWindowInnerRect(aRect
);
121 // Here we manipulate the value of aRect to represent the screen size,
123 if (nsCOMPtr
<nsPIDOMWindowInner
> owner
= GetOwner()) {
124 if (Document
* doc
= owner
->GetExtantDoc()) {
125 Maybe
<CSSIntSize
> deviceSize
=
126 nsGlobalWindowOuter::GetRDMDeviceSize(*doc
);
127 if (deviceSize
.isSome()) {
128 const CSSIntSize
& size
= deviceSize
.value();
129 aRect
.SetRect(0, 0, size
.width
, size
.height
);
135 nsDeviceContext
* context
= GetDeviceContext();
137 return NS_ERROR_FAILURE
;
141 context
->GetClientRect(r
);
142 aRect
= CSSIntRect::FromAppUnitsRounded(r
);
146 uint16_t nsScreen::GetOrientationAngle() const {
147 nsDeviceContext
* context
= GetDeviceContext();
149 return context
->GetScreenOrientationAngle();
151 RefPtr
<widget::Screen
> s
=
152 widget::ScreenManager::GetSingleton().GetPrimaryScreen();
153 return s
->GetOrientationAngle();
156 hal::ScreenOrientation
nsScreen::GetOrientationType() const {
157 nsDeviceContext
* context
= GetDeviceContext();
159 return context
->GetScreenOrientationType();
161 RefPtr
<widget::Screen
> s
=
162 widget::ScreenManager::GetSingleton().GetPrimaryScreen();
163 return s
->GetOrientationType();
166 ScreenOrientation
* nsScreen::Orientation() const { return mScreenOrientation
; }
168 void nsScreen::GetMozOrientation(nsString
& aOrientation
,
169 CallerType aCallerType
) const {
170 switch (mScreenOrientation
->DeviceType(aCallerType
)) {
171 case OrientationType::Portrait_primary
:
172 aOrientation
.AssignLiteral("portrait-primary");
174 case OrientationType::Portrait_secondary
:
175 aOrientation
.AssignLiteral("portrait-secondary");
177 case OrientationType::Landscape_primary
:
178 aOrientation
.AssignLiteral("landscape-primary");
180 case OrientationType::Landscape_secondary
:
181 aOrientation
.AssignLiteral("landscape-secondary");
184 MOZ_CRASH("Unacceptable screen orientation type.");
188 bool nsScreen::MozLockOrientation(const nsAString
& aOrientation
,
190 nsString
orientation(aOrientation
);
191 Sequence
<nsString
> orientations
;
192 if (!orientations
.AppendElement(orientation
, fallible
)) {
193 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
196 return MozLockOrientation(orientations
, aRv
);
199 // This function is deprecated, use ScreenOrientation API instead.
200 bool nsScreen::MozLockOrientation(const Sequence
<nsString
>& aOrientations
,
205 void nsScreen::MozUnlockOrientation() {}
208 JSObject
* nsScreen::WrapObject(JSContext
* aCx
,
209 JS::Handle
<JSObject
*> aGivenProto
) {
210 return Screen_Binding::Wrap(aCx
, this, aGivenProto
);
213 nsresult
nsScreen::GetWindowInnerRect(CSSIntRect
& aRect
) {
216 nsCOMPtr
<nsPIDOMWindowInner
> win
= GetOwner();
218 return NS_ERROR_FAILURE
;
222 nsresult rv
= win
->GetInnerWidth(&width
);
223 NS_ENSURE_SUCCESS(rv
, rv
);
224 rv
= win
->GetInnerHeight(&height
);
225 NS_ENSURE_SUCCESS(rv
, rv
);
226 aRect
.SizeTo(std::round(width
), std::round(height
));
230 bool nsScreen::ShouldResistFingerprinting(RFPTarget aTarget
) const {
231 nsCOMPtr
<nsPIDOMWindowInner
> owner
= GetOwner();
233 nsGlobalWindowInner::Cast(owner
)->ShouldResistFingerprinting(aTarget
);