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 ListValue* GetOrCreateList(DictionaryValue* dictionary,
     29                            const std::string& key) {
     30   ListValue* list = NULL;
     31   if (!dictionary->GetList(key, &list)) {
     32     list = new 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, Value* value, ListValue* list) {
     45   DictionaryValue* dictionary = new DictionaryValue;
     46   dictionary->SetWithoutPathExpansion(key, value);
     47   list->Append(dictionary);
     48 }
     49 
     50 }  // namespace subtle
     51 
     52 // Implementation of UploadDataPresenter.
     53 
     54 UploadDataPresenter::~UploadDataPresenter() {}
     55 
     56 // Implementation of RawDataPresenter.
     57 
     58 RawDataPresenter::RawDataPresenter()
     59   : success_(true),
     60     list_(new base::ListValue) {
     61 }
     62 RawDataPresenter::~RawDataPresenter() {}
     63 
     64 void RawDataPresenter::FeedNext(const net::UploadElementReader& reader) {
     65   if (!success_)
     66     return;
     67 
     68   if (reader.AsBytesReader()) {
     69     const net::UploadBytesElementReader* bytes_reader = reader.AsBytesReader();
     70     FeedNextBytes(bytes_reader->bytes(), bytes_reader->length());
     71   } else if (reader.AsFileReader()) {
     72     // Insert the file path instead of the contents, which may be too large.
     73     const net::UploadFileElementReader* file_reader = reader.AsFileReader();
     74     FeedNextFile(file_reader->path().AsUTF8Unsafe());
     75   } else {
     76     NOTIMPLEMENTED();
     77   }
     78 }
     79 
     80 bool RawDataPresenter::Succeeded() {
     81   return success_;
     82 }
     83 
     84 scoped_ptr<Value> RawDataPresenter::Result() {
     85   if (!success_)
     86     return scoped_ptr<Value>();
     87 
     88   return list_.PassAs<Value>();
     89 }
     90 
     91 void RawDataPresenter::FeedNextBytes(const char* bytes, size_t size) {
     92   subtle::AppendKeyValuePair(keys::kRequestBodyRawBytesKey,
     93                              BinaryValue::CreateWithCopiedBuffer(bytes, size),
     94                              list_.get());
     95 }
     96 
     97 void RawDataPresenter::FeedNextFile(const std::string& filename) {
     98   // Insert the file path instead of the contents, which may be too large.
     99   subtle::AppendKeyValuePair(keys::kRequestBodyRawFileKey,
    100                              new base::StringValue(filename),
    101                              list_.get());
    102 }
    103 
    104 // Implementation of ParsedDataPresenter.
    105 
    106 ParsedDataPresenter::ParsedDataPresenter(const net::URLRequest& request)
    107   : parser_(FormDataParser::Create(request)),
    108     success_(parser_.get() != NULL),
    109     dictionary_(success_ ? new DictionaryValue() : NULL) {
    110 }
    111 
    112 ParsedDataPresenter::~ParsedDataPresenter() {}
    113 
    114 void ParsedDataPresenter::FeedNext(const net::UploadElementReader& reader) {
    115   if (!success_)
    116     return;
    117 
    118   const net::UploadBytesElementReader* bytes_reader = reader.AsBytesReader();
    119   if (!bytes_reader) {
    120     return;
    121   }
    122   if (!parser_->SetSource(base::StringPiece(bytes_reader->bytes(),
    123                                             bytes_reader->length()))) {
    124     Abort();
    125     return;
    126   }
    127 
    128   FormDataParser::Result result;
    129   while (parser_->GetNextNameValue(&result)) {
    130     GetOrCreateList(dictionary_.get(), result.name())->Append(
    131         new StringValue(result.value()));
    132   }
    133 }
    134 
    135 bool ParsedDataPresenter::Succeeded() {
    136   if (success_ && !parser_->AllDataReadOK())
    137     Abort();
    138   return success_;
    139 }
    140 
    141 scoped_ptr<Value> ParsedDataPresenter::Result() {
    142   if (!success_)
    143     return scoped_ptr<Value>();
    144 
    145   return dictionary_.PassAs<Value>();
    146 }
    147 
    148 // static
    149 scoped_ptr<ParsedDataPresenter> ParsedDataPresenter::CreateForTests() {
    150   const std::string form_type("application/x-www-form-urlencoded");
    151   return scoped_ptr<ParsedDataPresenter>(new ParsedDataPresenter(form_type));
    152 }
    153 
    154 ParsedDataPresenter::ParsedDataPresenter(const std::string& form_type)
    155   : parser_(FormDataParser::CreateFromContentTypeHeader(&form_type)),
    156     success_(parser_.get() != NULL),
    157     dictionary_(success_ ? new DictionaryValue() : NULL) {
    158 }
    159 
    160 void ParsedDataPresenter::Abort() {
    161   success_ = false;
    162   dictionary_.reset();
    163   parser_.reset();
    164 }
    165 
    166 }  // namespace extensions
    167