Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/indexed_db/indexed_db_internals_ui.h" | 5 #include "content/browser/indexed_db/indexed_db_internals_ui.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | |
| 8 | 9 |
| 9 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/files/scoped_temp_dir.h" | |
| 10 #include "base/memory/scoped_vector.h" | 12 #include "base/memory/scoped_vector.h" |
| 11 #include "base/threading/platform_thread.h" | 13 #include "base/threading/platform_thread.h" |
| 12 #include "base/values.h" | 14 #include "base/values.h" |
| 15 #include "components/zip/zip.h" | |
| 16 #include "content/browser/indexed_db/indexed_db_context_impl.h" | |
| 13 #include "content/public/browser/browser_context.h" | 17 #include "content/public/browser/browser_context.h" |
| 14 #include "content/public/browser/browser_thread.h" | 18 #include "content/public/browser/browser_thread.h" |
| 19 #include "content/public/browser/download_manager.h" | |
| 20 #include "content/public/browser/download_url_parameters.h" | |
| 15 #include "content/public/browser/storage_partition.h" | 21 #include "content/public/browser/storage_partition.h" |
| 16 #include "content/public/browser/web_contents.h" | 22 #include "content/public/browser/web_contents.h" |
| 17 #include "content/public/browser/web_ui.h" | 23 #include "content/public/browser/web_ui.h" |
| 18 #include "content/public/browser/web_ui_data_source.h" | 24 #include "content/public/browser/web_ui_data_source.h" |
| 19 #include "content/public/common/url_constants.h" | 25 #include "content/public/common/url_constants.h" |
| 20 #include "grit/content_resources.h" | 26 #include "grit/content_resources.h" |
| 27 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h" | |
| 28 #include "webkit/base/file_path_string_conversions.h" | |
| 29 #include "webkit/database/database_util.h" | |
| 30 | |
| 31 using webkit_database::DatabaseUtil; | |
| 21 | 32 |
| 22 namespace content { | 33 namespace content { |
| 23 | 34 |
| 24 IndexedDBInternalsUI::IndexedDBInternalsUI(WebUI* web_ui) | 35 IndexedDBInternalsUI::IndexedDBInternalsUI(WebUI* web_ui) |
| 25 : WebUIController(web_ui) { | 36 : WebUIController(web_ui) { |
| 26 web_ui->RegisterMessageCallback( | 37 web_ui->RegisterMessageCallback( |
| 27 "getAllOrigins", | 38 "getAllOrigins", |
| 28 base::Bind(&IndexedDBInternalsUI::GetAllOrigins, base::Unretained(this))); | 39 base::Bind(&IndexedDBInternalsUI::GetAllOrigins, base::Unretained(this))); |
| 29 | 40 |
| 41 web_ui->RegisterMessageCallback( | |
| 42 "downloadOriginData", | |
| 43 base::Bind(&IndexedDBInternalsUI::DownloadOriginData, | |
| 44 base::Unretained(this))); | |
| 45 | |
| 30 WebUIDataSource* source = | 46 WebUIDataSource* source = |
| 31 WebUIDataSource::Create(kChromeUIIndexedDBInternalsHost); | 47 WebUIDataSource::Create(kChromeUIIndexedDBInternalsHost); |
| 32 source->SetUseJsonJSFormatV2(); | 48 source->SetUseJsonJSFormatV2(); |
| 33 source->SetJsonPath("strings.js"); | 49 source->SetJsonPath("strings.js"); |
| 34 source->AddResourcePath("indexeddb_internals.js", | 50 source->AddResourcePath("indexeddb_internals.js", |
| 35 IDR_INDEXED_DB_INTERNALS_JS); | 51 IDR_INDEXED_DB_INTERNALS_JS); |
| 36 source->AddResourcePath("indexeddb_internals.css", | 52 source->AddResourcePath("indexeddb_internals.css", |
| 37 IDR_INDEXED_DB_INTERNALS_CSS); | 53 IDR_INDEXED_DB_INTERNALS_CSS); |
| 38 source->SetDefaultResource(IDR_INDEXED_DB_INTERNALS_HTML); | 54 source->SetDefaultResource(IDR_INDEXED_DB_INTERNALS_HTML); |
| 39 | 55 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 73 base::Unretained(this), | 89 base::Unretained(this), |
| 74 base::Passed(&contexts), | 90 base::Passed(&contexts), |
| 75 base::Passed(&paths))); | 91 base::Passed(&paths))); |
| 76 } | 92 } |
| 77 | 93 |
| 78 bool HostNameComparator(const IndexedDBInfo& i, const IndexedDBInfo& j) { | 94 bool HostNameComparator(const IndexedDBInfo& i, const IndexedDBInfo& j) { |
| 79 return i.origin_.host() < j.origin_.host(); | 95 return i.origin_.host() < j.origin_.host(); |
| 80 } | 96 } |
| 81 | 97 |
| 82 void IndexedDBInternalsUI::GetAllOriginsOnWebkitThread( | 98 void IndexedDBInternalsUI::GetAllOriginsOnWebkitThread( |
| 83 scoped_ptr<ContextList> contexts, | 99 const scoped_ptr<ContextList> contexts, |
| 84 scoped_ptr<std::vector<base::FilePath> > context_paths) { | 100 const scoped_ptr<std::vector<base::FilePath> > context_paths) { |
| 85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); | 101 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); |
| 86 DCHECK_EQ(contexts->size(), context_paths->size()); | 102 DCHECK_EQ(contexts->size(), context_paths->size()); |
| 87 | 103 |
| 88 std::vector<base::FilePath>::const_iterator path_iter = | 104 std::vector<base::FilePath>::const_iterator path_iter = |
| 89 context_paths->begin(); | 105 context_paths->begin(); |
| 90 for (ContextList::const_iterator iter = contexts->begin(); | 106 for (ContextList::const_iterator iter = contexts->begin(); |
| 91 iter != contexts->end(); | 107 iter != contexts->end(); |
| 92 ++iter, ++path_iter) { | 108 ++iter, ++path_iter) { |
| 93 IndexedDBContext* context = *iter; | 109 IndexedDBContext* context = *iter; |
| 94 const base::FilePath& context_path = *path_iter; | 110 const base::FilePath& context_path = *path_iter; |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 117 info->SetString("url", iter->origin_.spec()); | 133 info->SetString("url", iter->origin_.spec()); |
| 118 info->SetDouble("size", iter->size_); | 134 info->SetDouble("size", iter->size_); |
| 119 info->SetDouble("last_modified", iter->last_modified_.ToJsTime()); | 135 info->SetDouble("last_modified", iter->last_modified_.ToJsTime()); |
| 120 info->SetString("path", iter->path_.value()); | 136 info->SetString("path", iter->path_.value()); |
| 121 urls.Append(info); | 137 urls.Append(info); |
| 122 } | 138 } |
| 123 web_ui()->CallJavascriptFunction( | 139 web_ui()->CallJavascriptFunction( |
| 124 "indexeddb.onOriginsReady", urls, base::StringValue(path.value())); | 140 "indexeddb.onOriginsReady", urls, base::StringValue(path.value())); |
| 125 } | 141 } |
| 126 | 142 |
| 143 static void FindContext(const base::FilePath& partition_path, | |
| 144 StoragePartition** result_partition, | |
| 145 scoped_refptr<IndexedDBContextImpl>* result_context, | |
| 146 StoragePartition* storage_partition) { | |
| 147 if (storage_partition->GetPath() == partition_path) { | |
| 148 *result_partition = storage_partition; | |
| 149 *result_context = static_cast<IndexedDBContextImpl*>( | |
| 150 storage_partition->GetIndexedDBContext()); | |
| 151 } | |
| 152 } | |
| 153 | |
| 154 void IndexedDBInternalsUI::DownloadOriginData(const base::ListValue* args) { | |
| 155 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 156 | |
| 157 base::FilePath::StringType path_string; | |
| 158 if (!args->GetString(0, &path_string)) | |
| 159 return; | |
| 160 const base::FilePath partition_path(path_string); | |
| 161 | |
| 162 std::string url_string; | |
| 163 if (!args->GetString(1, &url_string)) | |
| 164 return; | |
| 165 const GURL origin_url(url_string); | |
| 166 | |
| 167 // search the origins to find the right context | |
| 168 | |
| 169 BrowserContext* browser_context = | |
| 170 web_ui()->GetWebContents()->GetBrowserContext(); | |
| 171 | |
| 172 scoped_refptr<IndexedDBContextImpl> result_context; | |
| 173 StoragePartition* result_partition; | |
| 174 scoped_ptr<ContextList> contexts(new ContextList); | |
| 175 BrowserContext::StoragePartitionCallback cb = base::Bind( | |
| 176 &FindContext, partition_path, &result_partition, &result_context); | |
| 177 BrowserContext::ForEachStoragePartition(browser_context, cb); | |
| 178 DCHECK(result_partition); | |
| 179 DCHECK(result_context); | |
| 180 | |
| 181 BrowserThread::PostTask( | |
| 182 BrowserThread::WEBKIT_DEPRECATED, | |
| 183 FROM_HERE, | |
| 184 base::Bind(&IndexedDBInternalsUI::DownloadOriginDataOnWebkitThread, | |
| 185 base::Unretained(this), | |
| 186 result_partition->GetPath(), | |
| 187 result_context, | |
| 188 origin_url)); | |
| 189 } | |
| 190 | |
| 191 void IndexedDBInternalsUI::DownloadOriginDataOnWebkitThread( | |
| 192 const base::FilePath& partition_path, | |
| 193 const scoped_refptr<IndexedDBContextImpl> context, | |
| 194 const GURL& origin_url) { | |
| 195 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT_DEPRECATED)); | |
| 196 | |
| 197 if (!context->HasOrigin(origin_url)) | |
| 198 return; | |
| 199 | |
| 200 context->ForceClose(origin_url); | |
| 201 | |
| 202 base::ScopedTempDir temp_dir; | |
| 203 if (!temp_dir.CreateUniqueTempDir()) | |
| 204 return; | |
| 205 | |
| 206 // This will get cleaned up on the File thread after the download | |
| 207 // has completed. | |
| 208 base::FilePath temp_path = temp_dir.Take(); | |
| 209 | |
| 210 base::string16 origin_id = DatabaseUtil::GetOriginIdentifier(origin_url); | |
| 211 base::FilePath::StringType zip_name = | |
| 212 webkit_base::WebStringToFilePathString(origin_id); | |
| 213 base::FilePath zip_path = temp_path.Append(zip_name).AddExtension("zip"); | |
| 214 | |
| 215 // This happens on the "webkit" thread (which is really just the IndexedDB | |
| 216 // thread) as a simple way to avoid another script reopening the origin | |
| 217 // while we are zipping. | |
| 218 zip::Zip(context->GetFilePath(origin_url), zip_path, true); | |
| 219 | |
| 220 BrowserThread::PostTask(BrowserThread::UI, | |
| 221 FROM_HERE, | |
| 222 base::Bind(&IndexedDBInternalsUI::OnDownloadDataReady, | |
| 223 base::Unretained(this), | |
| 224 partition_path, | |
| 225 origin_url, | |
| 226 temp_path, | |
| 227 zip_path)); | |
| 228 | |
| 229 LOG(ERROR) << "Origin data ready in " << zip_path.value(); | |
|
jsbell
2013/04/18 22:08:52
Don't forget to remove this.
| |
| 230 } | |
| 231 | |
| 232 void IndexedDBInternalsUI::OnDownloadDataReady( | |
| 233 const base::FilePath& partition_path, | |
| 234 const GURL& origin_url, | |
| 235 const base::FilePath temp_path, | |
| 236 const base::FilePath zip_path) { | |
| 237 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 238 const GURL url = GURL("file://" + zip_path.value()); | |
| 239 BrowserContext* browser_context = | |
| 240 web_ui()->GetWebContents()->GetBrowserContext(); | |
| 241 scoped_ptr<DownloadUrlParameters> dl_params( | |
| 242 DownloadUrlParameters::FromWebContents(web_ui()->GetWebContents(), url)); | |
| 243 DownloadManager* dlm = BrowserContext::GetDownloadManager(browser_context); | |
| 244 | |
| 245 const GURL referrer(web_ui()->GetWebContents()->GetURL()); | |
| 246 dl_params->set_referrer( | |
| 247 content::Referrer(referrer, WebKit::WebReferrerPolicyDefault)); | |
| 248 | |
| 249 // This is how to watch for the download to finish: first wait for it | |
| 250 // to start, then attach a DownloadItem::Observer to observe the | |
| 251 // state change to the finished state. | |
| 252 dl_params->set_callback(base::Bind(&IndexedDBInternalsUI::OnDownloadStarted, | |
| 253 base::Unretained(this), | |
| 254 partition_path, | |
| 255 origin_url, | |
| 256 temp_path)); | |
| 257 dlm->DownloadUrl(dl_params.Pass()); | |
| 258 | |
| 259 LOG(ERROR) << "I'd start to download: " << url.spec(); | |
|
jsbell
2013/04/18 22:08:52
Don't forget to remove this.
| |
| 260 } | |
| 261 | |
| 262 // The entire purpose of this class is to delete the temp file after | |
| 263 // the download is complete. | |
| 264 class FileDeleter : public DownloadItem::Observer { | |
| 265 public: | |
| 266 explicit FileDeleter(const base::FilePath& temp_dir) : temp_dir_(temp_dir) {} | |
| 267 virtual ~FileDeleter(); | |
| 268 | |
| 269 virtual void OnDownloadUpdated(DownloadItem* download) OVERRIDE; | |
| 270 virtual void OnDownloadOpened(DownloadItem* item) OVERRIDE {} | |
| 271 virtual void OnDownloadRemoved(DownloadItem* item) OVERRIDE {} | |
| 272 virtual void OnDownloadDestroyed(DownloadItem* item) OVERRIDE {} | |
| 273 | |
| 274 private: | |
| 275 const base::FilePath temp_dir_; | |
| 276 }; | |
| 277 | |
| 278 void FileDeleter::OnDownloadUpdated(DownloadItem* item) { | |
| 279 switch (item->GetState()) { | |
| 280 case DownloadItem::IN_PROGRESS: | |
| 281 break; | |
| 282 case DownloadItem::COMPLETE: | |
| 283 case DownloadItem::CANCELLED: | |
| 284 case DownloadItem::INTERRUPTED: { | |
| 285 item->RemoveObserver(this); | |
| 286 BrowserThread::DeleteOnFileThread::Destruct(this); | |
| 287 } break; | |
|
jsbell
2013/04/18 22:08:52
Put break; inside braces?
| |
| 288 default: | |
| 289 NOTREACHED(); | |
| 290 } | |
| 291 } | |
| 292 | |
| 293 FileDeleter::~FileDeleter() { | |
| 294 base::ScopedTempDir path; | |
| 295 (void) path.Set(temp_dir_); | |
| 296 } | |
| 297 | |
| 298 void IndexedDBInternalsUI::OnDownloadStarted( | |
| 299 const base::FilePath& partition_path, | |
| 300 const GURL& origin_url, | |
| 301 const base::FilePath& temp_path, | |
| 302 DownloadItem* item, | |
| 303 net::Error error) { | |
| 304 | |
| 305 if (error != net::OK) { | |
| 306 LOG(ERROR) | |
| 307 << "Error downloading database dump: " << net::ErrorToString(error); | |
|
jsbell
2013/04/18 22:08:52
Nit: Put first bit of log on previous line. (I thi
| |
| 308 return; | |
| 309 } | |
| 310 | |
| 311 item->AddObserver(new FileDeleter(temp_path)); | |
| 312 web_ui()->CallJavascriptFunction("indexeddb.onOriginDownloadReady", | |
| 313 base::StringValue(partition_path.value()), | |
| 314 base::StringValue(origin_url.spec())); | |
| 315 } | |
| 316 | |
| 127 } // namespace content | 317 } // namespace content |
| OLD | NEW |