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/indexed_db_context.h"
19 #include "content/public/browser/service_worker_context.h"
20 #include "net/cookies/canonical_cookie.h"
21 #include "net/ssl/ssl_client_cert_type.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
71 std::string
ClientCertTypeToString(net::SSLClientCertType type
) {
73 case net::CLIENT_CERT_RSA_SIGN
:
74 return l10n_util::GetStringUTF8(IDS_CLIENT_CERT_RSA_SIGN
);
75 case net::CLIENT_CERT_DSS_SIGN
:
76 return l10n_util::GetStringUTF8(IDS_CLIENT_CERT_DSS_SIGN
);
77 case net::CLIENT_CERT_ECDSA_SIGN
:
78 return l10n_util::GetStringUTF8(IDS_CLIENT_CERT_ECDSA_SIGN
);
80 return base::IntToString(type
);
86 CookiesTreeModelUtil::CookiesTreeModelUtil() {
89 CookiesTreeModelUtil::~CookiesTreeModelUtil() {
92 std::string
CookiesTreeModelUtil::GetTreeNodeId(const CookieTreeNode
* node
) {
93 CookieTreeNodeMap::const_iterator iter
= node_map_
.find(node
);
94 if (iter
!= node_map_
.end())
95 return base::IntToString(iter
->second
);
97 int32 new_id
= id_map_
.Add(node
);
98 node_map_
[node
] = new_id
;
99 return base::IntToString(new_id
);
102 bool CookiesTreeModelUtil::GetCookieTreeNodeDictionary(
103 const CookieTreeNode
& node
,
104 base::DictionaryValue
* dict
) {
105 // Use node's address as an id for WebUI to look it up.
106 dict
->SetString(kKeyId
, GetTreeNodeId(&node
));
107 dict
->SetString(kKeyTitle
, node
.GetTitle());
108 dict
->SetBoolean(kKeyHasChildren
, !node
.empty());
110 switch (node
.GetDetailedInfo().node_type
) {
111 case CookieTreeNode::DetailedInfo::TYPE_HOST
: {
112 dict
->SetString(kKeyType
, "origin");
113 #if defined(OS_MACOSX)
114 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_BOOKMARK_BAR_FOLDER");
118 case CookieTreeNode::DetailedInfo::TYPE_COOKIE
: {
119 dict
->SetString(kKeyType
, "cookie");
120 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_ICON");
122 const net::CanonicalCookie
& cookie
= *node
.GetDetailedInfo().cookie
;
124 dict
->SetString(kKeyName
, cookie
.Name());
125 dict
->SetString(kKeyContent
, cookie
.Value());
126 dict
->SetString(kKeyDomain
, cookie
.Domain());
127 dict
->SetString(kKeyPath
, cookie
.Path());
128 dict
->SetString(kKeySendFor
,
129 l10n_util::GetStringUTF16(
130 CookiesTreeModel::GetSendForMessageID(cookie
)));
131 std::string accessible
= cookie
.IsHttpOnly() ?
132 l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_ACCESSIBLE_TO_SCRIPT_NO
) :
133 l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_ACCESSIBLE_TO_SCRIPT_YES
);
134 dict
->SetString(kKeyAccessibleToScript
, accessible
);
135 dict
->SetString(kKeyCreated
, base::UTF16ToUTF8(
136 base::TimeFormatFriendlyDateAndTime(cookie
.CreationDate())));
137 dict
->SetString(kKeyExpires
, cookie
.IsPersistent() ? base::UTF16ToUTF8(
138 base::TimeFormatFriendlyDateAndTime(cookie
.ExpiryDate())) :
139 l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_EXPIRES_SESSION
));
143 case CookieTreeNode::DetailedInfo::TYPE_DATABASE
: {
144 dict
->SetString(kKeyType
, "database");
145 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
147 const BrowsingDataDatabaseHelper::DatabaseInfo
& database_info
=
148 *node
.GetDetailedInfo().database_info
;
150 dict
->SetString(kKeyName
, database_info
.database_name
.empty() ?
151 l10n_util::GetStringUTF8(IDS_COOKIES_WEB_DATABASE_UNNAMED_NAME
) :
152 database_info
.database_name
);
153 dict
->SetString(kKeyDesc
, database_info
.description
);
154 dict
->SetString(kKeySize
, ui::FormatBytes(database_info
.size
));
155 dict
->SetString(kKeyModified
, base::UTF16ToUTF8(
156 base::TimeFormatFriendlyDateAndTime(database_info
.last_modified
)));
160 case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE
: {
161 dict
->SetString(kKeyType
, "local_storage");
162 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
164 const BrowsingDataLocalStorageHelper::LocalStorageInfo
&
165 local_storage_info
= *node
.GetDetailedInfo().local_storage_info
;
167 dict
->SetString(kKeyOrigin
, local_storage_info
.origin_url
.spec());
168 dict
->SetString(kKeySize
, ui::FormatBytes(local_storage_info
.size
));
169 dict
->SetString(kKeyModified
, base::UTF16ToUTF8(
170 base::TimeFormatFriendlyDateAndTime(
171 local_storage_info
.last_modified
)));
175 case CookieTreeNode::DetailedInfo::TYPE_APPCACHE
: {
176 dict
->SetString(kKeyType
, "app_cache");
177 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
179 const content::AppCacheInfo
& appcache_info
=
180 *node
.GetDetailedInfo().appcache_info
;
182 dict
->SetString(kKeyManifest
, appcache_info
.manifest_url
.spec());
183 dict
->SetString(kKeySize
, ui::FormatBytes(appcache_info
.size
));
184 dict
->SetString(kKeyCreated
, base::UTF16ToUTF8(
185 base::TimeFormatFriendlyDateAndTime(appcache_info
.creation_time
)));
186 dict
->SetString(kKeyAccessed
, base::UTF16ToUTF8(
187 base::TimeFormatFriendlyDateAndTime(appcache_info
.last_access_time
)));
191 case CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB
: {
192 dict
->SetString(kKeyType
, "indexed_db");
193 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
195 const content::IndexedDBInfo
& indexed_db_info
=
196 *node
.GetDetailedInfo().indexed_db_info
;
198 dict
->SetString(kKeyOrigin
, indexed_db_info
.origin_
.spec());
199 dict
->SetString(kKeySize
, ui::FormatBytes(indexed_db_info
.size_
));
200 dict
->SetString(kKeyModified
, base::UTF16ToUTF8(
201 base::TimeFormatFriendlyDateAndTime(indexed_db_info
.last_modified_
)));
205 case CookieTreeNode::DetailedInfo::TYPE_FILE_SYSTEM
: {
206 dict
->SetString(kKeyType
, "file_system");
207 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
209 const BrowsingDataFileSystemHelper::FileSystemInfo
& file_system_info
=
210 *node
.GetDetailedInfo().file_system_info
;
211 const storage::FileSystemType kPerm
= storage::kFileSystemTypePersistent
;
212 const storage::FileSystemType kTemp
= storage::kFileSystemTypeTemporary
;
214 dict
->SetString(kKeyOrigin
, file_system_info
.origin
.spec());
215 dict
->SetString(kKeyPersistent
,
216 ContainsKey(file_system_info
.usage_map
, kPerm
) ?
217 base::UTF16ToUTF8(ui::FormatBytes(
218 file_system_info
.usage_map
.find(kPerm
)->second
)) :
219 l10n_util::GetStringUTF8(
220 IDS_COOKIES_FILE_SYSTEM_USAGE_NONE
));
221 dict
->SetString(kKeyTemporary
,
222 ContainsKey(file_system_info
.usage_map
, kTemp
) ?
223 base::UTF16ToUTF8(ui::FormatBytes(
224 file_system_info
.usage_map
.find(kTemp
)->second
)) :
225 l10n_util::GetStringUTF8(
226 IDS_COOKIES_FILE_SYSTEM_USAGE_NONE
));
229 case CookieTreeNode::DetailedInfo::TYPE_QUOTA
: {
230 dict
->SetString(kKeyType
, "quota");
231 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
233 const BrowsingDataQuotaHelper::QuotaInfo
& quota_info
=
234 *node
.GetDetailedInfo().quota_info
;
235 if (quota_info
.temporary_usage
+ quota_info
.persistent_usage
<=
239 dict
->SetString(kKeyOrigin
, quota_info
.host
);
240 dict
->SetString(kKeyTotalUsage
,
241 base::UTF16ToUTF8(ui::FormatBytes(
242 quota_info
.temporary_usage
+
243 quota_info
.persistent_usage
)));
244 dict
->SetString(kKeyTemporaryUsage
,
245 base::UTF16ToUTF8(ui::FormatBytes(
246 quota_info
.temporary_usage
)));
247 dict
->SetString(kKeyPersistentUsage
,
248 base::UTF16ToUTF8(ui::FormatBytes(
249 quota_info
.persistent_usage
)));
252 case CookieTreeNode::DetailedInfo::TYPE_CHANNEL_ID
: {
253 dict
->SetString(kKeyType
, "channel_id");
254 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_ICON");
256 const net::ChannelIDStore::ChannelID
& channel_id
=
257 *node
.GetDetailedInfo().channel_id
;
259 dict
->SetString(kKeyServerId
, channel_id
.server_identifier());
260 dict
->SetString(kKeyCertType
,
261 ClientCertTypeToString(net::CLIENT_CERT_ECDSA_SIGN
));
262 dict
->SetString(kKeyCreated
, base::UTF16ToUTF8(
263 base::TimeFormatFriendlyDateAndTime(
264 channel_id
.creation_time())));
267 case CookieTreeNode::DetailedInfo::TYPE_SERVICE_WORKER
: {
268 dict
->SetString(kKeyType
, "service_worker");
269 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
271 const content::ServiceWorkerUsageInfo
& service_worker_info
=
272 *node
.GetDetailedInfo().service_worker_info
;
274 dict
->SetString(kKeyOrigin
, service_worker_info
.origin
.spec());
275 dict
->SetString(kKeySize
,
276 ui::FormatBytes(service_worker_info
.total_size_bytes
));
277 base::ListValue
* scopes
= new base::ListValue
;
278 for (std::vector
<GURL
>::const_iterator it
=
279 service_worker_info
.scopes
.begin();
280 it
!= service_worker_info
.scopes
.end();
282 scopes
->AppendString(it
->spec());
284 dict
->Set(kKeyScopes
, scopes
);
287 case CookieTreeNode::DetailedInfo::TYPE_FLASH_LSO
: {
288 dict
->SetString(kKeyType
, "flash_lso");
289 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_ICON");
291 dict
->SetString(kKeyDomain
, node
.GetDetailedInfo().flash_lso_domain
);
294 #if defined(OS_MACOSX)
295 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_BOOKMARK_BAR_FOLDER");
300 #if defined(ENABLE_EXTENSIONS)
301 const extensions::ExtensionSet
* protecting_apps
=
302 node
.GetModel()->ExtensionsProtectingNode(node
);
303 if (protecting_apps
&& !protecting_apps
->is_empty()) {
304 base::ListValue
* app_infos
= new base::ListValue
;
305 for (extensions::ExtensionSet::const_iterator it
= protecting_apps
->begin();
306 it
!= protecting_apps
->end(); ++it
) {
307 base::DictionaryValue
* app_info
= new base::DictionaryValue();
308 app_info
->SetString(kKeyId
, (*it
)->id());
309 app_info
->SetString(kKeyName
, (*it
)->name());
310 app_infos
->Append(app_info
);
312 dict
->Set(kKeyAppsProtectingThis
, app_infos
);
319 void CookiesTreeModelUtil::GetChildNodeList(const CookieTreeNode
* parent
,
322 base::ListValue
* nodes
) {
323 for (int i
= 0; i
< count
; ++i
) {
324 scoped_ptr
<base::DictionaryValue
> dict(new base::DictionaryValue
);
325 const CookieTreeNode
* child
= parent
->GetChild(start
+ i
);
326 if (GetCookieTreeNodeDictionary(*child
, dict
.get()))
327 nodes
->Append(dict
.release());
331 const CookieTreeNode
* CookiesTreeModelUtil::GetTreeNodeFromPath(
332 const CookieTreeNode
* root
,
333 const std::string
& path
) {
334 std::vector
<std::string
> node_ids
;
335 base::SplitString(path
, ',', &node_ids
);
337 const CookieTreeNode
* child
= NULL
;
338 const CookieTreeNode
* parent
= root
;
339 int child_index
= -1;
341 // Validate the tree path and get the node pointer.
342 for (size_t i
= 0; i
< node_ids
.size(); ++i
) {
344 if (!base::StringToInt(node_ids
[i
], &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
;