summaryrefslogtreecommitdiffstats
path: root/dom/vr/XRSystem.h
blob: 2a49dfb68f883b34114b3de66f40d801d12130e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 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_XRsystem_h_
#define mozilla_dom_XRsystem_h_

#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/dom/WebXRBinding.h"
#include "nsContentPermissionHelper.h"
#include "VRManagerChild.h"

#include "gfxVR.h"

namespace mozilla::dom {

struct XRSessionCreationOptions;

class IsSessionSupportedRequest {
 public:
  IsSessionSupportedRequest(XRSessionMode aSessionMode, Promise* aPromise)
      : mPromise(aPromise), mSessionMode(aSessionMode) {}
  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(IsSessionSupportedRequest)
  NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(IsSessionSupportedRequest)

  RefPtr<Promise> mPromise;
  XRSessionMode GetSessionMode() const;

 private:
  ~IsSessionSupportedRequest() = default;
  XRSessionMode mSessionMode;
};

class RequestSessionRequest {
 public:
  RequestSessionRequest(
      XRSessionMode aSessionMode, uint32_t aPresentationGroup,
      Promise* aPromise,
      const nsTArray<XRReferenceSpaceType>& aRequiredReferenceSpaceTypes,
      const nsTArray<XRReferenceSpaceType>& aOptionalReferenceSpaceTypes);
  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(RequestSessionRequest)
  NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(RequestSessionRequest)
  RefPtr<Promise> mPromise;

  bool ResolveSupport(
      const gfx::VRDisplayClient* aDisplay,
      nsTArray<XRReferenceSpaceType>& aEnabledReferenceSpaceTypes) const;
  bool IsImmersive() const;
  bool WantsHardware() const;
  bool NeedsHardware() const;
  XRSessionMode GetSessionMode() const;
  uint32_t GetPresentationGroup() const;

 private:
  ~RequestSessionRequest() = default;
  XRSessionMode mSessionMode;
  uint32_t mPresentationGroup;
  nsTArray<XRReferenceSpaceType> mRequiredReferenceSpaceTypes;
  nsTArray<XRReferenceSpaceType> mOptionalReferenceSpaceTypes;
};

class XRRequestSessionPermissionRequest final
    : public ContentPermissionRequestBase {
 public:
  NS_DECL_ISUPPORTS_INHERITED
  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(XRRequestSessionPermissionRequest,
                                           ContentPermissionRequestBase)

  // nsIContentPermissionRequest
  NS_IMETHOD Cancel(void) override;
  NS_IMETHOD Allow(JS::Handle<JS::Value> choices) override;

  using AllowCallback = std::function<void()>;
  using AllowAnySiteCallback = std::function<void()>;
  using CancelCallback = std::function<void()>;

  static already_AddRefed<XRRequestSessionPermissionRequest> Create(
      nsPIDOMWindowInner* aWindow, AllowCallback&& aAllowCallback,
      AllowAnySiteCallback&& aAllowAnySiteCallback,
      CancelCallback&& aCancelCallback);

  using AutoGrantDelayPromise = MozPromise<bool, bool, true>;
  RefPtr<AutoGrantDelayPromise> MaybeDelayAutomaticGrants();

 private:
  XRRequestSessionPermissionRequest(
      nsPIDOMWindowInner* aWindow, nsIPrincipal* aNodePrincipal,
      AllowCallback&& aAllowCallback,
      AllowAnySiteCallback&& aAllowAnySiteCallback,
      CancelCallback&& aCancelCallback);
  ~XRRequestSessionPermissionRequest();

  AllowCallback mAllowCallback;
  AllowAnySiteCallback mAllowAnySiteCallback;
  CancelCallback mCancelCallback;
  nsTArray<PermissionRequest> mPermissionRequests;
  bool mCallbackCalled;
};

class XRSystem final : public DOMEventTargetHelper,
                       public gfx::VRManagerEventObserver {
 public:
  NS_DECL_ISUPPORTS_INHERITED
  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(XRSystem, DOMEventTargetHelper)

  void Shutdown();
  void SessionEnded(XRSession* aSession);
  bool FeaturePolicyBlocked() const;
  bool OnXRPermissionRequestAllow();
  void OnXRPermissionRequestCancel();
  bool HasActiveImmersiveSession() const;

  // WebIDL Boilerplate
  static already_AddRefed<XRSystem> Create(nsPIDOMWindowInner* aWindow);
  JSObject* WrapObject(JSContext* aCx,
                       JS::Handle<JSObject*> aGivenProto) override;

  // WebIDL Members
  already_AddRefed<Promise> IsSessionSupported(XRSessionMode aMode,
                                               ErrorResult& aRv);
  already_AddRefed<Promise> RequestSession(JSContext* aCx, XRSessionMode aMode,
                                           const XRSessionInit& aOptions,
                                           CallerType aCallerType,
                                           ErrorResult& aRv);
  IMPL_EVENT_HANDLER(devicechange);

  // VRManagerEventObserver interface
  void NotifyVRDisplayMounted(uint32_t aDisplayID) override;
  void NotifyVRDisplayUnmounted(uint32_t aDisplayID) override;
  void NotifyVRDisplayConnect(uint32_t aDisplayID) override;
  void NotifyVRDisplayDisconnect(uint32_t aDisplayID) override;
  void NotifyVRDisplayPresentChange(uint32_t aDisplayID) override;
  void NotifyPresentationGenerationChanged(uint32_t aDisplayID) override;
  void NotifyEnumerationCompleted() override;
  void NotifyDetectRuntimesCompleted() override;
  bool GetStopActivityStatus() const override;

 private:
  explicit XRSystem(nsPIDOMWindowInner* aWindow);
  virtual ~XRSystem() = default;
  void ResolveIsSessionSupportedRequests();
  void ProcessSessionRequestsWaitingForRuntimeDetection();
  bool CancelHardwareRequest(RequestSessionRequest* aRequest);
  void QueueSessionRequestWithEnumeration(RequestSessionRequest* aRequest);
  void QueueSessionRequestWithoutEnumeration(RequestSessionRequest* aRequest);
  void ResolveSessionRequestsWithoutHardware();
  void ResolveSessionRequests(
      nsTArray<RefPtr<RequestSessionRequest>>& aRequests,
      const nsTArray<RefPtr<gfx::VRDisplayClient>>& aDisplays);

  bool mShuttingDown;
  // https://immersive-web.github.io/webxr/#pending-immersive-session
  bool mPendingImmersiveSession;
  // https://immersive-web.github.io/webxr/#active-immersive-session
  RefPtr<XRSession> mActiveImmersiveSession;
  // https://immersive-web.github.io/webxr/#list-of-inline-sessions
  nsTArray<RefPtr<XRSession>> mInlineSessions;

  bool mEnumerationInFlight;

  nsTArray<RefPtr<IsSessionSupportedRequest>> mIsSessionSupportedRequests;
  nsTArray<RefPtr<RequestSessionRequest>>
      mRequestSessionRequestsWithoutHardware;
  nsTArray<RefPtr<RequestSessionRequest>>
      mRequestSessionRequestsWaitingForRuntimeDetection;
  nsTArray<RefPtr<RequestSessionRequest>>
      mRequestSessionRequestsWaitingForEnumeration;
};

}  // namespace mozilla::dom

#endif  // mozilla_dom_XRsystem_h_