blob: af036568089cccbba90a4eb267702f7230a7aae3 [file] [log] [blame]
// 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 "extensions/browser/api/web_request/upload_data_presenter.h"
#include <utility>
#include "base/containers/span.h"
#include "base/files/file_path.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "extensions/browser/api/web_request/form_data_parser.h"
#include "extensions/browser/api/web_request/web_request_api_constants.h"
#include "net/base/upload_file_element_reader.h"
using base::DictionaryValue;
using base::ListValue;
using base::Value;
namespace keys = extension_web_request_api_constants;
namespace {
// Takes |dictionary| of <string, list of strings> pairs, and gets the list
// for |key|, creating it if necessary.
base::Value* GetOrCreateList(base::DictionaryValue* dictionary,
const std::string& key) {
base::Value* list = dictionary->FindKeyOfType(key, base::Value::Type::LIST);
if (list)
return list;
return dictionary->SetKey(key, base::Value(base::Value::Type::LIST));
}
} // namespace
namespace extensions {
namespace subtle {
void AppendKeyValuePair(const char* key,
std::unique_ptr<base::Value> value,
base::ListValue* list) {
std::unique_ptr<base::DictionaryValue> dictionary(new base::DictionaryValue);
dictionary->SetWithoutPathExpansion(key, std::move(value));
list->Append(std::move(dictionary));
}
} // namespace subtle
UploadDataPresenter::~UploadDataPresenter() {}
RawDataPresenter::RawDataPresenter()
: success_(true),
list_(new base::ListValue) {
}
RawDataPresenter::~RawDataPresenter() {}
void RawDataPresenter::FeedBytes(base::StringPiece bytes) {
if (!success_)
return;
FeedNextBytes(bytes.data(), bytes.size());
}
void RawDataPresenter::FeedFile(const base::FilePath& path) {
if (!success_)
return;
FeedNextFile(path.AsUTF8Unsafe());
}
bool RawDataPresenter::Succeeded() {
return success_;
}
std::unique_ptr<base::Value> RawDataPresenter::Result() {
if (!success_)
return nullptr;
return std::move(list_);
}
void RawDataPresenter::FeedNextBytes(const char* bytes, size_t size) {
subtle::AppendKeyValuePair(keys::kRequestBodyRawBytesKey,
base::Value::ToUniquePtrValue(base::Value(
base::as_bytes(base::make_span(bytes, size)))),
list_.get());
}
void RawDataPresenter::FeedNextFile(const std::string& filename) {
// Insert the file path instead of the contents, which may be too large.
subtle::AppendKeyValuePair(keys::kRequestBodyRawFileKey,
std::make_unique<base::Value>(filename),
list_.get());
}
ParsedDataPresenter::ParsedDataPresenter(
const net::HttpRequestHeaders& request_headers)
: parser_(FormDataParser::Create(request_headers)),
success_(parser_ != nullptr),
dictionary_(success_ ? new base::DictionaryValue() : nullptr) {}
ParsedDataPresenter::~ParsedDataPresenter() {}
void ParsedDataPresenter::FeedBytes(base::StringPiece bytes) {
if (!success_)
return;
if (!parser_->SetSource(bytes)) {
Abort();
return;
}
FormDataParser::Result result;
while (parser_->GetNextNameValue(&result)) {
base::Value* list = GetOrCreateList(dictionary_.get(), result.name());
list->Append(result.take_value());
}
}
void ParsedDataPresenter::FeedFile(const base::FilePath& path) {}
bool ParsedDataPresenter::Succeeded() {
if (success_ && !parser_->AllDataReadOK())
Abort();
return success_;
}
std::unique_ptr<base::Value> ParsedDataPresenter::Result() {
if (!success_)
return nullptr;
return std::move(dictionary_);
}
// static
std::unique_ptr<ParsedDataPresenter> ParsedDataPresenter::CreateForTests() {
static const std::string form_type("application/x-www-form-urlencoded");
return base::WrapUnique(new ParsedDataPresenter(form_type));
}
ParsedDataPresenter::ParsedDataPresenter(const std::string& form_type)
: parser_(FormDataParser::CreateFromContentTypeHeader(&form_type)),
success_(parser_.get() != NULL),
dictionary_(success_ ? new base::DictionaryValue() : NULL) {
}
void ParsedDataPresenter::Abort() {
success_ = false;
dictionary_.reset();
parser_.reset();
}
} // namespace extensions