133void VRDisplay::rejectRequestAndStopPresenting(Ref<DeferredPromise>& promise, ExceptionCode exceptionCode, const String& message)
134{
135 promise->reject(Exception { exceptionCode, message });
136 if (m_presentingLayer)
137 stopPresenting();
138}
139
140void VRDisplay::requestPresent(const Vector<VRLayerInit>& layers, Ref<DeferredPromise>&& promise)
141{
142 if (!m_capabilities->canPresent()) {
143 rejectRequestAndStopPresenting(promise, NotSupportedError, ASCIILiteral("VRDisplay cannot present"));
144 return;
145 }
146
147 if (!layers.size() || layers.size() > m_capabilities->maxLayers()) {
148 rejectRequestAndStopPresenting(promise, InvalidStateError, ASCIILiteral(layers.size() ? "Too many layers" : "Not enough layers"));
149 return;
150 }
151
152 if (!m_presentingLayer && !UserGestureIndicator::processingUserGesture()) {
153 rejectRequestAndStopPresenting(promise, InvalidAccessError, ASCIILiteral("Must request presentation from a user gesture handler."));
154 return;
155 }
156
157 RELEASE_ASSERT(layers.size() == 1);
158 auto layer = layers[0];
159
160 if (!layer.source) {
161 rejectRequestAndStopPresenting(promise, InvalidStateError, ASCIILiteral("Layer does not contain any source"));
162 return;
163 }
164
165 auto* canvasContext = layer.source->getContext("webgl");
166 if (!canvasContext || !canvasContext->isWebGL()) {
167 rejectRequestAndStopPresenting(promise, NotSupportedError, ASCIILiteral("WebVR requires VRLayerInit with WebGL context."));
168 return;
169 }
170
171 if ((layer.leftBounds.size() && layer.leftBounds.size() != 4)
172 || (layer.rightBounds.size() && layer.rightBounds.size() != 4)) {
173 rejectRequestAndStopPresenting(promise, InvalidStateError, ASCIILiteral("Layer bounds must be either 0 or 4"));
174 return;
175 }
176
177 m_presentingLayer = layer;
178 promise->resolve();
179}
180
181void VRDisplay::stopPresenting()