예제 #1
0
void NodeSet::traversalSort() const {
  HeapHashSet<Member<Node>> nodes;
  bool containsAttributeNodes = false;

  unsigned nodeCount = m_nodes.size();
  DCHECK_GT(nodeCount, 1u);
  for (unsigned i = 0; i < nodeCount; ++i) {
    Node* node = m_nodes[i].get();
    nodes.add(node);
    if (node->isAttributeNode())
      containsAttributeNodes = true;
  }

  HeapVector<Member<Node>> sortedNodes;
  sortedNodes.reserveInitialCapacity(nodeCount);

  for (Node& n : NodeTraversal::startsAt(*findRootNode(m_nodes.first()))) {
    if (nodes.contains(&n))
      sortedNodes.append(&n);

    if (!containsAttributeNodes || !n.isElementNode())
      continue;

    Element* element = toElement(&n);
    AttributeCollection attributes = element->attributes();
    for (auto& attribute : attributes) {
      Attr* attr = element->attrIfExists(attribute.name());
      if (attr && nodes.contains(attr))
        sortedNodes.append(attr);
    }
  }

  DCHECK_EQ(sortedNodes.size(), nodeCount);
  const_cast<HeapVector<Member<Node>>&>(m_nodes).swap(sortedNodes);
}
예제 #2
0
HeapVector<Member<Element>> TreeScope::elementsFromHitTestResult(
    HitTestResult& result) const {
  HeapVector<Member<Element>> elements;

  Node* lastNode = nullptr;
  for (const auto rectBasedNode : result.listBasedTestResult()) {
    Node* node = rectBasedNode.get();
    if (!node || !node->isElementNode() || node->isDocumentNode())
      continue;

    if (node->isPseudoElement() || node->isTextNode())
      node = node->parentOrShadowHostNode();
    node = ancestorInThisScope(node);

    // Prune duplicate entries. A pseduo ::before content above its parent
    // node should only result in a single entry.
    if (node == lastNode)
      continue;

    if (node && node->isElementNode()) {
      elements.append(toElement(node));
      lastNode = node;
    }
  }

  if (rootNode().isDocumentNode()) {
    if (Element* rootElement = toDocument(rootNode()).documentElement()) {
      if (elements.isEmpty() || elements.last() != rootElement)
        elements.append(rootElement);
    }
  }

  return elements;
}
void VRHardwareUnit::addDevicesToVector(HeapVector<Member<VRDevice>>& vrDevices)
{
    if (m_hmd)
        vrDevices.append(m_hmd);

    if (m_positionSensor)
        vrDevices.append(m_positionSensor);
}
예제 #4
0
bool MHTMLParser::parseArchiveWithHeader(
    MIMEHeader* header,
    HeapVector<Member<ArchiveResource>>& resources) {
  if (!header) {
    DVLOG(1) << "Failed to parse MHTML part: no header.";
    return false;
  }

  if (!header->isMultipart()) {
    // With IE a page with no resource is not multi-part.
    bool endOfArchiveReached = false;
    ArchiveResource* resource =
        parseNextPart(*header, String(), String(), endOfArchiveReached);
    if (!resource)
      return false;
    resources.append(resource);
    return true;
  }

  // Skip the message content (it's a generic browser specific message).
  skipLinesUntilBoundaryFound(m_lineReader, header->endOfPartBoundary());

  bool endOfArchive = false;
  while (!endOfArchive) {
    MIMEHeader* resourceHeader = MIMEHeader::parseHeader(&m_lineReader);
    if (!resourceHeader) {
      DVLOG(1) << "Failed to parse MHTML, invalid MIME header.";
      return false;
    }
    if (resourceHeader->contentType() == "multipart/alternative") {
      // Ignore IE nesting which makes little sense (IE seems to nest only some
      // of the frames).
      if (!parseArchiveWithHeader(resourceHeader, resources)) {
        DVLOG(1) << "Failed to parse MHTML subframe.";
        return false;
      }
      skipLinesUntilBoundaryFound(m_lineReader, header->endOfPartBoundary());
      continue;
    }

    ArchiveResource* resource =
        parseNextPart(*resourceHeader, header->endOfPartBoundary(),
                      header->endOfDocumentBoundary(), endOfArchive);
    if (!resource) {
      DVLOG(1) << "Failed to parse MHTML part.";
      return false;
    }
    resources.append(resource);
  }
  return true;
}
예제 #5
0
void CSSAnimations::calculateTransitionActiveInterpolations(CSSAnimationUpdate& update, const Element* animatingElement, double timelineCurrentTime)
{
    ElementAnimations* elementAnimations = animatingElement ? animatingElement->elementAnimations() : nullptr;
    AnimationStack* animationStack = elementAnimations ? &elementAnimations->defaultStack() : nullptr;

    ActiveInterpolationsMap activeInterpolationsForTransitions;
    if (update.newTransitions().isEmpty() && update.cancelledTransitions().isEmpty()) {
        activeInterpolationsForTransitions = AnimationStack::activeInterpolations(animationStack, 0, 0, KeyframeEffect::TransitionPriority, timelineCurrentTime);
    } else {
        HeapVector<Member<InertEffect>> newTransitions;
        for (const auto& entry : update.newTransitions())
            newTransitions.append(entry.value.effect.get());

        HeapHashSet<Member<const Animation>> cancelledAnimations;
        if (!update.cancelledTransitions().isEmpty()) {
            ASSERT(elementAnimations);
            const TransitionMap& transitionMap = elementAnimations->cssAnimations().m_transitions;
            for (CSSPropertyID id : update.cancelledTransitions()) {
                ASSERT(transitionMap.contains(id));
                cancelledAnimations.add(transitionMap.get(id).animation.get());
            }
        }

        activeInterpolationsForTransitions = AnimationStack::activeInterpolations(animationStack, &newTransitions, &cancelledAnimations, KeyframeEffect::TransitionPriority, timelineCurrentTime);
    }

    // Properties being animated by animations don't get values from transitions applied.
    if (!update.activeInterpolationsForAnimations().isEmpty() && !activeInterpolationsForTransitions.isEmpty()) {
        for (const auto& entry : update.activeInterpolationsForAnimations())
            activeInterpolationsForTransitions.remove(entry.key);
    }
    update.adoptActiveInterpolationsForTransitions(activeInterpolationsForTransitions);
}
  void onSuccess(const WebVector<WebBluetoothRemoteGATTCharacteristicInit*>&
                     webCharacteristics) override {
    if (!m_resolver->getExecutionContext() ||
        m_resolver->getExecutionContext()->activeDOMObjectsAreStopped())
      return;

    // If the resolver is not in the set of ActiveAlgorithms then the frame
    // disconnected so we reject.
    if (!m_service->device()->gatt()->RemoveFromActiveAlgorithms(
            m_resolver.get())) {
      m_resolver->reject(
          DOMException::create(NetworkError, kGATTServerDisconnected));
      return;
    }

    if (m_quantity == mojom::blink::WebBluetoothGATTQueryQuantity::SINGLE) {
      DCHECK_EQ(1u, webCharacteristics.size());
      m_resolver->resolve(BluetoothRemoteGATTCharacteristic::take(
          m_resolver, wrapUnique(webCharacteristics[0]), m_service));
      return;
    }

    HeapVector<Member<BluetoothRemoteGATTCharacteristic>> characteristics;
    characteristics.reserveInitialCapacity(webCharacteristics.size());
    for (WebBluetoothRemoteGATTCharacteristicInit* webCharacteristic :
         webCharacteristics) {
      characteristics.append(BluetoothRemoteGATTCharacteristic::take(
          m_resolver, wrapUnique(webCharacteristic), m_service));
    }
    m_resolver->resolve(characteristics);
  }
