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