1// Copyright (c) 2011 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 "base/i18n/time_formatting.h"
8#include "base/string_number_conversions.h"
9#include "base/string_split.h"
10#include "base/string_util.h"
11#include "base/values.h"
12#include "chrome/browser/cookies_tree_model.h"
13#include "grit/generated_resources.h"
14#include "ui/base/l10n/l10n_util.h"
15
16namespace {
17
18static const char kKeyId[] = "id";
19static const char kKeyTitle[] = "title";
20static const char kKeyIcon[] = "icon";
21static const char kKeyType[] = "type";
22static const char kKeyHasChildren[] = "hasChildren";
23
24static const char kKeyName[] = "name";
25static const char kKeyContent[] = "content";
26static const char kKeyDomain[] = "domain";
27static const char kKeyPath[] = "path";
28static const char kKeySendFor[] = "sendfor";
29static const char kKeyAccessibleToScript[] = "accessibleToScript";
30static const char kKeyDesc[] = "desc";
31static const char kKeySize[] = "size";
32static const char kKeyOrigin[] = "origin";
33static const char kKeyManifest[] = "manifest";
34
35static const char kKeyAccessed[] = "accessed";
36static const char kKeyCreated[] = "created";
37static const char kKeyExpires[] = "expires";
38static const char kKeyModified[] = "modified";
39
40// Encodes a pointer value into a hex string.
41std::string PointerToHexString(const void* pointer) {
42  return base::HexEncode(&pointer, sizeof(pointer));
43}
44
45// Decodes a pointer from a hex string.
46void* HexStringToPointer(const std::string& str) {
47  std::vector<uint8> buffer;
48  if (!base::HexStringToBytes(str, &buffer) ||
49      buffer.size() != sizeof(void*)) {
50    return NULL;
51  }
52
53  return *reinterpret_cast<void**>(&buffer[0]);
54}
55
56}  // namespace
57
58namespace cookies_tree_model_util {
59
60std::string GetTreeNodeId(CookieTreeNode* node) {
61  return PointerToHexString(node);
62}
63
64void GetCookieTreeNodeDictionary(const CookieTreeNode& node,
65                                 DictionaryValue* dict) {
66  // Use node's address as an id for WebUI to look it up.
67  dict->SetString(kKeyId, PointerToHexString(&node));
68  dict->SetString(kKeyTitle, node.GetTitle());
69  dict->SetBoolean(kKeyHasChildren, !!node.child_count());
70
71  switch (node.GetDetailedInfo().node_type) {
72    case CookieTreeNode::DetailedInfo::TYPE_ORIGIN: {
73      dict->SetString(kKeyType, "origin");
74#if defined(OS_MACOSX)
75      dict->SetString(kKeyIcon, "chrome://theme/IDR_BOOKMARK_BAR_FOLDER");
76#endif
77      break;
78    }
79    case CookieTreeNode::DetailedInfo::TYPE_COOKIE: {
80      dict->SetString(kKeyType, "cookie");
81      dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_ICON");
82
83      const net::CookieMonster::CanonicalCookie& cookie =
84          *node.GetDetailedInfo().cookie;
85
86      dict->SetString(kKeyName, cookie.Name());
87      dict->SetString(kKeyContent, cookie.Value());
88      dict->SetString(kKeyDomain, cookie.Domain());
89      dict->SetString(kKeyPath, cookie.Path());
90      dict->SetString(kKeySendFor, cookie.IsSecure() ?
91          l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_SENDFOR_SECURE) :
92          l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_SENDFOR_ANY));
93      std::string accessible = cookie.IsHttpOnly() ?
94          l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_ACCESSIBLE_TO_SCRIPT_NO) :
95          l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_ACCESSIBLE_TO_SCRIPT_YES);
96      dict->SetString(kKeyAccessibleToScript, accessible);
97      dict->SetString(kKeyCreated, UTF16ToUTF8(
98          base::TimeFormatFriendlyDateAndTime(cookie.CreationDate())));
99      dict->SetString(kKeyExpires, cookie.DoesExpire() ? UTF16ToUTF8(
100          base::TimeFormatFriendlyDateAndTime(cookie.ExpiryDate())) :
101          l10n_util::GetStringUTF8(IDS_COOKIES_COOKIE_EXPIRES_SESSION));
102
103      break;
104    }
105    case CookieTreeNode::DetailedInfo::TYPE_DATABASE: {
106      dict->SetString(kKeyType, "database");
107      dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
108
109      const BrowsingDataDatabaseHelper::DatabaseInfo& database_info =
110          *node.GetDetailedInfo().database_info;
111
112      dict->SetString(kKeyName, database_info.database_name.empty() ?
113          l10n_util::GetStringUTF8(IDS_COOKIES_WEB_DATABASE_UNNAMED_NAME) :
114          database_info.database_name);
115      dict->SetString(kKeyDesc, database_info.description);
116      dict->SetString(kKeySize,
117          FormatBytes(database_info.size,
118                      GetByteDisplayUnits(database_info.size),
119                      true));
120      dict->SetString(kKeyModified, UTF16ToUTF8(
121          base::TimeFormatFriendlyDateAndTime(database_info.last_modified)));
122
123      break;
124    }
125    case CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGE: {
126      dict->SetString(kKeyType, "local_storage");
127      dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
128
129      const BrowsingDataLocalStorageHelper::LocalStorageInfo&
130         local_storage_info = *node.GetDetailedInfo().local_storage_info;
131
132      dict->SetString(kKeyOrigin, local_storage_info.origin);
133      dict->SetString(kKeySize,
134          FormatBytes(local_storage_info.size,
135                      GetByteDisplayUnits(local_storage_info.size),
136                      true));
137      dict->SetString(kKeyModified, UTF16ToUTF8(
138          base::TimeFormatFriendlyDateAndTime(
139              local_storage_info.last_modified)));
140
141      break;
142    }
143    case CookieTreeNode::DetailedInfo::TYPE_APPCACHE: {
144      dict->SetString(kKeyType, "app_cache");
145      dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
146
147      const appcache::AppCacheInfo& appcache_info =
148          *node.GetDetailedInfo().appcache_info;
149
150      dict->SetString(kKeyManifest, appcache_info.manifest_url.spec());
151      dict->SetString(kKeySize,
152          FormatBytes(appcache_info.size,
153                      GetByteDisplayUnits(appcache_info.size),
154                      true));
155      dict->SetString(kKeyCreated, UTF16ToUTF8(
156          base::TimeFormatFriendlyDateAndTime(appcache_info.creation_time)));
157      dict->SetString(kKeyAccessed, UTF16ToUTF8(
158          base::TimeFormatFriendlyDateAndTime(appcache_info.last_access_time)));
159
160      break;
161    }
162    case CookieTreeNode::DetailedInfo::TYPE_INDEXED_DB: {
163      dict->SetString(kKeyType, "indexed_db");
164      dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON");
165
166      const BrowsingDataIndexedDBHelper::IndexedDBInfo& indexed_db_info =
167          *node.GetDetailedInfo().indexed_db_info;
168
169      dict->SetString(kKeyOrigin, indexed_db_info.origin);
170      dict->SetString(kKeySize,
171          FormatBytes(indexed_db_info.size,
172                      GetByteDisplayUnits(indexed_db_info.size),
173                      true));
174      dict->SetString(kKeyModified, UTF16ToUTF8(
175          base::TimeFormatFriendlyDateAndTime(indexed_db_info.last_modified)));
176
177      break;
178    }
179    default:
180#if defined(OS_MACOSX)
181      dict->SetString(kKeyIcon, "chrome://theme/IDR_BOOKMARK_BAR_FOLDER");
182#endif
183      break;
184  }
185}
186
187void GetChildNodeList(CookieTreeNode* parent, int start, int count,
188                      ListValue* nodes) {
189  for (int i = 0; i < count; ++i) {
190    DictionaryValue* dict = new DictionaryValue;
191    CookieTreeNode* child = parent->GetChild(start + i);
192    GetCookieTreeNodeDictionary(*child, dict);
193    nodes->Append(dict);
194  }
195}
196
197CookieTreeNode* GetTreeNodeFromPath(CookieTreeNode* root,
198                                    const std::string& path) {
199  std::vector<std::string> node_ids;
200  base::SplitString(path, ',', &node_ids);
201
202  CookieTreeNode* child = NULL;
203  CookieTreeNode* parent = root;
204  int child_index = -1;
205
206  // Validate the tree path and get the node pointer.
207  for (size_t i = 0; i < node_ids.size(); ++i) {
208    child = reinterpret_cast<CookieTreeNode*>(
209        HexStringToPointer(node_ids[i]));
210
211    child_index = parent->GetIndexOf(child);
212    if (child_index == -1)
213      break;
214
215    parent = child;
216  }
217
218  return child_index >= 0 ? child : NULL;
219}
220
221}  // namespace cookies_tree_model_util
222