Bug 1002354 - Proxy nsIScreenManager and nsIScreen's from the child process to the parent process, with caching. r=roc,jimm,smichaud,snorp.

Changes to nsIScreen and nsIScreenManager were reviewed by roc.
Changes to dom/ipc were reviewed by jimm.
Changes to gfx/src/nsDeviceContext.cpp were reviewed by roc.
Changes to widget/android were reviewed by snorp.
Changes to widget/cocoa were reviewed by smichaud.
Changes to widget/gtk were reviewed by roc.
Changes to widget/windows were reviewed by jimm.
Changes to widget/xpwidgets were reviewed by roc.

--HG--
extra : rebase_source : 90d263235b40f6f6937d361705a4dfa44253318e
extra : histedit_source : bab4e689269c67fe3eb65033b6987b93caf9a482%2C86645be32f82f0d80724532e528e597db165b1d1
This commit is contained in:
Mike Conley 2014-07-14 11:57:06 -04:00
parent 29d2ce2ffe
commit 78e56ed33a
37 changed files with 1087 additions and 15 deletions

View File

@ -59,6 +59,7 @@
#include "nsIMutable.h"
#include "nsIObserverService.h"
#include "nsIScriptSecurityManager.h"
#include "nsScreenManagerProxy.h"
#include "nsMemoryInfoDumper.h"
#include "nsServiceManagerUtils.h"
#include "nsStyleSheetService.h"
@ -169,6 +170,7 @@ using namespace mozilla::jsipc;
#if defined(MOZ_WIDGET_GONK)
using namespace mozilla::system;
#endif
using namespace mozilla::widget;
#ifdef MOZ_NUWA_PROCESS
static bool sNuwaForking = false;
@ -1200,6 +1202,28 @@ ContentChild::DeallocPNeckoChild(PNeckoChild* necko)
return true;
}
PScreenManagerChild*
ContentChild::AllocPScreenManagerChild(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess)
{
// The ContentParent should never attempt to allocate the
// nsScreenManagerProxy. Instead, the nsScreenManagerProxy
// service is requested and instantiated via XPCOM, and the
// constructor of nsScreenManagerProxy sets up the IPC connection.
NS_NOTREACHED("Should never get here!");
return nullptr;
}
bool
ContentChild::DeallocPScreenManagerChild(PScreenManagerChild* aService)
{
// nsScreenManagerProxy is AddRef'd in its constructor.
nsScreenManagerProxy *child = static_cast<nsScreenManagerProxy*>(aService);
child->Release();
return true;
}
PExternalHelperAppChild*
ContentChild::AllocPExternalHelperAppChild(const OptionalURIParams& uri,
const nsCString& aMimeContentType,

View File

@ -193,6 +193,12 @@ public:
virtual PNeckoChild* AllocPNeckoChild() MOZ_OVERRIDE;
virtual bool DeallocPNeckoChild(PNeckoChild*) MOZ_OVERRIDE;
virtual PScreenManagerChild*
AllocPScreenManagerChild(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool DeallocPScreenManagerChild(PScreenManagerChild*) MOZ_OVERRIDE;
virtual PExternalHelperAppChild *AllocPExternalHelperAppChild(
const OptionalURIParams& uri,
const nsCString& aMimeContentType,

View File

@ -113,6 +113,7 @@
#include "PreallocatedProcessManager.h"
#include "ProcessPriorityManager.h"
#include "SandboxHal.h"
#include "ScreenManagerParent.h"
#include "StructuredCloneUtils.h"
#include "TabParent.h"
#include "URIUtils.h"
@ -189,6 +190,7 @@ using namespace mozilla::ipc;
using namespace mozilla::layers;
using namespace mozilla::net;
using namespace mozilla::jsipc;
using namespace mozilla::widget;
#ifdef ENABLE_TESTS
@ -2903,6 +2905,21 @@ ContentParent::DeallocPNeckoParent(PNeckoParent* necko)
return true;
}
PScreenManagerParent*
ContentParent::AllocPScreenManagerParent(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess)
{
return new ScreenManagerParent(aNumberOfScreens, aSystemDefaultScale, aSuccess);
}
bool
ContentParent::DeallocPScreenManagerParent(PScreenManagerParent* aActor)
{
delete aActor;
return true;
}
PExternalHelperAppParent*
ContentParent::AllocPExternalHelperAppParent(const OptionalURIParams& uri,
const nsCString& aMimeContentType,

View File

@ -230,6 +230,12 @@ public:
return PContentParent::RecvPNeckoConstructor(aActor);
}
virtual PScreenManagerParent*
AllocPScreenManagerParent(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool DeallocPScreenManagerParent(PScreenManagerParent* aActor) MOZ_OVERRIDE;
virtual PHalParent* AllocPHalParent() MOZ_OVERRIDE;
virtual bool RecvPHalConstructor(PHalParent* aActor) MOZ_OVERRIDE {
return PContentParent::RecvPHalConstructor(aActor);

View File

@ -23,6 +23,7 @@ include protocol PImageBridge;
include protocol PIndexedDB;
include protocol PMemoryReportRequest;
include protocol PNecko;
include protocol PScreenManager;
include protocol PSharedBufferManager;
include protocol PSms;
include protocol PSpeechSynthesis;
@ -303,6 +304,7 @@ intr protocol PContent
manages PIndexedDB;
manages PMemoryReportRequest;
manages PNecko;
manages PScreenManager;
manages PSms;
manages PSpeechSynthesis;
manages PStorage;
@ -479,6 +481,11 @@ parent:
PNecko();
sync PScreenManager()
returns (uint32_t numberOfScreens,
float systemDefaultScale,
bool success);
PSms();
PSpeechSynthesis();

View File

@ -0,0 +1,57 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
/* 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/. */
include protocol PBrowser;
include protocol PContent;
using struct nsIntRect from "nsRect.h";
namespace mozilla {
namespace dom {
struct ScreenDetails {
uint32_t id;
nsIntRect rect;
nsIntRect availRect;
int32_t pixelDepth;
int32_t colorDepth;
double contentsScaleFactor;
};
sync protocol PScreenManager
{
manager PContent;
parent:
sync Refresh()
returns (uint32_t numberOfScreens,
float systemDefaultScale,
bool success);
sync ScreenRefresh(uint32_t aId)
returns (ScreenDetails screen,
bool success);
sync GetPrimaryScreen()
returns (ScreenDetails screen,
bool success);
sync ScreenForRect(int32_t aLeft,
int32_t aTop,
int32_t aWidth,
int32_t aHeight)
returns (ScreenDetails screen,
bool success);
sync ScreenForBrowser(PBrowser aBrowser)
returns (ScreenDetails screen,
bool success);
child:
__delete__();
};
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,195 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* 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/. */
#include "mozilla/dom/TabParent.h"
#include "mozilla/unused.h"
#include "nsIWidget.h"
#include "nsServiceManagerUtils.h"
#include "ScreenManagerParent.h"
namespace mozilla {
namespace dom {
static const char *sScreenManagerContractID = "@mozilla.org/gfx/screenmanager;1";
ScreenManagerParent::ScreenManagerParent(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess)
{
mScreenMgr = do_GetService(sScreenManagerContractID);
if (!mScreenMgr) {
MOZ_CRASH("Couldn't get nsIScreenManager from ScreenManagerParent.");
}
unused << RecvRefresh(aNumberOfScreens, aSystemDefaultScale, aSuccess);
}
bool
ScreenManagerParent::RecvRefresh(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess)
{
*aSuccess = false;
nsresult rv = mScreenMgr->GetNumberOfScreens(aNumberOfScreens);
if (NS_FAILED(rv)) {
return true;
}
rv = mScreenMgr->GetSystemDefaultScale(aSystemDefaultScale);
if (NS_FAILED(rv)) {
return true;
}
*aSuccess = true;
return true;
}
bool
ScreenManagerParent::RecvScreenRefresh(const uint32_t& aId,
ScreenDetails* aRetVal,
bool* aSuccess)
{
*aSuccess = false;
nsCOMPtr<nsIScreen> screen;
nsresult rv = mScreenMgr->ScreenForId(aId, getter_AddRefs(screen));
if (NS_FAILED(rv)) {
return true;
}
ScreenDetails details;
unused << ExtractScreenDetails(screen, details);
*aRetVal = details;
*aSuccess = true;
return true;
}
bool
ScreenManagerParent::RecvGetPrimaryScreen(ScreenDetails* aRetVal,
bool* aSuccess)
{
*aSuccess = false;
nsCOMPtr<nsIScreen> screen;
nsresult rv = mScreenMgr->GetPrimaryScreen(getter_AddRefs(screen));
NS_ENSURE_SUCCESS(rv, true);
ScreenDetails details;
if (!ExtractScreenDetails(screen, details)) {
return true;
}
*aRetVal = details;
*aSuccess = true;
return true;
}
bool
ScreenManagerParent::RecvScreenForRect(const int32_t& aLeft,
const int32_t& aTop,
const int32_t& aWidth,
const int32_t& aHeight,
ScreenDetails* aRetVal,
bool* aSuccess)
{
*aSuccess = false;
nsCOMPtr<nsIScreen> screen;
nsresult rv = mScreenMgr->ScreenForRect(aLeft, aTop, aWidth, aHeight, getter_AddRefs(screen));
NS_ENSURE_SUCCESS(rv, true);
ScreenDetails details;
if (!ExtractScreenDetails(screen, details)) {
return true;
}
*aRetVal = details;
*aSuccess = true;
return true;
}
bool
ScreenManagerParent::RecvScreenForBrowser(PBrowserParent* aBrowser,
ScreenDetails* aRetVal,
bool* aSuccess)
{
*aSuccess = false;
// Find the mWidget associated with the tabparent, and then return
// the nsIScreen it's on.
TabParent* tabParent = static_cast<TabParent*>(aBrowser);
nsCOMPtr<nsIWidget> widget = tabParent->GetWidget();
if (!widget) {
return true;
}
nsCOMPtr<nsIScreen> screen;
if (widget->GetNativeData(NS_NATIVE_WINDOW)) {
mScreenMgr->ScreenForNativeWidget(widget->GetNativeData(NS_NATIVE_WINDOW),
getter_AddRefs(screen));
}
NS_ENSURE_TRUE(screen, true);
ScreenDetails details;
if (!ExtractScreenDetails(screen, details)) {
return true;
}
*aRetVal = details;
*aSuccess = true;
return true;
}
bool
ScreenManagerParent::ExtractScreenDetails(nsIScreen* aScreen, ScreenDetails &aDetails)
{
uint32_t id;
nsresult rv = aScreen->GetId(&id);
NS_ENSURE_SUCCESS(rv, false);
aDetails.id() = id;
nsIntRect rect;
rv = aScreen->GetRect(&rect.x, &rect.y, &rect.width, &rect.height);
NS_ENSURE_SUCCESS(rv, false);
aDetails.rect() = rect;
nsIntRect availRect;
rv = aScreen->GetAvailRect(&availRect.x, &availRect.y, &availRect.width,
&availRect.height);
NS_ENSURE_SUCCESS(rv, false);
aDetails.availRect() = availRect;
int32_t pixelDepth = 0;
rv = aScreen->GetPixelDepth(&pixelDepth);
NS_ENSURE_SUCCESS(rv, false);
aDetails.pixelDepth() = pixelDepth;
int32_t colorDepth = 0;
rv = aScreen->GetColorDepth(&colorDepth);
NS_ENSURE_SUCCESS(rv, false);
aDetails.colorDepth() = colorDepth;
double contentsScaleFactor = 1.0;
rv = aScreen->GetContentsScaleFactor(&contentsScaleFactor);
NS_ENSURE_SUCCESS(rv, false);
aDetails.contentsScaleFactor() = contentsScaleFactor;
return true;
}
void
ScreenManagerParent::ActorDestroy(ActorDestroyReason why)
{
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,56 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* 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/. */
#ifndef mozilla_dom_ScreenManagerParent_h
#define mozilla_dom_ScreenManagerParent_h
#include "mozilla/dom/PScreenManagerParent.h"
#include "nsIScreenManager.h"
namespace mozilla {
namespace dom {
class ScreenManagerParent : public PScreenManagerParent
{
public:
ScreenManagerParent(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess);
~ScreenManagerParent() {};
virtual bool RecvRefresh(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool RecvScreenRefresh(const uint32_t& aId,
ScreenDetails* aRetVal,
bool* aSuccess) MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual bool RecvGetPrimaryScreen(ScreenDetails* aRetVal,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool RecvScreenForRect(const int32_t& aLeft,
const int32_t& aTop,
const int32_t& aWidth,
const int32_t& aHeight,
ScreenDetails* aRetVal,
bool* aSuccess) MOZ_OVERRIDE;
virtual bool RecvScreenForBrowser(PBrowserParent* aBrowser,
ScreenDetails* aRetVal,
bool* aSuccess);
private:
bool ExtractScreenDetails(nsIScreen* aScreen, ScreenDetails &aDetails);
nsCOMPtr<nsIScreenManager> mScreenMgr;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_ScreenManagerParent_h

View File

@ -309,6 +309,8 @@ public:
*/
bool IsDestroyed() const { return mIsDestroyed; }
already_AddRefed<nsIWidget> GetWidget() const;
protected:
bool ReceiveMessage(const nsString& aMessage,
bool aSync,
@ -380,7 +382,6 @@ protected:
private:
already_AddRefed<nsFrameLoader> GetFrameLoader() const;
already_AddRefed<nsIWidget> GetWidget() const;
layout::RenderFrameParent* GetRenderFrame();
nsRefPtr<nsIContentParent> mManager;
void TryCacheDPIAndScale();

View File

@ -59,6 +59,7 @@ UNIFIED_SOURCES += [
'PermissionMessageUtils.cpp',
'PreallocatedProcessManager.cpp',
'ProcessPriorityManager.cpp',
'ScreenManagerParent.cpp',
'StructuredCloneUtils.cpp',
'TabChild.cpp',
'TabContext.cpp',
@ -92,6 +93,7 @@ IPDL_SOURCES += [
'PFileDescriptorSet.ipdl',
'PFilePicker.ipdl',
'PMemoryReportRequest.ipdl',
'PScreenManager.ipdl',
'PTabContext.ipdlh',
]

View File

@ -631,11 +631,17 @@ nsDeviceContext::ComputeFullAreaUsingScreen(nsRect* outRect)
void
nsDeviceContext::FindScreen(nsIScreen** outScreen)
{
if (mWidget && mWidget->GetNativeData(NS_NATIVE_WINDOW))
if (mWidget && mWidget->GetOwningTabChild()) {
mScreenManager->ScreenForNativeWidget((void *)mWidget->GetOwningTabChild(),
outScreen);
}
else if (mWidget && mWidget->GetNativeData(NS_NATIVE_WINDOW)) {
mScreenManager->ScreenForNativeWidget(mWidget->GetNativeData(NS_NATIVE_WINDOW),
outScreen);
else
}
else {
mScreenManager->GetPrimaryScreen(outScreen);
}
}
void

View File

@ -19,6 +19,13 @@ nsScreenAndroid::~nsScreenAndroid()
{
}
NS_IMETHODIMP
nsScreenAndroid::GetId(uint32_t *outId)
{
*outId = 1;
return NS_OK;
}
NS_IMETHODIMP
nsScreenAndroid::GetRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight)
{
@ -80,6 +87,13 @@ nsScreenManagerAndroid::GetPrimaryScreen(nsIScreen **outScreen)
return NS_OK;
}
NS_IMETHODIMP
nsScreenManagerAndroid::ScreenForId(uint32_t aId,
nsIScreen **outScreen)
{
return GetPrimaryScreen(outScreen);
}
NS_IMETHODIMP
nsScreenManagerAndroid::ScreenForRect(int32_t inLeft,
int32_t inTop,

View File

@ -18,6 +18,7 @@ public:
nsScreenAndroid(void *nativeScreen);
~nsScreenAndroid();
NS_IMETHOD GetId(uint32_t* aId);
NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight);
NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight);
NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth);

View File

@ -16,6 +16,7 @@ public:
nsScreenCocoa (NSScreen *screen);
~nsScreenCocoa ();
NS_IMETHOD GetId(uint32_t* outId);
NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight);
NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight);
NS_IMETHOD GetRectDisplayPix(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight);
@ -30,6 +31,7 @@ private:
CGFloat BackingScaleFactor();
NSScreen *mScreen;
uint32_t mId;
};
#endif // nsScreenCocoa_h_

View File

@ -7,11 +7,14 @@
#include "nsObjCExceptions.h"
#include "nsCocoaUtils.h"
static uint32_t sScreenId = 0;
nsScreenCocoa::nsScreenCocoa (NSScreen *screen)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
mScreen = [screen retain];
mId = ++sScreenId;
NS_OBJC_END_TRY_ABORT_BLOCK;
}
@ -25,6 +28,17 @@ nsScreenCocoa::~nsScreenCocoa ()
NS_OBJC_END_TRY_ABORT_BLOCK;
}
NS_IMETHODIMP
nsScreenCocoa::GetId(uint32_t *outId)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
*outId = mId;
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK;
}
NS_IMETHODIMP
nsScreenCocoa::GetRect(int32_t *outX, int32_t *outY, int32_t *outWidth, int32_t *outHeight)
{

View File

@ -35,6 +35,30 @@ nsScreenManagerCocoa::ScreenForCocoaScreen(NSScreen *screen)
return sc.get();
}
NS_IMETHODIMP
nsScreenManagerCocoa::ScreenForId (uint32_t aId, nsIScreen **outScreen)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT
*outScreen = nullptr;
for (uint32_t i = 0; i < mScreenList.Length(); ++i) {
nsScreenCocoa* sc = mScreenList[i];
uint32_t id;
nsresult rv = sc->GetId(&id);
if (NS_SUCCEEDED(rv) && id == aId) {
*outScreen = sc;
NS_ADDREF(*outScreen);
return NS_OK;
}
}
return NS_ERROR_FAILURE;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP
nsScreenManagerCocoa::ScreenForRect (int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight,
nsIScreen **outScreen)

View File

@ -134,7 +134,8 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
mozilla::Module::MAIN_PROCESS_ONLY },
{ &kNS_BIDIKEYBOARD_CID, false, NULL, nsBidiKeyboardConstructor },
{ &kNS_THEMERENDERER_CID, false, NULL, nsNativeThemeCocoaConstructor },
{ &kNS_SCREENMANAGER_CID, false, NULL, nsScreenManagerCocoaConstructor },
{ &kNS_SCREENMANAGER_CID, false, NULL, nsScreenManagerCocoaConstructor,
mozilla::Module::MAIN_PROCESS_ONLY },
{ &kNS_DEVICE_CONTEXT_SPEC_CID, false, NULL, nsDeviceContextSpecXConstructor,
mozilla::Module::MAIN_PROCESS_ONLY },
{ &kNS_PRINTSESSION_CID, false, NULL, nsPrintSessionConstructor,
@ -172,7 +173,8 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
mozilla::Module::MAIN_PROCESS_ONLY },
{ "@mozilla.org/widget/bidikeyboard;1", &kNS_BIDIKEYBOARD_CID },
{ "@mozilla.org/chrome/chrome-native-theme;1", &kNS_THEMERENDERER_CID },
{ "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID },
{ "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID,
mozilla::Module::MAIN_PROCESS_ONLY },
{ "@mozilla.org/gfx/devicecontextspec;1", &kNS_DEVICE_CONTEXT_SPEC_CID,
mozilla::Module::MAIN_PROCESS_ONLY },
{ "@mozilla.org/gfx/printsession;1", &kNS_PRINTSESSION_CID,

View File

@ -31,6 +31,7 @@ public:
nsScreenGonk(void* nativeScreen);
~nsScreenGonk();
NS_IMETHOD GetId(uint32_t* aId);
NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight);
NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight);
NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth);

View File

@ -609,6 +609,13 @@ nsScreenGonk::~nsScreenGonk()
{
}
NS_IMETHODIMP
nsScreenGonk::GetId(uint32_t *outId)
{
*outId = 1;
return NS_OK;
}
NS_IMETHODIMP
nsScreenGonk::GetRect(int32_t *outLeft, int32_t *outTop,
int32_t *outWidth, int32_t *outHeight)
@ -754,6 +761,13 @@ nsScreenManagerGonk::GetPrimaryScreen(nsIScreen **outScreen)
return NS_OK;
}
NS_IMETHODIMP
nsScreenManagerGonk::ScreenForId(uint32_t aId,
nsIScreen **outScreen)
{
return GetPrimaryScreen(outScreen);
}
NS_IMETHODIMP
nsScreenManagerGonk::ScreenForRect(int32_t inLeft,
int32_t inTop,

View File

@ -12,10 +12,14 @@
#endif
#include <gtk/gtk.h>
static uint32_t sScreenId = 0;
nsScreenGtk :: nsScreenGtk ( )
: mScreenNum(0),
mRect(0, 0, 0, 0),
mAvailRect(0, 0, 0, 0)
mAvailRect(0, 0, 0, 0),
mId(++sScreenId)
{
}
@ -25,6 +29,20 @@ nsScreenGtk :: ~nsScreenGtk()
}
nsScreenGtk :: GetId(uint32_t *aId)
{
*aId = mId;
return NS_OK;
} // GetId
NS_IMETHODIMP
nsScreenGtk :: GetId(uint32_t *aId)
{
*aId = mId;
return NS_OK;
} // GetId
NS_IMETHODIMP
nsScreenGtk :: GetRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight)
{

View File

@ -30,6 +30,7 @@ public:
nsScreenGtk();
~nsScreenGtk();
NS_IMETHOD GetId(uint32_t* aId);
NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight);
NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight);
NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth);
@ -44,6 +45,7 @@ private:
uint32_t mScreenNum;
nsIntRect mRect;
nsIntRect mAvailRect;
uint32_t mId;
};
#endif // nsScreenGtk_h___

