[email protected] | 0c7a6b2d | 2011-02-10 15:27:55 | [diff] [blame^] | 1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
[email protected] | 2823fb24 | 2010-09-23 08:53:26 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "chrome/browser/browsing_data_indexed_db_helper.h" |
| 6 | |
| 7 | #include "base/file_util.h" |
| 8 | #include "base/message_loop.h" |
| 9 | #include "base/scoped_ptr.h" |
| 10 | #include "base/string_util.h" |
| 11 | #include "base/utf_string_conversions.h" |
[email protected] | ed7e6dd | 2010-10-12 02:02:45 | [diff] [blame] | 12 | #include "chrome/browser/browser_thread.h" |
[email protected] | 2823fb24 | 2010-09-23 08:53:26 | [diff] [blame] | 13 | #include "chrome/browser/in_process_webkit/webkit_context.h" |
[email protected] | 8ecad5e | 2010-12-02 21:18:33 | [diff] [blame] | 14 | #include "chrome/browser/profiles/profile.h" |
[email protected] | 8bd0fe6 | 2011-01-17 06:44:37 | [diff] [blame] | 15 | #include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h" |
| 16 | #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" |
| 17 | #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" |
[email protected] | 2823fb24 | 2010-09-23 08:53:26 | [diff] [blame] | 18 | #include "webkit/glue/webkit_glue.h" |
| 19 | |
| 20 | using WebKit::WebSecurityOrigin; |
| 21 | |
| 22 | namespace { |
| 23 | |
| 24 | class BrowsingDataIndexedDBHelperImpl : public BrowsingDataIndexedDBHelper { |
| 25 | public: |
| 26 | explicit BrowsingDataIndexedDBHelperImpl(Profile* profile); |
| 27 | |
| 28 | virtual void StartFetching( |
| 29 | Callback1<const std::vector<IndexedDBInfo>& >::Type* callback); |
| 30 | virtual void CancelNotification(); |
| 31 | virtual void DeleteIndexedDBFile(const FilePath& file_path); |
| 32 | |
| 33 | private: |
| 34 | virtual ~BrowsingDataIndexedDBHelperImpl(); |
| 35 | |
| 36 | // Enumerates all indexed database files in the WEBKIT thread. |
| 37 | void FetchIndexedDBInfoInWebKitThread(); |
| 38 | // Notifies the completion callback in the UI thread. |
| 39 | void NotifyInUIThread(); |
| 40 | // Delete a single indexed database file in the WEBKIT thread. |
| 41 | void DeleteIndexedDBFileInWebKitThread(const FilePath& file_path); |
| 42 | |
| 43 | Profile* profile_; |
| 44 | |
| 45 | // This only mutates in the WEBKIT thread. |
| 46 | std::vector<IndexedDBInfo> indexed_db_info_; |
| 47 | |
| 48 | // This only mutates on the UI thread. |
| 49 | scoped_ptr<Callback1<const std::vector<IndexedDBInfo>& >::Type > |
| 50 | completion_callback_; |
| 51 | // Indicates whether or not we're currently fetching information: |
| 52 | // it's true when StartFetching() is called in the UI thread, and it's reset |
| 53 | // after we notified the callback in the UI thread. |
| 54 | // This only mutates on the UI thread. |
| 55 | bool is_fetching_; |
| 56 | |
| 57 | DISALLOW_COPY_AND_ASSIGN(BrowsingDataIndexedDBHelperImpl); |
| 58 | }; |
| 59 | |
| 60 | BrowsingDataIndexedDBHelperImpl::BrowsingDataIndexedDBHelperImpl( |
| 61 | Profile* profile) |
| 62 | : profile_(profile), |
| 63 | completion_callback_(NULL), |
| 64 | is_fetching_(false) { |
| 65 | DCHECK(profile_); |
| 66 | } |
| 67 | |
| 68 | BrowsingDataIndexedDBHelperImpl::~BrowsingDataIndexedDBHelperImpl() { |
| 69 | } |
| 70 | |
| 71 | void BrowsingDataIndexedDBHelperImpl::StartFetching( |
| 72 | Callback1<const std::vector<IndexedDBInfo>& >::Type* callback) { |
[email protected] | d04e766 | 2010-10-10 22:24:48 | [diff] [blame] | 73 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | 2823fb24 | 2010-09-23 08:53:26 | [diff] [blame] | 74 | DCHECK(!is_fetching_); |
| 75 | DCHECK(callback); |
| 76 | is_fetching_ = true; |
| 77 | completion_callback_.reset(callback); |
[email protected] | d04e766 | 2010-10-10 22:24:48 | [diff] [blame] | 78 | BrowserThread::PostTask( |
| 79 | BrowserThread::WEBKIT, FROM_HERE, |
[email protected] | 2823fb24 | 2010-09-23 08:53:26 | [diff] [blame] | 80 | NewRunnableMethod( |
| 81 | this, |
| 82 | &BrowsingDataIndexedDBHelperImpl::FetchIndexedDBInfoInWebKitThread)); |
| 83 | } |
| 84 | |
| 85 | void BrowsingDataIndexedDBHelperImpl::CancelNotification() { |
[email protected] | d04e766 | 2010-10-10 22:24:48 | [diff] [blame] | 86 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | 2823fb24 | 2010-09-23 08:53:26 | [diff] [blame] | 87 | completion_callback_.reset(NULL); |
| 88 | } |
| 89 | |
| 90 | void BrowsingDataIndexedDBHelperImpl::DeleteIndexedDBFile( |
| 91 | const FilePath& file_path) { |
[email protected] | d04e766 | 2010-10-10 22:24:48 | [diff] [blame] | 92 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 93 | BrowserThread::PostTask( |
| 94 | BrowserThread::WEBKIT, FROM_HERE, |
[email protected] | 2823fb24 | 2010-09-23 08:53:26 | [diff] [blame] | 95 | NewRunnableMethod( |
| 96 | this, |
| 97 | &BrowsingDataIndexedDBHelperImpl:: |
| 98 | DeleteIndexedDBFileInWebKitThread, |
| 99 | file_path)); |
| 100 | } |
| 101 | |
| 102 | void BrowsingDataIndexedDBHelperImpl::FetchIndexedDBInfoInWebKitThread() { |
[email protected] | d04e766 | 2010-10-10 22:24:48 | [diff] [blame] | 103 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); |
[email protected] | 2823fb24 | 2010-09-23 08:53:26 | [diff] [blame] | 104 | file_util::FileEnumerator file_enumerator( |
| 105 | profile_->GetWebKitContext()->data_path().Append( |
| 106 | IndexedDBContext::kIndexedDBDirectory), |
| 107 | false, file_util::FileEnumerator::FILES); |
| 108 | for (FilePath file_path = file_enumerator.Next(); !file_path.empty(); |
| 109 | file_path = file_enumerator.Next()) { |
| 110 | if (file_path.Extension() == IndexedDBContext::kIndexedDBExtension) { |
[email protected] | 5000ade6 | 2010-11-08 23:20:49 | [diff] [blame] | 111 | WebSecurityOrigin web_security_origin = |
[email protected] | 0c7a6b2d | 2011-02-10 15:27:55 | [diff] [blame^] | 112 | WebSecurityOrigin::createFromDatabaseIdentifier( |
[email protected] | 5000ade6 | 2010-11-08 23:20:49 | [diff] [blame] | 113 | webkit_glue::FilePathToWebString(file_path.BaseName())); |
[email protected] | 2823fb24 | 2010-09-23 08:53:26 | [diff] [blame] | 114 | if (EqualsASCII(web_security_origin.protocol(), |
| 115 | chrome::kExtensionScheme)) { |
| 116 | // Extension state is not considered browsing data. |
| 117 | continue; |
| 118 | } |
| 119 | base::PlatformFileInfo file_info; |
| 120 | bool ret = file_util::GetFileInfo(file_path, &file_info); |
| 121 | if (ret) { |
| 122 | indexed_db_info_.push_back(IndexedDBInfo( |
| 123 | web_security_origin.protocol().utf8(), |
| 124 | web_security_origin.host().utf8(), |
| 125 | web_security_origin.port(), |
| 126 | web_security_origin.databaseIdentifier().utf8(), |
| 127 | web_security_origin.toString().utf8(), |
[email protected] | 2823fb24 | 2010-09-23 08:53:26 | [diff] [blame] | 128 | file_path, |
| 129 | file_info.size, |
| 130 | file_info.last_modified)); |
| 131 | } |
| 132 | } |
| 133 | } |
| 134 | |
[email protected] | d04e766 | 2010-10-10 22:24:48 | [diff] [blame] | 135 | BrowserThread::PostTask( |
| 136 | BrowserThread::UI, FROM_HERE, |
[email protected] | 2823fb24 | 2010-09-23 08:53:26 | [diff] [blame] | 137 | NewRunnableMethod( |
| 138 | this, &BrowsingDataIndexedDBHelperImpl::NotifyInUIThread)); |
| 139 | } |
| 140 | |
| 141 | void BrowsingDataIndexedDBHelperImpl::NotifyInUIThread() { |
[email protected] | d04e766 | 2010-10-10 22:24:48 | [diff] [blame] | 142 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
[email protected] | 2823fb24 | 2010-09-23 08:53:26 | [diff] [blame] | 143 | DCHECK(is_fetching_); |
| 144 | // Note: completion_callback_ mutates only in the UI thread, so it's safe to |
| 145 | // test it here. |
| 146 | if (completion_callback_ != NULL) { |
| 147 | completion_callback_->Run(indexed_db_info_); |
| 148 | completion_callback_.reset(); |
| 149 | } |
| 150 | is_fetching_ = false; |
| 151 | } |
| 152 | |
| 153 | void BrowsingDataIndexedDBHelperImpl::DeleteIndexedDBFileInWebKitThread( |
| 154 | const FilePath& file_path) { |
[email protected] | d04e766 | 2010-10-10 22:24:48 | [diff] [blame] | 155 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); |
[email protected] | 2823fb24 | 2010-09-23 08:53:26 | [diff] [blame] | 156 | // TODO(jochen): implement this once it's possible to delete indexed DBs. |
| 157 | } |
| 158 | |
| 159 | } // namespace |
| 160 | |
[email protected] | d2f05d0 | 2011-01-27 18:51:01 | [diff] [blame] | 161 | BrowsingDataIndexedDBHelper::IndexedDBInfo::IndexedDBInfo( |
| 162 | const std::string& protocol, |
| 163 | const std::string& host, |
| 164 | unsigned short port, |
| 165 | const std::string& database_identifier, |
| 166 | const std::string& origin, |
| 167 | const FilePath& file_path, |
| 168 | int64 size, |
| 169 | base::Time last_modified) |
| 170 | : protocol(protocol), |
| 171 | host(host), |
| 172 | port(port), |
| 173 | database_identifier(database_identifier), |
| 174 | origin(origin), |
| 175 | file_path(file_path), |
| 176 | size(size), |
| 177 | last_modified(last_modified) { |
| 178 | } |
| 179 | |
| 180 | BrowsingDataIndexedDBHelper::IndexedDBInfo::~IndexedDBInfo() {} |
| 181 | |
[email protected] | 2823fb24 | 2010-09-23 08:53:26 | [diff] [blame] | 182 | // static |
| 183 | BrowsingDataIndexedDBHelper* BrowsingDataIndexedDBHelper::Create( |
| 184 | Profile* profile) { |
| 185 | return new BrowsingDataIndexedDBHelperImpl(profile); |
| 186 | } |
| 187 | |
[email protected] | 0c7a6b2d | 2011-02-10 15:27:55 | [diff] [blame^] | 188 | CannedBrowsingDataIndexedDBHelper:: |
| 189 | PendingIndexedDBInfo::PendingIndexedDBInfo() { |
| 190 | } |
| 191 | |
| 192 | CannedBrowsingDataIndexedDBHelper:: |
| 193 | PendingIndexedDBInfo::PendingIndexedDBInfo(const GURL& origin, |
| 194 | const string16& description) |
| 195 | : origin(origin), |
| 196 | description(description) { |
| 197 | } |
| 198 | |
| 199 | CannedBrowsingDataIndexedDBHelper:: |
| 200 | PendingIndexedDBInfo::~PendingIndexedDBInfo() { |
| 201 | } |
| 202 | |
[email protected] | 2823fb24 | 2010-09-23 08:53:26 | [diff] [blame] | 203 | CannedBrowsingDataIndexedDBHelper::CannedBrowsingDataIndexedDBHelper( |
| 204 | Profile* profile) |
[email protected] | 0c7a6b2d | 2011-02-10 15:27:55 | [diff] [blame^] | 205 | : profile_(profile), |
| 206 | completion_callback_(NULL), |
| 207 | is_fetching_(false) { |
[email protected] | 2823fb24 | 2010-09-23 08:53:26 | [diff] [blame] | 208 | DCHECK(profile); |
| 209 | } |
| 210 | |
| 211 | void CannedBrowsingDataIndexedDBHelper::AddIndexedDB( |
[email protected] | 5000ade6 | 2010-11-08 23:20:49 | [diff] [blame] | 212 | const GURL& origin, const string16& description) { |
[email protected] | 0c7a6b2d | 2011-02-10 15:27:55 | [diff] [blame^] | 213 | base::AutoLock auto_lock(lock_); |
| 214 | pending_indexed_db_info_.push_back(PendingIndexedDBInfo(origin, description)); |
[email protected] | 2823fb24 | 2010-09-23 08:53:26 | [diff] [blame] | 215 | } |
| 216 | |
| 217 | void CannedBrowsingDataIndexedDBHelper::Reset() { |
[email protected] | 0c7a6b2d | 2011-02-10 15:27:55 | [diff] [blame^] | 218 | base::AutoLock auto_lock(lock_); |
[email protected] | 2823fb24 | 2010-09-23 08:53:26 | [diff] [blame] | 219 | indexed_db_info_.clear(); |
[email protected] | 0c7a6b2d | 2011-02-10 15:27:55 | [diff] [blame^] | 220 | pending_indexed_db_info_.clear(); |
[email protected] | 2823fb24 | 2010-09-23 08:53:26 | [diff] [blame] | 221 | } |
| 222 | |
| 223 | bool CannedBrowsingDataIndexedDBHelper::empty() const { |
[email protected] | 0c7a6b2d | 2011-02-10 15:27:55 | [diff] [blame^] | 224 | base::AutoLock auto_lock(lock_); |
| 225 | return indexed_db_info_.empty() && pending_indexed_db_info_.empty(); |
[email protected] | 2823fb24 | 2010-09-23 08:53:26 | [diff] [blame] | 226 | } |
| 227 | |
| 228 | void CannedBrowsingDataIndexedDBHelper::StartFetching( |
| 229 | Callback1<const std::vector<IndexedDBInfo>& >::Type* callback) { |
[email protected] | 0c7a6b2d | 2011-02-10 15:27:55 | [diff] [blame^] | 230 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 231 | DCHECK(!is_fetching_); |
| 232 | DCHECK(callback); |
| 233 | is_fetching_ = true; |
| 234 | completion_callback_.reset(callback); |
| 235 | BrowserThread::PostTask(BrowserThread::WEBKIT, FROM_HERE, NewRunnableMethod( |
| 236 | this, |
| 237 | &CannedBrowsingDataIndexedDBHelper::ConvertPendingInfoInWebKitThread)); |
[email protected] | 2823fb24 | 2010-09-23 08:53:26 | [diff] [blame] | 238 | } |
[email protected] | 8e38341 | 2010-10-19 16:57:03 | [diff] [blame] | 239 | |
| 240 | CannedBrowsingDataIndexedDBHelper::~CannedBrowsingDataIndexedDBHelper() {} |
[email protected] | 0c7a6b2d | 2011-02-10 15:27:55 | [diff] [blame^] | 241 | |
| 242 | void CannedBrowsingDataIndexedDBHelper::ConvertPendingInfoInWebKitThread() { |
| 243 | base::AutoLock auto_lock(lock_); |
| 244 | for (std::vector<PendingIndexedDBInfo>::const_iterator |
| 245 | info = pending_indexed_db_info_.begin(); |
| 246 | info != pending_indexed_db_info_.end(); ++info) { |
| 247 | WebSecurityOrigin web_security_origin = |
| 248 | WebSecurityOrigin::createFromString( |
| 249 | UTF8ToUTF16(info->origin.spec())); |
| 250 | std::string security_origin(web_security_origin.toString().utf8()); |
| 251 | |
| 252 | bool duplicate = false; |
| 253 | for (std::vector<IndexedDBInfo>::iterator |
| 254 | indexed_db = indexed_db_info_.begin(); |
| 255 | indexed_db != indexed_db_info_.end(); ++indexed_db) { |
| 256 | if (indexed_db->origin == security_origin) { |
| 257 | duplicate = true; |
| 258 | break; |
| 259 | } |
| 260 | } |
| 261 | if (duplicate) |
| 262 | continue; |
| 263 | |
| 264 | indexed_db_info_.push_back(IndexedDBInfo( |
| 265 | web_security_origin.protocol().utf8(), |
| 266 | web_security_origin.host().utf8(), |
| 267 | web_security_origin.port(), |
| 268 | web_security_origin.databaseIdentifier().utf8(), |
| 269 | security_origin, |
| 270 | profile_->GetWebKitContext()->indexed_db_context()-> |
| 271 | GetIndexedDBFilePath(web_security_origin.databaseIdentifier()), |
| 272 | 0, |
| 273 | base::Time())); |
| 274 | } |
| 275 | pending_indexed_db_info_.clear(); |
| 276 | |
| 277 | BrowserThread::PostTask( |
| 278 | BrowserThread::UI, FROM_HERE, |
| 279 | NewRunnableMethod( |
| 280 | this, &CannedBrowsingDataIndexedDBHelper::NotifyInUIThread)); |
| 281 | } |
| 282 | |
| 283 | void CannedBrowsingDataIndexedDBHelper::NotifyInUIThread() { |
| 284 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 285 | DCHECK(is_fetching_); |
| 286 | // Note: completion_callback_ mutates only in the UI thread, so it's safe to |
| 287 | // test it here. |
| 288 | if (completion_callback_ != NULL) { |
| 289 | completion_callback_->Run(indexed_db_info_); |
| 290 | completion_callback_.reset(); |
| 291 | } |
| 292 | is_fetching_ = false; |
| 293 | } |