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. 4 5#include "content/browser/loader/certificate_resource_handler.h" 6 7#include "base/strings/string_util.h" 8#include "content/browser/loader/resource_request_info_impl.h" 9#include "content/public/browser/content_browser_client.h" 10#include "content/public/common/resource_response.h" 11#include "net/base/io_buffer.h" 12#include "net/base/mime_sniffer.h" 13#include "net/base/mime_util.h" 14#include "net/http/http_response_headers.h" 15#include "net/url_request/redirect_info.h" 16#include "net/url_request/url_request.h" 17#include "net/url_request/url_request_status.h" 18 19namespace content { 20 21CertificateResourceHandler::CertificateResourceHandler( 22 net::URLRequest* request) 23 : ResourceHandler(request), 24 content_length_(0), 25 read_buffer_(NULL), 26 resource_buffer_(NULL), 27 cert_type_(net::CERTIFICATE_MIME_TYPE_UNKNOWN) { 28} 29 30CertificateResourceHandler::~CertificateResourceHandler() { 31} 32 33bool CertificateResourceHandler::OnUploadProgress(uint64 position, 34 uint64 size) { 35 return true; 36} 37 38bool CertificateResourceHandler::OnRequestRedirected( 39 const net::RedirectInfo& redirect_info, 40 ResourceResponse* resp, 41 bool* defer) { 42 return true; 43} 44 45bool CertificateResourceHandler::OnResponseStarted(ResourceResponse* resp, 46 bool* defer) { 47 cert_type_ = net::GetCertificateMimeTypeForMimeType(resp->head.mime_type); 48 return cert_type_ != net::CERTIFICATE_MIME_TYPE_UNKNOWN; 49} 50 51bool CertificateResourceHandler::OnWillStart(const GURL& url, bool* defer) { 52 return true; 53} 54 55bool CertificateResourceHandler::OnBeforeNetworkStart(const GURL& url, 56 bool* defer) { 57 return true; 58} 59 60bool CertificateResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, 61 int* buf_size, 62 int min_size) { 63 static const int kReadBufSize = 32768; 64 65 // TODO(gauravsh): Should we use 'min_size' here? 66 DCHECK(buf && buf_size); 67 if (!read_buffer_.get()) { 68 read_buffer_ = new net::IOBuffer(kReadBufSize); 69 } 70 *buf = read_buffer_.get(); 71 *buf_size = kReadBufSize; 72 73 return true; 74} 75 76bool CertificateResourceHandler::OnReadCompleted(int bytes_read, bool* defer) { 77 if (!bytes_read) 78 return true; 79 80 // We have more data to read. 81 DCHECK(read_buffer_.get()); 82 content_length_ += bytes_read; 83 84 // Release the ownership of the buffer, and store a reference 85 // to it. A new one will be allocated in OnWillRead(). 86 scoped_refptr<net::IOBuffer> buffer; 87 read_buffer_.swap(buffer); 88 // TODO(gauravsh): Should this be handled by a separate thread? 89 buffer_.push_back(std::make_pair(buffer, bytes_read)); 90 91 return true; 92} 93 94void CertificateResourceHandler::OnResponseCompleted( 95 const net::URLRequestStatus& urs, 96 const std::string& sec_info, 97 bool* defer) { 98 if (urs.status() != net::URLRequestStatus::SUCCESS) 99 return; 100 101 AssembleResource(); 102 103 const void* content_bytes = NULL; 104 if (resource_buffer_.get()) 105 content_bytes = resource_buffer_->data(); 106 107 // Note that it's up to the browser to verify that the certificate 108 // data is well-formed. 109 const ResourceRequestInfo* info = GetRequestInfo(); 110 GetContentClient()->browser()->AddCertificate( 111 cert_type_, content_bytes, content_length_, 112 info->GetChildID(), info->GetRenderFrameID()); 113} 114 115void CertificateResourceHandler::AssembleResource() { 116 // 0-length IOBuffers are not allowed. 117 if (content_length_ == 0) { 118 resource_buffer_ = NULL; 119 return; 120 } 121 122 // Create the new buffer. 123 resource_buffer_ = new net::IOBuffer(content_length_); 124 125 // Copy the data into it. 126 size_t bytes_copied = 0; 127 for (size_t i = 0; i < buffer_.size(); ++i) { 128 net::IOBuffer* data = buffer_[i].first.get(); 129 size_t data_len = buffer_[i].second; 130 DCHECK(data != NULL); 131 DCHECK_LE(bytes_copied + data_len, content_length_); 132 memcpy(resource_buffer_->data() + bytes_copied, data->data(), data_len); 133 bytes_copied += data_len; 134 } 135 DCHECK_EQ(content_length_, bytes_copied); 136} 137 138void CertificateResourceHandler::OnDataDownloaded(int bytes_downloaded) { 139 NOTREACHED(); 140} 141 142} // namespace content 143