void ScriptRunner::executeScripts() { RefPtrWillBeRawPtr<Document> protect(m_document.get()); WillBeHeapDeque<RawPtrWillBeMember<ScriptLoader>> scriptLoaders; scriptLoaders.swap(m_scriptsToExecuteSoon); WillBeHeapHashSet<RawPtrWillBeMember<ScriptLoader>> inorderSet; while (!m_scriptsToExecuteInOrder.isEmpty() && m_scriptsToExecuteInOrder.first()->isReady()) { ScriptLoader* script = m_scriptsToExecuteInOrder.takeFirst(); inorderSet.add(script); scriptLoaders.append(script); } while (!scriptLoaders.isEmpty()) { scriptLoaders.takeFirst()->execute(); m_document->decrementLoadEventDelayCount(); if (yieldForHighPriorityWork()) break; } // If we have to yield, we must re-enqueue any scriptLoaders back onto the front of // m_scriptsToExecuteInOrder or m_scriptsToExecuteSoon depending on where the script // came from. // NOTE a yield followed by a notifyScriptReady(... ASYNC_EXECUTION) will result in that script executing // before any pre-existing ScriptsToExecuteInOrder. while (!scriptLoaders.isEmpty()) { ScriptLoader* script = scriptLoaders.takeLast(); if (inorderSet.contains(script)) m_scriptsToExecuteInOrder.prepend(script); else m_scriptsToExecuteSoon.prepend(script); } }
void Fullscreen::eventQueueTimerFired(Timer<Fullscreen>*) { // Since we dispatch events in this function, it's possible that the // document will be detached and GC'd. We protect it here to make sure we // can finish the function successfully. RefPtrWillBeRawPtr<Document> protectDocument(document()); WillBeHeapDeque<RefPtrWillBeMember<Event> > eventQueue; m_eventQueue.swap(eventQueue); while (!eventQueue.isEmpty()) { RefPtrWillBeRawPtr<Event> event = eventQueue.takeFirst(); Node* target = event->target()->toNode(); // If the element was removed from our tree, also message the documentElement. if (!target->inDocument() && document()->documentElement()) { ASSERT(isPrefixed(event->type())); eventQueue.append(createEvent(event->type(), *document()->documentElement())); } target->dispatchEvent(event); } }
void FullscreenElementStack::fullScreenChangeDelayTimerFired(Timer<FullscreenElementStack>*) { // Since we dispatch events in this function, it's possible that the // document will be detached and GC'd. We protect it here to make sure we // can finish the function successfully. RefPtrWillBeRawPtr<Document> protectDocument(document()); WillBeHeapDeque<RefPtrWillBeMember<Node> > changeQueue; m_fullScreenChangeEventTargetQueue.swap(changeQueue); WillBeHeapDeque<RefPtrWillBeMember<Node> > errorQueue; m_fullScreenErrorEventTargetQueue.swap(errorQueue); while (!changeQueue.isEmpty()) { RefPtrWillBeRawPtr<Node> node = changeQueue.takeFirst(); if (!node) node = document()->documentElement(); // The dispatchEvent below may have blown away our documentElement. if (!node) continue; // If the element was removed from our tree, also message the documentElement. Since we may // have a document hierarchy, check that node isn't in another document. if (!document()->contains(node.get()) && !node->inDocument()) changeQueue.append(document()->documentElement()); node->dispatchEvent(Event::createBubble(EventTypeNames::webkitfullscreenchange)); } while (!errorQueue.isEmpty()) { RefPtrWillBeRawPtr<Node> node = errorQueue.takeFirst(); if (!node) node = document()->documentElement(); // The dispatchEvent below may have blown away our documentElement. if (!node) continue; // If the element was removed from our tree, also message the documentElement. Since we may // have a document hierarchy, check that node isn't in another document. if (!document()->contains(node.get()) && !node->inDocument()) errorQueue.append(document()->documentElement()); node->dispatchEvent(Event::createBubble(EventTypeNames::webkitfullscreenerror)); } }
void WebSocket::EventQueue::dispatchQueuedEvents() { if (m_state != Active) return; RefPtrWillBeRawPtr<EventQueue> protect(this); WillBeHeapDeque<RefPtrWillBeMember<Event> > events; events.swap(m_events); while (!events.isEmpty()) { if (m_state == Stopped || m_state == Suspended) break; ASSERT(m_state == Active); ASSERT(m_target->executionContext()); m_target->dispatchEvent(events.takeFirst()); // |this| can be stopped here. } if (m_state == Suspended) { while (!m_events.isEmpty()) events.append(m_events.takeFirst()); events.swap(m_events); } }
void Fullscreen::exitFullscreen() { // The exitFullscreen() method must run these steps: // 1. Let doc be the context object. (i.e. "this") Document* currentDoc = document(); if (!currentDoc->isActive()) return; // 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. WillBeHeapDeque<RefPtrWillBeMember<Document> > descendants; for (Frame* descendant = document()->frame() ? document()->frame()->tree().traverseNext() : 0; descendant; descendant = descendant->tree().traverseNext()) { if (!descendant->isLocalFrame()) continue; ASSERT(toLocalFrame(descendant)->document()); if (fullscreenElementFrom(*toLocalFrame(descendant)->document())) descendants.prepend(toLocalFrame(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 (WillBeHeapDeque<RefPtrWillBeMember<Document> >::iterator i = descendants.begin(); i != descendants.end(); ++i) { ASSERT(*i); RequestType requestType = from(**i).m_fullScreenElementStack.last().second; from(**i).clearFullscreenElementStack(); enqueueChangeEvent(**i, requestType); } // 5. While doc is not null, run these substeps: Element* newTop = 0; while (currentDoc) { RequestType requestType = from(*currentDoc).m_fullScreenElementStack.last().second; // 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. enqueueChangeEvent(*currentDoc, requestType); // 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. FrameHost* host = document()->frameHost(); // Speculative fix for engaget.com/videos per crbug.com/336239. // FIXME: This check is wrong. We ASSERT(document->isActive()) above // so this should be redundant and should be removed! if (!host) return; // Only exit out of full screen window mode if there are no remaining elements in the // full screen stack. if (!newTop) { // FIXME: if the frame exiting fullscreen is not the frame that entered // fullscreen (but a parent frame for example), m_fullScreenElement // might be null. We want to pass an element that is part of the // document so we will pass the documentElement in that case. // This should be fix by exiting fullscreen for a frame instead of an // element, see https://crbug.com/441259 host->chrome().client().exitFullScreenForElement( m_fullScreenElement ? m_fullScreenElement.get() : document()->documentElement()); return; } // Otherwise, notify the chrome of the new full screen element. host->chrome().client().enterFullScreenForElement(newTop); }