summaryrefslogtreecommitdiffstats
path: root/chrome/browser/cookies_tree_model.cc
diff options
context:
space:
mode:
authorian@chromium.org <ian@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-06 04:58:48 +0000
committerian@chromium.org <ian@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-06 04:58:48 +0000
commitdce516200cbac6100f0268c5f036e8dbddf4f8ac (patch)
tree9e758547e48369576b568c8dd46d69fb8a75f958 /chrome/browser/cookies_tree_model.cc
parent91c836e0591bd3c3d874eb18d2403ce927e6be6a (diff)
downloadchromium_src-dce516200cbac6100f0268c5f036e8dbddf4f8ac.zip
chromium_src-dce516200cbac6100f0268c5f036e8dbddf4f8ac.tar.gz
chromium_src-dce516200cbac6100f0268c5f036e8dbddf4f8ac.tar.bz2
Converting the Cookies options page from a TableView to a TreeView
so that we can add in Database, LocalStorage, and Appcache next to the cookies for an origin. BUG=26713 TEST=cookies_tree_model_unittest.cc Review URL: http://codereview.chromium.org/365005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@31207 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/cookies_tree_model.cc')
-rw-r--r--chrome/browser/cookies_tree_model.cc231
1 files changed, 231 insertions, 0 deletions
diff --git a/chrome/browser/cookies_tree_model.cc b/chrome/browser/cookies_tree_model.cc
new file mode 100644
index 0000000..1ec6e3f
--- /dev/null
+++ b/chrome/browser/cookies_tree_model.cc
@@ -0,0 +1,231 @@
+// Copyright (c) 2009 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/cookies_tree_model.h"
+
+#include <algorithm>
+#include <functional>
+#include <vector>
+
+#include "app/l10n_util.h"
+#include "app/resource_bundle.h"
+#include "app/table_model_observer.h"
+#include "app/tree_node_model.h"
+#include "base/linked_ptr.h"
+#include "base/string_util.h"
+#include "chrome/browser/net/chrome_url_request_context.h"
+#include "chrome/browser/profile.h"
+#include "grit/app_resources.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "net/base/cookie_monster.h"
+#include "net/url_request/url_request_context.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CookieTreeNode, public:
+
+void CookieTreeNode::DeleteStoredObjects() {
+ std::for_each(children().begin(),
+ children().end(),
+ std::mem_fun(&CookieTreeNode::DeleteStoredObjects));
+}
+
+CookiesTreeModel* CookieTreeNode::GetModel() const {
+ if (GetParent())
+ return GetParent()->GetModel();
+ else
+ return NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// CookieTreeCookieNode, public:
+
+CookieTreeCookieNode::CookieTreeCookieNode(
+ net::CookieMonster::CookieListPair* cookie)
+ : CookieTreeNode(UTF8ToWide(cookie->second.Name())),
+ cookie_(cookie) {
+}
+
+void CookieTreeCookieNode::DeleteStoredObjects() {
+ GetModel()->DeleteCookie(*cookie_);
+}
+
+namespace {
+// comparison functor, for use in CookieTreeRootNode
+class OriginNodeComparator {
+ public:
+ bool operator() (const CookieTreeNode* lhs,
+ const CookieTreeNode* rhs) {
+ return (lhs->GetTitle() < rhs->GetTitle());
+ }
+};
+
+} // namespace
+
+///////////////////////////////////////////////////////////////////////////////
+// CookieTreeRootNode, public:
+CookieTreeOriginNode* CookieTreeRootNode::GetOrCreateOriginNode(
+ const std::wstring& origin) {
+ // Strip the trailing dot if it exists.
+ std::wstring rewritten_origin = origin;
+ if (origin.length() >= 1 && origin[0] == '.')
+ rewritten_origin = origin.substr(1);
+
+ CookieTreeOriginNode rewritten_origin_node(rewritten_origin);
+
+ // First see if there is an existing match.
+ std::vector<CookieTreeNode*>::iterator origin_node_iterator =
+ lower_bound(children().begin(),
+ children().end(),
+ &rewritten_origin_node,
+ OriginNodeComparator());
+
+ if (origin_node_iterator != children().end() && rewritten_origin ==
+ (*origin_node_iterator)->GetTitle())
+ return static_cast<CookieTreeOriginNode*>(*origin_node_iterator);
+ // Node doesn't exist, create a new one and insert it into the (ordered)
+ // children.
+ CookieTreeOriginNode* retval = new CookieTreeOriginNode(rewritten_origin);
+ DCHECK(model_);
+ model_->Add(this, (origin_node_iterator - children().begin()), retval);
+ return retval;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// CookieTreeOriginNode, public:
+
+CookieTreeCookiesNode* CookieTreeOriginNode::GetOrCreateCookiesNode() {
+ if (cookies_child_)
+ return cookies_child_;
+ // need to make a Cookies node, add it to the tree, and return it
+ CookieTreeCookiesNode* retval = new CookieTreeCookiesNode;
+ GetModel()->Add(this, 0, retval);
+ cookies_child_ = retval;
+ return retval;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// CookieTreeCookiesNode, public:
+
+CookieTreeCookiesNode::CookieTreeCookiesNode()
+ : CookieTreeNode(l10n_util::GetString(IDS_COOKIES_COOKIES)) {}
+
+
+void CookieTreeCookiesNode::AddCookieNode(
+ CookieTreeCookieNode* new_child) {
+ std::vector<CookieTreeNode*>::iterator cookie_iterator =
+ lower_bound(children().begin(),
+ children().end(),
+ new_child,
+ CookieTreeCookieNode::CookieNodeComparator());
+ GetModel()->Add(this, (cookie_iterator - children().begin()), new_child);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// CookieTreeCookieNode, private
+
+bool CookieTreeCookieNode::CookieNodeComparator::operator() (
+ const CookieTreeNode* lhs, const CookieTreeNode* rhs) {
+ return (static_cast<const CookieTreeCookieNode*>(lhs)->
+ cookie_->second.Name() <
+ static_cast<const CookieTreeCookieNode*>(rhs)->
+ cookie_->second.Name());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// CookiesTreeModel, public:
+
+CookiesTreeModel::CookiesTreeModel(Profile* profile)
+ : ALLOW_THIS_IN_INITIALIZER_LIST(TreeNodeModel<CookieTreeNode>(
+ new CookieTreeRootNode(this))),
+ profile_(profile) {
+ LoadCookies();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// CookiesTreeModel, TreeModel methods (public):
+
+// TreeModel methods:
+// Returns the set of icons for the nodes in the tree. You only need override
+// this if you don't want to use the default folder icons.
+void CookiesTreeModel::GetIcons(std::vector<SkBitmap>* icons) {
+ icons->push_back(*ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ IDR_DEFAULT_FAVICON));
+ icons->push_back(*ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ IDR_COOKIE_ICON));
+}
+
+// Returns the index of the icon to use for |node|. Return -1 to use the
+// default icon. The index is relative to the list of icons returned from
+// GetIcons.
+int CookiesTreeModel::GetIconIndex(TreeModelNode* node) {
+ CookieTreeNode* ct_node = static_cast<CookieTreeNode*>(node);
+ switch (ct_node->GetDetailedInfo().node_type) {
+ case CookieTreeNode::DetailedInfo::TYPE_ORIGIN:
+ return ORIGIN;
+ break;
+ case CookieTreeNode::DetailedInfo::TYPE_COOKIE:
+ return COOKIE;
+ break;
+ default:
+ return -1;
+ }
+}
+
+void CookiesTreeModel::LoadCookies() {
+ // mmargh mmargh mmargh!
+
+ // Since we are running on the UI thread don't call GetURLRequestContext().
+ net::CookieMonster* cookie_monster =
+ profile_->GetRequestContext()->GetCookieStore()->GetCookieMonster();
+
+ all_cookies_ = cookie_monster->GetAllCookies();
+ CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot());
+ for (CookieList::iterator it = all_cookies_.begin();
+ it != all_cookies_.end();
+ ++it) {
+ // Get the origin cookie
+ CookieTreeOriginNode* origin =
+ root->GetOrCreateOriginNode(UTF8ToWide(it->first));
+ CookieTreeCookiesNode* cookies_node = origin->GetOrCreateCookiesNode();
+ CookieTreeCookieNode* new_cookie = new CookieTreeCookieNode(&*it);
+ cookies_node->AddCookieNode(new_cookie);
+ }
+}
+
+void CookiesTreeModel::DeleteCookie(
+ const net::CookieMonster::CookieListPair& cookie) {
+ // notify CookieMonster that we should delete this cookie
+ // Since we are running on the UI thread don't call GetURLRequestContext().
+ net::CookieMonster* monster =
+ profile_->GetRequestContext()->GetCookieStore()->GetCookieMonster();
+ // We have stored a copy of all the cookies in the model, and our model is
+ // never re-calculated. Thus, we just need to delete the nodes from our
+ // model, and tell CookieMonster to delete the cookies. We can keep the
+ // vector storing the cookies in-tact and not delete from there (that would
+ // invalidate our pointers), and the fact that it contains semi out-of-date
+ // data is not problematic as we don't re-build the model based on that.
+ monster->DeleteCookie(cookie.first, cookie.second, true);
+}
+
+void CookiesTreeModel::DeleteAllCookies() {
+ CookieTreeNode* root = GetRoot();
+ root->DeleteStoredObjects();
+ int num_children = root->GetChildCount();
+ for (int i = num_children - 1; i >= 0; --i) {
+ delete Remove(root, i);
+ }
+ LoadCookies();
+ NotifyObserverTreeNodeChanged(root);
+}
+
+void CookiesTreeModel::DeleteCookieNode(CookieTreeCookieNode* cookie_node) {
+ cookie_node->DeleteStoredObjects();
+ // find the parent and index
+ CookieTreeNode* parent_node = cookie_node->GetParent();
+ int cookie_node_index = parent_node->IndexOfChild(cookie_node);
+ delete Remove(parent_node, cookie_node_index);
+}