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 |