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 | |
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
-rw-r--r-- | chrome/browser/browser_about_handler.cc | 3 | ||||
-rw-r--r-- | chrome/browser/dom_ui/chrome_url_data_manager.cc | 5 | ||||
-rw-r--r-- | chrome/browser/net/view_blob_internals_job_factory.cc | 28 | ||||
-rw-r--r-- | chrome/browser/net/view_blob_internals_job_factory.h | 20 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | chrome/common/url_constants.cc | 2 | ||||
-rw-r--r-- | chrome/common/url_constants.h | 3 | ||||
-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 |
11 files changed, 345 insertions, 0 deletions
diff --git a/chrome/browser/browser_about_handler.cc b/chrome/browser/browser_about_handler.cc index ad6b091..1b14c1e 100644 --- a/chrome/browser/browser_about_handler.cc +++ b/chrome/browser/browser_about_handler.cc @@ -96,6 +96,7 @@ namespace { // The (alphabetized) paths used for the about pages. // Note: Keep these in sync with url_constants.h const char kAppCacheInternalsPath[] = "appcache-internals"; +const char kBlobInternalsPath[] = "blob-internals"; const char kCreditsPath[] = "credits"; const char kCachePath[] = "view-http-cache"; const char kDnsPath[] = "dns"; @@ -128,6 +129,7 @@ const char kOSCreditsPath[] = "os-credits"; // Add path here to be included in about:about const char *kAllAboutPaths[] = { kAppCacheInternalsPath, + kBlobInternalsPath, kCachePath, kCreditsPath, kDnsPath, @@ -259,6 +261,7 @@ std::string AboutAbout() { if (kAllAboutPaths[i] == kLabsPath && !about_labs::IsEnabled()) continue; if (kAllAboutPaths[i] == kAppCacheInternalsPath || + kAllAboutPaths[i] == kBlobInternalsPath || kAllAboutPaths[i] == kCachePath || kAllAboutPaths[i] == kLabsPath || kAllAboutPaths[i] == kNetInternalsPath || diff --git a/chrome/browser/dom_ui/chrome_url_data_manager.cc b/chrome/browser/dom_ui/chrome_url_data_manager.cc index e25bea9..26eba27 100644 --- a/chrome/browser/dom_ui/chrome_url_data_manager.cc +++ b/chrome/browser/dom_ui/chrome_url_data_manager.cc @@ -22,6 +22,7 @@ #include "chrome/browser/chrome_thread.h" #include "chrome/browser/dom_ui/shared_resources_data_source.h" #include "chrome/browser/net/chrome_url_request_context.h" +#include "chrome/browser/net/view_blob_internals_job_factory.h" #include "chrome/browser/net/view_http_cache_job_factory.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/ref_counted_util.h" @@ -329,6 +330,10 @@ URLRequestJob* ChromeURLDataManager::Factory(URLRequest* request, if (ViewAppCacheInternalsJobFactory::IsSupportedURL(request->url())) return ViewAppCacheInternalsJobFactory::CreateJobForRequest(request); + // Next check for chrome://blob-internals/, which uses its own job type. + if (ViewBlobInternalsJobFactory::IsSupportedURL(request->url())) + return ViewBlobInternalsJobFactory::CreateJobForRequest(request); + // Fall back to using a custom handler return new URLRequestChromeJob(request); } diff --git a/chrome/browser/net/view_blob_internals_job_factory.cc b/chrome/browser/net/view_blob_internals_job_factory.cc new file mode 100644 index 0000000..25832a0 --- /dev/null +++ b/chrome/browser/net/view_blob_internals_job_factory.cc @@ -0,0 +1,28 @@ +// 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 "chrome/browser/net/view_blob_internals_job_factory.h" + +#include "chrome/browser/net/chrome_url_request_context.h" +#include "chrome/browser/chrome_blob_storage_context.h" +#include "chrome/common/url_constants.h" +#include "webkit/blob/view_blob_internals_job.h" + +// static. +bool ViewBlobInternalsJobFactory::IsSupportedURL(const GURL& url) { + return StartsWithASCII(url.spec(), + chrome::kBlobViewInternalsURL, + true /*case_sensitive*/); +} + +// static. +URLRequestJob* ViewBlobInternalsJobFactory::CreateJobForRequest( + URLRequest* request) { + webkit_blob::BlobStorageController* blob_storage_controller = + static_cast<ChromeURLRequestContext*>(request->context())-> + blob_storage_context()->controller(); + return new webkit_blob::ViewBlobInternalsJob( + request, blob_storage_controller); +} + diff --git a/chrome/browser/net/view_blob_internals_job_factory.h b/chrome/browser/net/view_blob_internals_job_factory.h new file mode 100644 index 0000000..874e2bd --- /dev/null +++ b/chrome/browser/net/view_blob_internals_job_factory.h @@ -0,0 +1,20 @@ +// 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 CHROME_BROWSER_NET_VIEW_BLOB_INTERNALS_JOB_FACTORY_H_ +#define CHROME_BROWSER_NET_VIEW_BLOB_INTERNALS_JOB_FACTORY_H_ +#pragma once + +class GURL; +class URLRequest; +class URLRequestJob; + +class ViewBlobInternalsJobFactory { + public: + static bool IsSupportedURL(const GURL& url); + static URLRequestJob* CreateJobForRequest(URLRequest* request); +}; + +#endif // CHROME_BROWSER_NET_VIEW_BLOB_INTERNALS_JOB_FACTORY_H_ + diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index ece8f98..9cd7534 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -2205,6 +2205,8 @@ 'browser/net/url_request_slow_http_job.h', 'browser/net/url_request_tracking.cc', 'browser/net/url_request_tracking.h', + 'browser/net/view_blob_internals_job_factory.cc', + 'browser/net/view_blob_internals_job_factory.h', 'browser/net/view_http_cache_job_factory.cc', 'browser/net/view_http_cache_job_factory.h', 'browser/net/websocket_experiment/websocket_experiment_runner.cc', diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc index 4d505b2..2b49b6e 100644 --- a/chrome/common/url_constants.cc +++ b/chrome/common/url_constants.cc @@ -134,6 +134,8 @@ const char kChromeUIWrenchMenu[] = "wrench-menu"; const char kAppCacheViewInternalsURL[] = "chrome://appcache-internals/"; +const char kBlobViewInternalsURL[] = "chrome://blob-internals/"; + const char kCloudPrintResourcesURL[] = "chrome://cloudprintresources/"; const char kCloudPrintResourcesHost[] = "cloudprintresources"; diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h index a6dd0e3..ee0a376 100644 --- a/chrome/common/url_constants.h +++ b/chrome/common/url_constants.h @@ -129,6 +129,9 @@ extern const char kChromeUIWrenchMenu[]; // AppCache related URL. extern const char kAppCacheViewInternalsURL[]; +// Blob related URL. +extern const char kBlobViewInternalsURL[]; + // Cloud Print dialog URL components. extern const char kCloudPrintResourcesURL[]; extern const char kCloudPrintResourcesHost[]; 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', { |