EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); if (!thisValue.inherits(&RegExpObject::info)) return throwVMTypeError(exec); RefPtr<RegExp> regExp; JSValue arg0 = exec->argument(0); JSValue arg1 = exec->argument(1); if (arg0.inherits(&RegExpObject::info)) { if (!arg1.isUndefined()) return throwVMError(exec, createTypeError(exec, "Cannot supply flags when constructing one RegExp from another.")); regExp = asRegExpObject(arg0)->regExp(); } else { UString pattern = !exec->argumentCount() ? UString("") : arg0.toString(exec); UString flags = arg1.isUndefined() ? UString("") : arg1.toString(exec); regExp = exec->globalData().regExpCache()->lookupOrCreate(pattern, flags); } if (!regExp->isValid()) return throwVMError(exec, createSyntaxError(exec, makeString("Invalid regular expression: ", regExp->errorMessage()))); asRegExpObject(thisValue)->setRegExp(regExp.release()); asRegExpObject(thisValue)->setLastIndex(0); return JSValue::encode(jsUndefined()); }
short IDBFactory::cmp(ScriptExecutionContext* context, const Deprecated::ScriptValue& firstValue, const Deprecated::ScriptValue& secondValue, ExceptionCode& ec) { DOMRequestState requestState(context); RefPtr<IDBKey> first = scriptValueToIDBKey(&requestState, firstValue); RefPtr<IDBKey> second = scriptValueToIDBKey(&requestState, secondValue); ASSERT(first); ASSERT(second); if (!first->isValid() || !second->isValid()) { ec = IDBDatabaseException::DataError; return 0; } return static_cast<short>(first->compare(second.get())); }
// ECMA 15.10.4 JSObject* constructRegExp(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args) { JSValue arg0 = args.at(0); JSValue arg1 = args.at(1); if (arg0.inherits(&RegExpObject::s_info)) { if (!arg1.isUndefined()) return throwError(exec, createTypeError(exec, "Cannot supply flags when constructing one RegExp from another.")); return asObject(arg0); } UString pattern = arg0.isUndefined() ? UString("") : arg0.toString(exec); if (exec->hadException()) return 0; RegExpFlags flags = NoFlags; if (!arg1.isUndefined()) { flags = regExpFlags(arg1.toString(exec)); if (exec->hadException()) return 0; if (flags == InvalidFlags) return throwError(exec, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor.")); } RefPtr<RegExp> regExp = exec->globalData().regExpCache()->lookupOrCreate(pattern, flags); if (!regExp->isValid()) return throwError(exec, createSyntaxError(exec, regExp->errorMessage())); return new (exec) RegExpObject(exec->lexicalGlobalObject(), globalObject->regExpStructure(), regExp.release()); }
JSValue* regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args) { if (!thisValue->isObject(&RegExpObject::info)) return throwError(exec, TypeError); RefPtr<RegExp> regExp; JSValue* arg0 = args.at(exec, 0); JSValue* arg1 = args.at(exec, 1); if (arg0->isObject(&RegExpObject::info)) { if (!arg1->isUndefined()) return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another."); regExp = asRegExpObject(arg0)->regExp(); } else { UString pattern = args.isEmpty() ? UString("") : arg0->toString(exec); UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec); regExp = RegExp::create(&exec->globalData(), pattern, flags); } if (!regExp->isValid()) return throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage())); asRegExpObject(thisValue)->setRegExp(regExp.release()); asRegExpObject(thisValue)->setLastIndex(0); return jsUndefined(); }
void CSSFontSelector::addFontFaceRule(const StyleRuleFontFace* fontFaceRule) { RefPtr<FontFace> fontFace = FontFace::create(fontFaceRule); if (!fontFace || fontFace->family().isEmpty()) return; unsigned traitsMask = fontFace->traitsMask(); if (!traitsMask) return; RefPtr<CSSFontFace> cssFontFace = fontFace->createCSSFontFace(m_document); if (!cssFontFace || !cssFontFace->isValid()) return; OwnPtr<HashMap<unsigned, RefPtr<CSSSegmentedFontFace> > >& familyFontFaces = m_fontFaces.add(fontFace->family(), nullptr).iterator->value; if (!familyFontFaces) { familyFontFaces = adoptPtr(new HashMap<unsigned, RefPtr<CSSSegmentedFontFace> >); ASSERT(!m_locallyInstalledFontFaces.contains(fontFace->family())); Vector<unsigned> locallyInstalledFontsTraitsMasks; fontCache()->getTraitsInFamily(fontFace->family(), locallyInstalledFontsTraitsMasks); if (unsigned numLocallyInstalledFaces = locallyInstalledFontsTraitsMasks.size()) { OwnPtr<Vector<RefPtr<CSSSegmentedFontFace> > > familyLocallyInstalledFaces = adoptPtr(new Vector<RefPtr<CSSSegmentedFontFace> >); for (unsigned i = 0; i < numLocallyInstalledFaces; ++i) { RefPtr<CSSFontFace> locallyInstalledFontFace = CSSFontFace::create(0); locallyInstalledFontFace->addSource(adoptPtr(new CSSFontFaceSource(fontFace->family()))); ASSERT(locallyInstalledFontFace->isValid()); RefPtr<CSSSegmentedFontFace> segmentedFontFace = CSSSegmentedFontFace::create(this, static_cast<FontTraitsMask>(locallyInstalledFontsTraitsMasks[i]), true); segmentedFontFace->appendFontFace(locallyInstalledFontFace.release()); familyLocallyInstalledFaces->append(segmentedFontFace); } m_locallyInstalledFontFaces.set(fontFace->family(), familyLocallyInstalledFaces.release()); } } RefPtr<CSSSegmentedFontFace>& segmentedFontFace = familyFontFaces->add(traitsMask, 0).iterator->value; if (!segmentedFontFace) segmentedFontFace = CSSSegmentedFontFace::create(this, static_cast<FontTraitsMask>(traitsMask), false); segmentedFontFace->appendFontFace(cssFontFace); ++m_version; }
short IDBFactory::cmp(ScriptExecutionContext* context, const Deprecated::ScriptValue& firstValue, const Deprecated::ScriptValue& secondValue, ExceptionCodeWithMessage& ec) { DOMRequestState requestState(context); RefPtr<IDBKey> first = scriptValueToIDBKey(&requestState, firstValue); RefPtr<IDBKey> second = scriptValueToIDBKey(&requestState, secondValue); ASSERT(first); ASSERT(second); if (!first->isValid() || !second->isValid()) { ec.code = IDBDatabaseException::DataError; ec.message = ASCIILiteral("Failed to execute 'cmp' on 'IDBFactory': The parameter is not a valid key."); return 0; } return static_cast<short>(first->compare(second.get())); }
inline int computeCost() const { if (!texture || !texture->isValid() || texture->isPacked()) return 0; const IntSize textureSize = texture->size(); // An image's cost in bytes is width * height * bytes per pixel (4). return textureSize.width() * textureSize.height() * 4; }
PassRefPtr<IDBKeyRange> IDBKeyRange::only(PassRefPtr<IDBKey> prpKey, ExceptionState& es) { RefPtr<IDBKey> key = prpKey; if (!key || !key->isValid()) { es.throwDOMException(DataError, IDBDatabase::notValidKeyErrorMessage); return 0; } return IDBKeyRange::create(key, key, LowerBoundClosed, UpperBoundClosed); }
PassRefPtr<IDBKeyRange> IDBKeyRange::upperBound(ScriptExecutionContext* context, const ScriptValue& boundValue, bool open, ExceptionState& es) { DOMRequestState requestState(context); RefPtr<IDBKey> bound = scriptValueToIDBKey(&requestState, boundValue); if (!bound || !bound->isValid()) { es.throwDOMException(DataError, IDBDatabase::notValidKeyErrorMessage); return 0; } return IDBKeyRange::create(0, bound, LowerBoundOpen, open ? UpperBoundOpen : UpperBoundClosed); }
PassRefPtr<IDBKeyRange> IDBKeyRange::only(ScriptExecutionContext* context, const ScriptValue& keyValue, ExceptionState& es) { DOMRequestState requestState(context); RefPtr<IDBKey> key = scriptValueToIDBKey(&requestState, keyValue); if (!key || !key->isValid()) { es.throwDOMException(DataError, IDBDatabase::notValidKeyErrorMessage); return 0; } return IDBKeyRange::create(key, key, LowerBoundClosed, UpperBoundClosed); }
PassRefPtr<IDBKeyRange> IDBKeyRange::bound(ScriptExecutionContext* context, const ScriptValue& lowerValue, const ScriptValue& upperValue, bool lowerOpen, bool upperOpen, ExceptionState& es) { DOMRequestState requestState(context); RefPtr<IDBKey> lower = scriptValueToIDBKey(&requestState, lowerValue); RefPtr<IDBKey> upper = scriptValueToIDBKey(&requestState, upperValue); if (!lower || !lower->isValid() || !upper || !upper->isValid()) { es.throwDOMException(DataError, IDBDatabase::notValidKeyErrorMessage); return 0; } if (upper->isLessThan(lower.get())) { es.throwDOMException(DataError, "The lower key is greater than the upper key."); return 0; } if (upper->isEqual(lower.get()) && (lowerOpen || upperOpen)) { es.throwDOMException(DataError, "The lower key and upper key are equal and one of the bounds is open."); return 0; } return IDBKeyRange::create(lower, upper, lowerOpen ? LowerBoundOpen : LowerBoundClosed, upperOpen ? UpperBoundOpen : UpperBoundClosed); }
void generateIndexKeysForValue(ExecState* exec, const IDBIndexMetadata& indexMetadata, const Deprecated::ScriptValue& objectValue, Vector<IDBKeyData>& indexKeys) { RefPtr<IDBKey> indexKey = createIDBKeyFromScriptValueAndKeyPath(exec, objectValue, indexMetadata.keyPath); if (!indexKey) return; if (!indexMetadata.multiEntry || indexKey->type() != KeyType::Array) { if (!indexKey->isValid()) return; indexKeys.append(IDBKeyData(indexKey.get())); } else { ASSERT(indexMetadata.multiEntry); ASSERT(indexKey->type() == KeyType::Array); indexKey = IDBKey::createMultiEntryArray(indexKey->array()); if (!indexKey->isValid()) return; for (auto& i : indexKey->array()) indexKeys.append(IDBKeyData(i.get())); } }
PassRefPtr<IDBKeyRange> IDBKeyRange::fromScriptValue(ExecutionContext* context, const ScriptValue& value, ExceptionState& es) { DOMRequestState requestState(context); if (value.isUndefined() || value.isNull()) return 0; RefPtr<IDBKeyRange> range = scriptValueToIDBKeyRange(&requestState, value); if (range) return range.release(); RefPtr<IDBKey> key = scriptValueToIDBKey(&requestState, value); if (!key || !key->isValid()) { es.throwDOMException(DataError, IDBDatabase::notValidKeyErrorMessage); return 0; } return adoptRef(new IDBKeyRange(key, key, LowerBoundClosed, UpperBoundClosed)); }
// ECMA 15.10.4 AJObject* constructRegExp(ExecState* exec, const ArgList& args) { AJValue arg0 = args.at(0); AJValue arg1 = args.at(1); if (arg0.inherits(&RegExpObject::info)) { if (!arg1.isUndefined()) return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another."); return asObject(arg0); } UString pattern = arg0.isUndefined() ? UString("") : arg0.toString(exec); UString flags = arg1.isUndefined() ? UString("") : arg1.toString(exec); RefPtr<RegExp> regExp = exec->globalData().regExpCache()->lookupOrCreate(pattern, flags); if (!regExp->isValid()) return throwError(exec, SyntaxError, makeString("Invalid regular expression: ", regExp->errorMessage())); return new (exec) RegExpObject(exec->lexicalGlobalObject()->regExpStructure(), regExp.release()); }
// ECMA 15.10.4 JSObject* constructRegExp(ExecState* exec, const ArgList& args) { JSValuePtr arg0 = args.at(exec, 0); JSValuePtr arg1 = args.at(exec, 1); if (arg0->isObject(&RegExpObject::info)) { if (!arg1->isUndefined()) return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another."); return asObject(arg0); } UString pattern = arg0->isUndefined() ? UString("") : arg0->toString(exec); UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec); RefPtr<RegExp> regExp = RegExp::create(&exec->globalData(), pattern, flags); if (!regExp->isValid()) return throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage())); return new (exec) RegExpObject(exec->lexicalGlobalObject()->regExpStructure(), regExp.release()); }
void WebPageProxy::requestInstallMissingMediaPlugins(const String& details) { CString detail = details.utf8(); const char* detailArray[2] = { detail.data(), nullptr }; ref(); GUniquePtr<GstInstallPluginsContext> context = m_pageClient.createGstInstallPluginsContext(); GstInstallPluginsReturn result = gst_install_plugins_async(detailArray, context.get(), [](GstInstallPluginsReturn result, gpointer userData) { RefPtr<WebPageProxy> page = adoptRef(static_cast<WebPageProxy*>(userData)); if (page->isValid()) page->send(Messages::WebPage::DidEndRequestInstallMissingMediaPlugins(static_cast<uint32_t>(result))); }, this); if (result != GST_INSTALL_PLUGINS_STARTED_OK) { // If the installer didn't start, the callback will not be called, so remove the ref manually. deref(); send(Messages::WebPage::DidEndRequestInstallMissingMediaPlugins(static_cast<uint32_t>(result))); WTFLogAlways("Missing GStreamer Plugin: %s\n", detail.data()); } }
void shutdown() { if( !sg_system.isValid() ) return; SystemState systemState = sg_system->getState(); // ISystem::setupBase() ran successfully but ISystem::setupPresentation() was not called? assert( systemState != SystemState_Integrated ); // tear down the system if it's still running if( systemState == SystemState_Running ) sg_system->tearDown(); // release the main system interfaces sg_serviceManager = NULL; sg_typeManager = NULL; sg_system = NULL; // flush all released libraries LibraryManager::flush(); }
static void generateIndexKeysForValue(DOMRequestState* requestState, const IDBIndexMetadata& indexMetadata, const ScriptValue& objectValue, IDBObjectStore::IndexKeys* indexKeys) { ASSERT(indexKeys); RefPtr<IDBKey> indexKey = createIDBKeyFromScriptValueAndKeyPath(requestState, objectValue, indexMetadata.keyPath); if (!indexKey) return; if (!indexMetadata.multiEntry || indexKey->type() != IDBKey::ArrayType) { if (!indexKey->isValid()) return; indexKeys->append(indexKey); } else { ASSERT(indexMetadata.multiEntry); ASSERT(indexKey->type() == IDBKey::ArrayType); indexKey = IDBKey::createMultiEntryArray(indexKey->array()); for (size_t i = 0; i < indexKey->array().size(); ++i) indexKeys->append(indexKey->array()[i]); } }
void CSSFontSelector::addFontFaceRule(const CSSFontFaceRule* fontFaceRule) { // Obtain the font-family property and the src property. Both must be defined. const StylePropertySet* style = fontFaceRule->declaration(); RefPtr<CSSValue> fontFamily = style->getPropertyCSSValue(CSSPropertyFontFamily); RefPtr<CSSValue> src = style->getPropertyCSSValue(CSSPropertySrc); RefPtr<CSSValue> unicodeRange = style->getPropertyCSSValue(CSSPropertyUnicodeRange); if (!fontFamily || !src || !fontFamily->isValueList() || !src->isValueList() || (unicodeRange && !unicodeRange->isValueList())) return; CSSValueList* familyList = static_cast<CSSValueList*>(fontFamily.get()); if (!familyList->length()) return; CSSValueList* srcList = static_cast<CSSValueList*>(src.get()); if (!srcList->length()) return; CSSValueList* rangeList = static_cast<CSSValueList*>(unicodeRange.get()); unsigned traitsMask = 0; if (RefPtr<CSSValue> fontStyle = style->getPropertyCSSValue(CSSPropertyFontStyle)) { if (!fontStyle->isPrimitiveValue()) return; switch (static_cast<CSSPrimitiveValue*>(fontStyle.get())->getIdent()) { case CSSValueNormal: traitsMask |= FontStyleNormalMask; break; case CSSValueItalic: case CSSValueOblique: traitsMask |= FontStyleItalicMask; break; default: break; } } else traitsMask |= FontStyleNormalMask; if (RefPtr<CSSValue> fontWeight = style->getPropertyCSSValue(CSSPropertyFontWeight)) { if (!fontWeight->isPrimitiveValue()) return; switch (static_cast<CSSPrimitiveValue*>(fontWeight.get())->getIdent()) { case CSSValueBold: case CSSValue700: traitsMask |= FontWeight700Mask; break; case CSSValueNormal: case CSSValue400: traitsMask |= FontWeight400Mask; break; case CSSValue900: traitsMask |= FontWeight900Mask; break; case CSSValue800: traitsMask |= FontWeight800Mask; break; case CSSValue600: traitsMask |= FontWeight600Mask; break; case CSSValue500: traitsMask |= FontWeight500Mask; break; case CSSValue300: traitsMask |= FontWeight300Mask; break; case CSSValue200: traitsMask |= FontWeight200Mask; break; case CSSValue100: traitsMask |= FontWeight100Mask; break; default: break; } } else traitsMask |= FontWeight400Mask; if (RefPtr<CSSValue> fontVariant = style->getPropertyCSSValue(CSSPropertyFontVariant)) { // font-variant descriptor can be a value list. if (fontVariant->isPrimitiveValue()) { RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); list->append(fontVariant); fontVariant = list; } else if (!fontVariant->isValueList()) return; CSSValueList* variantList = static_cast<CSSValueList*>(fontVariant.get()); unsigned numVariants = variantList->length(); if (!numVariants) return; for (unsigned i = 0; i < numVariants; ++i) { switch (static_cast<CSSPrimitiveValue*>(variantList->itemWithoutBoundsCheck(i))->getIdent()) { case CSSValueNormal: traitsMask |= FontVariantNormalMask; break; case CSSValueSmallCaps: traitsMask |= FontVariantSmallCapsMask; break; default: break; } } } else traitsMask |= FontVariantMask; // Each item in the src property's list is a single CSSFontFaceSource. Put them all into a CSSFontFace. RefPtr<CSSFontFace> fontFace; int srcLength = srcList->length(); bool foundSVGFont = false; for (int i = 0; i < srcLength; i++) { // An item in the list either specifies a string (local font name) or a URL (remote font to download). CSSFontFaceSrcValue* item = static_cast<CSSFontFaceSrcValue*>(srcList->itemWithoutBoundsCheck(i)); OwnPtr<CSSFontFaceSource> source; #if ENABLE(SVG_FONTS) foundSVGFont = item->isSVGFontFaceSrc() || item->svgFontFaceElement(); #endif if (!item->isLocal()) { Settings* settings = m_document ? m_document->frame() ? m_document->frame()->settings() : 0 : 0; bool allowDownloading = foundSVGFont || (settings && settings->downloadableBinaryFontsEnabled()); if (allowDownloading && item->isSupportedFormat() && m_document) { CachedFont* cachedFont = item->cachedFont(m_document); if (cachedFont) { source = adoptPtr(new CSSFontFaceSource(item->resource(), cachedFont)); #if ENABLE(SVG_FONTS) if (foundSVGFont) source->setHasExternalSVGFont(true); #endif } } } else { source = adoptPtr(new CSSFontFaceSource(item->resource())); } if (!fontFace) fontFace = CSSFontFace::create(static_cast<FontTraitsMask>(traitsMask)); if (source) { #if ENABLE(SVG_FONTS) source->setSVGFontFaceElement(item->svgFontFaceElement()); #endif fontFace->addSource(source.release()); } } ASSERT(fontFace); if (fontFace && !fontFace->isValid()) return; if (rangeList) { unsigned numRanges = rangeList->length(); for (unsigned i = 0; i < numRanges; i++) { CSSUnicodeRangeValue* range = static_cast<CSSUnicodeRangeValue*>(rangeList->itemWithoutBoundsCheck(i)); fontFace->addRange(range->from(), range->to()); } } // Hash under every single family name. int familyLength = familyList->length(); for (int i = 0; i < familyLength; i++) { CSSPrimitiveValue* item = static_cast<CSSPrimitiveValue*>(familyList->itemWithoutBoundsCheck(i)); String familyName; if (item->isString()) familyName = item->getStringValue(); else if (item->isIdent()) { // We need to use the raw text for all the generic family types, since @font-face is a way of actually // defining what font to use for those types. switch (item->getIdent()) { case CSSValueSerif: familyName = serifFamily; break; case CSSValueSansSerif: familyName = sansSerifFamily; break; case CSSValueCursive: familyName = cursiveFamily; break; case CSSValueFantasy: familyName = fantasyFamily; break; case CSSValueMonospace: familyName = monospaceFamily; break; case CSSValueWebkitPictograph: familyName = pictographFamily; break; default: break; } } if (familyName.isEmpty()) continue; OwnPtr<Vector<RefPtr<CSSFontFace> > >& familyFontFaces = m_fontFaces.add(familyName, nullptr).first->second; if (!familyFontFaces) { familyFontFaces = adoptPtr(new Vector<RefPtr<CSSFontFace> >); ASSERT(!m_locallyInstalledFontFaces.contains(familyName)); Vector<unsigned> locallyInstalledFontsTraitsMasks; fontCache()->getTraitsInFamily(familyName, locallyInstalledFontsTraitsMasks); if (unsigned numLocallyInstalledFaces = locallyInstalledFontsTraitsMasks.size()) { OwnPtr<Vector<RefPtr<CSSFontFace> > > familyLocallyInstalledFaces = adoptPtr(new Vector<RefPtr<CSSFontFace> >); for (unsigned i = 0; i < numLocallyInstalledFaces; ++i) { RefPtr<CSSFontFace> locallyInstalledFontFace = CSSFontFace::create(static_cast<FontTraitsMask>(locallyInstalledFontsTraitsMasks[i]), true); locallyInstalledFontFace->addSource(adoptPtr(new CSSFontFaceSource(familyName))); ASSERT(locallyInstalledFontFace->isValid()); familyLocallyInstalledFaces->append(locallyInstalledFontFace); } m_locallyInstalledFontFaces.set(familyName, familyLocallyInstalledFaces.release()); } } familyFontFaces->append(fontFace); ++m_version; } }
RefPtr<WebCore::IDBRequest> IDBObjectStore::putOrAdd(JSC::ExecState& state, JSC::JSValue value, RefPtr<IDBKey> key, IndexedDB::ObjectStoreOverwriteMode overwriteMode, ExceptionCode& ec) { LOG(IndexedDB, "IDBObjectStore::putOrAdd"); if (m_transaction->isReadOnly()) { ec = static_cast<ExceptionCode>(IDBExceptionCode::ReadOnlyError); return nullptr; } if (!m_transaction->isActive()) { ec = static_cast<ExceptionCode>(IDBExceptionCode::TransactionInactiveError); return nullptr; } if (m_deleted) { ec = INVALID_STATE_ERR; return nullptr; } RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::create(&state, value, nullptr, nullptr); if (state.hadException()) { ec = DATA_CLONE_ERR; return nullptr; } if (serializedValue->hasBlobURLs()) { // FIXME: Add Blob/File/FileList support ec = DATA_CLONE_ERR; return nullptr; } if (key && key->type() == KeyType::Invalid) { ec = static_cast<ExceptionCode>(IDBExceptionCode::DataError); return nullptr; } bool usesInlineKeys = !m_info.keyPath().isNull(); bool usesKeyGenerator = autoIncrement(); if (usesInlineKeys) { if (key) { ec = static_cast<ExceptionCode>(IDBExceptionCode::DataError); return nullptr; } RefPtr<IDBKey> keyPathKey = maybeCreateIDBKeyFromScriptValueAndKeyPath(state, value, m_info.keyPath()); if (keyPathKey && !keyPathKey->isValid()) { ec = static_cast<ExceptionCode>(IDBExceptionCode::DataError); return nullptr; } if (!keyPathKey) { if (usesKeyGenerator) { if (!canInjectIDBKeyIntoScriptValue(state, value, m_info.keyPath())) { ec = static_cast<ExceptionCode>(IDBExceptionCode::DataError); return nullptr; } } else { ec = static_cast<ExceptionCode>(IDBExceptionCode::DataError); return nullptr; } } if (keyPathKey) { ASSERT(!key); key = keyPathKey; } } else if (!usesKeyGenerator && !key) { ec = static_cast<ExceptionCode>(IDBExceptionCode::DataError); return nullptr; } auto context = scriptExecutionContextFromExecState(&state); if (!context) { ec = static_cast<ExceptionCode>(IDBExceptionCode::Unknown); return nullptr; } Ref<IDBRequest> request = m_transaction->requestPutOrAdd(*context, *this, key.get(), *serializedValue, overwriteMode); return adoptRef(request.leakRef()); }
RefPtr<IDBRequest> IDBObjectStore::putOrAdd(ExecState& state, JSValue value, RefPtr<IDBKey> key, IndexedDB::ObjectStoreOverwriteMode overwriteMode, InlineKeyCheck inlineKeyCheck, ExceptionCodeWithMessage& ec) { LOG(IndexedDB, "IDBObjectStore::putOrAdd"); ASSERT(currentThread() == m_transaction->database().originThreadID()); auto context = scriptExecutionContextFromExecState(&state); if (!context) { ec.code = IDBDatabaseException::UnknownError; ec.message = ASCIILiteral("Unable to store record in object store because it does not have a valid script execution context"); return nullptr; } // The IDB spec for several IDBObjectStore methods states that transaction related exceptions should fire before // the exception for an object store being deleted. // However, a handful of W3C IDB tests expect the deleted exception even though the transaction inactive exception also applies. // Additionally, Chrome and Edge agree with the test, as does Legacy IDB in WebKit. // Until this is sorted out, we'll agree with the test and the majority share browsers. if (m_deleted) { ec.code = IDBDatabaseException::InvalidStateError; ec.message = ASCIILiteral("Failed to store record in an IDBObjectStore: The object store has been deleted."); return nullptr; } if (!m_transaction->isActive()) { ec.code = IDBDatabaseException::TransactionInactiveError; ec.message = ASCIILiteral("Failed to store record in an IDBObjectStore: The transaction is inactive or finished."); return nullptr; } if (m_transaction->isReadOnly()) { ec.code = IDBDatabaseException::ReadOnlyError; ec.message = ASCIILiteral("Failed to store record in an IDBObjectStore: The transaction is read-only."); return nullptr; } RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::create(&state, value, nullptr, nullptr); if (state.hadException()) { // Clear the DOM exception from the serializer so we can give a more targeted exception. state.clearException(); ec.code = IDBDatabaseException::DataCloneError; ec.message = ASCIILiteral("Failed to store record in an IDBObjectStore: An object could not be cloned."); return nullptr; } bool privateBrowsingEnabled = false; if (context->isDocument()) { if (auto* page = static_cast<Document*>(context)->page()) privateBrowsingEnabled = page->sessionID().isEphemeral(); } if (serializedValue->hasBlobURLs() && privateBrowsingEnabled) { // https://bugs.webkit.org/show_bug.cgi?id=156347 - Support Blobs in private browsing. ec.code = IDBDatabaseException::DataCloneError; ec.message = ASCIILiteral("Failed to store record in an IDBObjectStore: BlobURLs are not yet supported."); return nullptr; } if (key && !key->isValid()) { ec.code = IDBDatabaseException::DataError; ec.message = ASCIILiteral("Failed to store record in an IDBObjectStore: The parameter is not a valid key."); return nullptr; } bool usesInlineKeys = !m_info.keyPath().isNull(); bool usesKeyGenerator = autoIncrement(); if (usesInlineKeys && inlineKeyCheck == InlineKeyCheck::Perform) { if (key) { ec.code = IDBDatabaseException::DataError; ec.message = ASCIILiteral("Failed to store record in an IDBObjectStore: The object store uses in-line keys and the key parameter was provided."); return nullptr; } RefPtr<IDBKey> keyPathKey = maybeCreateIDBKeyFromScriptValueAndKeyPath(state, value, m_info.keyPath()); if (keyPathKey && !keyPathKey->isValid()) { ec.code = IDBDatabaseException::DataError; ec.message = ASCIILiteral("Failed to store record in an IDBObjectStore: Evaluating the object store's key path yielded a value that is not a valid key."); return nullptr; } if (!keyPathKey) { if (usesKeyGenerator) { if (!canInjectIDBKeyIntoScriptValue(state, value, m_info.keyPath())) { ec.code = IDBDatabaseException::DataError; return nullptr; } } else { ec.code = IDBDatabaseException::DataError; ec.message = ASCIILiteral("Failed to store record in an IDBObjectStore: Evaluating the object store's key path did not yield a value."); return nullptr; } } if (keyPathKey) { ASSERT(!key); key = keyPathKey; } } else if (!usesKeyGenerator && !key) { ec.code = IDBDatabaseException::DataError; ec.message = ASCIILiteral("Failed to store record in an IDBObjectStore: The object store uses out-of-line keys and has no key generator and the key parameter was not provided."); return nullptr; } return m_transaction->requestPutOrAdd(*context, *this, key.get(), *serializedValue, overwriteMode); }
PassRefPtr<IDBRequest> IDBObjectStore::put(WebIDBDatabase::PutMode putMode, PassRefPtr<IDBAny> source, ScriptState* state, ScriptValue& value, PassRefPtr<IDBKey> prpKey, ExceptionState& exceptionState) { RefPtr<IDBKey> key = prpKey; if (isDeleted()) { exceptionState.throwDOMException(InvalidStateError, IDBDatabase::objectStoreDeletedErrorMessage); return 0; } if (m_transaction->isFinished()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionFinishedErrorMessage); return 0; } if (!m_transaction->isActive()) { exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::transactionInactiveErrorMessage); return 0; } if (m_transaction->isReadOnly()) { exceptionState.throwDOMException(ReadOnlyError, IDBDatabase::transactionReadOnlyErrorMessage); return 0; } RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::create(value, exceptionState, state); if (exceptionState.hadException()) return 0; if (serializedValue->containsBlobs()) { // FIXME: Add Blob/File/FileList support exceptionState.throwDOMException(DataCloneError, "The object store currently does not support blob values."); return 0; } const IDBKeyPath& keyPath = m_metadata.keyPath; const bool usesInLineKeys = !keyPath.isNull(); const bool hasKeyGenerator = autoIncrement(); ExecutionContext* context = state->executionContext(); DOMRequestState requestState(context); if (putMode != WebIDBDatabase::CursorUpdate && usesInLineKeys && key) { exceptionState.throwDOMException(DataError, "The object store uses in-line keys and the key parameter was provided."); return 0; } if (!usesInLineKeys && !hasKeyGenerator && !key) { exceptionState.throwDOMException(DataError, "The object store uses out-of-line keys and has no key generator and the key parameter was not provided."); return 0; } if (usesInLineKeys) { RefPtr<IDBKey> keyPathKey = createIDBKeyFromScriptValueAndKeyPath(&requestState, value, keyPath); if (keyPathKey && !keyPathKey->isValid()) { exceptionState.throwDOMException(DataError, "Evaluating the object store's key path yielded a value that is not a valid key."); return 0; } if (!hasKeyGenerator && !keyPathKey) { exceptionState.throwDOMException(DataError, "Evaluating the object store's key path did not yield a value."); return 0; } if (hasKeyGenerator && !keyPathKey) { if (!canInjectIDBKeyIntoScriptValue(&requestState, value, keyPath)) { exceptionState.throwDOMException(DataError, "A generated key could not be inserted into the value."); return 0; } } if (keyPathKey) key = keyPathKey; } if (key && !key->isValid()) { exceptionState.throwDOMException(DataError, IDBDatabase::notValidKeyErrorMessage); return 0; } Vector<int64_t> indexIds; Vector<IndexKeys> indexKeys; for (IDBObjectStoreMetadata::IndexMap::const_iterator it = m_metadata.indexes.begin(); it != m_metadata.indexes.end(); ++it) { IndexKeys keys; generateIndexKeysForValue(&requestState, it->value, value, &keys); indexIds.append(it->key); indexKeys.append(keys); } RefPtr<IDBRequest> request = IDBRequest::create(context, source, m_transaction.get()); Vector<char> wireBytes; serializedValue->toWireBytes(wireBytes); RefPtr<SharedBuffer> valueBuffer = SharedBuffer::adoptVector(wireBytes); backendDB()->put(m_transaction->id(), id(), blink::WebData(valueBuffer), key.release(), static_cast<WebIDBDatabase::PutMode>(putMode), WebIDBCallbacksImpl::create(request).leakPtr(), indexIds, indexKeys); return request.release(); }
PassRefPtr<IDBRequest> IDBObjectStore::put(IDBDatabaseBackend::PutMode putMode, PassRefPtr<IDBAny> source, JSC::ExecState* state, Deprecated::ScriptValue& value, PassRefPtr<IDBKey> prpKey, ExceptionCode& ec) { RefPtr<IDBKey> key = prpKey; if (m_deleted) { ec = IDBDatabaseException::InvalidStateError; return nullptr; } if (!m_transaction->isActive()) { ec = IDBDatabaseException::TransactionInactiveError; return nullptr; } if (m_transaction->isReadOnly()) { ec = IDBDatabaseException::ReadOnlyError; return nullptr; } RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::create(state, value.jsValue(), nullptr, nullptr); if (state->hadException()) return nullptr; if (serializedValue->hasBlobURLs()) { // FIXME: Add Blob/File/FileList support ec = IDBDatabaseException::DataCloneError; return nullptr; } const IDBKeyPath& keyPath = m_metadata.keyPath; const bool usesInLineKeys = !keyPath.isNull(); const bool hasKeyGenerator = autoIncrement(); ScriptExecutionContext* context = scriptExecutionContextFromExecState(state); DOMRequestState requestState(context); if (putMode != IDBDatabaseBackend::CursorUpdate && usesInLineKeys && key) { ec = IDBDatabaseException::DataError; return nullptr; } if (!usesInLineKeys && !hasKeyGenerator && !key) { ec = IDBDatabaseException::DataError; return nullptr; } if (usesInLineKeys) { RefPtr<IDBKey> keyPathKey = createIDBKeyFromScriptValueAndKeyPath(requestState.exec(), value, keyPath); if (keyPathKey && !keyPathKey->isValid()) { ec = IDBDatabaseException::DataError; return nullptr; } if (!hasKeyGenerator && !keyPathKey) { ec = IDBDatabaseException::DataError; return nullptr; } if (hasKeyGenerator && !keyPathKey) { if (!canInjectIDBKeyIntoScriptValue(&requestState, value, keyPath)) { ec = IDBDatabaseException::DataError; return nullptr; } } if (keyPathKey) key = keyPathKey; } if (key && !key->isValid()) { ec = IDBDatabaseException::DataError; return nullptr; } Vector<int64_t> indexIds; Vector<IndexKeys> indexKeys; for (auto& index : m_metadata.indexes) { Vector<IDBKeyData> keyDatas; generateIndexKeysForValue(requestState.exec(), index.value, value, keyDatas); indexIds.append(index.key); // FIXME: Much of the Indexed DB code needs to use IDBKeyData directly to avoid wasteful conversions like this. Vector<RefPtr<IDBKey>> keys; for (auto& keyData : keyDatas) { RefPtr<IDBKey> key = keyData.maybeCreateIDBKey(); if (key) keys.append(key.release()); } indexKeys.append(keys); } RefPtr<IDBRequest> request = IDBRequest::create(context, source, m_transaction.get()); Vector<uint8_t> valueBytes = serializedValue->toWireBytes(); // This is a hack to account for disagreements about whether SerializedScriptValue should deal in Vector<uint8_t> or Vector<char>. // See https://lists.webkit.org/pipermail/webkit-dev/2013-February/023682.html Vector<char>* valueBytesSigned = reinterpret_cast<Vector<char>*>(&valueBytes); RefPtr<SharedBuffer> valueBuffer = SharedBuffer::adoptVector(*valueBytesSigned); backendDB()->put(m_transaction->id(), id(), valueBuffer, key.release(), static_cast<IDBDatabaseBackend::PutMode>(putMode), request, indexIds, indexKeys); return request.release(); }
PassRefPtr<IDBRequest> IDBObjectStore::put(IDBDatabaseBackend::PutMode putMode, PassRefPtr<IDBAny> source, JSC::ExecState* state, Deprecated::ScriptValue& value, PassRefPtr<IDBKey> prpKey, ExceptionCode& ec) { RefPtr<IDBKey> key = prpKey; if (m_deleted) { ec = IDBDatabaseException::InvalidStateError; return 0; } if (!m_transaction->isActive()) { ec = IDBDatabaseException::TransactionInactiveError; return 0; } if (m_transaction->isReadOnly()) { ec = IDBDatabaseException::ReadOnlyError; return 0; } // FIXME: Expose the JS engine exception state through ScriptState. bool didThrow = false; RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::serialize(value, state, nullptr, nullptr, didThrow); if (didThrow) { // Setting an explicit ExceptionCode here would defer handling the already thrown exception. return 0; } if (serializedValue->hasBlobURLs()) { // FIXME: Add Blob/File/FileList support ec = IDBDatabaseException::DataCloneError; return 0; } const IDBKeyPath& keyPath = m_metadata.keyPath; const bool usesInLineKeys = !keyPath.isNull(); const bool hasKeyGenerator = autoIncrement(); ScriptExecutionContext* context = scriptExecutionContextFromExecState(state); DOMRequestState requestState(context); if (putMode != IDBDatabaseBackend::CursorUpdate && usesInLineKeys && key) { ec = IDBDatabaseException::DataError; return 0; } if (!usesInLineKeys && !hasKeyGenerator && !key) { ec = IDBDatabaseException::DataError; return 0; } if (usesInLineKeys) { RefPtr<IDBKey> keyPathKey = createIDBKeyFromScriptValueAndKeyPath(&requestState, value, keyPath); if (keyPathKey && !keyPathKey->isValid()) { ec = IDBDatabaseException::DataError; return 0; } if (!hasKeyGenerator && !keyPathKey) { ec = IDBDatabaseException::DataError; return 0; } if (hasKeyGenerator && !keyPathKey) { if (!canInjectIDBKeyIntoScriptValue(&requestState, value, keyPath)) { ec = IDBDatabaseException::DataError; return 0; } } if (keyPathKey) key = keyPathKey; } if (key && !key->isValid()) { ec = IDBDatabaseException::DataError; return 0; } Vector<int64_t> indexIds; Vector<IndexKeys> indexKeys; for (IDBObjectStoreMetadata::IndexMap::const_iterator it = m_metadata.indexes.begin(); it != m_metadata.indexes.end(); ++it) { IndexKeys keys; generateIndexKeysForValue(&requestState, it->value, value, &keys); indexIds.append(it->key); indexKeys.append(keys); } RefPtr<IDBRequest> request = IDBRequest::create(context, source, m_transaction.get()); Vector<uint8_t> valueBytes = serializedValue->toWireBytes(); // This is a hack to account for disagreements about whether SerializedScriptValue should deal in Vector<uint8_t> or Vector<char>. // See https://lists.webkit.org/pipermail/webkit-dev/2013-February/023682.html Vector<char>* valueBytesSigned = reinterpret_cast<Vector<char>*>(&valueBytes); RefPtr<SharedBuffer> valueBuffer = SharedBuffer::adoptVector(*valueBytesSigned); backendDB()->put(m_transaction->id(), id(), valueBuffer, key.release(), static_cast<IDBDatabaseBackend::PutMode>(putMode), request, indexIds, indexKeys); return request.release(); }
RefPtr<IDBRequest> IDBObjectStore::putOrAdd(JSC::ExecState& state, JSC::JSValue value, RefPtr<IDBKey> key, IndexedDB::ObjectStoreOverwriteMode overwriteMode, InlineKeyCheck inlineKeyCheck, ExceptionCodeWithMessage& ec) { LOG(IndexedDB, "IDBObjectStore::putOrAdd"); if (!m_transaction->isActive()) { ec.code = IDBDatabaseException::TransactionInactiveError; ec.message = ASCIILiteral("Failed to store record in an IDBObjectStore: The transaction is inactive or finished."); return nullptr; } if (m_transaction->isReadOnly()) { ec.code = IDBDatabaseException::ReadOnlyError; ec.message = ASCIILiteral("Failed to store record in an IDBObjectStore: The transaction is read-only."); return nullptr; } if (m_deleted) { ec.code = IDBDatabaseException::InvalidStateError; return nullptr; } RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::create(&state, value, nullptr, nullptr); if (state.hadException()) { ec.code = IDBDatabaseException::DataCloneError; ec.message = ASCIILiteral("Failed to store record in an IDBObjectStore: An object could not be cloned."); return nullptr; } if (serializedValue->hasBlobURLs()) { // FIXME: Add Blob/File/FileList support ec.code = IDBDatabaseException::DataCloneError; ec.message = ASCIILiteral("Failed to store record in an IDBObjectStore: BlobURLs are not yet supported."); return nullptr; } if (key && key->type() == KeyType::Invalid) { ec.code = IDBDatabaseException::DataError; return nullptr; } bool usesInlineKeys = !m_info.keyPath().isNull(); bool usesKeyGenerator = autoIncrement(); if (usesInlineKeys && inlineKeyCheck == InlineKeyCheck::Perform) { if (key) { ec.code = IDBDatabaseException::DataError; return nullptr; } RefPtr<IDBKey> keyPathKey = maybeCreateIDBKeyFromScriptValueAndKeyPath(state, value, m_info.keyPath()); if (keyPathKey && !keyPathKey->isValid()) { ec.code = IDBDatabaseException::DataError; return nullptr; } if (!keyPathKey) { if (usesKeyGenerator) { if (!canInjectIDBKeyIntoScriptValue(state, value, m_info.keyPath())) { ec.code = IDBDatabaseException::DataError; return nullptr; } } else { ec.code = IDBDatabaseException::DataError; return nullptr; } } if (keyPathKey) { ASSERT(!key); key = keyPathKey; } } else if (!usesKeyGenerator && !key) { ec.code = IDBDatabaseException::DataError; return nullptr; } auto context = scriptExecutionContextFromExecState(&state); if (!context) { ec.code = IDBDatabaseException::UnknownError; return nullptr; } Ref<IDBRequest> request = m_transaction->requestPutOrAdd(*context, *this, key.get(), *serializedValue, overwriteMode); return adoptRef(request.leakRef()); }
void CSSFontSelector::addFontFaceRule(const CSSFontFaceRule* fontFaceRule) { // Obtain the font-family property and the src property. Both must be defined. const CSSMutableStyleDeclaration* style = fontFaceRule->style(); RefPtr<CSSValue> fontFamily = style->getPropertyCSSValue(CSSPropertyFontFamily); RefPtr<CSSValue> src = style->getPropertyCSSValue(CSSPropertySrc); RefPtr<CSSValue> unicodeRange = style->getPropertyCSSValue(CSSPropertyUnicodeRange); if (!fontFamily || !src || !fontFamily->isValueList() || !src->isValueList() || unicodeRange && !unicodeRange->isValueList()) return; CSSValueList* familyList = static_cast<CSSValueList*>(fontFamily.get()); if (!familyList->length()) return; CSSValueList* srcList = static_cast<CSSValueList*>(src.get()); if (!srcList->length()) return; CSSValueList* rangeList = static_cast<CSSValueList*>(unicodeRange.get()); unsigned traitsMask = 0; if (RefPtr<CSSValue> fontStyle = style->getPropertyCSSValue(CSSPropertyFontStyle)) { if (fontStyle->isPrimitiveValue()) { RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); list->append(fontStyle); fontStyle = list; } else if (!fontStyle->isValueList()) return; CSSValueList* styleList = static_cast<CSSValueList*>(fontStyle.get()); unsigned numStyles = styleList->length(); if (!numStyles) return; for (unsigned i = 0; i < numStyles; ++i) { switch (static_cast<CSSPrimitiveValue*>(styleList->itemWithoutBoundsCheck(i))->getIdent()) { case CSSValueAll: traitsMask |= FontStyleMask; break; case CSSValueNormal: traitsMask |= FontStyleNormalMask; break; case CSSValueItalic: case CSSValueOblique: traitsMask |= FontStyleItalicMask; break; default: break; } } } else traitsMask |= FontStyleMask; if (RefPtr<CSSValue> fontWeight = style->getPropertyCSSValue(CSSPropertyFontWeight)) { if (fontWeight->isPrimitiveValue()) { RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); list->append(fontWeight); fontWeight = list; } else if (!fontWeight->isValueList()) return; CSSValueList* weightList = static_cast<CSSValueList*>(fontWeight.get()); unsigned numWeights = weightList->length(); if (!numWeights) return; for (unsigned i = 0; i < numWeights; ++i) { switch (static_cast<CSSPrimitiveValue*>(weightList->itemWithoutBoundsCheck(i))->getIdent()) { case CSSValueAll: traitsMask |= FontWeightMask; break; case CSSValueBolder: case CSSValueBold: case CSSValue700: traitsMask |= FontWeight700Mask; break; case CSSValueNormal: case CSSValue400: traitsMask |= FontWeight400Mask; break; case CSSValue900: traitsMask |= FontWeight900Mask; break; case CSSValue800: traitsMask |= FontWeight800Mask; break; case CSSValue600: traitsMask |= FontWeight600Mask; break; case CSSValue500: traitsMask |= FontWeight500Mask; break; case CSSValue300: traitsMask |= FontWeight300Mask; break; case CSSValueLighter: case CSSValue200: traitsMask |= FontWeight200Mask; break; case CSSValue100: traitsMask |= FontWeight100Mask; break; default: break; } } } else traitsMask |= FontWeightMask; if (RefPtr<CSSValue> fontVariant = style->getPropertyCSSValue(CSSPropertyFontVariant)) { if (fontVariant->isPrimitiveValue()) { RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); list->append(fontVariant); fontVariant = list; } else if (!fontVariant->isValueList()) return; CSSValueList* variantList = static_cast<CSSValueList*>(fontVariant.get()); unsigned numVariants = variantList->length(); if (!numVariants) return; for (unsigned i = 0; i < numVariants; ++i) { switch (static_cast<CSSPrimitiveValue*>(variantList->itemWithoutBoundsCheck(i))->getIdent()) { case CSSValueAll: traitsMask |= FontVariantMask; break; case CSSValueNormal: traitsMask |= FontVariantNormalMask; break; case CSSValueSmallCaps: traitsMask |= FontVariantSmallCapsMask; break; default: break; } } } else traitsMask |= FontVariantNormalMask; // Each item in the src property's list is a single CSSFontFaceSource. Put them all into a CSSFontFace. RefPtr<CSSFontFace> fontFace; int srcLength = srcList->length(); bool foundLocal = false; #if ENABLE(SVG_FONTS) bool foundSVGFont = false; #endif for (int i = 0; i < srcLength; i++) { // An item in the list either specifies a string (local font name) or a URL (remote font to download). CSSFontFaceSrcValue* item = static_cast<CSSFontFaceSrcValue*>(srcList->itemWithoutBoundsCheck(i)); CSSFontFaceSource* source = 0; #if ENABLE(SVG_FONTS) foundSVGFont = item->isSVGFontFaceSrc() || item->svgFontFaceElement(); #endif if (!item->isLocal()) { if (item->isSupportedFormat() && m_document) { CachedFont* cachedFont = m_document->docLoader()->requestFont(item->resource()); if (cachedFont) { #if ENABLE(SVG_FONTS) if (foundSVGFont) cachedFont->setSVGFont(true); #endif source = new CSSFontFaceSource(item->resource(), cachedFont); } } } else { source = new CSSFontFaceSource(item->resource()); foundLocal = true; } if (!fontFace) fontFace = CSSFontFace::create(static_cast<FontTraitsMask>(traitsMask)); if (source) { #if ENABLE(SVG_FONTS) source->setSVGFontFaceElement(item->svgFontFaceElement()); #endif fontFace->addSource(source); } } ASSERT(fontFace); if (fontFace && !fontFace->isValid()) return; if (rangeList) { unsigned numRanges = rangeList->length(); for (unsigned i = 0; i < numRanges; i++) { CSSUnicodeRangeValue* range = static_cast<CSSUnicodeRangeValue*>(rangeList->itemWithoutBoundsCheck(i)); fontFace->addRange(range->from(), range->to()); } } // Hash under every single family name. int familyLength = familyList->length(); for (int i = 0; i < familyLength; i++) { CSSPrimitiveValue* item = static_cast<CSSPrimitiveValue*>(familyList->itemWithoutBoundsCheck(i)); String familyName; if (item->primitiveType() == CSSPrimitiveValue::CSS_STRING) familyName = static_cast<FontFamilyValue*>(item)->familyName(); else if (item->primitiveType() == CSSPrimitiveValue::CSS_IDENT) { // We need to use the raw text for all the generic family types, since @font-face is a way of actually // defining what font to use for those types. String familyName; switch (item->getIdent()) { case CSSValueSerif: familyName = "-webkit-serif"; break; case CSSValueSansSerif: familyName = "-webkit-sans-serif"; break; case CSSValueCursive: familyName = "-webkit-cursive"; break; case CSSValueFantasy: familyName = "-webkit-fantasy"; break; case CSSValueMonospace: familyName = "-webkit-monospace"; break; default: break; } } if (familyName.isEmpty()) continue; #if ENABLE(SVG_FONTS) // SVG allows several <font> elements with the same font-family, differing only // in ie. font-variant. Be sure to pick up the right one - in getFontData below. if (foundSVGFont && (traitsMask & FontVariantSmallCapsMask)) familyName += "-webkit-svg-small-caps"; #endif Vector<RefPtr<CSSFontFace> >* familyFontFaces = m_fontFaces.get(familyName); if (!familyFontFaces) { familyFontFaces = new Vector<RefPtr<CSSFontFace> >; m_fontFaces.set(familyName, familyFontFaces); ASSERT(!m_locallyInstalledFontFaces.contains(familyName)); Vector<RefPtr<CSSFontFace> >* familyLocallyInstalledFaces; Vector<unsigned> locallyInstalledFontsTraitsMasks; FontCache::getTraitsInFamily(familyName, locallyInstalledFontsTraitsMasks); unsigned numLocallyInstalledFaces = locallyInstalledFontsTraitsMasks.size(); if (numLocallyInstalledFaces) { familyLocallyInstalledFaces = new Vector<RefPtr<CSSFontFace> >; m_locallyInstalledFontFaces.set(familyName, familyLocallyInstalledFaces); for (unsigned i = 0; i < numLocallyInstalledFaces; ++i) { RefPtr<CSSFontFace> locallyInstalledFontFace = CSSFontFace::create(static_cast<FontTraitsMask>(locallyInstalledFontsTraitsMasks[i])); locallyInstalledFontFace->addSource(new CSSFontFaceSource(familyName)); ASSERT(locallyInstalledFontFace->isValid()); familyLocallyInstalledFaces->append(locallyInstalledFontFace); } } } familyFontFaces->append(fontFace); } }