예제 #7
0
  void onSuccess(
      const WebVector<WebBluetoothRemoteGATTService*>& webServices) override {
    if (!m_resolver->getExecutionContext() ||
        m_resolver->getExecutionContext()->isContextDestroyed())
      return;

    // If the resolver is not in the set of ActiveAlgorithms then the frame
    // disconnected so we reject.
    if (!m_device->gatt()->RemoveFromActiveAlgorithms(m_resolver.get())) {
      m_resolver->reject(
          DOMException::create(NetworkError, kGATTServerDisconnected));
      return;
    }

    if (m_quantity == mojom::blink::WebBluetoothGATTQueryQuantity::SINGLE) {
      DCHECK_EQ(1u, webServices.size());
      m_resolver->resolve(m_device->getOrCreateBluetoothRemoteGATTService(
          WTF::wrapUnique(webServices[0])));
      return;
    }

    HeapVector<Member<BluetoothRemoteGATTService>> services;
    services.reserveInitialCapacity(webServices.size());
    for (WebBluetoothRemoteGATTService* webService : webServices) {
      services.append(m_device->getOrCreateBluetoothRemoteGATTService(
          WTF::wrapUnique(webService)));
    }
    m_resolver->resolve(services);
  }
void CSSSegmentedFontFace::match(const String& text, HeapVector<Member<FontFace>>& faces) const
{
    for (const auto& fontFace : m_fontFaces) {
        if (fontFace->cssFontFace()->ranges()->intersectsWith(text))
            faces.append(fontFace);
    }
}
void AnimationTimeline::serviceAnimations(TimingUpdateReason reason)
{
    TRACE_EVENT0("blink", "AnimationTimeline::serviceAnimations");

    m_lastCurrentTimeInternal = currentTimeInternal();

    HeapVector<Member<Animation>> animations;
    animations.reserveInitialCapacity(m_animationsNeedingUpdate.size());
    for (Animation* animation : m_animationsNeedingUpdate)
        animations.append(animation);

    std::sort(animations.begin(), animations.end(), Animation::hasLowerPriority);

    for (Animation* animation : animations) {
        if (!animation->update(reason))
            m_animationsNeedingUpdate.remove(animation);
    }

    ASSERT(m_outdatedAnimationCount == 0);
    ASSERT(m_lastCurrentTimeInternal == currentTimeInternal() || (std::isnan(currentTimeInternal()) && std::isnan(m_lastCurrentTimeInternal)));

#if ENABLE(ASSERT)
    for (const auto& animation : m_animationsNeedingUpdate)
        ASSERT(!animation->outdated());
#endif
}
void ScreenOrientationController::notifyOrientationChanged() {
  if (!isActiveAndVisible())
    return;

  updateOrientation();

  // Keep track of the frames that need to be notified before notifying the
  // current frame as it will prevent side effects from the change event
  // handlers.
  HeapVector<Member<LocalFrame>> childFrames;
  for (Frame* child = frame()->tree().firstChild(); child;
       child = child->tree().nextSibling()) {
    if (child->isLocalFrame())
      childFrames.append(toLocalFrame(child));
  }

  // Notify current orientation object.
  if (!m_dispatchEventTimer.isActive())
    m_dispatchEventTimer.startOneShot(0, BLINK_FROM_HERE);

  // ... and child frames, if they have a ScreenOrientationController.
  for (size_t i = 0; i < childFrames.size(); ++i) {
    if (ScreenOrientationController* controller =
            ScreenOrientationController::from(*childFrames[i]))
      controller->notifyOrientationChanged();
  }
}
예제 #11
0
StaticNodeList* SVGSVGElement::collectIntersectionOrEnclosureList(
    const FloatRect& rect,
    SVGElement* referenceElement,
    CheckIntersectionOrEnclosure mode) const {
  HeapVector<Member<Node>> nodes;

  const SVGElement* root = this;
  if (referenceElement) {
    // Only the common subtree needs to be traversed.
    if (contains(referenceElement)) {
      root = referenceElement;
    } else if (!isDescendantOf(referenceElement)) {
      // No common subtree.
      return StaticNodeList::adopt(nodes);
    }
  }

  for (SVGGraphicsElement& element :
       Traversal<SVGGraphicsElement>::descendantsOf(*root)) {
    if (checkIntersectionOrEnclosure(element, rect, mode))
      nodes.append(&element);
  }

  return StaticNodeList::adopt(nodes);
}
예제 #12
0
DispatchEventResult IDBTransaction::dispatchEventInternal(Event* event) {
  IDB_TRACE("IDBTransaction::dispatchEvent");
  if (!getExecutionContext()) {
    m_state = Finished;
    return DispatchEventResult::CanceledBeforeDispatch;
  }
  DCHECK_NE(m_state, Finished);
  DCHECK(m_hasPendingActivity);
  DCHECK(getExecutionContext());
  DCHECK_EQ(event->target(), this);
  m_state = Finished;

  HeapVector<Member<EventTarget>> targets;
  targets.append(this);
  targets.append(db());

  // FIXME: When we allow custom event dispatching, this will probably need to
  // change.
  DCHECK(event->type() == EventTypeNames::complete ||
         event->type() == EventTypeNames::abort);
  DispatchEventResult dispatchResult =
      IDBEventDispatcher::dispatch(event, targets);
  // FIXME: Try to construct a test where |this| outlives openDBRequest and we
  // get a crash.
  if (m_openDBRequest) {
    DCHECK(isVersionChange());
    m_openDBRequest->transactionDidFinishAndDispatch();
  }
  m_hasPendingActivity = false;
  return dispatchResult;
}
예제 #13
0
 void runAdoptedCallback(Element* element,
                         Document* oldOwner,
                         Document* newOwner) override {
   m_logs.append(AdoptedCallback);
   EXPECT_EQ(element, m_element);
   m_adopted.append(new Adopted(oldOwner, newOwner));
 }
