1 // Copyright (c) 2012 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.
5 #include "chrome/browser/ui/webui/cookies_tree_model_util.h"
9 #include "base/i18n/time_formatting.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/stl_util.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_split.h"
14 #include "base/strings/string_util.h"
15 #include "base/values.h"
16 #include "chrome/browser/browsing_data/cookies_tree_model.h"
17 #include "chrome/grit/generated_resources.h"
18 #include "content/public/browser/cache_storage_context.h"
19 #include "content/public/browser/indexed_db_context.h"
20 #include "content/public/browser/service_worker_context.h"
21 #include "net/cookies/canonical_cookie.h"
22 #include "storage/common/fileapi/file_system_types.h"
23 #include "ui/base/l10n/l10n_util.h"
24 #include "ui/base/text/bytes_formatting.h"
26 #if defined(ENABLE_EXTENSIONS)
27 #include "extensions/common/extension_set.h"
32 const char kKeyId
[] = "id";
33 const char kKeyTitle
[] = "title";
34 const char kKeyIcon
[] = "icon";
35 const char kKeyType
[] = "type";
36 const char kKeyHasChildren
[] = "hasChildren";
38 #if defined(ENABLE_EXTENSIONS)
39 const char kKeyAppsProtectingThis
[] = "appsProtectingThis";
41 const char kKeyName
[] = "name";
42 const char kKeyContent
[] = "content";
43 const char kKeyDomain
[] = "domain";
44 const char kKeyPath
[] = "path";
45 const char kKeySendFor
[] = "sendfor";
46 const char kKeyAccessibleToScript
[] = "accessibleToScript";
47 const char kKeyDesc
[] = "desc";
48 const char kKeySize
[] = "size";
49 const char kKeyOrigin
[] = "origin";
50 const char kKeyManifest
[] = "manifest";
51 const char kKeyServerId
[] = "serverId";
53 const char kKeyAccessed
[] = "accessed";
54 const char kKeyCreated
[] = "created";
55 const char kKeyExpires
[] = "expires";
56 const char kKeyModified
[] = "modified";
58 const char kKeyPersistent
[] = "persistent";
59 const char kKeyTemporary
[] = "temporary";
61 const char kKeyTotalUsage
[] = "totalUsage";
62 const char kKeyTemporaryUsage
[] = "temporaryUsage";
63 const char kKeyPersistentUsage
[] = "persistentUsage";
65 const char kKeyCertType
[] = "certType";
67 const char kKeyScopes
[] = "scopes";
69 const int64 kNegligibleUsage
= 1024; // 1KiB
73 CookiesTreeModelUtil::CookiesTreeModelUtil() {
76 CookiesTreeModelUtil::~CookiesTreeModelUtil() {
79 std::string
CookiesTreeModelUtil::GetTreeNodeId(const CookieTreeNode
* node
) {
80 CookieTreeNodeMap::const_iterator iter
= node_map_
.find(node
);
81 if (iter
!= node_map_
.end())
82 return base::IntToString(iter
->second
);
84 int32 new_id
= id_map_
.Add(node
);
85 node_map_
[node
] = new_id
;
86 return base::IntToString(new_id
);
89 bool CookiesTreeModelUtil::GetCookieTreeNodeDictionary(
90 const CookieTreeNode
& node
,
91 base::DictionaryValue
* dict
) {
92 // Use node's address as an id for WebUI to look it up.
93 dict
->SetString(kKeyId
, GetTreeNodeId(&node
));
94 dict
->SetString(kKeyTitle
, node
.GetTitle());
95 dict
->SetBoolean(kKeyHasChildren
, !node
.empty());
97 switch (node
.GetDetailedInfo().node_type
) {
98 case CookieTreeNode::DetailedInfo::TYPE_HOST
: {
99 dict
->SetString(kKeyType
, "origin");
100 #if defined(OS_MACOSX)
101 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_BOOKMARK_BAR_FOLDER");
105 case CookieTreeNode::DetailedInfo::TYPE_COOKIE
: {
106 dict
->SetString(kKeyType
, "cookie");
107 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_ICON");
109 const net::CanonicalCookie
& cookie
= *node
.GetDetailedInfo().cookie
;
111 dict
->SetString(kKeyName
, cookie
.Name());
112 dict
->SetString(kKeyContent
, cookie
.Value());
113 dict
->SetString(kKeyDomain
, cookie
.Domain());
114 dict
->SetString(kKeyPath
, cookie
.Path());
115 dict
->SetString(kKeySendFor
,
116 l10n_util::GetStringUTF16(
117 CookiesTreeModel::GetSendForMessageID(cookie
)));
118 std::string accessible
= cookie
.IsHttpOnly() ?
119 l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_ACCESSIBLE_TO_SCRIPT_NO
) :
120 l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_ACCESSIBLE_TO_SCRIPT_YES
);
121 dict
->SetString(kKeyAccessibleToScript
, accessible
);
122 dict
->SetString(kKeyCreated
, base::UTF16ToUTF8(
123 base::TimeFormatFriendlyDateAndTime(cookie
.CreationDate())));
124 dict
->SetString(kKeyExpires
, cookie
.IsPersistent() ? base::UTF16ToUTF8(
125 base::TimeFormatFriendlyDateAndTime(cookie
.ExpiryDate())) :
126 l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_EXPIRES_SESSION
));
130 case CookieTreeNode::DetailedInfo::TYPE_DATABASE
: {
131 dict
->SetString(kKeyType
, "database");
132 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
134 const BrowsingDataDatabaseHelper::DatabaseInfo
& database_info
=
135 *node
.GetDetailedInfo().database_info
;
137 dict
->SetString(kKeyName
, database_info
.database_name
.empty() ?
138 l10n_util::GetStringUTF8(IDS_COOKIES_WEB_DATABASE_UNNAMED_NAME
) :
139 database_info
.database_name
);
140 dict
->SetString(kKeyDesc
, database_info
.description
);
141 dict
->SetString(kKeySize
, ui::FormatBytes(database_info
.size
));
142 dict
->SetString(kKeyModified
, base::UTF16ToUTF8(
143 base::TimeFormatFriendlyDateAndTime(database_info
.last_modified
)));
147 case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE
: {
148 dict
->SetString(kKeyType
, "local_storage");
149 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
151 const BrowsingDataLocalStorageHelper::LocalStorageInfo
&
152 local_storage_info
= *node
.GetDetailedInfo().local_storage_info
;
154 dict
->SetString(kKeyOrigin
, local_storage_info
.origin_url
.spec());
155 dict
->SetString(kKeySize
, ui::FormatBytes(local_storage_info
.size
));
156 dict
->SetString(kKeyModified
, base::UTF16ToUTF8(
157 base::TimeFormatFriendlyDateAndTime(
158 local_storage_info
.last_modified
)));
162 case CookieTreeNode::DetailedInfo::TYPE_APPCACHE
: {
163 dict
->SetString(kKeyType
, "app_cache");
164 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
166 const content::AppCacheInfo
& appcache_info
=
167 *node
.GetDetailedInfo().appcache_info
;
169 dict
->SetString(kKeyManifest
, appcache_info
.manifest_url
.spec());
170 dict
->SetString(kKeySize
, ui::FormatBytes(appcache_info
.size
));
171 dict
->SetString(kKeyCreated
, base::UTF16ToUTF8(
172 base::TimeFormatFriendlyDateAndTime(appcache_info
.creation_time
)));
173 dict
->SetString(kKeyAccessed
, base::UTF16ToUTF8(
174 base::TimeFormatFriendlyDateAndTime(appcache_info
.last_access_time
)));
178 case CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB
: {
179 dict
->SetString(kKeyType
, "indexed_db");
180 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
182 const content::IndexedDBInfo
& indexed_db_info
=
183 *node
.GetDetailedInfo().indexed_db_info
;
185 dict
->SetString(kKeyOrigin
, indexed_db_info
.origin
.spec());
186 dict
->SetString(kKeySize
, ui::FormatBytes(indexed_db_info
.size
));
187 dict
->SetString(kKeyModified
,
188 base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
189 indexed_db_info
.last_modified
)));
192 case CookieTreeNode::DetailedInfo::TYPE_FILE_SYSTEM
: {
193 dict
->SetString(kKeyType
, "file_system");
194 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
196 const BrowsingDataFileSystemHelper::FileSystemInfo
& file_system_info
=
197 *node
.GetDetailedInfo().file_system_info
;
198 const storage::FileSystemType kPerm
= storage::kFileSystemTypePersistent
;
199 const storage::FileSystemType kTemp
= storage::kFileSystemTypeTemporary
;
201 dict
->SetString(kKeyOrigin
, file_system_info
.origin
.spec());
202 dict
->SetString(kKeyPersistent
,
203 ContainsKey(file_system_info
.usage_map
, kPerm
) ?
204 base::UTF16ToUTF8(ui::FormatBytes(
205 file_system_info
.usage_map
.find(kPerm
)->second
)) :
206 l10n_util::GetStringUTF8(
207 IDS_COOKIES_FILE_SYSTEM_USAGE_NONE
));
208 dict
->SetString(kKeyTemporary
,
209 ContainsKey(file_system_info
.usage_map
, kTemp
) ?
210 base::UTF16ToUTF8(ui::FormatBytes(
211 file_system_info
.usage_map
.find(kTemp
)->second
)) :
212 l10n_util::GetStringUTF8(
213 IDS_COOKIES_FILE_SYSTEM_USAGE_NONE
));
216 case CookieTreeNode::DetailedInfo::TYPE_QUOTA
: {
217 dict
->SetString(kKeyType
, "quota");
218 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
220 const BrowsingDataQuotaHelper::QuotaInfo
& quota_info
=
221 *node
.GetDetailedInfo().quota_info
;
222 if (quota_info
.temporary_usage
+ quota_info
.persistent_usage
<=
226 dict
->SetString(kKeyOrigin
, quota_info
.host
);
227 dict
->SetString(kKeyTotalUsage
,
228 base::UTF16ToUTF8(ui::FormatBytes(
229 quota_info
.temporary_usage
+
230 quota_info
.persistent_usage
)));
231 dict
->SetString(kKeyTemporaryUsage
,
232 base::UTF16ToUTF8(ui::FormatBytes(
233 quota_info
.temporary_usage
)));
234 dict
->SetString(kKeyPersistentUsage
,
235 base::UTF16ToUTF8(ui::FormatBytes(
236 quota_info
.persistent_usage
)));
239 case CookieTreeNode::DetailedInfo::TYPE_CHANNEL_ID
: {
240 dict
->SetString(kKeyType
, "channel_id");
241 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_ICON");
243 const net::ChannelIDStore::ChannelID
& channel_id
=
244 *node
.GetDetailedInfo().channel_id
;
246 dict
->SetString(kKeyServerId
, channel_id
.server_identifier());
247 dict
->SetString(kKeyCertType
,
248 l10n_util::GetStringUTF8(IDS_CLIENT_CERT_ECDSA_SIGN
));
249 dict
->SetString(kKeyCreated
, base::UTF16ToUTF8(
250 base::TimeFormatFriendlyDateAndTime(
251 channel_id
.creation_time())));
254 case CookieTreeNode::DetailedInfo::TYPE_SERVICE_WORKER
: {
255 dict
->SetString(kKeyType
, "service_worker");
256 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
258 const content::ServiceWorkerUsageInfo
& service_worker_info
=
259 *node
.GetDetailedInfo().service_worker_info
;
261 dict
->SetString(kKeyOrigin
, service_worker_info
.origin
.spec());
262 dict
->SetString(kKeySize
,
263 ui::FormatBytes(service_worker_info
.total_size_bytes
));
264 base::ListValue
* scopes
= new base::ListValue
;
265 for (std::vector
<GURL
>::const_iterator it
=
266 service_worker_info
.scopes
.begin();
267 it
!= service_worker_info
.scopes
.end();
269 scopes
->AppendString(it
->spec());
271 dict
->Set(kKeyScopes
, scopes
);
274 case CookieTreeNode::DetailedInfo::TYPE_CACHE_STORAGE
: {
275 dict
->SetString(kKeyType
, "cache_storage");
276 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
278 const content::CacheStorageUsageInfo
& cache_storage_info
=
279 *node
.GetDetailedInfo().cache_storage_info
;
281 dict
->SetString(kKeyOrigin
, cache_storage_info
.origin
.spec());
282 dict
->SetString(kKeySize
,
283 ui::FormatBytes(cache_storage_info
.total_size_bytes
));
284 dict
->SetString(kKeyModified
,
285 base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
286 cache_storage_info
.last_modified
)));
289 case CookieTreeNode::DetailedInfo::TYPE_FLASH_LSO
: {
290 dict
->SetString(kKeyType
, "flash_lso");
291 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_ICON");
293 dict
->SetString(kKeyDomain
, node
.GetDetailedInfo().flash_lso_domain
);
296 #if defined(OS_MACOSX)
297 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_BOOKMARK_BAR_FOLDER");
302 #if defined(ENABLE_EXTENSIONS)
303 const extensions::ExtensionSet
* protecting_apps
=
304 node
.GetModel()->ExtensionsProtectingNode(node
);
305 if (protecting_apps
&& !protecting_apps
->is_empty()) {
306 base::ListValue
* app_infos
= new base::ListValue
;
307 for (extensions::ExtensionSet::const_iterator it
= protecting_apps
->begin();
308 it
!= protecting_apps
->end(); ++it
) {
309 base::DictionaryValue
* app_info
= new base::DictionaryValue();
310 app_info
->SetString(kKeyId
, (*it
)->id());
311 app_info
->SetString(kKeyName
, (*it
)->name());
312 app_infos
->Append(app_info
);
314 dict
->Set(kKeyAppsProtectingThis
, app_infos
);
321 void CookiesTreeModelUtil::GetChildNodeList(const CookieTreeNode
* parent
,
324 base::ListValue
* nodes
) {
325 for (int i
= 0; i
< count
; ++i
) {
326 scoped_ptr
<base::DictionaryValue
> dict(new base::DictionaryValue
);
327 const CookieTreeNode
* child
= parent
->GetChild(start
+ i
);
328 if (GetCookieTreeNodeDictionary(*child
, dict
.get()))
329 nodes
->Append(dict
.release());
333 const CookieTreeNode
* CookiesTreeModelUtil::GetTreeNodeFromPath(
334 const CookieTreeNode
* root
,
335 const std::string
& path
) {
336 const CookieTreeNode
* child
= NULL
;
337 const CookieTreeNode
* parent
= root
;
338 int child_index
= -1;
340 // Validate the tree path and get the node pointer.
341 for (const base::StringPiece
& cur_node
: base::SplitStringPiece(
342 path
, ",", base::TRIM_WHITESPACE
, base::SPLIT_WANT_ALL
)) {
344 if (!base::StringToInt(cur_node
, &node_id
))
347 child
= id_map_
.Lookup(node_id
);
348 child_index
= parent
->GetIndexOf(child
);
349 if (child_index
== -1)
355 return child_index
>= 0 ? child
: NULL
;