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