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