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
LocalStorageInfo()21 BrowsingDataLocalStorageHelper::LocalStorageInfo::LocalStorageInfo()
22 : port(0),
23 size(0) {
24 }
25
LocalStorageInfo(const std::string & protocol,const std::string & host,unsigned short port,const std::string & database_identifier,const std::string & origin,const FilePath & file_path,int64 size,base::Time last_modified)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
~LocalStorageInfo()45 BrowsingDataLocalStorageHelper::LocalStorageInfo::~LocalStorageInfo() {}
46
BrowsingDataLocalStorageHelper(Profile * profile)47 BrowsingDataLocalStorageHelper::BrowsingDataLocalStorageHelper(
48 Profile* profile)
49 : profile_(profile),
50 completion_callback_(NULL),
51 is_fetching_(false) {
52 DCHECK(profile_);
53 }
54
~BrowsingDataLocalStorageHelper()55 BrowsingDataLocalStorageHelper::~BrowsingDataLocalStorageHelper() {
56 }
57
StartFetching(Callback1<const std::vector<LocalStorageInfo> &>::Type * callback)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
CancelNotification()73 void BrowsingDataLocalStorageHelper::CancelNotification() {
74 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
75 completion_callback_.reset(NULL);
76 }
77
DeleteLocalStorageFile(const FilePath & file_path)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
FetchLocalStorageInfoInWebKitThread()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
NotifyInUIThread()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
DeleteLocalStorageFileInWebKitThread(const FilePath & file_path)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
CannedBrowsingDataLocalStorageHelper(Profile * profile)148 CannedBrowsingDataLocalStorageHelper::CannedBrowsingDataLocalStorageHelper(
149 Profile* profile)
150 : BrowsingDataLocalStorageHelper(profile),
151 profile_(profile) {
152 }
153
154 CannedBrowsingDataLocalStorageHelper*
Clone()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
AddLocalStorage(const GURL & origin)166 void CannedBrowsingDataLocalStorageHelper::AddLocalStorage(
167 const GURL& origin) {
168 base::AutoLock auto_lock(lock_);
169 pending_local_storage_info_.push_back(origin);
170 }
171
Reset()172 void CannedBrowsingDataLocalStorageHelper::Reset() {
173 base::AutoLock auto_lock(lock_);
174 local_storage_info_.clear();
175 pending_local_storage_info_.clear();
176 }
177
empty() const178 bool CannedBrowsingDataLocalStorageHelper::empty() const {
179 base::AutoLock auto_lock(lock_);
180 return local_storage_info_.empty() && pending_local_storage_info_.empty();
181 }
182
StartFetching(Callback1<const std::vector<LocalStorageInfo> &>::Type * callback)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
~CannedBrowsingDataLocalStorageHelper()198 CannedBrowsingDataLocalStorageHelper::~CannedBrowsingDataLocalStorageHelper() {}
199
ConvertPendingInfoInWebKitThread()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