15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 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) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/loader/certificate_resource_handler.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/loader/resource_request_info_impl.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/content_browser_client.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/resource_response.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/mime_sniffer.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/mime_util.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_status.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CertificateResourceHandler::CertificateResourceHandler( 2168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) net::URLRequest* request) 224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : ResourceHandler(request), 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content_length_(0), 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_(NULL), 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resource_buffer_(NULL), 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cert_type_(net::CERTIFICATE_MIME_TYPE_UNKNOWN) { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CertificateResourceHandler::~CertificateResourceHandler() { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CertificateResourceHandler::OnUploadProgress(int request_id, 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint64 position, 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint64 size) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CertificateResourceHandler::OnRequestRedirected(int request_id, 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& url, 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ResourceResponse* resp, 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* defer) { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_ = url; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CertificateResourceHandler::OnResponseStarted(int request_id, 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ResourceResponse* resp, 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* defer) { 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cert_type_ = net::GetCertificateMimeTypeForMimeType(resp->head.mime_type); 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return cert_type_ != net::CERTIFICATE_MIME_TYPE_UNKNOWN; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CertificateResourceHandler::OnWillStart(int request_id, 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& url, 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* defer) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CertificateResourceHandler::OnWillRead(int request_id, 604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scoped_refptr<net::IOBuffer>* buf, 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int* buf_size, 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int min_size) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kReadBufSize = 32768; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(gauravsh): Should we use 'min_size' here? 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(buf && buf_size); 67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!read_buffer_.get()) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_ = new net::IOBuffer(kReadBufSize); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *buf = read_buffer_.get(); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *buf_size = kReadBufSize; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CertificateResourceHandler::OnReadCompleted(int request_id, 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int bytes_read, 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* defer) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!bytes_read) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have more data to read. 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(read_buffer_.get()); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content_length_ += bytes_read; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release the ownership of the buffer, and store a reference 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to it. A new one will be allocated in OnWillRead(). 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::IOBuffer* buffer = NULL; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_buffer_.swap(&buffer); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(gauravsh): Should this be handled by a separate thread? 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_.push_back(std::make_pair(buffer, bytes_read)); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void CertificateResourceHandler::OnResponseCompleted( 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int request_id, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& urs, 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& sec_info, 100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool* defer) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (urs.status() != net::URLRequestStatus::SUCCESS) 102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AssembleResource(); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const void* content_bytes = NULL; 107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (resource_buffer_.get()) 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content_bytes = resource_buffer_->data(); 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Note that it's up to the browser to verify that the certificate 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // data is well-formed. 1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const ResourceRequestInfo* info = GetRequestInfo(); 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetContentClient()->browser()->AddCertificate( 1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) request(), cert_type_, content_bytes, content_length_, 11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) info->GetChildID(), info->GetRouteID()); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CertificateResourceHandler::AssembleResource() { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 0-length IOBuffers are not allowed. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (content_length_ == 0) { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resource_buffer_ = NULL; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the new buffer. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resource_buffer_ = new net::IOBuffer(content_length_); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copy the data into it. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bytes_copied = 0; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < buffer_.size(); ++i) { 131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) net::IOBuffer* data = buffer_[i].first.get(); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t data_len = buffer_[i].second; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(data != NULL); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(bytes_copied + data_len, content_length_); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(resource_buffer_->data() + bytes_copied, data->data(), data_len); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_copied += data_len; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(content_length_, bytes_copied); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CertificateResourceHandler::OnDataDownloaded( 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int request_id, 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int bytes_downloaded) { 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 148