• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
GetOrCreateList(DictionaryValue * dictionary,const std::string & key)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 
AppendKeyValuePair(const char * key,Value * value,ListValue * list)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 
~UploadDataPresenter()54 UploadDataPresenter::~UploadDataPresenter() {}
55 
56 // Implementation of RawDataPresenter.
57 
RawDataPresenter()58 RawDataPresenter::RawDataPresenter()
59   : success_(true),
60     list_(new base::ListValue) {
61 }
~RawDataPresenter()62 RawDataPresenter::~RawDataPresenter() {}
63 
FeedNext(const net::UploadElementReader & reader)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 
Succeeded()80 bool RawDataPresenter::Succeeded() {
81   return success_;
82 }
83 
Result()84 scoped_ptr<Value> RawDataPresenter::Result() {
85   if (!success_)
86     return scoped_ptr<Value>();
87 
88   return list_.PassAs<Value>();
89 }
90 
FeedNextBytes(const char * bytes,size_t size)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 
FeedNextFile(const std::string & filename)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 
ParsedDataPresenter(const net::URLRequest & request)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 
~ParsedDataPresenter()112 ParsedDataPresenter::~ParsedDataPresenter() {}
113 
FeedNext(const net::UploadElementReader & reader)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 
Succeeded()135 bool ParsedDataPresenter::Succeeded() {
136   if (success_ && !parser_->AllDataReadOK())
137     Abort();
138   return success_;
139 }
140 
Result()141 scoped_ptr<Value> ParsedDataPresenter::Result() {
142   if (!success_)
143     return scoped_ptr<Value>();
144 
145   return dictionary_.PassAs<Value>();
146 }
147 
148 // static
CreateForTests()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 
ParsedDataPresenter(const std::string & form_type)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 
Abort()160 void ParsedDataPresenter::Abort() {
161   success_ = false;
162   dictionary_.reset();
163   parser_.reset();
164 }
165 
166 }  // namespace extensions
167