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(); }
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; }
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); }
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(); }
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; }
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; }
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 }
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; }
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); }
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; } }
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); }
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; }
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; }
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; }
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); }
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)); }
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())); }