View File

@ -188,6 +188,30 @@ nsScreenManagerGtk :: Init()
return NS_OK;
}
NS_IMETHODIMP
nsScreenManagerGtk :: ScreenForId ( uint32_t aId, nsIScreen **outScreen )
{
*outScreen = nullptr;
nsresult rv;
rv = EnsureInit();
if (NS_FAILED(rv)) {
NS_ERROR("nsScreenManagerGtk::EnsureInit() failed from ScreenForId");
return rv;
}
for (int32_t i = 0, i_end = mCachedScreenArray.Count(); i < i_end; ++i) {
uint32_t id;
rv = mCachedScreenArray[i]->GetId(&id);
if (NS_SUCCEEDED(rv) && id == aId) {
NS_IF_ADDREF(*outScreen = mCachedScreenArray[i]);
return NS_OK;
}
}
return NS_ERROR_FAILURE;
}
//
// ScreenForRect

View File

@ -214,7 +214,8 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
#endif
{ &kNS_HTMLFORMATCONVERTER_CID, false, nullptr, nsHTMLFormatConverterConstructor },
{ &kNS_BIDIKEYBOARD_CID, false, nullptr, nsBidiKeyboardConstructor },
{ &kNS_SCREENMANAGER_CID, false, nullptr, nsScreenManagerGtkConstructor },
{ &kNS_SCREENMANAGER_CID, false, nullptr, nsScreenManagerGtkConstructor,
Module::MAIN_PROCESS_ONLY },
{ &kNS_THEMERENDERER_CID, false, nullptr, nsNativeThemeGTKConstructor },
#ifdef NS_PRINTING
{ &kNS_PRINTSETTINGSSERVICE_CID, false, nullptr, nsPrintOptionsGTKConstructor },
@ -250,7 +251,8 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
#endif
{ "@mozilla.org/widget/htmlformatconverter;1", &kNS_HTMLFORMATCONVERTER_CID },
{ "@mozilla.org/widget/bidikeyboard;1", &kNS_BIDIKEYBOARD_CID },
{ "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID },
{ "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID,
Module::MAIN_PROCESS_ONLY },
{ "@mozilla.org/chrome/chrome-native-theme;1", &kNS_THEMERENDERER_CID },
#ifdef NS_PRINTING
{ "@mozilla.org/gfx/printsettings-service;1", &kNS_PRINTSETTINGSSERVICE_CID },

View File

@ -6,7 +6,7 @@
#include "nsISupports.idl"
[scriptable, uuid(D6F13AF4-8ACA-4A10-8687-3F99C3692AC0)]
[scriptable, uuid(826e80c8-d70f-42e2-8aa9-82c05f2a370a)]
interface nsIScreen : nsISupports
{
/**
@ -29,6 +29,12 @@ interface nsIScreen : nsISupports
const unsigned long ROTATION_180_DEG = 2;
const unsigned long ROTATION_270_DEG = 3;
/**
* A unique identifier for this device, useful for requerying
* for it via nsIScreenManager.
*/
readonly attribute unsigned long id;
/**
* These report screen dimensions in (screen-specific) device pixels
*/

View File

@ -7,7 +7,7 @@
#include "nsISupports.idl"
#include "nsIScreen.idl"
[scriptable, uuid(1C195990-FF9E-412B-AFE7-67D1C660BB27)]
[scriptable, uuid(e8a96e60-6b61-4a14-bacc-53891604b502)]
interface nsIScreenManager : nsISupports
{
//
@ -17,11 +17,18 @@ interface nsIScreenManager : nsISupports
// The coordinates are in pixels (not twips) and in screen coordinates.
//
nsIScreen screenForRect ( in long left, in long top, in long width, in long height ) ;
//
// Returns the screen corresponding to the id. If no such screen exists,
// this will throw NS_ERROR_FAILURE. The id is a unique numeric value
// assigned to each screen, and is an attribute available on the nsIScreen
// interface.
nsIScreen screenForId ( in unsigned long id ) ;
// The screen with the menubar/taskbar. This shouldn't be needed very
// often.
readonly attribute nsIScreen primaryScreen;
// Holds the number of screens that are available
readonly attribute unsigned long numberOfScreens;

View File

@ -59,6 +59,23 @@ nsScreenManagerWin :: CreateNewScreenObject ( HMONITOR inScreen )
return retScreen;
}
NS_IMETHODIMP
nsScreenManagerWin::ScreenForId(uint32_t aId, nsIScreen **outScreen)
{
*outScreen = nullptr;
for (unsigned i = 0; i < mScreenList.Length(); ++i) {
ScreenListItem& curr = mScreenList[i];
uint32_t id;
nsresult rv = curr.mScreen->GetId(&id);
if (NS_SUCCEEDED(rv) && id == aId) {
NS_IF_ADDREF(*outScreen = curr.mScreen.get());
return NS_OK;
}
}
return NS_ERROR_FAILURE;
}
//
// ScreenForRect

View File

@ -8,9 +8,11 @@
#include "gfxWindowsPlatform.h"
#include "nsIWidget.h"
static uint32_t sScreenId;
nsScreenWin :: nsScreenWin ( HMONITOR inScreen )
: mScreen(inScreen)
, mId(++sScreenId)
{
#ifdef DEBUG
HDC hDCScreen = ::GetDC(nullptr);
@ -31,6 +33,14 @@ nsScreenWin :: ~nsScreenWin()
}
NS_IMETHODIMP
nsScreenWin::GetId(uint32_t *outId)
{
*outId = mId;
return NS_OK;
}
NS_IMETHODIMP
nsScreenWin :: GetRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight)
{

View File

@ -17,6 +17,8 @@ public:
nsScreenWin ( HMONITOR inScreen );
~nsScreenWin();
NS_IMETHOD GetId(uint32_t* aId);
// These methods return the size in device (physical) pixels
NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight);
NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight);
@ -34,6 +36,7 @@ public:
private:
HMONITOR mScreen;
uint32_t mId;
};
#endif // nsScreenWin_h___

