/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2003, 2010 Apple Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "core/html/HTMLMetaElement.h"

#include "core/HTMLNames.h"
#include "core/dom/Document.h"
#include "core/dom/ElementTraversal.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/html/HTMLHeadElement.h"
#include "core/html/parser/HTMLParserIdioms.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/loader/FrameLoaderClient.h"
#include "core/loader/HttpEquiv.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "wtf/text/StringToNumber.h"

namespace blink {

using namespace HTMLNames;

inline HTMLMetaElement::HTMLMetaElement(Document& document)
    : HTMLElement(metaTag, document) {}

DEFINE_NODE_FACTORY(HTMLMetaElement)

static bool isInvalidSeparator(UChar c) {
  return c == ';';
}

// Though isspace() considers \t and \v to be whitespace, Win IE doesn't.
static bool isSeparator(UChar c) {
  return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '=' ||
         c == ',' || c == '\0';
}

void HTMLMetaElement::parseContentAttribute(const String& content,
                                            void* data,
                                            Document* document,
                                            bool viewportMetaZeroValuesQuirk) {
  bool hasInvalidSeparator = false;

  // Tread lightly in this code -- it was specifically designed to mimic Win
  // IE's parsing behavior.
  unsigned keyBegin, keyEnd;
  unsigned valueBegin, valueEnd;

  String buffer = content.lower();
  unsigned length = buffer.length();
  for (unsigned i = 0; i < length; /* no increment here */) {
    // skip to first non-separator, but don't skip past the end of the string
    while (isSeparator(buffer[i])) {
      if (i >= length)
        break;
      i++;
    }
    keyBegin = i;

    // skip to first separator
    while (!isSeparator(buffer[i])) {
      hasInvalidSeparator |= isInvalidSeparator(buffer[i]);
      if (i >= length)
        break;
      i++;
    }
    keyEnd = i;

    // skip to first '=', but don't skip past a ',' or the end of the string
    while (buffer[i] != '=') {
      hasInvalidSeparator |= isInvalidSeparator(buffer[i]);
      if (buffer[i] == ',' || i >= length)
        break;
      i++;
    }

    // Skip to first non-separator, but don't skip past a ',' or the end of the
    // string.
    while (isSeparator(buffer[i])) {
      if (buffer[i] == ',' || i >= length)
        break;
      i++;
    }
    valueBegin = i;

    // skip to first separator
    while (!isSeparator(buffer[i])) {
      hasInvalidSeparator |= isInvalidSeparator(buffer[i]);
      if (i >= length)
        break;
      i++;
    }
    valueEnd = i;

    SECURITY_DCHECK(i <= length);

    String keyString = buffer.substring(keyBegin, keyEnd - keyBegin);
    String valueString = buffer.substring(valueBegin, valueEnd - valueBegin);
    processViewportKeyValuePair(document, !hasInvalidSeparator, keyString,
                                valueString, viewportMetaZeroValuesQuirk, data);
  }
  if (hasInvalidSeparator && document) {
    String message =
        "Error parsing a meta element's content: ';' is not a valid key-value "
        "pair separator. Please use ',' instead.";
    document->addConsoleMessage(ConsoleMessage::create(
        RenderingMessageSource, WarningMessageLevel, message));
  }
}

static inline float clampLengthValue(float value) {
  // Limits as defined in the css-device-adapt spec.
  if (value != ViewportDescription::ValueAuto)
    return std::min(float(10000), std::max(value, float(1)));
  return value;
}

static inline float clampScaleValue(float value) {
  // Limits as defined in the css-device-adapt spec.
  if (value != ViewportDescription::ValueAuto)
    return std::min(float(10), std::max(value, float(0.1)));
  return value;
}

float HTMLMetaElement::parsePositiveNumber(Document* document,
                                           bool reportWarnings,
                                           const String& keyString,
                                           const String& valueString,
                                           bool* ok) {
  size_t parsedLength;
  float value;
  if (valueString.is8Bit())
    value = charactersToFloat(valueString.characters8(), valueString.length(),
                              parsedLength);
  else
    value = charactersToFloat(valueString.characters16(), valueString.length(),
                              parsedLength);
  if (!parsedLength) {
    if (reportWarnings)
      reportViewportWarning(document, UnrecognizedViewportArgumentValueError,
                            valueString, keyString);
    if (ok)
      *ok = false;
    return 0;
  }
  if (parsedLength < valueString.length() && reportWarnings)
    reportViewportWarning(document, TruncatedViewportArgumentValueError,
                          valueString, keyString);
  if (ok)
    *ok = true;
  return value;
}

Length HTMLMetaElement::parseViewportValueAsLength(Document* document,
                                                   bool reportWarnings,
                                                   const String& keyString,
                                                   const String& valueString) {
  // 1) Non-negative number values are translated to px lengths.
  // 2) Negative number values are translated to auto.
  // 3) device-width and device-height are used as keywords.
  // 4) Other keywords and unknown values translate to 0.0.

  if (equalIgnoringCase(valueString, "device-width"))
    return Length(DeviceWidth);
  if (equalIgnoringCase(valueString, "device-height"))
    return Length(DeviceHeight);

  float value =
      parsePositiveNumber(document, reportWarnings, keyString, valueString);

  if (value < 0)
    return Length();  // auto

  return Length(clampLengthValue(value), Fixed);
}

float HTMLMetaElement::parseViewportValueAsZoom(
    Document* document,
    bool reportWarnings,
    const String& keyString,
    const String& valueString,
    bool& computedValueMatchesParsedValue,
    bool viewportMetaZeroValuesQuirk) {
  // 1) Non-negative number values are translated to <number> values.
  // 2) Negative number values are translated to auto.
  // 3) yes is translated to 1.0.
  // 4) device-width and device-height are translated to 10.0.
  // 5) no and unknown values are translated to 0.0

  computedValueMatchesParsedValue = false;
  if (equalIgnoringCase(valueString, "yes"))
    return 1;
  if (equalIgnoringCase(valueString, "no"))
    return 0;
  if (equalIgnoringCase(valueString, "device-width"))
    return 10;
  if (equalIgnoringCase(valueString, "device-height"))
    return 10;

  float value =
      parsePositiveNumber(document, reportWarnings, keyString, valueString);

  if (value < 0)
    return ViewportDescription::ValueAuto;

  if (value > 10.0 && reportWarnings)
    reportViewportWarning(document, MaximumScaleTooLargeError, String(),
                          String());

  if (!value && viewportMetaZeroValuesQuirk)
    return ViewportDescription::ValueAuto;

  float clampedValue = clampScaleValue(value);
  if (clampedValue == value)
    computedValueMatchesParsedValue = true;

  return clampedValue;
}

bool HTMLMetaElement::parseViewportValueAsUserZoom(
    Document* document,
    bool reportWarnings,
    const String& keyString,
    const String& valueString,
    bool& computedValueMatchesParsedValue) {
  // yes and no are used as keywords.
  // Numbers >= 1, numbers <= -1, device-width and device-height are mapped to
  // yes.
  // Numbers in the range <-1, 1>, and unknown values, are mapped to no.

  computedValueMatchesParsedValue = false;
  if (equalIgnoringCase(valueString, "yes")) {
    computedValueMatchesParsedValue = true;
    return true;
  }
  if (equalIgnoringCase(valueString, "no")) {
    computedValueMatchesParsedValue = true;
    return false;
  }
  if (equalIgnoringCase(valueString, "device-width"))
    return true;
  if (equalIgnoringCase(valueString, "device-height"))
    return true;

  float value =
      parsePositiveNumber(document, reportWarnings, keyString, valueString);
  if (fabs(value) < 1)
    return false;

  return true;
}

float HTMLMetaElement::parseViewportValueAsDPI(Document* document,
                                               bool reportWarnings,
                                               const String& keyString,
                                               const String& valueString) {
  if (equalIgnoringCase(valueString, "device-dpi"))
    return ViewportDescription::ValueDeviceDPI;
  if (equalIgnoringCase(valueString, "low-dpi"))
    return ViewportDescription::ValueLowDPI;
  if (equalIgnoringCase(valueString, "medium-dpi"))
    return ViewportDescription::ValueMediumDPI;
  if (equalIgnoringCase(valueString, "high-dpi"))
    return ViewportDescription::ValueHighDPI;

  bool ok;
  float value = parsePositiveNumber(document, reportWarnings, keyString,
                                    valueString, &ok);
  if (!ok || value < 70 || value > 400)
    return ViewportDescription::ValueAuto;

  return value;
}

void HTMLMetaElement::processViewportKeyValuePair(
    Document* document,
    bool reportWarnings,
    const String& keyString,
    const String& valueString,
    bool viewportMetaZeroValuesQuirk,
    void* data) {
  ViewportDescription* description = static_cast<ViewportDescription*>(data);

  if (keyString == "width") {
    const Length& width = parseViewportValueAsLength(document, reportWarnings,
                                                     keyString, valueString);
    if (!width.isAuto()) {
      description->minWidth = Length(ExtendToZoom);
      description->maxWidth = width;
    }
  } else if (keyString == "height") {
    const Length& height = parseViewportValueAsLength(document, reportWarnings,
                                                      keyString, valueString);
    if (!height.isAuto()) {
      description->minHeight = Length(ExtendToZoom);
      description->maxHeight = height;
    }
  } else if (keyString == "initial-scale") {
    description->zoom = parseViewportValueAsZoom(
        document, reportWarnings, keyString, valueString,
        description->zoomIsExplicit, viewportMetaZeroValuesQuirk);
  } else if (keyString == "minimum-scale") {
    description->minZoom = parseViewportValueAsZoom(
        document, reportWarnings, keyString, valueString,
        description->minZoomIsExplicit, viewportMetaZeroValuesQuirk);
  } else if (keyString == "maximum-scale") {
    description->maxZoom = parseViewportValueAsZoom(
        document, reportWarnings, keyString, valueString,
        description->maxZoomIsExplicit, viewportMetaZeroValuesQuirk);
  } else if (keyString == "user-scalable") {
    description->userZoom = parseViewportValueAsUserZoom(
        document, reportWarnings, keyString, valueString,
        description->userZoomIsExplicit);
  } else if (keyString == "target-densitydpi") {
    description->deprecatedTargetDensityDPI = parseViewportValueAsDPI(
        document, reportWarnings, keyString, valueString);
    if (reportWarnings)
      reportViewportWarning(document, TargetDensityDpiUnsupported, String(),
                            String());
  } else if (keyString == "minimal-ui") {
    // Ignore vendor-specific argument.
  } else if (keyString == "shrink-to-fit") {
    // Ignore vendor-specific argument.
  } else if (reportWarnings) {
    reportViewportWarning(document, UnrecognizedViewportArgumentKeyError,
                          keyString, String());
  }
}

static const char* viewportErrorMessageTemplate(ViewportErrorCode errorCode) {
  static const char* const errors[] = {
      "The key \"%replacement1\" is not recognized and ignored.",
      "The value \"%replacement1\" for key \"%replacement2\" is invalid, and "
      "has been ignored.",
      "The value \"%replacement1\" for key \"%replacement2\" was truncated to "
      "its numeric prefix.",
      "The value for key \"maximum-scale\" is out of bounds and the value has "
      "been clamped.",
      "The key \"target-densitydpi\" is not supported.",
  };

  return errors[errorCode];
}

static MessageLevel viewportErrorMessageLevel(ViewportErrorCode errorCode) {
  switch (errorCode) {
    case TruncatedViewportArgumentValueError:
    case TargetDensityDpiUnsupported:
    case UnrecognizedViewportArgumentKeyError:
    case UnrecognizedViewportArgumentValueError:
    case MaximumScaleTooLargeError:
      return WarningMessageLevel;
  }

  NOTREACHED();
  return ErrorMessageLevel;
}

void HTMLMetaElement::reportViewportWarning(Document* document,
                                            ViewportErrorCode errorCode,
                                            const String& replacement1,
                                            const String& replacement2) {
  if (!document || !document->frame())
    return;

  String message = viewportErrorMessageTemplate(errorCode);
  if (!replacement1.isNull())
    message.replace("%replacement1", replacement1);
  if (!replacement2.isNull())
    message.replace("%replacement2", replacement2);

  // FIXME: This message should be moved off the console once a solution to
  // https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
  document->addConsoleMessage(ConsoleMessage::create(
      RenderingMessageSource, viewportErrorMessageLevel(errorCode), message));
}

void HTMLMetaElement::getViewportDescriptionFromContentAttribute(
    const String& content,
    ViewportDescription& description,
    Document* document,
    bool viewportMetaZeroValuesQuirk) {
  parseContentAttribute(content, (void*)&description, document,
                        viewportMetaZeroValuesQuirk);

  if (description.minZoom == ViewportDescription::ValueAuto)
    description.minZoom = 0.25;

  if (description.maxZoom == ViewportDescription::ValueAuto) {
    description.maxZoom = 5;
    description.minZoom = std::min(description.minZoom, float(5));
  }
}
void HTMLMetaElement::processViewportContentAttribute(
    const String& content,
    ViewportDescription::Type origin) {
  DCHECK(!content.isNull());

  if (!document().shouldOverrideLegacyDescription(origin))
    return;

  ViewportDescription descriptionFromLegacyTag(origin);
  if (document().shouldMergeWithLegacyDescription(origin))
    descriptionFromLegacyTag = document().viewportDescription();

  getViewportDescriptionFromContentAttribute(
      content, descriptionFromLegacyTag, &document(),
      document().settings() &&
          document().settings()->viewportMetaZeroValuesQuirk());

  document().setViewportDescription(descriptionFromLegacyTag);
}

void HTMLMetaElement::parseAttribute(const QualifiedName& name,
                                     const AtomicString& oldValue,
                                     const AtomicString& value) {
  if (name == http_equivAttr || name == contentAttr) {
    process();
    return;
  }

  if (name != nameAttr)
    HTMLElement::parseAttribute(name, oldValue, value);
}

Node::InsertionNotificationRequest HTMLMetaElement::insertedInto(
    ContainerNode* insertionPoint) {
  HTMLElement::insertedInto(insertionPoint);
  return InsertionShouldCallDidNotifySubtreeInsertions;
}

void HTMLMetaElement::didNotifySubtreeInsertionsToDocument() {
  process();
}

static bool inDocumentHead(HTMLMetaElement* element) {
  if (!element->isConnected())
    return false;

  return Traversal<HTMLHeadElement>::firstAncestor(*element);
}

void HTMLMetaElement::process() {
  if (!isConnected())
    return;

  // All below situations require a content attribute (which can be the empty
  // string).
  const AtomicString& contentValue = fastGetAttribute(contentAttr);
  if (contentValue.isNull())
    return;

  const AtomicString& nameValue = fastGetAttribute(nameAttr);
  if (!nameValue.isEmpty()) {
    if (equalIgnoringCase(nameValue, "viewport"))
      processViewportContentAttribute(contentValue,
                                      ViewportDescription::ViewportMeta);
    else if (equalIgnoringCase(nameValue, "referrer"))
      document().parseAndSetReferrerPolicy(contentValue,
                                           true /* support legacy keywords */);
    else if (equalIgnoringCase(nameValue, "handheldfriendly") &&
             equalIgnoringCase(contentValue, "true"))
      processViewportContentAttribute(
          "width=device-width", ViewportDescription::HandheldFriendlyMeta);
    else if (equalIgnoringCase(nameValue, "mobileoptimized"))
      processViewportContentAttribute("width=device-width, initial-scale=1",
                                      ViewportDescription::MobileOptimizedMeta);
    else if (equalIgnoringCase(nameValue, "theme-color") && document().frame())
      document().frame()->loader().client()->dispatchDidChangeThemeColor();
  }

  // Get the document to process the tag, but only if we're actually part of DOM
  // tree (changing a meta tag while it's not in the tree shouldn't have any
  // effect on the document).

  const AtomicString& httpEquivValue = fastGetAttribute(http_equivAttr);
  if (httpEquivValue.isEmpty())
    return;

  HttpEquiv::process(document(), httpEquivValue, contentValue,
                     inDocumentHead(this));
}

WTF::TextEncoding HTMLMetaElement::computeEncoding() const {
  HTMLAttributeList attributeList;
  for (const Attribute& attr : attributes())
    attributeList.append(
        std::make_pair(attr.name().localName(), attr.value().getString()));
  return encodingFromMetaAttributes(attributeList);
}

const AtomicString& HTMLMetaElement::content() const {
  return getAttribute(contentAttr);
}

const AtomicString& HTMLMetaElement::httpEquiv() const {
  return getAttribute(http_equivAttr);
}

const AtomicString& HTMLMetaElement::name() const {
  return getNameAttribute();
}
}
