Home | History | Annotate | Download | only in webui
      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 "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"
     25 
     26 #if defined(ENABLE_EXTENSIONS)
     27 #include "extensions/common/extension_set.h"
     28 #endif
     29 
     30 namespace {
     31 
     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";
     37 
     38 #if defined(ENABLE_EXTENSIONS)
     39 const char kKeyAppsProtectingThis[] = "appsProtectingThis";
     40 #endif
     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";
     52 
     53 const char kKeyAccessed[] = "accessed";
     54 const char kKeyCreated[] = "created";
     55 const char kKeyExpires[] = "expires";
     56 const char kKeyModified[] = "modified";
     57 
     58 const char kKeyPersistent[] = "persistent";
     59 const char kKeyTemporary[] = "temporary";
     60 
     61 const char kKeyTotalUsage[] = "totalUsage";
     62 const char kKeyTemporaryUsage[] = "temporaryUsage";
     63 const char kKeyPersistentUsage[] = "persistentUsage";
     64 
     65 const char kKeyCertType[] = "certType";
     66 
     67 const char kKeyScopes[] = "scopes";
     68 
     69 const int64 kNegligibleUsage = 1024;  // 1KiB
     70 
     71 std::string ClientCertTypeToString(net::SSLClientCertType type) {
     72   switch (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);
     79     default:
     80       return base::IntToString(type);
     81   }
     82 }
     83 
     84 }  // namespace
     85 
     86 CookiesTreeModelUtil::CookiesTreeModelUtil() {
     87 }
     88 
     89 CookiesTreeModelUtil::~CookiesTreeModelUtil() {
     90 }
     91 
     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);
     96 
     97   int32 new_id = id_map_.Add(node);
     98   node_map_[node] = new_id;
     99   return base::IntToString(new_id);
    100 }
    101 
    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());
    109 
    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");
    115 #endif
    116       break;
    117     }
    118     case CookieTreeNode::DetailedInfo::TYPE_COOKIE: {
    119       dict->SetString(kKeyType, "cookie");
    120       dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_ICON");
    121 
    122       const net::CanonicalCookie& cookie = *node.GetDetailedInfo().cookie;
    123 
    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, cookie.IsSecure() ?
    129           l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_SENDFOR_SECURE) :
    130           l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_SENDFOR_ANY));
    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));
    140 
    141       break;
    142     }
    143     case CookieTreeNode::DetailedInfo::TYPE_DATABASE: {
    144       dict->SetString(kKeyType, "database");
    145       dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
    146 
    147       const BrowsingDataDatabaseHelper::DatabaseInfo& database_info =
    148           *node.GetDetailedInfo().database_info;
    149 
    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)));
    157 
    158       break;
    159     }
    160     case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE: {
    161       dict->SetString(kKeyType, "local_storage");
    162       dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
    163 
    164       const BrowsingDataLocalStorageHelper::LocalStorageInfo&
    165          local_storage_info = *node.GetDetailedInfo().local_storage_info;
    166 
    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)));
    172 
    173       break;
    174     }
    175     case CookieTreeNode::DetailedInfo::TYPE_APPCACHE: {
    176       dict->SetString(kKeyType, "app_cache");
    177       dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
    178 
    179       const content::AppCacheInfo& appcache_info =
    180           *node.GetDetailedInfo().appcache_info;
    181 
    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)));
    188 
    189       break;
    190     }
    191     case CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB: {
    192       dict->SetString(kKeyType, "indexed_db");
    193       dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
    194 
    195       const content::IndexedDBInfo& indexed_db_info =
    196           *node.GetDetailedInfo().indexed_db_info;
    197 
    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_)));
    202 
    203       break;
    204     }
    205     case CookieTreeNode::DetailedInfo::TYPE_FILE_SYSTEM: {
    206       dict->SetString(kKeyType, "file_system");
    207       dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
    208 
    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;
    213 
    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));
    227       break;
    228     }
    229     case CookieTreeNode::DetailedInfo::TYPE_QUOTA: {
    230       dict->SetString(kKeyType, "quota");
    231       dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
    232 
    233       const BrowsingDataQuotaHelper::QuotaInfo& quota_info =
    234           *node.GetDetailedInfo().quota_info;
    235       if (quota_info.temporary_usage + quota_info.persistent_usage <=
    236           kNegligibleUsage)
    237         return false;
    238 
    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)));
    250       break;
    251     }
    252     case CookieTreeNode::DetailedInfo::TYPE_CHANNEL_ID: {
    253       dict->SetString(kKeyType, "channel_id");
    254       dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_ICON");
    255 
    256       const net::ChannelIDStore::ChannelID& channel_id =
    257           *node.GetDetailedInfo().channel_id;
    258 
    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())));
    265       break;
    266     }
    267     case CookieTreeNode::DetailedInfo::TYPE_SERVICE_WORKER: {
    268       dict->SetString(kKeyType, "service_worker");
    269       dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
    270 
    271       const content::ServiceWorkerUsageInfo& service_worker_info =
    272           *node.GetDetailedInfo().service_worker_info;
    273 
    274       dict->SetString(kKeyOrigin, service_worker_info.origin.spec());
    275       base::ListValue* scopes = new base::ListValue;
    276       for (std::vector<GURL>::const_iterator it =
    277                service_worker_info.scopes.begin();
    278            it != service_worker_info.scopes.end();
    279            ++it) {
    280         scopes->AppendString(it->spec());
    281       }
    282       dict->Set(kKeyScopes, scopes);
    283       break;
    284     }
    285     case CookieTreeNode::DetailedInfo::TYPE_FLASH_LSO: {
    286       dict->SetString(kKeyType, "flash_lso");
    287       dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_ICON");
    288 
    289       dict->SetString(kKeyDomain, node.GetDetailedInfo().flash_lso_domain);
    290     }
    291     default:
    292 #if defined(OS_MACOSX)
    293       dict->SetString(kKeyIcon, "chrome://theme/IDR_BOOKMARK_BAR_FOLDER");
    294 #endif
    295       break;
    296   }
    297 
    298 #if defined(ENABLE_EXTENSIONS)
    299   const extensions::ExtensionSet* protecting_apps =
    300       node.GetModel()->ExtensionsProtectingNode(node);
    301   if (protecting_apps && !protecting_apps->is_empty()) {
    302     base::ListValue* app_infos = new base::ListValue;
    303     for (extensions::ExtensionSet::const_iterator it = protecting_apps->begin();
    304          it != protecting_apps->end(); ++it) {
    305       base::DictionaryValue* app_info = new base::DictionaryValue();
    306       app_info->SetString(kKeyId, (*it)->id());
    307       app_info->SetString(kKeyName, (*it)->name());
    308       app_infos->Append(app_info);
    309     }
    310     dict->Set(kKeyAppsProtectingThis, app_infos);
    311   }
    312 #endif
    313 
    314   return true;
    315 }
    316 
    317 void CookiesTreeModelUtil::GetChildNodeList(const CookieTreeNode* parent,
    318                                             int start,
    319                                             int count,
    320                                             base::ListValue* nodes) {
    321   for (int i = 0; i < count; ++i) {
    322     scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
    323     const CookieTreeNode* child = parent->GetChild(start + i);
    324     if (GetCookieTreeNodeDictionary(*child, dict.get()))
    325       nodes->Append(dict.release());
    326   }
    327 }
    328 
    329 const CookieTreeNode* CookiesTreeModelUtil::GetTreeNodeFromPath(
    330     const CookieTreeNode* root,
    331     const std::string& path) {
    332   std::vector<std::string> node_ids;
    333   base::SplitString(path, ',', &node_ids);
    334 
    335   const CookieTreeNode* child = NULL;
    336   const CookieTreeNode* parent = root;
    337   int child_index = -1;
    338 
    339   // Validate the tree path and get the node pointer.
    340   for (size_t i = 0; i < node_ids.size(); ++i) {
    341     int32 node_id = 0;
    342     if (!base::StringToInt(node_ids[i], &node_id))
    343       break;
    344 
    345     child = id_map_.Lookup(node_id);
    346     child_index = parent->GetIndexOf(child);
    347     if (child_index == -1)
    348       break;
    349 
    350     parent = child;
    351   }
    352 
    353   return child_index >= 0 ? child : NULL;
    354 }
    355