| Index: components/bookmarks/browser/managed_bookmarks_tracker.cc
|
| diff --git a/components/bookmarks/browser/managed_bookmarks_tracker.cc b/components/bookmarks/browser/managed_bookmarks_tracker.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..27e0170d4775462e4dedce9910a6b310ae96cf14
|
| --- /dev/null
|
| +++ b/components/bookmarks/browser/managed_bookmarks_tracker.cc
|
| @@ -0,0 +1,170 @@
|
| +// Copyright 2014 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 "components/bookmarks/browser/managed_bookmarks_tracker.h"
|
| +
|
| +#include <string>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/bind_helpers.h"
|
| +#include "base/prefs/pref_service.h"
|
| +#include "base/strings/utf_string_conversions.h"
|
| +#include "base/values.h"
|
| +#include "components/bookmarks/browser/bookmark_model.h"
|
| +#include "components/bookmarks/browser/bookmark_node.h"
|
| +#include "components/bookmarks/common/bookmark_pref_names.h"
|
| +#include "grit/components_strings.h"
|
| +#include "ui/base/l10n/l10n_util.h"
|
| +#include "url/gurl.h"
|
| +
|
| +const char ManagedBookmarksTracker::kName[] = "name";
|
| +const char ManagedBookmarksTracker::kUrl[] = "url";
|
| +const char ManagedBookmarksTracker::kChildren[] = "children";
|
| +
|
| +ManagedBookmarksTracker::ManagedBookmarksTracker(BookmarkModel* model,
|
| + PrefService* prefs)
|
| + : model_(model), prefs_(prefs) {}
|
| +
|
| +ManagedBookmarksTracker::~ManagedBookmarksTracker() {}
|
| +
|
| +scoped_ptr<base::ListValue>
|
| +ManagedBookmarksTracker::GetInitialManagedBookmarks() {
|
| + const base::ListValue* list = prefs_->GetList(prefs::kManagedBookmarks);
|
| + return make_scoped_ptr(list->DeepCopy());
|
| +}
|
| +
|
| +// static
|
| +int64 ManagedBookmarksTracker::LoadInitial(BookmarkNode* folder,
|
| + const base::ListValue* list,
|
| + int64 next_node_id) {
|
| + for (size_t i = 0; i < list->GetSize(); ++i) {
|
| + // Extract the data for the next bookmark from the |list|.
|
| + base::string16 title;
|
| + GURL url;
|
| + const base::ListValue* children = NULL;
|
| + if (!LoadBookmark(list, i, &title, &url, &children))
|
| + continue;
|
| +
|
| + BookmarkNode* child = new BookmarkNode(next_node_id++, url);
|
| + child->SetTitle(title);
|
| + folder->Add(child, folder->child_count());
|
| + if (children) {
|
| + child->set_type(BookmarkNode::FOLDER);
|
| + child->set_date_folder_modified(base::Time::Now());
|
| + next_node_id = LoadInitial(child, children, next_node_id);
|
| + } else {
|
| + child->set_type(BookmarkNode::URL);
|
| + child->set_date_added(base::Time::Now());
|
| + }
|
| + }
|
| +
|
| + return next_node_id;
|
| +}
|
| +
|
| +void ManagedBookmarksTracker::Init() {
|
| + registrar_.Init(prefs_);
|
| + registrar_.Add(prefs::kManagedBookmarks,
|
| + base::Bind(&ManagedBookmarksTracker::ReloadManagedBookmarks,
|
| + base::Unretained(this)));
|
| + // Reload now just in case something changed since the initial load started.
|
| + ReloadManagedBookmarks();
|
| +}
|
| +
|
| +void ManagedBookmarksTracker::ReloadManagedBookmarks() {
|
| + // Update the managed bookmarks folder title, in case the user just signed
|
| + // into or out of a managed account.
|
| + base::string16 title;
|
| + std::string domain = model_->client()->GetManagedBookmarksDomain();
|
| + if (domain.empty()) {
|
| + title =
|
| + l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_MANAGED_FOLDER_DEFAULT_NAME);
|
| + } else {
|
| + title = l10n_util::GetStringFUTF16(
|
| + IDS_BOOKMARK_BAR_MANAGED_FOLDER_DOMAIN_NAME, base::UTF8ToUTF16(domain));
|
| + }
|
| + const BookmarkNode* managed_node = model_->managed_node();
|
| + model_->SetTitle(managed_node, title);
|
| +
|
| + // Recursively update all the managed bookmarks and folders.
|
| + const base::ListValue* list = prefs_->GetList(prefs::kManagedBookmarks);
|
| + UpdateBookmarks(managed_node, list);
|
| +
|
| + // The managed bookmarks folder isn't visible when that policy isn't present.
|
| + model_->SetPermanentNodeVisible(BookmarkNode::MANAGED,
|
| + !managed_node->empty());
|
| +}
|
| +
|
| +void ManagedBookmarksTracker::UpdateBookmarks(const BookmarkNode* folder,
|
| + const base::ListValue* list) {
|
| + int folder_i = 0;
|
| + for (size_t i = 0; i < list->GetSize(); ++i) {
|
| + // Extract the data for the next bookmark from the |list|.
|
| + base::string16 title;
|
| + GURL url;
|
| + const base::ListValue* children = NULL;
|
| + if (!LoadBookmark(list, i, &title, &url, &children)) {
|
| + // Skip this bookmark from |list| but don't advance |folder_i|.
|
| + continue;
|
| + }
|
| +
|
| + // Look for a bookmark at |folder_i| or ahead that matches the current
|
| + // bookmark from the pref.
|
| + const BookmarkNode* existing = NULL;
|
| + for (int k = folder_i; k < folder->child_count(); ++k) {
|
| + const BookmarkNode* node = folder->GetChild(k);
|
| + if (node->GetTitle() == title &&
|
| + ((children && node->is_folder()) ||
|
| + (!children && node->url() == url))) {
|
| + existing = node;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + if (existing) {
|
| + // Reuse the existing node. The Move() is a nop if |existing| is already
|
| + // at |folder_i|.
|
| + model_->Move(existing, folder, folder_i);
|
| + if (children)
|
| + UpdateBookmarks(existing, children);
|
| + } else {
|
| + // Create a new node for this bookmark now.
|
| + if (children) {
|
| + const BookmarkNode* sub = model_->AddFolder(folder, folder_i, title);
|
| + UpdateBookmarks(sub, children);
|
| + } else {
|
| + model_->AddURL(folder, folder_i, title, url);
|
| + }
|
| + }
|
| +
|
| + // The |folder_i| index of |folder| has been updated, so advance it.
|
| + ++folder_i;
|
| + }
|
| +
|
| + // Remove any extra children of |folder| that haven't been reused.
|
| + while (folder->child_count() != folder_i)
|
| + model_->Remove(folder, folder_i);
|
| +}
|
| +
|
| +// static
|
| +bool ManagedBookmarksTracker::LoadBookmark(const base::ListValue* list,
|
| + size_t index,
|
| + base::string16* title,
|
| + GURL* url,
|
| + const base::ListValue** children) {
|
| + std::string spec;
|
| + *url = GURL();
|
| + *children = NULL;
|
| + const base::DictionaryValue* dict = NULL;
|
| + if (!list->GetDictionary(index, &dict) ||
|
| + !dict->GetString(kName, title) ||
|
| + (!dict->GetString(kUrl, &spec) &&
|
| + !dict->GetList(kChildren, children))) {
|
| + // Should never happen after policy validation.
|
| + NOTREACHED();
|
| + return false;
|
| + }
|
| + if (!*children)
|
| + *url = GURL(spec);
|
| + return true;
|
| +}
|
|
|