diff options
author | jianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-08 18:12:09 +0000 |
---|---|---|
committer | jianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-08 18:12:09 +0000 |
commit | af561035f6bd3f19318d0500e936d9259a71ffe1 (patch) | |
tree | 72977304f6459adb091047978396fcd27c698771 /webkit/blob | |
parent | 6777a5795196c21e69169695685191e2df0eb5dd (diff) | |
download | chromium_src-af561035f6bd3f19318d0500e936d9259a71ffe1.zip chromium_src-af561035f6bd3f19318d0500e936d9259a71ffe1.tar.gz chromium_src-af561035f6bd3f19318d0500e936d9259a71ffe1.tar.bz2 |
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
Diffstat (limited to 'webkit/blob')
-rw-r--r-- | webkit/blob/blob_storage_controller.h | 2 | ||||
-rw-r--r-- | webkit/blob/view_blob_internals_job.cc | 231 | ||||
-rw-r--r-- | webkit/blob/view_blob_internals_job.h | 47 | ||||
-rw-r--r-- | webkit/blob/webkit_blob.gypi | 2 |
4 files changed, 282 insertions, 0 deletions
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( + "<!DOCTYPE HTML>" + "<html><title>Blob Storage Internals</title>" + "<style>" + "body { font-family: sans-serif; font-size: 0.8em; }\n" + "tt, code, pre { font-family: WebKitHack, monospace; }\n" + ".subsection_body { margin: 10px 0 10px 2em; }\n" + ".subsection_title { font-weight: bold; }\n" + "</style>" + "<script>\n" + // Unfortunately we can't do XHR from chrome://blob-internals + // because the chrome:// protocol restricts access. + // + // So instead, we will send commands by doing a form + // submission (which as a side effect will reload the page). + "function SubmitCommand(command) {\n" + " document.getElementById('cmd').value = command;\n" + " document.getElementById('cmdsender').submit();\n" + "}\n" + "</script>\n" + "</head><body>" + "<form action='' method=GET id=cmdsender>" + "<input type='hidden' id=cmd name='remove'>" + "</form>"); +} + +void EndHTML(std::string* out) { + out->append("</body></html>"); +} + +void AddHTMLBoldText(const std::string& text, std::string* out) { + out->append("<b>"); + out->append(text); + out->append("</b>"); +} + +void StartHTMLList(std::string* out) { + out->append("<ul>"); +} + +void EndHTMLList(std::string* out) { + out->append("</ul>"); +} + +void AddHTMLListItem(const std::string& element_title, + const std::string& element_data, + std::string* out) { + out->append("<li>"); + out->append(element_title); + out->append(element_data); + out->append("</li>"); +} + +void AddHTMLButton(const std::string& title, + const std::string& command, + std::string* out) { + StringAppendF(out, + "<input type=\"button\" value=\"%s\" " + "onclick=\"SubmitCommand('%s')\" />", + 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("<br/>"); + 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<int64>(item.offset()))), out); + } + if (static_cast<int64>(item.length()) != -1) { + AddHTMLListItem(kLength, UTF16ToUTF8(base::FormatNumber( + static_cast<int64>(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 <string> + +#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', { |