| Index: chrome/browser/extensions/api/web_request/upload_data_presenter.cc
|
| diff --git a/chrome/browser/extensions/api/web_request/upload_data_presenter.cc b/chrome/browser/extensions/api/web_request/upload_data_presenter.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b11b5cc23b20d8381d3d943365b8bc1beeefb61e
|
| --- /dev/null
|
| +++ b/chrome/browser/extensions/api/web_request/upload_data_presenter.cc
|
| @@ -0,0 +1,187 @@
|
| +// 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.
|
| +
|
| +#include "chrome/browser/extensions/api/web_request/upload_data_presenter.h"
|
| +
|
| +#include "base/file_path.h"
|
| +#include "base/string_util.h"
|
| +#include "base/values.h"
|
| +#include "chrome/browser/extensions/api/web_request/form_data_parser.h"
|
| +#include "net/url_request/url_request.h"
|
| +
|
| +using base::BinaryValue;
|
| +using base::DictionaryValue;
|
| +using base::ListValue;
|
| +using base::StringValue;
|
| +using base::Value;
|
| +
|
| +namespace {
|
| +
|
| +// Takes |dictionary| of <string, list of strings> pairs, and gets the list
|
| +// for |key|, creating it if necessary.
|
| +ListValue* GetOrCreateList(DictionaryValue* dictionary,
|
| + const std::string& key) {
|
| + ListValue* list = NULL;
|
| + if (!dictionary->GetList(key, &list)) {
|
| + list = new ListValue();
|
| + dictionary->Set(key, list);
|
| + }
|
| + return list;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +namespace extensions {
|
| +
|
| +// Implementation of UploadDataPresenter.
|
| +
|
| +UploadDataPresenter::~UploadDataPresenter() {}
|
| +
|
| +// Implementation of ChunkedErrorPresenter.
|
| +
|
| +ChunkedErrorPresenter::ChunkedErrorPresenter(const net::URLRequest* request)
|
| + : chunks_found_(IsTransferEncodingChunked(request)) {
|
| +}
|
| +
|
| +ChunkedErrorPresenter::~ChunkedErrorPresenter() {}
|
| +
|
| +// static
|
| +bool ChunkedErrorPresenter::IsTransferEncodingChunked(
|
| + const net::URLRequest* request){
|
| + std::string transfer_encoding;
|
| + if (!request->extra_request_headers().GetHeader(
|
| + net::HttpRequestHeaders::kTransferEncoding, &transfer_encoding)) {
|
| + return false;
|
| + }
|
| + return base::strcasecmp(transfer_encoding.c_str(), "chunked") == 0;
|
| +}
|
| +
|
| +void ChunkedErrorPresenter::FeedNext(const net::UploadData::Element& element) {
|
| + if (chunks_found_)
|
| + return; // We already found a reason to report an error.
|
| +
|
| + if (element.type() == net::UploadData::TYPE_CHUNK)
|
| + chunks_found_ = true;
|
| +}
|
| +
|
| +bool ChunkedErrorPresenter::Succeeded() {
|
| + return chunks_found_;
|
| +}
|
| +
|
| +scoped_ptr<Value> ChunkedErrorPresenter::Result() {
|
| + if (!chunks_found_)
|
| + return scoped_ptr<Value>();
|
| +
|
| + scoped_ptr<StringValue> error_string(new StringValue(
|
| + "Not supported: data is uploaded chunked."));
|
| + return error_string.PassAs<Value>();
|
| +}
|
| +
|
| +// Implementation of RawDataPresenter.
|
| +
|
| +RawDataPresenter::RawDataPresenter()
|
| + : success_(true),
|
| + list_(new base::ListValue) {
|
| +}
|
| +RawDataPresenter::~RawDataPresenter() {}
|
| +
|
| +void RawDataPresenter::FeedNext(const net::UploadData::Element& element) {
|
| + if (!success_)
|
| + return;
|
| +
|
| + switch (element.type()) {
|
| + case net::UploadData::TYPE_BYTES:
|
| + FeedNextBytes(element.bytes());
|
| + break;
|
| + case net::UploadData::TYPE_CHUNK:
|
| + Abort(); // Chunks are not supported (yet).
|
| + break;
|
| + case net::UploadData::TYPE_FILE:
|
| + // Insert the file path instead of the contents, which may be too large.
|
| + FeedNextFile(element.file_path().AsUTF8Unsafe());
|
| + break;
|
| + case net::UploadData::TYPE_BLOB:
|
| + // TYPE_BLOB is silently ignored.
|
| + break;
|
| + }
|
| +}
|
| +
|
| +bool RawDataPresenter::Succeeded() {
|
| + return success_;
|
| +}
|
| +
|
| +scoped_ptr<Value> RawDataPresenter::Result() {
|
| + if (!success_)
|
| + return scoped_ptr<Value>();
|
| +
|
| + return list_.PassAs<Value>();
|
| +}
|
| +
|
| +void RawDataPresenter::Abort() {
|
| + success_ = false;
|
| + list_.reset();
|
| +}
|
| +
|
| +void RawDataPresenter::FeedNextBytes(const std::vector<char>& bytes) {
|
| + list_->Append(
|
| + BinaryValue::CreateWithCopiedBuffer(&(bytes[0]), bytes.size()));
|
| +}
|
| +
|
| +void RawDataPresenter::FeedNextFile(const std::string& filename) {
|
| + // Insert the file path instead of the contents, which may be too large.
|
| + list_->Append(Value::CreateStringValue(filename));
|
| +}
|
| +
|
| +// Implementation of ParsedDataPresenter.
|
| +
|
| +ParsedDataPresenter::ParsedDataPresenter(const net::URLRequest* request)
|
| + : parser_(FormDataParser::Create(request)),
|
| + success_(parser_.get() != NULL),
|
| + dictionary_(success_ ? new DictionaryValue() : NULL) {
|
| +}
|
| +
|
| +ParsedDataPresenter::~ParsedDataPresenter() {}
|
| +
|
| +void ParsedDataPresenter::FeedNext(const net::UploadData::Element& element) {
|
| + if (!success_)
|
| + return;
|
| +
|
| + if (element.type() != net::UploadData::TYPE_BYTES) {
|
| + if (element.type() != net::UploadData::TYPE_FILE) {
|
| + Abort(); // We do not handle blobs nor chunks.
|
| + }
|
| + return; // But we just ignore files.
|
| + }
|
| + if (!parser_->SetSource(&(element.bytes()))) {
|
| + Abort();
|
| + return;
|
| + }
|
| +
|
| + FormDataParser::Result result;
|
| + while (parser_->GetNextNameValue(&result)) {
|
| + GetOrCreateList(dictionary_.get(), result.name())->Append(
|
| + new StringValue(result.value()));
|
| + }
|
| +}
|
| +
|
| +bool ParsedDataPresenter::Succeeded() {
|
| + if (success_ && !parser_->AllDataReadOK())
|
| + Abort();
|
| + return success_;
|
| +}
|
| +
|
| +scoped_ptr<Value> ParsedDataPresenter::Result() {
|
| + if (success_)
|
| + return dictionary_.PassAs<Value>();
|
| + else
|
| + return scoped_ptr<Value>();
|
| +}
|
| +
|
| +void ParsedDataPresenter::Abort() {
|
| + success_ = false;
|
| + dictionary_.reset();
|
| + parser_.reset();
|
| +}
|
| +
|
| +} // namespace extensions
|
|
|