libyuv r905 with yuv off by 1 fix for valgrind overread
[chromium-blink-merge.git] / chrome_frame / urlmon_upload_data_stream.cc
blob2fe2ed0b71f0d1a26ecbb7380d6b628f330055a3
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.
5 #include "chrome_frame/urlmon_upload_data_stream.h"
7 #include "net/base/io_buffer.h"
8 #include "net/base/net_errors.h"
9 #include "net/base/upload_bytes_element_reader.h"
10 #include "net/base/upload_file_element_reader.h"
12 namespace {
14 // Creates UploadDataStream from UploadData.
15 net::UploadDataStream* CreateUploadDataStream(net::UploadData* upload_data) {
16 net::UploadDataStream* upload_data_stream = NULL;
17 const ScopedVector<net::UploadElement>& elements = upload_data->elements();
19 if (upload_data->is_chunked()) {
20 // Use AppendChunk when data is chunked.
21 upload_data_stream = new net::UploadDataStream(
22 net::UploadDataStream::CHUNKED, upload_data->identifier());
24 for (size_t i = 0; i < elements.size(); ++i) {
25 const net::UploadElement& element = *elements[i];
26 const bool is_last_chunk =
27 i == elements.size() - 1 && upload_data->last_chunk_appended();
28 DCHECK_EQ(net::UploadElement::TYPE_BYTES, element.type());
29 upload_data_stream->AppendChunk(element.bytes(), element.bytes_length(),
30 is_last_chunk);
32 } else {
33 // Not chunked.
34 ScopedVector<net::UploadElementReader> element_readers;
35 for (size_t i = 0; i < elements.size(); ++i) {
36 const net::UploadElement& element = *elements[i];
37 net::UploadElementReader* reader = NULL;
38 switch (element.type()) {
39 case net::UploadElement::TYPE_BYTES:
40 reader = new net::UploadBytesElementReader(element.bytes(),
41 element.bytes_length());
42 break;
43 case net::UploadElement::TYPE_FILE:
44 reader = new net::UploadFileElementReaderSync(
45 element.file_path(),
46 element.file_range_offset(),
47 element.file_range_length(),
48 element.expected_file_modification_time());
49 break;
51 DCHECK(reader);
52 element_readers.push_back(reader);
54 upload_data_stream = new net::UploadDataStream(element_readers.Pass(),
55 upload_data->identifier());
57 return upload_data_stream;
60 } // namespace
62 bool UrlmonUploadDataStream::Initialize(net::UploadData* upload_data) {
63 upload_data_ = upload_data;
64 request_body_stream_.reset(CreateUploadDataStream(upload_data));
65 return request_body_stream_->Init(net::CompletionCallback()) == net::OK;
68 STDMETHODIMP UrlmonUploadDataStream::Read(void* pv, ULONG cb, ULONG* read) {
69 if (pv == NULL) {
70 NOTREACHED();
71 return E_POINTER;
74 // Have we already read past the end of the stream?
75 if (request_body_stream_->IsEOF()) {
76 if (read) {
77 *read = 0;
79 return S_FALSE;
82 // The data in request_body_stream_ can be smaller than 'cb' so it's not
83 // guaranteed that we'll be able to read total_bytes_to_copy bytes.
84 uint64 total_bytes_to_copy = cb;
86 uint64 bytes_copied = 0;
88 char* write_pointer = reinterpret_cast<char*>(pv);
89 while (bytes_copied < total_bytes_to_copy) {
90 size_t bytes_to_copy_now = total_bytes_to_copy - bytes_copied;
92 scoped_refptr<net::IOBufferWithSize> buf(
93 new net::IOBufferWithSize(bytes_to_copy_now));
94 int bytes_read = request_body_stream_->Read(buf, buf->size(),
95 net::CompletionCallback());
96 DCHECK_NE(net::ERR_IO_PENDING, bytes_read);
97 if (bytes_read == 0) // Reached the end of the stream.
98 break;
100 memcpy(write_pointer, buf->data(), bytes_read);
102 // Advance our copy tally
103 bytes_copied += bytes_read;
105 // Advance our write pointer
106 write_pointer += bytes_read;
109 DCHECK_LE(bytes_copied, total_bytes_to_copy);
111 if (read) {
112 *read = static_cast<ULONG>(bytes_copied);
115 return S_OK;
118 STDMETHODIMP UrlmonUploadDataStream::Seek(LARGE_INTEGER move, DWORD origin,
119 ULARGE_INTEGER* new_pos) {
120 // UploadDataStream is really not very seek-able, so for now allow
121 // STREAM_SEEK_SETs to work with a 0 offset, but fail on everything else.
122 if (origin == STREAM_SEEK_SET && move.QuadPart == 0) {
123 if (request_body_stream_->position() != 0) {
124 request_body_stream_.reset(CreateUploadDataStream(upload_data_));
125 const int result = request_body_stream_->Init(net::CompletionCallback());
126 DCHECK_EQ(net::OK, result);
128 if (new_pos) {
129 new_pos->QuadPart = 0;
131 return S_OK;
134 DCHECK(false) << __FUNCTION__;
135 return STG_E_INVALIDFUNCTION;
138 STDMETHODIMP UrlmonUploadDataStream::Stat(STATSTG *stat_stg,
139 DWORD grf_stat_flag) {
140 if (stat_stg == NULL)
141 return E_POINTER;
143 memset(stat_stg, 0, sizeof(STATSTG));
144 if (0 == (grf_stat_flag & STATFLAG_NONAME)) {
145 const wchar_t kStreamBuffer[] = L"PostStream";
146 stat_stg->pwcsName =
147 static_cast<wchar_t*>(::CoTaskMemAlloc(sizeof(kStreamBuffer)));
148 lstrcpy(stat_stg->pwcsName, kStreamBuffer);
150 stat_stg->type = STGTY_STREAM;
151 stat_stg->cbSize.QuadPart = request_body_stream_->size();
152 return S_OK;