| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright 2016 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 "net/filter/brotli_stream_source.h" | 
|  | 6 | 
|  | 7 #include "base/bind.h" | 
|  | 8 #include "base/bit_cast.h" | 
|  | 9 #include "base/metrics/histogram_macros.h" | 
|  | 10 #include "net/filter/block_buffer.h" | 
|  | 11 | 
|  | 12 namespace net { | 
|  | 13 | 
|  | 14 BrotliStreamSource::BrotliStreamSource(scoped_ptr<StreamSource> previous) | 
|  | 15     : StreamSource(StreamSource::SOURCE_BROTLI, std::move(previous)), | 
|  | 16       decoding_status_(DecodingStatus::DECODING_IN_PROGRESS), | 
|  | 17       used_memory_(0), | 
|  | 18       used_memory_maximum_(0), | 
|  | 19       produced_bytes_(0), | 
|  | 20       consumed_bytes_(0) { | 
|  | 21   brotli_state_ = BrotliCreateState(AllocateMemory, FreeMemory, this); | 
|  | 22   CHECK(brotli_state_); | 
|  | 23 } | 
|  | 24 | 
|  | 25 BrotliStreamSource::~BrotliStreamSource() { | 
|  | 26   BrotliDestroyState(brotli_state_); | 
|  | 27   brotli_state_ = nullptr; | 
|  | 28   DCHECK(used_memory_ == 0); | 
|  | 29 | 
|  | 30   UMA_HISTOGRAM_ENUMERATION( | 
|  | 31       "BrotliStreamSource.Status", static_cast<int>(decoding_status_), | 
|  | 32       static_cast<int>(DecodingStatus::DECODING_STATUS_COUNT)); | 
|  | 33   if (decoding_status_ == DecodingStatus::DECODING_DONE) { | 
|  | 34     // CompressionPercent is undefined when there is no output produced. | 
|  | 35     if (produced_bytes_ != 0) { | 
|  | 36       UMA_HISTOGRAM_PERCENTAGE( | 
|  | 37           "BrotliStreamSource.CompressionPercent", | 
|  | 38           static_cast<int>((consumed_bytes_ * 100) / produced_bytes_)); | 
|  | 39     } | 
|  | 40   } | 
|  | 41   // All code here is for gathering stats, and can be removed when | 
|  | 42   // BrotliStreamSource is considered stable. | 
|  | 43   static const int kBuckets = 48; | 
|  | 44   static const int64_t kMaxKb = 1 << (kBuckets / 3);  // 64MiB in KiB | 
|  | 45   UMA_HISTOGRAM_CUSTOM_COUNTS("BrotliStreamSource.UsedMemoryKB", | 
|  | 46                               used_memory_maximum_ / 1024, 1, kMaxKb, kBuckets); | 
|  | 47 } | 
|  | 48 | 
|  | 49 Error BrotliStreamSource::ReadInternal(IOBuffer* dest_buffer, | 
|  | 50                                        size_t dest_buffer_size, | 
|  | 51                                        size_t* bytes_read) { | 
|  | 52   const uint8_t* next_in = bit_cast<uint8_t*>(buffer_->bytes()); | 
|  | 53   size_t available_in = buffer_->bytes_left(); | 
|  | 54   uint8_t* next_out = bit_cast<uint8_t*>(dest_buffer->data()); | 
|  | 55   size_t available_out = dest_buffer_size; | 
|  | 56   size_t total_out = 0; | 
|  | 57   BrotliResult result = | 
|  | 58       BrotliDecompressStream(&available_in, &next_in, &available_out, &next_out, | 
|  | 59                              &total_out, brotli_state_); | 
|  | 60 | 
|  | 61   size_t bytes_used = buffer_->bytes_left() - available_in; | 
|  | 62   size_t bytes_written = dest_buffer_size - available_out; | 
|  | 63   CHECK_GE(bytes_used, 0u); | 
|  | 64   CHECK_GE(bytes_written, 0u); | 
|  | 65   *bytes_read = bytes_written; | 
|  | 66   produced_bytes_ += bytes_written; | 
|  | 67   consumed_bytes_ += bytes_used; | 
|  | 68 | 
|  | 69   buffer_->WasDrained(bytes_used); | 
|  | 70 | 
|  | 71   switch (result) { | 
|  | 72     case BROTLI_RESULT_NEEDS_MORE_OUTPUT: | 
|  | 73     // Fall through. | 
|  | 74     case BROTLI_RESULT_SUCCESS: | 
|  | 75       decoding_status_ = DecodingStatus::DECODING_DONE; | 
|  | 76       return OK; | 
|  | 77     case BROTLI_RESULT_NEEDS_MORE_INPUT: | 
|  | 78       decoding_status_ = DecodingStatus::DECODING_IN_PROGRESS; | 
|  | 79       if (bytes_written > 0) { | 
|  | 80         return OK; | 
|  | 81       } | 
|  | 82       break; | 
|  | 83     // If the decompressor threw an error, fail synchronously. | 
|  | 84     default: | 
|  | 85       decoding_status_ = DecodingStatus::DECODING_ERROR; | 
|  | 86       return ERR_CONTENT_DECODING_FAILED; | 
|  | 87   } | 
|  | 88 | 
|  | 89   DCHECK_EQ(BROTLI_RESULT_NEEDS_MORE_INPUT, result); | 
|  | 90 | 
|  | 91   // Since Decompress needs more input, it has consumed all existing input. | 
|  | 92   DCHECK(!buffer_->HasMoreBytes()); | 
|  | 93 | 
|  | 94   return OK; | 
|  | 95 } | 
|  | 96 | 
|  | 97 void* BrotliStreamSource::AllocateMemory(void* opaque, size_t size) { | 
|  | 98   BrotliStreamSource* filter = reinterpret_cast<BrotliStreamSource*>(opaque); | 
|  | 99   return filter->AllocateMemoryInternal(size); | 
|  | 100 } | 
|  | 101 | 
|  | 102 void BrotliStreamSource::FreeMemory(void* opaque, void* address) { | 
|  | 103   BrotliStreamSource* filter = reinterpret_cast<BrotliStreamSource*>(opaque); | 
|  | 104   filter->FreeMemoryInternal(address); | 
|  | 105 } | 
|  | 106 | 
|  | 107 void* BrotliStreamSource::AllocateMemoryInternal(size_t size) { | 
|  | 108   size_t* array = reinterpret_cast<size_t*>(malloc(size + sizeof(size_t))); | 
|  | 109   if (!array) | 
|  | 110     return nullptr; | 
|  | 111   used_memory_ += size; | 
|  | 112   if (used_memory_maximum_ < used_memory_) | 
|  | 113     used_memory_maximum_ = used_memory_; | 
|  | 114   array[0] = size; | 
|  | 115   return &array[1]; | 
|  | 116 } | 
|  | 117 | 
|  | 118 void BrotliStreamSource::FreeMemoryInternal(void* address) { | 
|  | 119   if (!address) | 
|  | 120     return; | 
|  | 121   size_t* array = reinterpret_cast<size_t*>(address); | 
|  | 122   used_memory_ -= array[-1]; | 
|  | 123   free(&array[-1]); | 
|  | 124 } | 
|  | 125 | 
|  | 126 }  // namespace net | 
| OLD | NEW | 
|---|