Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(638)

Side by Side Diff: chrome/browser/extensions/api/web_request/upload_data_presenter.cc

Issue 10694055: Add read-only access to POST data for webRequest's onBeforeRequest (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Dominic's comments + adjusting to the recent move of UploadElement out of UploadData. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698