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