gecko-dev/dom/base/nsScreen.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

332 строки
10 KiB
C++
Исходник Обычный вид История

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
2012-05-21 15:12:37 +04:00
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Bug 1278816 - Move Performance API into dom/performance, r=smaug --HG-- rename : dom/base/PerformanceEntry.cpp => dom/performance/PerformanceEntry.cpp rename : dom/base/PerformanceEntry.h => dom/performance/PerformanceEntry.h rename : dom/base/PerformanceMark.cpp => dom/performance/PerformanceMark.cpp rename : dom/base/PerformanceMark.h => dom/performance/PerformanceMark.h rename : dom/base/PerformanceMeasure.cpp => dom/performance/PerformanceMeasure.cpp rename : dom/base/PerformanceMeasure.h => dom/performance/PerformanceMeasure.h rename : dom/base/PerformanceObserver.cpp => dom/performance/PerformanceObserver.cpp rename : dom/base/PerformanceObserver.h => dom/performance/PerformanceObserver.h rename : dom/base/PerformanceObserverEntryList.cpp => dom/performance/PerformanceObserverEntryList.cpp rename : dom/base/PerformanceObserverEntryList.h => dom/performance/PerformanceObserverEntryList.h rename : dom/base/PerformanceResourceTiming.cpp => dom/performance/PerformanceResourceTiming.cpp rename : dom/base/PerformanceResourceTiming.h => dom/performance/PerformanceResourceTiming.h rename : dom/base/nsPerformance.cpp => dom/performance/nsPerformance.cpp rename : dom/base/nsPerformance.h => dom/performance/nsPerformance.h rename : dom/base/test/performance_observer.html => dom/performance/tests/performance_observer.html rename : dom/base/test/test_performance_observer.html => dom/performance/tests/test_performance_observer.html rename : dom/base/test/test_performance_observer.js => dom/performance/tests/test_performance_observer.js rename : dom/base/test/test_performance_user_timing.html => dom/performance/tests/test_performance_user_timing.html rename : dom/base/test/test_performance_user_timing.js => dom/performance/tests/test_performance_user_timing.js
2016-06-09 13:42:21 +03:00
#include "nsContentUtils.h"
#include "nsScreen.h"
#include "mozilla/dom/Document.h"
#include "nsIDocShell.h"
#include "mozilla/dom/Document.h"
#include "nsPresContext.h"
#include "nsCOMPtr.h"
#include "nsIDocShellTreeItem.h"
#include "nsLayoutUtils.h"
#include "nsJSUtils.h"
#include "nsDeviceContext.h"
using namespace mozilla;
using namespace mozilla::dom;
/* static */
already_AddRefed<nsScreen> nsScreen::Create(nsPIDOMWindowInner* aWindow) {
MOZ_ASSERT(aWindow);
if (!aWindow->GetDocShell()) {
return nullptr;
}
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aWindow);
NS_ENSURE_TRUE(sgo, nullptr);
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 08:24:48 +03:00
RefPtr<nsScreen> screen = new nsScreen(aWindow);
return screen.forget();
}
nsScreen::nsScreen(nsPIDOMWindowInner* aWindow)
: DOMEventTargetHelper(aWindow),
mScreenOrientation(new ScreenOrientation(aWindow, this)) {}
nsScreen::~nsScreen() {}
// QueryInterface implementation for nsScreen
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsScreen)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(nsScreen, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(nsScreen, DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_INHERITED(nsScreen, DOMEventTargetHelper,
mScreenOrientation)
int32_t nsScreen::GetPixelDepth(ErrorResult& aRv) {
// Return 24 to prevent fingerprinting.
if (ShouldResistFingerprinting()) {
return 24;
}
nsDeviceContext* context = GetDeviceContext();
if (!context) {
aRv.Throw(NS_ERROR_FAILURE);
return -1;
}
uint32_t depth;
context->GetDepth(depth);
return depth;
}
nsPIDOMWindowOuter* nsScreen::GetOuter() const {
if (nsPIDOMWindowInner* inner = GetOwner()) {
return inner->GetOuterWindow();
}
return nullptr;
}
nsDeviceContext* nsScreen::GetDeviceContext() {
return nsLayoutUtils::GetDeviceContextForScreenInfo(GetOuter());
}
nsresult nsScreen::GetRect(nsRect& aRect) {
// Return window inner rect to prevent fingerprinting.
if (ShouldResistFingerprinting()) {
return GetWindowInnerRect(aRect);
}
nsDeviceContext* context = GetDeviceContext();
if (!context) {
return NS_ERROR_FAILURE;
}
context->GetRect(aRect);
LayoutDevicePoint screenTopLeftDev = LayoutDevicePixel::FromAppUnits(
aRect.TopLeft(), context->AppUnitsPerDevPixel());
DesktopPoint screenTopLeftDesk =
screenTopLeftDev / context->GetDesktopToDeviceScale();
aRect.x = NSToIntRound(screenTopLeftDesk.x);
aRect.y = NSToIntRound(screenTopLeftDesk.y);
aRect.SetHeight(nsPresContext::AppUnitsToIntCSSPixels(aRect.Height()));
aRect.SetWidth(nsPresContext::AppUnitsToIntCSSPixels(aRect.Width()));
return NS_OK;
}
nsresult nsScreen::GetAvailRect(nsRect& aRect) {
// Return window inner rect to prevent fingerprinting.
if (ShouldResistFingerprinting()) {
return GetWindowInnerRect(aRect);
}
// Here we manipulate the value of aRect to represent the screen avail size,
// if in RDM.
if (IsInRDMPane()) {
return GetRDMScreenSize(aRect);
}
nsDeviceContext* context = GetDeviceContext();
if (!context) {
return NS_ERROR_FAILURE;
}
nsRect r;
context->GetRect(r);
LayoutDevicePoint screenTopLeftDev = LayoutDevicePixel::FromAppUnits(
r.TopLeft(), context->AppUnitsPerDevPixel());
DesktopPoint screenTopLeftDesk =
screenTopLeftDev / context->GetDesktopToDeviceScale();
context->GetClientRect(aRect);
aRect.x = NSToIntRound(screenTopLeftDesk.x) +
nsPresContext::AppUnitsToIntCSSPixels(aRect.x - r.x);
aRect.y = NSToIntRound(screenTopLeftDesk.y) +
nsPresContext::AppUnitsToIntCSSPixels(aRect.y - r.y);
aRect.SetHeight(nsPresContext::AppUnitsToIntCSSPixels(aRect.Height()));
aRect.SetWidth(nsPresContext::AppUnitsToIntCSSPixels(aRect.Width()));
return NS_OK;
}
nsresult nsScreen::GetRDMScreenSize(nsRect& aRect) {
GetWindowInnerRect(aRect);
// GetOwner(), GetDocShell(), and GetPresContext() can potentially return
// nullptr, so to be safe let's make sure we check these before proceeding.
nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
if (owner) {
nsIDocShell* docShell = owner->GetDocShell();
if (docShell) {
RefPtr<nsPresContext> presContext = docShell->GetPresContext();
if (presContext) {
float zoom = presContext->GetDeviceFullZoom();
int32_t width = std::round(aRect.Width() * zoom);
int32_t height = std::round(aRect.Height() * zoom);
aRect.SetHeight(height);
aRect.SetWidth(width);
return NS_OK;
}
}
}
return NS_ERROR_FAILURE;
}
mozilla::dom::ScreenOrientation* nsScreen::Orientation() const {
return mScreenOrientation;
}
void nsScreen::GetMozOrientation(nsString& aOrientation,
CallerType aCallerType) const {
switch (mScreenOrientation->DeviceType(aCallerType)) {
case OrientationType::Portrait_primary:
aOrientation.AssignLiteral("portrait-primary");
break;
case OrientationType::Portrait_secondary:
aOrientation.AssignLiteral("portrait-secondary");
break;
case OrientationType::Landscape_primary:
aOrientation.AssignLiteral("landscape-primary");
break;
case OrientationType::Landscape_secondary:
aOrientation.AssignLiteral("landscape-secondary");
break;
default:
MOZ_CRASH("Unacceptable screen orientation type.");
}
}
static void UpdateDocShellOrientationLock(nsPIDOMWindowInner* aWindow,
hal::ScreenOrientation aOrientation) {
if (!aWindow) {
return;
}
nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
if (!docShell) {
return;
}
nsCOMPtr<nsIDocShellTreeItem> root;
docShell->GetInProcessSameTypeRootTreeItem(getter_AddRefs(root));
nsCOMPtr<nsIDocShell> rootShell(do_QueryInterface(root));
if (!rootShell) {
return;
}
rootShell->SetOrientationLock(aOrientation);
}
bool nsScreen::MozLockOrientation(const nsAString& aOrientation,
ErrorResult& aRv) {
nsString orientation(aOrientation);
Sequence<nsString> orientations;
if (!orientations.AppendElement(orientation, fallible)) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return false;
}
return MozLockOrientation(orientations, aRv);
}
bool nsScreen::MozLockOrientation(const Sequence<nsString>& aOrientations,
ErrorResult& aRv) {
if (ShouldResistFingerprinting()) {
return false;
}
hal::ScreenOrientation orientation = hal::eScreenOrientation_None;
for (uint32_t i = 0; i < aOrientations.Length(); ++i) {
const nsString& item = aOrientations[i];
if (item.EqualsLiteral("portrait")) {
orientation |= hal::eScreenOrientation_PortraitPrimary |
hal::eScreenOrientation_PortraitSecondary;
} else if (item.EqualsLiteral("portrait-primary")) {
orientation |= hal::eScreenOrientation_PortraitPrimary;
} else if (item.EqualsLiteral("portrait-secondary")) {
orientation |= hal::eScreenOrientation_PortraitSecondary;
} else if (item.EqualsLiteral("landscape")) {
orientation |= hal::eScreenOrientation_LandscapePrimary |
hal::eScreenOrientation_LandscapeSecondary;
} else if (item.EqualsLiteral("landscape-primary")) {
orientation |= hal::eScreenOrientation_LandscapePrimary;
} else if (item.EqualsLiteral("landscape-secondary")) {
orientation |= hal::eScreenOrientation_LandscapeSecondary;
} else if (item.EqualsLiteral("default")) {
orientation |= hal::eScreenOrientation_Default;
} else {
// If we don't recognize the token, we should just return 'false'
// without throwing.
return false;
}
}
switch (mScreenOrientation->GetLockOrientationPermission(false)) {
case ScreenOrientation::LOCK_DENIED:
return false;
case ScreenOrientation::LOCK_ALLOWED:
UpdateDocShellOrientationLock(GetOwner(), orientation);
return mScreenOrientation->LockDeviceOrientation(orientation, false, aRv);
case ScreenOrientation::FULLSCREEN_LOCK_ALLOWED:
UpdateDocShellOrientationLock(GetOwner(), orientation);
return mScreenOrientation->LockDeviceOrientation(orientation, true, aRv);
}
// This is only for compilers that don't understand that the previous switch
// will always return.
MOZ_CRASH("unexpected lock orientation permission value");
}
void nsScreen::MozUnlockOrientation() {
if (ShouldResistFingerprinting()) {
return;
}
UpdateDocShellOrientationLock(GetOwner(), hal::eScreenOrientation_None);
mScreenOrientation->UnlockDeviceOrientation();
}
bool nsScreen::IsDeviceSizePageSize() {
if (nsPIDOMWindowInner* owner = GetOwner()) {
nsIDocShell* docShell = owner->GetDocShell();
if (docShell) {
return docShell->GetDeviceSizeIsPageSize();
}
}
return false;
}
/* virtual */
Bug 1117172 part 3. Change the wrappercached WrapObject methods to allow passing in aGivenProto. r=peterv The only manual changes here are to BindingUtils.h, BindingUtils.cpp, Codegen.py, Element.cpp, IDBFileRequest.cpp, IDBObjectStore.cpp, dom/workers/Navigator.cpp, WorkerPrivate.cpp, DeviceStorageRequestChild.cpp, Notification.cpp, nsGlobalWindow.cpp, MessagePort.cpp, nsJSEnvironment.cpp, Sandbox.cpp, XPCConvert.cpp, ExportHelpers.cpp, and DataStoreService.cpp. The rest of this diff was generated by running the following commands: find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g' find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g' find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g' find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g' find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObject\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g' find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(Binding(?:_workers)?::Wrap\((?:aCx|cx|aContext|aCtx|js), [^,)]+)\)/\1, aGivenProto)/g'
2015-03-19 17:13:33 +03:00
JSObject* nsScreen::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
return Screen_Binding::Wrap(aCx, this, aGivenProto);
}
nsresult nsScreen::GetWindowInnerRect(nsRect& aRect) {
aRect.x = 0;
aRect.y = 0;
nsCOMPtr<nsPIDOMWindowInner> win = GetOwner();
if (!win) {
return NS_ERROR_FAILURE;
}
nsresult rv = win->GetInnerWidth(&aRect.width);
NS_ENSURE_SUCCESS(rv, rv);
return win->GetInnerHeight(&aRect.height);
}
bool nsScreen::ShouldResistFingerprinting() const {
bool resist = false;
nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
if (owner) {
resist = nsContentUtils::ShouldResistFingerprinting(owner->GetDocShell());
}
return resist;
}
bool nsScreen::IsInRDMPane() const {
bool isInRDM = false;
nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
if (owner) {
Document* doc = owner->GetExtantDoc();
isInRDM = doc && doc->InRDMPane();
}
return isInRDM;
}