| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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/intents/web_intents_model.h" | |
| 6 | |
| 7 #include "base/string_split.h" | |
| 8 #include "base/string_util.h" | |
| 9 #include "base/stringprintf.h" | |
| 10 #include "base/utf_string_conversions.h" | |
| 11 #include "chrome/browser/intents/web_intents_registry.h" | |
| 12 | |
| 13 WebIntentsTreeNode::WebIntentsTreeNode() | |
| 14 : ui::TreeNode<WebIntentsTreeNode>(string16()), | |
| 15 type_(TYPE_ROOT) {} | |
| 16 | |
| 17 WebIntentsTreeNode::WebIntentsTreeNode(const string16& title) | |
| 18 : ui::TreeNode<WebIntentsTreeNode>(title), | |
| 19 type_(TYPE_ORIGIN) {} | |
| 20 | |
| 21 WebIntentsTreeNode::~WebIntentsTreeNode() {} | |
| 22 | |
| 23 ServiceTreeNode::ServiceTreeNode(const string16& title) | |
| 24 : WebIntentsTreeNode(title, WebIntentsTreeNode::TYPE_SERVICE), | |
| 25 blocked_(false), | |
| 26 disabled_(false) {} | |
| 27 | |
| 28 ServiceTreeNode::~ServiceTreeNode() {} | |
| 29 | |
| 30 WebIntentsModel::WebIntentsModel(WebIntentsRegistry* intents_registry) | |
| 31 : ui::TreeNodeModel<WebIntentsTreeNode>(new WebIntentsTreeNode()), | |
| 32 intents_registry_(intents_registry), | |
| 33 batch_update_(0) { | |
| 34 LoadModel(); | |
| 35 } | |
| 36 | |
| 37 WebIntentsModel::~WebIntentsModel() {} | |
| 38 | |
| 39 void WebIntentsModel::AddWebIntentsTreeObserver(Observer* observer) { | |
| 40 intents_observer_list_.AddObserver(observer); | |
| 41 // Call super so that TreeNodeModel can notify, too. | |
| 42 ui::TreeNodeModel<WebIntentsTreeNode>::AddObserver(observer); | |
| 43 } | |
| 44 | |
| 45 void WebIntentsModel::RemoveWebIntentsTreeObserver(Observer* observer) { | |
| 46 intents_observer_list_.RemoveObserver(observer); | |
| 47 // Call super so that TreeNodeModel doesn't have dead pointers. | |
| 48 ui::TreeNodeModel<WebIntentsTreeNode>::RemoveObserver(observer); | |
| 49 } | |
| 50 | |
| 51 string16 WebIntentsModel::GetTreeNodeId(WebIntentsTreeNode* node) { | |
| 52 if (node->Type() == WebIntentsTreeNode::TYPE_ORIGIN) | |
| 53 return node->GetTitle(); | |
| 54 | |
| 55 // TODO(gbillock): handle TYPE_SERVICE when/if we ever want to do | |
| 56 // specific managing of them. | |
| 57 | |
| 58 return string16(); | |
| 59 } | |
| 60 | |
| 61 WebIntentsTreeNode* WebIntentsModel::GetTreeNode(const std::string& path_id) { | |
| 62 if (path_id.empty()) | |
| 63 return GetRoot(); | |
| 64 | |
| 65 std::vector<std::string> node_ids; | |
| 66 base::SplitString(path_id, ',', &node_ids); | |
| 67 | |
| 68 for (int i = 0; i < GetRoot()->child_count(); ++i) { | |
| 69 WebIntentsTreeNode* node = GetRoot()->GetChild(i); | |
| 70 if (UTF16ToUTF8(node->GetTitle()) == node_ids[0]) { | |
| 71 if (node_ids.size() == 1) | |
| 72 return node; | |
| 73 } | |
| 74 } | |
| 75 | |
| 76 // TODO: support service nodes? | |
| 77 return NULL; | |
| 78 } | |
| 79 | |
| 80 void WebIntentsModel::GetChildNodeList(WebIntentsTreeNode* parent, | |
| 81 int start, int count, | |
| 82 base::ListValue* nodes) { | |
| 83 for (int i = 0; i < count; ++i) { | |
| 84 base::DictionaryValue* dict = new base::DictionaryValue; | |
| 85 WebIntentsTreeNode* child = parent->GetChild(start + i); | |
| 86 GetWebIntentsTreeNodeDictionary(*child, dict); | |
| 87 nodes->Append(dict); | |
| 88 } | |
| 89 } | |
| 90 | |
| 91 void WebIntentsModel::GetWebIntentsTreeNodeDictionary( | |
| 92 const WebIntentsTreeNode& node, | |
| 93 base::DictionaryValue* dict) { | |
| 94 if (node.Type() == WebIntentsTreeNode::TYPE_ROOT) { | |
| 95 dict->SetBoolean("hasChildren", !node.empty()); | |
| 96 dict->SetInteger("numChildren", node.child_count()); | |
| 97 return; | |
| 98 } | |
| 99 | |
| 100 if (node.Type() == WebIntentsTreeNode::TYPE_ORIGIN) { | |
| 101 dict->SetString("site", node.GetTitle()); | |
| 102 dict->SetBoolean("hasChildren", !node.empty()); | |
| 103 dict->SetInteger("numChildren", node.child_count()); | |
| 104 return; | |
| 105 } | |
| 106 | |
| 107 if (node.Type() == WebIntentsTreeNode::TYPE_SERVICE) { | |
| 108 const ServiceTreeNode* snode = static_cast<const ServiceTreeNode*>(&node); | |
| 109 dict->SetString("site", snode->GetTitle()); | |
| 110 dict->SetString("name", snode->ServiceName()); | |
| 111 dict->SetString("url", snode->ServiceUrl()); | |
| 112 dict->SetString("icon", snode->IconUrl()); | |
| 113 dict->SetString("action", snode->Action()); | |
| 114 dict->Set("types", snode->Types().DeepCopy()); | |
| 115 dict->SetBoolean("blocked", snode->IsBlocked()); | |
| 116 dict->SetBoolean("disabled", snode->IsDisabled()); | |
| 117 return; | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 WebIntentsTreeNode* WebIntentsModel::GetNodeForHost(const std::string& host) { | |
| 122 WebIntentsTreeNode* root = GetRoot(); | |
| 123 for (int i = 0; i < root->child_count(); ++i) { | |
| 124 if (UTF16ToASCII(root->GetChild(i)->GetTitle()) == host) | |
| 125 return root->GetChild(i); | |
| 126 } | |
| 127 | |
| 128 // Couldn't find an existing matching node; create a new one. | |
| 129 WebIntentsTreeNode* origin = new WebIntentsTreeNode(ASCIIToUTF16(host)); | |
| 130 Add(GetRoot(), origin, GetRoot()->child_count()); | |
| 131 return origin; | |
| 132 } | |
| 133 | |
| 134 void WebIntentsModel::LoadModel() { | |
| 135 NotifyObserverBeginBatch(); | |
| 136 intents_registry_->GetAllIntentServices( | |
| 137 base::Bind(&WebIntentsModel::OnIntentsQueryDone, base::Unretained(this))); | |
| 138 } | |
| 139 | |
| 140 void WebIntentsModel::OnIntentsQueryDone( | |
| 141 const std::vector<webkit_glue::WebIntentServiceData>& services) { | |
| 142 for (size_t i = 0; i < services.size(); ++i) { | |
| 143 WebIntentsTreeNode* n = GetNodeForHost(services[i].service_url.host()); | |
| 144 ServiceTreeNode* ns = new ServiceTreeNode(ASCIIToUTF16( | |
| 145 services[i].service_url.host())); | |
| 146 ns->SetServiceName(services[i].title); | |
| 147 ns->SetServiceUrl(ASCIIToUTF16(services[i].service_url.spec())); | |
| 148 GURL icon_url = services[i].service_url.GetOrigin().Resolve("/favicon.ico"); | |
| 149 ns->SetIconUrl(ASCIIToUTF16(icon_url.spec())); | |
| 150 ns->SetAction(services[i].action); | |
| 151 ns->AddType(services[i].type); | |
| 152 Add(n, ns, n->child_count()); | |
| 153 } | |
| 154 | |
| 155 NotifyObserverEndBatch(); | |
| 156 } | |
| 157 | |
| 158 void WebIntentsModel::NotifyObserverBeginBatch() { | |
| 159 // Only notify the model once if we're batching in a nested manner. | |
| 160 if (batch_update_++ == 0) { | |
| 161 FOR_EACH_OBSERVER(Observer, | |
| 162 intents_observer_list_, | |
| 163 TreeModelBeginBatch(this)); | |
| 164 } | |
| 165 } | |
| 166 | |
| 167 void WebIntentsModel::NotifyObserverEndBatch() { | |
| 168 // Only notify the observers if this is the outermost call to EndBatch() if | |
| 169 // called in a nested manner. | |
| 170 if (--batch_update_ == 0) { | |
| 171 FOR_EACH_OBSERVER(Observer, | |
| 172 intents_observer_list_, | |
| 173 TreeModelEndBatch(this)); | |
| 174 } | |
| 175 } | |
| OLD | NEW |