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