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 "extensions/browser/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 "extensions/browser/api/web_request/form_data_parser.h" 11 #include "extensions/browser/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