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. 4 5 #include "chrome/browser/ui/webui/cookies_tree_model_util.h" 6 7 #include <vector> 8 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 "content/public/browser/indexed_db_context.h" 18 #include "extensions/common/extension_set.h" 19 #include "grit/generated_resources.h" 20 #include "net/cookies/canonical_cookie.h" 21 #include "net/ssl/ssl_client_cert_type.h" 22 #include "ui/base/l10n/l10n_util.h" 23 #include "ui/base/text/bytes_formatting.h" 24 #include "webkit/common/fileapi/file_system_types.h" 25 26 namespace { 27 28 const char kKeyId[] = "id"; 29 const char kKeyTitle[] = "title"; 30 const char kKeyIcon[] = "icon"; 31 const char kKeyType[] = "type"; 32 const char kKeyHasChildren[] = "hasChildren"; 33 34 const char kKeyAppsProtectingThis[] = "appsProtectingThis"; 35 const char kKeyName[] = "name"; 36 const char kKeyContent[] = "content"; 37 const char kKeyDomain[] = "domain"; 38 const char kKeyPath[] = "path"; 39 const char kKeySendFor[] = "sendfor"; 40 const char kKeyAccessibleToScript[] = "accessibleToScript"; 41 const char kKeyDesc[] = "desc"; 42 const char kKeySize[] = "size"; 43 const char kKeyOrigin[] = "origin"; 44 const char kKeyManifest[] = "manifest"; 45 const char kKeyServerId[] = "serverId"; 46 47 const char kKeyAccessed[] = "accessed"; 48 const char kKeyCreated[] = "created"; 49 const char kKeyExpires[] = "expires"; 50 const char kKeyModified[] = "modified"; 51 52 const char kKeyPersistent[] = "persistent"; 53 const char kKeyTemporary[] = "temporary"; 54 55 const char kKeyTotalUsage[] = "totalUsage"; 56 const char kKeyTemporaryUsage[] = "temporaryUsage"; 57 const char kKeyPersistentUsage[] = "persistentUsage"; 58 59 const char kKeyCertType[] = "certType"; 60 61 const int64 kNegligibleUsage = 1024; // 1KiB 62 63 std::string ClientCertTypeToString(net::SSLClientCertType type) { 64 switch (type) { 65 case net::CLIENT_CERT_RSA_SIGN: 66 return l10n_util::GetStringUTF8(IDS_CLIENT_CERT_RSA_SIGN); 67 case net::CLIENT_CERT_DSS_SIGN: 68 return l10n_util::GetStringUTF8(IDS_CLIENT_CERT_DSS_SIGN); 69 case net::CLIENT_CERT_ECDSA_SIGN: 70 return l10n_util::GetStringUTF8(IDS_CLIENT_CERT_ECDSA_SIGN); 71 default: 72 return base::IntToString(type); 73 } 74 } 75 76 } // namespace 77 78 CookiesTreeModelUtil::CookiesTreeModelUtil() { 79 } 80 81 CookiesTreeModelUtil::~CookiesTreeModelUtil() { 82 } 83 84 std::string CookiesTreeModelUtil::GetTreeNodeId(const CookieTreeNode* node) { 85 CookieTreeNodeMap::const_iterator iter = node_map_.find(node); 86 if (iter != node_map_.end()) 87 return base::IntToString(iter->second); 88 89 int32 new_id = id_map_.Add(node); 90 node_map_[node] = new_id; 91 return base::IntToString(new_id); 92 } 93 94 bool CookiesTreeModelUtil::GetCookieTreeNodeDictionary( 95 const CookieTreeNode& node, 96 base::DictionaryValue* dict) { 97 // Use node's address as an id for WebUI to look it up. 98 dict->SetString(kKeyId, GetTreeNodeId(&node)); 99 dict->SetString(kKeyTitle, node.GetTitle()); 100 dict->SetBoolean(kKeyHasChildren, !node.empty()); 101 102 switch (node.GetDetailedInfo().node_type) { 103 case CookieTreeNode::DetailedInfo::TYPE_HOST: { 104 dict->SetString(kKeyType, "origin"); 105 #if defined(OS_MACOSX) 106 dict->SetString(kKeyIcon, "chrome://theme/IDR_BOOKMARK_BAR_FOLDER"); 107 #endif 108 break; 109 } 110 case CookieTreeNode::DetailedInfo::TYPE_COOKIE: { 111 dict->SetString(kKeyType, "cookie"); 112 dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_ICON"); 113 114 const net::CanonicalCookie& cookie = *node.GetDetailedInfo().cookie; 115 116 dict->SetString(kKeyName, cookie.Name()); 117 dict->SetString(kKeyContent, cookie.Value()); 118 dict->SetString(kKeyDomain, cookie.Domain()); 119 dict->SetString(kKeyPath, cookie.Path()); 120 dict->SetString(kKeySendFor, cookie.IsSecure() ? 121 l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_SENDFOR_SECURE) : 122 l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_SENDFOR_ANY)); 123 std::string accessible = cookie.IsHttpOnly() ? 124 l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_ACCESSIBLE_TO_SCRIPT_NO) : 125 l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_ACCESSIBLE_TO_SCRIPT_YES); 126 dict->SetString(kKeyAccessibleToScript, accessible); 127 dict->SetString(kKeyCreated, base::UTF16ToUTF8( 128 base::TimeFormatFriendlyDateAndTime(cookie.CreationDate()))); 129 dict->SetString(kKeyExpires, cookie.IsPersistent() ? base::UTF16ToUTF8( 130 base::TimeFormatFriendlyDateAndTime(cookie.ExpiryDate())) : 131 l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_EXPIRES_SESSION)); 132 133 break; 134 } 135 case CookieTreeNode::DetailedInfo::TYPE_DATABASE: { 136 dict->SetString(kKeyType, "database"); 137 dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON"); 138 139 const BrowsingDataDatabaseHelper::DatabaseInfo& database_info = 140 *node.GetDetailedInfo().database_info; 141 142 dict->SetString(kKeyName, database_info.database_name.empty() ? 143 l10n_util::GetStringUTF8(IDS_COOKIES_WEB_DATABASE_UNNAMED_NAME) : 144 database_info.database_name); 145 dict->SetString(kKeyDesc, database_info.description); 146 dict->SetString(kKeySize, ui::FormatBytes(database_info.size)); 147 dict->SetString(kKeyModified, base::UTF16ToUTF8( 148 base::TimeFormatFriendlyDateAndTime(database_info.last_modified))); 149 150 break; 151 } 152 case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE: { 153 dict->SetString(kKeyType, "local_storage"); 154 dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON"); 155 156 const BrowsingDataLocalStorageHelper::LocalStorageInfo& 157 local_storage_info = *node.GetDetailedInfo().local_storage_info; 158 159 dict->SetString(kKeyOrigin, local_storage_info.origin_url.spec()); 160 dict->SetString(kKeySize, ui::FormatBytes(local_storage_info.size)); 161 dict->SetString(kKeyModified, base::UTF16ToUTF8( 162 base::TimeFormatFriendlyDateAndTime( 163 local_storage_info.last_modified))); 164 165 break; 166 } 167 case CookieTreeNode::DetailedInfo::TYPE_APPCACHE: { 168 dict->SetString(kKeyType, "app_cache"); 169 dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON"); 170 171 const appcache::AppCacheInfo& appcache_info = 172 *node.GetDetailedInfo().appcache_info; 173 174 dict->SetString(kKeyManifest, appcache_info.manifest_url.spec()); 175 dict->SetString(kKeySize, ui::FormatBytes(appcache_info.size)); 176 dict->SetString(kKeyCreated, base::UTF16ToUTF8( 177 base::TimeFormatFriendlyDateAndTime(appcache_info.creation_time))); 178 dict->SetString(kKeyAccessed, base::UTF16ToUTF8( 179 base::TimeFormatFriendlyDateAndTime(appcache_info.last_access_time))); 180 181 break; 182 } 183 case CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB: { 184 dict->SetString(kKeyType, "indexed_db"); 185 dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON"); 186 187 const content::IndexedDBInfo& indexed_db_info = 188 *node.GetDetailedInfo().indexed_db_info; 189 190 dict->SetString(kKeyOrigin, indexed_db_info.origin_.spec()); 191 dict->SetString(kKeySize, ui::FormatBytes(indexed_db_info.size_)); 192 dict->SetString(kKeyModified, base::UTF16ToUTF8( 193 base::TimeFormatFriendlyDateAndTime(indexed_db_info.last_modified_))); 194 195 break; 196 } 197 case CookieTreeNode::DetailedInfo::TYPE_FILE_SYSTEM: { 198 dict->SetString(kKeyType, "file_system"); 199 dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON"); 200 201 const BrowsingDataFileSystemHelper::FileSystemInfo& file_system_info = 202 *node.GetDetailedInfo().file_system_info; 203 const fileapi::FileSystemType kPerm = fileapi::kFileSystemTypePersistent; 204 const fileapi::FileSystemType kTemp = fileapi::kFileSystemTypeTemporary; 205 206 dict->SetString(kKeyOrigin, file_system_info.origin.spec()); 207 dict->SetString(kKeyPersistent, 208 ContainsKey(file_system_info.usage_map, kPerm) ? 209 base::UTF16ToUTF8(ui::FormatBytes( 210 file_system_info.usage_map.find(kPerm)->second)) : 211 l10n_util::GetStringUTF8( 212 IDS_COOKIES_FILE_SYSTEM_USAGE_NONE)); 213 dict->SetString(kKeyTemporary, 214 ContainsKey(file_system_info.usage_map, kTemp) ? 215 base::UTF16ToUTF8(ui::FormatBytes( 216 file_system_info.usage_map.find(kTemp)->second)) : 217 l10n_util::GetStringUTF8( 218 IDS_COOKIES_FILE_SYSTEM_USAGE_NONE)); 219 break; 220 } 221 case CookieTreeNode::DetailedInfo::TYPE_QUOTA: { 222 dict->SetString(kKeyType, "quota"); 223 dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON"); 224 225 const BrowsingDataQuotaHelper::QuotaInfo& quota_info = 226 *node.GetDetailedInfo().quota_info; 227 if (quota_info.temporary_usage + quota_info.persistent_usage <= 228 kNegligibleUsage) 229 return false; 230 231 dict->SetString(kKeyOrigin, quota_info.host); 232 dict->SetString(kKeyTotalUsage, 233 base::UTF16ToUTF8(ui::FormatBytes( 234 quota_info.temporary_usage + 235 quota_info.persistent_usage))); 236 dict->SetString(kKeyTemporaryUsage, 237 base::UTF16ToUTF8(ui::FormatBytes( 238 quota_info.temporary_usage))); 239 dict->SetString(kKeyPersistentUsage, 240 base::UTF16ToUTF8(ui::FormatBytes( 241 quota_info.persistent_usage))); 242 break; 243 } 244 case CookieTreeNode::DetailedInfo::TYPE_SERVER_BOUND_CERT: { 245 dict->SetString(kKeyType, "server_bound_cert"); 246 dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_ICON"); 247 248 const net::ServerBoundCertStore::ServerBoundCert& server_bound_cert = 249 *node.GetDetailedInfo().server_bound_cert; 250 251 dict->SetString(kKeyServerId, server_bound_cert.server_identifier()); 252 dict->SetString(kKeyCertType, 253 ClientCertTypeToString(net::CLIENT_CERT_ECDSA_SIGN)); 254 dict->SetString(kKeyCreated, base::UTF16ToUTF8( 255 base::TimeFormatFriendlyDateAndTime( 256 server_bound_cert.creation_time()))); 257 break; 258 } 259 case CookieTreeNode::DetailedInfo::TYPE_FLASH_LSO: { 260 dict->SetString(kKeyType, "flash_lso"); 261 dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_ICON"); 262 263 dict->SetString(kKeyDomain, node.GetDetailedInfo().flash_lso_domain); 264 } 265 default: 266 #if defined(OS_MACOSX) 267 dict->SetString(kKeyIcon, "chrome://theme/IDR_BOOKMARK_BAR_FOLDER"); 268 #endif 269 break; 270 } 271 272 const extensions::ExtensionSet* protecting_apps = 273 node.GetModel()->ExtensionsProtectingNode(node); 274 if (protecting_apps && !protecting_apps->is_empty()) { 275 base::ListValue* app_infos = new base::ListValue; 276 for (extensions::ExtensionSet::const_iterator it = protecting_apps->begin(); 277 it != protecting_apps->end(); ++it) { 278 base::DictionaryValue* app_info = new base::DictionaryValue(); 279 app_info->SetString(kKeyId, (*it)->id()); 280 app_info->SetString(kKeyName, (*it)->name()); 281 app_infos->Append(app_info); 282 } 283 dict->Set(kKeyAppsProtectingThis, app_infos); 284 } 285 286 return true; 287 } 288 289 void CookiesTreeModelUtil::GetChildNodeList(const CookieTreeNode* parent, 290 int start, 291 int count, 292 base::ListValue* nodes) { 293 for (int i = 0; i < count; ++i) { 294 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue); 295 const CookieTreeNode* child = parent->GetChild(start + i); 296 if (GetCookieTreeNodeDictionary(*child, dict.get())) 297 nodes->Append(dict.release()); 298 } 299 } 300 301 const CookieTreeNode* CookiesTreeModelUtil::GetTreeNodeFromPath( 302 const CookieTreeNode* root, 303 const std::string& path) { 304 std::vector<std::string> node_ids; 305 base::SplitString(path, ',', &node_ids); 306 307 const CookieTreeNode* child = NULL; 308 const CookieTreeNode* parent = root; 309 int child_index = -1; 310 311 // Validate the tree path and get the node pointer. 312 for (size_t i = 0; i < node_ids.size(); ++i) { 313 int32 node_id = 0; 314 if (!base::StringToInt(node_ids[i], &node_id)) 315 break; 316 317 child = id_map_.Lookup(node_id); 318 child_index = parent->GetIndexOf(child); 319 if (child_index == -1) 320 break; 321 322 parent = child; 323 } 324 325 return child_index >= 0 ? child : NULL; 326 } 327