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