| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/loader/certificate_resource_handler.h" |
| |
| #include "base/strings/string_util.h" |
| #include "content/browser/loader/resource_request_info_impl.h" |
| #include "content/public/browser/content_browser_client.h" |
| #include "content/public/common/resource_response.h" |
| #include "net/base/io_buffer.h" |
| #include "net/base/mime_sniffer.h" |
| #include "net/base/mime_util.h" |
| #include "net/http/http_response_headers.h" |
| #include "net/url_request/redirect_info.h" |
| #include "net/url_request/url_request.h" |
| #include "net/url_request/url_request_status.h" |
| |
| namespace content { |
| |
| CertificateResourceHandler::CertificateResourceHandler( |
| net::URLRequest* request) |
| : ResourceHandler(request), |
| content_length_(0), |
| read_buffer_(NULL), |
| resource_buffer_(NULL), |
| cert_type_(net::CERTIFICATE_MIME_TYPE_UNKNOWN) { |
| } |
| |
| CertificateResourceHandler::~CertificateResourceHandler() { |
| } |
| |
| bool CertificateResourceHandler::OnUploadProgress(uint64 position, |
| uint64 size) { |
| return true; |
| } |
| |
| bool CertificateResourceHandler::OnRequestRedirected( |
| const net::RedirectInfo& redirect_info, |
| ResourceResponse* resp, |
| bool* defer) { |
| return true; |
| } |
| |
| bool CertificateResourceHandler::OnResponseStarted(ResourceResponse* resp, |
| bool* defer) { |
| cert_type_ = net::GetCertificateMimeTypeForMimeType(resp->head.mime_type); |
| return cert_type_ != net::CERTIFICATE_MIME_TYPE_UNKNOWN; |
| } |
| |
| bool CertificateResourceHandler::OnWillStart(const GURL& url, bool* defer) { |
| return true; |
| } |
| |
| bool CertificateResourceHandler::OnBeforeNetworkStart(const GURL& url, |
| bool* defer) { |
| return true; |
| } |
| |
| bool CertificateResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, |
| int* buf_size, |
| int min_size) { |
| static const int kReadBufSize = 32768; |
| |
| // TODO(gauravsh): Should we use 'min_size' here? |
| DCHECK(buf && buf_size); |
| if (!read_buffer_.get()) { |
| read_buffer_ = new net::IOBuffer(kReadBufSize); |
| } |
| *buf = read_buffer_.get(); |
| *buf_size = kReadBufSize; |
| |
| return true; |
| } |
| |
| bool CertificateResourceHandler::OnReadCompleted(int bytes_read, bool* defer) { |
| if (!bytes_read) |
| return true; |
| |
| // We have more data to read. |
| DCHECK(read_buffer_.get()); |
| content_length_ += bytes_read; |
| |
| // Release the ownership of the buffer, and store a reference |
| // to it. A new one will be allocated in OnWillRead(). |
| scoped_refptr<net::IOBuffer> buffer; |
| read_buffer_.swap(buffer); |
| // TODO(gauravsh): Should this be handled by a separate thread? |
| buffer_.push_back(std::make_pair(buffer, bytes_read)); |
| |
| return true; |
| } |
| |
| void CertificateResourceHandler::OnResponseCompleted( |
| const net::URLRequestStatus& urs, |
| const std::string& sec_info, |
| bool* defer) { |
| if (urs.status() != net::URLRequestStatus::SUCCESS) |
| return; |
| |
| AssembleResource(); |
| |
| const void* content_bytes = NULL; |
| if (resource_buffer_.get()) |
| content_bytes = resource_buffer_->data(); |
| |
| // Note that it's up to the browser to verify that the certificate |
| // data is well-formed. |
| const ResourceRequestInfo* info = GetRequestInfo(); |
| GetContentClient()->browser()->AddCertificate( |
| cert_type_, content_bytes, content_length_, |
| info->GetChildID(), info->GetRenderFrameID()); |
| } |
| |
| void CertificateResourceHandler::AssembleResource() { |
| // 0-length IOBuffers are not allowed. |
| if (content_length_ == 0) { |
| resource_buffer_ = NULL; |
| return; |
| } |
| |
| // Create the new buffer. |
| resource_buffer_ = new net::IOBuffer(content_length_); |
| |
| // Copy the data into it. |
| size_t bytes_copied = 0; |
| for (size_t i = 0; i < buffer_.size(); ++i) { |
| net::IOBuffer* data = buffer_[i].first.get(); |
| size_t data_len = buffer_[i].second; |
| DCHECK(data != NULL); |
| DCHECK_LE(bytes_copied + data_len, content_length_); |
| memcpy(resource_buffer_->data() + bytes_copied, data->data(), data_len); |
| bytes_copied += data_len; |
| } |
| DCHECK_EQ(content_length_, bytes_copied); |
| } |
| |
| void CertificateResourceHandler::OnDataDownloaded(int bytes_downloaded) { |
| NOTREACHED(); |
| } |
| |
| } // namespace content |