summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-08 18:12:09 +0000
committerjianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-08 18:12:09 +0000
commitaf561035f6bd3f19318d0500e936d9259a71ffe1 (patch)
tree72977304f6459adb091047978396fcd27c698771
parent6777a5795196c21e69169695685191e2df0eb5dd (diff)
downloadchromium_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.cc3
-rw-r--r--chrome/browser/dom_ui/chrome_url_data_manager.cc5
-rw-r--r--chrome/browser/net/view_blob_internals_job_factory.cc28
-rw-r--r--chrome/browser/net/view_blob_internals_job_factory.h20
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/common/url_constants.cc2
-rw-r--r--chrome/common/url_constants.h3
-rw-r--r--webkit/blob/blob_storage_controller.h2
-rw-r--r--webkit/blob/view_blob_internals_job.cc231
-rw-r--r--webkit/blob/view_blob_internals_job.h47
-rw-r--r--webkit/blob/webkit_blob.gypi2
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', {