예제 #14
0
void MutationObserver::deliver() {
  DCHECK(!shouldBeSuspended());

  // Calling clearTransientRegistrations() can modify m_registrations, so it's
  // necessary to make a copy of the transient registrations before operating on
  // them.
  HeapVector<Member<MutationObserverRegistration>, 1> transientRegistrations;
  for (auto& registration : m_registrations) {
    if (registration->hasTransientRegistrations())
      transientRegistrations.append(registration);
  }
  for (size_t i = 0; i < transientRegistrations.size(); ++i)
    transientRegistrations[i]->clearTransientRegistrations();

  if (m_records.isEmpty())
    return;

  MutationRecordVector records;
  records.swap(m_records);

  // Report the first (earliest) stack as the async cause.
  InspectorInstrumentation::AsyncTask asyncTask(
      m_callback->getExecutionContext(), records.first());
  m_callback->call(records, this);
}
예제 #15
0
void SplitElementCommand::executeApply() {
  if (m_atChild->parentNode() != m_element2)
    return;

  HeapVector<Member<Node>> children;
  for (Node* node = m_element2->firstChild(); node != m_atChild;
       node = node->nextSibling())
    children.append(node);

  DummyExceptionStateForTesting exceptionState;

  ContainerNode* parent = m_element2->parentNode();
  if (!parent || !hasEditableStyle(*parent))
    return;
  parent->insertBefore(m_element1.get(), m_element2.get(), exceptionState);
  if (exceptionState.hadException())
    return;

  // Delete id attribute from the second element because the same id cannot be
  // used for more than one element
  m_element2->removeAttribute(HTMLNames::idAttr);

  for (const auto& child : children)
    m_element1->appendChild(child, exceptionState);
}
예제 #16
0
void Frame::didChangeVisibilityState()
{
    HeapVector<Member<Frame>> childFrames;
    for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling())
        childFrames.append(child);
    for (size_t i = 0; i < childFrames.size(); ++i)
        childFrames[i]->didChangeVisibilityState();
}
void AXObject::scrollToGlobalPoint(const IntPoint& globalPoint) const
{
    // Search up the parent chain and create a vector of all scrollable parent objects
    // and ending with this object itself.
    HeapVector<Member<const AXObject>> objects;
    AXObject* parentObject;
    for (parentObject = this->parentObject(); parentObject; parentObject = parentObject->parentObject()) {
        if (parentObject->getScrollableAreaIfScrollable() && !parentObject->isAXScrollView())
            objects.prepend(parentObject);
    }
    objects.append(this);

    // Start with the outermost scrollable (the main window) and try to scroll the
    // next innermost object to the given point.
    int offsetX = 0, offsetY = 0;
    IntPoint point = globalPoint;
    size_t levels = objects.size() - 1;
    for (size_t i = 0; i < levels; i++) {
        const AXObject* outer = objects[i];
        const AXObject* inner = objects[i + 1];
        ScrollableArea* scrollableArea = outer->getScrollableAreaIfScrollable();

        IntRect innerRect = inner->isWebArea() ? pixelSnappedIntRect(inner->parentObject()->elementRect()) : pixelSnappedIntRect(inner->elementRect());
        IntRect objectRect = innerRect;
        IntPoint scrollPosition = scrollableArea->scrollPosition();

        // Convert the object rect into local coordinates.
        objectRect.move(offsetX, offsetY);
        if (!outer->isWebArea())
            objectRect.move(scrollPosition.x(), scrollPosition.y());

        int desiredX = computeBestScrollOffset(
            0,
            objectRect.x(), objectRect.maxX(),
            objectRect.x(), objectRect.maxX(),
            point.x(), point.x());
        int desiredY = computeBestScrollOffset(
            0,
            objectRect.y(), objectRect.maxY(),
            objectRect.y(), objectRect.maxY(),
            point.y(), point.y());
        outer->setScrollOffset(IntPoint(desiredX, desiredY));

        if (outer->isWebArea() && !inner->isWebArea()) {
            // If outer object we just scrolled is a web area (frame) but the inner object
            // is not, keep track of the coordinate transformation to apply to
            // future nested calculations.
            scrollPosition = scrollableArea->scrollPosition();
            offsetX -= (scrollPosition.x() + point.x());
            offsetY -= (scrollPosition.y() + point.y());
            point.move(scrollPosition.x() - innerRect.x(), scrollPosition.y() - innerRect.y());
        } else if (inner->isWebArea()) {
            // Otherwise, if the inner object is a web area, reset the coordinate transformation.
            offsetX = 0;
            offsetY = 0;
        }
    }
}
예제 #18
0
static Position findWordBoundary(const HTMLElement* innerEditor, const Position& startPosition, const Position& endPosition, FindOption findOption)
{
    StringBuilder concatTexts;
    Vector<unsigned> lengthList;
    HeapVector<Member<Text>> textList;

    if (startPosition.anchorNode()->isTextNode())
        ASSERT(startPosition.isOffsetInAnchor());
    if (endPosition.anchorNode()->isTextNode())
        ASSERT(endPosition.isOffsetInAnchor());

    // Traverse text nodes.
    for (Node* node = startPosition.anchorNode(); node; node = NodeTraversal::next(*node, innerEditor)) {
        bool isStartNode = node == startPosition.anchorNode();
        bool isEndNode = node == endPosition.anchorNode();
        if (node->isTextNode()) {
            Text* text = toText(node);
            const unsigned start = isStartNode ? startPosition.offsetInContainerNode() : 0;
            const unsigned end = isEndNode ? endPosition.offsetInContainerNode() : text->data().length();
            const unsigned length = end - start;

            concatTexts.append(text->data(), start, length);
            lengthList.append(length);
            textList.append(text);
        }

        if (isEndNode)
            break;
    }

    if (concatTexts.length() == 0)
        return startPosition;

    int start, end;
    if (findOption == FindEnd && concatTexts[0] == '\n') {
        // findWordBoundary("\ntext", 0, &start, &end) assigns 1 to |end| but
        // we expect 0 at the case.
        start = 0;
        end = 0;
    } else {
        Vector<UChar> characters;
        concatTexts.toString().appendTo(characters);
        findWordBoundary(characters.data(), characters.size(), findOption == FindStart ? characters.size() : 0, &start, &end);
    }
    ASSERT(start >= 0);
    ASSERT(end >= 0);
    unsigned remainingOffset = findOption == FindStart ? start : end;
    // Find position.
    for (unsigned i = 0; i < lengthList.size(); ++i) {
        if (remainingOffset <= lengthList[i])
            return Position(textList[i], (textList[i] == startPosition.anchorNode()) ? remainingOffset + startPosition.offsetInContainerNode() : remainingOffset);
        remainingOffset -= lengthList[i];
    }

    ASSERT_NOT_REACHED();
    return Position();
}
예제 #19
0
inline void DistributionPool::populateChildren(const ContainerNode& parent) {
  clear();
  for (Node* child = parent.firstChild(); child; child = child->nextSibling()) {
    if (isHTMLSlotElement(child)) {
      // TODO(hayato): Support re-distribution across v0 and v1 shadow trees
      continue;
    }
    if (isActiveInsertionPoint(*child)) {
      InsertionPoint* insertionPoint = toInsertionPoint(child);
      for (size_t i = 0; i < insertionPoint->distributedNodesSize(); ++i)
        m_nodes.append(insertionPoint->distributedNodeAt(i));
    } else {
      m_nodes.append(child);
    }
  }
  m_distributed.resize(m_nodes.size());
  m_distributed.fill(false);
}
예제 #20
0
 void executeScriptInIsolatedWorld(const String& script) const {
   v8::HandleScope scope(v8::Isolate::GetCurrent());
   HeapVector<ScriptSourceCode> sources;
   sources.append(ScriptSourceCode(script));
   Vector<v8::Local<v8::Value>> results;
   m_scriptController->executeScriptInIsolatedWorld(isolatedWorldId, sources,
                                                    extensionGroup, 0);
   pumpPendingRequestsForFrameToLoad(m_webViewHelper.webView()->mainFrame());
 }
