1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/net/view_http_cache_job_factory.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/compiler_specific.h" 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h" 93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_util.h" 10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/task.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/url_constants.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_errors.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/url_request/url_request.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/url_request/url_request_context.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/url_request/url_request_simple_job.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/url_request/view_cache_helper.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A job subclass that dumps an HTTP cache entry. 21201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochclass ViewHttpCacheJob : public net::URLRequestJob { 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 2321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen explicit ViewHttpCacheJob(net::URLRequest* request) 2421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen : net::URLRequestJob(request), 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen core_(new Core), 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ALLOW_THIS_IN_INITIALIZER_LIST( 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen callback_(NewCallback(this, 29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &ViewHttpCacheJob::OnStartCompleted))) {} 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void Start(); 323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick virtual void Kill(); 33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual bool GetMimeType(std::string* mime_type) const { 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return core_->GetMimeType(mime_type); 35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual bool GetCharset(std::string* charset) { 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return core_->GetCharset(charset); 38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual bool ReadRawData(net::IOBuffer* buf, int buf_size, int *bytes_read) { 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return core_->ReadRawData(buf, buf_size, bytes_read); 41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen class Core : public base::RefCounted<Core> { 45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public: 46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Core() 47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : data_offset_(0), 48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ALLOW_THIS_IN_INITIALIZER_LIST( 49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen callback_(this, &Core::OnIOComplete)), 50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen user_callback_(NULL) {} 51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int Start(const net::URLRequest& request, Callback0::Type* callback); 53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Prevents it from invoking its callback. It will self-delete. 55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void Orphan() { 56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(user_callback_); 57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen user_callback_ = NULL; 58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool GetMimeType(std::string* mime_type) const; 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool GetCharset(std::string* charset); 62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool ReadRawData(net::IOBuffer* buf, int buf_size, int *bytes_read); 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen private: 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen friend class base::RefCounted<Core>; 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ~Core() {} 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Called when ViewCacheHelper completes the operation. 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void OnIOComplete(int result); 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string data_; 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int data_offset_; 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::ViewCacheHelper cache_helper_; 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::CompletionCallbackImpl<Core> callback_; 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Callback0::Type* user_callback_; 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DISALLOW_COPY_AND_ASSIGN(Core); 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }; 80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ~ViewHttpCacheJob() {} 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void StartAsync(); 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void OnStartCompleted(); 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_refptr<Core> core_; 87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ScopedRunnableMethodFactory<ViewHttpCacheJob> method_factory_; 88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<Callback0::Type> callback_; 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DISALLOW_COPY_AND_ASSIGN(ViewHttpCacheJob); 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ViewHttpCacheJob::Start() { 94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MessageLoop::current()->PostTask( 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FROM_HERE, 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen method_factory_.NewRunnableMethod(&ViewHttpCacheJob::StartAsync)); 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ViewHttpCacheJob::Kill() { 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen method_factory_.RevokeAll(); 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen core_->Orphan(); 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen core_ = NULL; 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::URLRequestJob::Kill(); 104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ViewHttpCacheJob::StartAsync() { 107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(request()); 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!request()) 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int rv = core_->Start(*request(), callback_.get()); 113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (rv != net::ERR_IO_PENDING) { 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(net::OK, rv); 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnStartCompleted(); 116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ViewHttpCacheJob::OnStartCompleted() { 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NotifyHeadersComplete(); 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint ViewHttpCacheJob::Core::Start(const net::URLRequest& request, 124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Callback0::Type* callback) { 125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(callback); 126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(!user_callback_); 127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick AddRef(); // Released on OnIOComplete(). 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string cache_key = 130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen request.url().spec().substr(strlen(chrome::kNetworkViewCacheURL)); 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int rv; 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (cache_key.empty()) { 134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen rv = cache_helper_.GetContentsHTML(request.context(), 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chrome::kNetworkViewCacheURL, &data_, 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &callback_); 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen rv = cache_helper_.GetEntryInfoHTML(cache_key, request.context(), 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &data_, &callback_); 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (rv == net::ERR_IO_PENDING) 143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen user_callback_ = callback; 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return rv; 1463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ViewHttpCacheJob::Core::GetMimeType(std::string* mime_type) const { 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mime_type->assign("text/html"); 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ViewHttpCacheJob::Core::GetCharset(std::string* charset) { 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch charset->assign("UTF-8"); 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ViewHttpCacheJob::Core::ReadRawData(net::IOBuffer* buf, 159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int buf_size, 160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int* bytes_read) { 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(bytes_read); 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int remaining = static_cast<int>(data_.size()) - data_offset_; 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (buf_size > remaining) 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch buf_size = remaining; 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(buf->data(), data_.data() + data_offset_, buf_size); 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_offset_ += buf_size; 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *bytes_read = buf_size; 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ViewHttpCacheJob::Core::OnIOComplete(int result) { 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(net::OK, result); 1733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (user_callback_) 175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen user_callback_->Run(); 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We may be holding the last reference to this job. Do not access |this| 178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // after Release(). 179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Release(); // Acquired on Start(). 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace. 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Static. 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ViewHttpCacheJobFactory::IsSupportedURL(const GURL& url) { 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return StartsWithASCII(url.spec(), chrome::kNetworkViewCacheURL, 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch true /*case_sensitive*/); 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Static. 19121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsennet::URLRequestJob* ViewHttpCacheJobFactory::CreateJobForRequest( 19221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen net::URLRequest* request) { 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return new ViewHttpCacheJob(request); 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 195