OLD | NEW |
(Empty) | |
| 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/file_path.h" |
| 8 #include "base/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_element.h" |
| 13 #include "net/url_request/url_request.h" |
| 14 |
| 15 using base::BinaryValue; |
| 16 using base::DictionaryValue; |
| 17 using base::ListValue; |
| 18 using base::StringValue; |
| 19 using base::Value; |
| 20 |
| 21 namespace keys = extension_web_request_api_constants; |
| 22 |
| 23 namespace { |
| 24 |
| 25 // Takes |dictionary| of <string, list of strings> pairs, and gets the list |
| 26 // for |key|, creating it if necessary. |
| 27 ListValue* GetOrCreateList(DictionaryValue* dictionary, |
| 28 const std::string& key) { |
| 29 ListValue* list = NULL; |
| 30 if (!dictionary->GetList(key, &list)) { |
| 31 list = new ListValue(); |
| 32 dictionary->Set(key, list); |
| 33 } |
| 34 return list; |
| 35 } |
| 36 |
| 37 } // namespace |
| 38 |
| 39 namespace extensions { |
| 40 |
| 41 // Implementation of UploadDataPresenter. |
| 42 |
| 43 UploadDataPresenter::~UploadDataPresenter() {} |
| 44 |
| 45 // Implementation of ChunkedErrorPresenter. |
| 46 |
| 47 ChunkedErrorPresenter::ChunkedErrorPresenter(const net::URLRequest* request) |
| 48 : chunks_found_(IsTransferEncodingChunked(request)) { |
| 49 } |
| 50 |
| 51 ChunkedErrorPresenter::~ChunkedErrorPresenter() {} |
| 52 |
| 53 // static |
| 54 bool ChunkedErrorPresenter::IsTransferEncodingChunked( |
| 55 const net::URLRequest* request){ |
| 56 std::string transfer_encoding; |
| 57 const net::HttpRequestHeaders& headers = request->extra_request_headers(); |
| 58 if (!headers.GetHeader(net::HttpRequestHeaders::kTransferEncoding, |
| 59 &transfer_encoding)) { |
| 60 return false; |
| 61 } |
| 62 return base::strcasecmp(transfer_encoding.c_str(), "chunked") == 0; |
| 63 } |
| 64 |
| 65 void ChunkedErrorPresenter::FeedNext(const net::UploadElement& element) { |
| 66 if (chunks_found_) |
| 67 return; // We already found a reason to report an error. |
| 68 |
| 69 if (element.type() == net::UploadElement::TYPE_CHUNK) |
| 70 chunks_found_ = true; |
| 71 } |
| 72 |
| 73 bool ChunkedErrorPresenter::Succeeded() { |
| 74 return chunks_found_; |
| 75 } |
| 76 |
| 77 scoped_ptr<Value> ChunkedErrorPresenter::Result() { |
| 78 if (!chunks_found_) |
| 79 return scoped_ptr<Value>(); |
| 80 |
| 81 scoped_ptr<StringValue> error_string(new StringValue( |
| 82 "Not supported: data is uploaded chunked.")); |
| 83 return error_string.PassAs<Value>(); |
| 84 } |
| 85 |
| 86 // Implementation of RawDataPresenter. |
| 87 |
| 88 RawDataPresenter::RawDataPresenter() |
| 89 : success_(true), |
| 90 list_(new base::ListValue) { |
| 91 } |
| 92 RawDataPresenter::~RawDataPresenter() {} |
| 93 |
| 94 void RawDataPresenter::FeedNext(const net::UploadElement& element) { |
| 95 if (!success_) |
| 96 return; |
| 97 |
| 98 switch (element.type()) { |
| 99 case net::UploadElement::TYPE_BYTES: |
| 100 FeedNextBytes(element.bytes(), element.bytes_length()); |
| 101 break; |
| 102 case net::UploadElement::TYPE_CHUNK: |
| 103 Abort(); // Chunks are not supported (yet). |
| 104 break; |
| 105 case net::UploadElement::TYPE_FILE: |
| 106 // Insert the file path instead of the contents, which may be too large. |
| 107 FeedNextFile(element.file_path().AsUTF8Unsafe()); |
| 108 break; |
| 109 } |
| 110 } |
| 111 |
| 112 bool RawDataPresenter::Succeeded() { |
| 113 return success_; |
| 114 } |
| 115 |
| 116 scoped_ptr<Value> RawDataPresenter::Result() { |
| 117 if (!success_) |
| 118 return scoped_ptr<Value>(); |
| 119 |
| 120 return list_.PassAs<Value>(); |
| 121 } |
| 122 |
| 123 // static |
| 124 void RawDataPresenter::AppendResultWithKey( |
| 125 ListValue* list, const char* key, Value* value) { |
| 126 DictionaryValue* dictionary = new DictionaryValue; |
| 127 dictionary->Set(key, value); |
| 128 list->Append(dictionary); |
| 129 } |
| 130 |
| 131 void RawDataPresenter::Abort() { |
| 132 success_ = false; |
| 133 list_.reset(); |
| 134 } |
| 135 |
| 136 void RawDataPresenter::FeedNextBytes(const char* bytes, size_t size) { |
| 137 AppendResultWithKey(list_.get(), keys::kRequestBodyRawBytesKey, |
| 138 BinaryValue::CreateWithCopiedBuffer(bytes, size)); |
| 139 } |
| 140 |
| 141 void RawDataPresenter::FeedNextFile(const std::string& filename) { |
| 142 // Insert the file path instead of the contents, which may be too large. |
| 143 AppendResultWithKey(list_.get(), keys::kRequestBodyRawFileKey, |
| 144 Value::CreateStringValue(filename)); |
| 145 } |
| 146 |
| 147 // Implementation of ParsedDataPresenter. |
| 148 |
| 149 ParsedDataPresenter::ParsedDataPresenter(const net::URLRequest* request) |
| 150 : parser_(FormDataParser::Create(request)), |
| 151 success_(parser_.get() != NULL), |
| 152 dictionary_(success_ ? new DictionaryValue() : NULL) { |
| 153 } |
| 154 |
| 155 ParsedDataPresenter::~ParsedDataPresenter() {} |
| 156 |
| 157 void ParsedDataPresenter::FeedNext(const net::UploadElement& element) { |
| 158 if (!success_) |
| 159 return; |
| 160 |
| 161 if (element.type() != net::UploadElement::TYPE_BYTES) { |
| 162 if (element.type() != net::UploadElement::TYPE_FILE) { |
| 163 Abort(); // We do not handle blobs nor chunks. |
| 164 } |
| 165 return; // But we just ignore files. |
| 166 } |
| 167 if (!parser_->SetSource(base::StringPiece(element.bytes(), |
| 168 element.bytes_length()))) { |
| 169 Abort(); |
| 170 return; |
| 171 } |
| 172 |
| 173 FormDataParser::Result result; |
| 174 while (parser_->GetNextNameValue(&result)) { |
| 175 GetOrCreateList(dictionary_.get(), result.name())->Append( |
| 176 new StringValue(result.value())); |
| 177 } |
| 178 } |
| 179 |
| 180 bool ParsedDataPresenter::Succeeded() { |
| 181 if (success_ && !parser_->AllDataReadOK()) |
| 182 Abort(); |
| 183 return success_; |
| 184 } |
| 185 |
| 186 scoped_ptr<Value> ParsedDataPresenter::Result() { |
| 187 if (success_) |
| 188 return dictionary_.PassAs<Value>(); |
| 189 else |
| 190 return scoped_ptr<Value>(); |
| 191 } |
| 192 |
| 193 void ParsedDataPresenter::Abort() { |
| 194 success_ = false; |
| 195 dictionary_.reset(); |
| 196 parser_.reset(); |
| 197 } |
| 198 |
| 199 } // namespace extensions |
OLD | NEW |