Example #1
0
PassRefPtr<API::Array> WebFrame::childFrames()
{
    if (!m_coreFrame)
        return API::Array::create();

    size_t size = m_coreFrame->tree().childCount();
    if (!size)
        return API::Array::create();

    Vector<RefPtr<API::Object>> vector;
    vector.reserveInitialCapacity(size);

    for (Frame* child = m_coreFrame->tree().firstChild(); child; child = child->tree().nextSibling()) {
        WebFrame* webFrame = WebFrame::fromCoreFrame(*child);
        ASSERT(webFrame);
        vector.uncheckedAppend(webFrame);
    }

    return API::Array::create(WTF::move(vector));
}
Example #2
0
void FontFaceSet::forEachInternal(PassOwnPtr<FontFaceSetForEachCallback> callback, const ScriptValue* thisArg) const
{
    if (!inActiveDocumentContext())
        return;
    const ListHashSet<RefPtr<FontFace> >& cssConnectedFaces = cssConnectedFontFaceList();
    Vector<RefPtr<FontFace> > fontFaces;
    fontFaces.reserveInitialCapacity(cssConnectedFaces.size() + m_nonCSSConnectedFaces.size());
    for (ListHashSet<RefPtr<FontFace> >::const_iterator it = cssConnectedFaces.begin(); it != cssConnectedFaces.end(); ++it)
        fontFaces.append(*it);
    for (ListHashSet<RefPtr<FontFace> >::const_iterator it = m_nonCSSConnectedFaces.begin(); it != m_nonCSSConnectedFaces.end(); ++it)
        fontFaces.append(*it);

    for (size_t i = 0; i < fontFaces.size(); ++i) {
        FontFace* face = fontFaces[i].get();
        if (thisArg)
            callback->handleItem(*thisArg, face, face, const_cast<FontFaceSet*>(this));
        else
            callback->handleItem(face, face, const_cast<FontFaceSet*>(this));
    }
}
Example #3
0
Vector<WebPopupItem> WebPopupMenu::populateItems()
{
    size_t size = m_popupClient->listSize();

    Vector<WebPopupItem> items;
    items.reserveInitialCapacity(size);
    
    for (size_t i = 0; i < size; ++i) {
        if (m_popupClient->itemIsSeparator(i))
            items.append(WebPopupItem(WebPopupItem::Seperator));
        else {
            // FIXME: Add support for styling the font.
            // FIXME: Add support for styling the foreground and background colors.
            // FIXME: Find a way to customize text color when an item is highlighted.
            items.append(WebPopupItem(WebPopupItem::Item, m_popupClient->itemText(i), m_popupClient->itemToolTip(i), m_popupClient->itemAccessibilityText(i), m_popupClient->itemIsEnabled(i), m_popupClient->itemIsLabel(i)));
        }
    }

    return items;
}
void WebOpenPanelResultListenerProxy::chooseFiles(ImmutableArray* fileURLsArray)
{
    if (!m_page)
        return;

    size_t size = fileURLsArray->size();

    Vector<String> filePaths;
    filePaths.reserveInitialCapacity(size);

    for (size_t i = 0; i < size; ++i) {
        WebURL* webURL = fileURLsArray->at<WebURL>(i);
        if (webURL) {
            KURL url(KURL(), webURL->string()); 
            filePaths.uncheckedAppend(url.fileSystemPath());
        }
    }

    m_page->didChooseFilesForOpenPanel(filePaths);
}
Example #5
0
void NodeSet::sort() const
{
    if (m_isSorted)
        return;

    unsigned nodeCount = m_nodes.size();
    if (nodeCount < 2) {
        const_cast<bool&>(m_isSorted) = true;
        return;
    }

    if (nodeCount > traversalSortCutoff) {
        traversalSort();
        return;
    }

    bool containsAttributeNodes = false;

    Vector<Vector<Node*> > parentMatrix(nodeCount);
    for (unsigned i = 0; i < nodeCount; ++i) {
        Vector<Node*>& parentsVector = parentMatrix[i];
        Node* n = m_nodes[i].get();
        parentsVector.append(n);
        if (n->isAttributeNode()) {
            n = static_cast<Attr*>(n)->ownerElement();
            parentsVector.append(n);
            containsAttributeNodes = true;
        }
        while ((n = n->parentNode()))
            parentsVector.append(n);
    }
    sortBlock(0, nodeCount, parentMatrix, containsAttributeNodes);

    // It is not possible to just assign the result to m_nodes, because some nodes may get dereferenced and destroyed.
    Vector<RefPtr<Node> > sortedNodes;
    sortedNodes.reserveInitialCapacity(nodeCount);
    for (unsigned i = 0; i < nodeCount; ++i)
        sortedNodes.append(parentMatrix[i][0]);

    const_cast<Vector<RefPtr<Node> >&>(m_nodes).swap(sortedNodes);
}
void HTMLFormattingElementList::ensureNoahsArkCondition(HTMLStackItem* newItem)
{
    Vector<HTMLStackItem*> candidates;
    tryToEnsureNoahsArkConditionQuickly(newItem, candidates);
    if (candidates.isEmpty())
        return;

    // We pre-allocate and re-use this second vector to save one malloc per
    // attribute that we verify.
    Vector<HTMLStackItem*> remainingCandidates;
    remainingCandidates.reserveInitialCapacity(candidates.size());

    const Vector<Attribute>& attributes = newItem->attributes();
    for (size_t i = 0; i < attributes.size(); ++i) {
        const Attribute& attribute = attributes[i];

        for (size_t j = 0; j < candidates.size(); ++j) {
            HTMLStackItem* candidate = candidates[j];

            // These properties should already have been checked by tryToEnsureNoahsArkConditionQuickly.
            ASSERT(newItem->attributes().size() == candidate->attributes().size());
            ASSERT(newItem->localName() == candidate->localName() && newItem->namespaceURI() == candidate->namespaceURI());

            Attribute* candidateAttribute = candidate->getAttributeItem(attribute.name());
            if (candidateAttribute && candidateAttribute->value() == attribute.value())
                remainingCandidates.append(candidate);
        }

        if (remainingCandidates.size() < kNoahsArkCapacity)
            return;

        candidates.swap(remainingCandidates);
        remainingCandidates.shrink(0);
    }

    // Inductively, we shouldn't spin this loop very many times. It's possible,
    // however, that we wil spin the loop more than once because of how the
    // formatting element list gets permuted.
    for (size_t i = kNoahsArkCapacity - 1; i < candidates.size(); ++i)
        remove(candidates[i]->element());
}
Example #7
0
void FontCache::purgeInactiveFontData(unsigned purgeCount)
{
    pruneUnreferencedEntriesFromFontCascadeCache();
    pruneSystemFallbackFonts();

#if PLATFORM(IOS)
    FontLocker fontLocker;
#endif

    while (purgeCount) {
        Vector<RefPtr<Font>, 20> fontsToDelete;
        for (auto& font : cachedFonts().values()) {
            if (!font->hasOneRef())
                continue;
            fontsToDelete.append(WTFMove(font));
            if (!--purgeCount)
                break;
        }
        // Fonts may ref other fonts so we loop until there are no changes.
        if (fontsToDelete.isEmpty())
            break;
        for (auto& font : fontsToDelete) {
            bool success = cachedFonts().remove(font->platformData());
            ASSERT_UNUSED(success, success);
#if ENABLE(OPENTYPE_VERTICAL)
            fontVerticalDataCache().remove(font->platformData());
#endif
        }
    };

    Vector<FontPlatformDataCacheKey> keysToRemove;
    keysToRemove.reserveInitialCapacity(fontPlatformDataCache().size());
    for (auto& entry : fontPlatformDataCache()) {
        if (entry.value && !cachedFonts().contains(*entry.value))
            keysToRemove.append(entry.key);
    }
    for (auto& key : keysToRemove)
        fontPlatformDataCache().remove(key);

    platformPurgeInactiveFontData();
}
Example #8
0
PassRefPtr<API::Array> WebFrame::childFrames()
{
    if (!m_coreFrame)
        return API::Array::create();

    size_t size = m_coreFrame->tree().childCount();
    if (!size)
        return API::Array::create();

    Vector<RefPtr<API::Object>> vector;
    vector.reserveInitialCapacity(size);

    for (Frame* child = m_coreFrame->tree().firstChild(); child; child = child->tree().nextSibling()) {
        WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient(child->loader().client());
        WebFrame* webFrame = webFrameLoaderClient ? webFrameLoaderClient->webFrame() : 0;
        ASSERT(webFrame);
        vector.uncheckedAppend(webFrame);
    }

    return API::Array::create(std::move(vector));
}
Example #9
0
void FontCache::invalidate()
{
    if (!gClients) {
        ASSERT(fontPlatformDataCache().isEmpty());
        return;
    }

    fontPlatformDataCache().clear();
    invalidateFontCascadeCache();

    gGeneration++;

    Vector<Ref<FontSelector>> clients;
    clients.reserveInitialCapacity(gClients->size());
    for (auto it = gClients->begin(), end = gClients->end(); it != end; ++it)
        clients.uncheckedAppend(**it);

    for (unsigned i = 0; i < clients.size(); ++i)
        clients[i]->fontCacheInvalidated();

    purgeInactiveFontData();
}
Example #10
0
void NodeSet::traversalSort() const
{
    HashSet<Node*> nodes;
    bool containsAttributeNodes = false;

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

    Vector<RefPtr<Node>> sortedNodes;
    sortedNodes.reserveInitialCapacity(nodeCount);

    for (Node* n = findRootNode(m_nodes.first().get()); n; n = NodeTraversal::next(n)) {
        if (nodes.contains(n))
            sortedNodes.append(n);

        if (!containsAttributeNodes || !n->isElementNode())
            continue;

        Element* element = toElement(n);
        if (!element->hasAttributes())
            continue;

        for (const Attribute& attribute : element->attributesIterator()) {
            RefPtr<Attr> attr = element->attrIfExists(attribute.name());
            if (attr && nodes.contains(attr.get()))
                sortedNodes.append(attr);
        }
    }

    ASSERT(sortedNodes.size() == nodeCount);
    m_nodes = std::move(sortedNodes);
    m_isSorted = true;
}
Example #11
0
void IDBDatabase::stop()
{
    LOG(IndexedDB, "IDBDatabase::stop - %" PRIu64, m_databaseConnectionIdentifier);

    ASSERT(&originThread() == &Thread::current());

    removeAllEventListeners();

    Vector<IDBResourceIdentifier> transactionIdentifiers;
    transactionIdentifiers.reserveInitialCapacity(m_activeTransactions.size());

    for (auto& id : m_activeTransactions.keys())
        transactionIdentifiers.uncheckedAppend(id);

    for (auto& id : transactionIdentifiers) {
        IDBTransaction* transaction = m_activeTransactions.get(id);
        if (transaction)
            transaction->stop();
    }

    close();
}
Example #12
0
void NodeSet::traversalSort() const
{
    HashSet<Node*> nodes;
    bool containsAttributeNodes = false;

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

    Vector<RefPtr<Node> > sortedNodes;
    sortedNodes.reserveInitialCapacity(nodeCount);

    for (Node* n = findRootNode(m_nodes.first().get()); n; n = n->traverseNextNode()) {
        if (nodes.contains(n))
            sortedNodes.append(n);

        if (!containsAttributeNodes || !n->isElementNode())
            continue;

        Element* element = toElement(n);
        if (!element->hasAttributes())
            continue;

        unsigned attributeCount = element->attributeCount();
        for (unsigned i = 0; i < attributeCount; ++i) {
            Attr* attribute = element->attributeItem(i)->attr();
            if (attribute && nodes.contains(attribute))
                sortedNodes.append(attribute);
        }
    }

    ASSERT(sortedNodes.size() == nodeCount);
    const_cast<Vector<RefPtr<Node> >&>(m_nodes).swap(sortedNodes);
}
PassRefPtr<ImmutableArray> WebBackForwardList::forwardListAsImmutableArrayWithLimit(unsigned limit) const
{
    ASSERT(!m_hasCurrentIndex || m_currentIndex < m_entries.size());

    if (!m_page || !m_hasCurrentIndex)
        return ImmutableArray::create();

    unsigned size = std::min(static_cast<unsigned>(forwardListCount()), limit);
    if (!size)
        return ImmutableArray::create();

    Vector<RefPtr<APIObject> > vector;
    vector.reserveInitialCapacity(size);

    unsigned last = m_currentIndex + size;
    ASSERT(last < m_entries.size());
    for (unsigned i = m_currentIndex + 1; i <= last; ++i) {
        ASSERT(m_entries[i]);
        vector.uncheckedAppend(m_entries[i].get());
    }

    return ImmutableArray::adopt(vector);
}
Example #14
0
PassRefPtr<API::Array> WebBackForwardList::backListAsAPIArrayWithLimit(unsigned limit) const
{
    ASSERT(!m_hasCurrentIndex || m_currentIndex < m_entries.size());

    if (!m_page || !m_hasCurrentIndex)
        return API::Array::create();

    unsigned backListSize = static_cast<unsigned>(backListCount());
    unsigned size = std::min(backListSize, limit);
    if (!size)
        return API::Array::create();

    Vector<RefPtr<API::Object>> vector;
    vector.reserveInitialCapacity(size);

    ASSERT(backListSize >= size);
    for (unsigned i = backListSize - size; i < backListSize; ++i) {
        ASSERT(m_entries[i]);
        vector.uncheckedAppend(m_entries[i].get());
    }

    return API::Array::create(std::move(vector));
}
static ExceptionOr<Vector<Ref<FileSystemEntry>>> toFileSystemEntries(ScriptExecutionContext& context, DOMFileSystem& fileSystem, ExceptionOr<Vector<ListedChild>>&& listedChildren, const String& parentVirtualPath)
{
    ASSERT(isMainThread());
    if (listedChildren.hasException())
        return listedChildren.releaseException();

    Vector<Ref<FileSystemEntry>> entries;
    entries.reserveInitialCapacity(listedChildren.returnValue().size());
    for (auto& child : listedChildren.returnValue()) {
        String virtualPath = parentVirtualPath + "/" + child.filename;
        switch (child.type) {
        case FileMetadata::Type::File:
            entries.uncheckedAppend(FileSystemFileEntry::create(context, fileSystem, virtualPath));
            break;
        case FileMetadata::Type::Directory:
            entries.uncheckedAppend(FileSystemDirectoryEntry::create(context, fileSystem, virtualPath));
            break;
        default:
            break;
        }
    }
    return WTFMove(entries);
}
static void didGetStorageDetailsByOrigin(const Vector<LocalStorageDetails>& storageDetails, void* context)
{
    RefPtr<ArrayCallback> callback = adoptRef(static_cast<ArrayCallback*>(context));

    Vector<RefPtr<API::Object>> result;
    result.reserveInitialCapacity(storageDetails.size());

    for (const LocalStorageDetails& originDetails : storageDetails) {
        HashMap<String, RefPtr<API::Object>> detailsMap;

        RefPtr<API::Object> origin = WebSecurityOrigin::createFromDatabaseIdentifier(originDetails.originIdentifier);

        detailsMap.set(WebKeyValueStorageManager::originKey(), origin);
        if (originDetails.creationTime)
            detailsMap.set(WebKeyValueStorageManager::creationTimeKey(), API::Double::create(originDetails.creationTime));
        if (originDetails.modificationTime)
            detailsMap.set(WebKeyValueStorageManager::modificationTimeKey(), API::Double::create(originDetails.modificationTime));

        result.uncheckedAppend(ImmutableDictionary::create(std::move(detailsMap)));
    }

    callback->performCallbackWithReturnValue(API::Array::create(std::move(result)).get());
}
Example #17
0
void EventPath::updateTouchLists(const TouchEvent& touchEvent)
{
    Vector<EventRelatedNodeResolver, 16> touchTargetResolvers;
    const size_t touchNodeCount = touchEvent.touches()->length() + touchEvent.targetTouches()->length() + touchEvent.changedTouches()->length();
    touchTargetResolvers.reserveInitialCapacity(touchNodeCount);

    addRelatedNodeResolversForTouchList(touchTargetResolvers, touchEvent.touches(), TouchEventContext::Touches);
    addRelatedNodeResolversForTouchList(touchTargetResolvers, touchEvent.targetTouches(), TouchEventContext::TargetTouches);
    addRelatedNodeResolversForTouchList(touchTargetResolvers, touchEvent.changedTouches(), TouchEventContext::ChangedTouches);

    ASSERT(touchTargetResolvers.size() == touchNodeCount);
    size_t eventPathSize = m_path.size();
    for (size_t i = 0; i < eventPathSize; ++i) {
        TouchEventContext& context = toTouchEventContext(*m_path[i]);
        Node& nodeToMoveTo = *context.node();
        for (size_t resolverIndex = 0; resolverIndex < touchNodeCount; ++resolverIndex) {
            EventRelatedNodeResolver& currentResolver = touchTargetResolvers[resolverIndex];
            Node* nodeInCurrentTreeScope = currentResolver.moveToParentOrShadowHost(nodeToMoveTo);
            ASSERT(currentResolver.touch());
            context.touchList(currentResolver.touchListType())->append(currentResolver.touch()->cloneWithNewTarget(nodeInCurrentTreeScope));
        }
    }
}
static bool findIndicatorsForTextRectsOverlap(const Vector<FloatRect>& textRects)
{
    size_t count = textRects.size();
    if (count <= 1)
        return false;

    Vector<FloatRect> indicatorRects;
    indicatorRects.reserveInitialCapacity(count);

    for (size_t i = 0; i < count; ++i) {
        FloatRect indicatorRect = outsetIndicatorRectIncludingShadow(textRects[i]);

        for (size_t j = indicatorRects.size(); j; ) {
            --j;
            if (indicatorRect.intersects(indicatorRects[j]))
                return true;
        }

        indicatorRects.uncheckedAppend(indicatorRect);
    }

    return false;
}
String Color::serialized() const
{
    if (!hasAlpha()) {
        StringBuilder builder;
        builder.reserveCapacity(7);
        builder.append('#');
        appendByteAsHex(red(), builder, Lowercase);
        appendByteAsHex(green(), builder, Lowercase);
        appendByteAsHex(blue(), builder, Lowercase);
        return builder.toString();
    }

    Vector<LChar> result;
    result.reserveInitialCapacity(28);
    const char commaSpace[] = ", ";
    const char rgbaParen[] = "rgba(";

    result.append(rgbaParen, 5);
    appendNumber(result, red());
    result.append(commaSpace, 2);
    appendNumber(result, green());
    result.append(commaSpace, 2);
    appendNumber(result, blue());
    result.append(commaSpace, 2);

    if (!alpha())
        result.append('0');
    else {
        NumberToLStringBuffer buffer;
        unsigned length = DecimalNumber(alpha() / 255.0).toStringDecimal(buffer, WTF::NumberToStringBufferLength);
        result.append(buffer, length);
    }

    result.append(')');
    return String::adopt(result);
}
Example #20
0
String CookieManager::getCookie(const KURL& url, CookieFilter filter) const
{
    Vector<ParsedCookie*> rawCookies;
    rawCookies.reserveInitialCapacity(s_maxCookieCountPerHost);

    // Retrieve cookies related to this url
    getRawCookies(rawCookies, url, filter);

    CookieLog("CookieManager - there are %d cookies in raw cookies\n", rawCookies.size());

    // Generate the cookie header string using the retrieved cookies
    StringBuilder cookieStringBuilder;
    cookieStringBuilder.reserveCapacity(512);
    size_t cookieSize = rawCookies.size();
    for (size_t i = 0; i < cookieSize; i++) {
        cookieStringBuilder.append(rawCookies[i]->toNameValuePair());
        if (i != cookieSize-1)
            cookieStringBuilder.append("; ");
    }

    CookieLog("CookieManager - cookieString is - %s\n", cookieStringBuilder.toString().utf8().data());

    return cookieStringBuilder.toString();
}
String CookieManager::getCookie(const KURL& url, HttpOnlyCookieFiltering filter)
{
    bool isConnectionSecure = false;
    static String httpsPrefix("https:");
    if (url.string().startsWith(httpsPrefix, false))
        isConnectionSecure = true;

    // The max size is the number of cookie per host multiplied by the maximum length of a cookie. We add 1 for the final '\0'.
    static const size_t cookiesMaxLength = s_maxCookieLength * s_maxCookieCountPerHost + 1;
    Vector<UChar> cookiePairs;
    cookiePairs.reserveInitialCapacity(cookiesMaxLength);
    for (HashMap<String, CookieMap*>::iterator it = m_managerMap.begin(); it != m_managerMap.end(); ++it) {

        // Handle sub-domain by only looking at the end of the host.
        if (it->first.endsWith(url.host()) || (it->first.startsWith(".", false) && ("." + url.host()).endsWith(it->first, false))) {
            // Get CookieMap to check for expired cookies.
            Vector<ParsedCookie*> cookies = it->second->getCookies();

            for (size_t i = 0; i < cookies.size(); ++i) {
                ParsedCookie* cookie = cookies[i];
                // Get the cookies filtering out the secure cookies on an unsecure connection and HttpOnly cookies if requested.
                if (url.path().startsWith(cookie->path(), false) && (isConnectionSecure || !cookie->isSecure()) && (filter == WithHttpOnlyCookies || !cookie->isHttpOnly())) {
                    String nameValuePair = cookie->toNameValuePair();
                    append(cookiePairs, nameValuePair);
                }
            }
        }
    }
    // Per construction of our cookies, we should not grow our vector.
    ASSERT(cookiePairs.capacity() == cookiesMaxLength);

    // Append the final '\0'.
    static const String nullTerminator("\0");
    append(cookiePairs, nullTerminator);
    return String::adopt(cookiePairs);
}
String SecurityOrigin::toString() const
{
    if (isEmpty())
        return "null";

    if (m_noAccess)
        return "null";

    if (m_protocol == "file")
        return String("file://");

    Vector<UChar> result;
    result.reserveInitialCapacity(m_protocol.length() + m_host.length() + 10);
    append(result, m_protocol);
    append(result, "://");
    append(result, m_host);

    if (m_port) {
        append(result, ":");
        append(result, String::number(m_port));
    }

    return String::adopt(result);
}
Example #23
0
ALWAYS_INLINE String CSSPrimitiveValue::formatNumberForcustomCSSText() const
{
    switch (m_primitiveUnitType) {
    case CSS_UNKNOWN:
        return String();
    case CSS_NUMBER:
    case CSS_PARSER_INTEGER:
        return formatNumberValue("");
    case CSS_PERCENTAGE:
        return formatNumberValue("%");
    case CSS_EMS:
        return formatNumberValue("em");
    case CSS_EXS:
        return formatNumberValue("ex");
    case CSS_REMS:
        return formatNumberValue("rem");
    case CSS_CHS:
        return formatNumberValue("ch");
    case CSS_PX:
        return formatNumberValue("px");
    case CSS_CM:
        return formatNumberValue("cm");
#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY)
    case CSS_DPPX:
        return formatNumberValue("dppx");
    case CSS_DPI:
        return formatNumberValue("dpi");
    case CSS_DPCM:
        return formatNumberValue("dpcm");
#endif
    case CSS_MM:
        return formatNumberValue("mm");
    case CSS_IN:
        return formatNumberValue("in");
    case CSS_PT:
        return formatNumberValue("pt");
    case CSS_PC:
        return formatNumberValue("pc");
    case CSS_DEG:
        return formatNumberValue("deg");
    case CSS_RAD:
        return formatNumberValue("rad");
    case CSS_GRAD:
        return formatNumberValue("grad");
    case CSS_MS:
        return formatNumberValue("ms");
    case CSS_S:
        return formatNumberValue("s");
    case CSS_HZ:
        return formatNumberValue("hz");
    case CSS_KHZ:
        return formatNumberValue("khz");
    case CSS_TURN:
        return formatNumberValue("turn");
    case CSS_FR:
        return formatNumberValue("fr");
    case CSS_DIMENSION:
        // FIXME: We currently don't handle CSS_DIMENSION properly as we don't store
        // the actual dimension, just the numeric value as a string.
    case CSS_STRING:
        return quoteCSSStringIfNeeded(m_value.string);
    case CSS_URI:
        return "url(" + quoteCSSURLIfNeeded(m_value.string) + ')';
    case CSS_VALUE_ID:
        return valueName(m_value.valueID);
    case CSS_PROPERTY_ID:
        return propertyName(m_value.propertyID);
    case CSS_ATTR: {
        StringBuilder result;
        result.reserveCapacity(6 + m_value.string->length());
        result.appendLiteral("attr(");
        result.append(m_value.string);
        result.append(')');

        return result.toString();
    }
    case CSS_COUNTER_NAME:
        return "counter(" + String(m_value.string) + ')';
    case CSS_COUNTER: {
        StringBuilder result;
        String separator = m_value.counter->separator();
        if (separator.isEmpty())
            result.appendLiteral("counter(");
        else
            result.appendLiteral("counters(");

        result.append(m_value.counter->identifier());
        if (!separator.isEmpty()) {
            result.appendLiteral(", ");
            result.append(quoteCSSStringIfNeeded(separator));
        }
        String listStyle = m_value.counter->listStyle();
        if (!listStyle.isEmpty()) {
            result.appendLiteral(", ");
            result.append(listStyle);
        }
        result.append(')');

        return result.toString();
    }
    case CSS_RECT:
        return getRectValue()->cssText();
    case CSS_QUAD:
        return getQuadValue()->cssText();
    case CSS_RGBCOLOR:
    case CSS_PARSER_HEXCOLOR: {
        RGBA32 rgbColor = m_value.rgbcolor;
        if (m_primitiveUnitType == CSS_PARSER_HEXCOLOR)
            Color::parseHexColor(m_value.string, rgbColor);
        Color color(rgbColor);

        Vector<LChar> result;
        result.reserveInitialCapacity(32);
        bool colorHasAlpha = color.hasAlpha();
        if (colorHasAlpha)
            result.append("rgba(", 5);
        else
            result.append("rgb(", 4);

        appendNumber(result, static_cast<unsigned char>(color.red()));
        result.append(", ", 2);

        appendNumber(result, static_cast<unsigned char>(color.green()));
        result.append(", ", 2);

        appendNumber(result, static_cast<unsigned char>(color.blue()));
        if (colorHasAlpha) {
            result.append(", ", 2);

            NumberToStringBuffer buffer;
            const char* alphaString = numberToFixedPrecisionString(color.alpha() / 255.0f, 6, buffer, true);
            result.append(alphaString, strlen(alphaString));
        }

        result.append(')');
        return String::adopt(result);
    }
    case CSS_PAIR:
        return getPairValue()->cssText();
#if ENABLE(DASHBOARD_SUPPORT)
    case CSS_DASHBOARD_REGION: {
        StringBuilder result;
        for (DashboardRegion* region = getDashboardRegionValue(); region; region = region->m_next.get()) {
            if (!result.isEmpty())
                result.append(' ');
            result.appendLiteral("dashboard-region(");
            result.append(region->m_label);
            if (region->m_isCircle)
                result.appendLiteral(" circle");
            else if (region->m_isRectangle)
                result.appendLiteral(" rectangle");
            else
                break;
            if (region->top()->m_primitiveUnitType == CSS_VALUE_ID && region->top()->getValueID() == CSSValueInvalid) {
                ASSERT(region->right()->m_primitiveUnitType == CSS_VALUE_ID);
                ASSERT(region->bottom()->m_primitiveUnitType == CSS_VALUE_ID);
                ASSERT(region->left()->m_primitiveUnitType == CSS_VALUE_ID);
                ASSERT(region->right()->getValueID() == CSSValueInvalid);
                ASSERT(region->bottom()->getValueID() == CSSValueInvalid);
                ASSERT(region->left()->getValueID() == CSSValueInvalid);
            } else {
                result.append(' ');
                result.append(region->top()->cssText());
                result.append(' ');
                result.append(region->right()->cssText());
                result.append(' ');
                result.append(region->bottom()->cssText());
                result.append(' ');
                result.append(region->left()->cssText());
            }
            result.append(')');
        }
        return result.toString();
    }
#endif
    case CSS_PARSER_OPERATOR: {
        char c = static_cast<char>(m_value.parserOperator);
        return String(&c, 1U);
    }
    case CSS_PARSER_IDENTIFIER:
        return quoteCSSStringIfNeeded(m_value.string);
    case CSS_CALC:
        return m_value.calc->cssText();
    case CSS_SHAPE:
        return m_value.shape->cssText();
    case CSS_VW:
        return formatNumberValue("vw");
    case CSS_VH:
        return formatNumberValue("vh");
    case CSS_VMIN:
        return formatNumberValue("vmin");
    case CSS_VMAX:
        return formatNumberValue("vmax");
    }
    return String();
}
Example #24
0
String CSSPrimitiveValue::customCssText() const
{
    // FIXME: return the original value instead of a generated one (e.g. color
    // name if it was specified) - check what spec says about this

    if (m_hasCachedCSSText) {
        ASSERT(cssTextCache().contains(this));
        return cssTextCache().get(this);
    }

    String text;
    switch (m_primitiveUnitType) {
        case CSS_UNKNOWN:
            // FIXME
            break;
        case CSS_NUMBER:
        case CSS_PARSER_INTEGER:
            text = formatNumber(m_value.num, "");
            break;
        case CSS_PERCENTAGE:
            text = formatNumber(m_value.num, "%");
            break;
        case CSS_EMS:
            text = formatNumber(m_value.num, "em");
            break;
        case CSS_EXS:
            text = formatNumber(m_value.num, "ex");
            break;
        case CSS_REMS:
            text = formatNumber(m_value.num, "rem");
            break;
        case CSS_CHS:
            text = formatNumber(m_value.num, "ch");
            break;
        case CSS_PX:
            text = formatNumber(m_value.num, "px");
            break;
        case CSS_CM:
            text = formatNumber(m_value.num, "cm");
            break;
#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY)
        case CSS_DPPX:
            text = formatNumber(m_value.num, "dppx");
            break;
        case CSS_DPI:
            text = formatNumber(m_value.num, "dpi");
            break;
        case CSS_DPCM:
            text = formatNumber(m_value.num, "dpcm");
            break;
#endif
        case CSS_MM:
            text = formatNumber(m_value.num, "mm");
            break;
        case CSS_IN:
            text = formatNumber(m_value.num, "in");
            break;
        case CSS_PT:
            text = formatNumber(m_value.num, "pt");
            break;
        case CSS_PC:
            text = formatNumber(m_value.num, "pc");
            break;
        case CSS_DEG:
            text = formatNumber(m_value.num, "deg");
            break;
        case CSS_RAD:
            text = formatNumber(m_value.num, "rad");
            break;
        case CSS_GRAD:
            text = formatNumber(m_value.num, "grad");
            break;
        case CSS_MS:
            text = formatNumber(m_value.num, "ms");
            break;
        case CSS_S:
            text = formatNumber(m_value.num, "s");
            break;
        case CSS_HZ:
            text = formatNumber(m_value.num, "hz");
            break;
        case CSS_KHZ:
            text = formatNumber(m_value.num, "khz");
            break;
        case CSS_TURN:
            text = formatNumber(m_value.num, "turn");
            break;
        case CSS_DIMENSION:
            // FIXME
            break;
        case CSS_STRING:
            text = quoteCSSStringIfNeeded(m_value.string);
            break;
        case CSS_URI:
            text = "url(" + quoteCSSURLIfNeeded(m_value.string) + ")";
            break;
        case CSS_IDENT:
            text = valueOrPropertyName(m_value.ident);
            break;
        case CSS_ATTR: {
            StringBuilder result;
            result.reserveCapacity(6 + m_value.string->length());
            result.appendLiteral("attr(");
            result.append(m_value.string);
            result.append(')');

            text = result.toString();
            break;
        }
        case CSS_COUNTER_NAME:
            text = "counter(" + String(m_value.string) + ')';
            break;
        case CSS_COUNTER: {
            StringBuilder result;
            String separator = m_value.counter->separator();
            if (separator.isEmpty())
                result.appendLiteral("counter(");
            else
                result.appendLiteral("counters(");

            result.append(m_value.counter->identifier());
            if (!separator.isEmpty()) {
                result.appendLiteral(", ");
                result.append(quoteCSSStringIfNeeded(separator));
            }
            String listStyle = m_value.counter->listStyle();
            if (!listStyle.isEmpty()) {
                result.appendLiteral(", ");
                result.append(listStyle);
            }
            result.append(')');

            text = result.toString();
            break;
        }
        case CSS_RECT:
            text = getRectValue()->cssText();
            break;
        case CSS_QUAD:
            text = getQuadValue()->cssText();
            break;
        case CSS_RGBCOLOR:
        case CSS_PARSER_HEXCOLOR: {
            RGBA32 rgbColor = m_value.rgbcolor;
            if (m_primitiveUnitType == CSS_PARSER_HEXCOLOR)
                Color::parseHexColor(m_value.string, rgbColor);
            Color color(rgbColor);

            Vector<LChar> result;
            result.reserveInitialCapacity(32);
            bool colorHasAlpha = color.hasAlpha();
            if (colorHasAlpha)
                result.append("rgba(", 5);
            else
                result.append("rgb(", 4);

            appendNumber(result, static_cast<unsigned char>(color.red()));
            result.append(", ", 2);

            appendNumber(result, static_cast<unsigned char>(color.green()));
            result.append(", ", 2);

            appendNumber(result, static_cast<unsigned char>(color.blue()));
            if (colorHasAlpha) {
                result.append(", ", 2);

                NumberToStringBuffer buffer;
                const char* alphaString = numberToFixedPrecisionString(color.alpha() / 255.0f, 6, buffer, true);
                result.append(alphaString, strlen(alphaString));
            }

            result.append(')');
            text = String::adopt(result);
            break;
        }
        case CSS_PAIR:
            text = getPairValue()->cssText();
            break;
#if ENABLE(DASHBOARD_SUPPORT)
        case CSS_DASHBOARD_REGION: {
            StringBuilder result;
            for (DashboardRegion* region = getDashboardRegionValue(); region; region = region->m_next.get()) {
                if (!result.isEmpty())
                    result.append(' ');
                result.appendLiteral("dashboard-region(");
                result.append(region->m_label);
                if (region->m_isCircle)
                    result.appendLiteral(" circle");
                else if (region->m_isRectangle)
                    result.appendLiteral(" rectangle");
                else
                    break;
                if (region->top()->m_primitiveUnitType == CSS_IDENT && region->top()->getIdent() == CSSValueInvalid) {
                    ASSERT(region->right()->m_primitiveUnitType == CSS_IDENT);
                    ASSERT(region->bottom()->m_primitiveUnitType == CSS_IDENT);
                    ASSERT(region->left()->m_primitiveUnitType == CSS_IDENT);
                    ASSERT(region->right()->getIdent() == CSSValueInvalid);
                    ASSERT(region->bottom()->getIdent() == CSSValueInvalid);
                    ASSERT(region->left()->getIdent() == CSSValueInvalid);
                } else {
                    result.append(' ');
                    result.append(region->top()->cssText());
                    result.append(' ');
                    result.append(region->right()->cssText());
                    result.append(' ');
                    result.append(region->bottom()->cssText());
                    result.append(' ');
                    result.append(region->left()->cssText());
                }
                result.append(')');
            }
            text = result.toString();
            break;
        }
#endif
        case CSS_PARSER_OPERATOR: {
            char c = static_cast<char>(m_value.ident);
            text = String(&c, 1U);
            break;
        }
        case CSS_PARSER_IDENTIFIER:
            text = quoteCSSStringIfNeeded(m_value.string);
            break;
        case CSS_CALC:
            text = m_value.calc->cssText();
            break;
        case CSS_SHAPE:
            text = m_value.shape->cssText();
            break;
        case CSS_VW:
            text = formatNumber(m_value.num, "vw");
            break;
        case CSS_VH:
            text = formatNumber(m_value.num, "vh");
            break;
        case CSS_VMIN:
            text = formatNumber(m_value.num, "vmin");
            break;
        case CSS_VMAX:
            text = formatNumber(m_value.num, "vmax");
            break;
#if ENABLE(CSS_VARIABLES)
        case CSS_VARIABLE_NAME:
            text = "-webkit-var(" + String(m_value.string) + ")";
            break;
#endif
    }

    ASSERT(!cssTextCache().contains(this));
    cssTextCache().set(this, text);
    m_hasCachedCSSText = true;
    return text;
}
Example #25
0
String CSSPrimitiveValue::customCssText() const
{
    // FIXME: return the original value instead of a generated one (e.g. color
    // name if it was specified) - check what spec says about this

    if (m_hasCachedCSSText) {
        ASSERT(cssTextCache().contains(this));
        return cssTextCache().get(this);
    }

    String text;
    switch (m_primitiveUnitType) {
        case CSS_UNKNOWN:
            // FIXME
            break;
        case CSS_NUMBER:
        case CSS_PARSER_INTEGER:
            text = formatNumber(m_value.num);
            break;
        case CSS_PERCENTAGE:
            text = formatNumber(m_value.num) + "%";
            break;
        case CSS_EMS:
            text = formatNumber(m_value.num) + "em";
            break;
        case CSS_EXS:
            text = formatNumber(m_value.num) + "ex";
            break;
        case CSS_REMS:
            text = formatNumber(m_value.num) + "rem";
            break;
        case CSS_PX:
            text = formatNumber(m_value.num) + "px";
            break;
        case CSS_CM:
            text = formatNumber(m_value.num) + "cm";
            break;
#if ENABLE(CSS_IMAGE_RESOLUTION)
        case CSS_DPPX:
            text = formatNumber(m_value.num) + "dppx";
            break;
        case CSS_DPI:
            text = formatNumber(m_value.num) + "dpi";
            break;
        case CSS_DPCM:
            text = formatNumber(m_value.num) + "dpcm";
            break;
#endif
        case CSS_MM:
            text = formatNumber(m_value.num) + "mm";
            break;
        case CSS_IN:
            text = formatNumber(m_value.num) + "in";
            break;
        case CSS_PT:
            text = formatNumber(m_value.num) + "pt";
            break;
        case CSS_PC:
            text = formatNumber(m_value.num) + "pc";
            break;
        case CSS_DEG:
            text = formatNumber(m_value.num) + "deg";
            break;
        case CSS_RAD:
            text = formatNumber(m_value.num) + "rad";
            break;
        case CSS_GRAD:
            text = formatNumber(m_value.num) + "grad";
            break;
        case CSS_MS:
            text = formatNumber(m_value.num) + "ms";
            break;
        case CSS_S:
            text = formatNumber(m_value.num) + "s";
            break;
        case CSS_HZ:
            text = formatNumber(m_value.num) + "hz";
            break;
        case CSS_KHZ:
            text = formatNumber(m_value.num) + "khz";
            break;
        case CSS_TURN:
            text = formatNumber(m_value.num) + "turn";
            break;
        case CSS_DIMENSION:
            // FIXME
            break;
        case CSS_STRING:
            text = quoteCSSStringIfNeeded(m_value.string);
            break;
        case CSS_URI:
            text = "url(" + quoteCSSURLIfNeeded(m_value.string) + ")";
            break;
        case CSS_IDENT:
            text = valueOrPropertyName(m_value.ident);
            break;
        case CSS_ATTR: {
            DEFINE_STATIC_LOCAL(const String, attrParen, ("attr("));

            StringBuilder result;
            result.reserveCapacity(6 + m_value.string->length());

            result.append(attrParen);
            result.append(m_value.string);
            result.append(')');

            text = result.toString();
            break;
        }
        case CSS_COUNTER_NAME:
            text = "counter(";
            text += m_value.string;
            text += ")";
            break;
        case CSS_COUNTER: {
            DEFINE_STATIC_LOCAL(const String, counterParen, ("counter("));
            DEFINE_STATIC_LOCAL(const String, countersParen, ("counters("));
            DEFINE_STATIC_LOCAL(const String, commaSpace, (", "));

            StringBuilder result;
            String separator = m_value.counter->separator();
            result.append(separator.isEmpty() ? counterParen : countersParen);

            result.append(m_value.counter->identifier());
            if (!separator.isEmpty()) {
                result.append(commaSpace);
                result.append(quoteCSSStringIfNeeded(separator));
            }
            String listStyle = m_value.counter->listStyle();
            if (!listStyle.isEmpty()) {
                result.append(commaSpace);
                result.append(listStyle);
            }
            result.append(')');

            text = result.toString();
            break;
        }
        case CSS_RECT: {
            DEFINE_STATIC_LOCAL(const String, rectParen, ("rect("));

            Rect* rectVal = getRectValue();
            StringBuilder result;
            result.reserveCapacity(32);
            result.append(rectParen);

            result.append(rectVal->top()->cssText());
            result.append(' ');

            result.append(rectVal->right()->cssText());
            result.append(' ');

            result.append(rectVal->bottom()->cssText());
            result.append(' ');

            result.append(rectVal->left()->cssText());
            result.append(')');

            text = result.toString();
            break;
        }
        case CSS_QUAD: {
            Quad* quadVal = getQuadValue();
            Vector<UChar> result;
            result.reserveInitialCapacity(32);
            append(result, quadVal->top()->cssText());
            if (quadVal->right() != quadVal->top() || quadVal->bottom() != quadVal->top() || quadVal->left() != quadVal->top()) {
                result.append(' ');
                append(result, quadVal->right()->cssText());
                if (quadVal->bottom() != quadVal->top() || quadVal->right() != quadVal->left()) {
                    result.append(' ');
                    append(result, quadVal->bottom()->cssText());
                    if (quadVal->left() != quadVal->right()) {
                        result.append(' ');
                        append(result, quadVal->left()->cssText());
                    }
                }
            }
            text = String::adopt(result);
            break;
        }
        case CSS_RGBCOLOR:
        case CSS_PARSER_HEXCOLOR: {
            DEFINE_STATIC_LOCAL(const String, commaSpace, (", "));
            DEFINE_STATIC_LOCAL(const String, rgbParen, ("rgb("));
            DEFINE_STATIC_LOCAL(const String, rgbaParen, ("rgba("));

            RGBA32 rgbColor = m_value.rgbcolor;
            if (m_primitiveUnitType == CSS_PARSER_HEXCOLOR)
                Color::parseHexColor(m_value.string, rgbColor);
            Color color(rgbColor);

            Vector<UChar> result;
            result.reserveInitialCapacity(32);
            if (color.hasAlpha())
                append(result, rgbaParen);
            else
                append(result, rgbParen);

            appendNumber(result, static_cast<unsigned char>(color.red()));
            append(result, commaSpace);

            appendNumber(result, static_cast<unsigned char>(color.green()));
            append(result, commaSpace);

            appendNumber(result, static_cast<unsigned char>(color.blue()));
            if (color.hasAlpha()) {
                append(result, commaSpace);
                append(result, String::number(color.alpha() / 255.0f));
            }

            result.append(')');
            text = String::adopt(result);
            break;
        }
        case CSS_PAIR:
            text = m_value.pair->first()->cssText();
            if (m_value.pair->second() != m_value.pair->first()) {
                text += " ";
                text += m_value.pair->second()->cssText();
            }
            break;
#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION)
        case CSS_DASHBOARD_REGION:
            for (DashboardRegion* region = getDashboardRegionValue(); region; region = region->m_next.get()) {
                if (!text.isEmpty())
                    text.append(' ');
#if ENABLE(DASHBOARD_SUPPORT) && ENABLE(WIDGET_REGION)
                text += region->m_cssFunctionName;
#elif ENABLE(DASHBOARD_SUPPORT)
                text += "dashboard-region(";
#else
                text += "region(";
#endif
                text += region->m_label;
                if (region->m_isCircle)
                    text += " circle";
                else if (region->m_isRectangle)
                    text += " rectangle";
                else
                    break;
                if (region->top()->m_primitiveUnitType == CSS_IDENT && region->top()->getIdent() == CSSValueInvalid) {
                    ASSERT(region->right()->m_primitiveUnitType == CSS_IDENT);
                    ASSERT(region->bottom()->m_primitiveUnitType == CSS_IDENT);
                    ASSERT(region->left()->m_primitiveUnitType == CSS_IDENT);
                    ASSERT(region->right()->getIdent() == CSSValueInvalid);
                    ASSERT(region->bottom()->getIdent() == CSSValueInvalid);
                    ASSERT(region->left()->getIdent() == CSSValueInvalid);
                } else {
                    text.append(' ');
                    text += region->top()->cssText() + " ";
                    text += region->right()->cssText() + " ";
                    text += region->bottom()->cssText() + " ";
                    text += region->left()->cssText();
                }
                text += ")";
            }
            break;
#endif
        case CSS_PARSER_OPERATOR: {
            char c = static_cast<char>(m_value.ident);
            text = String(&c, 1U);
            break;
        }
        case CSS_PARSER_IDENTIFIER:
            text = quoteCSSStringIfNeeded(m_value.string);
            break;
        case CSS_CALC:
            text = m_value.calc->cssText();
            break;
        case CSS_SHAPE:
            text = m_value.shape->cssText();
            break;
        case CSS_VW:
            text = formatNumber(m_value.num) + "vw";
            break;
        case CSS_VH:
            text = formatNumber(m_value.num) + "vh";
            break;
        case CSS_VMIN:
            text = formatNumber(m_value.num) + "vmin";
            break;
#if ENABLE(CSS_VARIABLES)
        case CSS_VARIABLE_NAME:
            text = "-webkit-var(";
            text += m_value.string;
            text += ")";
            break;
#endif
    }

    ASSERT(!cssTextCache().contains(this));
    cssTextCache().set(this, text);
    m_hasCachedCSSText = true;
    return text;
}
String CSSPrimitiveValue::cssText() const
{
    // FIXME: return the original value instead of a generated one (e.g. color
    // name if it was specified) - check what spec says about this
    String text;
    switch (m_type) {
        case CSS_UNKNOWN:
            // FIXME
            break;
        case CSS_NUMBER:
        case CSS_PARSER_INTEGER:
            text = String::number(m_value.num);
            break;
        case CSS_PERCENTAGE:
            text = String::format("%.6lg%%", m_value.num);
            break;
        case CSS_EMS:
            text = String::format("%.6lgem", m_value.num);
            break;
        case CSS_EXS:
            text = String::format("%.6lgex", m_value.num);
            break;
        case CSS_PX:
            text = String::format("%.6lgpx", m_value.num);
            break;
        case CSS_CM:
            text = String::format("%.6lgcm", m_value.num);
            break;
        case CSS_MM:
            text = String::format("%.6lgmm", m_value.num);
            break;
        case CSS_IN:
            text = String::format("%.6lgin", m_value.num);
            break;
        case CSS_PT:
            text = String::format("%.6lgpt", m_value.num);
            break;
        case CSS_PC:
            text = String::format("%.6lgpc", m_value.num);
            break;
        case CSS_DEG:
            text = String::format("%.6lgdeg", m_value.num);
            break;
        case CSS_RAD:
            text = String::format("%.6lgrad", m_value.num);
            break;
        case CSS_GRAD:
            text = String::format("%.6lggrad", m_value.num);
            break;
        case CSS_MS:
            text = String::format("%.6lgms", m_value.num);
            break;
        case CSS_S:
            text = String::format("%.6lgs", m_value.num);
            break;
        case CSS_HZ:
            text = String::format("%.6lghz", m_value.num);
            break;
        case CSS_KHZ:
            text = String::format("%.6lgkhz", m_value.num);
            break;
        case CSS_TURN:
            text = String::format("%.6lgturn", m_value.num);
            break;
        case CSS_DIMENSION:
            // FIXME
            break;
        case CSS_STRING:
            text = quoteStringIfNeeded(m_value.string);
            break;
        case CSS_URI:
            text = "url(" + quoteURLIfNeeded(m_value.string) + ")";
            break;
        case CSS_IDENT:
            text = valueOrPropertyName(m_value.ident);
            break;
        case CSS_ATTR: {
            DEFINE_STATIC_LOCAL(const String, attrParen, ("attr("));

            Vector<UChar> result;
            result.reserveInitialCapacity(6 + m_value.string->length());

            append(result, attrParen);
            append(result, m_value.string);
            result.uncheckedAppend(')');

            return String::adopt(result);
        }
        case CSS_COUNTER:
            text = "counter(";
            text += String::number(m_value.num);
            text += ")";
            // FIXME: Add list-style and separator
            break;
        case CSS_RECT: {
            DEFINE_STATIC_LOCAL(const String, rectParen, ("rect("));

            Rect* rectVal = getRectValue();
            Vector<UChar> result;
            result.reserveInitialCapacity(32);
            append(result, rectParen);

            append(result, rectVal->top()->cssText());
            result.append(' ');

            append(result, rectVal->right()->cssText());
            result.append(' ');

            append(result, rectVal->bottom()->cssText());
            result.append(' ');

            append(result, rectVal->left()->cssText());
            result.append(')');

            return String::adopt(result);
        }
        case CSS_RGBCOLOR:
        case CSS_PARSER_HEXCOLOR: {
            DEFINE_STATIC_LOCAL(const String, commaSpace, (", "));
            DEFINE_STATIC_LOCAL(const String, rgbParen, ("rgb("));
            DEFINE_STATIC_LOCAL(const String, rgbaParen, ("rgba("));

            RGBA32 rgbColor = m_value.rgbcolor;
            if (m_type == CSS_PARSER_HEXCOLOR)
                Color::parseHexColor(m_value.string, rgbColor);
            Color color(rgbColor);

            Vector<UChar> result;
            result.reserveInitialCapacity(32);
            if (color.hasAlpha())
                append(result, rgbaParen);
            else
                append(result, rgbParen);

            appendNumber(result, static_cast<unsigned char>(color.red()));
            append(result, commaSpace);

            appendNumber(result, static_cast<unsigned char>(color.green()));
            append(result, commaSpace);

            appendNumber(result, static_cast<unsigned char>(color.blue()));
            if (color.hasAlpha()) {
                append(result, commaSpace);
                append(result, String::number(static_cast<float>(color.alpha()) / 256.0f));
            }

            result.append(')');
            return String::adopt(result);
        }
        case CSS_PAIR:
            text = m_value.pair->first()->cssText();
            text += " ";
            text += m_value.pair->second()->cssText();
            break;
#if ENABLE(DASHBOARD_SUPPORT)
        case CSS_DASHBOARD_REGION:
            for (DashboardRegion* region = getDashboardRegionValue(); region; region = region->m_next.get()) {
                if (!text.isEmpty())
                    text.append(' ');
                text += "dashboard-region(";
                text += region->m_label;
                if (region->m_isCircle)
                    text += " circle";
                else if (region->m_isRectangle)
                    text += " rectangle";
                else
                    break;
                if (region->top()->m_type == CSS_IDENT && region->top()->getIdent() == CSSValueInvalid) {
                    ASSERT(region->right()->m_type == CSS_IDENT);
                    ASSERT(region->bottom()->m_type == CSS_IDENT);
                    ASSERT(region->left()->m_type == CSS_IDENT);
                    ASSERT(region->right()->getIdent() == CSSValueInvalid);
                    ASSERT(region->bottom()->getIdent() == CSSValueInvalid);
                    ASSERT(region->left()->getIdent() == CSSValueInvalid);
                } else {
                    text.append(' ');
                    text += region->top()->cssText() + " ";
                    text += region->right()->cssText() + " ";
                    text += region->bottom()->cssText() + " ";
                    text += region->left()->cssText();
                }
                text += ")";
            }
            break;
#endif
        case CSS_PARSER_VARIABLE_FUNCTION_SYNTAX:
            text = "-webkit-var(";
            text += m_value.string;
            text += ")";
            break;
        case CSS_PARSER_OPERATOR: {
            char c = static_cast<char>(m_value.ident);
            text = String(&c, 1U);
            break;
        }
        case CSS_PARSER_IDENTIFIER:
            text = quoteStringIfNeeded(m_value.string);
            break;
    }
    return text;
}
Example #27
0
bool WorkerOrWorkletScriptController::initializeContextIfNeeded() {
  v8::HandleScope handleScope(m_isolate);

  if (isContextInitialized())
    return true;

  // Create a new v8::Context with the worker/worklet as the global object
  // (aka the inner global).
  ScriptWrappable* scriptWrappable = m_globalScope->getScriptWrappable();
  const WrapperTypeInfo* wrapperTypeInfo = scriptWrappable->wrapperTypeInfo();
  v8::Local<v8::FunctionTemplate> globalInterfaceTemplate =
      wrapperTypeInfo->domTemplate(m_isolate, *m_world);
  if (globalInterfaceTemplate.IsEmpty())
    return false;
  v8::Local<v8::ObjectTemplate> globalTemplate =
      globalInterfaceTemplate->InstanceTemplate();
  v8::Local<v8::Context> context;
  {
    // Initialize V8 extensions before creating the context.
    Vector<const char*> extensionNames;
    if (m_globalScope->isServiceWorkerGlobalScope() &&
        Platform::current()->allowScriptExtensionForServiceWorker(
            toWorkerGlobalScope(m_globalScope.get())->url())) {
      const V8Extensions& extensions = ScriptController::registeredExtensions();
      extensionNames.reserveInitialCapacity(extensions.size());
      for (const auto* extension : extensions)
        extensionNames.push_back(extension->name());
    }
    v8::ExtensionConfiguration extensionConfiguration(extensionNames.size(),
                                                      extensionNames.data());

    V8PerIsolateData::UseCounterDisabledScope useCounterDisabled(
        V8PerIsolateData::from(m_isolate));
    context =
        v8::Context::New(m_isolate, &extensionConfiguration, globalTemplate);
  }
  if (context.IsEmpty())
    return false;

  m_scriptState = ScriptState::create(context, m_world);

  ScriptState::Scope scope(m_scriptState.get());

  // The global proxy object.  Note this is not the global object.
  v8::Local<v8::Object> globalProxy = context->Global();
  V8DOMWrapper::setNativeInfo(m_isolate, globalProxy, wrapperTypeInfo,
                              scriptWrappable);

  // The global object, aka worker/worklet wrapper object.
  v8::Local<v8::Object> globalObject =
      globalProxy->GetPrototype().As<v8::Object>();
  globalObject = V8DOMWrapper::associateObjectWithWrapper(
      m_isolate, scriptWrappable, wrapperTypeInfo, globalObject);

  // All interfaces must be registered to V8PerContextData.
  // So we explicitly call constructorForType for the global object.
  V8PerContextData::from(context)->constructorForType(wrapperTypeInfo);

  // Name new context for debugging. For main thread worklet global scopes
  // this is done once the context is initialized.
  if (m_globalScope->isWorkerGlobalScope() ||
      m_globalScope->isThreadedWorkletGlobalScope()) {
    WorkerThreadDebugger* debugger = WorkerThreadDebugger::from(m_isolate);
    debugger->contextCreated(m_globalScope->thread(), context);
  }

  return true;
}
Vector<Action> ContentExtensionsBackend::actionsForResourceLoad(const ResourceLoadInfo& resourceLoadInfo) const
{
#if CONTENT_EXTENSIONS_PERFORMANCE_REPORTING
    double addedTimeStart = monotonicallyIncreasingTime();
#endif
    if (resourceLoadInfo.resourceURL.protocolIsData())
        return Vector<Action>();

    const String& urlString = resourceLoadInfo.resourceURL.string();
    ASSERT_WITH_MESSAGE(urlString.containsOnlyASCII(), "A decoded URL should only contain ASCII characters. The matching algorithm assumes the input is ASCII.");
    const CString& urlCString = urlString.utf8();

    Vector<Action> finalActions;
    ResourceFlags flags = resourceLoadInfo.getResourceFlags();
    for (auto& contentExtension : m_contentExtensions.values()) {
        RELEASE_ASSERT(contentExtension);
        const CompiledContentExtension& compiledExtension = contentExtension->compiledExtension();
        
        // FIXME: These should use a different Vector<bool> to keep track of which memory pages are used when doing memory reporting. Or just remove the memory reporting completely.
        DFABytecodeInterpreter withoutDomainsInterpreter(compiledExtension.filtersWithoutDomainsBytecode(), compiledExtension.filtersWithoutDomainsBytecodeLength(), contentExtension->m_pagesUsed);
        DFABytecodeInterpreter::Actions triggeredActions = withoutDomainsInterpreter.interpret(urlCString, flags);
        
        // Check to see if there are any actions triggered with if- or unless-domain and check the domain if there are.
        DFABytecodeInterpreter withDomainsInterpreter(compiledExtension.filtersWithDomainsBytecode(), compiledExtension.filtersWithDomainsBytecodeLength(), contentExtension->m_pagesUsed);
        
        DFABytecodeInterpreter::Actions withDomainsPossibleActions = withDomainsInterpreter.interpret(urlCString, flags);
        if (!withDomainsPossibleActions.isEmpty()) {
            DFABytecodeInterpreter domainsInterpreter(compiledExtension.domainFiltersBytecode(), compiledExtension.domainFiltersBytecodeLength(), contentExtension->m_pagesUsed);
            DFABytecodeInterpreter::Actions domainsActions = domainsInterpreter.interpret(resourceLoadInfo.mainDocumentURL.host().utf8(), flags);
            
            DFABytecodeInterpreter::Actions ifDomainActions;
            DFABytecodeInterpreter::Actions unlessDomainActions;
            for (uint64_t action : domainsActions) {
                if (action & IfDomainFlag)
                    ifDomainActions.add(action);
                else
                    unlessDomainActions.add(action);
            }
            
            for (uint64_t action : withDomainsPossibleActions) {
                if (ifDomainActions.contains(action)) {
                    // If an if-domain trigger matches, add the action.
                    ASSERT(action & IfDomainFlag);
                    triggeredActions.add(action & ~IfDomainFlag);
                } else if (!(action & IfDomainFlag) && !unlessDomainActions.contains(action)) {
                    // If this action did not need an if-domain, it must have been an unless-domain rule.
                    // Add the action unless it matched an unless-domain trigger.
                    triggeredActions.add(action);
                }
            }
        }
        
        const SerializedActionByte* actions = compiledExtension.actions();
        const unsigned actionsLength = compiledExtension.actionsLength();
        
        bool sawIgnorePreviousRules = false;
        if (!triggeredActions.isEmpty()) {
            Vector<unsigned> actionLocations;
            actionLocations.reserveInitialCapacity(triggeredActions.size());
            for (auto actionLocation : triggeredActions)
                actionLocations.append(static_cast<unsigned>(actionLocation));
            std::sort(actionLocations.begin(), actionLocations.end());

            // Add actions in reverse order to properly deal with IgnorePreviousRules.
            for (unsigned i = actionLocations.size(); i; i--) {
                Action action = Action::deserialize(actions, actionsLength, actionLocations[i - 1]);
                action.setExtensionIdentifier(contentExtension->identifier());
                if (action.type() == ActionType::IgnorePreviousRules) {
                    sawIgnorePreviousRules = true;
                    break;
                }
                finalActions.append(action);
            }
        }
        if (!sawIgnorePreviousRules) {
            finalActions.append(Action(ActionType::CSSDisplayNoneStyleSheet, contentExtension->identifier()));
            finalActions.last().setExtensionIdentifier(contentExtension->identifier());
        }
    }
#if CONTENT_EXTENSIONS_PERFORMANCE_REPORTING
    double addedTimeEnd = monotonicallyIncreasingTime();
    WTFLogAlways("Time added: %f microseconds %s", (addedTimeEnd - addedTimeStart) * 1.0e6, resourceLoadInfo.resourceURL.string().utf8().data());
#endif
    return finalActions;
}
Example #29
0
SamplingProfiler::SamplingProfiler(VM& vm, RefPtr<Stopwatch>&& stopwatch)
    : m_vm(vm)
    , m_stopwatch(WTFMove(stopwatch))
    , m_indexOfNextStackTraceToVerify(0)
    , m_timingInterval(std::chrono::microseconds(1000))
    , m_totalTime(0)
    , m_timerQueue(WorkQueue::create("jsc.sampling-profiler.queue", WorkQueue::Type::Serial, WorkQueue::QOS::UserInteractive))
    , m_jscExecutionThread(nullptr)
    , m_isActive(false)
    , m_isPaused(false)
    , m_hasDispatchedFunction(false)
{
    if (sReportStats) {
        sNumTotalWalks = 0;
        sNumFailedWalks = 0;
    }

    m_currentFrames.grow(256);

    m_handler = [this] () {
        LockHolder samplingProfilerLocker(m_lock);
        if (!m_isActive || !m_jscExecutionThread || m_isPaused) {
            m_hasDispatchedFunction = false;
            deref();
            return;
        }

        if (m_vm.entryScope) {
            double nowTime = m_stopwatch->elapsedTime();

            LockHolder machineThreadsLocker(m_vm.heap.machineThreads().getLock());
            LockHolder codeBlockSetLocker(m_vm.heap.codeBlockSet().getLock());
            LockHolder executableAllocatorLocker(m_vm.executableAllocator.getLock());

            bool didSuspend = m_jscExecutionThread->suspend();
            if (didSuspend) {
                // While the JSC thread is suspended, we can't do things like malloc because the JSC thread
                // may be holding the malloc lock.
                ExecState* callFrame;
                void* pc;
                {
                    MachineThreads::Thread::Registers registers;
                    m_jscExecutionThread->getRegisters(registers);
                    callFrame = static_cast<ExecState*>(registers.framePointer());
                    pc = registers.instructionPointer();
                    m_jscExecutionThread->freeRegisters(registers);
                }
                // FIXME: Lets have a way of detecting when we're parsing code.
                // https://bugs.webkit.org/show_bug.cgi?id=152761
                if (m_vm.executableAllocator.isValidExecutableMemory(executableAllocatorLocker, pc)) {
                    if (m_vm.isExecutingInRegExpJIT) {
                        // FIXME: We're executing a regexp. Lets gather more intersting data.
                        // https://bugs.webkit.org/show_bug.cgi?id=152729
                        callFrame = m_vm.topCallFrame; // We need to do this or else we'd fail our backtrace validation b/c this isn't a JS frame.
                    }
                } else if (LLInt::isLLIntPC(pc)) {
                    // We're okay to take a normal stack trace when the PC
                    // is in LLInt code.
                } else {
                    // We resort to topCallFrame to see if we can get anything
                    // useful. We usually get here when we're executing C code.
                    callFrame = m_vm.topCallFrame;
                }

                size_t walkSize;
                bool wasValidWalk;
                bool didRunOutOfVectorSpace;
                bool stacktraceNeedsVerification;
                {
                    FrameWalker walker(callFrame, m_vm, codeBlockSetLocker, machineThreadsLocker);
                    walkSize = walker.walk(m_currentFrames, didRunOutOfVectorSpace, stacktraceNeedsVerification);
                    wasValidWalk = walker.wasValidWalk();
                }

                m_jscExecutionThread->resume();

                // We can now use data structures that malloc, and do other interesting things, again.

                // FIXME: It'd be interesting to take data about the program's state when
                // we fail to take a stack trace: https://bugs.webkit.org/show_bug.cgi?id=152758
                if (wasValidWalk && walkSize) {
                    if (sReportStats) {
                        sNumTotalStackTraces++;
                        if (stacktraceNeedsVerification)
                            sNumUnverifiedStackTraces++;
                    }
                    Vector<StackFrame> stackTrace;
                    stackTrace.reserveInitialCapacity(walkSize);
                    for (size_t i = 0; i < walkSize; i++) {
                        StackFrame frame = m_currentFrames[i];
                        stackTrace.uncheckedAppend(frame); 
                        if (frame.frameType == FrameType::VerifiedExecutable)
                            m_seenExecutables.add(frame.u.verifiedExecutable);
                    }

                    m_stackTraces.append(StackTrace{ stacktraceNeedsVerification, nowTime, WTFMove(stackTrace) });

                    if (didRunOutOfVectorSpace)
                        m_currentFrames.grow(m_currentFrames.size() * 1.25);

                    m_totalTime += nowTime - m_lastTime;
                }
            }
        }

        m_lastTime = m_stopwatch->elapsedTime();

        dispatchFunction(samplingProfilerLocker);
    };
}
Example #30
0
WebRenderObject::WebRenderObject(RenderObject* renderer, bool shouldIncludeDescendants)
{
    m_name = renderer->renderName();
    m_textLength = 0;

    if (Node* node = renderer->node()) {
        if (is<Element>(*node)) {
            Element& element = downcast<Element>(*node);
            m_elementTagName = element.tagName();
            m_elementID = element.getIdAttribute();
            
            if (element.isStyledElement() && element.hasClass()) {
                Vector<RefPtr<API::Object>> classNames;
                classNames.reserveInitialCapacity(element.classNames().size());

                for (size_t i = 0, size = element.classNames().size(); i < size; ++i)
                    classNames.append(API::String::create(element.classNames()[i]));

                m_elementClassNames = API::Array::create(WTFMove(classNames));
            }
        }

        if (node->isTextNode()) {
            String value = node->nodeValue();
            m_textLength = value.length();

            const int maxSnippetLength = 40;
            if (value.length() > maxSnippetLength)
                m_textSnippet = value.substring(0, maxSnippetLength);
            else
                m_textSnippet = value;
        }
    }

    // FIXME: broken with transforms
    m_absolutePosition = flooredIntPoint(renderer->localToAbsolute());

    if (is<RenderBox>(*renderer))
        m_frameRect = snappedIntRect(downcast<RenderBox>(*renderer).frameRect());
    else if (is<RenderText>(*renderer)) {
        m_frameRect = downcast<RenderText>(*renderer).linesBoundingBox();
        m_frameRect.setLocation(downcast<RenderText>(*renderer).firstRunLocation());
    } else if (is<RenderInline>(*renderer))
        m_frameRect = IntRect(downcast<RenderInline>(*renderer).borderBoundingBox());

    if (!shouldIncludeDescendants)
        return;

    Vector<RefPtr<API::Object>> children;

    for (RenderObject* coreChild = renderer->firstChildSlow(); coreChild; coreChild = coreChild->nextSibling()) {
        RefPtr<WebRenderObject> child = adoptRef(new WebRenderObject(coreChild, shouldIncludeDescendants));
        children.append(WTFMove(child));
    }

    if (is<RenderWidget>(*renderer)) {
        if (Widget* widget = downcast<RenderWidget>(*renderer).widget()) {
            if (is<FrameView>(*widget)) {
                FrameView& frameView = downcast<FrameView>(*widget);
                if (RenderView* coreContentRenderer = frameView.frame().contentRenderer()) {
                    RefPtr<WebRenderObject> contentRenderer = adoptRef(new WebRenderObject(coreContentRenderer, shouldIncludeDescendants));

                    children.append(WTFMove(contentRenderer));
                }
            }
        }
    }

    m_children = API::Array::create(WTFMove(children));
}