void IDBDatabaseBackend::processPendingOpenCalls(bool success) { // Open calls can be requeued if an open call started a version change transaction or deletes the database. Deque<OwnPtr<IDBPendingOpenCall>> pendingOpenCalls; m_pendingOpenCalls.swap(pendingOpenCalls); while (!pendingOpenCalls.isEmpty()) { OwnPtr<IDBPendingOpenCall> pendingOpenCall = pendingOpenCalls.takeFirst(); if (success) { if (m_metadata.id == InvalidId) { // This database was deleted then quickly re-opened. // openInternalAsync() will recreate it in the backing store and then resume processing pending callbacks. pendingOpenCalls.prepend(pendingOpenCall.release()); pendingOpenCalls.swap(m_pendingOpenCalls); openInternalAsync(); return; } openConnectionInternal(pendingOpenCall->callbacks(), pendingOpenCall->databaseCallbacks(), pendingOpenCall->transactionId(), pendingOpenCall->version()); } else { String message; if (pendingOpenCall->version() == IDBDatabaseMetadata::NoIntVersion) message = "Internal error opening database with no version specified."; else message = String::format("Internal error opening database with version %llu", static_cast<unsigned long long>(pendingOpenCall->version())); pendingOpenCall->callbacks()->onError(IDBDatabaseError::create(IDBDatabaseException::UnknownError, message)); } } }
TEST(WTF_Deque, Remove) { Deque<int> deque; deque.append(11); deque.prepend(10); deque.append(12); deque.append(13); EXPECT_EQ(10, deque.first()); EXPECT_EQ(13, deque.last()); deque.removeLast(); EXPECT_EQ(10, deque.first()); EXPECT_EQ(12, deque.last()); deque.removeFirst(); EXPECT_EQ(11, deque.first()); EXPECT_EQ(12, deque.last()); deque.removeFirst(); EXPECT_EQ(12, deque.first()); EXPECT_EQ(12, deque.last()); deque.removeLast(); EXPECT_TRUE(deque.isEmpty()); }
TEST(WTF_Deque, MoveOnly) { Deque<MoveOnly> deque; deque.append(MoveOnly(1)); deque.prepend(MoveOnly(0)); EXPECT_EQ(0U, deque.first().value()); EXPECT_EQ(1U, deque.last().value()); auto first = deque.takeFirst(); EXPECT_EQ(0U, first.value()); auto last = deque.takeLast(); EXPECT_EQ(1U, last.value()); }
TEST(WTF, DequeReverseIterator) { Deque<int> deque; deque.append(11); deque.prepend(10); deque.append(12); deque.append(13); Deque<int>::reverse_iterator it = deque.rbegin(); Deque<int>::reverse_iterator end = deque.rend(); EXPECT_TRUE(end != it); EXPECT_EQ(13, *it); ++it; EXPECT_EQ(12, *it); ++it; EXPECT_EQ(11, *it); ++it; EXPECT_EQ(10, *it); ++it; EXPECT_TRUE(end == it); }
TEST(WTF_Deque, Iterator) { Deque<int> deque; deque.append(11); deque.prepend(10); deque.append(12); deque.append(13); Deque<int>::iterator it = deque.begin(); Deque<int>::iterator end = deque.end(); EXPECT_TRUE(end != it); EXPECT_EQ(10, *it); ++it; EXPECT_EQ(11, *it); ++it; EXPECT_EQ(12, *it); ++it; EXPECT_EQ(13, *it); ++it; EXPECT_TRUE(end == it); }
void FullscreenElementStack::webkitExitFullscreen() { // The exitFullscreen() method must run these steps: // 1. Let doc be the context object. (i.e. "this") Document* currentDoc = document(); // 2. If doc's fullscreen element stack is empty, terminate these steps. if (m_fullScreenElementStack.isEmpty()) return; // 3. Let descendants be all the doc's descendant browsing context's documents with a non-empty fullscreen // element stack (if any), ordered so that the child of the doc is last and the document furthest // away from the doc is first. Deque<RefPtr<Document> > descendants; for (Frame* descendant = document()->frame() ? document()->frame()->tree()->traverseNext() : 0; descendant; descendant = descendant->tree()->traverseNext()) { if (fullscreenElementFrom(descendant->document())) descendants.prepend(descendant->document()); } // 4. For each descendant in descendants, empty descendant's fullscreen element stack, and queue a // task to fire an event named fullscreenchange with its bubbles attribute set to true on descendant. for (Deque<RefPtr<Document> >::iterator i = descendants.begin(); i != descendants.end(); ++i) { from(i->get())->clearFullscreenElementStack(); addDocumentToFullScreenChangeEventQueue(i->get()); } // 5. While doc is not null, run these substeps: Element* newTop = 0; while (currentDoc) { // 1. Pop the top element of doc's fullscreen element stack. from(currentDoc)->popFullscreenElementStack(); // If doc's fullscreen element stack is non-empty and the element now at the top is either // not in a document or its node document is not doc, repeat this substep. newTop = fullscreenElementFrom(currentDoc); if (newTop && (!newTop->inDocument() || &newTop->document() != currentDoc)) continue; // 2. Queue a task to fire an event named fullscreenchange with its bubbles attribute set to true // on doc. addDocumentToFullScreenChangeEventQueue(currentDoc); // 3. If doc's fullscreen element stack is empty and doc's browsing context has a browsing context // container, set doc to that browsing context container's node document. if (!newTop && currentDoc->ownerElement()) { currentDoc = ¤tDoc->ownerElement()->document(); continue; } // 4. Otherwise, set doc to null. currentDoc = 0; } // 6. Return, and run the remaining steps asynchronously. // 7. Optionally, perform some animation. if (!document()->page()) return; // Only exit out of full screen window mode if there are no remaining elements in the // full screen stack. if (!newTop) { document()->page()->chrome().client().exitFullScreenForElement(m_fullScreenElement.get()); return; } // Otherwise, notify the chrome of the new full screen element. document()->page()->chrome().client().enterFullScreenForElement(newTop); }
void FullscreenElementStack::requestFullScreenForElement(Element* element, unsigned short flags, FullScreenCheckType checkType) { // The Mozilla Full Screen API <https://wiki.mozilla.org/Gecko:FullScreenAPI> has different requirements // for full screen mode, and do not have the concept of a full screen element stack. bool inLegacyMozillaMode = (flags & Element::LEGACY_MOZILLA_REQUEST); do { if (!element) element = document()->documentElement(); // 1. If any of the following conditions are true, terminate these steps and queue a task to fire // an event named fullscreenerror with its bubbles attribute set to true on the context object's // node document: // The context object is not in a document. if (!element->inDocument()) break; // The context object's node document, or an ancestor browsing context's document does not have // the fullscreen enabled flag set. if (checkType == EnforceIFrameAllowFullScreenRequirement && !fullScreenIsAllowedForElement(element)) break; // The context object's node document fullscreen element stack is not empty and its top element // is not an ancestor of the context object. (NOTE: Ignore this requirement if the request was // made via the legacy Mozilla-style API.) if (!m_fullScreenElementStack.isEmpty() && !inLegacyMozillaMode) { Element* lastElementOnStack = m_fullScreenElementStack.last().get(); if (lastElementOnStack == element || !lastElementOnStack->contains(element)) break; } // A descendant browsing context's document has a non-empty fullscreen element stack. bool descendentHasNonEmptyStack = false; for (Frame* descendant = document()->frame() ? document()->frame()->tree()->traverseNext() : 0; descendant; descendant = descendant->tree()->traverseNext()) { if (fullscreenElementFrom(descendant->document())) { descendentHasNonEmptyStack = true; break; } } if (descendentHasNonEmptyStack && !inLegacyMozillaMode) break; // This algorithm is not allowed to show a pop-up: // An algorithm is allowed to show a pop-up if, in the task in which the algorithm is running, either: // - an activation behavior is currently being processed whose click event was trusted, or // - the event listener for a trusted click event is being handled. if (!ScriptController::processingUserGesture()) break; UserGestureIndicator::consumeUserGesture(); // There is a previously-established user preference, security risk, or platform limitation. if (!document()->page() || !document()->page()->settings().fullScreenEnabled()) break; // 2. Let doc be element's node document. (i.e. "this") Document* currentDoc = document(); // 3. Let docs be all doc's ancestor browsing context's documents (if any) and doc. Deque<Document*> docs; do { docs.prepend(currentDoc); currentDoc = currentDoc->ownerElement() ? ¤tDoc->ownerElement()->document() : 0; } while (currentDoc); // 4. For each document in docs, run these substeps: Deque<Document*>::iterator current = docs.begin(), following = docs.begin(); do { ++following; // 1. Let following document be the document after document in docs, or null if there is no // such document. Document* currentDoc = *current; Document* followingDoc = following != docs.end() ? *following : 0; // 2. If following document is null, push context object on document's fullscreen element // stack, and queue a task to fire an event named fullscreenchange with its bubbles attribute // set to true on the document. if (!followingDoc) { from(currentDoc)->pushFullscreenElementStack(element); addDocumentToFullScreenChangeEventQueue(currentDoc); continue; } // 3. Otherwise, if document's fullscreen element stack is either empty or its top element // is not following document's browsing context container, Element* topElement = fullscreenElementFrom(currentDoc); if (!topElement || topElement != followingDoc->ownerElement()) { // ...push following document's browsing context container on document's fullscreen element // stack, and queue a task to fire an event named fullscreenchange with its bubbles attribute // set to true on document. from(currentDoc)->pushFullscreenElementStack(followingDoc->ownerElement()); addDocumentToFullScreenChangeEventQueue(currentDoc); continue; } // 4. Otherwise, do nothing for this document. It stays the same. } while (++current != docs.end()); // 5. Return, and run the remaining steps asynchronously. // 6. Optionally, perform some animation. m_areKeysEnabledInFullScreen = flags & Element::ALLOW_KEYBOARD_INPUT; document()->page()->chrome().client().enterFullScreenForElement(element); // 7. Optionally, display a message indicating how the user can exit displaying the context object fullscreen. return; } while (0); m_fullScreenErrorEventTargetQueue.append(element ? element : document()->documentElement()); m_fullScreenChangeDelayTimer.startOneShot(0); }
void Fullscreen::requestFullscreen(Element& element, RequestType requestType) { // Ignore this request if the document is not in a live frame. if (!document()->isActive()) return; // If |element| is on top of |doc|'s fullscreen element stack, terminate these substeps. if (&element == fullscreenElement()) return; do { // 1. If any of the following conditions are true, terminate these steps and queue a task to fire // an event named fullscreenerror with its bubbles attribute set to true on the context object's // node document: // The fullscreen element ready check returns false. if (!fullscreenElementReady(element, requestType)) break; // This algorithm is not allowed to show a pop-up: // An algorithm is allowed to show a pop-up if, in the task in which the algorithm is running, either: // - an activation behavior is currently being processed whose click event was trusted, or // - the event listener for a trusted click event is being handled. if (!UserGestureIndicator::processingUserGesture() && !document()->frame()->isNodeJS()) { String message = ExceptionMessages::failedToExecute("requestFullScreen", "Element", "API can only be initiated by a user gesture."); document()->executionContext()->addConsoleMessage( ConsoleMessage::create(JSMessageSource, WarningMessageLevel, message)); break; } // Fullscreen is not supported. if (!fullscreenIsSupported(element.document())) break; // 2. Let doc be element's node document. (i.e. "this") Document* currentDoc = document(); // 3. Let docs be all doc's ancestor browsing context's documents (if any) and doc. Deque<Document*> docs; do { docs.prepend(currentDoc); currentDoc = currentDoc->ownerElement() ? ¤tDoc->ownerElement()->document() : 0; } while (currentDoc); // 4. For each document in docs, run these substeps: Deque<Document*>::iterator current = docs.begin(), following = docs.begin(); do { ++following; // 1. Let following document be the document after document in docs, or null if there is no // such document. Document* currentDoc = *current; Document* followingDoc = following != docs.end() ? *following : 0; // 2. If following document is null, push context object on document's fullscreen element // stack, and queue a task to fire an event named fullscreenchange with its bubbles attribute // set to true on the document. if (!followingDoc) { from(*currentDoc).pushFullscreenElementStack(element, requestType); enqueueChangeEvent(*currentDoc, requestType); continue; } // 3. Otherwise, if document's fullscreen element stack is either empty or its top element // is not following document's browsing context container, Element* topElement = fullscreenElementFrom(*currentDoc); if (!topElement || topElement != followingDoc->ownerElement()) { // ...push following document's browsing context container on document's fullscreen element // stack, and queue a task to fire an event named fullscreenchange with its bubbles attribute // set to true on document. from(*currentDoc).pushFullscreenElementStack(*followingDoc->ownerElement(), requestType); enqueueChangeEvent(*currentDoc, requestType); continue; } // 4. Otherwise, do nothing for this document. It stays the same. } while (++current != docs.end()); // 5. Return, and run the remaining steps asynchronously. // 6. Optionally, perform some animation. document()->frameHost()->chrome().client().enterFullScreenForElement(&element); // 7. Optionally, display a message indicating how the user can exit displaying the context object fullscreen. return; } while (0); enqueueErrorEvent(element, requestType); }