View File

@ -221,7 +221,8 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
{ &kNS_FILEPICKER_CID, false, nullptr, FilePickerConstructor, Module::MAIN_PROCESS_ONLY },
{ &kNS_COLORPICKER_CID, false, nullptr, ColorPickerConstructor, Module::MAIN_PROCESS_ONLY },
{ &kNS_APPSHELL_CID, false, nullptr, nsAppShellConstructor },
{ &kNS_SCREENMANAGER_CID, false, nullptr, nsScreenManagerWinConstructor },
{ &kNS_SCREENMANAGER_CID, false, nullptr, nsScreenManagerWinConstructor,
Module::MAIN_PROCESS_ONLY },
{ &kNS_GFXINFO_CID, false, nullptr, GfxInfoConstructor },
{ &kNS_THEMERENDERER_CID, false, nullptr, NS_NewNativeTheme },
{ &kNS_IDLE_SERVICE_CID, false, nullptr, nsIdleServiceWinConstructor },
@ -259,7 +260,7 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
{ "@mozilla.org/filepicker;1", &kNS_FILEPICKER_CID, Module::MAIN_PROCESS_ONLY },
{ "@mozilla.org/colorpicker;1", &kNS_COLORPICKER_CID, Module::MAIN_PROCESS_ONLY },
{ "@mozilla.org/widget/appshell/win;1", &kNS_APPSHELL_CID },
{ "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID },
{ "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID, Module::MAIN_PROCESS_ONLY },
{ "@mozilla.org/gfx/info;1", &kNS_GFXINFO_CID },
{ "@mozilla.org/chrome/chrome-native-theme;1", &kNS_THEMERENDERER_CID },
{ "@mozilla.org/widget/idleservice;1", &kNS_IDLE_SERVICE_CID },

View File

@ -803,6 +803,13 @@ ScreenConfig()
return config;
}
NS_IMETHODIMP
PuppetScreen::GetId(uint32_t *outId)
{
*outId = 1;
return NS_OK;
}
NS_IMETHODIMP
PuppetScreen::GetRect(int32_t *outLeft, int32_t *outTop,
int32_t *outWidth, int32_t *outHeight)
@ -822,7 +829,6 @@ PuppetScreen::GetAvailRect(int32_t *outLeft, int32_t *outTop,
return GetRect(outLeft, outTop, outWidth, outHeight);
}
NS_IMETHODIMP
PuppetScreen::GetPixelDepth(int32_t *aPixelDepth)
{
@ -862,6 +868,14 @@ PuppetScreenManager::~PuppetScreenManager()
{
}
NS_IMETHODIMP
PuppetScreenManager::ScreenForId(uint32_t aId,
nsIScreen** outScreen)
{
NS_IF_ADDREF(*outScreen = mOneScreen.get());
return NS_OK;
}
NS_IMETHODIMP
PuppetScreenManager::GetPrimaryScreen(nsIScreen** outScreen)
{

View File

@ -305,6 +305,7 @@ public:
PuppetScreen(void* nativeScreen);
~PuppetScreen();
NS_IMETHOD GetId(uint32_t* aId) MOZ_OVERRIDE;
NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight) MOZ_OVERRIDE;
NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight) MOZ_OVERRIDE;
NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) MOZ_OVERRIDE;

