Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 /* | |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | |
| 4 * (C) 2001 Dirk Mueller (mueller@kde.org) | |
| 5 * Copyright (C) 2003, 2010 Apple Inc. All rights reserved. | |
| 6 * Copyright (C) 2013 Intel Corporation. All rights reserved. | |
| 7 * | |
| 8 * This library is free software; you can redistribute it and/or | |
| 9 * modify it under the terms of the GNU Library General Public | |
| 10 * License as published by the Free Software Foundation; either | |
| 11 * version 2 of the License, or (at your option) any later version. | |
| 12 * | |
| 13 * This library is distributed in the hope that it will be useful, | |
| 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 16 * Library General Public License for more details. | |
| 17 * | |
| 18 * You should have received a copy of the GNU Library General Public License | |
| 19 * along with this library; see the file COPYING.LIB. If not, write to | |
| 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
| 21 * Boston, MA 02110-1301, USA. | |
| 22 */ | |
| 23 | |
| 24 #include "config.h" | |
| 25 #include "core/html/HTMLMetaElement.h" | |
| 26 | |
| 27 #include "HTMLNames.h" | |
| 28 #include "RuntimeEnabledFeatures.h" | |
| 29 #include "core/css/CSSStyleSheet.h" | |
| 30 #include "core/css/CSSValuePool.h" | |
| 31 #include "core/css/MediaList.h" | |
| 32 #include "core/css/StylePropertySet.h" | |
| 33 #include "core/css/StyleSheetContents.h" | |
| 34 #include "core/dom/Document.h" | |
| 35 #include "core/dom/DocumentStyleSheetCollection.h" | |
| 36 #include "wtf/text/TextPosition.h" | |
| 37 | |
| 38 namespace WebCore { | |
| 39 | |
| 40 using namespace HTMLNames; | |
| 41 using namespace std; | |
| 42 | |
| 43 inline HTMLMetaElement::HTMLMetaElement(const QualifiedName& tagName, Document* document) | |
| 44 : HTMLElement(tagName, document) | |
| 45 { | |
| 46 ASSERT(hasTagName(metaTag)); | |
| 47 ScriptWrappable::init(this); | |
| 48 } | |
| 49 | |
| 50 HTMLMetaElement::~HTMLMetaElement() | |
| 51 { | |
| 52 removeStyleSheet(); | |
| 53 } | |
| 54 | |
| 55 PassRefPtr<HTMLMetaElement> HTMLMetaElement::create(Document* document) | |
| 56 { | |
| 57 return adoptRef(new HTMLMetaElement(metaTag, document)); | |
| 58 } | |
| 59 | |
| 60 PassRefPtr<HTMLMetaElement> HTMLMetaElement::create(const QualifiedName& tagName , Document* document) | |
| 61 { | |
| 62 return adoptRef(new HTMLMetaElement(tagName, document)); | |
| 63 } | |
| 64 | |
| 65 void HTMLMetaElement::removedFrom(ContainerNode* insertionPoint) | |
| 66 { | |
| 67 HTMLElement::removedFrom(insertionPoint); | |
| 68 removeStyleSheet(); | |
| 69 } | |
| 70 | |
| 71 Node::InsertionNotificationRequest HTMLMetaElement::insertedInto(ContainerNode* insertionPoint) | |
| 72 { | |
| 73 HTMLElement::insertedInto(insertionPoint); | |
| 74 if (insertionPoint->inDocument()) | |
| 75 process(); | |
| 76 return InsertionDone; | |
| 77 } | |
| 78 | |
| 79 | |
| 80 static inline bool isValueSeparator(UChar c, bool* ok) | |
| 81 { | |
| 82 if (ok && c == ';') | |
| 83 *ok = false; | |
| 84 // Though isspace() considers \t and \v to be whitespace, Win IE doesn't. | |
| 85 return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '=' || c == ' ,' || c == '\0'; | |
| 86 } | |
| 87 | |
| 88 static inline bool isPropertySeparator(UChar c, bool* ok) | |
| 89 { | |
| 90 if (ok && c == ';') | |
| 91 *ok = false; | |
| 92 return c == ','; | |
| 93 } | |
| 94 | |
| 95 float HTMLMetaElement::parsePositiveNumber(const String& property, const String& value, float minValue, float maxValue) | |
| 96 { | |
| 97 size_t parsedLength; | |
| 98 float rawValue; | |
| 99 float fValue; | |
| 100 if (value.is8Bit()) | |
| 101 rawValue = charactersToFloat(value.characters8(), value.length(), parsed Length); | |
| 102 else | |
| 103 rawValue = charactersToFloat(value.characters16(), value.length(), parse dLength); | |
| 104 | |
| 105 if (!parsedLength || rawValue < 0) { | |
| 106 reportError(InvalidValueError, property, value); | |
| 107 return -1; | |
| 108 } | |
| 109 | |
| 110 if (parsedLength < value.length()) | |
| 111 reportError(TruncatedValueError, property, value); | |
| 112 | |
| 113 fValue = min(maxValue, max(rawValue, minValue)); | |
| 114 if (fValue != rawValue) | |
| 115 reportError(OutOfBoundsValueError, property, value); | |
| 116 | |
| 117 return fValue; | |
| 118 } | |
| 119 | |
| 120 void HTMLMetaElement::reportError(ErrorType error, const String& property, const String& value) | |
| 121 { | |
| 122 StringBuilder builder; | |
| 123 | |
| 124 switch (error) { | |
| 125 case NoError: | |
| 126 return; | |
| 127 | |
| 128 case InvalidPropertySeparatorError: | |
| 129 builder.appendLiteral("Note that ';' is not a property separator. The li st should be comma-separated."); | |
| 130 break; | |
| 131 | |
| 132 case InvalidPropertyError: | |
| 133 builder.appendLiteral("Property \""); | |
| 134 builder.append(property); | |
| 135 builder.appendLiteral("\" not recognized and ignored."); | |
| 136 break; | |
| 137 | |
| 138 case InvalidValueError: | |
| 139 case OutOfBoundsValueError: | |
| 140 case TruncatedValueError: | |
| 141 if (!value.isEmpty()) { | |
| 142 builder.appendLiteral("The value \""); | |
| 143 builder.append(value); | |
| 144 builder.append('\"'); | |
| 145 } else { | |
| 146 builder.appendLiteral("The empty value"); | |
| 147 } | |
| 148 | |
| 149 if (!property.isNull()) { | |
| 150 builder.appendLiteral(" for property \""); | |
| 151 builder.append(property); | |
| 152 builder.append('\"'); | |
| 153 } | |
| 154 | |
| 155 if (error == InvalidValueError) | |
| 156 builder.appendLiteral(" is invalid and the property has been ignored ."); | |
| 157 else if (error == OutOfBoundsValueError) | |
| 158 builder.appendLiteral(" is out of bounds and the value has been clam ped."); | |
| 159 else | |
| 160 builder.appendLiteral(" was truncated to its numeric prefix."); | |
| 161 break; | |
| 162 | |
| 163 default: | |
| 164 ASSERT_NOT_REACHED(); | |
| 165 } | |
| 166 | |
| 167 document()->addConsoleMessage(MetaContentMessageSource, WarningMessageLevel, builder.toString()); | |
| 168 } | |
| 169 | |
| 170 void HTMLMetaElement::parseContentAttribute(MutableStylePropertySet* properties, const String& content, PropertyCollector callback) | |
| 171 { | |
| 172 bool ok = true; | |
| 173 | |
| 174 // Tread lightly in this code -- it was specifically designed to mimic Win I E's parsing behavior. | |
| 175 int keyBegin, keyEnd; | |
| 176 int valueBegin, valueEnd; | |
| 177 | |
| 178 int i = 0; | |
| 179 int length = content.length(); | |
| 180 String buffer = content.lower(); | |
| 181 while (i < length) { | |
| 182 // Skip to first non-separator, but don't skip past the end of the strin g. | |
| 183 while (isValueSeparator(buffer[i], &ok)) { | |
| 184 if (i >= length) | |
| 185 break; | |
| 186 i++; | |
| 187 } | |
| 188 keyBegin = i; | |
| 189 | |
| 190 // skip to first separator | |
| 191 while (!isValueSeparator(buffer[i], &ok)) | |
| 192 i++; | |
| 193 keyEnd = i; | |
| 194 | |
| 195 // Skip to first '=', but don't skip past a ',' or the end of the string . | |
| 196 while (buffer[i] != '=') { | |
| 197 if (isPropertySeparator(buffer[i], &ok) || i >= length) | |
| 198 break; | |
| 199 i++; | |
| 200 } | |
| 201 | |
| 202 // Skip to first non-separator, but don't skip past a ',' or the end of the string. | |
| 203 while (isValueSeparator(buffer[i], &ok)) { | |
| 204 if (isPropertySeparator(buffer[i], &ok) || i >= length) | |
| 205 break; | |
| 206 i++; | |
| 207 } | |
| 208 valueBegin = i; | |
| 209 | |
| 210 // Skip to first separator. | |
| 211 while (!isValueSeparator(buffer[i], &ok)) | |
| 212 i++; | |
| 213 valueEnd = i; | |
| 214 | |
| 215 ASSERT_WITH_SECURITY_IMPLICATION(i <= length); | |
| 216 | |
| 217 String propertyString = buffer.substring(keyBegin, keyEnd - keyBegin); | |
| 218 String valueString = buffer.substring(valueBegin, valueEnd - valueBegin) ; | |
| 219 | |
| 220 callback(this, properties, propertyString, valueString); | |
| 221 } | |
| 222 if (!ok) | |
| 223 reportError(InvalidPropertySeparatorError, String(), String()); | |
| 224 } | |
| 225 | |
| 226 PassRefPtr<CSSValue> HTMLMetaElement::parseViewportValueAsLength(const String& p ropertyString, const String& valueString) | |
| 227 { | |
| 228 const UChar* characters; | |
| 229 unsigned valueLength = valueString.length(); | |
| 230 | |
| 231 const unsigned longestValueLength = 13; | |
| 232 UChar characterBuffer[longestValueLength]; | |
| 233 if (valueString.is8Bit()) { | |
| 234 unsigned length = std::min(longestValueLength, valueLength); | |
| 235 const LChar* characters8 = valueString.characters8(); | |
| 236 for (unsigned i = 0; i < length; ++i) | |
| 237 characterBuffer[i] = characters8[i]; | |
| 238 characters = characterBuffer; | |
| 239 } else { | |
| 240 characters = valueString.characters16(); | |
| 241 } | |
| 242 | |
| 243 SWITCH(characters, valueLength) { | |
| 244 CASE("device-width") { | |
| 245 return cssValuePool().createValue(100, CSSPrimitiveValue::CSS_PERCEN TAGE); | |
| 246 } | |
| 247 CASE("device-height") { | |
| 248 return cssValuePool().createValue(100, CSSPrimitiveValue::CSS_PERCEN TAGE); | |
| 249 } | |
| 250 } | |
| 251 | |
| 252 // Other keywords and unknown values translate to 1px. | |
| 253 float value = parsePositiveNumber(propertyString, valueString, float(1), flo at(10000)); | |
| 254 if (value >= 0) | |
| 255 return cssValuePool().createValue(value, CSSPrimitiveValue::CSS_PX); | |
| 256 | |
| 257 return 0; | |
| 258 } | |
| 259 | |
| 260 PassRefPtr<CSSValue> HTMLMetaElement::parseViewportValueAsZoom(const String& pro pertyString, const String& valueString) | |
| 261 { | |
| 262 const UChar* characters; | |
| 263 unsigned valueLength = valueString.length(); | |
| 264 | |
| 265 const unsigned longestValueLength = 13; | |
| 266 UChar characterBuffer[longestValueLength]; | |
| 267 if (valueString.is8Bit()) { | |
| 268 unsigned length = std::min(longestValueLength, valueLength); | |
| 269 const LChar* characters8 = valueString.characters8(); | |
| 270 for (unsigned i = 0; i < length; ++i) | |
| 271 characterBuffer[i] = characters8[i]; | |
| 272 characters = characterBuffer; | |
| 273 } else { | |
| 274 characters = valueString.characters16(); | |
| 275 } | |
| 276 | |
| 277 float value = -1; | |
| 278 SWITCH(characters, valueLength) { | |
| 279 CASE("yes") { | |
| 280 value = 1; | |
| 281 } | |
| 282 CASE("no") { | |
| 283 value = 0.1; | |
| 284 } | |
| 285 CASE("device-width") { | |
| 286 value = 10; | |
| 287 } | |
| 288 CASE("device-height") { | |
| 289 value = 10; | |
| 290 } | |
| 291 } | |
| 292 | |
| 293 if (value < 0) | |
| 294 value = parsePositiveNumber(propertyString, valueString, float(0.1), flo at(10)); | |
| 295 if (value >= 0) | |
| 296 return cssValuePool().createValue(value, CSSPrimitiveValue::CSS_NUMBER); | |
| 297 | |
| 298 return 0; | |
| 299 } | |
| 300 | |
| 301 CSSValueID HTMLMetaElement::parseViewportValueAsUserZoom(const String& propertyS tring, const String& valueString) | |
| 302 { | |
| 303 const UChar* characters; | |
| 304 unsigned valueLength = valueString.length(); | |
| 305 | |
| 306 const unsigned longestValueLength = 13; | |
| 307 UChar characterBuffer[longestValueLength]; | |
| 308 if (valueString.is8Bit()) { | |
| 309 unsigned length = std::min(longestValueLength, valueLength); | |
| 310 const LChar* characters8 = valueString.characters8(); | |
| 311 for (unsigned i = 0; i < length; ++i) | |
| 312 characterBuffer[i] = characters8[i]; | |
| 313 characters = characterBuffer; | |
| 314 } else { | |
| 315 characters = valueString.characters16(); | |
| 316 } | |
| 317 | |
| 318 SWITCH(characters, valueLength) { | |
| 319 CASE("yes") { | |
| 320 return CSSValueZoom; | |
| 321 } | |
| 322 CASE("no") { | |
| 323 return CSSValueFixed; | |
| 324 } | |
| 325 CASE("device-width") { | |
| 326 return CSSValueZoom; | |
| 327 } | |
| 328 CASE("device-height") { | |
| 329 return CSSValueZoom; | |
| 330 } | |
| 331 } | |
| 332 | |
| 333 float value = parsePositiveNumber(propertyString, valueString, float(0), flo at(1)); | |
| 334 // Numbers in the range <-1, 1>, and unknown values (represented as 0), are mapped to "fixed". | |
|
apavlov
2013/07/30 12:06:45
You should use (-1, 1) to denote the open interval
| |
| 335 // Numbers >= 1, numbers <= -1 are mapped to "zoom" | |
| 336 return (value > -1 && value < 1) ? CSSValueFixed : CSSValueZoom; | |
| 337 } | |
| 338 | |
| 339 PassRefPtr<CSSValue> HTMLMetaElement::parseViewportValueAsDPI(const String& prop ertyString, const String& valueString) | |
| 340 { | |
| 341 const UChar* characters; | |
| 342 unsigned valueLength = valueString.length(); | |
| 343 | |
| 344 const unsigned longestValueLength = 10; | |
| 345 UChar characterBuffer[longestValueLength]; | |
| 346 if (valueString.is8Bit()) { | |
| 347 unsigned length = std::min(longestValueLength, valueLength); | |
| 348 const LChar* characters8 = valueString.characters8(); | |
| 349 for (unsigned i = 0; i < length; ++i) | |
| 350 characterBuffer[i] = characters8[i]; | |
| 351 characters = characterBuffer; | |
| 352 } else { | |
| 353 characters = valueString.characters16(); | |
| 354 } | |
| 355 | |
| 356 CSSValueID id = CSSValueAuto; // Fallback for invalid. | |
| 357 SWITCH(characters, valueLength) { | |
| 358 CASE("device-dpi") { | |
| 359 id = CSSValueDevice; | |
| 360 } | |
| 361 CASE("low-dpi") { | |
| 362 id = CSSValueSmall; | |
| 363 } | |
| 364 CASE("medium-dpi") { | |
| 365 id = CSSValueMedium; | |
| 366 } | |
| 367 CASE("high-dpi") { | |
| 368 id = CSSValueLarge; | |
| 369 } | |
| 370 } | |
| 371 | |
| 372 if (id == CSSValueAuto) { | |
| 373 float value = parsePositiveNumber(propertyString, valueString, float(70) , float(400)); | |
| 374 | |
| 375 if (value >= 70 && value <= 400) | |
| 376 return cssValuePool().createValue(value, CSSPrimitiveValue::CSS_NUMB ER); | |
| 377 } | |
| 378 | |
| 379 return cssValuePool().createIdentifierValue(id); | |
| 380 } | |
| 381 | |
| 382 void HTMLMetaElement::viewportPropertyCollector(HTMLMetaElement* self, MutableSt ylePropertySet* properties, const String& propertyString, const String& valueStr ing) | |
| 383 { | |
| 384 const UChar* characters; | |
| 385 unsigned propertyLength = propertyString.length(); | |
| 386 | |
| 387 const unsigned longestPropertyLength = 17; | |
| 388 UChar characterBuffer[longestPropertyLength]; | |
| 389 if (propertyString.is8Bit()) { | |
| 390 unsigned length = std::min(longestPropertyLength, propertyLength); | |
| 391 const LChar* characters8 = propertyString.characters8(); | |
| 392 for (unsigned i = 0; i < length; ++i) | |
| 393 characterBuffer[i] = characters8[i]; | |
| 394 characters = characterBuffer; | |
| 395 } else { | |
| 396 characters = propertyString.characters16(); | |
| 397 } | |
| 398 | |
| 399 SWITCH(characters, propertyLength) { | |
| 400 CASE("width") { | |
| 401 RefPtr<CSSValue> value = self->parseViewportValueAsLength(propertySt ring, valueString); | |
| 402 if (!value) | |
| 403 return; | |
| 404 properties->setProperty(CSSPropertyMinWidth, CSSValueExtendToZoom); | |
| 405 properties->setProperty(CSSPropertyMaxWidth, value); | |
| 406 return; | |
| 407 } | |
| 408 CASE("height") { | |
| 409 RefPtr<CSSValue> value = self->parseViewportValueAsLength(propertySt ring, valueString); | |
| 410 if (!value) | |
| 411 return; | |
| 412 properties->setProperty(CSSPropertyMinHeight, CSSValueExtendToZoom); | |
| 413 properties->setProperty(CSSPropertyMaxHeight, value); | |
| 414 return; | |
| 415 } | |
| 416 CASE("initial-scale") { | |
| 417 if (RefPtr<CSSValue> value = self->parseViewportValueAsZoom(property String, valueString)) | |
| 418 properties->setProperty(CSSPropertyZoom, value); | |
| 419 return; | |
| 420 } | |
| 421 CASE("minimum-scale") { | |
| 422 if (RefPtr<CSSValue> value = self->parseViewportValueAsZoom(property String, valueString)) | |
| 423 properties->setProperty(CSSPropertyMinZoom, value); | |
| 424 return; | |
| 425 } | |
| 426 CASE("maximum-scale") { | |
| 427 if (RefPtr<CSSValue> value = self->parseViewportValueAsZoom(property String, valueString)) | |
| 428 properties->setProperty(CSSPropertyMaxZoom, value); | |
| 429 return; | |
| 430 } | |
| 431 CASE("user-scalable") { | |
| 432 CSSValueID value = self->parseViewportValueAsUserZoom(propertyString , valueString); | |
| 433 properties->setProperty(CSSPropertyUserZoom, value); | |
| 434 return; | |
| 435 } | |
| 436 CASE("target-densitydpi") { | |
| 437 RefPtr<CSSValue> value = self->parseViewportValueAsDPI(propertyStrin g, valueString); | |
| 438 properties->setProperty(CSSPropertyInternalTargetDensity, value); | |
| 439 return; | |
| 440 } | |
| 441 } | |
| 442 self->reportError(InvalidPropertyError, propertyString, String()); | |
| 443 } | |
| 444 | |
| 445 PassRefPtr<StyleRuleBase> HTMLMetaElement::parseViewportContent(const String& co ntentValue) | |
| 446 { | |
| 447 RefPtr<StyleRuleViewport> rule = StyleRuleViewport::create(); | |
| 448 RefPtr<MutableStylePropertySet> properties = MutableStylePropertySet::create (CSSStrictMode); | |
| 449 parseContentAttribute(properties.get(), contentValue, &HTMLMetaElement::view portPropertyCollector); | |
| 450 | |
| 451 // For a viewport META element that translates into an @viewport rule with a | |
| 452 // non-"auto" "zoom" declaration and no "width" declaration: | |
| 453 // If it adds a "height" descriptor, add: width: auto; Otherwise, add: width : extend-to-zoom; | |
| 454 RefPtr<CSSValue> widthValue = properties->getPropertyCSSValue(CSSPropertyMin Width); | |
| 455 RefPtr<CSSValue> zoomValue = properties->getPropertyCSSValue(CSSPropertyZoom ); | |
| 456 | |
| 457 if (!widthValue && zoomValue) { | |
| 458 RefPtr<CSSValue> heightValue = properties->getPropertyCSSValue(CSSProper tyMinHeight); | |
| 459 CSSValueID commonHeightValue = heightValue ? CSSValueAuto : CSSValueExte ndToZoom; | |
| 460 properties->setProperty(CSSPropertyMinWidth, commonHeightValue); | |
| 461 properties->setProperty(CSSPropertyMaxWidth, commonHeightValue); | |
| 462 } | |
| 463 | |
| 464 rule->setProperties(properties); | |
| 465 | |
| 466 return rule.release(); | |
| 467 } | |
| 468 | |
| 469 PassRefPtr<StyleRuleBase> HTMLMetaElement::parseHandheldFriendlyContent(const St ring& contentValue) | |
| 470 { | |
| 471 RefPtr<StyleRuleViewport> rule = StyleRuleViewport::create(); | |
| 472 RefPtr<MutableStylePropertySet> properties = MutableStylePropertySet::create (CSSStrictMode); | |
| 473 properties->setProperty(CSSPropertyInternalPriority, cssValuePool().createVa lue(2, CSSPrimitiveValue::CSS_NUMBER)); | |
| 474 | |
| 475 if (equalIgnoringCase(contentValue, "true")) { | |
| 476 properties->setProperty(CSSPropertyMinWidth, cssValuePool().createValue( 100, CSSPrimitiveValue::CSS_PERCENTAGE)); | |
| 477 properties->setProperty(CSSPropertyMaxWidth, cssValuePool().createValue( 100, CSSPrimitiveValue::CSS_PERCENTAGE)); | |
| 478 } | |
| 479 | |
| 480 rule->setProperties(properties); | |
| 481 return rule.release(); | |
| 482 } | |
| 483 | |
| 484 PassRefPtr<StyleRuleBase> HTMLMetaElement::parseMobileOptimizedContent(const Str ing& contentValue) | |
| 485 { | |
| 486 RefPtr<StyleRuleViewport> rule = StyleRuleViewport::create(); | |
| 487 RefPtr<MutableStylePropertySet> properties = MutableStylePropertySet::create (CSSStrictMode); | |
| 488 properties->setProperty(CSSPropertyInternalPriority, cssValuePool().createVa lue(3, CSSPrimitiveValue::CSS_NUMBER)); | |
| 489 | |
| 490 float value = parsePositiveNumber(String(), contentValue, float(0), float(10 000)); | |
| 491 RefPtr<CSSValue> widthValue; | |
| 492 if (value > 0) | |
| 493 widthValue = cssValuePool().createValue(value, CSSPrimitiveValue::CSS_PX ); | |
| 494 else | |
| 495 widthValue = cssValuePool().createValue(100, CSSPrimitiveValue::CSS_PERC ENTAGE); | |
| 496 | |
| 497 properties->setProperty(CSSPropertyMinWidth, CSSValueAuto); | |
| 498 properties->setProperty(CSSPropertyMaxWidth, widthValue); | |
| 499 | |
| 500 rule->setProperties(properties); | |
| 501 return rule.release(); | |
| 502 } | |
| 503 | |
| 504 void HTMLMetaElement::parseAttribute(const QualifiedName& name, const AtomicStri ng& value) | |
| 505 { | |
| 506 if (name == http_equivAttr || name == contentAttr) { | |
| 507 process(); | |
| 508 } else if (name == nameAttr) { | |
| 509 // Do nothing. | |
| 510 } else { | |
| 511 HTMLElement::parseAttribute(name, value); | |
| 512 } | |
| 513 } | |
| 514 | |
| 515 void HTMLMetaElement::process() | |
| 516 { | |
| 517 // We always need to clear rules as the meta tag could have been modified. | |
| 518 removeStyleSheet(); | |
| 519 | |
| 520 if (!inDocument()) | |
| 521 return; | |
| 522 | |
| 523 // All below situations requires a content attribute (which can be the empty string). | |
| 524 const AtomicString& contentValue = fastGetAttribute(contentAttr); | |
| 525 if (contentValue.isNull()) | |
| 526 return; | |
| 527 | |
| 528 const AtomicString& nameValue = fastGetAttribute(nameAttr); | |
| 529 | |
| 530 if (nameValue.isNull()) { | |
| 531 // Get the document to process the tag, but only if we're actually part of DOM tree (changing a meta tag while | |
| 532 // it's not in the tree shouldn't have any effect on the document) | |
| 533 const AtomicString& httpEquivValue = fastGetAttribute(http_equivAttr); | |
| 534 if (!httpEquivValue.isNull()) | |
| 535 document()->processHttpEquiv(httpEquivValue, contentValue); | |
| 536 return; | |
| 537 } | |
| 538 | |
| 539 if (equalIgnoringCase(nameValue, "viewport")) { | |
| 540 addStyleSheetForRule(parseViewportContent(contentValue)); | |
| 541 } else if (equalIgnoringCase(name(), "handheldfriendly")) { | |
| 542 addStyleSheetForRule(parseHandheldFriendlyContent(contentValue)); | |
| 543 } else if (equalIgnoringCase(name(), "mobileoptimized")) { | |
| 544 addStyleSheetForRule(parseMobileOptimizedContent(contentValue)); | |
| 545 } else if (equalIgnoringCase(name(), "referrer")) { | |
| 546 document()->processReferrerPolicy(contentValue); | |
| 547 } | |
| 548 } | |
| 549 | |
| 550 void HTMLMetaElement::addStyleSheetForRule(PassRefPtr<StyleRuleBase> rule) | |
| 551 { | |
| 552 ASSERT(inDocument()); | |
| 553 ASSERT(!m_sheet); | |
| 554 | |
| 555 document()->styleSheetCollection()->addStyleSheetCandidateNode(this, false); | |
| 556 | |
| 557 document()->styleSheetCollection()->addPendingSheet(); | |
| 558 | |
| 559 // As the stylesheet has no source URL, the position makes no difference. | |
| 560 TextPosition startPosition = TextPosition::minimumPosition(); | |
| 561 | |
| 562 m_sheet = CSSStyleSheet::createInline(this, KURL(), startPosition, document( )->inputEncoding()); | |
| 563 | |
| 564 m_sheet->setMediaQueries(MediaQuerySet::create("screen")); | |
| 565 m_sheet->setTitle(title()); | |
| 566 | |
| 567 m_sheet->contents()->parserAppendRule(rule); | |
| 568 | |
| 569 document()->styleSheetCollection()->removePendingSheet(); | |
| 570 } | |
| 571 | |
| 572 void HTMLMetaElement::removeStyleSheet() | |
| 573 { | |
| 574 if (m_sheet) { | |
| 575 document()->styleSheetCollection()->removeStyleSheetCandidateNode(this); | |
| 576 m_sheet.release()->clearOwnerNode(); | |
| 577 } | |
| 578 | |
| 579 // No need to resolve style during teardown. | |
| 580 if (document()->renderer()) | |
| 581 document()->styleResolverChanged(DeferRecalcStyle); | |
| 582 } | |
| 583 | |
| 584 String HTMLMetaElement::content() const | |
| 585 { | |
| 586 return getAttribute(contentAttr); | |
| 587 } | |
| 588 | |
| 589 String HTMLMetaElement::httpEquiv() const | |
| 590 { | |
| 591 return getAttribute(http_equivAttr); | |
| 592 } | |
| 593 | |
| 594 String HTMLMetaElement::name() const | |
| 595 { | |
| 596 return getNameAttribute(); | |
| 597 } | |
| 598 | |
| 599 } | |
| OLD | NEW |