forked from mirrors/gecko-dev
Bug 1885936 - Part 1: Introduce a chrome only function for getting all gamepads. r=cmartin,webidl,emilio
To collect the gamepad information on the user device, we introduce a chrome only function called RequestAllGamepads to Navigator. The function will return a promise which resolves when we get all gamepads info from the parent process. Note that we cannot rely on The existing navigator.getGamepads() function because it cannot allow us collecting gamepads info without the user interacts with the gamepads. Differential Revision: https://phabricator.services.mozilla.com/D207979
This commit is contained in:
parent
c887ea40f9
commit
226c880153
11 changed files with 101 additions and 1 deletions
|
|
@ -1643,6 +1643,20 @@ GamepadServiceTest* Navigator::RequestGamepadServiceTest(ErrorResult& aRv) {
|
|||
return mGamepadServiceTest;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> Navigator::RequestAllGamepads(ErrorResult& aRv) {
|
||||
if (!mWindow || !mWindow->IsFullyActive()) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsGlobalWindowInner* win = nsGlobalWindowInner::Cast(mWindow);
|
||||
|
||||
// We need to set the flag to trigger the parent process to start monitoring
|
||||
// gamepads. Otherwise, we cannot get any gamepad information.
|
||||
win->SetHasGamepadEventListener(true);
|
||||
return win->RequestAllGamepads(aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> Navigator::GetVRDisplays(ErrorResult& aRv) {
|
||||
if (!mWindow || !mWindow->GetDocShell() || !mWindow->GetExtantDoc()) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
|
|
|
|||
|
|
@ -177,6 +177,7 @@ class Navigator final : public nsISupports, public nsWrapperCache {
|
|||
|
||||
void GetGamepads(nsTArray<RefPtr<Gamepad>>& aGamepads, ErrorResult& aRv);
|
||||
GamepadServiceTest* RequestGamepadServiceTest(ErrorResult& aRv);
|
||||
already_AddRefed<Promise> RequestAllGamepads(ErrorResult& aRv);
|
||||
already_AddRefed<Promise> GetVRDisplays(ErrorResult& aRv);
|
||||
void FinishGetVRDisplays(bool isWebVRSupportedInwindow, Promise* p);
|
||||
void GetActiveVRDisplays(nsTArray<RefPtr<VRDisplay>>& aDisplays) const;
|
||||
|
|
|
|||
|
|
@ -6785,6 +6785,18 @@ void nsGlobalWindowInner::GetGamepads(nsTArray<RefPtr<Gamepad>>& aGamepads) {
|
|||
}
|
||||
}
|
||||
|
||||
already_AddRefed<mozilla::dom::Promise> nsGlobalWindowInner::RequestAllGamepads(
|
||||
ErrorResult& aRv) {
|
||||
RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
|
||||
|
||||
if (!gamepadManager) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return gamepadManager->RequestAllGamepads(this, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<Gamepad> nsGlobalWindowInner::GetGamepad(
|
||||
GamepadHandle aHandle) {
|
||||
RefPtr<Gamepad> gamepad;
|
||||
|
|
|
|||
|
|
@ -495,6 +495,8 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
|
|||
mozilla::dom::Gamepad* aGamepad);
|
||||
void RemoveGamepad(mozilla::dom::GamepadHandle aHandle);
|
||||
void GetGamepads(nsTArray<RefPtr<mozilla::dom::Gamepad>>& aGamepads);
|
||||
already_AddRefed<mozilla::dom::Promise> RequestAllGamepads(
|
||||
mozilla::ErrorResult& aRv);
|
||||
already_AddRefed<mozilla::dom::Gamepad> GetGamepad(
|
||||
mozilla::dom::GamepadHandle aHandle);
|
||||
void SetHasSeenGamepadInput(bool aHasSeen);
|
||||
|
|
|
|||
|
|
@ -659,4 +659,38 @@ already_AddRefed<Promise> GamepadManager::SetLightIndicatorColor(
|
|||
++mPromiseID;
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> GamepadManager::RequestAllGamepads(
|
||||
nsIGlobalObject* aGlobal, ErrorResult& aRv) {
|
||||
RefPtr<Promise> promise = Promise::Create(aGlobal, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!mChannelChild) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mChannelChild->SendRequestAllGamepads(
|
||||
[promise](const nsTArray<GamepadAdded>& aAddedGamepads) {
|
||||
nsTArray<RefPtr<Gamepad>> gamepads;
|
||||
|
||||
for (const auto& addedGamepad : aAddedGamepads) {
|
||||
RefPtr<Gamepad> gamepad = new Gamepad(
|
||||
nullptr, addedGamepad.id(), 0, GamepadHandle(),
|
||||
addedGamepad.mapping(), addedGamepad.hand(),
|
||||
addedGamepad.display_id(), addedGamepad.num_buttons(),
|
||||
addedGamepad.num_axes(), addedGamepad.num_haptics(),
|
||||
addedGamepad.num_lights(), addedGamepad.num_touches());
|
||||
gamepads.AppendElement(gamepad);
|
||||
}
|
||||
promise->MaybeResolve(gamepads);
|
||||
},
|
||||
[promise](mozilla::ipc::ResponseRejectReason) {
|
||||
promise->MaybeReject(NS_ERROR_UNEXPECTED);
|
||||
});
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
} // namespace mozilla::dom
|
||||
|
|
|
|||
|
|
@ -83,6 +83,10 @@ class GamepadManager final : public nsIObserver {
|
|||
nsIGlobalObject* aGlobal,
|
||||
ErrorResult& aRv);
|
||||
|
||||
// Request information of all gamepads from the parent process.
|
||||
already_AddRefed<Promise> RequestAllGamepads(nsIGlobalObject* aGlobal,
|
||||
ErrorResult& aRv);
|
||||
|
||||
protected:
|
||||
GamepadManager();
|
||||
~GamepadManager() = default;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#define mozilla_dom_GamepadPlatformService_h_
|
||||
|
||||
#include "mozilla/dom/GamepadBinding.h"
|
||||
#include "mozilla/dom/GamepadEventTypes.h"
|
||||
#include "mozilla/dom/GamepadHandle.h"
|
||||
|
||||
#include <map>
|
||||
|
|
@ -18,7 +19,6 @@
|
|||
|
||||
namespace mozilla::dom {
|
||||
|
||||
class GamepadAdded;
|
||||
class GamepadEventChannelParent;
|
||||
enum class GamepadLightIndicatorType : uint8_t;
|
||||
struct GamepadPoseState;
|
||||
|
|
@ -122,6 +122,15 @@ class GamepadPlatformService final {
|
|||
|
||||
void MaybeShutdown();
|
||||
|
||||
nsTArray<GamepadAdded> GetAllGamePads() {
|
||||
nsTArray<GamepadAdded> gamepads;
|
||||
|
||||
for (const auto& elem : mGamepadAdded) {
|
||||
gamepads.AppendElement(elem.second);
|
||||
}
|
||||
return gamepads;
|
||||
}
|
||||
|
||||
private:
|
||||
GamepadPlatformService();
|
||||
~GamepadPlatformService();
|
||||
|
|
|
|||
|
|
@ -100,6 +100,16 @@ mozilla::ipc::IPCResult GamepadEventChannelParent::RecvLightIndicatorColor(
|
|||
return IPC_FAIL(this, "SendReplyGamepadPromise fail.");
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult GamepadEventChannelParent::RecvRequestAllGamepads(
|
||||
RequestAllGamepadsResolver&& aResolver) {
|
||||
RefPtr<GamepadPlatformService> service =
|
||||
GamepadPlatformService::GetParentService();
|
||||
MOZ_ASSERT(service);
|
||||
|
||||
aResolver(service->GetAllGamePads());
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void GamepadEventChannelParent::DispatchUpdateEvent(
|
||||
const GamepadChangeEvent& aEvent) {
|
||||
mBackgroundEventTarget->Dispatch(new SendGamepadUpdateRunnable(this, aEvent),
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ class GamepadEventChannelParent final : public PGamepadEventChannelParent {
|
|||
const uint8_t& aGreen, const uint8_t& aBlue, const uint32_t& aPromiseID);
|
||||
void DispatchUpdateEvent(const GamepadChangeEvent& aEvent);
|
||||
|
||||
mozilla::ipc::IPCResult RecvRequestAllGamepads(
|
||||
RequestAllGamepadsResolver&& aResolver);
|
||||
|
||||
GamepadEventChannelParent(const GamepadEventChannelParent&) = delete;
|
||||
GamepadEventChannelParent(GamepadEventChannelParent&&) = delete;
|
||||
GamepadEventChannelParent& operator=(const GamepadEventChannelParent&) =
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ protocol PGamepadEventChannel {
|
|||
[Tainted] async LightIndicatorColor(GamepadHandle aHandle, uint32_t aLightColorIndex,
|
||||
[NoTaint=allvalid] uint8_t aRed, [NoTaint=allvalid] uint8_t aGreen,
|
||||
[NoTaint=allvalid] uint8_t aBlue, [NoTaint=passback] uint32_t aPromiseID);
|
||||
async RequestAllGamepads()
|
||||
returns (GamepadAdded[] gamepads);
|
||||
|
||||
child:
|
||||
async GamepadUpdate(GamepadChangeEvent aGamepadEvent);
|
||||
|
|
|
|||
|
|
@ -219,6 +219,15 @@ partial interface Navigator {
|
|||
GamepadServiceTest requestGamepadServiceTest();
|
||||
};
|
||||
|
||||
// Chrome-only interface for acquiring all gamepads. Normally, a gamepad can
|
||||
// only become visible if it gets interacted by the user. This function bypasses
|
||||
// this restriction; it allow requesting all gamepad info without user
|
||||
// interacting with the gamepads.
|
||||
partial interface Navigator {
|
||||
[Throws, ChromeOnly]
|
||||
Promise<sequence<Gamepad>> requestAllGamepads();
|
||||
};
|
||||
|
||||
// https://immersive-web.github.io/webvr/spec/1.1/#interface-navigator
|
||||
partial interface Navigator {
|
||||
[NewObject, SecureContext, Pref="dom.vr.enabled"]
|
||||
|
|
|
|||
Loading…
Reference in a new issue