|
Lines 28-44
a/Source/WebCore/Modules/webxr/WebXRSystem.cpp_sec1
|
| 28 |
|
28 |
|
| 29 |
#if ENABLE(WEBXR) |
29 |
#if ENABLE(WEBXR) |
| 30 |
|
30 |
|
|
|
31 |
#include "DOMWindow.h" |
| 31 |
#include "Document.h" |
32 |
#include "Document.h" |
| 32 |
#include "FeaturePolicy.h" |
33 |
#include "FeaturePolicy.h" |
|
|
34 |
#include "IDLTypes.h" |
| 35 |
#include "JSWebXRSession.h" |
| 36 |
#include "JSXRReferenceSpaceType.h" |
| 33 |
#include "PlatformXR.h" |
37 |
#include "PlatformXR.h" |
| 34 |
#include "RuntimeEnabledFeatures.h" |
38 |
#include "RuntimeEnabledFeatures.h" |
|
|
39 |
#include "SecurityOrigin.h" |
| 40 |
#include "UserGestureIndicator.h" |
| 35 |
#include "WebXRSession.h" |
41 |
#include "WebXRSession.h" |
|
|
42 |
#include "XRReferenceSpaceType.h" |
| 43 |
#include "XRSessionInit.h" |
| 44 |
#include <JavaScriptCore/JSGlobalObject.h> |
| 36 |
#include <wtf/IsoMallocInlines.h> |
45 |
#include <wtf/IsoMallocInlines.h> |
|
|
46 |
#include <wtf/Scope.h> |
| 37 |
|
47 |
|
| 38 |
namespace WebCore { |
48 |
namespace WebCore { |
| 39 |
|
49 |
|
| 40 |
WTF_MAKE_ISO_ALLOCATED_IMPL(WebXRSystem); |
50 |
WTF_MAKE_ISO_ALLOCATED_IMPL(WebXRSystem); |
| 41 |
|
51 |
|
|
|
52 |
WebXRSystem::DummyInlineDevice::DummyInlineDevice() |
| 53 |
{ |
| 54 |
setEnabledFeatures(XRSessionMode::Inline, { XRReferenceSpaceType::Viewer }); |
| 55 |
} |
| 56 |
|
| 42 |
Ref<WebXRSystem> WebXRSystem::create(ScriptExecutionContext& scriptExecutionContext) |
57 |
Ref<WebXRSystem> WebXRSystem::create(ScriptExecutionContext& scriptExecutionContext) |
| 43 |
{ |
58 |
{ |
| 44 |
return adoptRef(*new WebXRSystem(scriptExecutionContext)); |
59 |
return adoptRef(*new WebXRSystem(scriptExecutionContext)); |
|
Lines 56-63
WebXRSystem::~WebXRSystem() = default;
a/Source/WebCore/Modules/webxr/WebXRSystem.cpp_sec2
|
| 56 |
void WebXRSystem::ensureImmersiveXRDeviceIsSelected() |
71 |
void WebXRSystem::ensureImmersiveXRDeviceIsSelected() |
| 57 |
{ |
72 |
{ |
| 58 |
// Don't ask platform code for XR devices, we're using simulated ones. |
73 |
// Don't ask platform code for XR devices, we're using simulated ones. |
| 59 |
// TODO: should be have a MockPlatformXR implementation instead ? |
74 |
if (UNLIKELY(m_testingDevices)) |
| 60 |
if (UNLIKELY(m_testingMode)) |
|
|
| 61 |
return; |
75 |
return; |
| 62 |
|
76 |
|
| 63 |
if (m_activeImmersiveDevice) |
77 |
if (m_activeImmersiveDevice) |
|
Lines 96-101
void WebXRSystem::ensureImmersiveXRDeviceIsSelected()
a/Source/WebCore/Modules/webxr/WebXRSystem.cpp_sec3
|
| 96 |
// TODO: 9. Queue a task to fire an event named devicechange on the context object. |
110 |
// TODO: 9. Queue a task to fire an event named devicechange on the context object. |
| 97 |
} |
111 |
} |
| 98 |
|
112 |
|
|
|
113 |
|
| 114 |
PlatformXR::Device* WebXRSystem::obtainCurrentDevice(XRSessionMode mode, const JSFeaturesArray& requiredFeatures, const JSFeaturesArray& optionalFeatures) |
| 115 |
{ |
| 116 |
if (mode == XRSessionMode::ImmersiveAr || mode == XRSessionMode::ImmersiveVr) { |
| 117 |
ensureImmersiveXRDeviceIsSelected(); |
| 118 |
return m_activeImmersiveDevice.get(); |
| 119 |
} |
| 120 |
if (!requiredFeatures.isEmpty() || !optionalFeatures.isEmpty()) |
| 121 |
return m_inlineXRDevice.get(); |
| 122 |
|
| 123 |
return &m_defaultInlineDevice; |
| 124 |
} |
| 125 |
|
| 126 |
|
| 99 |
// https://immersive-web.github.io/webxr/#dom-xrsystem-issessionsupported |
127 |
// https://immersive-web.github.io/webxr/#dom-xrsystem-issessionsupported |
| 100 |
void WebXRSystem::isSessionSupported(XRSessionMode mode, IsSessionSupportedPromise&& promise) |
128 |
void WebXRSystem::isSessionSupported(XRSessionMode mode, IsSessionSupportedPromise&& promise) |
| 101 |
{ |
129 |
{ |
|
Lines 106-112
void WebXRSystem::isSessionSupported(XRSessionMode mode, IsSessionSupportedPromi
a/Source/WebCore/Modules/webxr/WebXRSystem.cpp_sec4
|
| 106 |
return; |
134 |
return; |
| 107 |
} |
135 |
} |
| 108 |
|
136 |
|
| 109 |
// 3. If the requesting document’s origin is not allowed to use the "xr-spatial-tracking" feature policy, |
137 |
// 3. If the requesting document's origin is not allowed to use the "xr-spatial-tracking" feature policy, |
| 110 |
// reject promise with a "SecurityError" DOMException and return it. |
138 |
// reject promise with a "SecurityError" DOMException and return it. |
| 111 |
auto document = downcast<Document>(scriptExecutionContext()); |
139 |
auto document = downcast<Document>(scriptExecutionContext()); |
| 112 |
if (!isFeaturePolicyAllowedByDocumentAndAllOwners(FeaturePolicy::Type::XRSpatialTracking, *document, LogFeaturePolicyFailure::Yes)) { |
140 |
if (!isFeaturePolicyAllowedByDocumentAndAllOwners(FeaturePolicy::Type::XRSpatialTracking, *document, LogFeaturePolicyFailure::Yes)) { |
|
Lines 136-161
void WebXRSystem::isSessionSupported(XRSessionMode mode, IsSessionSupportedPromi
a/Source/WebCore/Modules/webxr/WebXRSystem.cpp_sec5
|
| 136 |
}); |
164 |
}); |
| 137 |
} |
165 |
} |
| 138 |
|
166 |
|
| 139 |
void WebXRSystem::requestSession(XRSessionMode, const XRSessionInit&, RequestSessionPromise&&) |
167 |
// https://immersive-web.github.io/webxr/#immersive-session-request-is-allowed |
|
|
168 |
bool WebXRSystem::immersiveSessionRequestIsAllowedForGlobalObject(DOMWindow& globalObject, Document& document) const |
| 169 |
{ |
| 170 |
// 1. If the request was not made while the global object has transient |
| 171 |
// activation or when launching a web application, return false |
| 172 |
// TODO: add a check for "not launching a web application". |
| 173 |
if (!globalObject.hasTransientActivation()) |
| 174 |
return false; |
| 175 |
|
| 176 |
// 2. If the requesting document is not considered trustworthy, return false. |
| 177 |
// https://immersive-web.github.io/webxr/#trustworthy. |
| 178 |
if (&document != globalObject.document()) |
| 179 |
return false; |
| 180 |
|
| 181 |
// https://immersive-web.github.io/webxr/#active-and-focused |
| 182 |
if (!document.hasFocus() || !document.securityOrigin().isSameOriginAs(globalObject.document()->securityOrigin())) |
| 183 |
return false; |
| 184 |
|
| 185 |
// 3. If user intent to begin an immersive session is not well understood, |
| 186 |
// either via explicit consent or implicit consent, return false |
| 187 |
if (!UserGestureIndicator::processingUserGesture()) |
| 188 |
return false; |
| 189 |
|
| 190 |
return true; |
| 191 |
} |
| 192 |
|
| 193 |
// https://immersive-web.github.io/webxr/#inline-session-request-is-allowed |
| 194 |
bool WebXRSystem::inlineSessionRequestIsAllowedForGlobalObject(DOMWindow& globalObject, Document& document, const XRSessionInit& init) const |
| 195 |
{ |
| 196 |
// 1. If the session request contained any required features or optional features and the request was not made |
| 197 |
// while the global object has transient activation or when launching a web application, return false. |
| 198 |
bool sessionRequestContainedAnyFeature = !init.optionalFeatures.isEmpty() || !init.requiredFeatures.isEmpty(); |
| 199 |
if (sessionRequestContainedAnyFeature && !globalObject.hasTransientActivation() /* TODO: || !launching a web app */) |
| 200 |
return false; |
| 201 |
|
| 202 |
// 2. If the requesting document is not responsible, return false. |
| 203 |
if (&document != globalObject.document()) |
| 204 |
return false; |
| 205 |
|
| 206 |
return true; |
| 207 |
} |
| 208 |
|
| 209 |
|
| 210 |
struct WebXRSystem::ResolvedRequestedFeatures { |
| 211 |
FeaturesArray granted; |
| 212 |
FeaturesArray consentRequired; |
| 213 |
FeaturesArray consentOptional; |
| 214 |
}; |
| 215 |
|
| 216 |
#define RETURN_FALSE_OR_CONTINUE(mustReturn) { \ |
| 217 |
if (mustReturn) {\ |
| 218 |
return false; \ |
| 219 |
} \ |
| 220 |
continue; \ |
| 221 |
} |
| 222 |
|
| 223 |
// https://immersive-web.github.io/webxr/#resolve-the-requested-features |
| 224 |
Optional<WebXRSystem::ResolvedRequestedFeatures> WebXRSystem::resolveRequestedFeatures(XRSessionMode mode, const XRSessionInit& init, PlatformXR::Device* device, JSC::JSGlobalObject& globalObject) const |
| 140 |
{ |
225 |
{ |
| 141 |
PlatformXR::Instance::singleton(); |
226 |
// 1. Let consentRequired be an empty list of DOMString. |
|
|
227 |
// 2. Let consentOptional be an empty list of DOMString. |
| 228 |
ResolvedRequestedFeatures resolvedFeatures; |
| 229 |
|
| 230 |
// 3. Let device be the result of obtaining the current device for mode, requiredFeatures, and optionalFeatures. |
| 231 |
// 4. Let granted be a list of DOMString initialized to device's list of enabled features for mode. |
| 232 |
if (device) |
| 233 |
resolvedFeatures.granted = device->enabledFeatures(mode); |
| 234 |
|
| 235 |
// 5. If device is null or device's list of supported modes does not contain mode, run the following steps: |
| 236 |
// 5.1 Return the tuple (consentRequired, consentOptional, granted) |
| 237 |
if (!device || !device->supports(mode)) |
| 238 |
return resolvedFeatures; |
| 239 |
|
| 240 |
// 6. Add every feature descriptor in the default features table associated |
| 241 |
// with mode to the indicated feature list if it is not already present. |
| 242 |
// https://immersive-web.github.io/webxr/#default-features |
| 243 |
auto requiredFeaturesWithDefaultFeatures = init.requiredFeatures; |
| 244 |
requiredFeaturesWithDefaultFeatures.append(convertEnumerationToJS(globalObject, XRReferenceSpaceType::Viewer)); |
| 245 |
if (mode == XRSessionMode::ImmersiveAr || mode == XRSessionMode::ImmersiveVr) |
| 246 |
requiredFeaturesWithDefaultFeatures.append(convertEnumerationToJS(globalObject, XRReferenceSpaceType::Local)); |
| 247 |
|
| 248 |
// 7. For each feature in requiredFeatures|optionalFeatures perform the following steps: |
| 249 |
// 8. For each feature in optionalFeatures perform the following steps: |
| 250 |
// We're merging both loops in a single lambda. The only difference is that a failure on any required features |
| 251 |
// implies cancelling the whole process while failures in optional features are just skipped. |
| 252 |
enum class ParsingMode { Strict, Loose }; |
| 253 |
auto parseFeatures = [&device, &globalObject, mode, &resolvedFeatures] (const JSFeaturesArray& sessionFeatures, ParsingMode parsingMode) -> bool { |
| 254 |
bool returnOnFailure = parsingMode == ParsingMode::Strict; |
| 255 |
for (const auto& sessionFeature : sessionFeatures) { |
| 256 |
// 1. If the feature is null, continue to the next entry. |
| 257 |
if (sessionFeature.isNull()) |
| 258 |
continue; |
| 259 |
|
| 260 |
// 2. If feature is not a valid feature descriptor, perform the following steps |
| 261 |
// 2.1. Let s be the result of calling ? ToString(feature). |
| 262 |
// 2.2. If s is not a valid feature descriptor or is undefined, (return null|continue to next entry). |
| 263 |
// 2.3. Set feature to s. |
| 264 |
auto feature = parseEnumeration<XRReferenceSpaceType>(globalObject, sessionFeature); |
| 265 |
if (!feature) |
| 266 |
RETURN_FALSE_OR_CONTINUE(returnOnFailure); |
| 267 |
|
| 268 |
// 3. If feature is already in granted, continue to the next entry. |
| 269 |
if (resolvedFeatures.granted.contains(feature.value())) |
| 270 |
continue; |
| 271 |
|
| 272 |
// 4. If the requesting document's origin is not allowed to use any feature policy required by feature |
| 273 |
// as indicated by the feature requirements table, (return null|continue to next entry). |
| 274 |
|
| 275 |
// 5. If session's XR device is not capable of supporting the functionality described by feature or the |
| 276 |
// user agent has otherwise determined to reject the feature, (return null|continue to next entry). |
| 277 |
if (!device->enabledFeatures(mode).contains(feature.value())) |
| 278 |
RETURN_FALSE_OR_CONTINUE(returnOnFailure); |
| 279 |
|
| 280 |
// 6. If the functionality described by feature requires explicit consent, append it to (consentRequired|consentOptional). |
| 281 |
// 7. Else append feature to granted. |
| 282 |
resolvedFeatures.granted.append(feature.value()); |
| 283 |
} |
| 284 |
return true; |
| 285 |
}; |
| 286 |
|
| 287 |
if (!parseFeatures(requiredFeaturesWithDefaultFeatures, ParsingMode::Strict)) |
| 288 |
return WTF::nullopt; |
| 142 |
|
289 |
|
| 143 |
// When the requestSession(mode) method is invoked, the user agent MUST return a new Promise promise and run the following steps in parallel: |
290 |
parseFeatures(init.optionalFeatures, ParsingMode::Loose); |
| 144 |
// 1. Let immersive be true if mode is "immersive-vr" or "immersive-ar", and false otherwise. |
291 |
return resolvedFeatures; |
| 145 |
// 2. If immersive is true: |
292 |
} |
| 146 |
// 1. If pending immersive session is true or active immersive session is not null, reject promise with an "InvalidStateError" DOMException and abort these steps. |
293 |
|
| 147 |
// 2. Else set pending immersive session to be true. |
294 |
// https://immersive-web.github.io/webxr/#request-the-xr-permission |
| 148 |
// 3. Ensure an XR device is selected. |
295 |
bool WebXRSystem::isXRPermissionGranted(XRSessionMode mode, const XRSessionInit& init, PlatformXR::Device* device, JSC::JSGlobalObject& globalObject) const |
| 149 |
// 4. If the XR device is null, reject promise with null. |
296 |
{ |
| 150 |
// 5. Else if the XR device's list of supported modes does not contain mode, reject promise with a "NotSupportedError" DOMException. |
297 |
// 1. Set status's granted to an empty FrozenArray. |
| 151 |
// 6. Else If immersive is true and the algorithm is not triggered by user activation, reject promise with a "SecurityError" DOMException and abort these steps. |
298 |
// 2. Let requiredFeatures be descriptor's requiredFeatures. |
| 152 |
// 7. If promise was rejected and immersive is true, set pending immersive session to false. |
299 |
// 3. Let optionalFeatures be descriptor's optionalFeatures. |
| 153 |
// 8. If promise was rejected, abort these steps. |
300 |
// 4. Let device be the result of obtaining the current device for mode, requiredFeatures, and optionalFeatures. |
| 154 |
// 9. Let session be a new XRSession object. |
301 |
|
| 155 |
// 10. Initialize the session with session and mode. |
302 |
// 5. Let result be the result of resolving the requested features given requiredFeatures,optionalFeatures, and mode. |
| 156 |
// 11. If immersive is true, set the active immersive session to session, and set pending immersive session to false. |
303 |
auto resolvedFeatures = resolveRequestedFeatures(mode, init, device, globalObject); |
| 157 |
// 12. Else append session to the list of inline sessions. |
304 |
|
| 158 |
// 13. Resolve promise with session. |
305 |
// 6. If result is null, run the following steps: |
|
|
306 |
// 6.1. Set status's state to "denied". |
| 307 |
// 6.2. Abort these steps. |
| 308 |
if (!resolvedFeatures) |
| 309 |
return false; |
| 310 |
|
| 311 |
// 7. Let (consentRequired, consentOptional, granted) be the fields of result. |
| 312 |
// 8. The user agent MAY at this point ask the user's permission for the calling algorithm to use any of the features |
| 313 |
// in consentRequired and consentOptional. The results of these prompts should be included when determining if there |
| 314 |
// is a clear signal of user intent for enabling these features. |
| 315 |
// 9. For each feature in consentRequired perform the following steps: |
| 316 |
// 9.1. The user agent MAY at this point ask the user's permission for the calling algorithm to use feature. The results |
| 317 |
// of these prompts should be included when determining if there is a clear signal of user intent to enable feature. |
| 318 |
// 9.2. If a clear signal of user intent to enable feature has not been determined, set status's state to "denied" and |
| 319 |
// abort these steps. |
| 320 |
// 9.3. If feature is not in granted, append feature to granted. |
| 321 |
// 10. For each feature in consentOptional perform the following steps: |
| 322 |
// 10.1. The user agent MAY at this point ask the user's permission for the calling algorithm to use feature. The results |
| 323 |
// of these prompts should be included when determining if there is a clear signal of user intent to enable feature. |
| 324 |
// 10.2. If a clear signal of user intent to enable feature has not been determined, continue to the next entry. |
| 325 |
// 10.3. If feature is not in granted, append feature to granted. |
| 326 |
// 11. Set status's granted to granted. |
| 327 |
// 12. Set device's list of enabled features for mode to granted. |
| 328 |
// 13. Set status's state to "granted". |
| 329 |
return true; |
| 330 |
} |
| 331 |
|
| 332 |
|
| 333 |
// https://immersive-web.github.io/webxr/#dom-xrsystem-requestsession |
| 334 |
void WebXRSystem::requestSession(Document& document, XRSessionMode mode, const XRSessionInit& init, RequestSessionPromise&& promise) |
| 335 |
{ |
| 336 |
// 1. Let promise be a new Promise. |
| 337 |
// 2. Let immersive be true if mode is an immersive session mode, and false otherwise. |
| 338 |
// 3. Let global object be the relevant Global object for the XRSystem on which this method was invoked. |
| 339 |
bool immersive = mode == XRSessionMode::ImmersiveAr || mode == XRSessionMode::ImmersiveVr; |
| 340 |
auto* globalObject = document.domWindow(); |
| 341 |
if (!globalObject) { |
| 342 |
promise.reject(Exception { InvalidAccessError}); |
| 343 |
return; |
| 344 |
} |
| 345 |
|
| 346 |
// 4. Check whether the session request is allowed as follows: |
| 347 |
if (immersive) { |
| 348 |
if (!immersiveSessionRequestIsAllowedForGlobalObject(*globalObject, document)) { |
| 349 |
promise.reject(Exception { SecurityError }); |
| 350 |
return; |
| 351 |
} |
| 352 |
if (m_pendingImmersiveSession || m_activeImmersiveSession) { |
| 353 |
promise.reject(Exception { InvalidStateError }); |
| 354 |
return; |
| 355 |
} |
| 356 |
m_pendingImmersiveSession = true; |
| 357 |
} else { |
| 358 |
if (!inlineSessionRequestIsAllowedForGlobalObject(*globalObject, document, init)) { |
| 359 |
promise.reject(Exception { SecurityError }); |
| 360 |
return; |
| 361 |
} |
| 362 |
} |
| 363 |
|
| 364 |
// 5. Run the following steps in parallel: |
| 365 |
document.postTask([this, immersive, init, mode, promise = WTFMove(promise)] (auto& context) mutable { |
| 366 |
// 5.1 Let requiredFeatures be options' requiredFeatures. |
| 367 |
// 5.2 Let optionalFeatures be options' optionalFeatures. |
| 368 |
// 5.3 Set device to the result of obtaining the current device for mode, requiredFeatures, and optionalFeatures. |
| 369 |
auto* device = obtainCurrentDevice(mode, init.requiredFeatures, init.optionalFeatures); |
| 370 |
|
| 371 |
// 5.4 Queue a task to perform the following steps: |
| 372 |
queueTaskKeepingObjectAlive(*this, TaskSource::WebXR, [this, &context, device = makeWeakPtr(device), immersive, init, mode, promise = WTFMove(promise)] () mutable { |
| 373 |
auto rejectPromiseWithNotSupportedError = makeScopeExit([&] () { |
| 374 |
promise.reject(Exception { NotSupportedError }); |
| 375 |
m_pendingImmersiveSession = false; |
| 376 |
}); |
| 377 |
|
| 378 |
// 5.4.1 If device is null or device's list of supported modes does not contain mode, run the following steps: |
| 379 |
// - Reject promise with a "NotSupportedError" DOMException. |
| 380 |
// - If immersive is true, set pending immersive session to false. |
| 381 |
// - Abort these steps. |
| 382 |
if (!device || !device->supports(mode)) |
| 383 |
return; |
| 384 |
|
| 385 |
auto* globalObject = context.execState(); |
| 386 |
if (!globalObject) |
| 387 |
return; |
| 388 |
|
| 389 |
// WebKit does not currently support the Permissions API. https://w3c.github.io/permissions/ |
| 390 |
// However we do implement here the permission request algorithm without the |
| 391 |
// Permissions API bits as it handles, among others, the session features parsing. We also |
| 392 |
// do it here before creating the session as there is no need to do it on advance. |
| 393 |
// TODO: we just perform basic checks without asking any permission to the user so far. Maybe we should implement |
| 394 |
// a mechanism similar to what others do involving passing a message to the UI process. |
| 395 |
|
| 396 |
// 5.4.4 Let descriptor be an XRPermissionDescriptor initialized with session, requiredFeatures, and optionalFeatures |
| 397 |
// 5.4.5 Let status be an XRPermissionStatus, initially null |
| 398 |
// 5.4.6 Request the xr permission with descriptor and status. |
| 399 |
// 5.4.7 If status' state is "denied" run the following steps: (same as above in 5.4.1) |
| 400 |
if (!isXRPermissionGranted(mode, init, device.get(), *globalObject)) |
| 401 |
return; |
| 402 |
|
| 403 |
// 5.4.2 Let session be a new XRSession object. |
| 404 |
// 5.4.3 Initialize the session with session, mode, and device. |
| 405 |
ASSERT(is<Document>(context.get())); |
| 406 |
auto session = WebXRSession::create(downcast<Document>(context), *this, mode, WTFMove(device)); |
| 407 |
|
| 408 |
// 5.4.8 Potentially set the active immersive session as follows: |
| 409 |
if (immersive) { |
| 410 |
m_activeImmersiveSession = session.copyRef(); |
| 411 |
m_pendingImmersiveSession = false; |
| 412 |
} else |
| 413 |
m_listOfInlineSessions.append(session.copyRef()); |
| 414 |
|
| 415 |
// 5.4.9 Resolve promise with session. |
| 416 |
promise.resolve(session); |
| 417 |
rejectPromiseWithNotSupportedError.release(); |
| 418 |
|
| 419 |
// TODO: |
| 420 |
// 5.4.10 Queue a task to perform the following steps: NOTE: These steps ensure that initial inputsourceschange |
| 421 |
// events occur after the initial session is resolved. |
| 422 |
// 1. Set session's promise resolved flag to true. |
| 423 |
// 2. Let sources be any existing input sources attached to session. |
| 424 |
// 3. If sources is non-empty, perform the following steps: |
| 425 |
// 1. Set session's list of active XR input sources to sources. |
| 426 |
// 2. Fire an XRInputSourcesChangeEvent named inputsourceschange on session with added set to sources. |
| 427 |
|
| 428 |
}); |
| 429 |
}); |
| 159 |
} |
430 |
} |
| 160 |
|
431 |
|
| 161 |
const char* WebXRSystem::activeDOMObjectName() const |
432 |
const char* WebXRSystem::activeDOMObjectName() const |
|
Lines 171-177
void WebXRSystem::registerSimulatedXRDeviceForTesting(const PlatformXR::Device&
a/Source/WebCore/Modules/webxr/WebXRSystem.cpp_sec6
|
| 171 |
{ |
442 |
{ |
| 172 |
if (!RuntimeEnabledFeatures::sharedFeatures().webXREnabled()) |
443 |
if (!RuntimeEnabledFeatures::sharedFeatures().webXREnabled()) |
| 173 |
return; |
444 |
return; |
| 174 |
m_testingMode = true; |
445 |
m_testingDevices++; |
| 175 |
if (device.supports(PlatformXR::SessionMode::ImmersiveVr) || device.supports(PlatformXR::SessionMode::ImmersiveAr)) { |
446 |
if (device.supports(PlatformXR::SessionMode::ImmersiveVr) || device.supports(PlatformXR::SessionMode::ImmersiveAr)) { |
| 176 |
m_immersiveDevices.append(makeWeakPtr(device)); |
447 |
m_immersiveDevices.append(makeWeakPtr(device)); |
| 177 |
m_activeImmersiveDevice = m_immersiveDevices.last(); |
448 |
m_activeImmersiveDevice = m_immersiveDevices.last(); |
|
Lines 185-198
void WebXRSystem::unregisterSimulatedXRDeviceForTesting(PlatformXR::Device* devi
a/Source/WebCore/Modules/webxr/WebXRSystem.cpp_sec7
|
| 185 |
if (!RuntimeEnabledFeatures::sharedFeatures().webXREnabled()) |
456 |
if (!RuntimeEnabledFeatures::sharedFeatures().webXREnabled()) |
| 186 |
return; |
457 |
return; |
| 187 |
ASSERT(m_immersiveDevices.contains(device)); |
458 |
ASSERT(m_immersiveDevices.contains(device)); |
|
|
459 |
ASSERT(m_testingDevices); |
| 188 |
m_immersiveDevices.removeFirst(device); |
460 |
m_immersiveDevices.removeFirst(device); |
| 189 |
if (m_activeImmersiveDevice == device) |
461 |
if (m_activeImmersiveDevice == device) |
| 190 |
m_activeImmersiveDevice = nullptr; |
462 |
m_activeImmersiveDevice = nullptr; |
| 191 |
if (m_inlineXRDevice == device) |
463 |
if (m_inlineXRDevice == device) |
| 192 |
m_inlineXRDevice = makeWeakPtr(m_defaultInlineDevice); |
464 |
m_inlineXRDevice = makeWeakPtr(m_defaultInlineDevice); |
| 193 |
m_testingMode = false; |
465 |
m_testingDevices--; |
| 194 |
} |
466 |
} |
| 195 |
|
467 |
|
|
|
468 |
void WebXRSystem::sessionEnded(const WebXRSession* session) |
| 469 |
{ |
| 470 |
if (m_activeImmersiveSession == session) |
| 471 |
m_activeImmersiveSession = nullptr; |
| 472 |
|
| 473 |
m_listOfInlineSessions.removeFirstMatching([session](auto& item) { |
| 474 |
return item.ptr() == session; |
| 475 |
}); |
| 476 |
} |
| 196 |
|
477 |
|
| 197 |
} // namespace WebCore |
478 |
} // namespace WebCore |
| 198 |
|
479 |
|