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