15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome_frame/urlmon_upload_data_stream.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/upload_bytes_element_reader.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/upload_file_element_reader.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Creates UploadDataStream from UploadData. 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)net::UploadDataStream* CreateUploadDataStream(net::UploadData* upload_data) { 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::UploadDataStream* upload_data_stream = NULL; 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ScopedVector<net::UploadElement>& elements = upload_data->elements(); 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (upload_data->is_chunked()) { 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Use AppendChunk when data is chunked. 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) upload_data_stream = new net::UploadDataStream( 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::UploadDataStream::CHUNKED, upload_data->identifier()); 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < elements.size(); ++i) { 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const net::UploadElement& element = *elements[i]; 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const bool is_last_chunk = 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) i == elements.size() - 1 && upload_data->last_chunk_appended(); 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(net::UploadElement::TYPE_BYTES, element.type()); 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) upload_data_stream->AppendChunk(element.bytes(), element.bytes_length(), 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_last_chunk); 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Not chunked. 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScopedVector<net::UploadElementReader> element_readers; 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < elements.size(); ++i) { 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const net::UploadElement& element = *elements[i]; 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::UploadElementReader* reader = NULL; 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (element.type()) { 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case net::UploadElement::TYPE_BYTES: 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reader = new net::UploadBytesElementReader(element.bytes(), 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) element.bytes_length()); 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case net::UploadElement::TYPE_FILE: 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reader = new net::UploadFileElementReaderSync( 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) element.file_path(), 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) element.file_range_offset(), 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) element.file_range_length(), 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) element.expected_file_modification_time()); 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(reader); 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) element_readers.push_back(reader); 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) upload_data_stream = new net::UploadDataStream(element_readers.Pass(), 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) upload_data->identifier()); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return upload_data_stream; 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool UrlmonUploadDataStream::Initialize(net::UploadData* upload_data) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) upload_data_ = upload_data; 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_body_stream_.reset(CreateUploadDataStream(upload_data)); 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return request_body_stream_->Init(net::CompletionCallback()) == net::OK; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)STDMETHODIMP UrlmonUploadDataStream::Read(void* pv, ULONG cb, ULONG* read) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pv == NULL) { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return E_POINTER; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Have we already read past the end of the stream? 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request_body_stream_->IsEOF()) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (read) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *read = 0; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return S_FALSE; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The data in request_body_stream_ can be smaller than 'cb' so it's not 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // guaranteed that we'll be able to read total_bytes_to_copy bytes. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 total_bytes_to_copy = cb; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 bytes_copied = 0; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* write_pointer = reinterpret_cast<char*>(pv); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (bytes_copied < total_bytes_to_copy) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bytes_to_copy_now = total_bytes_to_copy - bytes_copied; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<net::IOBufferWithSize> buf( 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new net::IOBufferWithSize(bytes_to_copy_now)); 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int bytes_read = request_body_stream_->Read(buf, buf->size(), 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::CompletionCallback()); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_NE(net::ERR_IO_PENDING, bytes_read); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes_read == 0) // Reached the end of the stream. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(write_pointer, buf->data(), bytes_read); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Advance our copy tally 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_copied += bytes_read; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Advance our write pointer 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write_pointer += bytes_read; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(bytes_copied, total_bytes_to_copy); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (read) { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *read = static_cast<ULONG>(bytes_copied); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return S_OK; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)STDMETHODIMP UrlmonUploadDataStream::Seek(LARGE_INTEGER move, DWORD origin, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULARGE_INTEGER* new_pos) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // UploadDataStream is really not very seek-able, so for now allow 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // STREAM_SEEK_SETs to work with a 0 offset, but fail on everything else. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (origin == STREAM_SEEK_SET && move.QuadPart == 0) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request_body_stream_->position() != 0) { 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) request_body_stream_.reset(CreateUploadDataStream(upload_data_)); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int result = request_body_stream_->Init(net::CompletionCallback()); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(net::OK, result); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_pos) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_pos->QuadPart = 0; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return S_OK; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(false) << __FUNCTION__; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return STG_E_INVALIDFUNCTION; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)STDMETHODIMP UrlmonUploadDataStream::Stat(STATSTG *stat_stg, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD grf_stat_flag) { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stat_stg == NULL) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return E_POINTER; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(stat_stg, 0, sizeof(STATSTG)); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (0 == (grf_stat_flag & STATFLAG_NONAME)) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const wchar_t kStreamBuffer[] = L"PostStream"; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stat_stg->pwcsName = 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<wchar_t*>(::CoTaskMemAlloc(sizeof(kStreamBuffer))); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lstrcpy(stat_stg->pwcsName, kStreamBuffer); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stat_stg->type = STGTY_STREAM; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stat_stg->cbSize.QuadPart = request_body_stream_->size(); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return S_OK; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 154