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_adapter.h"
6
7#include "base/memory/scoped_ptr.h"
8#include "base/string_number_conversions.h"
9#include "base/values.h"
10#include "chrome/browser/ui/webui/cookies_tree_model_util.h"
11#include "content/browser/webui/web_ui.h"
12#include "grit/generated_resources.h"
13#include "ui/base/l10n/l10n_util.h"
14
15namespace {
16
17// Returns a unique callback name for |adapter|'s requestChildren.
18std::string GetRequestChildrenCallbackName(CookiesTreeModelAdapter* adapter) {
19  static const char kPrefixLoadCookie[] = "requestChildren";
20  return std::string(kPrefixLoadCookie) +
21         base::HexEncode(&adapter, sizeof(adapter));
22}
23
24}  // namespace
25
26CookiesTreeModelAdapter::CookiesTreeModelAdapter()
27    : web_ui_(NULL),
28      model_(NULL),
29      batch_update_(false) {
30}
31
32CookiesTreeModelAdapter::~CookiesTreeModelAdapter() {
33  if (model_)
34    model_->RemoveCookiesTreeObserver(this);
35}
36
37void CookiesTreeModelAdapter::Init(WebUI* web_ui) {
38  web_ui_ = web_ui;
39
40  web_ui_->RegisterMessageCallback(GetRequestChildrenCallbackName(this),
41      NewCallback(this, &CookiesTreeModelAdapter::RequestChildren));
42}
43
44void CookiesTreeModelAdapter::Bind(const std::string& tree_id,
45                                   CookiesTreeModel* model) {
46  DCHECK(web_ui_);  // We should have been initialized.
47  DCHECK(tree_id_.empty() && !model_);  // No existing bindings.
48
49  tree_id_ = tree_id;
50  model_ = model;
51  model_->AddCookiesTreeObserver(this);
52
53  StringValue tree_id_value(tree_id_);
54  StringValue message_name(GetRequestChildrenCallbackName(this));
55  web_ui_->CallJavascriptFunction("ui.CookiesTree.setCallback",
56      tree_id_value, message_name);
57
58  SendChildren(model_->GetRoot());
59}
60
61void CookiesTreeModelAdapter::TreeNodesAdded(ui::TreeModel* model,
62                                             ui::TreeModelNode* parent,
63                                             int start,
64                                             int count) {
65  // Skip if there is a batch update in progress.
66  if (batch_update_)
67    return;
68
69  CookieTreeNode* parent_node = model_->AsNode(parent);
70
71  StringValue tree_id(tree_id_);
72  scoped_ptr<Value> parend_id(GetTreeNodeId(parent_node));
73  FundamentalValue start_value(start);
74  ListValue children;
75  cookies_tree_model_util::GetChildNodeList(parent_node, start, count,
76                                            &children);
77  web_ui_->CallJavascriptFunction("ui.CookiesTree.onTreeItemAdded",
78      tree_id, *parend_id.get(), start_value, children);
79}
80
81void CookiesTreeModelAdapter::TreeNodesRemoved(ui::TreeModel* model,
82                                               ui::TreeModelNode* parent,
83                                               int start,
84                                               int count) {
85  // Skip if there is a batch update in progress.
86  if (batch_update_)
87    return;
88
89  StringValue tree_id(tree_id_);
90  scoped_ptr<Value> parend_id(GetTreeNodeId(model_->AsNode(parent)));
91  FundamentalValue start_value(start);
92  FundamentalValue count_value(count);
93  web_ui_->CallJavascriptFunction("ui.CookiesTree.onTreeItemRemoved",
94      tree_id, *parend_id.get(), start_value, count_value);
95}
96
97void CookiesTreeModelAdapter::TreeModelBeginBatch(CookiesTreeModel* model) {
98  DCHECK(!batch_update_);  // There should be no nested batch begin.
99  batch_update_ = true;
100}
101
102void CookiesTreeModelAdapter::TreeModelEndBatch(CookiesTreeModel* model) {
103  DCHECK(batch_update_);
104  batch_update_ = false;
105
106  SendChildren(model_->GetRoot());
107}
108
109void CookiesTreeModelAdapter::RequestChildren(const ListValue* args) {
110  std::string node_path;
111  CHECK(args->GetString(0, &node_path));
112
113  CookieTreeNode* node = cookies_tree_model_util::GetTreeNodeFromPath(
114      model_->GetRoot(), node_path);
115  if (node)
116    SendChildren(node);
117}
118
119void CookiesTreeModelAdapter::SendChildren(CookieTreeNode* parent) {
120  StringValue tree_id(tree_id_);
121  scoped_ptr<Value> parend_id(GetTreeNodeId(model_->AsNode(parent)));
122  ListValue children;
123  cookies_tree_model_util::GetChildNodeList(parent, 0, parent->child_count(),
124      &children);
125  web_ui_->CallJavascriptFunction("ui.CookiesTree.setChildren",
126      tree_id, *parend_id.get(), children);
127}
128
129Value* CookiesTreeModelAdapter::GetTreeNodeId(CookieTreeNode* node) {
130  if (node == model_->GetRoot())
131    return Value::CreateNullValue();
132
133  return Value::CreateStringValue(
134      cookies_tree_model_util::GetTreeNodeId(node));
135}
136