Home | History | Annotate | Download | only in web_request
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/extensions/api/web_request/upload_data_presenter.h"
      6 
      7 #include "base/files/file_path.h"
      8 #include "base/strings/string_util.h"
      9 #include "base/values.h"
     10 #include "chrome/browser/extensions/api/web_request/form_data_parser.h"
     11 #include "chrome/browser/extensions/api/web_request/web_request_api_constants.h"
     12 #include "net/base/upload_bytes_element_reader.h"
     13 #include "net/base/upload_file_element_reader.h"
     14 #include "net/url_request/url_request.h"
     15 
     16 using base::BinaryValue;
     17 using base::DictionaryValue;
     18 using base::ListValue;
     19 using base::StringValue;
     20 using base::Value;
     21 
     22 namespace keys = extension_web_request_api_constants;
     23 
     24 namespace {
     25 
     26 // Takes |dictionary| of <string, list of strings> pairs, and gets the list
     27 // for |key|, creating it if necessary.
     28 base::ListValue* GetOrCreateList(base::DictionaryValue* dictionary,
     29                                  const std::string& key) {
     30   base::ListValue* list = NULL;
     31   if (!dictionary->GetList(key, &list)) {
     32     list = new base::ListValue();
     33     dictionary->SetWithoutPathExpansion(key, list);
     34   }
     35   return list;
     36 }
     37 
     38 }  // namespace
     39 
     40 namespace extensions {
     41 
     42 namespace subtle {
     43 
     44 void AppendKeyValuePair(const char* key,
     45                         base::Value* value,
     46                         base::ListValue* list) {
     47   base::DictionaryValue* dictionary = new base::DictionaryValue;
     48   dictionary->SetWithoutPathExpansion(key, value);
     49   list->Append(dictionary);
     50 }
     51 
     52 }  // namespace subtle
     53 
     54 UploadDataPresenter::~UploadDataPresenter() {}
     55 
     56 RawDataPresenter::RawDataPresenter()
     57   : success_(true),
     58     list_(new base::ListValue) {
     59 }
     60 RawDataPresenter::~RawDataPresenter() {}
     61 
     62 void RawDataPresenter::FeedNext(const net::UploadElementReader& reader) {
     63   if (!success_)
     64     return;
     65 
     66   if (reader.AsBytesReader()) {
     67     const net::UploadBytesElementReader* bytes_reader = reader.AsBytesReader();
     68     FeedNextBytes(bytes_reader->bytes(), bytes_reader->length());
     69   } else if (reader.AsFileReader()) {
     70     // Insert the file path instead of the contents, which may be too large.
     71     const net::UploadFileElementReader* file_reader = reader.AsFileReader();
     72     FeedNextFile(file_reader->path().AsUTF8Unsafe());
     73   } else {
     74     NOTIMPLEMENTED();
     75   }
     76 }
     77 
     78 bool RawDataPresenter::Succeeded() {
     79   return success_;
     80 }
     81 
     82 scoped_ptr<base::Value> RawDataPresenter::Result() {
     83   if (!success_)
     84     return scoped_ptr<base::Value>();
     85 
     86   return list_.PassAs<base::Value>();
     87 }
     88 
     89 void RawDataPresenter::FeedNextBytes(const char* bytes, size_t size) {
     90   subtle::AppendKeyValuePair(keys::kRequestBodyRawBytesKey,
     91                              BinaryValue::CreateWithCopiedBuffer(bytes, size),
     92                              list_.get());
     93 }
     94 
     95 void RawDataPresenter::FeedNextFile(const std::string& filename) {
     96   // Insert the file path instead of the contents, which may be too large.
     97   subtle::AppendKeyValuePair(keys::kRequestBodyRawFileKey,
     98                              new base::StringValue(filename),
     99                              list_.get());
    100 }
    101 
    102 ParsedDataPresenter::ParsedDataPresenter(const net::URLRequest& request)
    103   : parser_(FormDataParser::Create(request)),
    104     success_(parser_.get() != NULL),
    105     dictionary_(success_ ? new base::DictionaryValue() : NULL) {
    106 }
    107 
    108 ParsedDataPresenter::~ParsedDataPresenter() {}
    109 
    110 void ParsedDataPresenter::FeedNext(const net::UploadElementReader& reader) {
    111   if (!success_)
    112     return;
    113 
    114   const net::UploadBytesElementReader* bytes_reader = reader.AsBytesReader();
    115   if (!bytes_reader) {
    116     return;
    117   }
    118   if (!parser_->SetSource(base::StringPiece(bytes_reader->bytes(),
    119                                             bytes_reader->length()))) {
    120     Abort();
    121     return;
    122   }
    123 
    124   FormDataParser::Result result;
    125   while (parser_->GetNextNameValue(&result)) {
    126     GetOrCreateList(dictionary_.get(), result.name())->Append(
    127         new base::StringValue(result.value()));
    128   }
    129 }
    130 
    131 bool ParsedDataPresenter::Succeeded() {
    132   if (success_ && !parser_->AllDataReadOK())
    133     Abort();
    134   return success_;
    135 }
    136 
    137 scoped_ptr<base::Value> ParsedDataPresenter::Result() {
    138   if (!success_)
    139     return scoped_ptr<base::Value>();
    140 
    141   return dictionary_.PassAs<base::Value>();
    142 }
    143 
    144 // static
    145 scoped_ptr<ParsedDataPresenter> ParsedDataPresenter::CreateForTests() {
    146   const std::string form_type("application/x-www-form-urlencoded");
    147   return scoped_ptr<ParsedDataPresenter>(new ParsedDataPresenter(form_type));
    148 }
    149 
    150 ParsedDataPresenter::ParsedDataPresenter(const std::string& form_type)
    151   : parser_(FormDataParser::CreateFromContentTypeHeader(&form_type)),
    152     success_(parser_.get() != NULL),
    153     dictionary_(success_ ? new base::DictionaryValue() : NULL) {
    154 }
    155 
    156 void ParsedDataPresenter::Abort() {
    157   success_ = false;
    158   dictionary_.reset();
    159   parser_.reset();
    160 }
    161 
    162 }  // namespace extensions
    163