1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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_local_storage_helper.h" 6 7 #include "base/file_util.h" 8 #include "base/message_loop.h" 9 #include "base/string_util.h" 10 #include "base/utf_string_conversions.h" 11 #include "chrome/browser/profiles/profile.h" 12 #include "content/browser/browser_thread.h" 13 #include "content/browser/in_process_webkit/webkit_context.h" 14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h" 15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" 17 #include "webkit/glue/webkit_glue.h" 18 19 using WebKit::WebSecurityOrigin; 20 21 BrowsingDataLocalStorageHelper::LocalStorageInfo::LocalStorageInfo() 22 : port(0), 23 size(0) { 24 } 25 26 BrowsingDataLocalStorageHelper::LocalStorageInfo::LocalStorageInfo( 27 const std::string& protocol, 28 const std::string& host, 29 unsigned short port, 30 const std::string& database_identifier, 31 const std::string& origin, 32 const FilePath& file_path, 33 int64 size, 34 base::Time last_modified) 35 : protocol(protocol), 36 host(host), 37 port(port), 38 database_identifier(database_identifier), 39 origin(origin), 40 file_path(file_path), 41 size(size), 42 last_modified(last_modified) { 43 } 44 45 BrowsingDataLocalStorageHelper::LocalStorageInfo::~LocalStorageInfo() {} 46 47 BrowsingDataLocalStorageHelper::BrowsingDataLocalStorageHelper( 48 Profile* profile) 49 : profile_(profile), 50 completion_callback_(NULL), 51 is_fetching_(false) { 52 DCHECK(profile_); 53 } 54 55 BrowsingDataLocalStorageHelper::~BrowsingDataLocalStorageHelper() { 56 } 57 58 void BrowsingDataLocalStorageHelper::StartFetching( 59 Callback1<const std::vector<LocalStorageInfo>& >::Type* callback) { 60 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 61 DCHECK(!is_fetching_); 62 DCHECK(callback); 63 is_fetching_ = true; 64 completion_callback_.reset(callback); 65 BrowserThread::PostTask( 66 BrowserThread::WEBKIT, FROM_HERE, 67 NewRunnableMethod( 68 this, 69 &BrowsingDataLocalStorageHelper:: 70 FetchLocalStorageInfoInWebKitThread)); 71 } 72 73 void BrowsingDataLocalStorageHelper::CancelNotification() { 74 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 75 completion_callback_.reset(NULL); 76 } 77 78 void BrowsingDataLocalStorageHelper::DeleteLocalStorageFile( 79 const FilePath& file_path) { 80 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 81 BrowserThread::PostTask( 82 BrowserThread::WEBKIT, FROM_HERE, 83 NewRunnableMethod( 84 this, 85 &BrowsingDataLocalStorageHelper:: 86 DeleteLocalStorageFileInWebKitThread, 87 file_path)); 88 } 89 90 void BrowsingDataLocalStorageHelper::FetchLocalStorageInfoInWebKitThread() { 91 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); 92 file_util::FileEnumerator file_enumerator( 93 profile_->GetWebKitContext()->data_path().Append( 94 DOMStorageContext::kLocalStorageDirectory), 95 false, file_util::FileEnumerator::FILES); 96 for (FilePath file_path = file_enumerator.Next(); !file_path.empty(); 97 file_path = file_enumerator.Next()) { 98 if (file_path.Extension() == DOMStorageContext::kLocalStorageExtension) { 99 WebSecurityOrigin web_security_origin = 100 WebSecurityOrigin::createFromDatabaseIdentifier( 101 webkit_glue::FilePathToWebString(file_path.BaseName())); 102 if (EqualsASCII(web_security_origin.protocol(), 103 chrome::kExtensionScheme)) { 104 // Extension state is not considered browsing data. 105 continue; 106 } 107 base::PlatformFileInfo file_info; 108 bool ret = file_util::GetFileInfo(file_path, &file_info); 109 if (ret) { 110 local_storage_info_.push_back(LocalStorageInfo( 111 web_security_origin.protocol().utf8(), 112 web_security_origin.host().utf8(), 113 web_security_origin.port(), 114 web_security_origin.databaseIdentifier().utf8(), 115 web_security_origin.toString().utf8(), 116 file_path, 117 file_info.size, 118 file_info.last_modified)); 119 } 120 } 121 } 122 123 BrowserThread::PostTask( 124 BrowserThread::UI, FROM_HERE, 125 NewRunnableMethod( 126 this, &BrowsingDataLocalStorageHelper::NotifyInUIThread)); 127 } 128 129 void BrowsingDataLocalStorageHelper::NotifyInUIThread() { 130 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 131 DCHECK(is_fetching_); 132 // Note: completion_callback_ mutates only in the UI thread, so it's safe to 133 // test it here. 134 if (completion_callback_ != NULL) { 135 completion_callback_->Run(local_storage_info_); 136 completion_callback_.reset(); 137 } 138 is_fetching_ = false; 139 } 140 141 void BrowsingDataLocalStorageHelper::DeleteLocalStorageFileInWebKitThread( 142 const FilePath& file_path) { 143 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); 144 profile_->GetWebKitContext()->dom_storage_context()->DeleteLocalStorageFile( 145 file_path); 146 } 147 148 CannedBrowsingDataLocalStorageHelper::CannedBrowsingDataLocalStorageHelper( 149 Profile* profile) 150 : BrowsingDataLocalStorageHelper(profile), 151 profile_(profile) { 152 } 153 154 CannedBrowsingDataLocalStorageHelper* 155 CannedBrowsingDataLocalStorageHelper::Clone() { 156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 157 CannedBrowsingDataLocalStorageHelper* clone = 158 new CannedBrowsingDataLocalStorageHelper(profile_); 159 160 base::AutoLock auto_lock(lock_); 161 clone->pending_local_storage_info_ = pending_local_storage_info_; 162 clone->local_storage_info_ = local_storage_info_; 163 return clone; 164 } 165 166 void CannedBrowsingDataLocalStorageHelper::AddLocalStorage( 167 const GURL& origin) { 168 base::AutoLock auto_lock(lock_); 169 pending_local_storage_info_.push_back(origin); 170 } 171 172 void CannedBrowsingDataLocalStorageHelper::Reset() { 173 base::AutoLock auto_lock(lock_); 174 local_storage_info_.clear(); 175 pending_local_storage_info_.clear(); 176 } 177 178 bool CannedBrowsingDataLocalStorageHelper::empty() const { 179 base::AutoLock auto_lock(lock_); 180 return local_storage_info_.empty() && pending_local_storage_info_.empty(); 181 } 182 183 void CannedBrowsingDataLocalStorageHelper::StartFetching( 184 Callback1<const std::vector<LocalStorageInfo>& >::Type* callback) { 185 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 186 DCHECK(!is_fetching_); 187 DCHECK(callback); 188 is_fetching_ = true; 189 completion_callback_.reset(callback); 190 BrowserThread::PostTask( 191 BrowserThread::WEBKIT, FROM_HERE, 192 NewRunnableMethod( 193 this, 194 &CannedBrowsingDataLocalStorageHelper:: 195 ConvertPendingInfoInWebKitThread)); 196 } 197 198 CannedBrowsingDataLocalStorageHelper::~CannedBrowsingDataLocalStorageHelper() {} 199 200 void CannedBrowsingDataLocalStorageHelper::ConvertPendingInfoInWebKitThread() { 201 base::AutoLock auto_lock(lock_); 202 for (std::vector<GURL>::iterator info = pending_local_storage_info_.begin(); 203 info != pending_local_storage_info_.end(); ++info) { 204 WebSecurityOrigin web_security_origin = 205 WebSecurityOrigin::createFromString( 206 UTF8ToUTF16(info->spec())); 207 std::string security_origin(web_security_origin.toString().utf8()); 208 209 bool duplicate = false; 210 for (std::vector<LocalStorageInfo>::iterator 211 local_storage = local_storage_info_.begin(); 212 local_storage != local_storage_info_.end(); ++local_storage) { 213 if (local_storage->origin == security_origin) { 214 duplicate = true; 215 break; 216 } 217 } 218 if (duplicate) 219 continue; 220 221 local_storage_info_.push_back(LocalStorageInfo( 222 web_security_origin.protocol().utf8(), 223 web_security_origin.host().utf8(), 224 web_security_origin.port(), 225 web_security_origin.databaseIdentifier().utf8(), 226 security_origin, 227 profile_->GetWebKitContext()->dom_storage_context()-> 228 GetLocalStorageFilePath(web_security_origin.databaseIdentifier()), 229 0, 230 base::Time())); 231 } 232 pending_local_storage_info_.clear(); 233 234 BrowserThread::PostTask( 235 BrowserThread::UI, FROM_HERE, 236 NewRunnableMethod( 237 this, &CannedBrowsingDataLocalStorageHelper::NotifyInUIThread)); 238 } 239