void IntersectionObserverController::removeTrackedObserversForRoot(
    const Node& root) {
  HeapVector<Member<IntersectionObserver>> toRemove;
  for (auto& observer : m_trackedIntersectionObservers) {
    if (observer->rootNode() == &root)
      toRemove.append(observer);
  }
  m_trackedIntersectionObservers.removeAll(toRemove);
}
void InsertParagraphSeparatorCommand::getAncestorsInsideBlock(const Node* insertionNode, Element* outerBlock, HeapVector<Member<Element>>& ancestors)
{
    ancestors.clear();

    // Build up list of ancestors elements between the insertion node and the outer block.
    if (insertionNode != outerBlock) {
        for (Element* n = insertionNode->parentElement(); n && n != outerBlock; n = n->parentElement())
            ancestors.append(n);
    }
}
HeapVector<Member<Animation>> AnimationTimeline::getAnimations()
{
    HeapVector<Member<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;
}
예제 #24
0
PassRefPtrWillBeRawPtr<SpeechRecognitionEvent> SpeechRecognitionEvent::createNoMatch(SpeechRecognitionResult* result)
{
    if (result) {
        HeapVector<Member<SpeechRecognitionResult>> results;
        results.append(result);
        return adoptRefWillBeNoop(new SpeechRecognitionEvent(EventTypeNames::nomatch, 0, SpeechRecognitionResultList::create(results)));
    }

    return adoptRefWillBeNoop(new SpeechRecognitionEvent(EventTypeNames::nomatch, 0, nullptr));
}
예제 #25
0
FontFaceSetIterable::IterationSource* FontFaceSet::startIteration(
    ScriptState*,
    ExceptionState&) {
  // Setlike should iterate each item in insertion order, and items should
  // be keep on up to date. But since blink does not have a way to hook up CSS
  // modification, take a snapshot here, and make it ordered as follows.
  HeapVector<Member<FontFace>> fontFaces;
  if (inActiveDocumentContext()) {
    const HeapListHashSet<Member<FontFace>>& cssConnectedFaces =
        cssConnectedFontFaceList();
    fontFaces.reserveInitialCapacity(cssConnectedFaces.size() +
                                     m_nonCSSConnectedFaces.size());
    for (const auto& fontFace : cssConnectedFaces)
      fontFaces.append(fontFace);
    for (const auto& fontFace : m_nonCSSConnectedFaces)
      fontFaces.append(fontFace);
  }
  return new IterationSource(fontFaces);
}
예제 #26
0
PaymentAppRequestData PaymentAppRequestDataConversion::toPaymentAppRequestData(
    ScriptState* scriptState,
    const WebPaymentAppRequestData& webData) {
  PaymentAppRequestData data;

  data.setOrigin(webData.origin);
  HeapVector<PaymentMethodData> methodData;
  for (const auto& md : webData.methodData) {
    methodData.append(toPaymentMethodData(scriptState, md));
  }
  data.setMethodData(methodData);
  data.setTotal(toPaymentItem(webData.total));
  HeapVector<PaymentDetailsModifier> modifiers;
  for (const auto& modifier : webData.modifiers) {
    modifiers.append(toPaymentDetailsModifier(scriptState, modifier));
  }
  data.setOptionId(webData.optionId);
  return data;
}
예제 #27
0
bool TouchEventManager::generateTouchInfosAfterHittest(
    const PlatformTouchEvent& event,
    HeapVector<TouchInfo>& touchInfos)
{
    bool newTouchSequence = true;
    bool allTouchesReleased = true;

    for (const auto& point : event.touchPoints()) {
        if (point.state() != PlatformTouchPoint::TouchPressed)
            newTouchSequence = false;
        if (point.state() != PlatformTouchPoint::TouchReleased && point.state() != PlatformTouchPoint::TouchCancelled)
            allTouchesReleased = false;
    }
    if (newTouchSequence) {
        // Ideally we'd ASSERT(!m_touchSequenceDocument) here since we should
        // have cleared the active document when we saw the last release. But we
        // have some tests that violate this, ClusterFuzz could trigger it, and
        // there may be cases where the browser doesn't reliably release all
        // touches. http://crbug.com/345372 tracks this.
        m_touchSequenceDocument.clear();
        m_touchSequenceUserGestureToken.clear();
    }

    ASSERT(m_frame->view());
    if (m_touchSequenceDocument && (!m_touchSequenceDocument->frame() || !m_touchSequenceDocument->frame()->view())) {
        // If the active touch document has no frame or view, it's probably being destroyed
        // so we can't dispatch events.
        return false;
    }

    for (const auto& point : event.touchPoints()) {
        TouchEventManager::TouchInfo touchInfo;
        touchInfo.point = point;
        touchInfos.append(touchInfo);
    }

    updateTargetAndRegionMapsForTouchStarts(touchInfos);

    m_touchPressed = !allTouchesReleased;

    // If there's no document receiving touch events, or no handlers on the
    // document set to receive the events, then we can skip all the rest of
    // this work.
    if (!m_touchSequenceDocument || !m_touchSequenceDocument->frameHost() || !hasTouchHandlers(m_touchSequenceDocument->frameHost()->eventHandlerRegistry()) || !m_touchSequenceDocument->frame()) {
        if (allTouchesReleased) {
            m_touchSequenceDocument.clear();
            m_touchSequenceUserGestureToken.clear();
        }
        return false;
    }

    setAllPropertiesOfTouchInfos(touchInfos);

    return true;
}
예제 #28
0
void CSSAnimations::calculateAnimationActiveInterpolations(CSSAnimationUpdate& update, const Element* animatingElement, double timelineCurrentTime)
{
    ElementAnimations* elementAnimations = animatingElement ? animatingElement->elementAnimations() : nullptr;
    AnimationStack* animationStack = elementAnimations ? &elementAnimations->defaultStack() : nullptr;

    if (update.newAnimations().isEmpty() && update.suppressedAnimations().isEmpty()) {
        ActiveInterpolationsMap activeInterpolationsForAnimations(AnimationStack::activeInterpolations(animationStack, 0, 0, KeyframeEffect::DefaultPriority, timelineCurrentTime));
        update.adoptActiveInterpolationsForAnimations(activeInterpolationsForAnimations);
        return;
    }

    HeapVector<Member<InertEffect>> newEffects;
    for (const auto& newAnimation : update.newAnimations())
        newEffects.append(newAnimation.effect.get());
    for (const auto& updatedAnimation : update.animationsWithUpdates())
        newEffects.append(updatedAnimation.effect.get()); // Animations with updates use a temporary InertEffect for the current frame.

    ActiveInterpolationsMap activeInterpolationsForAnimations(AnimationStack::activeInterpolations(animationStack, &newEffects, &update.suppressedAnimations(), KeyframeEffect::DefaultPriority, timelineCurrentTime));
    update.adoptActiveInterpolationsForAnimations(activeInterpolationsForAnimations);
}
예제 #29
0
const TreeScope* TreeScope::commonAncestorTreeScope(const TreeScope& other) const
{
    HeapVector<Member<const TreeScope>, 16> thisChain;
    for (const TreeScope* tree = this; tree; tree = tree->parentTreeScope())
        thisChain.append(tree);

    HeapVector<Member<const TreeScope>, 16> otherChain;
    for (const TreeScope* tree = &other; tree; tree = tree->parentTreeScope())
        otherChain.append(tree);

    // Keep popping out the last elements of these chains until a mismatched pair is found. If |this| and |other|
    // belong to different documents, null will be returned.
    const TreeScope* lastAncestor = nullptr;
    while (!thisChain.isEmpty() && !otherChain.isEmpty() && thisChain.last() == otherChain.last()) {
        lastAncestor = thisChain.last();
        thisChain.removeLast();
        otherChain.removeLast();
    }
    return lastAncestor;
}
예제 #30
0
PointerEvent* PointerEventFactory::create(
    const PlatformTouchPoint& touchPoint,
    const Vector<PlatformTouchPoint>& coalescedPoints,
    PlatformEvent::Modifiers modifiers,
    LocalFrame* targetFrame,
    DOMWindow* view) {
  const PlatformTouchPoint::TouchState pointState = touchPoint.state();
  const AtomicString& type =
      pointerEventNameForTouchPointState(touchPoint.state());

  DCHECK(type == EventTypeNames::pointermove || coalescedPoints.isEmpty());

  bool pointerReleasedOrCancelled =
      pointState == PlatformTouchPoint::TouchReleased ||
      pointState == PlatformTouchPoint::TouchCancelled;
  bool pointerPressedOrReleased =
      pointState == PlatformTouchPoint::TouchPressed ||
      pointState == PlatformTouchPoint::TouchReleased;

  PointerEventInit pointerEventInit;

  setIdTypeButtons(pointerEventInit, touchPoint.pointerProperties(),
                   pointerReleasedOrCancelled ? 0 : 1);
  pointerEventInit.setButton(static_cast<int>(
      pointerPressedOrReleased ? WebPointerProperties::Button::Left
                               : WebPointerProperties::Button::NoButton));

  pointerEventInit.setView(view);
  updateTouchPointerEventInit(touchPoint, targetFrame, &pointerEventInit);

  UIEventWithKeyState::setFromPlatformModifiers(pointerEventInit, modifiers);

  setEventSpecificFields(pointerEventInit, type);

  // Created coalesced events init structure
  HeapVector<Member<PointerEvent>> coalescedPointerEvents;
  for (const auto& coalescedTouchPoint : coalescedPoints) {
    DCHECK_EQ(touchPoint.state(), coalescedTouchPoint.state());
    DCHECK_EQ(touchPoint.pointerProperties().id,
              coalescedTouchPoint.pointerProperties().id);
    DCHECK_EQ(touchPoint.pointerProperties().pointerType,
              coalescedTouchPoint.pointerProperties().pointerType);
    PointerEventInit coalescedEventInit = pointerEventInit;
    updateTouchPointerEventInit(coalescedTouchPoint, targetFrame,
                                &coalescedEventInit);
    coalescedPointerEvents.append(
        PointerEvent::create(type, coalescedEventInit));
  }
  pointerEventInit.setCoalescedEvents(coalescedPointerEvents);

  return PointerEvent::create(type, pointerEventInit);
}