void AnimationTimeline::serviceAnimations(TimingUpdateReason reason) { TRACE_EVENT0("blink", "AnimationTimeline::serviceAnimations"); m_lastCurrentTimeInternal = currentTimeInternal(); m_timing->cancelWake(); WillBeHeapVector<RawPtrWillBeMember<Animation>> animations; animations.reserveInitialCapacity(m_animationsNeedingUpdate.size()); for (RefPtrWillBeMember<Animation> animation : m_animationsNeedingUpdate) animations.append(animation.get()); std::sort(animations.begin(), animations.end(), Animation::hasLowerPriority); for (Animation* animation : animations) { if (!animation->update(reason)) m_animationsNeedingUpdate.remove(animation); } ASSERT(m_outdatedAnimationCount == 0); #if ENABLE(ASSERT) for (const auto& animation : m_animationsNeedingUpdate) ASSERT(!animation->outdated()); #endif }
void AnimationTimeline::serviceAnimations(TimingUpdateReason reason) { TRACE_EVENT0("webkit", "AnimationTimeline::serviceAnimations"); m_timing->cancelWake(); double timeToNextEffect = std::numeric_limits<double>::infinity(); WillBeHeapVector<RawPtrWillBeMember<AnimationPlayer> > players; for (WillBeHeapHashSet<RefPtrWillBeMember<AnimationPlayer> >::iterator it = m_playersNeedingUpdate.begin(); it != m_playersNeedingUpdate.end(); ++it) players.append(it->get()); std::sort(players.begin(), players.end(), AnimationPlayer::hasLowerPriority); for (size_t i = 0; i < players.size(); ++i) { AnimationPlayer* player = players[i]; if (player->update(reason)) timeToNextEffect = std::min(timeToNextEffect, player->timeToEffectChange()); else m_playersNeedingUpdate.remove(player); } if (timeToNextEffect < s_minimumDelay) m_timing->serviceOnNextFrame(); else if (timeToNextEffect != std::numeric_limits<double>::infinity()) m_timing->wakeAfter(timeToNextEffect - s_minimumDelay); ASSERT(!hasOutdatedAnimationPlayer()); }
void SVGDocumentExtensions::serviceAnimations(double monotonicAnimationStartTime) { WillBeHeapVector<RefPtrWillBeMember<SVGSVGElement> > timeContainers; timeContainers.appendRange(m_timeContainers.begin(), m_timeContainers.end()); WillBeHeapVector<RefPtrWillBeMember<SVGSVGElement> >::iterator end = timeContainers.end(); for (WillBeHeapVector<RefPtrWillBeMember<SVGSVGElement> >::iterator itr = timeContainers.begin(); itr != end; ++itr) (*itr)->timeContainer()->serviceAnimations(monotonicAnimationStartTime); }
WillBeHeapVector<RefPtrWillBeMember<AnimationPlayer>> AnimationTimeline::getAnimationPlayers() { WillBeHeapVector<RefPtrWillBeMember<AnimationPlayer>> animationPlayers; for (const auto& player : m_players) { if (player->source() && (player->source()->isCurrent() || player->source()->isInEffect())) animationPlayers.append(player); } std::sort(animationPlayers.begin(), animationPlayers.end(), compareAnimationPlayers); return animationPlayers; }
WillBeHeapVector<RefPtrWillBeMember<Animation>> AnimationTimeline::getAnimations() { WillBeHeapVector<RefPtrWillBeMember<Animation>> animations; for (const auto& animation : m_animations) { if (animation->effect() && (animation->effect()->isCurrent() || animation->effect()->isInEffect())) animations.append(animation); } std::sort(animations.begin(), animations.end(), compareAnimations); return animations; }
WillBeHeapVector<RefPtrWillBeMember<AnimationPlayer> > AnimationTimeline::getAnimationPlayers() { WillBeHeapVector<RefPtrWillBeMember<AnimationPlayer> > animationPlayers; for (WillBeHeapHashSet<RawPtrWillBeWeakMember<AnimationPlayer> >::iterator it = m_players.begin(); it != m_players.end(); ++it) { if ((*it)->source() && (*it)->source()->isCurrent()) { animationPlayers.append(*it); } } std::sort(animationPlayers.begin(), animationPlayers.end(), compareAnimationPlayers); return animationPlayers; }
void RTCDataChannel::scheduledEventTimerFired(Timer<RTCDataChannel>*) { WillBeHeapVector<RefPtrWillBeMember<Event>> events; events.swap(m_scheduledEvents); WillBeHeapVector<RefPtrWillBeMember<Event>>::iterator it = events.begin(); for (; it != events.end(); ++it) dispatchEvent((*it).release()); events.clear(); }
void PrintTo(const AnimatableRepeatable& animValue, ::std::ostream* os) { *os << "AnimatableRepeatable("; const WillBeHeapVector<RefPtrWillBeMember<AnimatableValue> > v = animValue.values(); for (WillBeHeapVector<RefPtrWillBeMember<AnimatableValue> >::const_iterator it = v.begin(); it != v.end(); ++it) { PrintTo(*(it->get()), os); if (it+1 != v.end()) *os << ", "; } *os << ")"; }
void RTCDTMFSender::scheduledEventTimerFired(Timer<RTCDTMFSender>*) { if (m_stopped) return; WillBeHeapVector<RefPtrWillBeMember<Event> > events; events.swap(m_scheduledEvents); WillBeHeapVector<RefPtrWillBeMember<Event> >::iterator it = events.begin(); for (; it != events.end(); ++it) dispatchEvent((*it).release()); }
void SVGAnimatedTypeAnimator::stopAnimValAnimation(const WillBeHeapVector<RawPtrWillBeMember<SVGElement> >& list) { ASSERT(isAnimatingSVGDom()); SVGElement::InstanceUpdateBlocker blocker(m_contextElement); WillBeHeapVector<RawPtrWillBeMember<SVGElement> >::const_iterator it = list.begin(); WillBeHeapVector<RawPtrWillBeMember<SVGElement> >::const_iterator itEnd = list.end(); for (; it != itEnd; ++it) { RefPtr<SVGAnimatedPropertyBase> animatedProperty = (*it)->propertyFromAttribute(m_animatedProperty->attributeName()); if (animatedProperty) animatedProperty->animationEnded(); } }
void RTCPeerConnection::dispatchScheduledEvent() { if (m_stopped) return; WillBeHeapVector<RefPtrWillBeMember<Event> > events; events.swap(m_scheduledEvents); WillBeHeapVector<RefPtrWillBeMember<Event> >::iterator it = events.begin(); for (; it != events.end(); ++it) dispatchEvent((*it).release()); events.clear(); }
void SVGDocumentExtensions::startAnimations() { // FIXME: Eventually every "Time Container" will need a way to latch on to some global timer // starting animations for a document will do this "latching" // FIXME: We hold a ref pointers to prevent a shadow tree from getting removed out from underneath us. // In the future we should refactor the use-element to avoid this. See https://webkit.org/b/53704 WillBeHeapVector<RefPtrWillBeMember<SVGSVGElement> > timeContainers; timeContainers.appendRange(m_timeContainers.begin(), m_timeContainers.end()); WillBeHeapVector<RefPtrWillBeMember<SVGSVGElement> >::iterator end = timeContainers.end(); for (WillBeHeapVector<RefPtrWillBeMember<SVGSVGElement> >::iterator itr = timeContainers.begin(); itr != end; ++itr) { SMILTimeContainer* timeContainer = (*itr)->timeContainer(); if (!timeContainer->isStarted()) timeContainer->begin(); } }
void SVGDocumentExtensions::dispatchSVGLoadEventToOutermostSVGElements() { WillBeHeapVector<RefPtrWillBeMember<SVGSVGElement> > timeContainers; timeContainers.appendRange(m_timeContainers.begin(), m_timeContainers.end()); WillBeHeapVector<RefPtrWillBeMember<SVGSVGElement> >::iterator end = timeContainers.end(); for (WillBeHeapVector<RefPtrWillBeMember<SVGSVGElement> >::iterator it = timeContainers.begin(); it != end; ++it) { SVGSVGElement* outerSVG = it->get(); if (!outerSVG->isOutermostSVGSVGElement()) continue; // don't dispatch the load event document is not wellformed (for XML/standalone svg) if (outerSVG->document().wellFormed() || !outerSVG->document().isSVGDocument()) outerSVG->sendSVGLoadEventIfPossible(); } }
void PageRuleCollector::matchPageRules(RuleSet* rules) { if (!rules) return; rules->compactRulesIfNeeded(); WillBeHeapVector<RawPtrWillBeMember<StyleRulePage> > matchedPageRules; matchPageRulesForList(matchedPageRules, rules->pageRules(), m_isLeftPage, m_isFirstPage, m_pageName); if (matchedPageRules.isEmpty()) return; std::stable_sort(matchedPageRules.begin(), matchedPageRules.end(), comparePageRules); for (unsigned i = 0; i < matchedPageRules.size(); i++) m_result.addMatchedProperties(&matchedPageRules[i]->properties()); }
EventTarget* EventPath::findRelatedNode(TreeScope& scope, RelatedTargetMap& relatedTargetMap) { WillBeHeapVector<RawPtrWillBeMember<TreeScope>, 32> parentTreeScopes; EventTarget* relatedNode = 0; for (TreeScope* current = &scope; current; current = current->olderShadowRootOrParentTreeScope()) { parentTreeScopes.append(current); RelatedTargetMap::const_iterator iter = relatedTargetMap.find(current); if (iter != relatedTargetMap.end() && iter->value) { relatedNode = iter->value; break; } } ASSERT(relatedNode); for (WillBeHeapVector<RawPtrWillBeMember<TreeScope>, 32>::iterator iter = parentTreeScopes.begin(); iter < parentTreeScopes.end(); ++iter) relatedTargetMap.add(*iter, relatedNode); return relatedNode; }
void SVGDocumentExtensions::rebuildAllElementReferencesForTarget(SVGElement* referencedElement) { ASSERT(referencedElement); if (!referencedElement->hasSVGRareData()) return; const SVGElementSet& referencingElements = referencedElement->svgRareData()->referencingElements(); // Iterate on a snapshot as |referencingElements| may be altered inside loop. WillBeHeapVector<RawPtrWillBeMember<SVGElement> > referencingElementsSnapShot; copyToVector(referencingElements, referencingElementsSnapShot); // Force rebuilding the referencingElement so it knows about this change. for (WillBeHeapVector<RawPtrWillBeMember<SVGElement> >::iterator it = referencingElementsSnapShot.begin(), itEnd = referencingElementsSnapShot.end(); it != itEnd; ++it) { SVGElement* referencingElement = *it; // Before rebuilding referencingElement ensure it was not removed from under us. if (referencingElements.contains(referencingElement)) referencingElement->svgAttributeChanged(XLinkNames::hrefAttr); } }
void SVGDocumentExtensions::rebuildAllElementReferencesForTarget(SVGElement* referencedElement) { ASSERT(referencedElement); ElementDependenciesMap::iterator it = m_elementDependencies.find(referencedElement); if (it == m_elementDependencies.end()) return; ASSERT(it->key == referencedElement); WillBeHeapVector<RawPtrWillBeMember<SVGElement> > toBeNotified; SVGElementSet* referencingElements = it->value.get(); copyToVector(*referencingElements, toBeNotified); // Force rebuilding the referencingElement so it knows about this change. WillBeHeapVector<RawPtrWillBeMember<SVGElement> >::iterator vectorEnd = toBeNotified.end(); for (WillBeHeapVector<RawPtrWillBeMember<SVGElement> >::iterator vectorIt = toBeNotified.begin(); vectorIt != vectorEnd; ++vectorIt) { // Before rebuilding referencingElement ensure it was not removed from under us. if (SVGElementSet* referencingElements = setOfElementsReferencingTarget(referencedElement)) { if (referencingElements->contains(*vectorIt)) (*vectorIt)->svgAttributeChanged(XLinkNames::hrefAttr); } } }
void AnimationTimeline::serviceAnimations(TimingUpdateReason reason) { TRACE_EVENT0("blink", "AnimationTimeline::serviceAnimations"); m_lastCurrentTimeInternal = currentTimeInternal(); m_timing->cancelWake(); WillBeHeapVector<RawPtrWillBeMember<AnimationPlayer>> players; players.reserveInitialCapacity(m_playersNeedingUpdate.size()); for (RefPtrWillBeMember<AnimationPlayer> player : m_playersNeedingUpdate) players.append(player.get()); std::sort(players.begin(), players.end(), AnimationPlayer::hasLowerPriority); for (AnimationPlayer* player : players) { if (!player->update(reason)) m_playersNeedingUpdate.remove(player); } ASSERT(!hasOutdatedAnimationPlayer()); }
void SVGAnimateElement::resetAnimatedType() { SVGAnimatedTypeAnimator* animator = ensureAnimator(); SVGElement* targetElement = this->targetElement(); const QualifiedName& attributeName = this->attributeName(); ShouldApplyAnimation shouldApply = shouldApplyAnimation(targetElement, attributeName); if (shouldApply == DontApplyAnimation) return; if (shouldApply == ApplyXMLAnimation) { // SVG DOM animVal animation code-path. WillBeHeapVector<RawPtrWillBeMember<SVGElement> > animatedElements = findElementInstances(targetElement); ASSERT(!animatedElements.isEmpty()); WillBeHeapVector<RawPtrWillBeMember<SVGElement> >::const_iterator end = animatedElements.end(); for (WillBeHeapVector<RawPtrWillBeMember<SVGElement> >::const_iterator it = animatedElements.begin(); it != end; ++it) document().accessSVGExtensions().addElementReferencingTarget(this, *it); if (!m_animatedProperty) m_animatedProperty = animator->startAnimValAnimation(animatedElements); else m_animatedProperty = animator->resetAnimValToBaseVal(animatedElements); return; } // CSS properties animation code-path. String baseValue; if (shouldApply == ApplyCSSAnimation) { ASSERT(SVGAnimationElement::isTargetAttributeCSSProperty(targetElement, attributeName)); computeCSSPropertyValue(targetElement, cssPropertyID(attributeName.localName()), baseValue); } m_animatedProperty = animator->constructFromString(baseValue); }
void IdTargetObserverRegistry::notifyObserversInternal(const AtomicString& id) { ASSERT(!id.isEmpty()); ASSERT(!m_registry.isEmpty()); m_notifyingObserversInSet = m_registry.get(id.impl()); if (!m_notifyingObserversInSet) return; WillBeHeapVector<RawPtrWillBeMember<IdTargetObserver> > copy; copyToVector(*m_notifyingObserversInSet, copy); for (WillBeHeapVector<RawPtrWillBeMember<IdTargetObserver> >::const_iterator it = copy.begin(); it != copy.end(); ++it) { if (m_notifyingObserversInSet->contains(*it)) (*it)->idTargetChanged(); } if (m_notifyingObserversInSet->isEmpty()) m_registry.remove(id.impl()); m_notifyingObserversInSet = nullptr; }
void CueTimeline::updateActiveCues(double movieTime) { // 4.8.10.8 Playing the media resource // If the current playback position changes while the steps are running, // then the user agent must wait for the steps to complete, and then must // immediately rerun the steps. if (ignoreUpdateRequests()) return; HTMLMediaElement& mediaElement = this->mediaElement(); // https://html.spec.whatwg.org/#time-marches-on // 1 - Let current cues be a list of cues, initialized to contain all the // cues of all the hidden, showing, or showing by default text tracks of the // media element (not the disabled ones) whose start times are less than or // equal to the current playback position and whose end times are greater // than the current playback position. CueList currentCues; // The user agent must synchronously unset [the text track cue active] flag // whenever ... the media element's readyState is changed back to HAVE_NOTHING. if (mediaElement.readyState() != HTMLMediaElement::HAVE_NOTHING && mediaElement.webMediaPlayer()) currentCues = m_cueTree.allOverlaps(m_cueTree.createInterval(movieTime, movieTime)); CueList previousCues; CueList missedCues; // 2 - Let other cues be a list of cues, initialized to contain all the cues // of hidden, showing, and showing by default text tracks of the media // element that are not present in current cues. previousCues = m_currentlyActiveCues; // 3 - Let last time be the current playback position at the time this // algorithm was last run for this media element, if this is not the first // time it has run. double lastTime = m_lastUpdateTime; double lastSeekTime = mediaElement.lastSeekTime(); // 4 - If the current playback position has, since the last time this // algorithm was run, only changed through its usual monotonic increase // during normal playback, then let missed cues be the list of cues in other // cues whose start times are greater than or equal to last time and whose // end times are less than or equal to the current playback position. // Otherwise, let missed cues be an empty list. if (lastTime >= 0 && lastSeekTime < movieTime) { CueList potentiallySkippedCues = m_cueTree.allOverlaps(m_cueTree.createInterval(lastTime, movieTime)); for (CueInterval cue : potentiallySkippedCues) { // Consider cues that may have been missed since the last seek time. if (cue.low() > std::max(lastSeekTime, lastTime) && cue.high() < movieTime) missedCues.append(cue); } } m_lastUpdateTime = movieTime; // 5 - If the time was reached through the usual monotonic increase of the // current playback position during normal playback, and if the user agent // has not fired a timeupdate event at the element in the past 15 to 250ms // and is not still running event handlers for such an event, then the user // agent must queue a task to fire a simple event named timeupdate at the // element. (In the other cases, such as explicit seeks, relevant events get // fired as part of the overall process of changing the current playback // position.) if (!mediaElement.seeking() && lastSeekTime < lastTime) mediaElement.scheduleTimeupdateEvent(true); // Explicitly cache vector sizes, as their content is constant from here. size_t currentCuesSize = currentCues.size(); size_t missedCuesSize = missedCues.size(); size_t previousCuesSize = previousCues.size(); // 6 - If all of the cues in current cues have their text track cue active // flag set, none of the cues in other cues have their text track cue active // flag set, and missed cues is empty, then abort these steps. bool activeSetChanged = missedCuesSize; for (size_t i = 0; !activeSetChanged && i < previousCuesSize; ++i) { if (!currentCues.contains(previousCues[i]) && previousCues[i].data()->isActive()) activeSetChanged = true; } for (CueInterval currentCue : currentCues) { // Notify any cues that are already active of the current time to mark // past and future nodes. Any inactive cues have an empty display state; // they will be notified of the current time when the display state is // updated. if (currentCue.data()->isActive()) currentCue.data()->updatePastAndFutureNodes(movieTime); else activeSetChanged = true; } if (!activeSetChanged) return; // 7 - If the time was reached through the usual monotonic increase of the // current playback position during normal playback, and there are cues in // other cues that have their text track cue pause-on-exi flag set and that // either have their text track cue active flag set or are also in missed // cues, then immediately pause the media element. for (size_t i = 0; !mediaElement.paused() && i < previousCuesSize; ++i) { if (previousCues[i].data()->pauseOnExit() && previousCues[i].data()->isActive() && !currentCues.contains(previousCues[i])) mediaElement.pause(); } for (size_t i = 0; !mediaElement.paused() && i < missedCuesSize; ++i) { if (missedCues[i].data()->pauseOnExit()) mediaElement.pause(); } // 8 - Let events be a list of tasks, initially empty. Each task in this // list will be associated with a text track, a text track cue, and a time, // which are used to sort the list before the tasks are queued. WillBeHeapVector<std::pair<double, RawPtrWillBeMember<TextTrackCue>>> eventTasks; // 8 - Let affected tracks be a list of text tracks, initially empty. WillBeHeapVector<RawPtrWillBeMember<TextTrack>> affectedTracks; for (size_t i = 0; i < missedCuesSize; ++i) { // 9 - For each text track cue in missed cues, prepare an event named enter // for the TextTrackCue object with the text track cue start time. eventTasks.append(std::make_pair(missedCues[i].data()->startTime(), missedCues[i].data())); // 10 - For each text track [...] in missed cues, prepare an event // named exit for the TextTrackCue object with the with the later of // the text track cue end time and the text track cue start time. // Note: An explicit task is added only if the cue is NOT a zero or // negative length cue. Otherwise, the need for an exit event is // checked when these tasks are actually queued below. This doesn't // affect sorting events before dispatch either, because the exit // event has the same time as the enter event. if (missedCues[i].data()->startTime() < missedCues[i].data()->endTime()) eventTasks.append(std::make_pair(missedCues[i].data()->endTime(), missedCues[i].data())); } for (size_t i = 0; i < previousCuesSize; ++i) { // 10 - For each text track cue in other cues that has its text // track cue active flag set prepare an event named exit for the // TextTrackCue object with the text track cue end time. if (!currentCues.contains(previousCues[i])) eventTasks.append(std::make_pair(previousCues[i].data()->endTime(), previousCues[i].data())); } for (size_t i = 0; i < currentCuesSize; ++i) { // 11 - For each text track cue in current cues that does not have its // text track cue active flag set, prepare an event named enter for the // TextTrackCue object with the text track cue start time. if (!previousCues.contains(currentCues[i])) eventTasks.append(std::make_pair(currentCues[i].data()->startTime(), currentCues[i].data())); } // 12 - Sort the tasks in events in ascending time order (tasks with earlier // times first). nonCopyingSort(eventTasks.begin(), eventTasks.end(), eventTimeCueCompare); for (size_t i = 0; i < eventTasks.size(); ++i) { if (!affectedTracks.contains(eventTasks[i].second->track())) affectedTracks.append(eventTasks[i].second->track()); // 13 - Queue each task in events, in list order. // Each event in eventTasks may be either an enterEvent or an exitEvent, // depending on the time that is associated with the event. This // correctly identifies the type of the event, if the startTime is // less than the endTime in the cue. if (eventTasks[i].second->startTime() >= eventTasks[i].second->endTime()) { mediaElement.scheduleEvent(createEventWithTarget(EventTypeNames::enter, eventTasks[i].second)); mediaElement.scheduleEvent(createEventWithTarget(EventTypeNames::exit, eventTasks[i].second)); } else { bool isEnterEvent = eventTasks[i].first == eventTasks[i].second->startTime(); AtomicString eventName = isEnterEvent ? EventTypeNames::enter : EventTypeNames::exit; mediaElement.scheduleEvent(createEventWithTarget(eventName, eventTasks[i].second)); } } // 14 - Sort affected tracks in the same order as the text tracks appear in // the media element's list of text tracks, and remove duplicates. nonCopyingSort(affectedTracks.begin(), affectedTracks.end(), trackIndexCompare); // 15 - For each text track in affected tracks, in the list order, queue a // task to fire a simple event named cuechange at the TextTrack object, and, ... for (size_t i = 0; i < affectedTracks.size(); ++i) { mediaElement.scheduleEvent(createEventWithTarget(EventTypeNames::cuechange, affectedTracks[i])); // ... if the text track has a corresponding track element, to then fire a // simple event named cuechange at the track element as well. if (affectedTracks[i]->trackType() == TextTrack::TrackElement) { HTMLTrackElement* trackElement = static_cast<LoadableTextTrack*>(affectedTracks[i].get())->trackElement(); ASSERT(trackElement); mediaElement.scheduleEvent(createEventWithTarget(EventTypeNames::cuechange, trackElement)); } } // 16 - Set the text track cue active flag of all the cues in the current // cues, and unset the text track cue active flag of all the cues in the // other cues. for (size_t i = 0; i < currentCuesSize; ++i) currentCues[i].data()->setIsActive(true); for (size_t i = 0; i < previousCuesSize; ++i) { if (!currentCues.contains(previousCues[i])) { TextTrackCue* cue = previousCues[i].data(); cue->setIsActive(false); cue->removeDisplayTree(); } } // Update the current active cues. m_currentlyActiveCues = currentCues; mediaElement.updateTextTrackDisplay(); }
void run(LocalFrame* frame) override { if (m_running) return; m_running = true; // 0. Flush pending frontend messages. WebLocalFrameImpl* frameImpl = WebLocalFrameImpl::fromFrame(frame); WebDevToolsAgentImpl* agent = frameImpl->devToolsAgentImpl(); agent->flushPendingProtocolNotifications(); Vector<WebViewImpl*> views; WillBeHeapVector<RawPtrWillBeMember<WebFrameWidgetImpl>> widgets; // 1. Disable input events. const HashSet<WebViewImpl*>& viewImpls = WebViewImpl::allInstances(); HashSet<WebViewImpl*>::const_iterator viewImplsEnd = viewImpls.end(); for (HashSet<WebViewImpl*>::const_iterator it = viewImpls.begin(); it != viewImplsEnd; ++it) { WebViewImpl* view = *it; m_frozenViews.add(view); views.append(view); view->setIgnoreInputEvents(true); } const WebFrameWidgetsSet& widgetImpls = WebFrameWidgetImpl::allInstances(); WebFrameWidgetsSet::const_iterator widgetImplsEnd = widgetImpls.end(); for (WebFrameWidgetsSet::const_iterator it = widgetImpls.begin(); it != widgetImplsEnd; ++it) { WebFrameWidgetImpl* widget = *it; m_frozenWidgets.add(widget); widgets.append(widget); widget->setIgnoreInputEvents(true); } // 2. Notify embedder about pausing. agent->client()->willEnterDebugLoop(); // 3. Disable active objects WebView::willEnterModalLoop(); // 4. Process messages until quitNow is called. m_messageLoop->run(); // 5. Resume active objects WebView::didExitModalLoop(); // 6. Resume input events. for (Vector<WebViewImpl*>::iterator it = views.begin(); it != views.end(); ++it) { if (m_frozenViews.contains(*it)) { // The view was not closed during the dispatch. (*it)->setIgnoreInputEvents(false); } } for (WillBeHeapVector<RawPtrWillBeMember<WebFrameWidgetImpl>>::iterator it = widgets.begin(); it != widgets.end(); ++it) { if (m_frozenWidgets.contains(*it)) { // The widget was not closed during the dispatch. (*it)->setIgnoreInputEvents(false); } } // 7. Notify embedder about resuming. agent->client()->didExitDebugLoop(); // 8. All views have been resumed, clear the set. m_frozenViews.clear(); m_frozenWidgets.clear(); m_running = false; }