tor-browser

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

nsScreen.cpp (6681B)


      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/. */
      6 
      7 #include "nsScreen.h"
      8 
      9 #include "mozilla/GeckoBindings.h"
     10 #include "mozilla/dom/BrowsingContextBinding.h"
     11 #include "mozilla/dom/Document.h"
     12 #include "mozilla/dom/DocumentInlines.h"
     13 #include "mozilla/widget/ScreenManager.h"
     14 #include "nsCOMPtr.h"
     15 #include "nsContentUtils.h"
     16 #include "nsDeviceContext.h"
     17 #include "nsGlobalWindowInner.h"
     18 #include "nsGlobalWindowOuter.h"
     19 #include "nsIDocShell.h"
     20 #include "nsIDocShellTreeItem.h"
     21 #include "nsLayoutUtils.h"
     22 #include "nsPresContext.h"
     23 
     24 using namespace mozilla;
     25 using namespace mozilla::dom;
     26 
     27 nsScreen::nsScreen(nsPIDOMWindowInner* aWindow)
     28    : DOMEventTargetHelper(aWindow),
     29      mScreenOrientation(new ScreenOrientation(aWindow, this)) {}
     30 
     31 nsScreen::~nsScreen() = default;
     32 
     33 // QueryInterface implementation for nsScreen
     34 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsScreen)
     35 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
     36 
     37 NS_IMPL_ADDREF_INHERITED(nsScreen, DOMEventTargetHelper)
     38 NS_IMPL_RELEASE_INHERITED(nsScreen, DOMEventTargetHelper)
     39 
     40 NS_IMPL_CYCLE_COLLECTION_INHERITED(nsScreen, DOMEventTargetHelper,
     41                                   mScreenOrientation)
     42 
     43 int32_t nsScreen::PixelDepth() {
     44  // Return 24 to prevent fingerprinting.
     45  if (ShouldResistFingerprinting(RFPTarget::ScreenPixelDepth)) {
     46    return 24;
     47  }
     48  nsDeviceContext* context = GetDeviceContext();
     49  if (NS_WARN_IF(!context)) {
     50    return 24;
     51  }
     52  return context->GetDepth();
     53 }
     54 
     55 nsPIDOMWindowOuter* nsScreen::GetOuter() const {
     56  if (nsPIDOMWindowInner* inner = GetOwnerWindow()) {
     57    return inner->GetOuterWindow();
     58  }
     59  return nullptr;
     60 }
     61 
     62 nsDeviceContext* nsScreen::GetDeviceContext() const {
     63  return nsLayoutUtils::GetDeviceContextForScreenInfo(GetOuter());
     64 }
     65 
     66 CSSIntRect nsScreen::GetRect() {
     67  // Return window inner rect to prevent fingerprinting.
     68  if (ShouldResistFingerprinting(RFPTarget::ScreenRect)) {
     69    return GetTopWindowInnerRectForRFP();
     70  }
     71 
     72  // Here we manipulate the value of aRect to represent the screen size,
     73  // if there is an override set with WebDriver BiDi or in RDM.
     74  if (nsPIDOMWindowInner* owner = GetOwnerWindow()) {
     75    if (Document* doc = owner->GetExtantDoc()) {
     76      Maybe<CSSIntSize> deviceSize =
     77          nsGlobalWindowOuter::GetRDMDeviceSize(*doc);
     78      if (deviceSize.isSome()) {
     79        const CSSIntSize& size = deviceSize.value();
     80        return {0, 0, size.width, size.height};
     81      }
     82    }
     83 
     84    if (BrowsingContext* bc = owner->GetBrowsingContext()) {
     85      if (auto size = bc->GetScreenAreaOverride()) {
     86        return {{}, *size};
     87      }
     88    }
     89  }
     90 
     91  nsDeviceContext* context = GetDeviceContext();
     92  if (NS_WARN_IF(!context)) {
     93    return {};
     94  }
     95  return CSSIntRect::FromAppUnitsRounded(context->GetRect());
     96 }
     97 
     98 CSSIntRect nsScreen::GetAvailRect() {
     99  // Return window inner rect to prevent fingerprinting.
    100  if (ShouldResistFingerprinting(RFPTarget::ScreenAvailRect)) {
    101    return GetTopWindowInnerRectForRFP();
    102  }
    103 
    104  if (ShouldResistFingerprinting(RFPTarget::ScreenAvailToResolution)) {
    105    nsDeviceContext* context = GetDeviceContext();
    106    if (NS_WARN_IF(!context)) {
    107      return {};
    108    }
    109    return nsRFPService::GetSpoofedScreenAvailSize(
    110        context->GetRect(), context->GetFullZoom(), IsFullscreen());
    111  }
    112 
    113  // Here we manipulate the value of aRect to represent the screen size,
    114  // if there is an override set with WebDriver BiDi or in RDM.
    115  if (nsPIDOMWindowInner* owner = GetOwnerWindow()) {
    116    if (Document* doc = owner->GetExtantDoc()) {
    117      Maybe<CSSIntSize> deviceSize =
    118          nsGlobalWindowOuter::GetRDMDeviceSize(*doc);
    119      if (deviceSize.isSome()) {
    120        const CSSIntSize& size = deviceSize.value();
    121        return {0, 0, size.width, size.height};
    122      }
    123    }
    124 
    125    if (BrowsingContext* bc = owner->GetBrowsingContext()) {
    126      if (auto size = bc->GetScreenAreaOverride()) {
    127        return {{}, *size};
    128      }
    129    }
    130  }
    131 
    132  nsDeviceContext* context = GetDeviceContext();
    133  if (NS_WARN_IF(!context)) {
    134    return {};
    135  }
    136  return CSSIntRect::FromAppUnitsRounded(context->GetClientRect());
    137 }
    138 
    139 bool nsScreen::IsFullscreen() const {
    140  if (nsPIDOMWindowInner* owner = GetOwnerWindow()) {
    141    if (Document* doc = owner->GetExtantDoc()) {
    142      return StyleDisplayMode::Fullscreen ==
    143             Gecko_MediaFeatures_GetDisplayMode(doc);
    144    }
    145  }
    146  return false;
    147 }
    148 
    149 uint16_t nsScreen::GetOrientationAngle() const {
    150  nsDeviceContext* context = GetDeviceContext();
    151  if (context) {
    152    return context->GetScreenOrientationAngle();
    153  }
    154  RefPtr<widget::Screen> s =
    155      widget::ScreenManager::GetSingleton().GetPrimaryScreen();
    156  return s->GetOrientationAngle();
    157 }
    158 
    159 hal::ScreenOrientation nsScreen::GetOrientationType() const {
    160  nsDeviceContext* context = GetDeviceContext();
    161  if (context) {
    162    return context->GetScreenOrientationType();
    163  }
    164  RefPtr<widget::Screen> s =
    165      widget::ScreenManager::GetSingleton().GetPrimaryScreen();
    166  return s->GetOrientationType();
    167 }
    168 
    169 ScreenOrientation* nsScreen::Orientation() const { return mScreenOrientation; }
    170 
    171 void nsScreen::GetMozOrientation(nsString& aOrientation,
    172                                 CallerType aCallerType) const {
    173  switch (mScreenOrientation->DeviceType(aCallerType)) {
    174    case OrientationType::Portrait_primary:
    175      aOrientation.AssignLiteral("portrait-primary");
    176      break;
    177    case OrientationType::Portrait_secondary:
    178      aOrientation.AssignLiteral("portrait-secondary");
    179      break;
    180    case OrientationType::Landscape_primary:
    181      aOrientation.AssignLiteral("landscape-primary");
    182      break;
    183    case OrientationType::Landscape_secondary:
    184      aOrientation.AssignLiteral("landscape-secondary");
    185      break;
    186    default:
    187      MOZ_CRASH("Unacceptable screen orientation type.");
    188  }
    189 }
    190 
    191 /* virtual */
    192 JSObject* nsScreen::WrapObject(JSContext* aCx,
    193                               JS::Handle<JSObject*> aGivenProto) {
    194  return Screen_Binding::Wrap(aCx, this, aGivenProto);
    195 }
    196 
    197 CSSIntRect nsScreen::GetTopWindowInnerRectForRFP() {
    198  if (nsPIDOMWindowInner* inner = GetOwnerWindow()) {
    199    if (BrowsingContext* bc = inner->GetBrowsingContext()) {
    200      CSSIntSize size = bc->Top()->GetTopInnerSizeForRFP();
    201      return {0, 0, size.width, size.height};
    202    }
    203  }
    204  return {};
    205 }
    206 
    207 bool nsScreen::ShouldResistFingerprinting(RFPTarget aTarget) const {
    208  nsGlobalWindowInner* owner = GetOwnerWindow();
    209  return owner && owner->ShouldResistFingerprinting(aTarget);
    210 }