diff options
author | Joe Downing <joedow@google.com> | 2015-08-10 13:39:12 -0700 |
---|---|---|
committer | Joe Downing <joedow@google.com> | 2015-08-10 20:42:08 +0000 |
commit | 3fd8c3abf1d1216a3370e2765b9318504f9f1d91 (patch) | |
tree | ccf8fd8b0e75cb58af616a960cc77ddce995c660 /content/browser/appcache | |
parent | ae7209aeafdcb56f6761aeffe27f992fe2571a04 (diff) | |
download | chromium_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.cc | 510 | ||||
-rw-r--r-- | content/browser/appcache/appcache_internals_ui.h | 129 | ||||
-rw-r--r-- | content/browser/appcache/appcache_service_impl.cc | 3 | ||||
-rw-r--r-- | content/browser/appcache/appcache_service_impl.h | 7 | ||||
-rw-r--r-- | content/browser/appcache/view_appcache_internals_job.cc | 668 | ||||
-rw-r--r-- | content/browser/appcache/view_appcache_internals_job.h | 32 |
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(" "); + 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, ¶m); + + 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_ |