Chromium Code Reviews| Index: chrome/browser/extensions/api/web_request/post_data_parser.h |
| diff --git a/chrome/browser/extensions/api/web_request/post_data_parser.h b/chrome/browser/extensions/api/web_request/post_data_parser.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..7f43f29b9cb5cee018d88beba7eaec39ffb8b5b1 |
| --- /dev/null |
| +++ b/chrome/browser/extensions/api/web_request/post_data_parser.h |
| @@ -0,0 +1,252 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#ifndef CHROME_BROWSER_EXTENSIONS_API_WEB_REQUEST_POST_DATA_PARSER_H_ |
| +#define CHROME_BROWSER_EXTENSIONS_API_WEB_REQUEST_POST_DATA_PARSER_H_ |
| + |
| +#include <string> |
| +#include <vector> |
| + |
| +#include "base/compiler_specific.h" |
| +#include "base/memory/scoped_ptr.h" |
| +#include "base/string_piece.h" |
| +// Need to include this, because UploadData::Element cannot be forward declared. |
| +#include "net/base/upload_data.h" |
| + |
| +namespace base { |
| +class DictionaryValue; |
| +class Value; |
| +} |
| + |
| +namespace net { |
| +class URLRequest; |
| +} |
| + |
| +namespace extensions { |
| + |
| +// Interface for parsers for the POST data. |
|
wtc
2012/08/09 23:39:40
Nit: POST data => form data
vabr (Chromium)
2012/08/10 17:12:55
Done.
|
| +class FormDataParser { |
| + public: |
| + class Result { |
| + public: |
| + Result(); |
| + ~Result(); |
| + const std::string& name() const { |
| + return name_; |
| + } |
| + const std::string& value() const { |
| + return value_; |
| + } |
| + void Reset(); |
| + void set_name(const base::StringPiece& str); |
| + void set_name(const std::string& str); |
| + void set_value(const base::StringPiece& str); |
| + void set_value(const std::string& str); |
|
wtc
2012/08/09 23:39:40
Nit: since we define the getters in the header, pe
vabr (Chromium)
2012/08/10 17:12:55
Done.
|
| + |
| + private: |
| + std::string name_; |
| + std::string value_; |
| + }; |
| + |
| + virtual ~FormDataParser(); |
| + |
| + // Creates a correct parser instance based on the |request|. Returns NULL |
| + // on failure. |
| + static scoped_ptr<FormDataParser> Create(const net::URLRequest* request); |
| + |
| + // Creates a correct parser instance based on |content_type_header|, the |
| + // "Content-Type" request header value. If |content_type_header| is NULL, it |
| + // defaults to "application/x-www-form-urlencoded". Returns NULL on failure. |
| + static scoped_ptr<FormDataParser> Create( |
| + const std::string* content_type_header); |
| + |
| + // Returns true if there was some data, it was well formed and all was read. |
| + virtual bool AllDataReadOK() = 0; |
| + |
| + // Returns the next name-value pair as |result|. After SetSource has |
| + // succeeded, this allows to iterate over all pairs in the source. |
| + // Returns true as long as a new pair was successfully found. |
| + virtual bool GetNextNameValue(Result* result) = 0; |
| + |
| + // Sets the |source| of the data to be parsed. The ownership is left with the |
| + // caller and the source should live until |this| dies or |this->SetSource()| |
| + // is called again, whichever comes sooner. Returns true on success. |
| + virtual bool SetSource(const std::vector<char>* source) = 0; |
| + |
| + protected: |
| + FormDataParser(); |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(FormDataParser); |
| +}; |
| + |
| +// Parses URLencoded forms, see |
| +// http://www.w3.org/TR/REC-html40-971218/interact/forms.html#h-17.13.4.1 . |
| +class FormDataParserUrlEncoded : public FormDataParser { |
| + public: |
| + FormDataParserUrlEncoded(); |
| + virtual ~FormDataParserUrlEncoded(); |
| + |
| + // Implementation of FormDataParser. |
| + virtual bool AllDataReadOK() OVERRIDE; |
| + virtual bool GetNextNameValue(Result* result) OVERRIDE; |
| + virtual bool SetSource(const std::vector<char>* source) OVERRIDE; |
| + |
| + private: |
| + // Gets next char from |source_|, seeks, and does book-keeping of = and &. |
| + // Returns false if end of |source_| was reached, otherwise true. |
| + bool GetNextChar(char* c); |
| + // Once called the parser gives up and claims any results so far invalid. |
| + void Abort(); |
| + |
| + const std::vector<char>* source_; |
| + bool aborted_; |
| + |
| + // Variables from this block are only to be written to by GetNextChar. |
| + std::vector<char>::const_iterator offset_; // Next char to be read. |
| + size_t equality_signs_; // How many '=' were read so far. |
| + size_t amp_signs_; // How many '&' were read so far. |
| + bool expect_equality_; // Is the next trailing sign '=' (as opposed to '&')? |
| + |
| + DISALLOW_COPY_AND_ASSIGN(FormDataParserUrlEncoded); |
| +}; |
| + |
| +// Parses forms encoded as multipart, see RFC 2388. |
| +class FormDataParserMultipart : public FormDataParser { |
| + public: |
| + explicit FormDataParserMultipart(const std::string& boundary_separator); |
| + virtual ~FormDataParserMultipart(); |
| + |
| + // Implementation of FormDataParser. |
| + virtual bool AllDataReadOK() OVERRIDE; |
| + virtual bool GetNextNameValue(Result* result) OVERRIDE; |
| + virtual bool SetSource(const std::vector<char>* source) OVERRIDE; |
| + |
| + private: |
| + // Note on implementation: |
| + // This parser reads the source line by line. These are the types of lines: |
| + // - "Boundary" line, separating entries. |
| + // - "End boundary" line, ends the data. |
| + // - "Content-Disposition" line, containing the "name" for |result|. |
| + // - Empty lines. |
| + // - Other non-empty lines. |
| + enum LineType {kBoundary, kEndBoundary, kDisposition, kEmpty, kOther}; |
| + |
| + // The parser uses the following 7-state automaton to check for structure: |
| + // kInit --Boundary--> kHeaderStart, kInit --not(Boundary)--> kError |
| + // kHeaderStart --Disposition--> kHeaderRead, |
| + // kHeaderStart --not(Disposition)--> kHeader |
| + // kHeader --Disposition--> kHeaderRead, kHeader --not(Disposition)-->kHeader |
| + // kHeaderRead --Empty-->kBody, kHeaderRead --not(Empty)--> kHeaderRead |
| + // kBody --Boundary--> kHeaderStart, kBody --EndBoundary--> kFinal, |
| + // kBody --not(Boundary OR EndBoundary)--> kBody |
| + enum State {kInit, kHeaderStart, kHeader, kHeaderRead, kBody, kFinal, kError}; |
| + |
| + // One step of the automaton, based on |state_| and |line_type_|. |
| + // This calls SeekNextLine() and returns its return value. |
| + bool DoStep(); |
| + |
| + // Determine the |line_type_| of the current line_start_. |
| + LineType GetLineType(); |
| + |
| + // Read one more line from |source_|, update line pointers. |
| + bool SeekNextLine(); |
| + |
| + // Extracts "name" and possibly "value" from a line with type kDisposition. |
| + // Returns true on success and false otherwise. |
| + bool ParseHeader(Result* result, bool* value_extracted); |
| + |
| + // We parse the first |length_| bytes from |source_|. |
| + const char* source_; |
| + size_t length_; |
| + |
| + // Offset of the current and next line from |source_|: |
| + // [line_start_]...line... [line_end_]EOL [next_line_]...line... |
| + size_t line_start_; // Points at the first character of the current line. |
| + size_t line_end_; // Points right beyond the last character of the line. |
| + size_t next_line_; // First char. of the next line, or beyond source length. |
| + const std::string boundary_; |
| + const std::string end_boundary_; |
| + State state_; |
| + LineType line_type_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(FormDataParserMultipart); |
| +}; |
| + |
| +// Workflow for objects implementing this interface: |
|
wtc
2012/08/09 23:39:40
Nit: first define what this interface is or does.
vabr (Chromium)
2012/08/10 17:12:55
Done.
|
| +// 1. Call object->FeedNext(element) for each element from the request's body. |
| +// 2. Check if object->Succeeded(). |
| +// 3. If that check passed then retrieve object->Result(). |
| +class RequestDataRepresentationProducer { |
| + public: |
| + virtual ~RequestDataRepresentationProducer(); |
| + virtual void FeedNext(const net::UploadData::Element& element) = 0; |
| + virtual bool Succeeded() = 0; |
| + virtual scoped_ptr<base::Value> Result() = 0; |
| + |
| + protected: |
| + RequestDataRepresentationProducer() {} |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(RequestDataRepresentationProducer); |
| +}; |
| + |
| +// This class checks that chunked transfer encoding (defined in RFC 2616) |
| +// is not used. If it is, an error string is generated. |
| +class ChunkedErrorProducer : public RequestDataRepresentationProducer { |
| + public: |
| + explicit ChunkedErrorProducer(const net::URLRequest* request); |
| + virtual ~ChunkedErrorProducer(); |
| + |
| + // Tests the headers of |request| for transfer encoding. |
| + static bool TransferEncodingChunked(const net::URLRequest* request); |
| + |
| + // Implementation of RequestDataRepresentationProducer. |
| + virtual void FeedNext(const net::UploadData::Element& element) OVERRIDE; |
| + virtual bool Succeeded() OVERRIDE; |
| + virtual scoped_ptr<base::Value> Result() OVERRIDE; |
| + |
| + private: |
| + bool chunks_found_; |
| +}; |
| + |
| +class RawDataProducer : public RequestDataRepresentationProducer { |
| + public: |
| + RawDataProducer(); |
| + virtual ~RawDataProducer(); |
| + |
| + // Implementation of RequestDataRepresentationProducer. |
| + virtual void FeedNext(const net::UploadData::Element& element) OVERRIDE; |
| + virtual bool Succeeded() OVERRIDE; |
| + virtual scoped_ptr<base::Value> Result() OVERRIDE; |
| + |
| + private: |
| + // Clears resources and the success flag. |
| + void Abort(); |
| + std::vector<char> data_; |
| + std::string data_string_; |
| + bool success_; |
| +}; |
| + |
| +class ParsedDataProducer : public RequestDataRepresentationProducer { |
| + public: |
| + explicit ParsedDataProducer(const net::URLRequest* request); |
| + virtual ~ParsedDataProducer(); |
| + |
| + // Implementation of RequestDataRepresentationProducer. |
| + virtual void FeedNext(const net::UploadData::Element& element) OVERRIDE; |
| + virtual bool Succeeded() OVERRIDE; |
| + virtual scoped_ptr<base::Value> Result() OVERRIDE; |
| + |
| + private: |
| + // Clears resources and the success flag. |
| + void Abort(); |
| + scoped_ptr<FormDataParser> parser_; |
| + bool success_; |
| + scoped_ptr<base::DictionaryValue> dictionary_; |
| +}; |
| + |
| +} // namespace extensions |
| + |
| +#endif // CHROME_BROWSER_EXTENSIONS_API_WEB_REQUEST_POST_DATA_PARSER_H_ |