View File

@ -0,0 +1,157 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 2; -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* 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/. */
#include "mozilla/unused.h"
#include "nsIAppShell.h"
#include "nsScreenManagerProxy.h"
#include "nsServiceManagerUtils.h"
#include "nsWidgetsCID.h"
#include "ScreenProxy.h"
namespace mozilla {
namespace widget {
using namespace mozilla::dom;
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
ScreenProxy::ScreenProxy(nsScreenManagerProxy* aScreenManager, ScreenDetails aDetails)
: mScreenManager(aScreenManager)
, mCacheValid(false)
, mCacheWillInvalidate(false)
{
PopulateByDetails(aDetails);
}
NS_IMETHODIMP
ScreenProxy::GetId(uint32_t *outId)
{
*outId = mId;
return NS_OK;
}
NS_IMETHODIMP
ScreenProxy::GetRect(int32_t *outLeft,
int32_t *outTop,
int32_t *outWidth,
int32_t *outHeight)
{
if (!EnsureCacheIsValid()) {
return NS_ERROR_FAILURE;
}
*outLeft = mRect.x;
*outTop = mRect.y;
*outWidth = mRect.width;
*outHeight = mRect.height;
return NS_OK;
}
NS_IMETHODIMP
ScreenProxy::GetAvailRect(int32_t *outLeft,
int32_t *outTop,
int32_t *outWidth,
int32_t *outHeight)
{
if (!EnsureCacheIsValid()) {
return NS_ERROR_FAILURE;
}
*outLeft = mAvailRect.x;
*outTop = mAvailRect.y;
*outWidth = mAvailRect.width;
*outHeight = mAvailRect.height;
return NS_OK;
}
NS_IMETHODIMP
ScreenProxy::GetPixelDepth(int32_t *aPixelDepth)
{
if (!EnsureCacheIsValid()) {
return NS_ERROR_FAILURE;
}
*aPixelDepth = mPixelDepth;
return NS_OK;
}
NS_IMETHODIMP
ScreenProxy::GetColorDepth(int32_t *aColorDepth)
{
if (!EnsureCacheIsValid()) {
return NS_ERROR_FAILURE;
}
*aColorDepth = mColorDepth;
return NS_OK;
}
void
ScreenProxy::PopulateByDetails(ScreenDetails aDetails)
{
mId = aDetails.id();
mRect = nsIntRect(aDetails.rect());
mAvailRect = nsIntRect(aDetails.availRect());
mPixelDepth = aDetails.pixelDepth();
mColorDepth = aDetails.colorDepth();
mContentsScaleFactor = aDetails.contentsScaleFactor();
}
bool
ScreenProxy::EnsureCacheIsValid()
{
if (mCacheValid) {
return true;
}
bool success = false;
// Kick off a synchronous IPC call to the parent to get the
// most up-to-date information.
ScreenDetails details;
unused << mScreenManager->SendScreenRefresh(mId, &details, &success);
if (!success) {
NS_WARNING("Updating a ScreenProxy in the child process failed on parent side.");
return false;
}
PopulateByDetails(details);
mCacheValid = true;
InvalidateCacheOnNextTick();
return true;
}
void
ScreenProxy::InvalidateCacheOnNextTick()
{
if (mCacheWillInvalidate) {
return;
}
mCacheWillInvalidate = true;
nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
if (appShell) {
appShell->RunInStableState(
NS_NewRunnableMethod(this, &ScreenProxy::InvalidateCache)
);
} else {
// It's pretty bad news if we can't get the appshell. In that case,
// let's just invalidate the cache right away.
InvalidateCache();
}
}
void
ScreenProxy::InvalidateCache()
{
mCacheValid = false;
mCacheWillInvalidate = false;
}
} // namespace widget
} // namespace mozilla

View File

@ -0,0 +1,60 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 2; -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* 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/. */
#ifndef mozilla_widget_ScreenProxy_h
#define mozilla_widget_ScreenProxy_h
#include "nsBaseScreen.h"
#include "mozilla/dom/PScreenManagerChild.h"
#include "mozilla/dom/TabChild.h"
class nsScreenManagerProxy;
namespace mozilla {
namespace widget {
class ScreenProxy : public nsBaseScreen
{
public:
ScreenProxy(nsScreenManagerProxy* aScreenManager,
mozilla::dom::ScreenDetails aDetails);
~ScreenProxy() {};
NS_IMETHOD GetId(uint32_t* aId) MOZ_OVERRIDE;
NS_IMETHOD GetRect(int32_t* aLeft,
int32_t* aTop,
int32_t* aWidth,
int32_t* aHeight) MOZ_OVERRIDE;
NS_IMETHOD GetAvailRect(int32_t* aLeft,
int32_t* aTop,
int32_t* aWidth,
int32_t* aHeight) MOZ_OVERRIDE;
NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) MOZ_OVERRIDE;
NS_IMETHOD GetColorDepth(int32_t* aColorDepth) MOZ_OVERRIDE;
private:
void PopulateByDetails(mozilla::dom::ScreenDetails aDetails);
bool EnsureCacheIsValid();
void InvalidateCacheOnNextTick();
void InvalidateCache();
double mContentsScaleFactor;
nsRefPtr<nsScreenManagerProxy> mScreenManager;
uint32_t mId;
int32_t mPixelDepth;
int32_t mColorDepth;
nsIntRect mRect;
nsIntRect mAvailRect;
bool mCacheValid;
bool mCacheWillInvalidate;
};
} // namespace widget
} // namespace mozilla
#endif

