dom/base/nsScreen.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial