| Index: chrome/browser/ui/intents/intents_model.cc
|
| diff --git a/chrome/browser/ui/intents/intents_model.cc b/chrome/browser/ui/intents/intents_model.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..81147249d076cbbf0b55c22aec38b8f0ddd763ab
|
| --- /dev/null
|
| +++ b/chrome/browser/ui/intents/intents_model.cc
|
| @@ -0,0 +1,152 @@
|
| +// Copyright (c) 2011 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/ui/intents/intents_model.h"
|
| +#include "base/string_split.h"
|
| +#include "base/string_util.h"
|
| +#include "base/stringprintf.h"
|
| +#include "base/utf_string_conversions.h"
|
| +#include "chrome/browser/intents/web_intents_registry.h"
|
| +
|
| +ServiceTreeNode::ServiceTreeNode(const string16& title)
|
| + : IntentsTreeNode(title, IntentsTreeNode::TYPE_SERVICE),
|
| + blocked_(false),
|
| + disabled_(false) {}
|
| +
|
| +ServiceTreeNode::~ServiceTreeNode() {}
|
| +
|
| +IntentsModel::IntentsModel(WebIntentsRegistry* intents_registry)
|
| + : ui::TreeNodeModel<IntentsTreeNode>(new IntentsTreeNode()),
|
| + intents_registry_(intents_registry),
|
| + batch_update_(0) {
|
| + LoadModel();
|
| +}
|
| +
|
| +IntentsModel::~IntentsModel() {}
|
| +
|
| +void IntentsModel::AddIntentsTreeObserver(Observer* observer) {
|
| + intents_observer_list_.AddObserver(observer);
|
| + // Call super so that TreeNodeModel can notify, too.
|
| + ui::TreeNodeModel<IntentsTreeNode>::AddObserver(observer);
|
| +}
|
| +
|
| +void IntentsModel::RemoveIntentsTreeObserver(Observer* observer) {
|
| + intents_observer_list_.RemoveObserver(observer);
|
| + // Call super so that TreeNodeModel doesn't have dead pointers.
|
| + ui::TreeNodeModel<IntentsTreeNode>::RemoveObserver(observer);
|
| +}
|
| +
|
| +string16 IntentsModel::GetTreeNodeId(IntentsTreeNode* node) {
|
| + if (node->Type() == IntentsTreeNode::TYPE_ORIGIN)
|
| + return node->GetTitle();
|
| +
|
| + // TODO(gbillock): handle TYPE_SERVICE when/if we ever want to do
|
| + // specific managing of them.
|
| +
|
| + return string16();
|
| +}
|
| +
|
| +IntentsTreeNode* IntentsModel::GetTreeNode(std::string path_id) {
|
| + if (path_id.empty())
|
| + return GetRoot();
|
| +
|
| + std::vector<std::string> node_ids;
|
| + base::SplitString(path_id, ',', &node_ids);
|
| +
|
| + for (int i = 0; i < GetRoot()->child_count(); ++i) {
|
| + IntentsTreeNode* node = GetRoot()->GetChild(i);
|
| + if (UTF16ToUTF8(node->GetTitle()) == node_ids[0]) {
|
| + if (node_ids.size() == 1)
|
| + return node;
|
| + }
|
| + }
|
| +
|
| + // TODO: support service nodes?
|
| + return NULL;
|
| +}
|
| +
|
| +void IntentsModel::GetChildNodeList(IntentsTreeNode* parent,
|
| + int start, int count,
|
| + base::ListValue* nodes) {
|
| + for (int i = 0; i < count; ++i) {
|
| + base::DictionaryValue* dict = new base::DictionaryValue;
|
| + IntentsTreeNode* child = parent->GetChild(start + i);
|
| + GetIntentsTreeNodeDictionary(*child, dict);
|
| + nodes->Append(dict);
|
| + }
|
| +}
|
| +
|
| +void IntentsModel::GetIntentsTreeNodeDictionary(const IntentsTreeNode& node,
|
| + base::DictionaryValue* dict) {
|
| + if (node.Type() == IntentsTreeNode::TYPE_ROOT) {
|
| + return;
|
| + }
|
| +
|
| + if (node.Type() == IntentsTreeNode::TYPE_ORIGIN) {
|
| + dict->SetString("site", node.GetTitle());
|
| + dict->SetBoolean("hasChildren", node.child_count() > 0);
|
| + return;
|
| + }
|
| +
|
| + if (node.Type() == IntentsTreeNode::TYPE_SERVICE) {
|
| + const ServiceTreeNode* snode = static_cast<const ServiceTreeNode*>(&node);
|
| + dict->SetString("site", snode->GetTitle());
|
| + dict->SetString("name", snode->ServiceName());
|
| + dict->SetString("url", snode->ServiceUrl());
|
| + dict->SetString("icon", snode->IconUrl());
|
| + dict->SetString("action", snode->Action());
|
| + dict->Set("types", snode->Types().DeepCopy());
|
| + dict->SetBoolean("blocked", snode->IsBlocked());
|
| + dict->SetBoolean("disabled", snode->IsDisabled());
|
| + return;
|
| + }
|
| +}
|
| +
|
| +void IntentsModel::LoadModel() {
|
| + NotifyObserverBeginBatch();
|
| + intents_registry_->GetAllIntentProviders(this);
|
| +}
|
| +
|
| +void IntentsModel::OnIntentsQueryDone(
|
| + WebIntentsRegistry::QueryID query_id,
|
| + const std::vector<WebIntentData>& intents) {
|
| + for (size_t i = 0; i < intents.size(); ++i) {
|
| + // Eventually do some awesome sorting, grouping, clustering stuff here.
|
| + // For now, just stick it in the model flat.
|
| + IntentsTreeNode* n = new IntentsTreeNode(ASCIIToUTF16(
|
| + intents[i].service_url.host()));
|
| + ServiceTreeNode* ns = new ServiceTreeNode(ASCIIToUTF16(
|
| + intents[i].service_url.host()));
|
| + ns->SetServiceName(intents[i].title);
|
| + ns->SetServiceUrl(ASCIIToUTF16(intents[i].service_url.spec()));
|
| + GURL icon_url = intents[i].service_url.GetOrigin().Resolve("/favicon.ico");
|
| + ns->SetIconUrl(ASCIIToUTF16(icon_url.spec()));
|
| + ns->SetAction(intents[i].action);
|
| + ns->AddType(intents[i].type);
|
| + // Won't generate a notification. OK for now as the next line will.
|
| + n->Add(ns, 0);
|
| + Add(GetRoot(), n, GetRoot()->child_count());
|
| + }
|
| +
|
| + NotifyObserverEndBatch();
|
| +}
|
| +
|
| +void IntentsModel::NotifyObserverBeginBatch() {
|
| + // Only notify the model once if we're batching in a nested manner.
|
| + if (batch_update_++ == 0) {
|
| + FOR_EACH_OBSERVER(Observer,
|
| + intents_observer_list_,
|
| + TreeModelBeginBatch(this));
|
| + }
|
| +}
|
| +
|
| +void IntentsModel::NotifyObserverEndBatch() {
|
| + // Only notify the observers if this is the outermost call to EndBatch() if
|
| + // called in a nested manner.
|
| + if (--batch_update_ == 0) {
|
| + FOR_EACH_OBSERVER(Observer,
|
| + intents_observer_list_,
|
| + TreeModelEndBatch(this));
|
| + }
|
| +}
|
|
|