View File

@ -34,9 +34,11 @@ UNIFIED_SOURCES += [
'nsPrintOptionsImpl.cpp',
'nsPrintSession.cpp',
'nsPrintSettingsImpl.cpp',
'nsScreenManagerProxy.cpp',
'nsTransferable.cpp',
'nsXPLookAndFeel.cpp',
'PuppetWidget.cpp',
'ScreenProxy.cpp',
'WidgetUtils.cpp',
]

View File

@ -10,6 +10,7 @@
#include "nsClipboardProxy.h"
#include "nsColorPickerProxy.h"
#include "nsFilePickerProxy.h"
#include "nsScreenManagerProxy.h"
using namespace mozilla;
@ -18,10 +19,12 @@ using namespace mozilla;
NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardProxy)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsColorPickerProxy)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePickerProxy)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerProxy)
NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID);
NS_DEFINE_NAMED_CID(NS_COLORPICKER_CID);
NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID);
NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID);
static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
{ &kNS_CLIPBOARD_CID, false, nullptr, nsClipboardProxyConstructor,
@ -30,6 +33,8 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
Module::CONTENT_PROCESS_ONLY },
{ &kNS_FILEPICKER_CID, false, nullptr, nsFilePickerProxyConstructor,
Module::CONTENT_PROCESS_ONLY },
{ &kNS_SCREENMANAGER_CID, false, nullptr, nsScreenManagerProxyConstructor,
Module::CONTENT_PROCESS_ONLY },
{ nullptr }
};
@ -37,6 +42,7 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
{ "@mozilla.org/widget/clipboard;1", &kNS_CLIPBOARD_CID, Module::CONTENT_PROCESS_ONLY },
{ "@mozilla.org/colorpicker;1", &kNS_COLORPICKER_CID, Module::CONTENT_PROCESS_ONLY },
{ "@mozilla.org/filepicker;1", &kNS_FILEPICKER_CID, Module::CONTENT_PROCESS_ONLY },
{ "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID, Module::CONTENT_PROCESS_ONLY },
{ nullptr }
};

