From af561035f6bd3f19318d0500e936d9259a71ffe1 Mon Sep 17 00:00:00 2001 From: "jianli@chromium.org" Date: Fri, 8 Oct 2010 18:12:09 +0000 Subject: Support chrome://blob-internals to inspect the blob storage. BUG=none TEST=none Review URL: http://codereview.chromium.org/3516019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@61982 0039d316-1c4b-4281-b951-d872f2087c98 --- webkit/blob/blob_storage_controller.h | 2 + webkit/blob/view_blob_internals_job.cc | 231 +++++++++++++++++++++++++++++++++ webkit/blob/view_blob_internals_job.h | 47 +++++++ webkit/blob/webkit_blob.gypi | 2 + 4 files changed, 282 insertions(+) create mode 100644 webkit/blob/view_blob_internals_job.cc create mode 100644 webkit/blob/view_blob_internals_job.h (limited to 'webkit/blob') diff --git a/webkit/blob/blob_storage_controller.h b/webkit/blob/blob_storage_controller.h index 6c735c4..1f0b25e 100644 --- a/webkit/blob/blob_storage_controller.h +++ b/webkit/blob/blob_storage_controller.h @@ -35,6 +35,8 @@ class BlobStorageController { void ResolveBlobReferencesInUploadData(net::UploadData* upload_data); private: + friend class ViewBlobInternalsJob; + void AppendStorageItems(BlobData* target_blob_data, BlobData* src_blob_data, uint64 offset, diff --git a/webkit/blob/view_blob_internals_job.cc b/webkit/blob/view_blob_internals_job.cc new file mode 100644 index 0000000..36463b9 --- /dev/null +++ b/webkit/blob/view_blob_internals_job.cc @@ -0,0 +1,231 @@ +// Copyright (c) 2010 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 "webkit/blob/view_blob_internals_job.h" + +#include "base/logging.h" +#include "base/format_macros.h" +#include "base/i18n/number_formatting.h" +#include "base/i18n/time_formatting.h" +#include "base/message_loop.h" +#include "base/string_util.h" +#include "base/utf_string_conversions.h" +#include "net/base/escape.h" +#include "net/url_request/url_request.h" +#include "webkit/blob/blob_data.h" +#include "webkit/blob/blob_storage_controller.h" + +namespace { + +const char kEmptyBlobStorageMessage[] = "No available blob data."; +const char kRemove[] = "Remove"; +const char kContentType[] = "Content Type: "; +const char kContentDisposition[] = "Content Disposition: "; +const char kCount[] = "Count: "; +const char kIndex[] = "Index: "; +const char kType[] = "Type: "; +const char kPath[] = "Path: "; +const char kURL[] = "URL: "; +const char kModificationTime[] = "Modification Time: "; +const char kOffset[] = "Offset: "; +const char kLength[] = "Length: "; + +void StartHTML(std::string* out) { + out->append( + "" + "Blob Storage Internals" + "" + "\n" + "" + "
" + "" + "
"); +} + +void EndHTML(std::string* out) { + out->append(""); +} + +void AddHTMLBoldText(const std::string& text, std::string* out) { + out->append(""); + out->append(text); + out->append(""); +} + +void StartHTMLList(std::string* out) { + out->append(""); +} + +void AddHTMLListItem(const std::string& element_title, + const std::string& element_data, + std::string* out) { + out->append("
  • "); + out->append(element_title); + out->append(element_data); + out->append("
  • "); +} + +void AddHTMLButton(const std::string& title, + const std::string& command, + std::string* out) { + StringAppendF(out, + "", + title.c_str(), + command.c_str()); +} + +} // namespace + +namespace webkit_blob { + +ViewBlobInternalsJob::ViewBlobInternalsJob( + URLRequest* request, BlobStorageController* blob_storage_controller) + : URLRequestSimpleJob(request), + blob_storage_controller_(blob_storage_controller) { +} + +ViewBlobInternalsJob::~ViewBlobInternalsJob() { +} + +void ViewBlobInternalsJob::Start() { + MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( + this, &ViewBlobInternalsJob::DoWorkAsync)); +} + +bool ViewBlobInternalsJob::IsRedirectResponse(GURL* location, + int* http_status_code) { + if (request_->url().has_query()) { + // Strip the query parameters. + GURL::Replacements replacements; + replacements.ClearQuery(); + *location = request_->url().ReplaceComponents(replacements); + *http_status_code = 307; + return true; + } + return false; +} + +void ViewBlobInternalsJob::DoWorkAsync() { + if (request_->url().has_query() && + StartsWithASCII(request_->url().query(), "remove=", true)) { + std::string blob_url = request_->url().query().substr(strlen("remove=")); + blob_url = UnescapeURLComponent(blob_url, + UnescapeRule::NORMAL | UnescapeRule::URL_SPECIAL_CHARS); + blob_storage_controller_->UnregisterBlobUrl(GURL(blob_url)); + } + + StartAsync(); +} + +bool ViewBlobInternalsJob::GetData(std::string* mime_type, + std::string* charset, + std::string* data) const { + mime_type->assign("text/html"); + charset->assign("UTF-8"); + + data->clear(); + StartHTML(data); + if (blob_storage_controller_->blob_map_.empty()) + data->append(kEmptyBlobStorageMessage); + else + GenerateHTML(data); + EndHTML(data); + return true; +} + +void ViewBlobInternalsJob::GenerateHTML(std::string* out) const { + for (BlobStorageController::BlobMap::const_iterator iter = + blob_storage_controller_->blob_map_.begin(); + iter != blob_storage_controller_->blob_map_.end(); + ++iter) { + AddHTMLBoldText(iter->first, out); + AddHTMLButton(kRemove, iter->first, out); + out->append("
    "); + GenerateHTMLForBlobData(*iter->second, out); + } +} + +void ViewBlobInternalsJob::GenerateHTMLForBlobData(const BlobData& blob_data, + std::string* out) { + StartHTMLList(out); + + if (!blob_data.content_type().empty()) + AddHTMLListItem(kContentType, blob_data.content_type(), out); + if (!blob_data.content_disposition().empty()) + AddHTMLListItem(kContentDisposition, blob_data.content_disposition(), out); + + bool has_multi_items = blob_data.items().size() > 1; + if (has_multi_items) { + AddHTMLListItem(kCount, + UTF16ToUTF8(base::FormatNumber(blob_data.items().size())), out); + } + + for (size_t i = 0; i < blob_data.items().size(); ++i) { + if (has_multi_items) { + AddHTMLListItem(kIndex, UTF16ToUTF8(base::FormatNumber(i)), out); + StartHTMLList(out); + } + const BlobData::Item& item = blob_data.items().at(i); + + switch (item.type()) { + case BlobData::TYPE_DATA: + AddHTMLListItem(kType, "data", out); + break; + case BlobData::TYPE_FILE: + AddHTMLListItem(kType, "file", out); + AddHTMLListItem(kPath, +#if defined(OS_WIN) + EscapeForHTML(WideToUTF8(item.file_path().value())), +#else + EscapeForHTML(item.file_path().value()), +#endif + out); + if (!item.expected_modification_time().is_null()) { + AddHTMLListItem(kModificationTime, WideToUTF8( + TimeFormatFriendlyDateAndTime(item.expected_modification_time())), + out); + } + break; + case BlobData::TYPE_BLOB: + AddHTMLListItem(kType, "blob", out); + AddHTMLListItem(kURL, item.blob_url().spec(), out); + break; + } + if (item.offset()) { + AddHTMLListItem(kOffset, UTF16ToUTF8(base::FormatNumber( + static_cast(item.offset()))), out); + } + if (static_cast(item.length()) != -1) { + AddHTMLListItem(kLength, UTF16ToUTF8(base::FormatNumber( + static_cast(item.length()))), out); + } + + if (has_multi_items) + EndHTMLList(out); + } + + EndHTMLList(out); +} + +} // namespace webkit_blob diff --git a/webkit/blob/view_blob_internals_job.h b/webkit/blob/view_blob_internals_job.h new file mode 100644 index 0000000..0248153 --- /dev/null +++ b/webkit/blob/view_blob_internals_job.h @@ -0,0 +1,47 @@ +// Copyright (c) 2010 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 WEBKIT_BLOB_VIEW_BLOB_INTERNALS_JOB_H_ +#define WEBKIT_BLOB_VIEW_BLOB_INTERNALS_JOB_H_ + +#include + +#include "net/url_request/url_request_simple_job.h" + +class URLRequest; + +namespace webkit_blob { + +class BlobData; +class BlobStorageController; + +// A job subclass that implements a protocol to inspect the internal +// state of blob registry. +class ViewBlobInternalsJob : public URLRequestSimpleJob { + public: + ViewBlobInternalsJob(URLRequest* request, + BlobStorageController* blob_storage_controller); + + virtual void Start(); + virtual bool GetData(std::string* mime_type, + std::string* charset, + std::string* data) const; + virtual bool IsRedirectResponse(GURL* location, int* http_status_code); + + private: + ~ViewBlobInternalsJob(); + + void DoWorkAsync(); + void GenerateHTML(std::string* out) const; + static void GenerateHTMLForBlobData(const BlobData& blob_data, + std::string* out); + + BlobStorageController* blob_storage_controller_; + + DISALLOW_COPY_AND_ASSIGN(ViewBlobInternalsJob); +}; + +} // namespace webkit_blob + +#endif // WEBKIT_BLOB_VIEW_BLOB_INTERNALS_JOB_H_ diff --git a/webkit/blob/webkit_blob.gypi b/webkit/blob/webkit_blob.gypi index eb4b3be..b952c7f 100644 --- a/webkit/blob/webkit_blob.gypi +++ b/webkit/blob/webkit_blob.gypi @@ -22,6 +22,8 @@ 'blob_url_request_job.h', 'deletable_file_reference.cc', 'deletable_file_reference.h', + 'view_blob_internals_job.cc', + 'view_blob_internals_job.h', ], 'conditions': [ ['inside_chromium_build==0', { -- cgit v1.1