// Copyright 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/dom/testing/stub_css_parser.h"

namespace cobalt {
namespace dom {
namespace testing {

scoped_refptr<cssom::CSSStyleSheet> StubCSSParser::ParseStyleSheet(
    const std::string& input, const base::SourceLocation& input_location) {
  UNREFERENCED_PARAMETER(input);
  UNREFERENCED_PARAMETER(input_location);
  return new cssom::CSSStyleSheet();
}

scoped_refptr<cssom::CSSRule> StubCSSParser::ParseRule(
    const std::string& input, const base::SourceLocation& input_location) {
  UNREFERENCED_PARAMETER(input);
  UNREFERENCED_PARAMETER(input_location);
  return NULL;
}

scoped_refptr<cssom::CSSDeclaredStyleData>
StubCSSParser::ParseStyleDeclarationList(
    const std::string& input, const base::SourceLocation& input_location) {
  UNREFERENCED_PARAMETER(input);
  UNREFERENCED_PARAMETER(input_location);
  return new cssom::CSSDeclaredStyleData();
}

scoped_refptr<cssom::CSSFontFaceDeclarationData>
StubCSSParser::ParseFontFaceDeclarationList(
    const std::string& input, const base::SourceLocation& input_location) {
  UNREFERENCED_PARAMETER(input);
  UNREFERENCED_PARAMETER(input_location);
  return new cssom::CSSFontFaceDeclarationData();
}

scoped_refptr<cssom::PropertyValue> StubCSSParser::ParsePropertyValue(
    const std::string& property_name, const std::string& property_value,
    const base::SourceLocation& property_location) {
  UNREFERENCED_PARAMETER(property_name);
  UNREFERENCED_PARAMETER(property_value);
  UNREFERENCED_PARAMETER(property_location);
  return NULL;
}

void StubCSSParser::ParsePropertyIntoDeclarationData(
    const std::string& property_name, const std::string& property_value,
    const base::SourceLocation& property_location,
    cssom::CSSDeclarationData* declaration_data) {
  UNREFERENCED_PARAMETER(property_name);
  UNREFERENCED_PARAMETER(property_value);
  UNREFERENCED_PARAMETER(property_location);
  UNREFERENCED_PARAMETER(declaration_data);
}

scoped_refptr<cssom::MediaList> StubCSSParser::ParseMediaList(
    const std::string& media_list, const base::SourceLocation& input_location) {
  UNREFERENCED_PARAMETER(media_list);
  UNREFERENCED_PARAMETER(input_location);
  return new cssom::MediaList();
}

scoped_refptr<cssom::MediaQuery> StubCSSParser::ParseMediaQuery(
    const std::string& media_query,
    const base::SourceLocation& input_location) {
  UNREFERENCED_PARAMETER(media_query);
  UNREFERENCED_PARAMETER(input_location);
  return new cssom::MediaQuery();
}

}  // namespace testing
}  // namespace dom
}  // namespace cobalt
