123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- /* -*- 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 "nsContentUtils.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;
- }
- RefPtr<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->GetTabId(), &details, &success);
- if (!success) {
- return NS_ERROR_FAILURE;
- }
- ScreenCacheEntry newEntry;
- RefPtr<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;
- nsContentUtils::RunInStableState(NewRunnableMethod(this, &nsScreenManagerProxy::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);
- }
- }
|