blob: b309b210c1531248a72b26a3f8e3580b0a9c5d56 [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// 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 <string_view>
#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"
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::List& GetOrCreateList(base::Value::Dict& dictionary,
const std::string& key) {
base::Value::List* list = dictionary.FindList(key);
if (list) {
return *list;
}
return dictionary.Set(key, base::Value::List())->GetList();
}
} // namespace
namespace extensions {
namespace subtle {
void AppendKeyValuePair(const char* key,
base::Value value,
base::Value::List& list) {
base::Value::Dict dictionary;
dictionary.Set(key, std::move(value));
list.Append(std::move(dictionary));
}
} // namespace subtle
UploadDataPresenter::~UploadDataPresenter() = default;
RawDataPresenter::RawDataPresenter() = default;
RawDataPresenter::~RawDataPresenter() = default;
void RawDataPresenter::FeedBytes(std::string_view bytes) {
FeedNextBytes(base::as_byte_span(bytes));
}
void RawDataPresenter::FeedFile(const base::FilePath& path) {
FeedNextFile(path.AsUTF8Unsafe());
}
bool RawDataPresenter::Succeeded() {
return true;
}
std::optional<base::Value> RawDataPresenter::TakeResult() {
return base::Value(std::move(list_));
}
void RawDataPresenter::FeedNextBytes(base::span<const uint8_t> bytes) {
subtle::AppendKeyValuePair(keys::kRequestBodyRawBytesKey, base::Value(bytes),
list_);
}
void RawDataPresenter::FeedNextFile(const std::string& filename) {
// Insert the file path instead of the contents, which may be too large.
subtle::AppendKeyValuePair(keys::kRequestBodyRawFileKey,
base::Value(filename), list_);
}
ParsedDataPresenter::ParsedDataPresenter(
const net::HttpRequestHeaders& request_headers)
: parser_(FormDataParser::Create(request_headers)),
success_(parser_ != nullptr) {
if (success_) {
dictionary_.emplace();
}
}
ParsedDataPresenter::~ParsedDataPresenter() = default;
void ParsedDataPresenter::FeedBytes(std::string_view bytes) {
if (!success_) {
return;
}
if (!parser_->SetSource(bytes)) {
Abort();
return;
}
FormDataParser::Result result;
while (parser_->GetNextNameValue(&result)) {
base::Value::List& list =
GetOrCreateList(dictionary_.value(), 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::optional<base::Value> ParsedDataPresenter::TakeResult() {
if (!success_) {
return std::nullopt;
}
return base::Value(std::move(dictionary_.value()));
}
// static
std::unique_ptr<ParsedDataPresenter> ParsedDataPresenter::CreateForTests() {
return base::WrapUnique(
new ParsedDataPresenter("application/x-www-form-urlencoded"));
}
ParsedDataPresenter::ParsedDataPresenter(const std::string& form_type)
: parser_(FormDataParser::CreateFromContentTypeHeader(&form_type)),
success_(parser_.get() != nullptr) {
if (success_) {
dictionary_.emplace();
}
}
void ParsedDataPresenter::Abort() {
success_ = false;
dictionary_.reset();
parser_.reset();
}
} // namespace extensions