view_http_cache_job_factory.cc revision 9ab5563a3196760eb381d102cbb2bc0f7abc6a50
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)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/net/view_http_cache_job_factory.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h"
129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/url_constants.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/completion_callback.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_simple_job.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/view_cache_helper.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A job subclass that dumps an HTTP cache entry.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ViewHttpCacheJob : public net::URLRequestJob {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ViewHttpCacheJob(net::URLRequest* request,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   net::NetworkDelegate* network_delegate)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : net::URLRequestJob(request, network_delegate),
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        core_(new Core),
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        weak_factory_(this),
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        callback_(base::Bind(&ViewHttpCacheJob::OnStartCompleted,
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             base::Unretained(this))) {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // net::URLRequestJob implementation.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Start() OVERRIDE;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Kill() OVERRIDE;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool GetMimeType(std::string* mime_type) const OVERRIDE{
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return core_->GetMimeType(mime_type);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool GetCharset(std::string* charset) OVERRIDE{
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return core_->GetCharset(charset);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool ReadRawData(net::IOBuffer* buf,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int buf_size, int *bytes_read) OVERRIDE{
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return core_->ReadRawData(buf, buf_size, bytes_read);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class Core : public base::RefCounted<Core> {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Core()
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : data_offset_(0),
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          callback_(base::Bind(&Core::OnIOComplete, this)) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int Start(const net::URLRequest& request, const base::Closure& callback);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Prevents it from invoking its callback. It will self-delete.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void Orphan() {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      user_callback_.Reset();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool GetMimeType(std::string* mime_type) const;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool GetCharset(std::string* charset);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool ReadRawData(net::IOBuffer* buf, int buf_size, int *bytes_read);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    friend class base::RefCounted<Core>;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~Core() {}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Called when ViewCacheHelper completes the operation.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void OnIOComplete(int result);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string data_;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int data_offset_;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::ViewCacheHelper cache_helper_;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::CompletionCallback callback_;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Closure user_callback_;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(Core);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~ViewHttpCacheJob() {}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartAsync();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnStartCompleted();
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Core> core_;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<ViewHttpCacheJob> weak_factory_;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Closure callback_;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ViewHttpCacheJob);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViewHttpCacheJob::Start() {
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop::current()->PostTask(
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&ViewHttpCacheJob::StartAsync, weak_factory_.GetWeakPtr()));
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViewHttpCacheJob::Kill() {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  weak_factory_.InvalidateWeakPtrs();
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (core_.get()) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core_->Orphan();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core_ = NULL;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::URLRequestJob::Kill();
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViewHttpCacheJob::StartAsync() {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(request());
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!request())
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = core_->Start(*request(), callback_);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != net::ERR_IO_PENDING) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(net::OK, rv);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnStartCompleted();
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViewHttpCacheJob::OnStartCompleted() {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotifyHeadersComplete();
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ViewHttpCacheJob::Core::Start(const net::URLRequest& request,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const base::Closure& callback) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_callback_.is_null());
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddRef();  // Released on OnIOComplete().
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string cache_key =
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request.url().spec().substr(strlen(kChromeUINetworkViewCacheURL));
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cache_key.empty()) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = cache_helper_.GetContentsHTML(request.context(),
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       kChromeUINetworkViewCacheURL,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       &data_, callback_);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = cache_helper_.GetEntryInfoHTML(cache_key, request.context(),
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        &data_, callback_);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == net::ERR_IO_PENDING)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_callback_ = callback;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ViewHttpCacheJob::Core::GetMimeType(std::string* mime_type) const {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mime_type->assign("text/html");
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ViewHttpCacheJob::Core::GetCharset(std::string* charset) {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  charset->assign("UTF-8");
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ViewHttpCacheJob::Core::ReadRawData(net::IOBuffer* buf,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         int buf_size,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         int* bytes_read) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(bytes_read);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int remaining = static_cast<int>(data_.size()) - data_offset_;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (buf_size > remaining)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buf_size = remaining;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(buf->data(), data_.data() + data_offset_, buf_size);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_offset_ += buf_size;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *bytes_read = buf_size;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViewHttpCacheJob::Core::OnIOComplete(int result) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(net::OK, result);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!user_callback_.is_null())
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_callback_.Run();
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We may be holding the last reference to this job. Do not access |this|
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // after Release().
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Release();  // Acquired on Start().
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace.
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Static.
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ViewHttpCacheJobFactory::IsSupportedURL(const GURL& url) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return url.SchemeIs(chrome::kChromeUIScheme) &&
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         url.host() == kChromeUINetworkViewCacheHost;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Static.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)net::URLRequestJob* ViewHttpCacheJobFactory::CreateJobForRequest(
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request, net::NetworkDelegate* network_delegate) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ViewHttpCacheJob(request, network_delegate);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
204