blob: a1cef917ef870316d7414cfebe3c3f343cf7d843 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/webui/cookies_tree_model_util.h"
#include <memory>
#include <utility>
#include <vector>
#include "base/i18n/time_formatting.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/browsing_data/cookies_tree_model.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/cache_storage_context.h"
#include "content/public/browser/indexed_db_context.h"
#include "content/public/browser/service_worker_context.h"
#include "net/cookies/canonical_cookie.h"
#include "storage/common/fileapi/file_system_types.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/text/bytes_formatting.h"
#if defined(ENABLE_EXTENSIONS)
#include "extensions/common/extension_set.h"
#endif
namespace {
const char kKeyId[] = "id";
const char kKeyTitle[] = "title";
const char kKeyIcon[] = "icon";
const char kKeyType[] = "type";
const char kKeyHasChildren[] = "hasChildren";
#if defined(ENABLE_EXTENSIONS)
const char kKeyAppsProtectingThis[] = "appsProtectingThis";
#endif
const char kKeyName[] = "name";
const char kKeyContent[] = "content";
const char kKeyDomain[] = "domain";
const char kKeyPath[] = "path";
const char kKeySendFor[] = "sendfor";
const char kKeyAccessibleToScript[] = "accessibleToScript";
const char kKeyDesc[] = "desc";
const char kKeySize[] = "size";
const char kKeyOrigin[] = "origin";
const char kKeyManifest[] = "manifest";
const char kKeyServerId[] = "serverId";
const char kKeyAccessed[] = "accessed";
const char kKeyCreated[] = "created";
const char kKeyExpires[] = "expires";
const char kKeyModified[] = "modified";
const char kKeyPersistent[] = "persistent";
const char kKeyTemporary[] = "temporary";
const char kKeyTotalUsage[] = "totalUsage";
const char kKeyTemporaryUsage[] = "temporaryUsage";
const char kKeyPersistentUsage[] = "persistentUsage";
const char kKeyCertType[] = "certType";
const char kKeyScopes[] = "scopes";
const int64_t kNegligibleUsage = 1024; // 1KiB
} // namespace
CookiesTreeModelUtil::CookiesTreeModelUtil() {
}
CookiesTreeModelUtil::~CookiesTreeModelUtil() {
}
std::string CookiesTreeModelUtil::GetTreeNodeId(const CookieTreeNode* node) {
CookieTreeNodeMap::const_iterator iter = node_map_.find(node);
if (iter != node_map_.end())
return base::IntToString(iter->second);
int32_t new_id = id_map_.Add(node);
node_map_[node] = new_id;
return base::IntToString(new_id);
}
bool CookiesTreeModelUtil::GetCookieTreeNodeDictionary(
const CookieTreeNode& node,
base::DictionaryValue* dict) {
// Use node's address as an id for WebUI to look it up.
dict->SetString(kKeyId, GetTreeNodeId(&node));
dict->SetString(kKeyTitle, node.GetTitle());
dict->SetBoolean(kKeyHasChildren, !node.empty());
switch (node.GetDetailedInfo().node_type) {
case CookieTreeNode::DetailedInfo::TYPE_HOST: {
dict->SetString(kKeyType, "origin");
#if defined(OS_MACOSX)
dict->SetString(kKeyIcon, "chrome://theme/IDR_BOOKMARK_BAR_FOLDER");
#endif
break;
}
case CookieTreeNode::DetailedInfo::TYPE_COOKIE: {
dict->SetString(kKeyType, "cookie");
dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_ICON");
const net::CanonicalCookie& cookie = *node.GetDetailedInfo().cookie;
dict->SetString(kKeyName, cookie.Name());
dict->SetString(kKeyContent, cookie.Value());
dict->SetString(kKeyDomain, cookie.Domain());
dict->SetString(kKeyPath, cookie.Path());
dict->SetString(kKeySendFor,
l10n_util::GetStringUTF16(
CookiesTreeModel::GetSendForMessageID(cookie)));
std::string accessible = cookie.IsHttpOnly() ?
l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_ACCESSIBLE_TO_SCRIPT_NO) :
l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_ACCESSIBLE_TO_SCRIPT_YES);
dict->SetString(kKeyAccessibleToScript, accessible);
dict->SetString(kKeyCreated, base::UTF16ToUTF8(
base::TimeFormatFriendlyDateAndTime(cookie.CreationDate())));
dict->SetString(kKeyExpires, cookie.IsPersistent() ? base::UTF16ToUTF8(
base::TimeFormatFriendlyDateAndTime(cookie.ExpiryDate())) :
l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_EXPIRES_SESSION));
break;
}
case CookieTreeNode::DetailedInfo::TYPE_DATABASE: {
dict->SetString(kKeyType, "database");
dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
const BrowsingDataDatabaseHelper::DatabaseInfo& database_info =
*node.GetDetailedInfo().database_info;
dict->SetString(kKeyName, database_info.database_name.empty() ?
l10n_util::GetStringUTF8(IDS_COOKIES_WEB_DATABASE_UNNAMED_NAME) :
database_info.database_name);
dict->SetString(kKeyDesc, database_info.description);
dict->SetString(kKeySize, ui::FormatBytes(database_info.size));
dict->SetString(kKeyModified, base::UTF16ToUTF8(
base::TimeFormatFriendlyDateAndTime(database_info.last_modified)));
break;
}
case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE: {
dict->SetString(kKeyType, "local_storage");
dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
const BrowsingDataLocalStorageHelper::LocalStorageInfo&
local_storage_info = *node.GetDetailedInfo().local_storage_info;
dict->SetString(kKeyOrigin, local_storage_info.origin_url.spec());
dict->SetString(kKeySize, ui::FormatBytes(local_storage_info.size));
dict->SetString(kKeyModified, base::UTF16ToUTF8(
base::TimeFormatFriendlyDateAndTime(
local_storage_info.last_modified)));
break;
}
case CookieTreeNode::DetailedInfo::TYPE_APPCACHE: {
dict->SetString(kKeyType, "app_cache");
dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
const content::AppCacheInfo& appcache_info =
*node.GetDetailedInfo().appcache_info;
dict->SetString(kKeyManifest, appcache_info.manifest_url.spec());
dict->SetString(kKeySize, ui::FormatBytes(appcache_info.size));
dict->SetString(kKeyCreated, base::UTF16ToUTF8(
base::TimeFormatFriendlyDateAndTime(appcache_info.creation_time)));
dict->SetString(kKeyAccessed, base::UTF16ToUTF8(
base::TimeFormatFriendlyDateAndTime(appcache_info.last_access_time)));
break;
}
case CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB: {
dict->SetString(kKeyType, "indexed_db");
dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
const content::IndexedDBInfo& indexed_db_info =
*node.GetDetailedInfo().indexed_db_info;
dict->SetString(kKeyOrigin, indexed_db_info.origin.spec());
dict->SetString(kKeySize, ui::FormatBytes(indexed_db_info.size));
dict->SetString(kKeyModified,
base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
indexed_db_info.last_modified)));
break;
}
case CookieTreeNode::DetailedInfo::TYPE_FILE_SYSTEM: {
dict->SetString(kKeyType, "file_system");
dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
const BrowsingDataFileSystemHelper::FileSystemInfo& file_system_info =
*node.GetDetailedInfo().file_system_info;
const storage::FileSystemType kPerm = storage::kFileSystemTypePersistent;
const storage::FileSystemType kTemp = storage::kFileSystemTypeTemporary;
dict->SetString(kKeyOrigin, file_system_info.origin.spec());
dict->SetString(kKeyPersistent,
ContainsKey(file_system_info.usage_map, kPerm) ?
base::UTF16ToUTF8(ui::FormatBytes(
file_system_info.usage_map.find(kPerm)->second)) :
l10n_util::GetStringUTF8(
IDS_COOKIES_FILE_SYSTEM_USAGE_NONE));
dict->SetString(kKeyTemporary,
ContainsKey(file_system_info.usage_map, kTemp) ?
base::UTF16ToUTF8(ui::FormatBytes(
file_system_info.usage_map.find(kTemp)->second)) :
l10n_util::GetStringUTF8(
IDS_COOKIES_FILE_SYSTEM_USAGE_NONE));
break;
}
case CookieTreeNode::DetailedInfo::TYPE_QUOTA: {
dict->SetString(kKeyType, "quota");
dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
const BrowsingDataQuotaHelper::QuotaInfo& quota_info =
*node.GetDetailedInfo().quota_info;
if (quota_info.temporary_usage + quota_info.persistent_usage <=
kNegligibleUsage)
return false;
dict->SetString(kKeyOrigin, quota_info.host);
dict->SetString(kKeyTotalUsage,
base::UTF16ToUTF8(ui::FormatBytes(
quota_info.temporary_usage +
quota_info.persistent_usage)));
dict->SetString(kKeyTemporaryUsage,
base::UTF16ToUTF8(ui::FormatBytes(
quota_info.temporary_usage)));
dict->SetString(kKeyPersistentUsage,
base::UTF16ToUTF8(ui::FormatBytes(
quota_info.persistent_usage)));
break;
}
case CookieTreeNode::DetailedInfo::TYPE_CHANNEL_ID: {
dict->SetString(kKeyType, "channel_id");
dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_ICON");
const net::ChannelIDStore::ChannelID& channel_id =
*node.GetDetailedInfo().channel_id;
dict->SetString(kKeyServerId, channel_id.server_identifier());
dict->SetString(kKeyCertType,
l10n_util::GetStringUTF8(IDS_CLIENT_CERT_ECDSA_SIGN));
dict->SetString(kKeyCreated, base::UTF16ToUTF8(
base::TimeFormatFriendlyDateAndTime(
channel_id.creation_time())));
break;
}
case CookieTreeNode::DetailedInfo::TYPE_SERVICE_WORKER: {
dict->SetString(kKeyType, "service_worker");
dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
const content::ServiceWorkerUsageInfo& service_worker_info =
*node.GetDetailedInfo().service_worker_info;
dict->SetString(kKeyOrigin, service_worker_info.origin.spec());
dict->SetString(kKeySize,
ui::FormatBytes(service_worker_info.total_size_bytes));
base::ListValue* scopes = new base::ListValue;
for (std::vector<GURL>::const_iterator it =
service_worker_info.scopes.begin();
it != service_worker_info.scopes.end();
++it) {
scopes->AppendString(it->spec());
}
dict->Set(kKeyScopes, scopes);
break;
}
case CookieTreeNode::DetailedInfo::TYPE_CACHE_STORAGE: {
dict->SetString(kKeyType, "cache_storage");
dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
const content::CacheStorageUsageInfo& cache_storage_info =
*node.GetDetailedInfo().cache_storage_info;
dict->SetString(kKeyOrigin, cache_storage_info.origin.spec());
dict->SetString(kKeySize,
ui::FormatBytes(cache_storage_info.total_size_bytes));
dict->SetString(kKeyModified,
base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
cache_storage_info.last_modified)));
break;
}
case CookieTreeNode::DetailedInfo::TYPE_FLASH_LSO: {
dict->SetString(kKeyType, "flash_lso");
dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_ICON");
dict->SetString(kKeyDomain, node.GetDetailedInfo().flash_lso_domain);
break;
}
default:
#if defined(OS_MACOSX)
dict->SetString(kKeyIcon, "chrome://theme/IDR_BOOKMARK_BAR_FOLDER");
#endif
break;
}
#if defined(ENABLE_EXTENSIONS)
const extensions::ExtensionSet* protecting_apps =
node.GetModel()->ExtensionsProtectingNode(node);
if (protecting_apps && !protecting_apps->is_empty()) {
base::ListValue* app_infos = new base::ListValue;
for (extensions::ExtensionSet::const_iterator it = protecting_apps->begin();
it != protecting_apps->end(); ++it) {
std::unique_ptr<base::DictionaryValue> app_info(
new base::DictionaryValue());
app_info->SetString(kKeyId, (*it)->id());
app_info->SetString(kKeyName, (*it)->name());
app_infos->Append(std::move(app_info));
}
dict->Set(kKeyAppsProtectingThis, app_infos);
}
#endif
return true;
}
void CookiesTreeModelUtil::GetChildNodeList(const CookieTreeNode* parent,
int start,
int count,
base::ListValue* nodes) {
for (int i = 0; i < count; ++i) {
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
const CookieTreeNode* child = parent->GetChild(start + i);
if (GetCookieTreeNodeDictionary(*child, dict.get()))
nodes->Append(std::move(dict));
}
}
const CookieTreeNode* CookiesTreeModelUtil::GetTreeNodeFromPath(
const CookieTreeNode* root,
const std::string& path) {
const CookieTreeNode* child = NULL;
const CookieTreeNode* parent = root;
int child_index = -1;
// Validate the tree path and get the node pointer.
for (const base::StringPiece& cur_node : base::SplitStringPiece(
path, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
int32_t node_id = 0;
if (!base::StringToInt(cur_node, &node_id))
break;
child = id_map_.Lookup(node_id);
child_index = parent->GetIndexOf(child);
if (child_index == -1)
break;
parent = child;
}
return child_index >= 0 ? child : NULL;
}