Vector<String> Database::performGetTableNames()
{
    disableAuthorizer();

    SQLiteStatement statement(sqliteDatabase(), "SELECT name FROM sqlite_master WHERE type='table';");
    if (statement.prepare() != SQLResultOk) {
        WTF_LOG_ERROR("Unable to retrieve list of tables for database %s", databaseDebugName().ascii().data());
        enableAuthorizer();
        return Vector<String>();
    }

    Vector<String> tableNames;
    int result;
    while ((result = statement.step()) == SQLResultRow) {
        String name = statement.getColumnText(0);
        if (name != databaseInfoTableName())
            tableNames.append(name);
    }

    enableAuthorizer();

    if (result != SQLResultDone) {
        WTF_LOG_ERROR("Error getting tables for database %s", databaseDebugName().ascii().data());
        return Vector<String>();
    }

    return tableNames;
}
void PrintContext::computePageRects(const FloatRect& printRect, float headerHeight, float footerHeight, float userScaleFactor, float& outPageHeight)
{
    m_pageRects.clear();
    outPageHeight = 0;

    if (!m_frame->document() || !m_frame->view() || !m_frame->document()->renderView())
        return;

    if (userScaleFactor <= 0) {
        WTF_LOG_ERROR("userScaleFactor has bad value %.2f", userScaleFactor);
        return;
    }

    RenderView* view = m_frame->document()->renderView();
    const IntRect& documentRect = view->documentRect();
    FloatSize pageSize = m_frame->resizePageRectsKeepingRatio(FloatSize(printRect.width(), printRect.height()), FloatSize(documentRect.width(), documentRect.height()));
    float pageWidth = pageSize.width();
    float pageHeight = pageSize.height();

    outPageHeight = pageHeight; // this is the height of the page adjusted by margins
    pageHeight -= headerHeight + footerHeight;

    if (pageHeight <= 0) {
        WTF_LOG_ERROR("pageHeight has bad value %.2f", pageHeight);
        return;
    }

    computePageRectsWithPageSizeInternal(FloatSize(pageWidth / userScaleFactor, pageHeight / userScaleFactor), false);
}
void SQLiteDatabase::setMaximumSize(int64_t size)
{
    if (size < 0)
        size = 0;

    int currentPageSize = pageSize();

    ASSERT(currentPageSize || !m_db);
    int64_t newMaxPageCount = currentPageSize ? size / currentPageSize : 0;

    MutexLocker locker(m_authorizerLock);
    enableAuthorizer(false);

    SQLiteStatement statement(*this, "PRAGMA max_page_count = " + String::number(newMaxPageCount));
    statement.prepare();
    if (statement.step() != SQLResultRow)
#if OS(WIN)
        WTF_LOG_ERROR("Failed to set maximum size of database to %I64i bytes", static_cast<long long>(size));
#else
        WTF_LOG_ERROR("Failed to set maximum size of database to %lli bytes", static_cast<long long>(size));
#endif

    enableAuthorizer(true);

}
bool SQLiteDatabase::open(const String& filename)
{
    close();

    m_openError = SQLiteFileSystem::openDatabase(filename, &m_db);
    if (m_openError != SQLITE_OK) {
        m_openErrorMessage = m_db ? sqlite3_errmsg(m_db) : "sqlite_open returned null";
        WTF_LOG_ERROR("SQLite database failed to load from %s\nCause - %s", filename.ascii().data(),
            m_openErrorMessage.data());
        sqlite3_close(m_db);
        m_db = 0;
        return false;
    }

    m_openError = sqlite3_extended_result_codes(m_db, 1);
    if (m_openError != SQLITE_OK) {
        m_openErrorMessage = sqlite3_errmsg(m_db);
        WTF_LOG_ERROR("SQLite database error when enabling extended errors - %s", m_openErrorMessage.data());
        sqlite3_close(m_db);
        m_db = 0;
        return false;
    }

    if (isOpen())
        m_openingThread = currentThread();
    else
        m_openErrorMessage = "sqlite_open returned null";

    if (!SQLiteStatement(*this, "PRAGMA temp_store = MEMORY;").executeCommand())
        WTF_LOG_ERROR("SQLite database could not set temp_store to memory");

    return isOpen();
}
示例#5
0
bool parseContentType(const String& contentType, ReceiverType& receiver)
{
    unsigned index = 0;
    unsigned contentTypeLength = contentType.length();
    skipSpaces(contentType, index);
    if (index >= contentTypeLength)  {
        WTF_LOG_ERROR("Invalid Content-Type string '%s'", contentType.ascii().data());
        return false;
    }

    // There should not be any quoted strings until we reach the parameters.
    size_t semiColonIndex = contentType.find(';', index);
    if (semiColonIndex == kNotFound) {
        receiver.setContentType(SubstringRange(index, contentTypeLength - index));
        return true;
    }

    receiver.setContentType(SubstringRange(index, semiColonIndex - index));
    index = semiColonIndex + 1;
    while (true) {
        skipSpaces(contentType, index);
        SubstringRange keyRange = parseParameterPart(contentType, index);
        if (!keyRange.second || index >= contentTypeLength) {
            WTF_LOG_ERROR("Invalid Content-Type parameter name. (at %i)", index);
            return false;
        }

        // Should we tolerate spaces here?
        if (contentType[index++] != '=' || index >= contentTypeLength) {
            WTF_LOG_ERROR("Invalid Content-Type malformed parameter (at %i).", index);
            return false;
        }

        // Should we tolerate spaces here?
        SubstringRange valueRange = parseParameterPart(contentType, index);

        if (!valueRange.second) {
            WTF_LOG_ERROR("Invalid Content-Type, invalid parameter value (at %i, for '%s').", index, substringForRange(contentType, keyRange).stripWhiteSpace().ascii().data());
            return false;
        }

        // Should we tolerate spaces here?
        if (index < contentTypeLength && contentType[index++] != ';') {
            WTF_LOG_ERROR("Invalid Content-Type, invalid character at the end of key/value parameter (at %i).", index);
            return false;
        }

        receiver.setContentTypeParameter(keyRange, valueRange);

        if (index >= contentTypeLength)
            return true;
    }

    return true;
}
示例#6
0
PassRefPtrWillBeRawPtr<MHTMLArchive> MHTMLParser::parseArchiveWithHeader(MIMEHeader* header)
{
    if (!header) {
        WTF_LOG_ERROR("Failed to parse MHTML part: no header.");
        return nullptr;
    }

    RefPtrWillBeRawPtr<MHTMLArchive> archive = MHTMLArchive::create();
    if (!header->isMultipart()) {
        // With IE a page with no resource is not multi-part.
        bool endOfArchiveReached = false;
        RefPtrWillBeRawPtr<ArchiveResource> resource = parseNextPart(*header, String(), String(), endOfArchiveReached);
        if (!resource)
            return nullptr;
        archive->setMainResource(resource);
        return archive;
    }

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

    bool endOfArchive = false;
    while (!endOfArchive) {
        RefPtrWillBeRawPtr<MIMEHeader> resourceHeader = MIMEHeader::parseHeader(&m_lineReader);
        if (!resourceHeader) {
            WTF_LOG_ERROR("Failed to parse MHTML, invalid MIME header.");
            return nullptr;
        }
        if (resourceHeader->contentType() == "multipart/alternative") {
            // Ignore IE nesting which makes little sense (IE seems to nest only some of the frames).
            RefPtrWillBeRawPtr<MHTMLArchive> subframeArchive = parseArchiveWithHeader(resourceHeader.get());
            if (!subframeArchive) {
                WTF_LOG_ERROR("Failed to parse MHTML subframe.");
                return nullptr;
            }
            bool endOfPartReached = skipLinesUntilBoundaryFound(m_lineReader, header->endOfPartBoundary());
            ASSERT_UNUSED(endOfPartReached, endOfPartReached);
            // The top-frame is the first frame found, regardless of the nesting level.
            if (subframeArchive->mainResource())
                addResourceToArchive(subframeArchive->mainResource(), archive.get());
            archive->addSubframeArchive(subframeArchive);
            continue;
        }

        RefPtrWillBeRawPtr<ArchiveResource> resource = parseNextPart(*resourceHeader, header->endOfPartBoundary(), header->endOfDocumentBoundary(), endOfArchive);
        if (!resource) {
            WTF_LOG_ERROR("Failed to parse MHTML part.");
            return nullptr;
        }
        addResourceToArchive(resource.get(), archive.get());
    }

    return archive.release();
}
bool FontPlatformData::isFixedPitch() const
{
#if ENABLE(GDI_FONTS_ON_WINDOWS)
    // TEXTMETRICS have this. Set m_treatAsFixedPitch based off that.
    HWndDC dc(0);
    HGDIOBJ oldFont = SelectObject(dc, hfont());

    // Yes, this looks backwards, but the fixed pitch bit is actually set if the font
    // is *not* fixed pitch. Unbelievable but true.
    TEXTMETRIC textMetric = { 0 };
    if (!GetTextMetrics(dc, &textMetric)) {
        if (ensureFontLoaded(hfont())) {
            // Retry GetTextMetrics.
            // FIXME: Handle gracefully the error if this call also fails.
            // See http://crbug.com/6401.
            if (!GetTextMetrics(dc, &textMetric))
                WTF_LOG_ERROR("Unable to get the text metrics after second attempt");
        }
    }

    bool treatAsFixedPitch = !(textMetric.tmPitchAndFamily & TMPF_FIXED_PITCH);

    SelectObject(dc, oldFont);

    return treatAsFixedPitch;
#else
    return typeface() && typeface()->isFixedPitch();
#endif
}
SCRIPT_FONTPROPERTIES* FontPlatformData::scriptFontProperties() const
{
    if (!m_scriptFontProperties) {
        m_scriptFontProperties = adoptPtr(new SCRIPT_FONTPROPERTIES);
        memset(m_scriptFontProperties.get(), 0, sizeof(SCRIPT_FONTPROPERTIES));
        m_scriptFontProperties->cBytes = sizeof(SCRIPT_FONTPROPERTIES);
        HRESULT result = ScriptGetFontProperties(0, scriptCache(), m_scriptFontProperties.get());
        if (result == E_PENDING) {
            HWndDC dc(0);
            HGDIOBJ oldFont = SelectObject(dc, hfont());
            HRESULT hr = ScriptGetFontProperties(dc, scriptCache(), m_scriptFontProperties.get());
            if (S_OK != hr) {
                if (FontPlatformData::ensureFontLoaded(hfont())) {
                    // FIXME: Handle gracefully the error if this call also fails.
                    hr = ScriptGetFontProperties(dc, scriptCache(), m_scriptFontProperties.get());
                    if (S_OK != hr) {
                        WTF_LOG_ERROR("Unable to get the font properties after second attempt");
                    }
                }
            }

            SelectObject(dc, oldFont);
        }
    }
    return m_scriptFontProperties.get();
}
static KeyValueMap retrieveKeyValuePairs(SharedBufferChunkReader* buffer)
{
    KeyValueMap keyValuePairs;
    String line;
    String key;
    StringBuilder value;
    while (!(line = buffer->nextChunkAsUTF8StringWithLatin1Fallback()).isNull()) {
        if (line.isEmpty())
            break; // Empty line means end of key/value section.
        if (line[0] == '\t') {
            ASSERT(!key.isEmpty());
            value.append(line.substring(1));
            continue;
        }
        // New key/value, store the previous one if any.
        if (!key.isEmpty()) {
            if (keyValuePairs.find(key) != keyValuePairs.end())
                WTF_LOG_ERROR("Key duplicate found in MIME header. Key is '%s', previous value replaced.", key.ascii().data());
            keyValuePairs.add(key, value.toString().stripWhiteSpace());
            key = String();
            value.clear();
        }
        size_t semiColonIndex = line.find(':');
        if (semiColonIndex == kNotFound) {
            // This is not a key value pair, ignore.
            continue;
        }
        key = line.substring(0, semiColonIndex).lower().stripWhiteSpace();
        value.append(line.substring(semiColonIndex + 1));
    }
    // Store the last property if there is one.
    if (!key.isEmpty())
        keyValuePairs.set(key, value.toString().stripWhiteSpace());
    return keyValuePairs;
}
void TextCodecICU::createICUConverter() const
{
    ASSERT(!m_converterICU);

#if defined(USING_SYSTEM_ICU)
    const char* name = m_encoding.name();
    m_needsGBKFallbacks = name[0] == 'G' && name[1] == 'B' && name[2] == 'K' && !name[3];
#endif

    UErrorCode err;

    UConverter*& cachedConverter = cachedConverterICU();
    if (cachedConverter) {
        err = U_ZERO_ERROR;
        const char* cachedName = ucnv_getName(cachedConverter, &err);
        if (U_SUCCESS(err) && m_encoding == cachedName) {
            m_converterICU = cachedConverter;
            cachedConverter = 0;
            return;
        }
    }

    err = U_ZERO_ERROR;
    m_converterICU = ucnv_open(m_encoding.name(), &err);
#if !LOG_DISABLED
    if (err == U_AMBIGUOUS_ALIAS_WARNING)
        WTF_LOG_ERROR("ICU ambiguous alias warning for encoding: %s", m_encoding.name());
#endif
    if (m_converterICU)
        ucnv_setFallback(m_converterICU, TRUE);
}
示例#11
0
PassRefPtrWillBeRawPtr<MIMEHeader> MIMEHeader::parseHeader(SharedBufferChunkReader* buffer)
{
    RefPtrWillBeRawPtr<MIMEHeader> mimeHeader = MIMEHeader::create();
    KeyValueMap keyValuePairs = retrieveKeyValuePairs(buffer);
    KeyValueMap::iterator mimeParametersIterator = keyValuePairs.find("content-type");
    if (mimeParametersIterator != keyValuePairs.end()) {
        ParsedContentType parsedContentType(mimeParametersIterator->value);
        mimeHeader->m_contentType = parsedContentType.mimeType();
        if (!mimeHeader->isMultipart()) {
            mimeHeader->m_charset = parsedContentType.charset().stripWhiteSpace();
        } else {
            mimeHeader->m_multipartType = parsedContentType.parameterValueForName("type");
            mimeHeader->m_endOfPartBoundary = parsedContentType.parameterValueForName("boundary");
            if (mimeHeader->m_endOfPartBoundary.isNull()) {
                WTF_LOG_ERROR("No boundary found in multipart MIME header.");
                return nullptr;
            }
            mimeHeader->m_endOfPartBoundary.insert("--", 0);
            mimeHeader->m_endOfDocumentBoundary = mimeHeader->m_endOfPartBoundary;
            mimeHeader->m_endOfDocumentBoundary.append("--");
        }
    }

    mimeParametersIterator = keyValuePairs.find("content-transfer-encoding");
    if (mimeParametersIterator != keyValuePairs.end())
        mimeHeader->m_contentTransferEncoding = parseContentTransferEncoding(mimeParametersIterator->value);

    mimeParametersIterator = keyValuePairs.find("content-location");
    if (mimeParametersIterator != keyValuePairs.end())
        mimeHeader->m_contentLocation = mimeParametersIterator->value;

    return mimeHeader.release();
}
示例#12
0
bool MHTMLParser::parseArchiveWithHeader(MIMEHeader* header, WillBeHeapVector<RefPtrWillBeMember<ArchiveResource>>& resources)
{
    if (!header) {
        WTF_LOG_ERROR("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;
        RefPtrWillBeRawPtr<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) {
        RefPtrWillBeRawPtr<MIMEHeader> resourceHeader = MIMEHeader::parseHeader(&m_lineReader);
        if (!resourceHeader) {
            WTF_LOG_ERROR("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.get(), resources)) {
                WTF_LOG_ERROR("Failed to parse MHTML subframe.");
                return false;
            }
            bool endOfPartReached = skipLinesUntilBoundaryFound(m_lineReader, header->endOfPartBoundary());
            ASSERT_UNUSED(endOfPartReached, endOfPartReached);
            continue;
        }

        RefPtrWillBeRawPtr<ArchiveResource> resource = parseNextPart(*resourceHeader, header->endOfPartBoundary(), header->endOfDocumentBoundary(), endOfArchive);
        if (!resource) {
            WTF_LOG_ERROR("Failed to parse MHTML part.");
            return false;
        }
        resources.append(resource);
    }
    return true;
}
示例#13
0
int waitForThreadCompletion(ThreadIdentifier threadID)
{
    ASSERT(threadID);

    HANDLE threadHandle = threadHandleForIdentifier(threadID);
    if (!threadHandle)
        WTF_LOG_ERROR("ThreadIdentifier %u did not correspond to an active thread when trying to quit", threadID);

    DWORD joinResult = WaitForSingleObject(threadHandle, INFINITE);
    if (joinResult == WAIT_FAILED)
        WTF_LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID);

    CloseHandle(threadHandle);
    clearThreadHandleForIdentifier(threadID);

    return joinResult;
}
示例#14
0
static bool fontContainsCharacter(const FontPlatformData* fontData,
                                  const wchar_t* family, UChar32 character)
{
    // FIXME: For non-BMP characters, GetFontUnicodeRanges is of
    // no use. We have to read directly from the cmap table of a font.
    // Return true for now.
    if (character > 0xFFFF)
        return true;

    // This cache is just leaked on shutdown.
    static FontCmapCache* fontCmapCache = 0;
    if (!fontCmapCache)
        fontCmapCache = new FontCmapCache;

    HashMap<const wchar_t*, icu::UnicodeSet*>::iterator it = fontCmapCache->find(family);
    if (it != fontCmapCache->end())
        return it->value->contains(character);

    HFONT hfont = fontData->hfont();
    HWndDC hdc(0);
    HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(hdc, hfont));
    int count = GetFontUnicodeRanges(hdc, 0);
    if (!count && FontPlatformData::ensureFontLoaded(hfont))
        count = GetFontUnicodeRanges(hdc, 0);
    if (!count) {
        WTF_LOG_ERROR("Unable to get the font unicode range after second attempt");
        SelectObject(hdc, oldFont);
        return true;
    }

    static Vector<char, 512>* gGlyphsetBuffer = 0;
    if (!gGlyphsetBuffer)
        gGlyphsetBuffer = new Vector<char, 512>();
    gGlyphsetBuffer->resize(GetFontUnicodeRanges(hdc, 0));
    GLYPHSET* glyphset = reinterpret_cast<GLYPHSET*>(gGlyphsetBuffer->data());
    // In addition, refering to the OS/2 table and converting the codepage list
    // to the coverage map might be faster.
    count = GetFontUnicodeRanges(hdc, glyphset);
    ASSERT(count > 0);
    SelectObject(hdc, oldFont);

    // FIXME: consider doing either of the following two:
    // 1) port back ICU 4.0's faster look-up code for UnicodeSet
    // 2) port Mozilla's CompressedCharMap or gfxSparseBitset
    unsigned i = 0;
    icu::UnicodeSet* cmap = new icu::UnicodeSet;
    while (i < glyphset->cRanges) {
        WCHAR start = glyphset->ranges[i].wcLow;
        cmap->add(start, start + glyphset->ranges[i].cGlyphs - 1);
        i++;
    }
    cmap->freeze();
    // We don't lowercase |family| because all of them are under our control
    // and they're already lowercased.
    fontCmapCache->set(family, cmap);
    return cmap->contains(character);
}
String TextCodecICU::decode(const char* bytes, size_t length, FlushBehavior flush, bool stopOnError, bool& sawError)
{
    // Get a converter for the passed-in encoding.
    if (!m_converterICU) {
        createICUConverter();
        ASSERT(m_converterICU);
        if (!m_converterICU) {
            WTF_LOG_ERROR("error creating ICU encoder even though encoding was in table");
            return String();
        }
    }

    ErrorCallbackSetter callbackSetter(m_converterICU, stopOnError);

    StringBuilder result;

    UChar buffer[ConversionBufferSize];
    UChar* bufferLimit = buffer + ConversionBufferSize;
    const char* source = reinterpret_cast<const char*>(bytes);
    const char* sourceLimit = source + length;
    int32_t* offsets = nullptr;
    UErrorCode err = U_ZERO_ERROR;

    do {
        int ucharsDecoded = decodeToBuffer(buffer, bufferLimit, source, sourceLimit, offsets, flush != DoNotFlush, err);
        result.append(buffer, ucharsDecoded);
    } while (err == U_BUFFER_OVERFLOW_ERROR);

    if (U_FAILURE(err)) {
        // flush the converter so it can be reused, and not be bothered by this error.
        do {
            decodeToBuffer(buffer, bufferLimit, source, sourceLimit, offsets, true, err);
        } while (source < sourceLimit);
        sawError = true;
    }

#if !defined(USING_SYSTEM_ICU)
    // Chrome's copy of ICU does not have the issue described below.
    return result.toString();
#else
    String resultString = result.toString();

    // <http://bugs.webkit.org/show_bug.cgi?id=17014>
    // Simplified Chinese pages use the code A3A0 to mean "full-width space", but ICU decodes it as U+E5E5.
    if (!strcmp(m_encoding.name(), "GBK")) {
        if (!strcasecmp(m_encoding.name(), "gb18030"))
            resultString.replace(0xE5E5, ideographicSpaceCharacter);
        // Make GBK compliant to the encoding spec and align with GB18030
        resultString.replace(0x01F9, 0xE7C8);
        // FIXME: Once https://www.w3.org/Bugs/Public/show_bug.cgi?id=28740#c3
        // is resolved, add U+1E3F => 0xE7C7.
    }

    return resultString;
#endif
}
示例#16
0
void SimpleFontData::platformGlyphInit()
{
    GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
    if (!glyphPageZero) {
        WTF_LOG_ERROR("Failed to get glyph page zero.");
        m_spaceGlyph = 0;
        m_spaceWidth = 0;
        m_zeroGlyph = 0;
        m_adjustedSpaceWidth = 0;
        determinePitch();
        m_zeroWidthSpaceGlyph = 0;
        m_missingGlyphData.fontData = this;
        m_missingGlyphData.glyph = 0;
        return;
    }

    m_zeroWidthSpaceGlyph = glyphPageZero->glyphForCharacter(0);

    // Nasty hack to determine if we should round or ceil space widths.
    // If the font is monospace or fake monospace we ceil to ensure that
    // every character and the space are the same width.  Otherwise we round.
    m_spaceGlyph = glyphPageZero->glyphForCharacter(' ');
    float width = widthForGlyph(m_spaceGlyph);
    m_spaceWidth = width;
    m_zeroGlyph = glyphPageZero->glyphForCharacter('0');
    m_fontMetrics.setZeroWidth(widthForGlyph(m_zeroGlyph));
    determinePitch();
    m_adjustedSpaceWidth = m_treatAsFixedPitch ? ceilf(width) : roundf(width);

    // Force the glyph for ZERO WIDTH SPACE to have zero width, unless it is shared with SPACE.
    // Helvetica is an example of a non-zero width ZERO WIDTH SPACE glyph.
    // See <http://bugs.webkit.org/show_bug.cgi?id=13178>
    // Ask for the glyph for 0 to avoid paging in ZERO WIDTH SPACE. Control characters, including 0,
    // are mapped to the ZERO WIDTH SPACE glyph.
    if (m_zeroWidthSpaceGlyph == m_spaceGlyph) {
        m_zeroWidthSpaceGlyph = 0;
        WTF_LOG_ERROR("Font maps SPACE and ZERO WIDTH SPACE to the same glyph. Glyph width will not be overridden.");
    }

    m_missingGlyphData.fontData = this;
    m_missingGlyphData.glyph = 0;
}
static bool setTextValueInDatabase(SQLiteDatabase& db, const String& query, const String& value)
{
    SQLiteStatement statement(db, query);
    int result = statement.prepare();

    if (result != SQLResultOk) {
        WTF_LOG_ERROR("Failed to prepare statement to set value in database (%s)", query.ascii().data());
        return false;
    }

    statement.bindText(1, value);

    result = statement.step();
    if (result != SQLResultDone) {
        WTF_LOG_ERROR("Failed to step statement to set value in database (%s)", query.ascii().data());
        return false;
    }

    return true;
}
示例#18
0
void SimpleFontData::platformInit()
{
    if (!m_platformData.size()) {
        m_fontMetrics.reset();
        m_avgCharWidth = 0;
        m_maxCharWidth = 0;
        return;
    }

    HWndDC dc(0);
    HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());

    TEXTMETRIC textMetric = {0};
    if (!GetTextMetrics(dc, &textMetric)) {
        if (FontPlatformData::ensureFontLoaded(m_platformData.hfont())) {
            // Retry GetTextMetrics.
            // FIXME: Handle gracefully the error if this call also fails.
            // See http://crbug.com/6401.
            if (!GetTextMetrics(dc, &textMetric))
                WTF_LOG_ERROR("Unable to get the text metrics after second attempt");
        }
    }

    m_avgCharWidth = textMetric.tmAveCharWidth;
    m_maxCharWidth = textMetric.tmMaxCharWidth;

    // FIXME: Access ascent/descent/lineGap with floating point precision.
    float ascent = textMetric.tmAscent;
    float descent = textMetric.tmDescent;
    float lineGap = textMetric.tmExternalLeading;
    float xHeight = ascent * 0.56f; // Best guess for xHeight for non-Truetype fonts.

    OUTLINETEXTMETRIC outlineTextMetric;
    if (GetOutlineTextMetrics(dc, sizeof(outlineTextMetric), &outlineTextMetric) > 0) {
        m_fontMetrics.setUnitsPerEm(outlineTextMetric.otmEMSquare);

        // This is a TrueType font.  We might be able to get an accurate xHeight.
        GLYPHMETRICS glyphMetrics = {0};
        MAT2 identityMatrix = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
        DWORD len = GetGlyphOutlineW(dc, 'x', GGO_METRICS, &glyphMetrics, 0, 0, &identityMatrix);
        if (len != GDI_ERROR && glyphMetrics.gmBlackBoxY > 0)
            xHeight = static_cast<float>(glyphMetrics.gmBlackBoxY);
    }

    m_fontMetrics.setAscent(ascent);
    m_fontMetrics.setDescent(descent);
    m_fontMetrics.setLineGap(lineGap);
    m_fontMetrics.setXHeight(xHeight);
    m_fontMetrics.setLineSpacing(ascent + descent + lineGap);

    SelectObject(dc, oldFont);
}
void SQLiteDatabase::setAuthorizer(DatabaseAuthorizer* auth)
{
    if (!m_db) {
        WTF_LOG_ERROR("Attempt to set an authorizer on a non-open SQL database");
        ASSERT_NOT_REACHED();
        return;
    }

    MutexLocker locker(m_authorizerLock);

    m_authorizer = auth;

    enableAuthorizer(true);
}
示例#20
0
void FrameView::paint(GraphicsContext* context, const IntRect& rect)
{
#ifndef NDEBUG
    bool fillWithRed;
    if (isTransparent())
        fillWithRed = false; // Transparent, don't fill with red.
    else
        fillWithRed = true;

    if (fillWithRed)
        context->fillRect(rect, Color(0xFF, 0, 0));
#endif

    RenderView* renderView = this->renderView();
    if (!renderView) {
        WTF_LOG_ERROR("called FrameView::paint with nil renderer");
        return;
    }

    RELEASE_ASSERT(!needsLayout());

    bool isTopLevelPainter = !s_inPaintContents;
    s_inPaintContents = true;

    FontCachePurgePreventer fontCachePurgePreventer;

    ASSERT(!m_isPainting);
    m_isPainting = true;

#if ENABLE(ASSERT)
    renderView->assertSubtreeIsLaidOut();
    RenderObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(*renderView);
#endif

    LayerPaintingInfo paintingInfo(renderView->layer(),
        pixelSnappedIntRect(renderView->viewRect()), LayoutSize());
    renderView->paintLayer(context, paintingInfo);

    m_isPainting = false;
    m_lastPaintTime = currentTime();

    if (isTopLevelPainter) {
        // Everything that happens after paintContents completions is considered
        // to be part of the next frame.
        s_currentFrameTimeStamp = currentTime();
        s_inPaintContents = false;
    }
}
示例#21
0
ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* name)
{
    // Visual Studio has a 31-character limit on thread names. Longer names will
    // be truncated silently, but we'd like callers to know about the limit.
#if !LOG_DISABLED
    if (name && strlen(name) > 31)
        WTF_LOG_ERROR("Thread name \"%s\" is longer than 31 characters and will be truncated by Visual Studio", name);
#endif

    NewThreadContext* context = new NewThreadContext(entryPoint, data, name);

    // Prevent the thread body from executing until we've established the thread identifier.
    MutexLocker locker(context->creationMutex);

    return createThreadInternal(threadEntryPoint, context, name);
}
示例#22
0
MIMEHeader::Encoding MIMEHeader::parseContentTransferEncoding(const String& text)
{
    String encoding = text.stripWhiteSpace().lower();
    if (encoding == "base64")
        return Base64;
    if (encoding == "quoted-printable")
        return QuotedPrintable;
    if (encoding == "8bit")
        return EightBit;
    if (encoding == "7bit")
        return SevenBit;
    if (encoding == "binary")
        return Binary;
    WTF_LOG_ERROR("Unknown encoding '%s' found in MIME header.", text.ascii().data());
    return Unknown;
}
示例#23
0
String TextCodecICU::decode(const char* bytes, size_t length, FlushBehavior flush, bool stopOnError, bool& sawError)
{
    // Get a converter for the passed-in encoding.
    if (!m_converterICU) {
        createICUConverter();
        ASSERT(m_converterICU);
        if (!m_converterICU) {
            WTF_LOG_ERROR("error creating ICU encoder even though encoding was in table");
            return String();
        }
    }

    ErrorCallbackSetter callbackSetter(m_converterICU, stopOnError);

    StringBuilder result;

    UChar buffer[ConversionBufferSize];
    UChar* bufferLimit = buffer + ConversionBufferSize;
    const char* source = reinterpret_cast<const char*>(bytes);
    const char* sourceLimit = source + length;
    int32_t* offsets = NULL;
    UErrorCode err = U_ZERO_ERROR;

    do {
        int ucharsDecoded = decodeToBuffer(buffer, bufferLimit, source, sourceLimit, offsets, flush != DoNotFlush, err);
        result.append(buffer, ucharsDecoded);
    } while (err == U_BUFFER_OVERFLOW_ERROR);

    if (U_FAILURE(err)) {
        // flush the converter so it can be reused, and not be bothered by this error.
        do {
            decodeToBuffer(buffer, bufferLimit, source, sourceLimit, offsets, true, err);
        } while (source < sourceLimit);
        sawError = true;
    }

    String resultString = result.toString();

    // <http://bugs.webkit.org/show_bug.cgi?id=17014>
    // Simplified Chinese pages use the code A3A0 to mean "full-width space", but ICU decodes it as U+E5E5.
    if (!strcmp(m_encoding.name(), "GBK") || !strcasecmp(m_encoding.name(), "gb18030"))
        resultString.replace(0xE5E5, ideographicSpace);

    return resultString;
}
bool Database::getVersionFromDatabase(String& version, bool shouldCacheVersion)
{
    String query(String("SELECT value FROM ") + infoTableName +  " WHERE key = '" + versionKey + "';");

    m_databaseAuthorizer->disable();

    bool result = retrieveTextResultFromDatabase(m_sqliteDatabase, query, version);
    if (result) {
        if (shouldCacheVersion)
            setCachedVersion(version);
    } else {
        WTF_LOG_ERROR("Failed to retrieve version from database %s", databaseDebugName().ascii().data());
    }

    m_databaseAuthorizer->enable();

    return result;
}
示例#25
0
ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char* threadName)
{
    unsigned threadIdentifier = 0;
    ThreadIdentifier threadID = 0;
    OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(new ThreadFunctionInvocation(entryPoint, data));
    HANDLE threadHandle = reinterpret_cast<HANDLE>(_beginthreadex(0, 0, wtfThreadEntryPoint, invocation.get(), 0, &threadIdentifier));
    if (!threadHandle) {
        WTF_LOG_ERROR("Failed to create thread at entry point %p with data %p: %ld", entryPoint, data, errno);
        return 0;
    }

    // The thread will take ownership of invocation.
    ThreadFunctionInvocation* leakedInvocation ALLOW_UNUSED = invocation.leakPtr();

    threadID = static_cast<ThreadIdentifier>(threadIdentifier);
    storeThreadHandleByIdentifier(threadIdentifier, threadHandle);

    return threadID;
}
bool Database::setVersionInDatabase(const String& version, bool shouldCacheVersion)
{
    // The INSERT will replace an existing entry for the database with the new
    // version number, due to the UNIQUE ON CONFLICT REPLACE clause in the
    // CREATE statement (see Database::performOpenAndVerify()).
    String query(String("INSERT INTO ") + infoTableName +  " (key, value) VALUES ('" + versionKey + "', ?);");

    m_databaseAuthorizer->disable();

    bool result = setTextValueInDatabase(m_sqliteDatabase, query, version);
    if (result) {
        if (shouldCacheVersion)
            setCachedVersion(version);
    } else {
        WTF_LOG_ERROR("Failed to set version %s in database (%s)", version.ascii().data(), query.ascii().data());
    }

    m_databaseAuthorizer->enable();

    return result;
}
示例#27
0
FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const
{
    HWndDC hdc(0);
    SetGraphicsMode(hdc, GM_ADVANCED);
    HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont());

    GLYPHMETRICS gdiMetrics;
    static const MAT2 identity = { 0, 1,  0, 0,  0, 0,  0, 1 };
    if (GetGlyphOutline(hdc, glyph, GGO_METRICS | GGO_GLYPH_INDEX, &gdiMetrics, 0, 0, &identity) == -1) {
        if (FontPlatformData::ensureFontLoaded(m_platformData.hfont())) {
            // Retry GetTextMetrics.
            // FIXME: Handle gracefully the error if this call also fails.
            // See http://crbug.com/6401.
            if (GetGlyphOutline(hdc, glyph, GGO_METRICS | GGO_GLYPH_INDEX, &gdiMetrics, 0, 0, &identity) == -1)
                WTF_LOG_ERROR("Unable to get the glyph metrics after second attempt");
        }
    }

    SelectObject(hdc, oldFont);

    return FloatRect(gdiMetrics.gmptGlyphOrigin.x, -gdiMetrics.gmptGlyphOrigin.y,
        gdiMetrics.gmBlackBoxX, gdiMetrics.gmBlackBoxY);
}
示例#28
0
float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
{
    if (!m_platformData.size())
        return 0;

    HWndDC dc(0);
    HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());

    int width = 0;
    if (!GetCharWidthI(dc, glyph, 1, 0, &width)) {
        // Ask the browser to preload the font and retry.
        if (FontPlatformData::ensureFontLoaded(m_platformData.hfont())) {
            // FIXME: Handle gracefully the error if this call also fails.
            // See http://crbug.com/6401.
            if (!GetCharWidthI(dc, glyph, 1, 0, &width))
                WTF_LOG_ERROR("Unable to get the char width after second attempt");
        }
    }

    SelectObject(dc, oldFont);

    return static_cast<float>(width);
}
void FramePainter::paintContents(GraphicsContext& context, const GlobalPaintFlags globalPaintFlags, const IntRect& rect)
{
    Document* document = frameView().frame().document();

#ifndef NDEBUG
    bool fillWithRed;
    if (document->printing())
        fillWithRed = false; // Printing, don't fill with red (can't remember why).
    else if (frameView().frame().owner())
        fillWithRed = false; // Subframe, don't fill with red.
    else if (frameView().isTransparent())
        fillWithRed = false; // Transparent, don't fill with red.
    else if (globalPaintFlags & GlobalPaintSelectionOnly)
        fillWithRed = false; // Selections are transparent, don't fill with red.
    else
        fillWithRed = true;

    if (fillWithRed && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, *frameView().layoutView(), DisplayItem::DebugRedFill, LayoutPoint())) {
        IntRect contentRect(IntPoint(), frameView().contentsSize());
        LayoutObjectDrawingRecorder drawingRecorder(context, *frameView().layoutView(), DisplayItem::DebugRedFill, contentRect, LayoutPoint());
    }
