dom/base/nsScreen.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "mozilla/Hal.h"
     7 #include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
     8 #include "mozilla/dom/ScreenBinding.h"
     9 #include "nsScreen.h"
    10 #include "nsIDocument.h"
    11 #include "nsIDocShell.h"
    12 #include "nsIDocument.h"
    13 #include "nsPresContext.h"
    14 #include "nsCOMPtr.h"
    15 #include "nsIDocShellTreeItem.h"
    16 #include "nsLayoutUtils.h"
    17 #include "nsJSUtils.h"
    18 #include "nsDeviceContext.h"
    20 using namespace mozilla;
    21 using namespace mozilla::dom;
    23 /* static */ already_AddRefed<nsScreen>
    24 nsScreen::Create(nsPIDOMWindow* aWindow)
    25 {
    26   MOZ_ASSERT(aWindow);
    28   if (!aWindow->GetDocShell()) {
    29     return nullptr;
    30   }
    32   nsCOMPtr<nsIScriptGlobalObject> sgo =
    33     do_QueryInterface(static_cast<nsPIDOMWindow*>(aWindow));
    34   NS_ENSURE_TRUE(sgo, nullptr);
    36   nsRefPtr<nsScreen> screen = new nsScreen(aWindow);
    38   hal::RegisterScreenConfigurationObserver(screen);
    39   hal::ScreenConfiguration config;
    40   hal::GetCurrentScreenConfiguration(&config);
    41   screen->mOrientation = config.orientation();
    43   return screen.forget();
    44 }
    46 nsScreen::nsScreen(nsPIDOMWindow* aWindow)
    47   : DOMEventTargetHelper(aWindow)
    48   , mEventListener(nullptr)
    49 {
    50 }
    52 nsScreen::~nsScreen()
    53 {
    54   MOZ_ASSERT(!mEventListener);
    55   hal::UnregisterScreenConfigurationObserver(this);
    56 }
    59 // QueryInterface implementation for nsScreen
    60 NS_INTERFACE_MAP_BEGIN(nsScreen)
    61   NS_INTERFACE_MAP_ENTRY(nsIDOMScreen)
    62 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
    64 NS_IMPL_ADDREF_INHERITED(nsScreen, DOMEventTargetHelper)
    65 NS_IMPL_RELEASE_INHERITED(nsScreen, DOMEventTargetHelper)
    67 int32_t
    68 nsScreen::GetPixelDepth(ErrorResult& aRv)
    69 {
    70   // For non-chrome callers, always return 24 to prevent fingerprinting.
    71   if (!IsChrome()) return 24;
    73   nsDeviceContext* context = GetDeviceContext();
    75   if (!context) {
    76     aRv.Throw(NS_ERROR_FAILURE);
    77     return -1;
    78   }
    80   uint32_t depth;
    81   context->GetDepth(depth);
    82   return depth;
    83 }
    85 #define FORWARD_LONG_GETTER(_name)                                              \
    86   NS_IMETHODIMP                                                                 \
    87   nsScreen::Get ## _name(int32_t* aOut)                                         \
    88   {                                                                             \
    89     ErrorResult rv;                                                             \
    90     *aOut = Get ## _name(rv);                                                   \
    91     return rv.ErrorCode();                                                      \
    92   }
    94 FORWARD_LONG_GETTER(AvailWidth)
    95 FORWARD_LONG_GETTER(AvailHeight)
    96 FORWARD_LONG_GETTER(Width)
    97 FORWARD_LONG_GETTER(Height)
    99 FORWARD_LONG_GETTER(Top)
   100 FORWARD_LONG_GETTER(Left)
   101 FORWARD_LONG_GETTER(AvailTop)
   102 FORWARD_LONG_GETTER(AvailLeft)
   104 FORWARD_LONG_GETTER(PixelDepth)
   105 FORWARD_LONG_GETTER(ColorDepth)
   107 nsDeviceContext*
   108 nsScreen::GetDeviceContext()
   109 {
   110   return nsLayoutUtils::GetDeviceContextForScreenInfo(GetOwner());
   111 }
   113 nsresult
   114 nsScreen::GetRect(nsRect& aRect)
   115 {
   116   // For non-chrome callers, return window inner rect to prevent fingerprinting.
   117   if (!IsChrome()) return GetWindowInnerRect(aRect);
   119   nsDeviceContext *context = GetDeviceContext();
   121   if (!context) {
   122     return NS_ERROR_FAILURE;
   123   }
   125   context->GetRect(aRect);
   127   aRect.x = nsPresContext::AppUnitsToIntCSSPixels(aRect.x);
   128   aRect.y = nsPresContext::AppUnitsToIntCSSPixels(aRect.y);
   129   aRect.height = nsPresContext::AppUnitsToIntCSSPixels(aRect.height);
   130   aRect.width = nsPresContext::AppUnitsToIntCSSPixels(aRect.width);
   132   return NS_OK;
   133 }
   135 nsresult
   136 nsScreen::GetAvailRect(nsRect& aRect)
   137 {
   138   // For non-chrome callers, return window inner rect to prevent fingerprinting.
   139   if (!IsChrome()) return GetWindowInnerRect(aRect);
   141   nsDeviceContext *context = GetDeviceContext();
   143   if (!context) {
   144     return NS_ERROR_FAILURE;
   145   }
   147   context->GetClientRect(aRect);
   149   aRect.x = nsPresContext::AppUnitsToIntCSSPixels(aRect.x);
   150   aRect.y = nsPresContext::AppUnitsToIntCSSPixels(aRect.y);
   151   aRect.height = nsPresContext::AppUnitsToIntCSSPixels(aRect.height);
   152   aRect.width = nsPresContext::AppUnitsToIntCSSPixels(aRect.width);
   154   return NS_OK;
   155 }
   157 void
   158 nsScreen::Notify(const hal::ScreenConfiguration& aConfiguration)
   159 {
   160   ScreenOrientation previousOrientation = mOrientation;
   161   mOrientation = aConfiguration.orientation();
   163   NS_ASSERTION(mOrientation == eScreenOrientation_PortraitPrimary ||
   164                mOrientation == eScreenOrientation_PortraitSecondary ||
   165                mOrientation == eScreenOrientation_LandscapePrimary ||
   166                mOrientation == eScreenOrientation_LandscapeSecondary,
   167                "Invalid orientation value passed to notify method!");
   169   if (mOrientation != previousOrientation) {
   170     DispatchTrustedEvent(NS_LITERAL_STRING("mozorientationchange"));
   171   }
   172 }
   174 void
   175 nsScreen::GetMozOrientation(nsString& aOrientation)
   176 {
   177   if (!IsChrome()) {
   178     aOrientation.AssignLiteral("landscape-primary");
   179   } else {
   180     switch (mOrientation) {
   181     case eScreenOrientation_PortraitPrimary:
   182       aOrientation.AssignLiteral("portrait-primary");
   183       break;
   184     case eScreenOrientation_PortraitSecondary:
   185       aOrientation.AssignLiteral("portrait-secondary");
   186       break;
   187     case eScreenOrientation_LandscapePrimary:
   188       aOrientation.AssignLiteral("landscape-primary");
   189       break;
   190     case eScreenOrientation_LandscapeSecondary:
   191       aOrientation.AssignLiteral("landscape-secondary");
   192       break;
   193     case eScreenOrientation_None:
   194     default:
   195       MOZ_CRASH("Unacceptable mOrientation value");
   196     }
   197   }
   198 }
   200 NS_IMETHODIMP
   201 nsScreen::GetSlowMozOrientation(nsAString& aOrientation)
   202 {
   203   nsString orientation;
   204   GetMozOrientation(orientation);
   205   aOrientation = orientation;
   206   return NS_OK;
   207 }
   209 nsScreen::LockPermission
   210 nsScreen::GetLockOrientationPermission() const
   211 {
   212   nsCOMPtr<nsPIDOMWindow> owner = GetOwner();
   213   if (!owner) {
   214     return LOCK_DENIED;
   215   }
   217   // Chrome can always lock the screen orientation.
   218   nsIDocShell* docShell = owner->GetDocShell();
   219   if (docShell && docShell->ItemType() == nsIDocShellTreeItem::typeChrome) {
   220     return LOCK_ALLOWED;
   221   }
   223   nsCOMPtr<nsIDocument> doc = owner->GetDoc();
   224   if (!doc || doc->Hidden()) {
   225     return LOCK_DENIED;
   226   }
   228   // Apps can always lock the screen orientation.
   229   if (doc->NodePrincipal()->GetAppStatus() >=
   230         nsIPrincipal::APP_STATUS_INSTALLED) {
   231     return LOCK_ALLOWED;
   232   }
   234   // Other content must be full-screen in order to lock orientation.
   235   return doc->MozFullScreen() ? FULLSCREEN_LOCK_ALLOWED : LOCK_DENIED;
   236 }
   238 bool
   239 nsScreen::MozLockOrientation(const nsAString& aOrientation, ErrorResult& aRv)
   240 {
   241   nsString orientation(aOrientation);
   242   Sequence<nsString> orientations;
   243   if (!orientations.AppendElement(orientation)) {
   244     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
   245     return false;
   246   }
   247   return MozLockOrientation(orientations, aRv);
   248 }
   250 bool
   251 nsScreen::MozLockOrientation(const Sequence<nsString>& aOrientations,
   252                              ErrorResult& aRv)
   253 {
   254   ScreenOrientation orientation = eScreenOrientation_None;
   256   for (uint32_t i = 0; i < aOrientations.Length(); ++i) {
   257     const nsString& item = aOrientations[i];
   259     if (item.EqualsLiteral("portrait")) {
   260       orientation |= eScreenOrientation_PortraitPrimary |
   261                      eScreenOrientation_PortraitSecondary;
   262     } else if (item.EqualsLiteral("portrait-primary")) {
   263       orientation |= eScreenOrientation_PortraitPrimary;
   264     } else if (item.EqualsLiteral("portrait-secondary")) {
   265       orientation |= eScreenOrientation_PortraitSecondary;
   266     } else if (item.EqualsLiteral("landscape")) {
   267       orientation |= eScreenOrientation_LandscapePrimary |
   268                      eScreenOrientation_LandscapeSecondary;
   269     } else if (item.EqualsLiteral("landscape-primary")) {
   270       orientation |= eScreenOrientation_LandscapePrimary;
   271     } else if (item.EqualsLiteral("landscape-secondary")) {
   272       orientation |= eScreenOrientation_LandscapeSecondary;
   273     } else if (item.EqualsLiteral("default")) {
   274       orientation |= eScreenOrientation_Default;
   275     } else {
   276       // If we don't recognize the token, we should just return 'false'
   277       // without throwing.
   278       return false;
   279     }
   280   }
   282   switch (GetLockOrientationPermission()) {
   283     case LOCK_DENIED:
   284       return false;
   285     case LOCK_ALLOWED:
   286       return hal::LockScreenOrientation(orientation);
   287     case FULLSCREEN_LOCK_ALLOWED: {
   288       // We need to register a listener so we learn when we leave full-screen
   289       // and when we will have to unlock the screen.
   290       // This needs to be done before LockScreenOrientation call to make sure
   291       // the locking can be unlocked.
   292       nsCOMPtr<EventTarget> target = do_QueryInterface(GetOwner()->GetDoc());
   293       if (!target) {
   294         return false;
   295       }
   297       if (!hal::LockScreenOrientation(orientation)) {
   298         return false;
   299       }
   301       // We are fullscreen and lock has been accepted.
   302       if (!mEventListener) {
   303         mEventListener = new FullScreenEventListener();
   304       }
   306       aRv = target->AddSystemEventListener(NS_LITERAL_STRING("mozfullscreenchange"),
   307                                            mEventListener, /* useCapture = */ true);
   308       return true;
   309     }
   310   }
   312   // This is only for compilers that don't understand that the previous switch
   313   // will always return.
   314   MOZ_CRASH("unexpected lock orientation permission value");
   315 }
   317 void
   318 nsScreen::MozUnlockOrientation()
   319 {
   320   hal::UnlockScreenOrientation();
   321 }
   323 bool
   324 nsScreen::IsDeviceSizePageSize()
   325 {
   326   nsPIDOMWindow* owner = GetOwner();
   327   if (owner) {
   328     nsIDocShell* docShell = owner->GetDocShell();
   329     if (docShell) {
   330       return docShell->GetDeviceSizeIsPageSize();
   331     }
   332   }
   333   return false;
   334 }
   336 /* virtual */
   337 JSObject*
   338 nsScreen::WrapObject(JSContext* aCx)
   339 {
   340   return ScreenBinding::Wrap(aCx, this);
   341 }
   343 NS_IMPL_ISUPPORTS(nsScreen::FullScreenEventListener, nsIDOMEventListener)
   345 NS_IMETHODIMP
   346 nsScreen::FullScreenEventListener::HandleEvent(nsIDOMEvent* aEvent)
   347 {
   348 #ifdef DEBUG
   349   nsAutoString eventType;
   350   aEvent->GetType(eventType);
   352   MOZ_ASSERT(eventType.EqualsLiteral("mozfullscreenchange"));
   353 #endif
   355   nsCOMPtr<EventTarget> target = aEvent->InternalDOMEvent()->GetCurrentTarget();
   356   MOZ_ASSERT(target);
   358   nsCOMPtr<nsIDocument> doc = do_QueryInterface(target);
   359   MOZ_ASSERT(doc);
   361   // We have to make sure that the event we got is the event sent when
   362   // fullscreen is disabled because we could get one when fullscreen
   363   // got enabled if the lock call is done at the same moment.
   364   if (doc->MozFullScreen()) {
   365     return NS_OK;
   366   }
   368   target->RemoveSystemEventListener(NS_LITERAL_STRING("mozfullscreenchange"),
   369                                     this, true);
   371   hal::UnlockScreenOrientation();
   373   return NS_OK;
   374 }
   376 bool
   377 nsScreen::IsChrome()
   378 {
   379   nsCOMPtr<nsPIDOMWindow> owner = GetOwner();
   380   if (owner && owner->GetDocShell()) {
   381     return owner->GetDocShell()->ItemType() == nsIDocShellTreeItem::typeChrome;
   382   }
   383   return false;
   384 }
   386 nsresult
   387 nsScreen::GetDOMWindow(nsIDOMWindow **aResult)
   388 {
   389   NS_ENSURE_ARG_POINTER(aResult);
   390   *aResult = NULL;
   392   nsCOMPtr<nsPIDOMWindow> owner = GetOwner();
   393   if (!owner)
   394     return NS_ERROR_FAILURE;
   396   nsCOMPtr<nsIDOMWindow> win = do_QueryInterface(owner);
   397   NS_ENSURE_STATE(win);
   398   win.swap(*aResult);
   400   return NS_OK;
   401 }
   403 nsresult
   404 nsScreen::GetWindowInnerRect(nsRect& aRect)
   405 {
   406   aRect.x = 0;
   407   aRect.y = 0;
   408   nsCOMPtr<nsIDOMWindow> win;
   409   nsresult rv = GetDOMWindow(getter_AddRefs(win));
   410   NS_ENSURE_SUCCESS(rv, rv);
   411   rv = win->GetInnerWidth(&aRect.width);
   412   NS_ENSURE_SUCCESS(rv, rv);
   413   return win->GetInnerHeight(&aRect.height);
   414 }

mercurial