View File

@ -0,0 +1,226 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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/. */
#include "mozilla/unused.h"
#include "mozilla/dom/ContentChild.h"
#include "nsScreenManagerProxy.h"
#include "nsServiceManagerUtils.h"
#include "nsIAppShell.h"
#include "nsIScreen.h"
#include "nsIScreenManager.h"
#include "nsWidgetsCID.h"
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::widget;
NS_IMPL_ISUPPORTS(nsScreenManagerProxy, nsIScreenManager)
nsScreenManagerProxy::nsScreenManagerProxy()
: mNumberOfScreens(-1)
, mSystemDefaultScale(1.0)
, mCacheValid(true)
, mCacheWillInvalidate(false)
{
bool success = false;
unused << ContentChild::GetSingleton()->SendPScreenManagerConstructor(
this,
&mNumberOfScreens,
&mSystemDefaultScale,
&success);
if (!success) {
// We're in bad shape. We'll return the default values, but we'll basically
// be lying.
NS_WARNING("Setting up communications with the parent nsIScreenManager failed.");
}
InvalidateCacheOnNextTick();
// nsScreenManagerProxy is a service, which will always have a reference
// held to it by the Component Manager once the service is requested.
// However, nsScreenManagerProxy also implements PScreenManagerChild, and
// that means that the manager of the PScreenManager protocol (PContent
// in this case) needs to know how to deallocate this actor. We AddRef here
// so that in the event that PContent tries to deallocate us either before
// or after process shutdown, we don't try to do a double-free.
AddRef();
}
/**
* nsIScreenManager
**/
NS_IMETHODIMP
nsScreenManagerProxy::GetPrimaryScreen(nsIScreen** outScreen)
{
InvalidateCacheOnNextTick();
if (!mPrimaryScreen) {
ScreenDetails details;
bool success = false;
unused << SendGetPrimaryScreen(&details, &success);
if (!success) {
return NS_ERROR_FAILURE;
}
mPrimaryScreen = new ScreenProxy(this, details);
}
NS_ADDREF(*outScreen = mPrimaryScreen);
return NS_OK;
}
NS_IMETHODIMP
nsScreenManagerProxy::ScreenForId(uint32_t aId, nsIScreen** outScreen)
{
// At this time, there's no need for child processes to query for
// screens by ID.
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsScreenManagerProxy::ScreenForRect(int32_t inLeft,
int32_t inTop,
int32_t inWidth,
int32_t inHeight,
nsIScreen** outScreen)
{
bool success = false;
ScreenDetails details;
unused << SendScreenForRect(inLeft, inTop, inWidth, inHeight, &details, &success);
if (!success) {
return NS_ERROR_FAILURE;
}
nsRefPtr<ScreenProxy> screen = new ScreenProxy(this, details);
NS_ADDREF(*outScreen = screen);
return NS_OK;
}
NS_IMETHODIMP
nsScreenManagerProxy::ScreenForNativeWidget(void* aWidget,
nsIScreen** outScreen)
{
// Because ScreenForNativeWidget can be called numerous times
// indirectly from content via the DOM Screen API, we cache the
// results for this tick of the event loop.
TabChild* tabChild = static_cast<TabChild*>(aWidget);
// Enumerate the cached screen array, looking for one that has
// the TabChild that we're looking for...
for (uint32_t i = 0; i < mScreenCache.Length(); ++i) {
ScreenCacheEntry& curr = mScreenCache[i];
if (curr.mTabChild == aWidget) {
NS_ADDREF(*outScreen = static_cast<nsIScreen*>(curr.mScreenProxy));
return NS_OK;
}
}
// Never cached this screen, so we have to ask the parent process
// for it.
bool success = false;
ScreenDetails details;
unused << SendScreenForBrowser(tabChild, &details, &success);
if (!success) {
return NS_ERROR_FAILURE;
}
ScreenCacheEntry newEntry;
nsRefPtr<ScreenProxy> screen = new ScreenProxy(this, details);
newEntry.mScreenProxy = screen;
newEntry.mTabChild = tabChild;
mScreenCache.AppendElement(newEntry);
NS_ADDREF(*outScreen = screen);
InvalidateCacheOnNextTick();
return NS_OK;
}
NS_IMETHODIMP
nsScreenManagerProxy::GetNumberOfScreens(uint32_t* aNumberOfScreens)
{
if (!EnsureCacheIsValid()) {
return NS_ERROR_FAILURE;
}
*aNumberOfScreens = mNumberOfScreens;
return NS_OK;
}
NS_IMETHODIMP
nsScreenManagerProxy::GetSystemDefaultScale(float *aSystemDefaultScale)
{
if (!EnsureCacheIsValid()) {
return NS_ERROR_FAILURE;
}
*aSystemDefaultScale = mSystemDefaultScale;
return NS_OK;
}
bool
nsScreenManagerProxy::EnsureCacheIsValid()
{
if (mCacheValid) {
return true;
}
bool success = false;
// Kick off a synchronous IPC call to the parent to get the
// most up-to-date information.
unused << SendRefresh(&mNumberOfScreens, &mSystemDefaultScale, &success);
if (!success) {
NS_WARNING("Refreshing nsScreenManagerProxy failed in the parent process.");
return false;
}
mCacheValid = true;
InvalidateCacheOnNextTick();
return true;
}
void
nsScreenManagerProxy::InvalidateCacheOnNextTick()
{
if (mCacheWillInvalidate) {
return;
}
mCacheWillInvalidate = true;
nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
if (appShell) {
appShell->RunInStableState(
NS_NewRunnableMethod(this, &nsScreenManagerProxy::InvalidateCache)
);
} else {
// It's pretty bad news if we can't get the appshell. In that case,
// let's just invalidate the cache right away.
InvalidateCache();
}
}
void
nsScreenManagerProxy::InvalidateCache()
{
mCacheValid = false;
mCacheWillInvalidate = false;
if (mPrimaryScreen) {
mPrimaryScreen = nullptr;
}
for (int32_t i = mScreenCache.Length() - 1; i >= 0; --i) {
mScreenCache.RemoveElementAt(i);
}
}

View File

@ -0,0 +1,67 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef nsScreenManagerProxy_h
#define nsScreenManagerProxy_h
#include "nsIScreenManager.h"
#include "mozilla/dom/PScreenManagerChild.h"
#include "mozilla/dom/TabChild.h"
#include "ScreenProxy.h"
/**
* The nsScreenManagerProxy is used by the content process to get
* information about system screens. It uses the PScreenManager protocol
* to communicate with a PScreenManagerParent to get this information,
* and also caches the information it gets back.
*
* We cache both the system screen information that nsIScreenManagers
* provide, as well as the nsIScreens that callers can query for.
*
* Both of these caches are invalidated on the next tick of the event
* loop.
*/
class nsScreenManagerProxy MOZ_FINAL : public nsIScreenManager,
public mozilla::dom::PScreenManagerChild
{
public:
nsScreenManagerProxy();
NS_DECL_ISUPPORTS
NS_DECL_NSISCREENMANAGER
private:
~nsScreenManagerProxy() {};
bool EnsureCacheIsValid();
void InvalidateCacheOnNextTick();
void InvalidateCache();
uint32_t mNumberOfScreens;
float mSystemDefaultScale;
bool mCacheValid;
bool mCacheWillInvalidate;
nsRefPtr<mozilla::widget::ScreenProxy> mPrimaryScreen;
// nsScreenManagerProxy caches the results to repeated calls to
// ScreenForNativeWidget, which can be triggered indirectly by
// web content using the DOM Screen API. This allows us to bypass
// a lot of IPC traffic.
//
// The cache stores ScreenProxy's mapped to the TabChild that
// asked for the ScreenForNativeWidget was called with via
// ScreenCacheEntry's. The cache is cleared on the next tick of
// the event loop.
struct ScreenCacheEntry
{
nsRefPtr<mozilla::widget::ScreenProxy> mScreenProxy;
nsRefPtr<mozilla::dom::TabChild> mTabChild;
};
nsTArray<ScreenCacheEntry> mScreenCache;
};
#endif // nsScreenManagerProxy_h