15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 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) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/filter/filter.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 85e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h" 90de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#include "net/base/filename_util_unsafe.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/mime_util.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/filter/gzip_filter.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/filter/sdch_filter.h" 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "net/url_request/url_request_context.h" 15c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "url/gurl.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Filter types (using canonical lower case only): 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDeflate[] = "deflate"; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kGZip[] = "gzip"; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kXGZip[] = "x-gzip"; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kSdch[] = "sdch"; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// compress and x-compress are currently not supported. If we decide to support 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// them, we'll need the same mime type compatibility hack we have for gzip. For 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// more information, see Firefox's nsHttpChannel::ProcessNormal. 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Mime types: 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kApplicationXGzip[] = "application/x-gzip"; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kApplicationGzip[] = "application/gzip"; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kApplicationXGunzip[] = "application/x-gunzip"; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kTextHtml[] = "text/html"; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Buffer size allocated when de-compressing data. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kFilterBufSize = 32 * 1024; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FilterContext::~FilterContext() { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Filter::~Filter() {} 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Filter* Filter::Factory(const std::vector<FilterType>& filter_types, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilterContext& filter_context) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (filter_types.empty()) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Filter* filter_list = NULL; // Linked list of filters. 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < filter_types.size(); i++) { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filter_list = PrependNewFilter(filter_types[i], filter_context, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kFilterBufSize, filter_list); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!filter_list) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return filter_list; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Filter* Filter::GZipFactory() { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InitGZipFilter(FILTER_TYPE_GZIP, kFilterBufSize); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Filter* Filter::FactoryForTests(const std::vector<FilterType>& filter_types, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilterContext& filter_context, 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int buffer_size) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (filter_types.empty()) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Filter* filter_list = NULL; // Linked list of filters. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < filter_types.size(); i++) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filter_list = PrependNewFilter(filter_types[i], filter_context, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_size, filter_list); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!filter_list) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return filter_list; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Filter::FilterStatus Filter::ReadData(char* dest_buffer, int* dest_len) { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int dest_buffer_capacity = *dest_len; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (last_status_ == FILTER_ERROR) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return last_status_; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!next_filter_.get()) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return last_status_ = ReadFilteredData(dest_buffer, dest_len); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (last_status_ == FILTER_NEED_MORE_DATA && !stream_data_len()) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return next_filter_->ReadData(dest_buffer, dest_len); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next_filter_->last_status() == FILTER_NEED_MORE_DATA) { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PushDataIntoNextFilter(); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FILTER_ERROR == last_status_) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FILTER_ERROR; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dest_len = dest_buffer_capacity; // Reset the input/output parameter. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_filter_->ReadData(dest_buffer, dest_len); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FILTER_NEED_MORE_DATA == last_status_) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return next_filter_->last_status(); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In the case where this filter has data internally, and is indicating such 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with a last_status_ of FILTER_OK, but at the same time the next filter in 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the chain indicated it FILTER_NEED_MORE_DATA, we have to be cautious 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // about confusing the caller. The API confusion can appear if we return 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FILTER_OK (suggesting we have more data in aggregate), but yet we don't 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // populate our output buffer. When that is the case, we need to 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // alternately call our filter element, and the next_filter element until we 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // get out of this state (by pumping data into the next filter until it 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // outputs data, or it runs out of data and reports that it NEED_MORE_DATA.) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (FILTER_OK == last_status_ && 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILTER_NEED_MORE_DATA == next_filter_->last_status() && 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0 == *dest_len); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next_filter_->last_status() == FILTER_ERROR) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FILTER_ERROR; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FILTER_OK; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Filter::FlushStreamBuffer(int stream_data_len) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(stream_data_len, stream_buffer_size_); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stream_data_len <= 0 || stream_data_len > stream_buffer_size_) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(stream_buffer()); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Bail out if there is more data in the stream buffer to be filtered. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!stream_buffer() || stream_data_len_) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_stream_data_ = stream_buffer()->data(); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_data_len_ = stream_data_len; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Filter::FilterType Filter::ConvertEncodingToType( 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& filter_type) { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilterType type_id; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (LowerCaseEqualsASCII(filter_type, kDeflate)) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type_id = FILTER_TYPE_DEFLATE; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (LowerCaseEqualsASCII(filter_type, kGZip) || 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LowerCaseEqualsASCII(filter_type, kXGZip)) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type_id = FILTER_TYPE_GZIP; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (LowerCaseEqualsASCII(filter_type, kSdch)) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type_id = FILTER_TYPE_SDCH; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note we also consider "identity" and "uncompressed" UNSUPPORTED as 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // filter should be disabled in such cases. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type_id = FILTER_TYPE_UNSUPPORTED; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return type_id; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Filter::FixupEncodingTypes( 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilterContext& filter_context, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<FilterType>* encoding_types) { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string mime_type; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = filter_context.GetMimeType(&mime_type); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(success || mime_type.empty()); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((1 == encoding_types->size()) && 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (FILTER_TYPE_GZIP == encoding_types->front())) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (LowerCaseEqualsASCII(mime_type, kApplicationXGzip) || 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LowerCaseEqualsASCII(mime_type, kApplicationGzip) || 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LowerCaseEqualsASCII(mime_type, kApplicationXGunzip)) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The server has told us that it sent us gziped content with a gzip 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // content encoding. Sadly, Apache mistakenly sets these headers for all 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // .gz files. We match Firefox's nsHttpChannel::ProcessNormal and ignore 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the Content-Encoding here. 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoding_types->clear(); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url; 176effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::string disposition; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = filter_context.GetURL(&url); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(success); 179effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch filter_context.GetContentDisposition(&disposition); 180effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Don't supply a MIME type here, since that may cause disk IO. 1810de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) base::FilePath::StringType extension = 1820de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) GenerateFileExtensionUnsafe(url, disposition, "UTF-8", "", "", ""); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (filter_context.IsDownload()) { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't want to decompress gzipped files when the user explicitly 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // asks to download them. 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For the case of svgz files, we use the extension to distinguish 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // between svgz files and svg files compressed with gzip by the server. 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When viewing a .svgz file, we need to uncompress it, but we don't 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // want to do that when downloading. 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See Firefox's nonDecodableExtensions in nsExternalHelperAppService.cpp 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (EndsWith(extension, FILE_PATH_LITERAL(".gz"), false) || 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LowerCaseEqualsASCII(extension, ".tgz") || 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LowerCaseEqualsASCII(extension, ".svgz")) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoding_types->clear(); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When the user does not explicitly ask to download a file, if we get a 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // supported mime type, then we attempt to decompress in order to view it. 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // However, if it's not a supported mime type, then we will attempt to 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // download it, and in that case, don't decompress .gz/.tgz files. 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((EndsWith(extension, FILE_PATH_LITERAL(".gz"), false) || 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LowerCaseEqualsASCII(extension, ".tgz")) && 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !IsSupportedMimeType(mime_type)) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoding_types->clear(); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the request was for SDCH content, then we might need additional fixups. 2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!filter_context.SdchResponseExpected()) { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It was not an SDCH request, so we'll just record stats. 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (1 < encoding_types->size()) { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Multiple filters were intended to only be used for SDCH (thus far!) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SdchManager::SdchErrorRecovery( 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SdchManager::MULTIENCODING_FOR_NON_SDCH_REQUEST); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((1 == encoding_types->size()) && 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (FILTER_TYPE_SDCH == encoding_types->front())) { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SdchManager::SdchErrorRecovery( 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SdchManager::SDCH_CONTENT_ENCODE_FOR_NON_SDCH_REQUEST); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The request was tagged as an SDCH request, which means the server supplied 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a dictionary, and we advertised it in the request. Some proxies will do 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // very strange things to the request, or the response, so we have to handle 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // them gracefully. 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If content encoding included SDCH, then everything is "relatively" fine. 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!encoding_types->empty() && 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (FILTER_TYPE_SDCH == encoding_types->front())) { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Some proxies (found currently in Argentina) strip the Content-Encoding 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // text from "sdch,gzip" to a mere "sdch" without modifying the compressed 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // payload. To handle this gracefully, we simulate the "probably" deleted 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ",gzip" by appending a tentative gzip decode, which will default to a 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // no-op pass through filter if it doesn't get gzip headers where expected. 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (1 == encoding_types->size()) { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoding_types->push_back(FILTER_TYPE_GZIP_HELPING_SDCH); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SdchManager::SdchErrorRecovery( 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SdchManager::OPTIONAL_GUNZIP_ENCODING_ADDED); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There are now several cases to handle for an SDCH request. Foremost, if 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the outbound request was stripped so as not to advertise support for 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // encodings, we might get back content with no encoding, or (for example) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // just gzip. We have to be sure that any changes we make allow for such 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // minimal coding to work. That issue is why we use TENTATIVE filters if we 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // add any, as those filters sniff the content, and act as pass-through 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // filters if headers are not found. 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the outbound GET is not modified, then the server will generally try to 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // send us SDCH encoded content. As that content returns, there are several 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // corruptions of the header "content-encoding" that proxies may perform (and 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // have been detected in the wild). We already dealt with the a honest 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // content encoding of "sdch,gzip" being corrupted into "sdch" with on change 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the actual content. Another common corruption is to either disscard 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the accurate content encoding, or to replace it with gzip only (again, with 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // no change in actual content). The last observed corruption it to actually 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // change the content, such as by re-gzipping it, and that may happen along 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with corruption of the stated content encoding (wow!). 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The one unresolved failure mode comes when we advertise a dictionary, and 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the server tries to *send* a gzipped file (not gzip encode content), and 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // then we could do a gzip decode :-(. Since SDCH is only (currently) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // supported server side on paths that only send HTML content, this mode has 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // never surfaced in the wild (and is unlikely to). 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We will gather a lot of stats as we perform the fixups 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (StartsWithASCII(mime_type, kTextHtml, false)) { 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Suspicious case: Advertised dictionary, but server didn't use sdch, and 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we're HTML tagged. 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (encoding_types->empty()) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SdchManager::SdchErrorRecovery( 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SdchManager::ADDED_CONTENT_ENCODING); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (1 == encoding_types->size()) { 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SdchManager::SdchErrorRecovery( 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SdchManager::FIXED_CONTENT_ENCODING); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SdchManager::SdchErrorRecovery( 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SdchManager::FIXED_CONTENT_ENCODINGS); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remarkable case!?! We advertised an SDCH dictionary, content-encoding 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // was not marked for SDCH processing: Why did the server suggest an SDCH 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dictionary in the first place??. Also, the content isn't 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tagged as HTML, despite the fact that SDCH encoding is mostly likely for 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // HTML: Did some anti-virus system strip this tag (sometimes they strip 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // accept-encoding headers on the request)?? Does the content encoding not 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // start with "text/html" for some other reason?? We'll report this as a 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fixup to a binary file, but it probably really is text/html (some how). 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (encoding_types->empty()) { 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SdchManager::SdchErrorRecovery( 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SdchManager::BINARY_ADDED_CONTENT_ENCODING); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (1 == encoding_types->size()) { 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SdchManager::SdchErrorRecovery( 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SdchManager::BINARY_FIXED_CONTENT_ENCODING); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SdchManager::SdchErrorRecovery( 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SdchManager::BINARY_FIXED_CONTENT_ENCODINGS); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Leave the existing encoding type to be processed first, and add our 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tentative decodings to be done afterwards. Vodaphone UK reportedyl will 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // perform a second layer of gzip encoding atop the server's sdch,gzip 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // encoding, and then claim that the content encoding is a mere gzip. As a 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // result we'll need (in that case) to do the gunzip, plus our tentative 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // gunzip and tentative SDCH decoding. 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This approach nicely handles the empty() list as well, and should work with 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // other (as yet undiscovered) proxies the choose to re-compressed with some 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // other encoding (such as bzip2, etc.). 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoding_types->insert(encoding_types->begin(), 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILTER_TYPE_GZIP_HELPING_SDCH); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoding_types->insert(encoding_types->begin(), FILTER_TYPE_SDCH_POSSIBLE); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Filter::Filter() 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : stream_buffer_(NULL), 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_buffer_size_(0), 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_stream_data_(NULL), 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_data_len_(0), 3247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) last_status_(FILTER_NEED_MORE_DATA) {} 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Filter::FilterStatus Filter::CopyOut(char* dest_buffer, int* dest_len) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int out_len; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int input_len = *dest_len; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dest_len = 0; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (0 == stream_data_len_) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Filter::FILTER_NEED_MORE_DATA; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out_len = std::min(input_len, stream_data_len_); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(dest_buffer, next_stream_data_, out_len); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dest_len += out_len; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_data_len_ -= out_len; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (0 == stream_data_len_) { 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_stream_data_ = NULL; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Filter::FILTER_NEED_MORE_DATA; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_stream_data_ += out_len; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Filter::FILTER_OK; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Filter* Filter::InitGZipFilter(FilterType type_id, int buffer_size) { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<GZipFilter> gz_filter(new GZipFilter()); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gz_filter->InitBuffer(buffer_size); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gz_filter->InitDecoding(type_id) ? gz_filter.release() : NULL; 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Filter* Filter::InitSdchFilter(FilterType type_id, 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilterContext& filter_context, 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int buffer_size) { 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<SdchFilter> sdch_filter(new SdchFilter(filter_context)); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sdch_filter->InitBuffer(buffer_size); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sdch_filter->InitDecoding(type_id) ? sdch_filter.release() : NULL; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Filter* Filter::PrependNewFilter(FilterType type_id, 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FilterContext& filter_context, 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int buffer_size, 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Filter* filter_list) { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<Filter> first_filter; // Soon to be start of chain. 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type_id) { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FILTER_TYPE_GZIP_HELPING_SDCH: 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FILTER_TYPE_DEFLATE: 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FILTER_TYPE_GZIP: 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_filter.reset(InitGZipFilter(type_id, buffer_size)); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FILTER_TYPE_SDCH: 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case FILTER_TYPE_SDCH_POSSIBLE: 377f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (filter_context.GetURLRequestContext()->sdch_manager() && 378f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SdchManager::sdch_enabled()) { 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) first_filter.reset( 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InitSdchFilter(type_id, filter_context, buffer_size)); 3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!first_filter.get()) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_filter->next_filter_.reset(filter_list); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return first_filter.release(); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Filter::InitBuffer(int buffer_size) { 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!stream_buffer()); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(buffer_size, 0); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_buffer_ = new IOBuffer(buffer_size); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_buffer_size_ = buffer_size; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Filter::PushDataIntoNextFilter() { 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOBuffer* next_buffer = next_filter_->stream_buffer(); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int next_size = next_filter_->stream_buffer_size(); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_status_ = ReadFilteredData(next_buffer->data(), &next_size); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FILTER_ERROR != last_status_) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_filter_->FlushStreamBuffer(next_size); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 410