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#ifndef CHROME_BROWSER_COOKIES_TREE_MODEL_H_
6#define CHROME_BROWSER_COOKIES_TREE_MODEL_H_
7#pragma once
8
9// TODO(viettrungluu): This header file #includes far too much and has too much
10// inline code (which shouldn't be inline).
11
12#include <string>
13#include <vector>
14
15#include "base/memory/ref_counted.h"
16#include "base/observer_list.h"
17#include "base/string16.h"
18#include "base/utf_string_conversions.h"
19#include "chrome/browser/browsing_data_appcache_helper.h"
20#include "chrome/browser/browsing_data_database_helper.h"
21#include "chrome/browser/browsing_data_indexed_db_helper.h"
22#include "chrome/browser/browsing_data_local_storage_helper.h"
23#include "net/base/cookie_monster.h"
24#include "ui/base/models/tree_node_model.h"
25
26class CookiesTreeModel;
27class CookieTreeAppCacheNode;
28class CookieTreeAppCachesNode;
29class CookieTreeCookieNode;
30class CookieTreeCookiesNode;
31class CookieTreeDatabaseNode;
32class CookieTreeDatabasesNode;
33class CookieTreeLocalStorageNode;
34class CookieTreeLocalStoragesNode;
35class CookieTreeSessionStorageNode;
36class CookieTreeSessionStoragesNode;
37class CookieTreeIndexedDBNode;
38class CookieTreeIndexedDBsNode;
39class CookieTreeOriginNode;
40
41// CookieTreeNode -------------------------------------------------------------
42// The base node type in the Cookies, Databases, and Local Storage options
43// view, from which all other types are derived. Specialized from TreeNode in
44// that it has a notion of deleting objects stored in the profile, and being
45// able to have its children do the same.
46class CookieTreeNode : public ui::TreeNode<CookieTreeNode> {
47 public:
48  // Used to pull out information for the InfoView (the details display below
49  // the tree control.)
50  struct DetailedInfo {
51    // NodeType corresponds to the various CookieTreeNode types.
52    enum NodeType {
53      TYPE_ROOT,  // This is used for CookieTreeRootNode nodes.
54      TYPE_ORIGIN,  // This is used for CookieTreeOriginNode nodes.
55      TYPE_COOKIES,  // This is used for CookieTreeCookiesNode nodes.
56      TYPE_COOKIE,  // This is used for CookieTreeCookieNode nodes.
57      TYPE_DATABASES,  // This is used for CookieTreeDatabasesNode.
58      TYPE_DATABASE,  // This is used for CookieTreeDatabaseNode.
59      TYPE_LOCAL_STORAGES,  // This is used for CookieTreeLocalStoragesNode.
60      TYPE_LOCAL_STORAGE,  // This is used for CookieTreeLocalStorageNode.
61      TYPE_SESSION_STORAGES,  // This is used for CookieTreeSessionStoragesNode.
62      TYPE_SESSION_STORAGE,  // This is used for CookieTreeSessionStorageNode.
63      TYPE_APPCACHES,  // This is used for CookieTreeAppCachesNode.
64      TYPE_APPCACHE,  // This is used for CookieTreeAppCacheNode.
65      TYPE_INDEXED_DBS,  // This is used for CookieTreeIndexedDBsNode.
66      TYPE_INDEXED_DB,  // This is used for CookieTreeIndexedDBNode.
67    };
68
69    // TODO(viettrungluu): Figure out whether we want to store |origin| as a
70    // |string16| or a (UTF-8) |std::string|, and convert. Remove constructor
71    // taking an |std::wstring|.
72    DetailedInfo(const string16& origin, NodeType node_type,
73        const net::CookieMonster::CanonicalCookie* cookie,
74        const BrowsingDataDatabaseHelper::DatabaseInfo* database_info,
75        const BrowsingDataLocalStorageHelper::LocalStorageInfo*
76            local_storage_info,
77        const BrowsingDataLocalStorageHelper::LocalStorageInfo*
78            session_storage_info,
79        const appcache::AppCacheInfo* appcache_info,
80        const BrowsingDataIndexedDBHelper::IndexedDBInfo* indexed_db_info)
81        : origin(UTF16ToWideHack(origin)),
82          node_type(node_type),
83          cookie(cookie),
84          database_info(database_info),
85          local_storage_info(local_storage_info),
86          session_storage_info(session_storage_info),
87          appcache_info(appcache_info),
88          indexed_db_info(indexed_db_info) {
89      DCHECK((node_type != TYPE_DATABASE) || database_info);
90      DCHECK((node_type != TYPE_LOCAL_STORAGE) || local_storage_info);
91      DCHECK((node_type != TYPE_SESSION_STORAGE) || session_storage_info);
92      DCHECK((node_type != TYPE_APPCACHE) || appcache_info);
93      DCHECK((node_type != TYPE_INDEXED_DB) || indexed_db_info);
94    }
95#if !defined(WCHAR_T_IS_UTF16)
96    DetailedInfo(const std::wstring& origin, NodeType node_type,
97        const net::CookieMonster::CanonicalCookie* cookie,
98        const BrowsingDataDatabaseHelper::DatabaseInfo* database_info,
99        const BrowsingDataLocalStorageHelper::LocalStorageInfo*
100            local_storage_info,
101        const BrowsingDataLocalStorageHelper::LocalStorageInfo*
102            session_storage_info,
103        const appcache::AppCacheInfo* appcache_info,
104        const BrowsingDataIndexedDBHelper::IndexedDBInfo* indexed_db_info)
105        : origin(origin),
106          node_type(node_type),
107          cookie(cookie),
108          database_info(database_info),
109          local_storage_info(local_storage_info),
110          session_storage_info(session_storage_info),
111          appcache_info(appcache_info),
112          indexed_db_info(indexed_db_info) {
113      DCHECK((node_type != TYPE_DATABASE) || database_info);
114      DCHECK((node_type != TYPE_LOCAL_STORAGE) || local_storage_info);
115      DCHECK((node_type != TYPE_SESSION_STORAGE) || session_storage_info);
116      DCHECK((node_type != TYPE_APPCACHE) || appcache_info);
117      DCHECK((node_type != TYPE_INDEXED_DB) || indexed_db_info);
118    }
119#endif
120
121    std::wstring origin;
122    NodeType node_type;
123    const net::CookieMonster::CanonicalCookie* cookie;
124    const BrowsingDataDatabaseHelper::DatabaseInfo* database_info;
125    const BrowsingDataLocalStorageHelper::LocalStorageInfo* local_storage_info;
126    const BrowsingDataLocalStorageHelper::LocalStorageInfo*
127        session_storage_info;
128    const appcache::AppCacheInfo* appcache_info;
129    const BrowsingDataIndexedDBHelper::IndexedDBInfo* indexed_db_info;
130  };
131
132  CookieTreeNode() {}
133  explicit CookieTreeNode(const string16& title)
134      : ui::TreeNode<CookieTreeNode>(title) {}
135  virtual ~CookieTreeNode() {}
136
137  // Delete backend storage for this node, and any children nodes. (E.g. delete
138  // the cookie from CookieMonster, clear the database, and so forth.)
139  virtual void DeleteStoredObjects();
140
141  // Gets a pointer back to the associated model for the tree we are in.
142  virtual CookiesTreeModel* GetModel() const;
143
144  // Returns a struct with detailed information used to populate the details
145  // part of the view.
146  virtual DetailedInfo GetDetailedInfo() const = 0;
147
148 protected:
149  class NodeTitleComparator {
150   public:
151    bool operator() (const CookieTreeNode* lhs, const CookieTreeNode* rhs);
152  };
153
154  void AddChildSortedByTitle(CookieTreeNode* new_child);
155
156 private:
157
158  DISALLOW_COPY_AND_ASSIGN(CookieTreeNode);
159};
160
161// CookieTreeRootNode ---------------------------------------------------------
162// The node at the root of the CookieTree that gets inserted into the view.
163class CookieTreeRootNode : public CookieTreeNode {
164 public:
165  explicit CookieTreeRootNode(CookiesTreeModel* model);
166  virtual ~CookieTreeRootNode();
167
168  CookieTreeOriginNode* GetOrCreateOriginNode(const GURL& url);
169
170  // CookieTreeNode methods:
171  virtual CookiesTreeModel* GetModel() const;
172  virtual DetailedInfo GetDetailedInfo() const;
173
174 private:
175  CookiesTreeModel* model_;
176
177  DISALLOW_COPY_AND_ASSIGN(CookieTreeRootNode);
178};
179
180// CookieTreeOriginNode -------------------------------------------------------
181class CookieTreeOriginNode : public CookieTreeNode {
182 public:
183  // Returns the origin node's title to use for a given URL.
184  static std::wstring TitleForUrl(const GURL& url);
185
186  explicit CookieTreeOriginNode(const GURL& url);
187  virtual ~CookieTreeOriginNode();
188
189  // CookieTreeNode methods:
190  virtual DetailedInfo GetDetailedInfo() const;
191
192  // CookieTreeOriginNode methods:
193  CookieTreeCookiesNode* GetOrCreateCookiesNode();
194  CookieTreeDatabasesNode* GetOrCreateDatabasesNode();
195  CookieTreeLocalStoragesNode* GetOrCreateLocalStoragesNode();
196  CookieTreeSessionStoragesNode* GetOrCreateSessionStoragesNode();
197  CookieTreeAppCachesNode* GetOrCreateAppCachesNode();
198  CookieTreeIndexedDBsNode* GetOrCreateIndexedDBsNode();
199
200  // Creates an content exception for this origin of type
201  // CONTENT_SETTINGS_TYPE_COOKIES.
202  void CreateContentException(HostContentSettingsMap* content_settings,
203                              ContentSetting setting) const;
204
205  // True if a content exception can be created for this origin.
206  bool CanCreateContentException() const;
207
208 private:
209  // Pointers to the cookies, databases, local and session storage and appcache
210  // nodes.  When we build up the tree we need to quickly get a reference to
211  // the COOKIES node to add children. Checking each child and interrogating
212  // them to see if they are a COOKIES, APPCACHES, DATABASES etc node seems
213  // less preferable than storing an extra pointer per origin.
214  CookieTreeCookiesNode* cookies_child_;
215  CookieTreeDatabasesNode* databases_child_;
216  CookieTreeLocalStoragesNode* local_storages_child_;
217  CookieTreeSessionStoragesNode* session_storages_child_;
218  CookieTreeAppCachesNode* appcaches_child_;
219  CookieTreeIndexedDBsNode* indexed_dbs_child_;
220
221  // The URL for which this node was initially created.
222  GURL url_;
223
224  DISALLOW_COPY_AND_ASSIGN(CookieTreeOriginNode);
225};
226
227// CookieTreeCookieNode ------------------------------------------------------
228class CookieTreeCookieNode : public CookieTreeNode {
229 public:
230  friend class CookieTreeCookiesNode;
231
232  // Does not take ownership of cookie, and cookie should remain valid at least
233  // as long as the CookieTreeCookieNode is valid.
234  explicit CookieTreeCookieNode(net::CookieMonster::CanonicalCookie* cookie);
235  virtual ~CookieTreeCookieNode();
236
237  // CookieTreeNode methods:
238  virtual void DeleteStoredObjects();
239  virtual DetailedInfo GetDetailedInfo() const;
240
241 private:
242  // Cookie_ is not owned by the node, and is expected to remain valid as long
243  // as the CookieTreeCookieNode is valid.
244  net::CookieMonster::CanonicalCookie* cookie_;
245
246  DISALLOW_COPY_AND_ASSIGN(CookieTreeCookieNode);
247};
248
249class CookieTreeCookiesNode : public CookieTreeNode {
250 public:
251  CookieTreeCookiesNode();
252  virtual ~CookieTreeCookiesNode();
253
254  virtual DetailedInfo GetDetailedInfo() const;
255
256  void AddCookieNode(CookieTreeCookieNode* child) {
257    AddChildSortedByTitle(child);
258  }
259
260 private:
261  DISALLOW_COPY_AND_ASSIGN(CookieTreeCookiesNode);
262};
263
264// CookieTreeAppCacheNode -----------------------------------------------------
265class CookieTreeAppCacheNode : public CookieTreeNode {
266 public:
267  friend class CookieTreeAppCachesNode;
268
269  // Does not take ownership of appcache_info, and appcache_info should remain
270  // valid at least as long as the CookieTreeAppCacheNode is valid.
271  explicit CookieTreeAppCacheNode(
272      const appcache::AppCacheInfo* appcache_info);
273  virtual ~CookieTreeAppCacheNode() {}
274
275  virtual void DeleteStoredObjects();
276  virtual DetailedInfo GetDetailedInfo() const;
277
278 private:
279  const appcache::AppCacheInfo* appcache_info_;
280  DISALLOW_COPY_AND_ASSIGN(CookieTreeAppCacheNode);
281};
282
283class CookieTreeAppCachesNode : public CookieTreeNode {
284 public:
285  CookieTreeAppCachesNode();
286  virtual ~CookieTreeAppCachesNode();
287
288  virtual DetailedInfo GetDetailedInfo() const;
289
290  void AddAppCacheNode(CookieTreeAppCacheNode* child) {
291    AddChildSortedByTitle(child);
292  }
293
294 private:
295  DISALLOW_COPY_AND_ASSIGN(CookieTreeAppCachesNode);
296};
297
298// CookieTreeDatabaseNode -----------------------------------------------------
299class CookieTreeDatabaseNode : public CookieTreeNode {
300 public:
301  friend class CookieTreeDatabasesNode;
302
303  // Does not take ownership of database_info, and database_info should remain
304  // valid at least as long as the CookieTreeDatabaseNode is valid.
305  explicit CookieTreeDatabaseNode(
306      BrowsingDataDatabaseHelper::DatabaseInfo* database_info);
307  virtual ~CookieTreeDatabaseNode();
308
309  virtual void DeleteStoredObjects();
310  virtual DetailedInfo GetDetailedInfo() const;
311
312 private:
313  // database_info_ is not owned by the node, and is expected to remain
314  // valid as long as the CookieTreeDatabaseNode is valid.
315  BrowsingDataDatabaseHelper::DatabaseInfo* database_info_;
316
317  DISALLOW_COPY_AND_ASSIGN(CookieTreeDatabaseNode);
318};
319
320class CookieTreeDatabasesNode : public CookieTreeNode {
321 public:
322  CookieTreeDatabasesNode();
323  virtual ~CookieTreeDatabasesNode();
324
325  virtual DetailedInfo GetDetailedInfo() const;
326
327  void AddDatabaseNode(CookieTreeDatabaseNode* child) {
328    AddChildSortedByTitle(child);
329  }
330
331 private:
332  DISALLOW_COPY_AND_ASSIGN(CookieTreeDatabasesNode);
333};
334
335
336// CookieTreeLocalStorageNode -------------------------------------------------
337class CookieTreeLocalStorageNode : public CookieTreeNode {
338 public:
339  // Does not take ownership of local_storage_info, and local_storage_info
340  // should remain valid at least as long as the CookieTreeLocalStorageNode is
341  // valid.
342  explicit CookieTreeLocalStorageNode(
343      BrowsingDataLocalStorageHelper::LocalStorageInfo* local_storage_info);
344  virtual ~CookieTreeLocalStorageNode();
345
346  // CookieTreeNode methods:
347  virtual void DeleteStoredObjects();
348  virtual DetailedInfo GetDetailedInfo() const;
349
350 private:
351  // local_storage_info_ is not owned by the node, and is expected to remain
352  // valid as long as the CookieTreeLocalStorageNode is valid.
353  BrowsingDataLocalStorageHelper::LocalStorageInfo* local_storage_info_;
354
355  DISALLOW_COPY_AND_ASSIGN(CookieTreeLocalStorageNode);
356};
357
358class CookieTreeLocalStoragesNode : public CookieTreeNode {
359 public:
360  CookieTreeLocalStoragesNode();
361  virtual ~CookieTreeLocalStoragesNode();
362
363  virtual DetailedInfo GetDetailedInfo() const;
364
365  void AddLocalStorageNode(CookieTreeLocalStorageNode* child) {
366    AddChildSortedByTitle(child);
367  }
368
369 private:
370
371  DISALLOW_COPY_AND_ASSIGN(CookieTreeLocalStoragesNode);
372};
373
374
375// CookieTreeSessionStorageNode -----------------------------------------------
376class CookieTreeSessionStorageNode : public CookieTreeNode {
377 public:
378  // Does not take ownership of session_storage_info, and session_storage_info
379  // should remain valid at least as long as the CookieTreeSessionStorageNode
380  // is valid.
381  explicit CookieTreeSessionStorageNode(
382      BrowsingDataLocalStorageHelper::LocalStorageInfo* session_storage_info);
383  virtual ~CookieTreeSessionStorageNode();
384
385  // CookieTreeNode methods:
386  virtual DetailedInfo GetDetailedInfo() const;
387
388 private:
389  // session_storage_info_ is not owned by the node, and is expected to remain
390  // valid as long as the CookieTreeSessionStorageNode is valid.
391  BrowsingDataLocalStorageHelper::LocalStorageInfo* session_storage_info_;
392
393  DISALLOW_COPY_AND_ASSIGN(CookieTreeSessionStorageNode);
394};
395
396class CookieTreeSessionStoragesNode : public CookieTreeNode {
397 public:
398  CookieTreeSessionStoragesNode();
399  virtual ~CookieTreeSessionStoragesNode();
400
401  virtual DetailedInfo GetDetailedInfo() const;
402
403  void AddSessionStorageNode(CookieTreeSessionStorageNode* child) {
404    AddChildSortedByTitle(child);
405  }
406
407 private:
408
409  DISALLOW_COPY_AND_ASSIGN(CookieTreeSessionStoragesNode);
410};
411
412// CookieTreeIndexedDBNode -----------------------------------------------
413class CookieTreeIndexedDBNode : public CookieTreeNode {
414 public:
415  // Does not take ownership of session_storage_info, and session_storage_info
416  // should remain valid at least as long as the CookieTreeSessionStorageNode
417  // is valid.
418  explicit CookieTreeIndexedDBNode(
419      BrowsingDataIndexedDBHelper::IndexedDBInfo* indexed_db_info);
420  virtual ~CookieTreeIndexedDBNode();
421
422  // CookieTreeNode methods:
423  virtual void DeleteStoredObjects();
424  virtual DetailedInfo GetDetailedInfo() const;
425
426 private:
427  // indexed_db_info_ is not owned by the node, and is expected to remain
428  // valid as long as the CookieTreeIndexedDBNode is valid.
429  BrowsingDataIndexedDBHelper::IndexedDBInfo* indexed_db_info_;
430
431  DISALLOW_COPY_AND_ASSIGN(CookieTreeIndexedDBNode);
432};
433
434class CookieTreeIndexedDBsNode : public CookieTreeNode {
435 public:
436  CookieTreeIndexedDBsNode();
437  virtual ~CookieTreeIndexedDBsNode();
438
439  virtual DetailedInfo GetDetailedInfo() const;
440
441  void AddIndexedDBNode(CookieTreeIndexedDBNode* child) {
442    AddChildSortedByTitle(child);
443  }
444
445 private:
446  DISALLOW_COPY_AND_ASSIGN(CookieTreeIndexedDBsNode);
447};
448
449
450// CookiesTreeModel -----------------------------------------------------------
451class CookiesTreeModel : public ui::TreeNodeModel<CookieTreeNode> {
452 public:
453  // Because non-cookie nodes are fetched in a background thread, they are not
454  // present at the time the Model is created. The Model then notifies its
455  // observers for every item added from databases, local storage, and
456  // appcache. We extend the Observer interface to add notifications before and
457  // after these batch inserts.
458  class Observer : public ui::TreeModelObserver {
459   public:
460    virtual void TreeModelBeginBatch(CookiesTreeModel* model) {}
461    virtual void TreeModelEndBatch(CookiesTreeModel* model) {}
462  };
463
464  CookiesTreeModel(
465      net::CookieMonster* cookie_monster_,
466      BrowsingDataDatabaseHelper* database_helper,
467      BrowsingDataLocalStorageHelper* local_storage_helper,
468      BrowsingDataLocalStorageHelper* session_storage_helper,
469      BrowsingDataAppCacheHelper* appcache_helper,
470      BrowsingDataIndexedDBHelper* indexed_db_helper,
471      bool use_cookie_source);
472  virtual ~CookiesTreeModel();
473
474  // ui::TreeModel methods:
475  // Returns the set of icons for the nodes in the tree. You only need override
476  // this if you don't want to use the default folder icons.
477  virtual void GetIcons(std::vector<SkBitmap>* icons);
478
479  // Returns the index of the icon to use for |node|. Return -1 to use the
480  // default icon. The index is relative to the list of icons returned from
481  // GetIcons.
482  virtual int GetIconIndex(ui::TreeModelNode* node);
483
484  // CookiesTreeModel methods:
485  void DeleteAllStoredObjects();
486  void DeleteCookieNode(CookieTreeNode* cookie_node);
487
488  // Filter the origins to only display matched results.
489  void UpdateSearchResults(const std::wstring& filter);
490
491  // Manages CookiesTreeModel::Observers. This will also call
492  // TreeNodeModel::AddObserver so that it gets all the proper notifications.
493  // Note that the converse is not true: simply adding a TreeModelObserver will
494  // not get CookiesTreeModel::Observer notifications.
495  virtual void AddCookiesTreeObserver(Observer* observer);
496  virtual void RemoveCookiesTreeObserver(Observer* observer);
497
498 private:
499  enum CookieIconIndex {
500    ORIGIN = 0,
501    COOKIE = 1,
502    DATABASE = 2
503  };
504  typedef net::CookieList CookieList;
505  typedef std::vector<BrowsingDataDatabaseHelper::DatabaseInfo>
506      DatabaseInfoList;
507  typedef std::vector<BrowsingDataLocalStorageHelper::LocalStorageInfo>
508      LocalStorageInfoList;
509  typedef std::vector<BrowsingDataLocalStorageHelper::LocalStorageInfo>
510      SessionStorageInfoList;
511  typedef std::vector<BrowsingDataIndexedDBHelper::IndexedDBInfo>
512      IndexedDBInfoList;
513
514  void LoadCookies();
515  void LoadCookiesWithFilter(const std::wstring& filter);
516
517  void OnAppCacheModelInfoLoaded();
518  void OnDatabaseModelInfoLoaded(const DatabaseInfoList& database_info);
519  void OnLocalStorageModelInfoLoaded(
520      const LocalStorageInfoList& local_storage_info);
521  void OnSessionStorageModelInfoLoaded(
522      const LocalStorageInfoList& local_storage_info);
523  void OnIndexedDBModelInfoLoaded(
524      const IndexedDBInfoList& indexed_db_info);
525
526  void PopulateAppCacheInfoWithFilter(const std::wstring& filter);
527  void PopulateDatabaseInfoWithFilter(const std::wstring& filter);
528  void PopulateLocalStorageInfoWithFilter(const std::wstring& filter);
529  void PopulateSessionStorageInfoWithFilter(const std::wstring& filter);
530  void PopulateIndexedDBInfoWithFilter(const std::wstring& filter);
531
532  void NotifyObserverBeginBatch();
533  void NotifyObserverEndBatch();
534
535  scoped_refptr<net::CookieMonster> cookie_monster_;
536  CookieList all_cookies_;
537
538  scoped_refptr<BrowsingDataAppCacheHelper> appcache_helper_;
539  scoped_refptr<BrowsingDataDatabaseHelper> database_helper_;
540  scoped_refptr<appcache::AppCacheInfoCollection> appcache_info_;
541  DatabaseInfoList database_info_list_;
542
543  scoped_refptr<BrowsingDataLocalStorageHelper> local_storage_helper_;
544  scoped_refptr<BrowsingDataLocalStorageHelper> session_storage_helper_;
545  scoped_refptr<BrowsingDataIndexedDBHelper> indexed_db_helper_;
546  LocalStorageInfoList local_storage_info_list_;
547  LocalStorageInfoList session_storage_info_list_;
548  IndexedDBInfoList indexed_db_info_list_;
549
550  // The CookiesTreeModel maintains a separate list of observers that are
551  // specifically of the type CookiesTreeModel::Observer.
552  ObserverList<Observer> cookies_observer_list_;
553
554  // If this is non-zero, then this model is batching updates (there's a lot of
555  // notifications coming down the pipe). This is an integer is used to balance
556  // calls to Begin/EndBatch() if they're called in a nested manner.
557  int batch_update_;
558
559  // If true, use the CanonicalCookie::Source attribute to group cookies.
560  // Otherwise, use the CanonicalCookie::Domain attribute.
561  bool use_cookie_source_;
562
563  friend class CookieTreeAppCacheNode;
564  friend class CookieTreeCookieNode;
565  friend class CookieTreeDatabaseNode;
566  friend class CookieTreeLocalStorageNode;
567  friend class CookieTreeIndexedDBNode;
568
569  DISALLOW_COPY_AND_ASSIGN(CookiesTreeModel);
570};
571
572#endif  // CHROME_BROWSER_COOKIES_TREE_MODEL_H_
573