summaryrefslogtreecommitdiffstats
path: root/content/browser/appcache
diff options
context:
space:
mode:
authorJoe Downing <joedow@google.com>2015-08-10 13:39:12 -0700
committerJoe Downing <joedow@google.com>2015-08-10 20:42:08 +0000
commit3fd8c3abf1d1216a3370e2765b9318504f9f1d91 (patch)
treeccf8fd8b0e75cb58af616a960cc77ddce995c660 /content/browser/appcache
parentae7209aeafdcb56f6761aeffe27f992fe2571a04 (diff)
downloadchromium_src-3fd8c3abf1d1216a3370e2765b9318504f9f1d91.zip
chromium_src-3fd8c3abf1d1216a3370e2765b9318504f9f1d91.tar.gz
chromium_src-3fd8c3abf1d1216a3370e2765b9318504f9f1d91.tar.bz2
Revert "Implements "chrome://appcache-internals" based on WebUI API"
This reverts commit 8fc82b21621f21ea8d2d8cb483cb14295d1f6e1f. BUG=518954 R=ekaramad@chromium.org Review URL: https://codereview.chromium.org/1283843003 . Cr-Commit-Position: refs/heads/master@{#342689}
Diffstat (limited to 'content/browser/appcache')
-rw-r--r--content/browser/appcache/appcache_internals_ui.cc510
-rw-r--r--content/browser/appcache/appcache_internals_ui.h129
-rw-r--r--content/browser/appcache/appcache_service_impl.cc3
-rw-r--r--content/browser/appcache/appcache_service_impl.h7
-rw-r--r--content/browser/appcache/view_appcache_internals_job.cc668
-rw-r--r--content/browser/appcache/view_appcache_internals_job.h32
6 files changed, 701 insertions, 648 deletions
diff --git a/content/browser/appcache/appcache_internals_ui.cc b/content/browser/appcache/appcache_internals_ui.cc
deleted file mode 100644
index a9409d5..0000000
--- a/content/browser/appcache/appcache_internals_ui.cc
+++ /dev/null
@@ -1,510 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/appcache/appcache_internals_ui.h"
-
-#include <iostream>
-#include <sstream>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/platform_thread.h"
-#include "base/values.h"
-#include "content/browser/appcache/appcache.h"
-#include "content/browser/appcache/appcache_response.h"
-#include "content/browser/storage_partition_impl.h"
-#include "content/grit/content_resources.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/web_ui.h"
-#include "content/public/browser/web_ui_data_source.h"
-#include "content/public/common/url_constants.h"
-#include "net/base/escape.h"
-#include "net/http/http_response_headers.h"
-#include "net/url_request/view_cache_helper.h"
-
-namespace content {
-
-namespace {
-const char kRequestGetAllAppCacheInfo[] = "getAllAppCache";
-const char kRequestDeleteAppCache[] = "deleteAppCache";
-const char kRequestGetAppCacheDetails[] = "getAppCacheDetails";
-const char kRequestGetFileDetails[] = "getFileDetails";
-
-const char kFunctionOnAllAppCacheInfoReady[] =
- "appcache.onAllAppCacheInfoReady";
-const char kFunctionOnAppCacheInfoDeleted[] = "appcache.onAppCacheInfoDeleted";
-const char kFunctionOnAppCacheDetailsReady[] =
- "appcache.onAppCacheDetailsReady";
-const char kFunctionOnFileDetailsReady[] = "appcache.onFileDetailsReady";
-const char kFunctionOnFileDetailsFailed[] = "appcache.onFileDetailsFailed";
-
-int64 ToInt64(const std::string& str) {
- int64 i = 0;
- base::StringToInt64(str.c_str(), &i);
- return i;
-}
-
-bool SortByResourceUrl(const AppCacheResourceInfo& lhs,
- const AppCacheResourceInfo& rhs) {
- return lhs.url.spec() < rhs.url.spec();
-}
-
-scoped_ptr<base::DictionaryValue> GetDictionaryValueForResponseEnquiry(
- const content::AppCacheInternalsUI::Proxy::ResponseEnquiry&
- response_enquiry) {
- scoped_ptr<base::DictionaryValue> dict_value(new base::DictionaryValue());
- dict_value->SetString("manifestURL", response_enquiry.manifest_url);
- dict_value->SetString("groupId",
- base::Int64ToString(response_enquiry.group_id));
- dict_value->SetString("responseId",
- base::Int64ToString(response_enquiry.response_id));
- return dict_value;
-}
-
-scoped_ptr<base::DictionaryValue> GetDictionaryValueForAppCacheInfo(
- const content::AppCacheInfo& appcache_info) {
- scoped_ptr<base::DictionaryValue> dict_value(new base::DictionaryValue());
- dict_value->SetString("manifestURL", appcache_info.manifest_url.spec());
- dict_value->SetDouble("creationTime", appcache_info.creation_time.ToJsTime());
- dict_value->SetDouble("lastUpdateTime",
- appcache_info.last_update_time.ToJsTime());
- dict_value->SetDouble("lastAccessTime",
- appcache_info.last_access_time.ToJsTime());
- dict_value->SetString(
- "size",
- base::UTF16ToUTF8(base::FormatBytesUnlocalized(appcache_info.size)));
- dict_value->SetString("groupId", base::Int64ToString(appcache_info.group_id));
-
- return dict_value;
-}
-
-scoped_ptr<base::ListValue> GetListValueForAppCacheInfoVector(
- const AppCacheInfoVector& appcache_info_vector) {
- scoped_ptr<base::ListValue> list(new base::ListValue());
- for (const AppCacheInfo& info : appcache_info_vector)
- list->Append(GetDictionaryValueForAppCacheInfo(info));
- return list;
-}
-
-scoped_ptr<base::ListValue> GetListValueFromAppCacheInfoCollection(
- AppCacheInfoCollection* appcache_collection) {
- scoped_ptr<base::ListValue> list(new base::ListValue());
- for (const auto& key_value : appcache_collection->infos_by_origin) {
- base::DictionaryValue* dict = new base::DictionaryValue;
- dict->SetString("originURL", key_value.first.spec());
- dict->Set("manifests", GetListValueForAppCacheInfoVector(key_value.second));
- list->Append(scoped_ptr<base::Value>(dict));
- }
- return list;
-}
-
-scoped_ptr<base::DictionaryValue> GetDictionaryValueForAppCacheResourceInfo(
- const AppCacheResourceInfo& resource_info) {
- scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
- dict->Set("url", scoped_ptr<base::StringValue>(
- new base::StringValue(resource_info.url.spec())));
- dict->Set(
- "size",
- scoped_ptr<base::StringValue>(new base::StringValue(base::UTF16ToUTF8(
- base::FormatBytesUnlocalized(resource_info.size)))));
- dict->SetString("responseId", base::Int64ToString(resource_info.response_id));
- dict->SetBoolean("isExplicit", resource_info.is_explicit);
- dict->SetBoolean("isManifest", resource_info.is_manifest);
- dict->SetBoolean("isMaster", resource_info.is_master);
- dict->SetBoolean("isFallback", resource_info.is_fallback);
- dict->SetBoolean("isIntercept", resource_info.is_intercept);
- dict->SetBoolean("isForeign", resource_info.is_foreign);
-
- return dict;
-}
-
-scoped_ptr<base::ListValue> GetListValueForAppCacheResourceInfoVector(
- AppCacheResourceInfoVector* resource_info_vector) {
- scoped_ptr<base::ListValue> list(new base::ListValue);
- for (const AppCacheResourceInfo& res_info : *resource_info_vector)
- list->Append(GetDictionaryValueForAppCacheResourceInfo(res_info));
- return list;
-}
-
-} // namespace
-
-AppCacheInternalsUI::Proxy::Proxy(
- base::WeakPtr<AppCacheInternalsUI> appcache_internals_ui,
- const base::FilePath& partition_path)
- : appcache_internals_ui_(appcache_internals_ui),
- partition_path_(partition_path) {}
-
-void AppCacheInternalsUI::Proxy::Initialize(
- const scoped_refptr<ChromeAppCacheService>& chrome_appcache_service) {
- if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&Proxy::Initialize, this, chrome_appcache_service));
- return;
- }
- appcache_service_ = chrome_appcache_service->AsWeakPtr();
- shutdown_called_ = false;
- preparing_response_ = false;
-}
-
-AppCacheInternalsUI::Proxy::~Proxy() {
- DCHECK(shutdown_called_);
-}
-
-void AppCacheInternalsUI::Proxy::Shutdown() {
- if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&Proxy::Shutdown, this));
- return;
- }
- shutdown_called_ = true;
- if (appcache_service_) {
- appcache_service_->storage()->CancelDelegateCallbacks(this);
- appcache_service_.reset();
- response_enquiries_.clear();
- }
-}
-
-void AppCacheInternalsUI::Proxy::RequestAllAppCacheInfo() {
- if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&Proxy::RequestAllAppCacheInfo, this));
- return;
- }
- if (appcache_service_) {
- scoped_refptr<AppCacheInfoCollection> collection(
- new AppCacheInfoCollection());
- appcache_service_->GetAllAppCacheInfo(
- collection.get(),
- base::Bind(&Proxy::OnAllAppCacheInfoReady, this, collection));
- }
-}
-
-void AppCacheInternalsUI::Proxy::OnAllAppCacheInfoReady(
- scoped_refptr<AppCacheInfoCollection> collection,
- int net_result_code) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&AppCacheInternalsUI::OnAllAppCacheInfoReady,
- appcache_internals_ui_, collection, partition_path_));
-}
-
-void AppCacheInternalsUI::Proxy::DeleteAppCache(
- const std::string& manifest_url) {
- if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&Proxy::DeleteAppCache, this, manifest_url));
- return;
- }
- if (appcache_service_) {
- appcache_service_->DeleteAppCacheGroup(
- GURL(manifest_url),
- base::Bind(&Proxy::OnAppCacheInfoDeleted, this, manifest_url));
- }
-}
-
-void AppCacheInternalsUI::Proxy::OnAppCacheInfoDeleted(
- const std::string& manifest_url,
- int net_result_code) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&AppCacheInternalsUI::OnAppCacheInfoDeleted,
- appcache_internals_ui_, partition_path_, manifest_url,
- net_result_code == net::OK));
-}
-
-void AppCacheInternalsUI::Proxy::RequestAppCacheDetails(
- const std::string& manifest_url) {
- if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&Proxy::RequestAppCacheDetails, this, manifest_url));
- return;
- }
-
- if (appcache_service_)
- appcache_service_->storage()->LoadOrCreateGroup(GURL(manifest_url), this);
-}
-
-void AppCacheInternalsUI::Proxy::OnGroupLoaded(AppCacheGroup* appcache_group,
- const GURL& manifest_gurl) {
- scoped_ptr<AppCacheResourceInfoVector> resource_info_vector;
- if (appcache_group && appcache_group->newest_complete_cache()) {
- resource_info_vector.reset(new AppCacheResourceInfoVector);
- appcache_group->newest_complete_cache()->ToResourceInfoVector(
- resource_info_vector.get());
- std::sort(resource_info_vector->begin(), resource_info_vector->end(),
- SortByResourceUrl);
- }
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&AppCacheInternalsUI::OnAppCacheDetailsReady,
- appcache_internals_ui_, partition_path_, manifest_gurl.spec(),
- base::Passed(&resource_info_vector)));
-}
-
-void AppCacheInternalsUI::Proxy::RequestFileDetails(
- const ResponseEnquiry& response_enquiry) {
- if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&Proxy::RequestFileDetails, this, response_enquiry));
- return;
- }
- DCHECK(!shutdown_called_);
- response_enquiries_.push_back(response_enquiry);
- HandleFileDetailsRequest();
-}
-
-void AppCacheInternalsUI::Proxy::HandleFileDetailsRequest() {
- if (preparing_response_ || !response_enquiries_.size() || !appcache_service_)
- return;
- preparing_response_ = true;
- appcache_service_->storage()->LoadResponseInfo(
- GURL(response_enquiries_.front().manifest_url),
- response_enquiries_.front().group_id,
- response_enquiries_.front().response_id, this);
-}
-
-void AppCacheInternalsUI::Proxy::OnResponseInfoLoaded(
- AppCacheResponseInfo* response,
- int64 response_id) {
- if (shutdown_called_)
- return;
- if (!appcache_service_)
- return;
- ResponseEnquiry response_enquiry = response_enquiries_.front();
- response_enquiries_.pop_front();
- if (response) {
- scoped_refptr<AppCacheResponseInfo> response_info = response;
- const int64 kLimit = 100 * 1000;
- int64 amount_to_read =
- std::min(kLimit, response_info->response_data_size());
- scoped_refptr<net::IOBuffer> response_data(new net::IOBuffer(
- base::CheckedNumeric<size_t>(amount_to_read).ValueOrDie()));
- scoped_ptr<AppCacheResponseReader> reader(
- appcache_service_->storage()->CreateResponseReader(
- GURL(response_enquiry.manifest_url), response_enquiry.group_id,
- response_enquiry.response_id));
-
- reader->ReadData(
- response_data.get(), amount_to_read,
- base::Bind(&Proxy::OnResponseDataReadComplete, this, response_enquiry,
- response_info, base::Passed(&reader), response_data));
- } else {
- OnResponseDataReadComplete(response_enquiry, nullptr, nullptr, nullptr, -1);
- }
-}
-
-void AppCacheInternalsUI::Proxy::OnResponseDataReadComplete(
- const ResponseEnquiry& response_enquiry,
- scoped_refptr<AppCacheResponseInfo> response_info,
- scoped_ptr<AppCacheResponseReader> reader,
- scoped_refptr<net::IOBuffer> response_data,
- int net_result_code) {
- if (shutdown_called_)
- return;
- if (!response_info || net_result_code < 0) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&AppCacheInternalsUI::OnFileDetailsFailed,
- appcache_internals_ui_, response_enquiry, net_result_code));
- } else {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&AppCacheInternalsUI::OnFileDetailsReady,
- appcache_internals_ui_, response_enquiry, response_info,
- response_data, net_result_code));
- }
- preparing_response_ = false;
- HandleFileDetailsRequest();
-}
-
-AppCacheInternalsUI::AppCacheInternalsUI(WebUI* web_ui)
- : WebUIController(web_ui), weak_ptr_factory_(this) {
- web_ui->RegisterMessageCallback(
- kRequestGetAllAppCacheInfo,
- base::Bind(&AppCacheInternalsUI::GetAllAppCache, AsWeakPtr()));
-
- web_ui->RegisterMessageCallback(
- kRequestDeleteAppCache,
- base::Bind(&AppCacheInternalsUI::DeleteAppCache, AsWeakPtr()));
-
- web_ui->RegisterMessageCallback(
- kRequestGetAppCacheDetails,
- base::Bind(&AppCacheInternalsUI::GetAppCacheDetails, AsWeakPtr()));
-
- web_ui->RegisterMessageCallback(
- kRequestGetFileDetails,
- base::Bind(&AppCacheInternalsUI::GetFileDetails, AsWeakPtr()));
-
- WebUIDataSource* source =
- WebUIDataSource::Create(kChromeUIAppCacheInternalsHost);
-
- source->SetJsonPath("strings.js");
- source->AddResourcePath("appcache_internals.js", IDR_APPCACHE_INTERNALS_JS);
- source->AddResourcePath("appcache_internals.css", IDR_APPCACHE_INTERNALS_CSS);
- source->SetDefaultResource(IDR_APPCACHE_INTERNALS_HTML);
-
- WebUIDataSource::Add(browser_context(), source);
-
- BrowserContext::StoragePartitionCallback callback =
- base::Bind(&AppCacheInternalsUI::CreateProxyForPartition, AsWeakPtr());
- BrowserContext::ForEachStoragePartition(browser_context(), callback);
-}
-
-AppCacheInternalsUI::~AppCacheInternalsUI() {
- for (auto& proxy : appcache_proxies_)
- proxy->Shutdown();
-}
-
-void AppCacheInternalsUI::CreateProxyForPartition(
- StoragePartition* storage_partition) {
- scoped_refptr<Proxy> proxy =
- new Proxy(weak_ptr_factory_.GetWeakPtr(), storage_partition->GetPath());
- proxy->Initialize(static_cast<StoragePartitionImpl*>(storage_partition)
- ->GetAppCacheService());
- appcache_proxies_.push_back(proxy);
-}
-
-void AppCacheInternalsUI::GetAllAppCache(const base::ListValue* args) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- for (scoped_refptr<Proxy>& proxy : appcache_proxies_)
- proxy->RequestAllAppCacheInfo();
-}
-
-void AppCacheInternalsUI::DeleteAppCache(const base::ListValue* args) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- std::string manifest_url, partition_path;
- args->GetString(0, &partition_path);
- args->GetString(1, &manifest_url);
- Proxy* proxy =
- GetProxyForPartitionPath(base::FilePath::FromUTF8Unsafe(partition_path));
- if (proxy)
- proxy->DeleteAppCache(manifest_url);
-}
-
-void AppCacheInternalsUI::GetAppCacheDetails(const base::ListValue* args) {
- std::string manifest_url, partition_path;
- args->GetString(0, &partition_path);
- args->GetString(1, &manifest_url);
- Proxy* proxy =
- GetProxyForPartitionPath(base::FilePath::FromUTF8Unsafe(partition_path));
- if (proxy)
- proxy->RequestAppCacheDetails(manifest_url);
-}
-
-void AppCacheInternalsUI::GetFileDetails(const base::ListValue* args) {
- std::string manifest_url, partition_path, group_id_str, response_id_str;
- args->GetString(0, &partition_path);
- args->GetString(1, &manifest_url);
- args->GetString(2, &group_id_str);
- args->GetString(3, &response_id_str);
- Proxy* proxy =
- GetProxyForPartitionPath(base::FilePath::FromUTF8Unsafe(partition_path));
- if (proxy)
- proxy->RequestFileDetails(
- {manifest_url, ToInt64(group_id_str), ToInt64(response_id_str)});
-}
-
-void AppCacheInternalsUI::OnAllAppCacheInfoReady(
- scoped_refptr<AppCacheInfoCollection> collection,
- const base::FilePath& partition_path) {
- web_ui()->CallJavascriptFunction(
- kFunctionOnAllAppCacheInfoReady,
- base::StringValue(partition_path.AsUTF8Unsafe()),
- *GetListValueFromAppCacheInfoCollection(collection.get()));
-}
-
-void AppCacheInternalsUI::OnAppCacheInfoDeleted(
- const base::FilePath& partition_path,
- const std::string& manifest_url,
- bool deleted) {
- web_ui()->CallJavascriptFunction(
- kFunctionOnAppCacheInfoDeleted,
- base::StringValue(partition_path.AsUTF8Unsafe()),
- base::StringValue(manifest_url), base::FundamentalValue(deleted));
-}
-
-void AppCacheInternalsUI::OnAppCacheDetailsReady(
- const base::FilePath& partition_path,
- const std::string& manifest_url,
- scoped_ptr<AppCacheResourceInfoVector> resource_info_vector) {
- if (resource_info_vector) {
- web_ui()->CallJavascriptFunction(
- kFunctionOnAppCacheDetailsReady, base::StringValue(manifest_url),
- base::StringValue(partition_path.AsUTF8Unsafe()),
- *GetListValueForAppCacheResourceInfoVector(resource_info_vector.get()));
- } else {
- web_ui()->CallJavascriptFunction(
- kFunctionOnAppCacheDetailsReady, base::StringValue(manifest_url),
- base::StringValue(partition_path.AsUTF8Unsafe()));
- }
-}
-
-void AppCacheInternalsUI::OnFileDetailsReady(
- const Proxy::ResponseEnquiry& response_enquiry,
- scoped_refptr<AppCacheResponseInfo> response_info,
- scoped_refptr<net::IOBuffer> response_data,
- int data_length) {
- std::string headers;
- if (response_info->http_response_info()) {
- headers.append("<hr><pre>");
- headers.append(net::EscapeForHTML(
- response_info->http_response_info()->headers->GetStatusLine()));
- headers.push_back('\n');
-
- void* iter = nullptr;
- std::string name, value;
- while (response_info->http_response_info()->headers->EnumerateHeaderLines(
- &iter, &name, &value)) {
- headers.append(net::EscapeForHTML(name));
- headers.append(": ");
- headers.append(net::EscapeForHTML(value));
- headers.push_back('\n');
- }
- headers.append("</pre>");
- } else {
- headers.append("Failed to read response headers. <br>");
- }
- std::string hex_dump = base::StringPrintf(
- "<hr><pre> Showing %d of %d bytes\n\n", static_cast<int>(data_length),
- static_cast<int>(response_info->response_data_size()));
- net::ViewCacheHelper::HexDump(response_data->data(), data_length, &hex_dump);
- if (data_length < response_info->response_data_size())
- hex_dump.append("\nNote: data is truncated...");
- hex_dump.append("</pre>");
- web_ui()->CallJavascriptFunction(
- kFunctionOnFileDetailsReady,
- *GetDictionaryValueForResponseEnquiry(response_enquiry),
- base::StringValue(headers), base::StringValue(hex_dump));
-}
-
-void AppCacheInternalsUI::OnFileDetailsFailed(
- const Proxy::ResponseEnquiry& response_enquiry,
- int net_result_code) {
- web_ui()->CallJavascriptFunction(
- kFunctionOnFileDetailsFailed,
- *GetDictionaryValueForResponseEnquiry(response_enquiry),
- base::FundamentalValue(net_result_code));
-}
-
-AppCacheInternalsUI::Proxy* AppCacheInternalsUI::GetProxyForPartitionPath(
- const base::FilePath& partition_path) {
- for (const scoped_refptr<Proxy>& proxy : appcache_proxies_) {
- if (proxy->partition_path_ == partition_path)
- return proxy.get();
- }
- NOTREACHED();
- return nullptr;
-}
-
-} // namespace content
diff --git a/content/browser/appcache/appcache_internals_ui.h b/content/browser/appcache/appcache_internals_ui.h
deleted file mode 100644
index 3b2ddfa..0000000
--- a/content/browser/appcache/appcache_internals_ui.h
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_APPCACHE_APPCACHE_INTERNALS_UI_H_
-#define CONTENT_BROWSER_APPCACHE_APPCACHE_INTERNALS_UI_H_
-
-#include <list>
-
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/browser/appcache/appcache_group.h"
-#include "content/browser/appcache/appcache_storage.h"
-#include "content/browser/appcache/chrome_appcache_service.h"
-#include "content/public/browser/storage_partition.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_ui_controller.h"
-#include "net/base/io_buffer.h"
-
-namespace base {
-class ListValue;
-class FilePath;
-}
-
-namespace content {
-
-// The implementation for the chrome://appcache-internals page.
-// This implementation is based on the WebUI API and consists of a controller on
-// The UI thread which communicates (through a Proxy) with the AppCacheService
-// and AppCache storage which live on the IO thread.
-class AppCacheInternalsUI : public WebUIController {
- public:
- explicit AppCacheInternalsUI(WebUI* web_ui);
- ~AppCacheInternalsUI() override;
-
- class Proxy : public AppCacheStorage::Delegate,
- public base::RefCountedThreadSafe<Proxy> {
- public:
- friend class AppCacheInternalsUI;
-
- struct ResponseEnquiry {
- std::string manifest_url;
- int64 group_id;
- int64 response_id;
- };
-
- private:
- friend class base::RefCountedThreadSafe<Proxy>;
-
- Proxy(base::WeakPtr<AppCacheInternalsUI> appcache_internals_ui,
- const base::FilePath& storage_partition);
- ~Proxy() override;
-
- void RequestAllAppCacheInfo();
- void DeleteAppCache(const std::string& manifest_url);
- void RequestAppCacheDetails(const std::string& manifest_url);
- void RequestFileDetails(const ResponseEnquiry& response_enquiry);
- void HandleFileDetailsRequest();
- void OnAllAppCacheInfoReady(
- scoped_refptr<AppCacheInfoCollection> collection,
- int net_result_code);
- void OnAppCacheInfoDeleted(const std::string& manifest_url,
- int net_result_code);
- void OnGroupLoaded(AppCacheGroup* appcache_group,
- const GURL& manifest_gurl) override;
- void OnResponseInfoLoaded(AppCacheResponseInfo* response_info,
- int64 response_id) override;
- void OnResponseDataReadComplete(
- const ResponseEnquiry& response_enquiry,
- scoped_refptr<AppCacheResponseInfo> response_info,
- scoped_ptr<AppCacheResponseReader> reader,
- scoped_refptr<net::IOBuffer> response_data,
- int net_result_code);
- void Initialize(
- const scoped_refptr<ChromeAppCacheService>& chrome_appcache_service);
- void Shutdown();
-
- base::WeakPtr<AppCacheInternalsUI> appcache_internals_ui_;
- base::WeakPtr<AppCacheServiceImpl> appcache_service_;
- AppCacheStorage* appcache_storage_;
- base::FilePath partition_path_;
- scoped_refptr<AppCacheStorageReference> disabled_appcache_storage_ref_;
- std::list<ResponseEnquiry> response_enquiries_;
- bool preparing_response_;
- bool shutdown_called_;
- };
-
- base::WeakPtr<AppCacheInternalsUI> AsWeakPtr() {
- return weak_ptr_factory_.GetWeakPtr();
- }
-
- private:
- void CreateProxyForPartition(StoragePartition* storage_partition);
- // Commands from Javascript side.
- void GetAllAppCache(const base::ListValue* args);
- void DeleteAppCache(const base::ListValue* args);
- void GetAppCacheDetails(const base::ListValue* args);
- void GetFileDetails(const base::ListValue* args);
-
- // Results from commands to be sent to Javascript.
- void OnAllAppCacheInfoReady(scoped_refptr<AppCacheInfoCollection> collection,
- const base::FilePath& partition_path);
- void OnAppCacheInfoDeleted(const base::FilePath& partition_path,
- const std::string& manifest_url,
- bool deleted);
- void OnAppCacheDetailsReady(
- const base::FilePath& partition_path,
- const std::string& manifest_url,
- scoped_ptr<AppCacheResourceInfoVector> resource_info_vector);
- void OnFileDetailsReady(const Proxy::ResponseEnquiry& response_enquiry,
- scoped_refptr<AppCacheResponseInfo> response_info,
- scoped_refptr<net::IOBuffer> response_data,
- int data_length);
- void OnFileDetailsFailed(const Proxy::ResponseEnquiry& response_enquiry,
- int data_length);
-
- BrowserContext* browser_context() {
- return web_ui()->GetWebContents()->GetBrowserContext();
- }
-
- Proxy* GetProxyForPartitionPath(const base::FilePath& path);
- std::list<scoped_refptr<Proxy>> appcache_proxies_;
- base::WeakPtrFactory<AppCacheInternalsUI> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(AppCacheInternalsUI);
-};
-
-} // namespace content
-#endif
diff --git a/content/browser/appcache/appcache_service_impl.cc b/content/browser/appcache/appcache_service_impl.cc
index 01cbb46..47e81a4 100644
--- a/content/browser/appcache/appcache_service_impl.cc
+++ b/content/browser/appcache/appcache_service_impl.cc
@@ -448,8 +448,7 @@ AppCacheServiceImpl::AppCacheServiceImpl(
handler_factory_(NULL),
quota_manager_proxy_(quota_manager_proxy),
request_context_(NULL),
- force_keep_session_state_(false),
- weak_factory_(this) {
+ force_keep_session_state_(false) {
if (quota_manager_proxy_.get()) {
quota_client_ = new AppCacheQuotaClient(this);
quota_manager_proxy_->RegisterClient(quota_client_);
diff --git a/content/browser/appcache/appcache_service_impl.h b/content/browser/appcache/appcache_service_impl.h
index 8ec839e..07d89cc 100644
--- a/content/browser/appcache/appcache_service_impl.h
+++ b/content/browser/appcache/appcache_service_impl.h
@@ -172,10 +172,6 @@ class CONTENT_EXPORT AppCacheServiceImpl
AppCacheStorage* storage() const { return storage_.get(); }
- base::WeakPtr<AppCacheServiceImpl> AsWeakPtr() {
- return weak_factory_.GetWeakPtr();
- }
-
// Disables the exit-time deletion of session-only data.
void set_force_keep_session_state() { force_keep_session_state_ = true; }
bool force_keep_session_state() const { return force_keep_session_state_; }
@@ -218,9 +214,6 @@ class CONTENT_EXPORT AppCacheServiceImpl
base::OneShotTimer<AppCacheServiceImpl> reinit_timer_;
base::ObserverList<Observer> observers_;
- private:
- base::WeakPtrFactory<AppCacheServiceImpl> weak_factory_;
-
DISALLOW_COPY_AND_ASSIGN(AppCacheServiceImpl);
};
diff --git a/content/browser/appcache/view_appcache_internals_job.cc b/content/browser/appcache/view_appcache_internals_job.cc
new file mode 100644
index 0000000..f7a814a
--- /dev/null
+++ b/content/browser/appcache/view_appcache_internals_job.cc
@@ -0,0 +1,668 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/appcache/view_appcache_internals_job.h"
+
+#include <algorithm>
+#include <string>
+
+#include "base/base64.h"
+#include "base/bind.h"
+#include "base/format_macros.h"
+#include "base/i18n/time_formatting.h"
+#include "base/logging.h"
+#include "base/memory/weak_ptr.h"
+#include "base/numerics/safe_math.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/browser/appcache/appcache.h"
+#include "content/browser/appcache/appcache_group.h"
+#include "content/browser/appcache/appcache_policy.h"
+#include "content/browser/appcache/appcache_response.h"
+#include "content/browser/appcache/appcache_service_impl.h"
+#include "content/browser/appcache/appcache_storage.h"
+#include "net/base/escape.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/http/http_response_headers.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_simple_job.h"
+#include "net/url_request/view_cache_helper.h"
+
+namespace content {
+namespace {
+
+const char kErrorMessage[] = "Error in retrieving Application Caches.";
+const char kEmptyAppCachesMessage[] = "No available Application Caches.";
+const char kManifestNotFoundMessage[] = "Manifest not found.";
+const char kManifest[] = "Manifest: ";
+const char kSize[] = "Size: ";
+const char kCreationTime[] = "Creation Time: ";
+const char kLastAccessTime[] = "Last Access Time: ";
+const char kLastUpdateTime[] = "Last Update Time: ";
+const char kFormattedDisabledAppCacheMsg[] =
+ "<b><i><font color=\"FF0000\">"
+ "This Application Cache is disabled by policy.</font></i></b><br/>";
+const char kRemoveCacheLabel[] = "Remove";
+const char kViewCacheLabel[] = "View Entries";
+const char kRemoveCacheCommand[] = "remove-cache";
+const char kViewCacheCommand[] = "view-cache";
+const char kViewEntryCommand[] = "view-entry";
+
+void EmitPageStart(std::string* out) {
+ out->append(
+ "<!DOCTYPE HTML>\n"
+ "<html><title>AppCache Internals</title>\n"
+ "<meta http-equiv=\"Content-Security-Policy\""
+ " content=\"object-src 'none'; script-src 'none'\">\n"
+ "<style>\n"
+ "body { font-family: sans-serif; font-size: 0.8em; }\n"
+ "tt, code, pre { font-family: WebKitHack, monospace; }\n"
+ "form { display: inline; }\n"
+ ".subsection_body { margin: 10px 0 10px 2em; }\n"
+ ".subsection_title { font-weight: bold; }\n"
+ "</style>\n"
+ "</head><body>\n");
+}
+
+void EmitPageEnd(std::string* out) {
+ out->append("</body></html>\n");
+}
+
+void EmitListItem(const std::string& label,
+ const std::string& data,
+ std::string* out) {
+ out->append("<li>");
+ out->append(net::EscapeForHTML(label));
+ out->append(net::EscapeForHTML(data));
+ out->append("</li>\n");
+}
+
+void EmitAnchor(const std::string& url, const std::string& text,
+ std::string* out) {
+ out->append("<a href=\"");
+ out->append(net::EscapeForHTML(url));
+ out->append("\">");
+ out->append(net::EscapeForHTML(text));
+ out->append("</a>");
+}
+
+void EmitCommandAnchor(const char* label,
+ const GURL& base_url,
+ const char* command,
+ const char* param,
+ std::string* out) {
+ std::string query(command);
+ query.push_back('=');
+ query.append(param);
+ GURL::Replacements replacements;
+ replacements.SetQuery(query.data(), url::Component(0, query.length()));
+ GURL command_url = base_url.ReplaceComponents(replacements);
+ EmitAnchor(command_url.spec(), label, out);
+}
+
+void EmitAppCacheInfo(const GURL& base_url,
+ AppCacheServiceImpl* service,
+ const AppCacheInfo* info,
+ std::string* out) {
+ std::string manifest_url_base64;
+ base::Base64Encode(info->manifest_url.spec(), &manifest_url_base64);
+
+ out->append("\n<p>");
+ out->append(kManifest);
+ EmitAnchor(info->manifest_url.spec(), info->manifest_url.spec(), out);
+ out->append("<br/>\n");
+ if (!service->appcache_policy()->CanLoadAppCache(
+ info->manifest_url, info->manifest_url)) {
+ out->append(kFormattedDisabledAppCacheMsg);
+ }
+ out->append("\n<br/>\n");
+ EmitCommandAnchor(kRemoveCacheLabel, base_url,
+ kRemoveCacheCommand, manifest_url_base64.c_str(), out);
+ out->append("&nbsp;&nbsp;");
+ EmitCommandAnchor(kViewCacheLabel, base_url,
+ kViewCacheCommand, manifest_url_base64.c_str(), out);
+ out->append("\n<br/>\n");
+ out->append("<ul>");
+ EmitListItem(
+ kSize,
+ base::UTF16ToUTF8(base::FormatBytesUnlocalized(info->size)),
+ out);
+ EmitListItem(
+ kCreationTime,
+ base::UTF16ToUTF8(TimeFormatFriendlyDateAndTime(info->creation_time)),
+ out);
+ EmitListItem(
+ kLastUpdateTime,
+ base::UTF16ToUTF8(TimeFormatFriendlyDateAndTime(info->last_update_time)),
+ out);
+ EmitListItem(
+ kLastAccessTime,
+ base::UTF16ToUTF8(TimeFormatFriendlyDateAndTime(info->last_access_time)),
+ out);
+ out->append("</ul></p></br>\n");
+}
+
+void EmitAppCacheInfoVector(
+ const GURL& base_url,
+ AppCacheServiceImpl* service,
+ const AppCacheInfoVector& appcaches,
+ std::string* out) {
+ for (std::vector<AppCacheInfo>::const_iterator info =
+ appcaches.begin();
+ info != appcaches.end(); ++info) {
+ EmitAppCacheInfo(base_url, service, &(*info), out);
+ }
+}
+
+void EmitTableData(const std::string& data, bool align_right, bool bold,
+ std::string* out) {
+ if (align_right)
+ out->append("<td align='right'>");
+ else
+ out->append("<td>");
+ if (bold)
+ out->append("<b>");
+ out->append(data);
+ if (bold)
+ out->append("</b>");
+ out->append("</td>");
+}
+
+std::string FormFlagsString(const AppCacheResourceInfo& info) {
+ std::string str;
+ if (info.is_manifest)
+ str.append("Manifest, ");
+ if (info.is_master)
+ str.append("Master, ");
+ if (info.is_intercept)
+ str.append("Intercept, ");
+ if (info.is_fallback)
+ str.append("Fallback, ");
+ if (info.is_explicit)
+ str.append("Explicit, ");
+ if (info.is_foreign)
+ str.append("Foreign, ");
+ return str;
+}
+
+std::string FormViewEntryAnchor(const GURL& base_url,
+ const GURL& manifest_url, const GURL& entry_url,
+ int64 response_id,
+ int64 group_id) {
+ std::string manifest_url_base64;
+ std::string entry_url_base64;
+ std::string response_id_string;
+ std::string group_id_string;
+ base::Base64Encode(manifest_url.spec(), &manifest_url_base64);
+ base::Base64Encode(entry_url.spec(), &entry_url_base64);
+ response_id_string = base::Int64ToString(response_id);
+ group_id_string = base::Int64ToString(group_id);
+
+ std::string query(kViewEntryCommand);
+ query.push_back('=');
+ query.append(manifest_url_base64);
+ query.push_back('|');
+ query.append(entry_url_base64);
+ query.push_back('|');
+ query.append(response_id_string);
+ query.push_back('|');
+ query.append(group_id_string);
+
+ GURL::Replacements replacements;
+ replacements.SetQuery(query.data(), url::Component(0, query.length()));
+ GURL view_entry_url = base_url.ReplaceComponents(replacements);
+
+ std::string anchor;
+ EmitAnchor(view_entry_url.spec(), entry_url.spec(), &anchor);
+ return anchor;
+}
+
+void EmitAppCacheResourceInfoVector(
+ const GURL& base_url,
+ const GURL& manifest_url,
+ const AppCacheResourceInfoVector& resource_infos,
+ int64 group_id,
+ std::string* out) {
+ out->append("<table border='0'>\n");
+ out->append("<tr>");
+ EmitTableData("Flags", false, true, out);
+ EmitTableData("URL", false, true, out);
+ EmitTableData("Size (headers and data)", true, true, out);
+ out->append("</tr>\n");
+ for (AppCacheResourceInfoVector::const_iterator
+ iter = resource_infos.begin();
+ iter != resource_infos.end(); ++iter) {
+ out->append("<tr>");
+ EmitTableData(FormFlagsString(*iter), false, false, out);
+ EmitTableData(FormViewEntryAnchor(base_url, manifest_url,
+ iter->url, iter->response_id,
+ group_id),
+ false, false, out);
+ EmitTableData(base::UTF16ToUTF8(base::FormatBytesUnlocalized(iter->size)),
+ true, false, out);
+ out->append("</tr>\n");
+ }
+ out->append("</table>\n");
+}
+
+void EmitResponseHeaders(net::HttpResponseHeaders* headers, std::string* out) {
+ out->append("<hr><pre>");
+ out->append(net::EscapeForHTML(headers->GetStatusLine()));
+ out->push_back('\n');
+
+ void* iter = NULL;
+ std::string name, value;
+ while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
+ out->append(net::EscapeForHTML(name));
+ out->append(": ");
+ out->append(net::EscapeForHTML(value));
+ out->push_back('\n');
+ }
+ out->append("</pre>");
+}
+
+void EmitHexDump(const char *buf, size_t buf_len, size_t total_len,
+ std::string* out) {
+ out->append("<hr><pre>");
+ base::StringAppendF(out, "Showing %d of %d bytes\n\n",
+ static_cast<int>(buf_len), static_cast<int>(total_len));
+ net::ViewCacheHelper::HexDump(buf, buf_len, out);
+ if (buf_len < total_len)
+ out->append("\nNote: data is truncated...");
+ out->append("</pre>");
+}
+
+GURL DecodeBase64URL(base::StringPiece base64) {
+ std::string url;
+ base::Base64Decode(base64, &url);
+ return GURL(url);
+}
+
+bool ParseQuery(const std::string& query,
+ std::string* command, std::string* value) {
+ size_t position = query.find("=");
+ if (position == std::string::npos)
+ return false;
+ *command = query.substr(0, position);
+ *value = query.substr(position + 1);
+ return !command->empty() && !value->empty();
+}
+
+bool SortByManifestUrl(const AppCacheInfo& lhs,
+ const AppCacheInfo& rhs) {
+ return lhs.manifest_url.spec() < rhs.manifest_url.spec();
+}
+
+bool SortByResourceUrl(const AppCacheResourceInfo& lhs,
+ const AppCacheResourceInfo& rhs) {
+ return lhs.url.spec() < rhs.url.spec();
+}
+
+GURL ClearQuery(const GURL& url) {
+ GURL::Replacements replacements;
+ replacements.ClearQuery();
+ return url.ReplaceComponents(replacements);
+}
+
+// Simple base class for the job subclasses defined here.
+class BaseInternalsJob : public net::URLRequestSimpleJob,
+ public AppCacheServiceImpl::Observer {
+ protected:
+ BaseInternalsJob(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ AppCacheServiceImpl* service)
+ : URLRequestSimpleJob(request, network_delegate),
+ appcache_service_(service),
+ appcache_storage_(service->storage()) {
+ appcache_service_->AddObserver(this);
+ }
+
+ ~BaseInternalsJob() override { appcache_service_->RemoveObserver(this); }
+
+ void OnServiceReinitialized(
+ AppCacheStorageReference* old_storage_ref) override {
+ if (old_storage_ref->storage() == appcache_storage_)
+ disabled_storage_reference_ = old_storage_ref;
+ }
+
+ AppCacheServiceImpl* appcache_service_;
+ AppCacheStorage* appcache_storage_;
+ scoped_refptr<AppCacheStorageReference> disabled_storage_reference_;
+};
+
+// Job that lists all appcaches in the system.
+class MainPageJob : public BaseInternalsJob {
+ public:
+ MainPageJob(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ AppCacheServiceImpl* service)
+ : BaseInternalsJob(request, network_delegate, service),
+ weak_factory_(this) {
+ }
+
+ void Start() override {
+ DCHECK(request_);
+ info_collection_ = new AppCacheInfoCollection;
+ appcache_service_->GetAllAppCacheInfo(
+ info_collection_.get(),
+ base::Bind(&MainPageJob::OnGotInfoComplete,
+ weak_factory_.GetWeakPtr()));
+ }
+
+ // Produces a page containing the listing
+ int GetData(std::string* mime_type,
+ std::string* charset,
+ std::string* out,
+ const net::CompletionCallback& callback) const override {
+ mime_type->assign("text/html");
+ charset->assign("UTF-8");
+
+ out->clear();
+ EmitPageStart(out);
+ if (!info_collection_.get()) {
+ out->append(kErrorMessage);
+ } else if (info_collection_->infos_by_origin.empty()) {
+ out->append(kEmptyAppCachesMessage);
+ } else {
+ typedef std::map<GURL, AppCacheInfoVector> InfoByOrigin;
+ AppCacheInfoVector appcaches;
+ for (InfoByOrigin::const_iterator origin =
+ info_collection_->infos_by_origin.begin();
+ origin != info_collection_->infos_by_origin.end(); ++origin) {
+ appcaches.insert(appcaches.end(),
+ origin->second.begin(), origin->second.end());
+ }
+ std::sort(appcaches.begin(), appcaches.end(), SortByManifestUrl);
+
+ GURL base_url = ClearQuery(request_->url());
+ EmitAppCacheInfoVector(base_url, appcache_service_, appcaches, out);
+ }
+ EmitPageEnd(out);
+ return net::OK;
+ }
+
+ private:
+ ~MainPageJob() override {}
+
+ void OnGotInfoComplete(int rv) {
+ if (rv != net::OK)
+ info_collection_ = NULL;
+ StartAsync();
+ }
+
+ scoped_refptr<AppCacheInfoCollection> info_collection_;
+ base::WeakPtrFactory<MainPageJob> weak_factory_;
+ DISALLOW_COPY_AND_ASSIGN(MainPageJob);
+};
+
+// Job that redirects back to the main appcache internals page.
+class RedirectToMainPageJob : public BaseInternalsJob {
+ public:
+ RedirectToMainPageJob(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ AppCacheServiceImpl* service)
+ : BaseInternalsJob(request, network_delegate, service) {}
+
+ int GetData(std::string* mime_type,
+ std::string* charset,
+ std::string* data,
+ const net::CompletionCallback& callback) const override {
+ return net::OK; // IsRedirectResponse induces a redirect.
+ }
+
+ bool IsRedirectResponse(GURL* location, int* http_status_code) override {
+ *location = ClearQuery(request_->url());
+ *http_status_code = 307;
+ return true;
+ }
+
+ protected:
+ ~RedirectToMainPageJob() override {}
+};
+
+// Job that removes an appcache and then redirects back to the main page.
+class RemoveAppCacheJob : public RedirectToMainPageJob {
+ public:
+ RemoveAppCacheJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ AppCacheServiceImpl* service,
+ const GURL& manifest_url)
+ : RedirectToMainPageJob(request, network_delegate, service),
+ manifest_url_(manifest_url),
+ weak_factory_(this) {
+ }
+
+ void Start() override {
+ DCHECK(request_);
+
+ appcache_service_->DeleteAppCacheGroup(
+ manifest_url_,base::Bind(&RemoveAppCacheJob::OnDeleteAppCacheComplete,
+ weak_factory_.GetWeakPtr()));
+ }
+
+ private:
+ ~RemoveAppCacheJob() override {}
+
+ void OnDeleteAppCacheComplete(int rv) {
+ StartAsync(); // Causes the base class to redirect.
+ }
+
+ GURL manifest_url_;
+ base::WeakPtrFactory<RemoveAppCacheJob> weak_factory_;
+};
+
+
+// Job shows the details of a particular manifest url.
+class ViewAppCacheJob : public BaseInternalsJob,
+ public AppCacheStorage::Delegate {
+ public:
+ ViewAppCacheJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ AppCacheServiceImpl* service,
+ const GURL& manifest_url)
+ : BaseInternalsJob(request, network_delegate, service),
+ manifest_url_(manifest_url) {}
+
+ void Start() override {
+ DCHECK(request_);
+ appcache_storage_->LoadOrCreateGroup(manifest_url_, this);
+ }
+
+ // Produces a page containing the entries listing.
+ int GetData(std::string* mime_type,
+ std::string* charset,
+ std::string* out,
+ const net::CompletionCallback& callback) const override {
+ mime_type->assign("text/html");
+ charset->assign("UTF-8");
+ out->clear();
+ EmitPageStart(out);
+ if (appcache_info_.manifest_url.is_empty()) {
+ out->append(kManifestNotFoundMessage);
+ } else {
+ GURL base_url = ClearQuery(request_->url());
+ EmitAppCacheInfo(base_url, appcache_service_, &appcache_info_, out);
+ EmitAppCacheResourceInfoVector(base_url,
+ manifest_url_,
+ resource_infos_,
+ appcache_info_.group_id,
+ out);
+ }
+ EmitPageEnd(out);
+ return net::OK;
+ }
+
+ private:
+ ~ViewAppCacheJob() override {
+ appcache_storage_->CancelDelegateCallbacks(this);
+ }
+
+ // AppCacheStorage::Delegate override
+ void OnGroupLoaded(AppCacheGroup* group, const GURL& manifest_url) override {
+ DCHECK_EQ(manifest_url_, manifest_url);
+ if (group && group->newest_complete_cache()) {
+ appcache_info_.manifest_url = manifest_url;
+ appcache_info_.group_id = group->group_id();
+ appcache_info_.size = group->newest_complete_cache()->cache_size();
+ appcache_info_.creation_time = group->creation_time();
+ appcache_info_.last_update_time =
+ group->newest_complete_cache()->update_time();
+ appcache_info_.last_access_time = base::Time::Now();
+ group->newest_complete_cache()->ToResourceInfoVector(&resource_infos_);
+ std::sort(resource_infos_.begin(), resource_infos_.end(),
+ SortByResourceUrl);
+ }
+ StartAsync();
+ }
+
+ GURL manifest_url_;
+ AppCacheInfo appcache_info_;
+ AppCacheResourceInfoVector resource_infos_;
+ DISALLOW_COPY_AND_ASSIGN(ViewAppCacheJob);
+};
+
+// Job that shows the details of a particular cached resource.
+class ViewEntryJob : public BaseInternalsJob,
+ public AppCacheStorage::Delegate {
+ public:
+ ViewEntryJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ AppCacheServiceImpl* service,
+ const GURL& manifest_url,
+ const GURL& entry_url,
+ int64 response_id, int64 group_id)
+ : BaseInternalsJob(request, network_delegate, service),
+ manifest_url_(manifest_url), entry_url_(entry_url),
+ response_id_(response_id), group_id_(group_id), amount_read_(0) {
+ }
+
+ void Start() override {
+ DCHECK(request_);
+ appcache_storage_->LoadResponseInfo(
+ manifest_url_, group_id_, response_id_, this);
+ }
+
+ // Produces a page containing the response headers and data.
+ int GetData(std::string* mime_type,
+ std::string* charset,
+ std::string* out,
+ const net::CompletionCallback& callback) const override {
+ mime_type->assign("text/html");
+ charset->assign("UTF-8");
+ out->clear();
+ EmitPageStart(out);
+ EmitAnchor(entry_url_.spec(), entry_url_.spec(), out);
+ out->append("<br/>\n");
+ if (response_info_.get()) {
+ if (response_info_->http_response_info())
+ EmitResponseHeaders(response_info_->http_response_info()->headers.get(),
+ out);
+ else
+ out->append("Failed to read response headers.<br>");
+
+ if (response_data_.get()) {
+ EmitHexDump(response_data_->data(),
+ amount_read_,
+ response_info_->response_data_size(),
+ out);
+ } else {
+ out->append("Failed to read response data.<br>");
+ }
+ } else {
+ out->append("Failed to read response headers and data.<br>");
+ }
+ EmitPageEnd(out);
+ return net::OK;
+ }
+
+ private:
+ ~ViewEntryJob() override { appcache_storage_->CancelDelegateCallbacks(this); }
+
+ void OnResponseInfoLoaded(AppCacheResponseInfo* response_info,
+ int64 response_id) override {
+ if (!response_info) {
+ StartAsync();
+ return;
+ }
+ response_info_ = response_info;
+
+ // Read the response data, truncating if its too large.
+ const int64 kLimit = 100 * 1000;
+ int64 amount_to_read =
+ std::min(kLimit, response_info->response_data_size());
+ response_data_ = new net::IOBuffer(
+ base::CheckedNumeric<size_t>(amount_to_read).ValueOrDie());
+
+ reader_.reset(appcache_storage_->CreateResponseReader(
+ manifest_url_, group_id_, response_id_));
+ reader_->ReadData(
+ response_data_.get(),
+ amount_to_read,
+ base::Bind(&ViewEntryJob::OnReadComplete, base::Unretained(this)));
+ }
+
+ void OnReadComplete(int result) {
+ reader_.reset();
+ amount_read_ = result;
+ if (result < 0)
+ response_data_ = NULL;
+ StartAsync();
+ }
+
+ GURL manifest_url_;
+ GURL entry_url_;
+ int64 response_id_;
+ int64 group_id_;
+ scoped_refptr<AppCacheResponseInfo> response_info_;
+ scoped_refptr<net::IOBuffer> response_data_;
+ int amount_read_;
+ scoped_ptr<AppCacheResponseReader> reader_;
+};
+
+} // namespace
+
+net::URLRequestJob* ViewAppCacheInternalsJobFactory::CreateJobForRequest(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ AppCacheServiceImpl* service) {
+ if (!request->url().has_query())
+ return new MainPageJob(request, network_delegate, service);
+
+ std::string command;
+ std::string param;
+ ParseQuery(request->url().query(), &command, &param);
+
+ if (command == kRemoveCacheCommand)
+ return new RemoveAppCacheJob(request, network_delegate, service,
+ DecodeBase64URL(param));
+
+ if (command == kViewCacheCommand)
+ return new ViewAppCacheJob(request, network_delegate, service,
+ DecodeBase64URL(param));
+
+ if (command == kViewEntryCommand) {
+ std::vector<base::StringPiece> tokens = base::SplitStringPiece(
+ param, "|", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ int64 response_id = 0;
+ int64 group_id = 0;
+ if (tokens.size() == 4u &&
+ base::StringToInt64(tokens[2], &response_id) &&
+ base::StringToInt64(tokens[3], &group_id)) {
+ return new ViewEntryJob(request, network_delegate, service,
+ DecodeBase64URL(tokens[0]), // manifest url
+ DecodeBase64URL(tokens[1]), // entry url
+ response_id, group_id);
+ }
+ }
+
+ return new RedirectToMainPageJob(request, network_delegate, service);
+}
+
+} // namespace content
diff --git a/content/browser/appcache/view_appcache_internals_job.h b/content/browser/appcache/view_appcache_internals_job.h
new file mode 100644
index 0000000..5118212
--- /dev/null
+++ b/content/browser/appcache/view_appcache_internals_job.h
@@ -0,0 +1,32 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_APPCACHE_VIEW_APPCACHE_INTERNALS_JOB_H_
+#define CONTENT_BROWSER_APPCACHE_VIEW_APPCACHE_INTERNALS_JOB_H_
+
+#include "base/basictypes.h"
+
+namespace net {
+class NetworkDelegate;
+class URLRequest;
+class URLRequestJob;
+}
+
+namespace content {
+class AppCacheServiceImpl;
+
+class ViewAppCacheInternalsJobFactory {
+ public:
+ static net::URLRequestJob* CreateJobForRequest(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ AppCacheServiceImpl* service);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ViewAppCacheInternalsJobFactory);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_VIEW_APPCACHE_INTERNALS_JOB_H_