#endif

    LayoutView* layoutView = frameView().layoutView();
    if (!layoutView) {
        WTF_LOG_ERROR("called FramePainter::paint with nil layoutObject");
        return;
    }

    if (!frameView().shouldThrottleRendering()) {
        RELEASE_ASSERT(!frameView().needsLayout());
        ASSERT(document->lifecycle().state() >= DocumentLifecycle::CompositingClean);
    }

    TRACE_EVENT1("devtools.timeline", "Paint", "data", InspectorPaintEvent::data(layoutView, LayoutRect(rect), 0));

    bool isTopLevelPainter = !s_inPaintContents;
    s_inPaintContents = true;

    FontCachePurgePreventer fontCachePurgePreventer;

    // TODO(jchaffraix): GlobalPaintFlags should be const during a paint
    // phase. Thus we should set this flag upfront (crbug.com/510280).
    GlobalPaintFlags localPaintFlags = globalPaintFlags;
    if (document->printing())
        localPaintFlags |= GlobalPaintFlattenCompositingLayers | GlobalPaintPrinting;

    PaintLayer* rootLayer = layoutView->layer();

#if ENABLE(ASSERT)
    if (!frameView().shouldThrottleRendering())
        layoutView->assertSubtreeIsLaidOut();
    LayoutObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(*rootLayer->layoutObject());
