mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-13 10:47:31 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
401
dom/presentation/PresentationServiceBase.h
Normal file
401
dom/presentation/PresentationServiceBase.h
Normal file
|
|
@ -0,0 +1,401 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et ft=cpp : */
|
||||
/* 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_PresentationServiceBase_h
|
||||
#define mozilla_dom_PresentationServiceBase_h
|
||||
|
||||
#include "mozilla/Unused.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsIPresentationListener.h"
|
||||
#include "nsIPresentationService.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
template<class T>
|
||||
class PresentationServiceBase
|
||||
{
|
||||
public:
|
||||
PresentationServiceBase() = default;
|
||||
|
||||
already_AddRefed<T>
|
||||
GetSessionInfo(const nsAString& aSessionId, const uint8_t aRole)
|
||||
{
|
||||
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
|
||||
aRole == nsIPresentationService::ROLE_RECEIVER);
|
||||
|
||||
RefPtr<T> info;
|
||||
if (aRole == nsIPresentationService::ROLE_CONTROLLER) {
|
||||
return mSessionInfoAtController.Get(aSessionId, getter_AddRefs(info)) ?
|
||||
info.forget() : nullptr;
|
||||
} else {
|
||||
return mSessionInfoAtReceiver.Get(aSessionId, getter_AddRefs(info)) ?
|
||||
info.forget() : nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
class SessionIdManager final
|
||||
{
|
||||
public:
|
||||
explicit SessionIdManager()
|
||||
{
|
||||
MOZ_COUNT_CTOR(SessionIdManager);
|
||||
}
|
||||
|
||||
~SessionIdManager()
|
||||
{
|
||||
MOZ_COUNT_DTOR(SessionIdManager);
|
||||
}
|
||||
|
||||
nsresult GetWindowId(const nsAString& aSessionId, uint64_t* aWindowId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mRespondingWindowIds.Get(aSessionId, aWindowId)) {
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsresult GetSessionIds(uint64_t aWindowId, nsTArray<nsString>& aSessionIds)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsTArray<nsString>* sessionIdArray;
|
||||
if (!mRespondingSessionIds.Get(aWindowId, &sessionIdArray)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
aSessionIds.Assign(*sessionIdArray);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void AddSessionId(uint64_t aWindowId, const nsAString& aSessionId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (NS_WARN_IF(aWindowId == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsTArray<nsString>* sessionIdArray;
|
||||
if (!mRespondingSessionIds.Get(aWindowId, &sessionIdArray)) {
|
||||
sessionIdArray = new nsTArray<nsString>();
|
||||
mRespondingSessionIds.Put(aWindowId, sessionIdArray);
|
||||
}
|
||||
|
||||
sessionIdArray->AppendElement(nsString(aSessionId));
|
||||
mRespondingWindowIds.Put(aSessionId, aWindowId);
|
||||
}
|
||||
|
||||
void RemoveSessionId(const nsAString& aSessionId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
uint64_t windowId = 0;
|
||||
if (mRespondingWindowIds.Get(aSessionId, &windowId)) {
|
||||
mRespondingWindowIds.Remove(aSessionId);
|
||||
nsTArray<nsString>* sessionIdArray;
|
||||
if (mRespondingSessionIds.Get(windowId, &sessionIdArray)) {
|
||||
sessionIdArray->RemoveElement(nsString(aSessionId));
|
||||
if (sessionIdArray->IsEmpty()) {
|
||||
mRespondingSessionIds.Remove(windowId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult UpdateWindowId(const nsAString& aSessionId, const uint64_t aWindowId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
RemoveSessionId(aSessionId);
|
||||
AddSessionId(aWindowId, aSessionId);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
mRespondingSessionIds.Clear();
|
||||
mRespondingWindowIds.Clear();
|
||||
}
|
||||
|
||||
private:
|
||||
nsClassHashtable<nsUint64HashKey, nsTArray<nsString>> mRespondingSessionIds;
|
||||
nsDataHashtable<nsStringHashKey, uint64_t> mRespondingWindowIds;
|
||||
};
|
||||
|
||||
class AvailabilityManager final
|
||||
{
|
||||
public:
|
||||
explicit AvailabilityManager()
|
||||
{
|
||||
MOZ_COUNT_CTOR(AvailabilityManager);
|
||||
}
|
||||
|
||||
~AvailabilityManager()
|
||||
{
|
||||
MOZ_COUNT_DTOR(AvailabilityManager);
|
||||
}
|
||||
|
||||
void AddAvailabilityListener(
|
||||
const nsTArray<nsString>& aAvailabilityUrls,
|
||||
nsIPresentationAvailabilityListener* aListener)
|
||||
{
|
||||
nsTArray<nsString> dummy;
|
||||
AddAvailabilityListener(aAvailabilityUrls, aListener, dummy);
|
||||
}
|
||||
|
||||
void AddAvailabilityListener(
|
||||
const nsTArray<nsString>& aAvailabilityUrls,
|
||||
nsIPresentationAvailabilityListener* aListener,
|
||||
nsTArray<nsString>& aAddedUrls)
|
||||
{
|
||||
if (!aListener) {
|
||||
MOZ_ASSERT(false, "aListener should not be null.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (aAvailabilityUrls.IsEmpty()) {
|
||||
MOZ_ASSERT(false, "aAvailabilityUrls should not be empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
aAddedUrls.Clear();
|
||||
nsTArray<nsString> knownAvailableUrls;
|
||||
for (const auto& url : aAvailabilityUrls) {
|
||||
AvailabilityEntry* entry;
|
||||
if (!mAvailabilityUrlTable.Get(url, &entry)) {
|
||||
entry = new AvailabilityEntry();
|
||||
mAvailabilityUrlTable.Put(url, entry);
|
||||
aAddedUrls.AppendElement(url);
|
||||
}
|
||||
if (!entry->mListeners.Contains(aListener)) {
|
||||
entry->mListeners.AppendElement(aListener);
|
||||
}
|
||||
if (entry->mAvailable) {
|
||||
knownAvailableUrls.AppendElement(url);
|
||||
}
|
||||
}
|
||||
|
||||
if (!knownAvailableUrls.IsEmpty()) {
|
||||
Unused <<
|
||||
NS_WARN_IF(
|
||||
NS_FAILED(aListener->NotifyAvailableChange(knownAvailableUrls,
|
||||
true)));
|
||||
} else {
|
||||
// If we can't find any known available url and there is no newly
|
||||
// added url, we still need to notify the listener of the result.
|
||||
// So, the promise returned by |getAvailability| can be resolved.
|
||||
if (aAddedUrls.IsEmpty()) {
|
||||
Unused <<
|
||||
NS_WARN_IF(
|
||||
NS_FAILED(aListener->NotifyAvailableChange(aAvailabilityUrls,
|
||||
false)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveAvailabilityListener(
|
||||
const nsTArray<nsString>& aAvailabilityUrls,
|
||||
nsIPresentationAvailabilityListener* aListener)
|
||||
{
|
||||
nsTArray<nsString> dummy;
|
||||
RemoveAvailabilityListener(aAvailabilityUrls, aListener, dummy);
|
||||
}
|
||||
|
||||
void RemoveAvailabilityListener(
|
||||
const nsTArray<nsString>& aAvailabilityUrls,
|
||||
nsIPresentationAvailabilityListener* aListener,
|
||||
nsTArray<nsString>& aRemovedUrls)
|
||||
{
|
||||
if (!aListener) {
|
||||
MOZ_ASSERT(false, "aListener should not be null.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (aAvailabilityUrls.IsEmpty()) {
|
||||
MOZ_ASSERT(false, "aAvailabilityUrls should not be empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
aRemovedUrls.Clear();
|
||||
for (const auto& url : aAvailabilityUrls) {
|
||||
AvailabilityEntry* entry;
|
||||
if (mAvailabilityUrlTable.Get(url, &entry)) {
|
||||
entry->mListeners.RemoveElement(aListener);
|
||||
if (entry->mListeners.IsEmpty()) {
|
||||
mAvailabilityUrlTable.Remove(url);
|
||||
aRemovedUrls.AppendElement(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult DoNotifyAvailableChange(const nsTArray<nsString>& aAvailabilityUrls,
|
||||
bool aAvailable)
|
||||
{
|
||||
typedef nsClassHashtable<nsISupportsHashKey,
|
||||
nsTArray<nsString>> ListenerToUrlsMap;
|
||||
ListenerToUrlsMap availabilityListenerTable;
|
||||
// Create a mapping from nsIPresentationAvailabilityListener to
|
||||
// availabilityUrls.
|
||||
for (auto it = mAvailabilityUrlTable.ConstIter(); !it.Done(); it.Next()) {
|
||||
if (aAvailabilityUrls.Contains(it.Key())) {
|
||||
AvailabilityEntry* entry = it.UserData();
|
||||
entry->mAvailable = aAvailable;
|
||||
|
||||
for (uint32_t i = 0; i < entry->mListeners.Length(); ++i) {
|
||||
nsIPresentationAvailabilityListener* listener =
|
||||
entry->mListeners.ObjectAt(i);
|
||||
nsTArray<nsString>* urlArray;
|
||||
if (!availabilityListenerTable.Get(listener, &urlArray)) {
|
||||
urlArray = new nsTArray<nsString>();
|
||||
availabilityListenerTable.Put(listener, urlArray);
|
||||
}
|
||||
urlArray->AppendElement(it.Key());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = availabilityListenerTable.Iter(); !it.Done(); it.Next()) {
|
||||
auto listener =
|
||||
static_cast<nsIPresentationAvailabilityListener*>(it.Key());
|
||||
|
||||
Unused <<
|
||||
NS_WARN_IF(NS_FAILED(listener->NotifyAvailableChange(*it.UserData(),
|
||||
aAvailable)));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void GetAvailbilityUrlByAvailability(nsTArray<nsString>& aOutArray,
|
||||
bool aAvailable)
|
||||
{
|
||||
aOutArray.Clear();
|
||||
|
||||
for (auto it = mAvailabilityUrlTable.ConstIter(); !it.Done(); it.Next()) {
|
||||
if (it.UserData()->mAvailable == aAvailable) {
|
||||
aOutArray.AppendElement(it.Key());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
mAvailabilityUrlTable.Clear();
|
||||
}
|
||||
|
||||
private:
|
||||
struct AvailabilityEntry
|
||||
{
|
||||
explicit AvailabilityEntry()
|
||||
: mAvailable(false)
|
||||
{}
|
||||
|
||||
bool mAvailable;
|
||||
nsCOMArray<nsIPresentationAvailabilityListener> mListeners;
|
||||
};
|
||||
|
||||
nsClassHashtable<nsStringHashKey, AvailabilityEntry> mAvailabilityUrlTable;
|
||||
};
|
||||
|
||||
virtual ~PresentationServiceBase() = default;
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
mRespondingListeners.Clear();
|
||||
mControllerSessionIdManager.Clear();
|
||||
mReceiverSessionIdManager.Clear();
|
||||
}
|
||||
|
||||
nsresult GetWindowIdBySessionIdInternal(const nsAString& aSessionId,
|
||||
uint8_t aRole,
|
||||
uint64_t* aWindowId)
|
||||
{
|
||||
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
|
||||
aRole == nsIPresentationService::ROLE_RECEIVER);
|
||||
|
||||
if (NS_WARN_IF(!aWindowId)) {
|
||||
return NS_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
if (aRole == nsIPresentationService::ROLE_CONTROLLER) {
|
||||
return mControllerSessionIdManager.GetWindowId(aSessionId, aWindowId);
|
||||
}
|
||||
|
||||
return mReceiverSessionIdManager.GetWindowId(aSessionId, aWindowId);
|
||||
}
|
||||
|
||||
void AddRespondingSessionId(uint64_t aWindowId,
|
||||
const nsAString& aSessionId,
|
||||
uint8_t aRole)
|
||||
{
|
||||
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
|
||||
aRole == nsIPresentationService::ROLE_RECEIVER);
|
||||
|
||||
if (aRole == nsIPresentationService::ROLE_CONTROLLER) {
|
||||
mControllerSessionIdManager.AddSessionId(aWindowId, aSessionId);
|
||||
} else {
|
||||
mReceiverSessionIdManager.AddSessionId(aWindowId, aSessionId);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveRespondingSessionId(const nsAString& aSessionId,
|
||||
uint8_t aRole)
|
||||
{
|
||||
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
|
||||
aRole == nsIPresentationService::ROLE_RECEIVER);
|
||||
|
||||
if (aRole == nsIPresentationService::ROLE_CONTROLLER) {
|
||||
mControllerSessionIdManager.RemoveSessionId(aSessionId);
|
||||
} else {
|
||||
mReceiverSessionIdManager.RemoveSessionId(aSessionId);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult UpdateWindowIdBySessionIdInternal(const nsAString& aSessionId,
|
||||
uint8_t aRole,
|
||||
const uint64_t aWindowId)
|
||||
{
|
||||
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
|
||||
aRole == nsIPresentationService::ROLE_RECEIVER);
|
||||
|
||||
if (aRole == nsIPresentationService::ROLE_CONTROLLER) {
|
||||
return mControllerSessionIdManager.UpdateWindowId(aSessionId, aWindowId);
|
||||
}
|
||||
|
||||
return mReceiverSessionIdManager.UpdateWindowId(aSessionId, aWindowId);
|
||||
}
|
||||
|
||||
// Store the responding listener based on the window ID of the (in-process or
|
||||
// OOP) receiver page.
|
||||
nsRefPtrHashtable<nsUint64HashKey, nsIPresentationRespondingListener>
|
||||
mRespondingListeners;
|
||||
|
||||
// Store the mapping between the window ID of the in-process and OOP page and the ID
|
||||
// of the responding session. It's used for both controller and receiver page
|
||||
// to retrieve the correspondent session ID. Besides, also keep the mapping
|
||||
// between the responding session ID and the window ID to help look up the
|
||||
// window ID.
|
||||
SessionIdManager mControllerSessionIdManager;
|
||||
SessionIdManager mReceiverSessionIdManager;
|
||||
|
||||
nsRefPtrHashtable<nsStringHashKey, T> mSessionInfoAtController;
|
||||
nsRefPtrHashtable<nsStringHashKey, T> mSessionInfoAtReceiver;
|
||||
|
||||
AvailabilityManager mAvailabilityManager;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_PresentationServiceBase_h
|
||||
Loading…
Add table
Add a link
Reference in a new issue