Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* |
michael@0 | 2 | * Copyright 2011 The Android Open Source Project |
michael@0 | 3 | * |
michael@0 | 4 | * Use of this source code is governed by a BSD-style license that can be |
michael@0 | 5 | * found in the LICENSE file. |
michael@0 | 6 | */ |
michael@0 | 7 | |
michael@0 | 8 | #include "SkFontConfigParser_android.h" |
michael@0 | 9 | #include "SkTDArray.h" |
michael@0 | 10 | #include "SkTypeface.h" |
michael@0 | 11 | |
michael@0 | 12 | #include <expat.h> |
michael@0 | 13 | #include <stdio.h> |
michael@0 | 14 | #include <sys/system_properties.h> |
michael@0 | 15 | |
michael@0 | 16 | #define SYSTEM_FONTS_FILE "/system/etc/system_fonts.xml" |
michael@0 | 17 | #define FALLBACK_FONTS_FILE "/system/etc/fallback_fonts.xml" |
michael@0 | 18 | #define VENDOR_FONTS_FILE "/vendor/etc/fallback_fonts.xml" |
michael@0 | 19 | |
michael@0 | 20 | // These defines are used to determine the kind of tag that we're currently |
michael@0 | 21 | // populating with data. We only care about the sibling tags nameset and fileset |
michael@0 | 22 | // for now. |
michael@0 | 23 | #define NO_TAG 0 |
michael@0 | 24 | #define NAMESET_TAG 1 |
michael@0 | 25 | #define FILESET_TAG 2 |
michael@0 | 26 | |
michael@0 | 27 | /** |
michael@0 | 28 | * The FamilyData structure is passed around by the parser so that each handler |
michael@0 | 29 | * can read these variables that are relevant to the current parsing. |
michael@0 | 30 | */ |
michael@0 | 31 | struct FamilyData { |
michael@0 | 32 | FamilyData(XML_Parser *parserRef, SkTDArray<FontFamily*> &familiesRef) : |
michael@0 | 33 | parser(parserRef), |
michael@0 | 34 | families(familiesRef), |
michael@0 | 35 | currentFamily(NULL), |
michael@0 | 36 | currentFontInfo(NULL), |
michael@0 | 37 | currentTag(NO_TAG) {}; |
michael@0 | 38 | |
michael@0 | 39 | XML_Parser *parser; // The expat parser doing the work |
michael@0 | 40 | SkTDArray<FontFamily*> &families; // The array that each family is put into as it is parsed |
michael@0 | 41 | FontFamily *currentFamily; // The current family being created |
michael@0 | 42 | FontFileInfo *currentFontInfo; // The current fontInfo being created |
michael@0 | 43 | int currentTag; // A flag to indicate whether we're in nameset/fileset tags |
michael@0 | 44 | }; |
michael@0 | 45 | |
michael@0 | 46 | /** |
michael@0 | 47 | * Handler for arbitrary text. This is used to parse the text inside each name |
michael@0 | 48 | * or file tag. The resulting strings are put into the fNames or FontFileInfo arrays. |
michael@0 | 49 | */ |
michael@0 | 50 | static void textHandler(void *data, const char *s, int len) { |
michael@0 | 51 | FamilyData *familyData = (FamilyData*) data; |
michael@0 | 52 | // Make sure we're in the right state to store this name information |
michael@0 | 53 | if (familyData->currentFamily && |
michael@0 | 54 | (familyData->currentTag == NAMESET_TAG || familyData->currentTag == FILESET_TAG)) { |
michael@0 | 55 | // Malloc new buffer to store the string |
michael@0 | 56 | char *buff; |
michael@0 | 57 | buff = (char*) malloc((len + 1) * sizeof(char)); |
michael@0 | 58 | strncpy(buff, s, len); |
michael@0 | 59 | buff[len] = '\0'; |
michael@0 | 60 | switch (familyData->currentTag) { |
michael@0 | 61 | case NAMESET_TAG: |
michael@0 | 62 | *(familyData->currentFamily->fNames.append()) = buff; |
michael@0 | 63 | break; |
michael@0 | 64 | case FILESET_TAG: |
michael@0 | 65 | if (familyData->currentFontInfo) { |
michael@0 | 66 | familyData->currentFontInfo->fFileName = buff; |
michael@0 | 67 | } |
michael@0 | 68 | break; |
michael@0 | 69 | default: |
michael@0 | 70 | // Noop - don't care about any text that's not in the Fonts or Names list |
michael@0 | 71 | break; |
michael@0 | 72 | } |
michael@0 | 73 | } |
michael@0 | 74 | } |
michael@0 | 75 | |
michael@0 | 76 | /** |
michael@0 | 77 | * Handler for font files. This processes the attributes for language and |
michael@0 | 78 | * variants then lets textHandler handle the actual file name |
michael@0 | 79 | */ |
michael@0 | 80 | static void fontFileElementHandler(FamilyData *familyData, const char **attributes) { |
michael@0 | 81 | FontFileInfo* newFileInfo = new FontFileInfo(); |
michael@0 | 82 | if (attributes) { |
michael@0 | 83 | int currentAttributeIndex = 0; |
michael@0 | 84 | while (attributes[currentAttributeIndex]) { |
michael@0 | 85 | const char* attributeName = attributes[currentAttributeIndex]; |
michael@0 | 86 | const char* attributeValue = attributes[currentAttributeIndex+1]; |
michael@0 | 87 | int nameLength = strlen(attributeName); |
michael@0 | 88 | int valueLength = strlen(attributeValue); |
michael@0 | 89 | if (strncmp(attributeName, "variant", nameLength) == 0) { |
michael@0 | 90 | if (strncmp(attributeValue, "elegant", valueLength) == 0) { |
michael@0 | 91 | newFileInfo->fPaintOptions.setFontVariant(SkPaintOptionsAndroid::kElegant_Variant); |
michael@0 | 92 | } else if (strncmp(attributeValue, "compact", valueLength) == 0) { |
michael@0 | 93 | newFileInfo->fPaintOptions.setFontVariant(SkPaintOptionsAndroid::kCompact_Variant); |
michael@0 | 94 | } |
michael@0 | 95 | } else if (strncmp(attributeName, "lang", nameLength) == 0) { |
michael@0 | 96 | newFileInfo->fPaintOptions.setLanguage(attributeValue); |
michael@0 | 97 | } |
michael@0 | 98 | //each element is a pair of attributeName/attributeValue string pairs |
michael@0 | 99 | currentAttributeIndex += 2; |
michael@0 | 100 | } |
michael@0 | 101 | } |
michael@0 | 102 | *(familyData->currentFamily->fFontFiles.append()) = newFileInfo; |
michael@0 | 103 | familyData->currentFontInfo = newFileInfo; |
michael@0 | 104 | XML_SetCharacterDataHandler(*familyData->parser, textHandler); |
michael@0 | 105 | } |
michael@0 | 106 | |
michael@0 | 107 | /** |
michael@0 | 108 | * Handler for the start of a tag. The only tags we expect are family, nameset, |
michael@0 | 109 | * fileset, name, and file. |
michael@0 | 110 | */ |
michael@0 | 111 | static void startElementHandler(void *data, const char *tag, const char **atts) { |
michael@0 | 112 | FamilyData *familyData = (FamilyData*) data; |
michael@0 | 113 | int len = strlen(tag); |
michael@0 | 114 | if (strncmp(tag, "family", len)== 0) { |
michael@0 | 115 | familyData->currentFamily = new FontFamily(); |
michael@0 | 116 | familyData->currentFamily->order = -1; |
michael@0 | 117 | // The Family tag has an optional "order" attribute with an integer value >= 0 |
michael@0 | 118 | // If this attribute does not exist, the default value is -1 |
michael@0 | 119 | for (int i = 0; atts[i] != NULL; i += 2) { |
michael@0 | 120 | const char* valueString = atts[i+1]; |
michael@0 | 121 | int value; |
michael@0 | 122 | int len = sscanf(valueString, "%d", &value); |
michael@0 | 123 | if (len > 0) { |
michael@0 | 124 | familyData->currentFamily->order = value; |
michael@0 | 125 | } |
michael@0 | 126 | } |
michael@0 | 127 | } else if (len == 7 && strncmp(tag, "nameset", len) == 0) { |
michael@0 | 128 | familyData->currentTag = NAMESET_TAG; |
michael@0 | 129 | } else if (len == 7 && strncmp(tag, "fileset", len) == 0) { |
michael@0 | 130 | familyData->currentTag = FILESET_TAG; |
michael@0 | 131 | } else if (strncmp(tag, "name", len) == 0 && familyData->currentTag == NAMESET_TAG) { |
michael@0 | 132 | // If it's a Name, parse the text inside |
michael@0 | 133 | XML_SetCharacterDataHandler(*familyData->parser, textHandler); |
michael@0 | 134 | } else if (strncmp(tag, "file", len) == 0 && familyData->currentTag == FILESET_TAG) { |
michael@0 | 135 | // If it's a file, parse the attributes, then parse the text inside |
michael@0 | 136 | fontFileElementHandler(familyData, atts); |
michael@0 | 137 | } |
michael@0 | 138 | } |
michael@0 | 139 | |
michael@0 | 140 | /** |
michael@0 | 141 | * Handler for the end of tags. We only care about family, nameset, fileset, |
michael@0 | 142 | * name, and file. |
michael@0 | 143 | */ |
michael@0 | 144 | static void endElementHandler(void *data, const char *tag) { |
michael@0 | 145 | FamilyData *familyData = (FamilyData*) data; |
michael@0 | 146 | int len = strlen(tag); |
michael@0 | 147 | if (strncmp(tag, "family", len)== 0) { |
michael@0 | 148 | // Done parsing a Family - store the created currentFamily in the families array |
michael@0 | 149 | *familyData->families.append() = familyData->currentFamily; |
michael@0 | 150 | familyData->currentFamily = NULL; |
michael@0 | 151 | } else if (len == 7 && strncmp(tag, "nameset", len) == 0) { |
michael@0 | 152 | familyData->currentTag = NO_TAG; |
michael@0 | 153 | } else if (len == 7 && strncmp(tag, "fileset", len) == 0) { |
michael@0 | 154 | familyData->currentTag = NO_TAG; |
michael@0 | 155 | } else if ((strncmp(tag, "name", len) == 0 && familyData->currentTag == NAMESET_TAG) || |
michael@0 | 156 | (strncmp(tag, "file", len) == 0 && familyData->currentTag == FILESET_TAG)) { |
michael@0 | 157 | // Disable the arbitrary text handler installed to load Name data |
michael@0 | 158 | XML_SetCharacterDataHandler(*familyData->parser, NULL); |
michael@0 | 159 | } |
michael@0 | 160 | } |
michael@0 | 161 | |
michael@0 | 162 | /** |
michael@0 | 163 | * This function parses the given filename and stores the results in the given |
michael@0 | 164 | * families array. |
michael@0 | 165 | */ |
michael@0 | 166 | static void parseConfigFile(const char *filename, SkTDArray<FontFamily*> &families) { |
michael@0 | 167 | |
michael@0 | 168 | FILE* file = NULL; |
michael@0 | 169 | |
michael@0 | 170 | #if !defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) |
michael@0 | 171 | // if we are using a version of Android prior to Android 4.2 (JellyBean MR1 |
michael@0 | 172 | // at API Level 17) then we need to look for files with a different suffix. |
michael@0 | 173 | char sdkVersion[PROP_VALUE_MAX]; |
michael@0 | 174 | __system_property_get("ro.build.version.sdk", sdkVersion); |
michael@0 | 175 | const int sdkVersionInt = atoi(sdkVersion); |
michael@0 | 176 | |
michael@0 | 177 | if (0 != *sdkVersion && sdkVersionInt < 17) { |
michael@0 | 178 | SkString basename; |
michael@0 | 179 | SkString updatedFilename; |
michael@0 | 180 | SkString locale = SkFontConfigParser::GetLocale(); |
michael@0 | 181 | |
michael@0 | 182 | basename.set(filename); |
michael@0 | 183 | // Remove the .xml suffix. We'll add it back in a moment. |
michael@0 | 184 | if (basename.endsWith(".xml")) { |
michael@0 | 185 | basename.resize(basename.size()-4); |
michael@0 | 186 | } |
michael@0 | 187 | // Try first with language and region |
michael@0 | 188 | updatedFilename.printf("%s-%s.xml", basename.c_str(), locale.c_str()); |
michael@0 | 189 | file = fopen(updatedFilename.c_str(), "r"); |
michael@0 | 190 | if (!file) { |
michael@0 | 191 | // If not found, try next with just language |
michael@0 | 192 | updatedFilename.printf("%s-%.2s.xml", basename.c_str(), locale.c_str()); |
michael@0 | 193 | file = fopen(updatedFilename.c_str(), "r"); |
michael@0 | 194 | } |
michael@0 | 195 | } |
michael@0 | 196 | #endif |
michael@0 | 197 | |
michael@0 | 198 | if (NULL == file) { |
michael@0 | 199 | file = fopen(filename, "r"); |
michael@0 | 200 | } |
michael@0 | 201 | |
michael@0 | 202 | // Some of the files we attempt to parse (in particular, /vendor/etc/fallback_fonts.xml) |
michael@0 | 203 | // are optional - failure here is okay because one of these optional files may not exist. |
michael@0 | 204 | if (NULL == file) { |
michael@0 | 205 | return; |
michael@0 | 206 | } |
michael@0 | 207 | |
michael@0 | 208 | XML_Parser parser = XML_ParserCreate(NULL); |
michael@0 | 209 | FamilyData *familyData = new FamilyData(&parser, families); |
michael@0 | 210 | XML_SetUserData(parser, familyData); |
michael@0 | 211 | XML_SetElementHandler(parser, startElementHandler, endElementHandler); |
michael@0 | 212 | |
michael@0 | 213 | char buffer[512]; |
michael@0 | 214 | bool done = false; |
michael@0 | 215 | while (!done) { |
michael@0 | 216 | fgets(buffer, sizeof(buffer), file); |
michael@0 | 217 | int len = strlen(buffer); |
michael@0 | 218 | if (feof(file) != 0) { |
michael@0 | 219 | done = true; |
michael@0 | 220 | } |
michael@0 | 221 | XML_Parse(parser, buffer, len, done); |
michael@0 | 222 | } |
michael@0 | 223 | XML_ParserFree(parser); |
michael@0 | 224 | fclose(file); |
michael@0 | 225 | } |
michael@0 | 226 | |
michael@0 | 227 | static void getSystemFontFamilies(SkTDArray<FontFamily*> &fontFamilies) { |
michael@0 | 228 | parseConfigFile(SYSTEM_FONTS_FILE, fontFamilies); |
michael@0 | 229 | } |
michael@0 | 230 | |
michael@0 | 231 | static void getFallbackFontFamilies(SkTDArray<FontFamily*> &fallbackFonts) { |
michael@0 | 232 | SkTDArray<FontFamily*> vendorFonts; |
michael@0 | 233 | parseConfigFile(FALLBACK_FONTS_FILE, fallbackFonts); |
michael@0 | 234 | parseConfigFile(VENDOR_FONTS_FILE, vendorFonts); |
michael@0 | 235 | |
michael@0 | 236 | // This loop inserts the vendor fallback fonts in the correct order in the |
michael@0 | 237 | // overall fallbacks list. |
michael@0 | 238 | int currentOrder = -1; |
michael@0 | 239 | for (int i = 0; i < vendorFonts.count(); ++i) { |
michael@0 | 240 | FontFamily* family = vendorFonts[i]; |
michael@0 | 241 | int order = family->order; |
michael@0 | 242 | if (order < 0) { |
michael@0 | 243 | if (currentOrder < 0) { |
michael@0 | 244 | // Default case - just add it to the end of the fallback list |
michael@0 | 245 | *fallbackFonts.append() = family; |
michael@0 | 246 | } else { |
michael@0 | 247 | // no order specified on this font, but we're incrementing the order |
michael@0 | 248 | // based on an earlier order insertion request |
michael@0 | 249 | *fallbackFonts.insert(currentOrder++) = family; |
michael@0 | 250 | } |
michael@0 | 251 | } else { |
michael@0 | 252 | // Add the font into the fallback list in the specified order. Set |
michael@0 | 253 | // currentOrder for correct placement of other fonts in the vendor list. |
michael@0 | 254 | *fallbackFonts.insert(order) = family; |
michael@0 | 255 | currentOrder = order + 1; |
michael@0 | 256 | } |
michael@0 | 257 | } |
michael@0 | 258 | } |
michael@0 | 259 | |
michael@0 | 260 | /** |
michael@0 | 261 | * Loads data on font families from various expected configuration files. The |
michael@0 | 262 | * resulting data is returned in the given fontFamilies array. |
michael@0 | 263 | */ |
michael@0 | 264 | void SkFontConfigParser::GetFontFamilies(SkTDArray<FontFamily*> &fontFamilies) { |
michael@0 | 265 | |
michael@0 | 266 | getSystemFontFamilies(fontFamilies); |
michael@0 | 267 | |
michael@0 | 268 | // Append all the fallback fonts to system fonts |
michael@0 | 269 | SkTDArray<FontFamily*> fallbackFonts; |
michael@0 | 270 | getFallbackFontFamilies(fallbackFonts); |
michael@0 | 271 | for (int i = 0; i < fallbackFonts.count(); ++i) { |
michael@0 | 272 | fallbackFonts[i]->fIsFallbackFont = true; |
michael@0 | 273 | *fontFamilies.append() = fallbackFonts[i]; |
michael@0 | 274 | } |
michael@0 | 275 | } |
michael@0 | 276 | |
michael@0 | 277 | void SkFontConfigParser::GetTestFontFamilies(SkTDArray<FontFamily*> &fontFamilies, |
michael@0 | 278 | const char* testMainConfigFile, |
michael@0 | 279 | const char* testFallbackConfigFile) { |
michael@0 | 280 | parseConfigFile(testMainConfigFile, fontFamilies); |
michael@0 | 281 | |
michael@0 | 282 | SkTDArray<FontFamily*> fallbackFonts; |
michael@0 | 283 | parseConfigFile(testFallbackConfigFile, fallbackFonts); |
michael@0 | 284 | |
michael@0 | 285 | // Append all fallback fonts to system fonts |
michael@0 | 286 | for (int i = 0; i < fallbackFonts.count(); ++i) { |
michael@0 | 287 | fallbackFonts[i]->fIsFallbackFont = true; |
michael@0 | 288 | *fontFamilies.append() = fallbackFonts[i]; |
michael@0 | 289 | } |
michael@0 | 290 | } |
michael@0 | 291 | |
michael@0 | 292 | /** |
michael@0 | 293 | * Read the persistent locale. |
michael@0 | 294 | */ |
michael@0 | 295 | SkString SkFontConfigParser::GetLocale() |
michael@0 | 296 | { |
michael@0 | 297 | char propLang[PROP_VALUE_MAX], propRegn[PROP_VALUE_MAX]; |
michael@0 | 298 | __system_property_get("persist.sys.language", propLang); |
michael@0 | 299 | __system_property_get("persist.sys.country", propRegn); |
michael@0 | 300 | |
michael@0 | 301 | if (*propLang == 0 && *propRegn == 0) { |
michael@0 | 302 | /* Set to ro properties, default is en_US */ |
michael@0 | 303 | __system_property_get("ro.product.locale.language", propLang); |
michael@0 | 304 | __system_property_get("ro.product.locale.region", propRegn); |
michael@0 | 305 | if (*propLang == 0 && *propRegn == 0) { |
michael@0 | 306 | strcpy(propLang, "en"); |
michael@0 | 307 | strcpy(propRegn, "US"); |
michael@0 | 308 | } |
michael@0 | 309 | } |
michael@0 | 310 | |
michael@0 | 311 | SkString locale(6); |
michael@0 | 312 | char* localeCStr = locale.writable_str(); |
michael@0 | 313 | |
michael@0 | 314 | strncpy(localeCStr, propLang, 2); |
michael@0 | 315 | localeCStr[2] = '-'; |
michael@0 | 316 | strncpy(&localeCStr[3], propRegn, 2); |
michael@0 | 317 | localeCStr[5] = '\0'; |
michael@0 | 318 | |
michael@0 | 319 | return locale; |
michael@0 | 320 | } |