PassOwnPtr<DOMPatchSupport::Digest> DOMPatchSupport::createDigest(Node* node, UnusedNodesMap* unusedNodesMap)
{
    Digest* digest = new Digest(node);

    OwnPtr<blink::WebCryptoDigestor> digestor = createDigestor(HashAlgorithmSha1);
    DigestValue digestResult;

    Node::NodeType nodeType = node->nodeType();
    digestor->consume(reinterpret_cast<const unsigned char*>(&nodeType), sizeof(nodeType));
    addStringToDigestor(digestor.get(), node->nodeName());
    addStringToDigestor(digestor.get(), node->nodeValue());

    if (node->isElementNode()) {
        Element& element = toElement(*node);
        Node* child = element.firstChild();
        while (child) {
            OwnPtr<Digest> childInfo = createDigest(child, unusedNodesMap);
            addStringToDigestor(digestor.get(), childInfo->m_sha1);
            child = child->nextSibling();
            digest->m_children.append(childInfo.release());
        }

        if (element.hasAttributesWithoutUpdate()) {
            OwnPtr<blink::WebCryptoDigestor> attrsDigestor = createDigestor(HashAlgorithmSha1);
            AttributeCollection attributes = element.attributes();
            AttributeCollection::const_iterator end = attributes.end();
            for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it) {
                addStringToDigestor(attrsDigestor.get(), it->name().toString());
                addStringToDigestor(attrsDigestor.get(), it->value().string());
            }
            finishDigestor(attrsDigestor.get(), digestResult);
            digest->m_attrsSHA1 = base64Encode(reinterpret_cast<const char*>(digestResult.data()), 10);
            addStringToDigestor(digestor.get(), digest->m_attrsSHA1);
            digestResult.clear();
        }
    }
    finishDigestor(digestor.get(), digestResult);
    digest->m_sha1 = base64Encode(reinterpret_cast<const char*>(digestResult.data()), 10);

    if (unusedNodesMap)
        unusedNodesMap->add(digest->m_sha1, digest);
    return adoptPtr(digest);
}
String WebSocketHandshake::getExpectedWebSocketAccept(const String& secWebSocketKey)
{
    static const char webSocketKeyGUID[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
    CString keyData = secWebSocketKey.ascii();

    StringBuilder digestable;
    digestable.append(secWebSocketKey);
    digestable.append(webSocketKeyGUID, strlen(webSocketKeyGUID));
    CString digestableCString = digestable.toString().utf8();
    DigestValue digest;
    bool digestSuccess = computeDigest(HashAlgorithmSha1, digestableCString.data(), digestableCString.length(), digest);
    RELEASE_ASSERT(digestSuccess);

    return base64Encode(reinterpret_cast<const char*>(digest.data()), sha1HashSize);
}
String InspectorAnimationAgent::createCSSId(blink::Animation& animation) {
  String type =
      m_idToAnimationType.get(String::number(animation.sequenceNumber()));
  ASSERT(type != AnimationType::WebAnimation);

  KeyframeEffect* effect = toKeyframeEffect(animation.effect());
  Vector<CSSPropertyID> cssProperties;
  if (type == AnimationType::CSSAnimation) {
    for (CSSPropertyID property : animationProperties)
      cssProperties.append(property);
  } else {
    for (CSSPropertyID property : transitionProperties)
      cssProperties.append(property);
    cssProperties.append(cssPropertyID(animation.id()));
  }

  Element* element = effect->target();
  HeapVector<Member<CSSStyleDeclaration>> styles =
      m_cssAgent->matchingStyles(element);
  std::unique_ptr<WebCryptoDigestor> digestor =
      createDigestor(HashAlgorithmSha1);
  addStringToDigestor(digestor.get(), type);
  addStringToDigestor(digestor.get(), animation.id());
  for (CSSPropertyID property : cssProperties) {
    CSSStyleDeclaration* style =
        m_cssAgent->findEffectiveDeclaration(property, styles);
    // Ignore inline styles.
    if (!style || !style->parentStyleSheet() || !style->parentRule() ||
        style->parentRule()->type() != CSSRule::kStyleRule)
      continue;
    addStringToDigestor(digestor.get(), getPropertyNameString(property));
    addStringToDigestor(digestor.get(),
                        m_cssAgent->styleSheetId(style->parentStyleSheet()));
    addStringToDigestor(digestor.get(),
                        toCSSStyleRule(style->parentRule())->selectorText());
  }
  DigestValue digestResult;
  finishDigestor(digestor.get(), digestResult);
  return base64Encode(reinterpret_cast<const char*>(digestResult.data()), 10);
}
static String digestToString(const DigestValue& digest)
{
    return base64Encode(reinterpret_cast<const char*>(digest.data()), digest.size(), Base64DoNotInsertLFs);
}