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 "storage/common/fileapi/file_system_types.h"
22 #include "ui/base/l10n/l10n_util.h"
23 #include "ui/base/text/bytes_formatting.h"
25 #if defined(ENABLE_EXTENSIONS)
26 #include "extensions/common/extension_set.h"
31 const char kKeyId
[] = "id";
32 const char kKeyTitle
[] = "title";
33 const char kKeyIcon
[] = "icon";
34 const char kKeyType
[] = "type";
35 const char kKeyHasChildren
[] = "hasChildren";
37 #if defined(ENABLE_EXTENSIONS)
38 const char kKeyAppsProtectingThis
[] = "appsProtectingThis";
40 const char kKeyName
[] = "name";
41 const char kKeyContent
[] = "content";
42 const char kKeyDomain
[] = "domain";
43 const char kKeyPath
[] = "path";
44 const char kKeySendFor
[] = "sendfor";
45 const char kKeyAccessibleToScript
[] = "accessibleToScript";
46 const char kKeyDesc
[] = "desc";
47 const char kKeySize
[] = "size";
48 const char kKeyOrigin
[] = "origin";
49 const char kKeyManifest
[] = "manifest";
50 const char kKeyServerId
[] = "serverId";
52 const char kKeyAccessed
[] = "accessed";
53 const char kKeyCreated
[] = "created";
54 const char kKeyExpires
[] = "expires";
55 const char kKeyModified
[] = "modified";
57 const char kKeyPersistent
[] = "persistent";
58 const char kKeyTemporary
[] = "temporary";
60 const char kKeyTotalUsage
[] = "totalUsage";
61 const char kKeyTemporaryUsage
[] = "temporaryUsage";
62 const char kKeyPersistentUsage
[] = "persistentUsage";
64 const char kKeyCertType
[] = "certType";
66 const char kKeyScopes
[] = "scopes";
68 const int64 kNegligibleUsage
= 1024; // 1KiB
72 CookiesTreeModelUtil::CookiesTreeModelUtil() {
75 CookiesTreeModelUtil::~CookiesTreeModelUtil() {
78 std::string
CookiesTreeModelUtil::GetTreeNodeId(const CookieTreeNode
* node
) {
79 CookieTreeNodeMap::const_iterator iter
= node_map_
.find(node
);
80 if (iter
!= node_map_
.end())
81 return base::IntToString(iter
->second
);
83 int32 new_id
= id_map_
.Add(node
);
84 node_map_
[node
] = new_id
;
85 return base::IntToString(new_id
);
88 bool CookiesTreeModelUtil::GetCookieTreeNodeDictionary(
89 const CookieTreeNode
& node
,
90 base::DictionaryValue
* dict
) {
91 // Use node's address as an id for WebUI to look it up.
92 dict
->SetString(kKeyId
, GetTreeNodeId(&node
));
93 dict
->SetString(kKeyTitle
, node
.GetTitle());
94 dict
->SetBoolean(kKeyHasChildren
, !node
.empty());
96 switch (node
.GetDetailedInfo().node_type
) {
97 case CookieTreeNode::DetailedInfo::TYPE_HOST
: {
98 dict
->SetString(kKeyType
, "origin");
99 #if defined(OS_MACOSX)
100 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_BOOKMARK_BAR_FOLDER");
104 case CookieTreeNode::DetailedInfo::TYPE_COOKIE
: {
105 dict
->SetString(kKeyType
, "cookie");
106 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_ICON");
108 const net::CanonicalCookie
& cookie
= *node
.GetDetailedInfo().cookie
;
110 dict
->SetString(kKeyName
, cookie
.Name());
111 dict
->SetString(kKeyContent
, cookie
.Value());
112 dict
->SetString(kKeyDomain
, cookie
.Domain());
113 dict
->SetString(kKeyPath
, cookie
.Path());
114 dict
->SetString(kKeySendFor
,
115 l10n_util::GetStringUTF16(
116 CookiesTreeModel::GetSendForMessageID(cookie
)));
117 std::string accessible
= cookie
.IsHttpOnly() ?
118 l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_ACCESSIBLE_TO_SCRIPT_NO
) :
119 l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_ACCESSIBLE_TO_SCRIPT_YES
);
120 dict
->SetString(kKeyAccessibleToScript
, accessible
);
121 dict
->SetString(kKeyCreated
, base::UTF16ToUTF8(
122 base::TimeFormatFriendlyDateAndTime(cookie
.CreationDate())));
123 dict
->SetString(kKeyExpires
, cookie
.IsPersistent() ? base::UTF16ToUTF8(
124 base::TimeFormatFriendlyDateAndTime(cookie
.ExpiryDate())) :
125 l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_EXPIRES_SESSION
));
129 case CookieTreeNode::DetailedInfo::TYPE_DATABASE
: {
130 dict
->SetString(kKeyType
, "database");
131 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
133 const BrowsingDataDatabaseHelper::DatabaseInfo
& database_info
=
134 *node
.GetDetailedInfo().database_info
;
136 dict
->SetString(kKeyName
, database_info
.database_name
.empty() ?
137 l10n_util::GetStringUTF8(IDS_COOKIES_WEB_DATABASE_UNNAMED_NAME
) :
138 database_info
.database_name
);
139 dict
->SetString(kKeyDesc
, database_info
.description
);
140 dict
->SetString(kKeySize
, ui::FormatBytes(database_info
.size
));
141 dict
->SetString(kKeyModified
, base::UTF16ToUTF8(
142 base::TimeFormatFriendlyDateAndTime(database_info
.last_modified
)));
146 case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE
: {
147 dict
->SetString(kKeyType
, "local_storage");
148 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
150 const BrowsingDataLocalStorageHelper::LocalStorageInfo
&
151 local_storage_info
= *node
.GetDetailedInfo().local_storage_info
;
153 dict
->SetString(kKeyOrigin
, local_storage_info
.origin_url
.spec());
154 dict
->SetString(kKeySize
, ui::FormatBytes(local_storage_info
.size
));
155 dict
->SetString(kKeyModified
, base::UTF16ToUTF8(
156 base::TimeFormatFriendlyDateAndTime(
157 local_storage_info
.last_modified
)));
161 case CookieTreeNode::DetailedInfo::TYPE_APPCACHE
: {
162 dict
->SetString(kKeyType
, "app_cache");
163 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
165 const content::AppCacheInfo
& appcache_info
=
166 *node
.GetDetailedInfo().appcache_info
;
168 dict
->SetString(kKeyManifest
, appcache_info
.manifest_url
.spec());
169 dict
->SetString(kKeySize
, ui::FormatBytes(appcache_info
.size
));
170 dict
->SetString(kKeyCreated
, base::UTF16ToUTF8(
171 base::TimeFormatFriendlyDateAndTime(appcache_info
.creation_time
)));
172 dict
->SetString(kKeyAccessed
, base::UTF16ToUTF8(
173 base::TimeFormatFriendlyDateAndTime(appcache_info
.last_access_time
)));
177 case CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB
: {
178 dict
->SetString(kKeyType
, "indexed_db");
179 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
181 const content::IndexedDBInfo
& indexed_db_info
=
182 *node
.GetDetailedInfo().indexed_db_info
;
184 dict
->SetString(kKeyOrigin
, indexed_db_info
.origin_
.spec());
185 dict
->SetString(kKeySize
, ui::FormatBytes(indexed_db_info
.size_
));
186 dict
->SetString(kKeyModified
, base::UTF16ToUTF8(
187 base::TimeFormatFriendlyDateAndTime(indexed_db_info
.last_modified_
)));
191 case CookieTreeNode::DetailedInfo::TYPE_FILE_SYSTEM
: {
192 dict
->SetString(kKeyType
, "file_system");
193 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
195 const BrowsingDataFileSystemHelper::FileSystemInfo
& file_system_info
=
196 *node
.GetDetailedInfo().file_system_info
;
197 const storage::FileSystemType kPerm
= storage::kFileSystemTypePersistent
;
198 const storage::FileSystemType kTemp
= storage::kFileSystemTypeTemporary
;
200 dict
->SetString(kKeyOrigin
, file_system_info
.origin
.spec());
201 dict
->SetString(kKeyPersistent
,
202 ContainsKey(file_system_info
.usage_map
, kPerm
) ?
203 base::UTF16ToUTF8(ui::FormatBytes(
204 file_system_info
.usage_map
.find(kPerm
)->second
)) :
205 l10n_util::GetStringUTF8(
206 IDS_COOKIES_FILE_SYSTEM_USAGE_NONE
));
207 dict
->SetString(kKeyTemporary
,
208 ContainsKey(file_system_info
.usage_map
, kTemp
) ?
209 base::UTF16ToUTF8(ui::FormatBytes(
210 file_system_info
.usage_map
.find(kTemp
)->second
)) :
211 l10n_util::GetStringUTF8(
212 IDS_COOKIES_FILE_SYSTEM_USAGE_NONE
));
215 case CookieTreeNode::DetailedInfo::TYPE_QUOTA
: {
216 dict
->SetString(kKeyType
, "quota");
217 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
219 const BrowsingDataQuotaHelper::QuotaInfo
& quota_info
=
220 *node
.GetDetailedInfo().quota_info
;
221 if (quota_info
.temporary_usage
+ quota_info
.persistent_usage
<=
225 dict
->SetString(kKeyOrigin
, quota_info
.host
);
226 dict
->SetString(kKeyTotalUsage
,
227 base::UTF16ToUTF8(ui::FormatBytes(
228 quota_info
.temporary_usage
+
229 quota_info
.persistent_usage
)));
230 dict
->SetString(kKeyTemporaryUsage
,
231 base::UTF16ToUTF8(ui::FormatBytes(
232 quota_info
.temporary_usage
)));
233 dict
->SetString(kKeyPersistentUsage
,
234 base::UTF16ToUTF8(ui::FormatBytes(
235 quota_info
.persistent_usage
)));
238 case CookieTreeNode::DetailedInfo::TYPE_CHANNEL_ID
: {
239 dict
->SetString(kKeyType
, "channel_id");
240 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_ICON");
242 const net::ChannelIDStore::ChannelID
& channel_id
=
243 *node
.GetDetailedInfo().channel_id
;
245 dict
->SetString(kKeyServerId
, channel_id
.server_identifier());
246 dict
->SetString(kKeyCertType
,
247 l10n_util::GetStringUTF8(IDS_CLIENT_CERT_ECDSA_SIGN
));
248 dict
->SetString(kKeyCreated
, base::UTF16ToUTF8(
249 base::TimeFormatFriendlyDateAndTime(
250 channel_id
.creation_time())));
253 case CookieTreeNode::DetailedInfo::TYPE_SERVICE_WORKER
: {
254 dict
->SetString(kKeyType
, "service_worker");
255 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
257 const content::ServiceWorkerUsageInfo
& service_worker_info
=
258 *node
.GetDetailedInfo().service_worker_info
;
260 dict
->SetString(kKeyOrigin
, service_worker_info
.origin
.spec());
261 dict
->SetString(kKeySize
,
262 ui::FormatBytes(service_worker_info
.total_size_bytes
));
263 base::ListValue
* scopes
= new base::ListValue
;
264 for (std::vector
<GURL
>::const_iterator it
=
265 service_worker_info
.scopes
.begin();
266 it
!= service_worker_info
.scopes
.end();
268 scopes
->AppendString(it
->spec());
270 dict
->Set(kKeyScopes
, scopes
);
273 case CookieTreeNode::DetailedInfo::TYPE_FLASH_LSO
: {
274 dict
->SetString(kKeyType
, "flash_lso");
275 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_COOKIE_ICON");
277 dict
->SetString(kKeyDomain
, node
.GetDetailedInfo().flash_lso_domain
);
280 #if defined(OS_MACOSX)
281 dict
->SetString(kKeyIcon
, "chrome://theme/IDR_BOOKMARK_BAR_FOLDER");
286 #if defined(ENABLE_EXTENSIONS)
287 const extensions::ExtensionSet
* protecting_apps
=
288 node
.GetModel()->ExtensionsProtectingNode(node
);
289 if (protecting_apps
&& !protecting_apps
->is_empty()) {
290 base::ListValue
* app_infos
= new base::ListValue
;
291 for (extensions::ExtensionSet::const_iterator it
= protecting_apps
->begin();
292 it
!= protecting_apps
->end(); ++it
) {
293 base::DictionaryValue
* app_info
= new base::DictionaryValue();
294 app_info
->SetString(kKeyId
, (*it
)->id());
295 app_info
->SetString(kKeyName
, (*it
)->name());
296 app_infos
->Append(app_info
);
298 dict
->Set(kKeyAppsProtectingThis
, app_infos
);
305 void CookiesTreeModelUtil::GetChildNodeList(const CookieTreeNode
* parent
,
308 base::ListValue
* nodes
) {
309 for (int i
= 0; i
< count
; ++i
) {
310 scoped_ptr
<base::DictionaryValue
> dict(new base::DictionaryValue
);
311 const CookieTreeNode
* child
= parent
->GetChild(start
+ i
);
312 if (GetCookieTreeNodeDictionary(*child
, dict
.get()))
313 nodes
->Append(dict
.release());
317 const CookieTreeNode
* CookiesTreeModelUtil::GetTreeNodeFromPath(
318 const CookieTreeNode
* root
,
319 const std::string
& path
) {
320 const CookieTreeNode
* child
= NULL
;
321 const CookieTreeNode
* parent
= root
;
322 int child_index
= -1;
324 // Validate the tree path and get the node pointer.
325 for (const base::StringPiece
& cur_node
: base::SplitStringPiece(
326 path
, ",", base::TRIM_WHITESPACE
, base::SPLIT_WANT_ALL
)) {
328 if (!base::StringToInt(cur_node
, &node_id
))
331 child
= id_map_
.Lookup(node_id
);
332 child_index
= parent
->GetIndexOf(child
);
333 if (child_index
== -1)
339 return child_index
>= 0 ? child
: NULL
;