| // Copyright 2015 The Cobalt Authors. 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. | |
| #ifndef COBALT_DOM_PARSER_LIBXML_PARSER_WRAPPER_H_ | |
| #define COBALT_DOM_PARSER_LIBXML_PARSER_WRAPPER_H_ | |
| #include <stack> | |
| #include <string> | |
| #include <vector> | |
| #include "base/callback.h" | |
| #include "base/memory/ref_counted.h" | |
| #include "base/strings/string_piece.h" | |
| #include "cobalt/base/source_location.h" | |
| #include "cobalt/dom/document.h" | |
| #include "cobalt/dom/node.h" | |
| #include "cobalt/loader/decoder.h" | |
| namespace cobalt { | |
| namespace dom_parser { | |
| typedef unsigned char xmlChar; | |
| ///////////////////////////////////////////////////////////////////////////// | |
| // Libxml SAX Handlers | |
| ///////////////////////////////////////////////////////////////////////////// | |
| // These handlers are shared between HTML parser and XML parser. | |
| void StartDocument(void* context); | |
| void EndDocument(void* context); | |
| void StartElement(void* context, const xmlChar* name, | |
| const xmlChar** attribute_pairs); | |
| void EndElement(void* context, const xmlChar* name); | |
| void Characters(void* context, const xmlChar* ch, int len); | |
| void Comment(void* context, const xmlChar* value); | |
| void ParserWarning(void* context, const char* message, ...); | |
| void ParserError(void* context, const char* message, ...); | |
| void ParserFatal(void* context, const char* message, ...); | |
| void CDATABlock(void* context, const xmlChar* value, int len); | |
| ////////////////////////////////////////////////////////////////// | |
| // LibxmlParserWrapper | |
| ////////////////////////////////////////////////////////////////// | |
| class LibxmlParserWrapper { | |
| public: | |
| enum IssueSeverity { | |
| kNoIssue, | |
| kWarning, // A simple warning | |
| kError, // A recoverable error | |
| kFatal, // A fatal error | |
| kIssueSeverityCount, | |
| }; | |
| struct ParserAttribute { | |
| ParserAttribute() {} | |
| ParserAttribute(const base::StringPiece& new_name, | |
| const base::StringPiece& new_value) | |
| : name(new_name), value(new_value) {} | |
| base::StringPiece name; | |
| base::StringPiece value; | |
| }; | |
| typedef std::vector<ParserAttribute> ParserAttributeVector; | |
| LibxmlParserWrapper( | |
| const scoped_refptr<dom::Document>& document, | |
| const scoped_refptr<dom::Node>& parent_node, | |
| const scoped_refptr<dom::Node>& reference_node, | |
| const int dom_max_element_depth, | |
| const base::SourceLocation& first_chunk_location, | |
| const loader::Decoder::OnCompleteFunction& load_complete_callback) | |
| : document_(document), | |
| parent_node_(parent_node), | |
| reference_node_(reference_node), | |
| dom_max_element_depth_(dom_max_element_depth), | |
| first_chunk_location_(first_chunk_location), | |
| load_complete_callback_(load_complete_callback), | |
| depth_limit_exceeded_(false), | |
| max_severity_(kNoIssue), | |
| total_input_size_(0) {} | |
| virtual ~LibxmlParserWrapper() {} | |
| // These functions are for Libxml interface, calls are forwarded here by | |
| // the SAX handlers. | |
| virtual void OnStartDocument(); | |
| virtual void OnEndDocument(); | |
| virtual void OnStartElement(const std::string& name, | |
| const ParserAttributeVector& attributes); | |
| virtual void OnEndElement(const std::string& name); | |
| virtual void OnCharacters(const std::string& value); | |
| virtual void OnComment(const std::string& comment); | |
| virtual void OnParsingIssue(IssueSeverity severity, | |
| const std::string& message); | |
| virtual void OnCDATABlock(const std::string& value); | |
| // These interfaces are for the decoder that uses the wrapper. The input data | |
| // should be UTF8, and will be ignored if not. | |
| virtual void DecodeChunk(const char* data, size_t size) = 0; | |
| virtual void Finish() = 0; | |
| protected: | |
| // Returns the source location from libxml context. | |
| virtual base::SourceLocation GetSourceLocation() = 0; | |
| // Returns true when the input is a full document, false when it's a fragment. | |
| bool IsFullDocument() { return document_ == parent_node_; } | |
| // Preprocesses the input chunk and updates the max error severity level. | |
| // Sets current chunk if successful. | |
| void PreprocessChunk(const char* data, size_t size, | |
| std::string* current_chunk); | |
| const scoped_refptr<dom::Document>& document() { return document_; } | |
| const base::SourceLocation& first_chunk_location() { | |
| return first_chunk_location_; | |
| } | |
| const loader::Decoder::OnCompleteFunction& load_complete_callback() { | |
| return load_complete_callback_; | |
| } | |
| const std::stack<scoped_refptr<dom::Node> >& node_stack() { | |
| return node_stack_; | |
| } | |
| IssueSeverity max_severity() const { return max_severity_; } | |
| private: | |
| // Maximum total input size, as specified in Libxml's value | |
| // XML_MAX_TEXT_LENGTH in parserInternals.h. | |
| static const size_t kMaxTotalInputSize = 10000000; | |
| const scoped_refptr<dom::Document> document_; | |
| const scoped_refptr<dom::Node> parent_node_; | |
| const scoped_refptr<dom::Node> reference_node_; | |
| // Max number the depth of the elements in the DOM tree. All elements at a | |
| // depth deeper than this will be discarded. | |
| const int dom_max_element_depth_; | |
| const base::SourceLocation first_chunk_location_; | |
| const loader::Decoder::OnCompleteFunction load_complete_callback_; | |
| bool depth_limit_exceeded_; | |
| IssueSeverity max_severity_; | |
| size_t total_input_size_; | |
| std::string next_chunk_start_; | |
| std::stack<scoped_refptr<dom::Node> > node_stack_; | |
| DISALLOW_COPY_AND_ASSIGN(LibxmlParserWrapper); | |
| }; | |
| } // namespace dom_parser | |
| } // namespace cobalt | |
| #endif // COBALT_DOM_PARSER_LIBXML_PARSER_WRAPPER_H_ |