LCOV - code coverage report
Current view: top level - dom/base - nsScreen.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 67 163 41.1 %
Date: 2017-07-14 16:53:18 Functions: 15 29 51.7 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
       8             : #include "mozilla/dom/ScreenBinding.h"
       9             : #include "nsContentUtils.h"
      10             : #include "nsScreen.h"
      11             : #include "nsIDocument.h"
      12             : #include "nsIDocShell.h"
      13             : #include "nsIDocument.h"
      14             : #include "nsPresContext.h"
      15             : #include "nsCOMPtr.h"
      16             : #include "nsIDocShellTreeItem.h"
      17             : #include "nsLayoutUtils.h"
      18             : #include "nsJSUtils.h"
      19             : #include "nsDeviceContext.h"
      20             : 
      21             : using namespace mozilla;
      22             : using namespace mozilla::dom;
      23             : 
      24             : /* static */ already_AddRefed<nsScreen>
      25           1 : nsScreen::Create(nsPIDOMWindowInner* aWindow)
      26             : {
      27           1 :   MOZ_ASSERT(aWindow);
      28           1 :   MOZ_ASSERT(aWindow->IsInnerWindow());
      29             : 
      30           1 :   if (!aWindow->GetDocShell()) {
      31           0 :     return nullptr;
      32             :   }
      33             : 
      34           2 :   nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aWindow);
      35           1 :   NS_ENSURE_TRUE(sgo, nullptr);
      36             : 
      37           2 :   RefPtr<nsScreen> screen = new nsScreen(aWindow);
      38           1 :   return screen.forget();
      39             : }
      40             : 
      41           1 : nsScreen::nsScreen(nsPIDOMWindowInner* aWindow)
      42             :   : DOMEventTargetHelper(aWindow)
      43           2 :   , mScreenOrientation(new ScreenOrientation(aWindow, this))
      44             : {
      45           1 : }
      46             : 
      47           0 : nsScreen::~nsScreen()
      48             : {
      49           0 : }
      50             : 
      51             : 
      52             : // QueryInterface implementation for nsScreen
      53          13 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsScreen)
      54           7 :   NS_INTERFACE_MAP_ENTRY(nsIDOMScreen)
      55           6 : NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
      56             : 
      57           5 : NS_IMPL_ADDREF_INHERITED(nsScreen, DOMEventTargetHelper)
      58           2 : NS_IMPL_RELEASE_INHERITED(nsScreen, DOMEventTargetHelper)
      59             : 
      60           1 : NS_IMPL_CYCLE_COLLECTION_INHERITED(nsScreen,
      61             :                                    DOMEventTargetHelper,
      62             :                                    mScreenOrientation)
      63             : 
      64             : int32_t
      65           0 : nsScreen::GetPixelDepth(ErrorResult& aRv)
      66             : {
      67             :   // Return 24 to prevent fingerprinting.
      68           0 :   if (ShouldResistFingerprinting()) {
      69           0 :     return 24;
      70             :   }
      71             : 
      72           0 :   nsDeviceContext* context = GetDeviceContext();
      73             : 
      74           0 :   if (!context) {
      75           0 :     aRv.Throw(NS_ERROR_FAILURE);
      76           0 :     return -1;
      77             :   }
      78             : 
      79             :   uint32_t depth;
      80           0 :   context->GetDepth(depth);
      81           0 :   return depth;
      82             : }
      83             : 
      84             : #define FORWARD_LONG_GETTER(_name)                                              \
      85             :   NS_IMETHODIMP                                                                 \
      86             :   nsScreen::Get ## _name(int32_t* aOut)                                         \
      87             :   {                                                                             \
      88             :     ErrorResult rv;                                                             \
      89             :     *aOut = Get ## _name(rv);                                                   \
      90             :     return rv.StealNSResult();                                                  \
      91             :   }
      92             : 
      93           1 : FORWARD_LONG_GETTER(AvailWidth)
      94           1 : FORWARD_LONG_GETTER(AvailHeight)
      95             : 
      96           0 : FORWARD_LONG_GETTER(Top)
      97           0 : FORWARD_LONG_GETTER(AvailTop)
      98           0 : FORWARD_LONG_GETTER(AvailLeft)
      99             : 
     100             : nsPIDOMWindowOuter*
     101          10 : nsScreen::GetOuter() const
     102             : {
     103          10 :   if (nsPIDOMWindowInner* inner = GetOwner()) {
     104          10 :     return inner->GetOuterWindow();
     105             :   }
     106             : 
     107           0 :   return nullptr;
     108             : }
     109             : 
     110             : nsDeviceContext*
     111          10 : nsScreen::GetDeviceContext()
     112             : {
     113          10 :   return nsLayoutUtils::GetDeviceContextForScreenInfo(GetOuter());
     114             : }
     115             : 
     116             : nsresult
     117           6 : nsScreen::GetRect(nsRect& aRect)
     118             : {
     119             :   // Return window inner rect to prevent fingerprinting.
     120           6 :   if (ShouldResistFingerprinting()) {
     121           0 :     return GetWindowInnerRect(aRect);
     122             :   }
     123             : 
     124           6 :   nsDeviceContext *context = GetDeviceContext();
     125             : 
     126           6 :   if (!context) {
     127           0 :     return NS_ERROR_FAILURE;
     128             :   }
     129             : 
     130           6 :   context->GetRect(aRect);
     131             :   LayoutDevicePoint screenTopLeftDev =
     132          12 :     LayoutDevicePixel::FromAppUnits(aRect.TopLeft(),
     133          12 :                                     context->AppUnitsPerDevPixel());
     134             :   DesktopPoint screenTopLeftDesk =
     135           6 :     screenTopLeftDev / context->GetDesktopToDeviceScale();
     136             : 
     137           6 :   aRect.x = NSToIntRound(screenTopLeftDesk.x);
     138           6 :   aRect.y = NSToIntRound(screenTopLeftDesk.y);
     139             : 
     140           6 :   aRect.height = nsPresContext::AppUnitsToIntCSSPixels(aRect.height);
     141           6 :   aRect.width = nsPresContext::AppUnitsToIntCSSPixels(aRect.width);
     142             : 
     143           6 :   return NS_OK;
     144             : }
     145             : 
     146             : nsresult
     147           4 : nsScreen::GetAvailRect(nsRect& aRect)
     148             : {
     149             :   // Return window inner rect to prevent fingerprinting.
     150           4 :   if (ShouldResistFingerprinting()) {
     151           0 :     return GetWindowInnerRect(aRect);
     152             :   }
     153             : 
     154           4 :   nsDeviceContext *context = GetDeviceContext();
     155             : 
     156           4 :   if (!context) {
     157           0 :     return NS_ERROR_FAILURE;
     158             :   }
     159             : 
     160           8 :   nsRect r;
     161           4 :   context->GetRect(r);
     162             :   LayoutDevicePoint screenTopLeftDev =
     163           8 :     LayoutDevicePixel::FromAppUnits(r.TopLeft(),
     164           8 :                                     context->AppUnitsPerDevPixel());
     165             :   DesktopPoint screenTopLeftDesk =
     166           4 :     screenTopLeftDev / context->GetDesktopToDeviceScale();
     167             : 
     168           4 :   context->GetClientRect(aRect);
     169             : 
     170           8 :   aRect.x = NSToIntRound(screenTopLeftDesk.x) +
     171           4 :             nsPresContext::AppUnitsToIntCSSPixels(aRect.x - r.x);
     172           8 :   aRect.y = NSToIntRound(screenTopLeftDesk.y) +
     173           4 :             nsPresContext::AppUnitsToIntCSSPixels(aRect.y - r.y);
     174             : 
     175           4 :   aRect.height = nsPresContext::AppUnitsToIntCSSPixels(aRect.height);
     176           4 :   aRect.width = nsPresContext::AppUnitsToIntCSSPixels(aRect.width);
     177             : 
     178           4 :   return NS_OK;
     179             : }
     180             : 
     181             : mozilla::dom::ScreenOrientation*
     182           0 : nsScreen::Orientation() const
     183             : {
     184           0 :   return mScreenOrientation;
     185             : }
     186             : 
     187             : void
     188           0 : nsScreen::GetMozOrientation(nsString& aOrientation,
     189             :                             CallerType aCallerType) const
     190             : {
     191           0 :   switch (mScreenOrientation->DeviceType(aCallerType)) {
     192             :   case OrientationType::Portrait_primary:
     193           0 :     aOrientation.AssignLiteral("portrait-primary");
     194           0 :     break;
     195             :   case OrientationType::Portrait_secondary:
     196           0 :     aOrientation.AssignLiteral("portrait-secondary");
     197           0 :     break;
     198             :   case OrientationType::Landscape_primary:
     199           0 :     aOrientation.AssignLiteral("landscape-primary");
     200           0 :     break;
     201             :   case OrientationType::Landscape_secondary:
     202           0 :     aOrientation.AssignLiteral("landscape-secondary");
     203           0 :     break;
     204             :   default:
     205           0 :     MOZ_CRASH("Unacceptable screen orientation type.");
     206             :   }
     207           0 : }
     208             : 
     209             : static void
     210           0 : UpdateDocShellOrientationLock(nsPIDOMWindowInner* aWindow,
     211             :                               ScreenOrientationInternal aOrientation)
     212             : {
     213           0 :   if (!aWindow) {
     214           0 :     return;
     215             :   }
     216             : 
     217           0 :   nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
     218           0 :   if (!docShell) {
     219           0 :     return;
     220             :   }
     221             : 
     222           0 :   nsCOMPtr<nsIDocShellTreeItem> root;
     223           0 :   docShell->GetSameTypeRootTreeItem(getter_AddRefs(root));
     224           0 :   nsCOMPtr<nsIDocShell> rootShell(do_QueryInterface(root));
     225           0 :   if (!rootShell) {
     226           0 :     return;
     227             :   }
     228             : 
     229           0 :   rootShell->SetOrientationLock(aOrientation);
     230             : }
     231             : 
     232             : bool
     233           0 : nsScreen::MozLockOrientation(const nsAString& aOrientation, ErrorResult& aRv)
     234             : {
     235           0 :   nsString orientation(aOrientation);
     236           0 :   Sequence<nsString> orientations;
     237           0 :   if (!orientations.AppendElement(orientation, fallible)) {
     238           0 :     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     239           0 :     return false;
     240             :   }
     241           0 :   return MozLockOrientation(orientations, aRv);
     242             : }
     243             : 
     244             : bool
     245           0 : nsScreen::MozLockOrientation(const Sequence<nsString>& aOrientations,
     246             :                              ErrorResult& aRv)
     247             : {
     248           0 :   if (ShouldResistFingerprinting()) {
     249           0 :     return false;
     250             :   }
     251           0 :   ScreenOrientationInternal orientation = eScreenOrientation_None;
     252             : 
     253           0 :   for (uint32_t i = 0; i < aOrientations.Length(); ++i) {
     254           0 :     const nsString& item = aOrientations[i];
     255             : 
     256           0 :     if (item.EqualsLiteral("portrait")) {
     257           0 :       orientation |= eScreenOrientation_PortraitPrimary |
     258             :                      eScreenOrientation_PortraitSecondary;
     259           0 :     } else if (item.EqualsLiteral("portrait-primary")) {
     260           0 :       orientation |= eScreenOrientation_PortraitPrimary;
     261           0 :     } else if (item.EqualsLiteral("portrait-secondary")) {
     262           0 :       orientation |= eScreenOrientation_PortraitSecondary;
     263           0 :     } else if (item.EqualsLiteral("landscape")) {
     264           0 :       orientation |= eScreenOrientation_LandscapePrimary |
     265             :                      eScreenOrientation_LandscapeSecondary;
     266           0 :     } else if (item.EqualsLiteral("landscape-primary")) {
     267           0 :       orientation |= eScreenOrientation_LandscapePrimary;
     268           0 :     } else if (item.EqualsLiteral("landscape-secondary")) {
     269           0 :       orientation |= eScreenOrientation_LandscapeSecondary;
     270           0 :     } else if (item.EqualsLiteral("default")) {
     271           0 :       orientation |= eScreenOrientation_Default;
     272             :     } else {
     273             :       // If we don't recognize the token, we should just return 'false'
     274             :       // without throwing.
     275           0 :       return false;
     276             :     }
     277             :   }
     278             : 
     279           0 :   switch (mScreenOrientation->GetLockOrientationPermission(false)) {
     280             :     case ScreenOrientation::LOCK_DENIED:
     281           0 :       return false;
     282             :     case ScreenOrientation::LOCK_ALLOWED:
     283           0 :       UpdateDocShellOrientationLock(GetOwner(), orientation);
     284           0 :       return mScreenOrientation->LockDeviceOrientation(orientation, false, aRv);
     285             :     case ScreenOrientation::FULLSCREEN_LOCK_ALLOWED:
     286           0 :       UpdateDocShellOrientationLock(GetOwner(), orientation);
     287           0 :       return mScreenOrientation->LockDeviceOrientation(orientation, true, aRv);
     288             :   }
     289             : 
     290             :   // This is only for compilers that don't understand that the previous switch
     291             :   // will always return.
     292           0 :   MOZ_CRASH("unexpected lock orientation permission value");
     293             : }
     294             : 
     295             : void
     296           0 : nsScreen::MozUnlockOrientation()
     297             : {
     298           0 :   if (ShouldResistFingerprinting()) {
     299           0 :     return;
     300             :   }
     301           0 :   UpdateDocShellOrientationLock(GetOwner(), eScreenOrientation_None);
     302           0 :   mScreenOrientation->UnlockDeviceOrientation();
     303             : }
     304             : 
     305             : bool
     306           6 : nsScreen::IsDeviceSizePageSize()
     307             : {
     308           6 :   if (nsPIDOMWindowInner* owner = GetOwner()) {
     309           6 :     nsIDocShell* docShell = owner->GetDocShell();
     310           6 :     if (docShell) {
     311           6 :       return docShell->GetDeviceSizeIsPageSize();
     312             :     }
     313             :   }
     314           0 :   return false;
     315             : }
     316             : 
     317             : /* virtual */
     318             : JSObject*
     319           1 : nsScreen::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     320             : {
     321           1 :   return ScreenBinding::Wrap(aCx, this, aGivenProto);
     322             : }
     323             : 
     324             : nsresult
     325           0 : nsScreen::GetWindowInnerRect(nsRect& aRect)
     326             : {
     327           0 :   aRect.x = 0;
     328           0 :   aRect.y = 0;
     329           0 :   nsCOMPtr<nsPIDOMWindowInner> win = GetOwner();
     330           0 :   if (!win) {
     331           0 :     return NS_ERROR_FAILURE;
     332             :   }
     333           0 :   nsresult rv = win->GetInnerWidth(&aRect.width);
     334           0 :   NS_ENSURE_SUCCESS(rv, rv);
     335           0 :   return win->GetInnerHeight(&aRect.height);
     336             : }
     337             : 
     338          10 : bool nsScreen::ShouldResistFingerprinting() const
     339             : {
     340          10 :   bool resist = false;
     341          20 :   nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
     342          10 :   if (owner) {
     343          10 :     resist = nsContentUtils::ShouldResistFingerprinting(owner->GetDocShell());
     344             :   }
     345          20 :   return resist;
     346             : }

Generated by: LCOV version 1.13