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

Unified 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: Corrected the multipart parser + parsedForm->formData 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/api/web_request/upload_data_presenter.cc
diff --git a/chrome/browser/extensions/api/web_request/upload_data_presenter.cc b/chrome/browser/extensions/api/web_request/upload_data_presenter.cc
new file mode 100644
index 0000000000000000000000000000000000000000..71a0bd75e03a59f9143deb688b487bd8401a2a03
--- /dev/null
+++ b/chrome/browser/extensions/api/web_request/upload_data_presenter.cc
@@ -0,0 +1,183 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/web_request/upload_data_presenter.h"
+
+#include "base/base64.h"
+#include "base/file_path.h"
+#include "base/string_util.h"
+#include "base/values.h"
+#include "chrome/browser/extensions/api/web_request/form_data_parser.h"
+#include "net/url_request/url_request.h"
+
+using base::BinaryValue;
+using base::DictionaryValue;
+using base::ListValue;
+using base::StringValue;
+using base::Value;
+
+namespace {
+
+// Takes |dictionary| of <string, list of strings> pairs, and gets the list
+// for |key|, creating it if necessary.
+ListValue* GetOrCreateList(DictionaryValue* dictionary,
+ const std::string& key) {
+ ListValue* list = NULL;
+ if (!dictionary->GetList(key, &list)) {
+ list = new ListValue();
+ dictionary->Set(key, list);
+ }
+ return list;
+}
+
+} // namespace
+
+namespace extensions {
+
+// Implementation of UploadDataPresenter.
+
+UploadDataPresenter::~UploadDataPresenter() {}
+
+// Implementation of ChunkedErrorPresenter.
+
+ChunkedErrorPresenter::ChunkedErrorPresenter(const net::URLRequest* request)
+ : chunks_found_(TransferEncodingChunked(request)) {
+}
+
+ChunkedErrorPresenter::~ChunkedErrorPresenter() {}
+
+// static
+bool ChunkedErrorPresenter::TransferEncodingChunked(
+ const net::URLRequest* request){
+ std::string transfer_encoding;
+ if (!request->extra_request_headers().GetHeader(
+ net::HttpRequestHeaders::kTransferEncoding, &transfer_encoding))
battre 2012/08/16 19:18:03 nit: +4 indent
vabr (Chromium) 2012/08/17 18:29:57 Are you sure? Does the +4 indent rule here apply t
battre 2012/08/20 12:09:38 The reasoning is that the line would usually conti
vabr (Chromium) 2012/08/23 15:41:54 :) I sacrificed one more line to get the headers f
+ return false;
+ return base::strcasecmp(transfer_encoding.c_str(), "chunked") == 0;
+}
+
+void ChunkedErrorPresenter::FeedNext(const net::UploadData::Element& element) {
+ if (chunks_found_)
+ return; // We already found a reason to report an error.
+
+ if (element.type() == net::UploadData::TYPE_CHUNK)
+ chunks_found_ = true;
+}
+
+bool ChunkedErrorPresenter::Succeeded() {
+ return chunks_found_;
battre 2012/08/16 19:18:03 is this correct? Shouldn't this always return true
vabr (Chromium) 2012/08/17 18:29:57 It should only return true if there were some elem
+}
+
+scoped_ptr<Value> ChunkedErrorPresenter::Result() {
+ if (!chunks_found_)
+ return scoped_ptr<Value>();
+
+ scoped_ptr<StringValue> error_string(new StringValue(
+ "Not supported: data is uploaded chunked."));
+ return error_string.PassAs<Value>();
+}
+
+// Implementation of RawDataPresenter.
+
+RawDataPresenter::RawDataPresenter()
+ : success_(true),
+ list_(new base::ListValue) {
+}
+RawDataPresenter::~RawDataPresenter() {}
+
+void RawDataPresenter::FeedNext(const net::UploadData::Element& element) {
+ if (!success_)
+ return;
+
+ if (element.type() == net::UploadData::TYPE_BYTES) {
+ FeedNextBytes(element.bytes());
+ } else if (element.type() == net::UploadData::TYPE_CHUNK) {
+ Abort(); // Chunks are not supported (yet).
+ } else if (element.type() == net::UploadData::TYPE_FILE) {
+ // Insert the file path instead of the contents, which may be too large.
+ FeedNextFile(element.file_path().AsUTF8Unsafe());
+ } // TYPE_BLOB is silently ignored.
battre 2012/08/16 19:18:03 how about: switch (element.type()) { case TYPE_B
battre 2012/08/16 19:18:03 Why silently ignored? Should we not generate a str
vabr (Chromium) 2012/08/17 18:29:57 Good idea.
vabr (Chromium) 2012/08/17 18:29:57 Given the comment at UploadData::Element::SetToBlo
battre 2012/08/20 12:09:38 Add a NOTREACHED()?
vabr (Chromium) 2012/08/23 15:41:54 Well, CL https://chromiumcodereview.appspot.com/10
+}
+
+bool RawDataPresenter::Succeeded() {
+ return success_;
+}
+
+scoped_ptr<Value> RawDataPresenter::Result() {
+ if (!success_)
+ return scoped_ptr<Value>();
+
+ return list_.PassAs<Value>();
+}
+
+void RawDataPresenter::Abort() {
+ success_ = false;
+ list_.reset();
+}
+
+void RawDataPresenter::FeedNextBytes(const std::vector<char>& bytes) {
+ list_->Append(
+ BinaryValue::CreateWithCopiedBuffer(&(bytes[0]), bytes.size()));
+}
+
+void RawDataPresenter::FeedNextFile(const std::string& filename) {
+ // Insert the file path instead of the contents, which may be too large.
+ std::string bytes_encoded;
+ success_ = base::Base64Encode(filename, &bytes_encoded);
battre 2012/08/16 19:18:03 Why do you pass the file path as base64 encoded da
vabr (Chromium) 2012/08/17 18:29:57 I removed the encoding. At some point I saw it tra
+ if (success_)
+ list_->Append(new StringValue(bytes_encoded));
+}
+
+// Implementation of ParsedDataPresenter.
+
+ParsedDataPresenter::ParsedDataPresenter(const net::URLRequest* request)
+ : parser_(FormDataParser::Create(request).release()),
battre 2012/08/16 19:18:03 is this .release() necessary?
vabr (Chromium) 2012/08/17 18:29:57 No :). Removed.
+ success_(parser_.get() != NULL),
+ dictionary_(success_ ? new DictionaryValue() : NULL) {
+}
+
+ParsedDataPresenter::~ParsedDataPresenter() {}
+
+void ParsedDataPresenter::FeedNext(const net::UploadData::Element& element) {
+ if (!success_)
+ return;
+
+ if (element.type() != net::UploadData::TYPE_BYTES) {
+ if (element.type() != net::UploadData::TYPE_FILE) {
+ Abort(); // We do not handle blobs nor chunks.
+ }
+ return; // But we just ignore files.
+ }
+ if (!parser_->SetSource(&(element.bytes()))) {
+ Abort();
+ return;
+ }
+
+ FormDataParser::Result result;
+ while (parser_->GetNextNameValue(&result)) {
+ GetOrCreateList(dictionary_.get(), result.name())->Append(
+ new StringValue(result.value()));
+ }
+}
+
+bool ParsedDataPresenter::Succeeded() {
+ if (success_ && !parser_->AllDataReadOK())
+ Abort();
+ return success_;
+}
+
+scoped_ptr<Value> ParsedDataPresenter::Result() {
+ if (success_)
+ return dictionary_.PassAs<Value>();
battre 2012/08/16 19:18:03 I think this looks wrong. You return the ownership
vabr (Chromium) 2012/08/17 18:29:57 I start with dictionary_, which is a scoped_ptr<Di
battre 2012/08/20 12:09:38 Never mind. I misunderstood your code in web_reque
+ else
+ return scoped_ptr<Value>();
+}
+
+void ParsedDataPresenter::Abort() {
+ success_ = false;
+ dictionary_.reset();
+ parser_.reset();
+}
+
+} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698