Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(422)

Unified Diff: content/browser/indexed_db/indexed_db_internals_ui.cc

Issue 13949013: Implement download link in chrome://indexeddb-internals/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: use FILE_PATH_LITERAL Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/indexed_db/indexed_db_internals_ui.cc
diff --git a/content/browser/indexed_db/indexed_db_internals_ui.cc b/content/browser/indexed_db/indexed_db_internals_ui.cc
index 1869091ab5de94fd822089d65823288aeac7df69..4d6f04b285b2d57a4721104cdf2d36881e231b18 100644
--- a/content/browser/indexed_db/indexed_db_internals_ui.cc
+++ b/content/browser/indexed_db/indexed_db_internals_ui.cc
@@ -5,19 +5,30 @@
#include "content/browser/indexed_db/indexed_db_internals_ui.h"
#include <algorithm>
+#include <string>
#include "base/bind.h"
+#include "base/files/scoped_temp_dir.h"
#include "base/memory/scoped_vector.h"
#include "base/threading/platform_thread.h"
#include "base/values.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/download_manager.h"
+#include "content/public/browser/download_url_parameters.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.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 "grit/content_resources.h"
+#include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
+#include "third_party/zlib/google/zip.h"
+#include "webkit/base/file_path_string_conversions.h"
+#include "webkit/database/database_util.h"
+
+using webkit_database::DatabaseUtil;
namespace content {
@@ -27,6 +38,11 @@ IndexedDBInternalsUI::IndexedDBInternalsUI(WebUI* web_ui)
"getAllOrigins",
base::Bind(&IndexedDBInternalsUI::GetAllOrigins, base::Unretained(this)));
+ web_ui->RegisterMessageCallback(
+ "downloadOriginData",
+ base::Bind(&IndexedDBInternalsUI::DownloadOriginData,
+ base::Unretained(this)));
+
WebUIDataSource* source =
WebUIDataSource::Create(kChromeUIIndexedDBInternalsHost);
source->SetUseJsonJSFormatV2();
@@ -80,8 +96,8 @@ bool HostNameComparator(const IndexedDBInfo& i, const IndexedDBInfo& j) {
}
void IndexedDBInternalsUI::GetAllOriginsOnWebkitThread(
- scoped_ptr<ContextList> contexts,
- scoped_ptr<std::vector<base::FilePath> > context_paths) {
+ const scoped_ptr<ContextList> contexts,
+ const scoped_ptr<std::vector<base::FilePath> > context_paths) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
DCHECK_EQ(contexts->size(), context_paths->size());
@@ -124,4 +140,177 @@ void IndexedDBInternalsUI::OnOriginsReady(
"indexeddb.onOriginsReady", urls, base::StringValue(path.value()));
}
+static void FindContext(const base::FilePath& partition_path,
+ StoragePartition** result_partition,
+ scoped_refptr<IndexedDBContextImpl>* result_context,
+ StoragePartition* storage_partition) {
+ if (storage_partition->GetPath() == partition_path) {
+ *result_partition = storage_partition;
+ *result_context = static_cast<IndexedDBContextImpl*>(
+ storage_partition->GetIndexedDBContext());
+ }
+}
+
+void IndexedDBInternalsUI::DownloadOriginData(const base::ListValue* args) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ base::FilePath::StringType path_string;
+ if (!args->GetString(0, &path_string))
+ return;
+ const base::FilePath partition_path(path_string);
+
+ std::string url_string;
+ if (!args->GetString(1, &url_string))
+ return;
+ const GURL origin_url(url_string);
+
+ // search the origins to find the right context
+
+ BrowserContext* browser_context =
+ web_ui()->GetWebContents()->GetBrowserContext();
+
+ scoped_refptr<IndexedDBContextImpl> result_context;
+ StoragePartition* result_partition;
+ scoped_ptr<ContextList> contexts(new ContextList);
+ BrowserContext::StoragePartitionCallback cb = base::Bind(
+ &FindContext, partition_path, &result_partition, &result_context);
+ BrowserContext::ForEachStoragePartition(browser_context, cb);
+ DCHECK(result_partition);
+ DCHECK(result_context);
+
+ BrowserThread::PostTask(
+ BrowserThread::WEBKIT_DEPRECATED,
+ FROM_HERE,
+ base::Bind(&IndexedDBInternalsUI::DownloadOriginDataOnWebkitThread,
+ base::Unretained(this),
+ result_partition->GetPath(),
+ result_context,
+ origin_url));
+}
+
+void IndexedDBInternalsUI::DownloadOriginDataOnWebkitThread(
+ const base::FilePath& partition_path,
+ const scoped_refptr<IndexedDBContextImpl> context,
+ const GURL& origin_url) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED));
+
+ if (!context->IsInOriginSet(origin_url))
+ return;
+
+ context->ForceClose(origin_url);
+
+ base::ScopedTempDir temp_dir;
+ if (!temp_dir.CreateUniqueTempDir())
+ return;
+
+ // This will get cleaned up on the File thread after the download
+ // has completed.
+ base::FilePath temp_path = temp_dir.Take();
+
+ base::string16 origin_id = DatabaseUtil::GetOriginIdentifier(origin_url);
+ base::FilePath::StringType zip_name =
+ webkit_base::WebStringToFilePathString(origin_id);
+ base::FilePath zip_path =
+ temp_path.Append(zip_name).AddExtension(FILE_PATH_LITERAL("zip"));
+
+ // This happens on the "webkit" thread (which is really just the IndexedDB
+ // thread) as a simple way to avoid another script reopening the origin
+ // while we are zipping.
+ zip::Zip(context->GetFilePath(origin_url), zip_path, true);
+
+ BrowserThread::PostTask(BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&IndexedDBInternalsUI::OnDownloadDataReady,
+ base::Unretained(this),
+ partition_path,
+ origin_url,
+ temp_path,
+ zip_path));
+}
+
+void IndexedDBInternalsUI::OnDownloadDataReady(
+ const base::FilePath& partition_path,
+ const GURL& origin_url,
+ const base::FilePath temp_path,
+ const base::FilePath zip_path) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ const GURL url = GURL(FILE_PATH_LITERAL("file://") + zip_path.value());
+ BrowserContext* browser_context =
+ web_ui()->GetWebContents()->GetBrowserContext();
+ scoped_ptr<DownloadUrlParameters> dl_params(
+ DownloadUrlParameters::FromWebContents(web_ui()->GetWebContents(), url));
+ DownloadManager* dlm = BrowserContext::GetDownloadManager(browser_context);
+
+ const GURL referrer(web_ui()->GetWebContents()->GetURL());
+ dl_params->set_referrer(
+ content::Referrer(referrer, WebKit::WebReferrerPolicyDefault));
+
+ // This is how to watch for the download to finish: first wait for it
+ // to start, then attach a DownloadItem::Observer to observe the
+ // state change to the finished state.
+ dl_params->set_callback(base::Bind(&IndexedDBInternalsUI::OnDownloadStarted,
+ base::Unretained(this),
+ partition_path,
+ origin_url,
+ temp_path));
+ dlm->DownloadUrl(dl_params.Pass());
+}
+
+// The entire purpose of this class is to delete the temp file after
+// the download is complete.
+class FileDeleter : public DownloadItem::Observer {
+ public:
+ explicit FileDeleter(const base::FilePath& temp_dir) : temp_dir_(temp_dir) {}
+ virtual ~FileDeleter();
+
+ virtual void OnDownloadUpdated(DownloadItem* download) OVERRIDE;
+ virtual void OnDownloadOpened(DownloadItem* item) OVERRIDE {}
+ virtual void OnDownloadRemoved(DownloadItem* item) OVERRIDE {}
+ virtual void OnDownloadDestroyed(DownloadItem* item) OVERRIDE {}
+
+ private:
+ const base::FilePath temp_dir_;
+};
+
+void FileDeleter::OnDownloadUpdated(DownloadItem* item) {
+ switch (item->GetState()) {
+ case DownloadItem::IN_PROGRESS:
+ break;
+ case DownloadItem::COMPLETE:
+ case DownloadItem::CANCELLED:
+ case DownloadItem::INTERRUPTED: {
+ item->RemoveObserver(this);
+ BrowserThread::DeleteOnFileThread::Destruct(this);
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+}
+
+FileDeleter::~FileDeleter() {
+ base::ScopedTempDir path;
+ bool will_delete ALLOW_UNUSED = path.Set(temp_dir_);
+ DCHECK(will_delete);
+}
+
+void IndexedDBInternalsUI::OnDownloadStarted(
+ const base::FilePath& partition_path,
+ const GURL& origin_url,
+ const base::FilePath& temp_path,
+ DownloadItem* item,
+ net::Error error) {
+
+ if (error != net::OK) {
+ LOG(ERROR) << "Error downloading database dump: "
+ << net::ErrorToString(error);
+ return;
+ }
+
+ item->AddObserver(new FileDeleter(temp_path));
+ web_ui()->CallJavascriptFunction("indexeddb.onOriginDownloadReady",
+ base::StringValue(partition_path.value()),
+ base::StringValue(origin_url.spec()));
+}
+
} // namespace content
« no previous file with comments | « content/browser/indexed_db/indexed_db_internals_ui.h ('k') | content/browser/resources/indexed_db/indexeddb_internals.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698