root/chrome/browser/extensions/api/web_request/upload_data_presenter.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. GetOrCreateList
  2. AppendKeyValuePair
  3. list_
  4. FeedNext
  5. Succeeded
  6. Result
  7. FeedNextBytes
  8. FeedNextFile
  9. dictionary_
  10. FeedNext
  11. Succeeded
  12. Result
  13. CreateForTests
  14. dictionary_
  15. Abort

// 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/files/file_path.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "chrome/browser/extensions/api/web_request/form_data_parser.h"
#include "chrome/browser/extensions/api/web_request/web_request_api_constants.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_file_element_reader.h"
#include "net/url_request/url_request.h"

using base::BinaryValue;
using base::DictionaryValue;
using base::ListValue;
using base::StringValue;
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::ListValue* GetOrCreateList(base::DictionaryValue* dictionary,
                                 const std::string& key) {
  base::ListValue* list = NULL;
  if (!dictionary->GetList(key, &list)) {
    list = new base::ListValue();
    dictionary->SetWithoutPathExpansion(key, list);
  }
  return list;
}

}  // namespace

namespace extensions {

namespace subtle {

void AppendKeyValuePair(const char* key,
                        base::Value* value,
                        base::ListValue* list) {
  base::DictionaryValue* dictionary = new base::DictionaryValue;
  dictionary->SetWithoutPathExpansion(key, value);
  list->Append(dictionary);
}

}  // namespace subtle

// Implementation of UploadDataPresenter.

UploadDataPresenter::~UploadDataPresenter() {}

// Implementation of RawDataPresenter.

RawDataPresenter::RawDataPresenter()
  : success_(true),
    list_(new base::ListValue) {
}
RawDataPresenter::~RawDataPresenter() {}

void RawDataPresenter::FeedNext(const net::UploadElementReader& reader) {
  if (!success_)
    return;

  if (reader.AsBytesReader()) {
    const net::UploadBytesElementReader* bytes_reader = reader.AsBytesReader();
    FeedNextBytes(bytes_reader->bytes(), bytes_reader->length());
  } else if (reader.AsFileReader()) {
    // Insert the file path instead of the contents, which may be too large.
    const net::UploadFileElementReader* file_reader = reader.AsFileReader();
    FeedNextFile(file_reader->path().AsUTF8Unsafe());
  } else {
    NOTIMPLEMENTED();
  }
}

bool RawDataPresenter::Succeeded() {
  return success_;
}

scoped_ptr<base::Value> RawDataPresenter::Result() {
  if (!success_)
    return scoped_ptr<base::Value>();

  return list_.PassAs<base::Value>();
}

void RawDataPresenter::FeedNextBytes(const char* bytes, size_t size) {
  subtle::AppendKeyValuePair(keys::kRequestBodyRawBytesKey,
                             BinaryValue::CreateWithCopiedBuffer(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,
                             new base::StringValue(filename),
                             list_.get());
}

// Implementation of ParsedDataPresenter.

ParsedDataPresenter::ParsedDataPresenter(const net::URLRequest& request)
  : parser_(FormDataParser::Create(request)),
    success_(parser_.get() != NULL),
    dictionary_(success_ ? new base::DictionaryValue() : NULL) {
}

ParsedDataPresenter::~ParsedDataPresenter() {}

void ParsedDataPresenter::FeedNext(const net::UploadElementReader& reader) {
  if (!success_)
    return;

  const net::UploadBytesElementReader* bytes_reader = reader.AsBytesReader();
  if (!bytes_reader) {
    return;
  }
  if (!parser_->SetSource(base::StringPiece(bytes_reader->bytes(),
                                            bytes_reader->length()))) {
    Abort();
    return;
  }

  FormDataParser::Result result;
  while (parser_->GetNextNameValue(&result)) {
    GetOrCreateList(dictionary_.get(), result.name())->Append(
        new base::StringValue(result.value()));
  }
}

bool ParsedDataPresenter::Succeeded() {
  if (success_ && !parser_->AllDataReadOK())
    Abort();
  return success_;
}

scoped_ptr<base::Value> ParsedDataPresenter::Result() {
  if (!success_)
    return scoped_ptr<base::Value>();

  return dictionary_.PassAs<base::Value>();
}

// static
scoped_ptr<ParsedDataPresenter> ParsedDataPresenter::CreateForTests() {
  const std::string form_type("application/x-www-form-urlencoded");
  return scoped_ptr<ParsedDataPresenter>(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

/* [<][>][^][v][top][bottom][index][help] */