#endif

    PaintLayerPainter layerPainter(*rootLayer);

    float deviceScaleFactor = blink::deviceScaleFactor(rootLayer->layoutObject()->frame());
    context.setDeviceScaleFactor(deviceScaleFactor);

    layerPainter.paint(context, LayoutRect(rect), localPaintFlags);

    if (rootLayer->containsDirtyOverlayScrollbars())
        layerPainter.paintOverlayScrollbars(context, LayoutRect(rect), localPaintFlags);

    // Regions may have changed as a result of the visibility/z-index of element changing.
    if (document->annotatedRegionsDirty())
        frameView().updateDocumentAnnotatedRegions();

    if (isTopLevelPainter) {
        // Everything that happens after paintContents completions is considered
        // to be part of the next frame.
        memoryCache()->updateFramePaintTimestamp();
        s_inPaintContents = false;
    }

    InspectorInstrumentation::didPaint(layoutView, 0, context, LayoutRect(rect));
}
示例#30
0
PassRefPtrWillBeRawPtr<ArchiveResource> MHTMLParser::parseNextPart(const MIMEHeader& mimeHeader, const String& endOfPartBoundary, const String& endOfDocumentBoundary, bool& endOfArchiveReached)
{
    ASSERT(endOfPartBoundary.isEmpty() == endOfDocumentBoundary.isEmpty());

    // If no content transfer encoding is specified, default to binary encoding.
    MIMEHeader::Encoding contentTransferEncoding = mimeHeader.contentTransferEncoding();
    if (contentTransferEncoding == MIMEHeader::Unknown)
        contentTransferEncoding = MIMEHeader::Binary;

    RefPtr<SharedBuffer> content = SharedBuffer::create();
    const bool checkBoundary = !endOfPartBoundary.isEmpty();
    bool endOfPartReached = false;
    if (contentTransferEncoding == MIMEHeader::Binary) {
        if (!checkBoundary) {
            WTF_LOG_ERROR("Binary contents requires end of part");
            return nullptr;
        }
        m_lineReader.setSeparator(endOfPartBoundary.utf8().data());
        Vector<char> part;
        if (!m_lineReader.nextChunk(part)) {
            WTF_LOG_ERROR("Binary contents requires end of part");
            return nullptr;
        }
        content->append(part);
        m_lineReader.setSeparator("\r\n");
        Vector<char> nextChars;
        if (m_lineReader.peek(nextChars, 2) != 2) {
            WTF_LOG_ERROR("Invalid seperator.");
            return nullptr;
        }
        endOfPartReached = true;
        ASSERT(nextChars.size() == 2);
        endOfArchiveReached = (nextChars[0] == '-' && nextChars[1] == '-');
        if (!endOfArchiveReached) {
            String line = m_lineReader.nextChunkAsUTF8StringWithLatin1Fallback();
            if (!line.isEmpty()) {
                WTF_LOG_ERROR("No CRLF at end of binary section.");
                return nullptr;
            }
        }
    } else {
        String line;
        while (!(line = m_lineReader.nextChunkAsUTF8StringWithLatin1Fallback()).isNull()) {
            endOfArchiveReached = (line == endOfDocumentBoundary);
            if (checkBoundary && (line == endOfPartBoundary || endOfArchiveReached)) {
                endOfPartReached = true;
                break;
            }
            // Note that we use line.utf8() and not line.ascii() as ascii turns special characters (such as tab, line-feed...) into '?'.
            content->append(line.utf8().data(), line.length());
            if (contentTransferEncoding == MIMEHeader::QuotedPrintable) {
                // The line reader removes the \r\n, but we need them for the content in this case as the QuotedPrintable decoder expects CR-LF terminated lines.
                content->append("\r\n", 2u);
            }
        }
    }
    if (!endOfPartReached && checkBoundary) {
        WTF_LOG_ERROR("No bounday found for MHTML part.");
        return nullptr;
    }

    Vector<char> data;
    switch (contentTransferEncoding) {
    case MIMEHeader::Base64:
        if (!base64Decode(content->data(), content->size(), data)) {
            WTF_LOG_ERROR("Invalid base64 content for MHTML part.");
            return nullptr;
        }
        break;
    case MIMEHeader::QuotedPrintable:
        quotedPrintableDecode(content->data(), content->size(), data);
        break;
    case MIMEHeader::EightBit:
    case MIMEHeader::SevenBit:
    case MIMEHeader::Binary:
        data.append(content->data(), content->size());
        break;
    default:
        WTF_LOG_ERROR("Invalid encoding for MHTML part.");
        return nullptr;
    }
    RefPtr<SharedBuffer> contentBuffer = SharedBuffer::adoptVector(data);
    // FIXME: the URL in the MIME header could be relative, we should resolve it if it is.
    // The specs mentions 5 ways to resolve a URL: http://tools.ietf.org/html/rfc2557#section-5
    // IE and Firefox (UNMht) seem to generate only absolute URLs.
    KURL location = KURL(KURL(), mimeHeader.contentLocation());
    return ArchiveResource::create(
        contentBuffer, location, mimeHeader.contentID(), AtomicString(mimeHeader.contentType()), AtomicString(mimeHeader.charset()));
}