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)        callback_(base::Bind(&ViewHttpCacheJob::OnStartCompleted,
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             base::Unretained(this))),
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        weak_factory_(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::Closure callback_;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::WeakPtrFactory<ViewHttpCacheJob> weak_factory_;
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ViewHttpCacheJob);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViewHttpCacheJob::Start() {
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop::current()->PostTask(
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&ViewHttpCacheJob::StartAsync, weak_factory_.GetWeakPtr()));
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViewHttpCacheJob::Kill() {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  weak_factory_.InvalidateWeakPtrs();
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (core_.get()) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core_->Orphan();
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core_ = NULL;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::URLRequestJob::Kill();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViewHttpCacheJob::StartAsync() {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(request());
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!request())
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = core_->Start(*request(), callback_);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != net::ERR_IO_PENDING) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(net::OK, rv);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnStartCompleted();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViewHttpCacheJob::OnStartCompleted() {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotifyHeadersComplete();
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ViewHttpCacheJob::Core::Start(const net::URLRequest& request,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const base::Closure& callback) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_callback_.is_null());
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddRef();  // Released on OnIOComplete().
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string cache_key =
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request.url().spec().substr(strlen(kChromeUINetworkViewCacheURL));
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cache_key.empty()) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = cache_helper_.GetContentsHTML(request.context(),
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       kChromeUINetworkViewCacheURL,
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       &data_, callback_);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = cache_helper_.GetEntryInfoHTML(cache_key, request.context(),
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        &data_, callback_);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == net::ERR_IO_PENDING)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_callback_ = callback;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ViewHttpCacheJob::Core::GetMimeType(std::string* mime_type) const {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mime_type->assign("text/html");
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ViewHttpCacheJob::Core::GetCharset(std::string* charset) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  charset->assign("UTF-8");
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ViewHttpCacheJob::Core::ReadRawData(net::IOBuffer* buf,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         int buf_size,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         int* bytes_read) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(bytes_read);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int remaining = static_cast<int>(data_.size()) - data_offset_;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (buf_size > remaining)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buf_size = remaining;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(buf->data(), data_.data() + data_offset_, buf_size);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_offset_ += buf_size;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *bytes_read = buf_size;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViewHttpCacheJob::Core::OnIOComplete(int result) {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(net::OK, result);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!user_callback_.is_null())
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_callback_.Run();
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We may be holding the last reference to this job. Do not access |this|
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // after Release().
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Release();  // Acquired on Start().
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Static.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ViewHttpCacheJobFactory::IsSupportedURL(const GURL& url) {
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return url.SchemeIs(kChromeUIScheme) &&
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         url.host() == kChromeUINetworkViewCacheHost;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Static.
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)net::URLRequestJob* ViewHttpCacheJobFactory::CreateJobForRequest(
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request, net::NetworkDelegate* network_delegate) {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ViewHttpCacheJob(request, network_delegate);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
205