blob: 2bf63f262e91a8a86eedc5c53996b14cc49a4e40 [file] [log] [blame]
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/bookmarks/managed/managed_bookmarks_policy_handler.h"
#include <utility>
#include "base/values.h"
#include "components/bookmarks/common/bookmark_pref_names.h"
#include "components/bookmarks/managed/managed_bookmarks_tracker.h"
#include "components/policy/core/browser/policy_error_map.h"
#include "components/policy/core/common/policy_logger.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_value_map.h"
#include "components/url_formatter/url_fixer.h"
#include "url/gurl.h"
using bookmarks::ManagedBookmarksTracker;
namespace bookmarks {
ManagedBookmarksPolicyHandler::ManagedBookmarksPolicyHandler(
policy::Schema chrome_schema)
: SchemaValidatingPolicyHandler(
policy::key::kManagedBookmarks,
chrome_schema.GetKnownProperty(policy::key::kManagedBookmarks),
policy::SCHEMA_ALLOW_UNKNOWN) {}
ManagedBookmarksPolicyHandler::~ManagedBookmarksPolicyHandler() = default;
void ManagedBookmarksPolicyHandler::ApplyPolicySettings(
const policy::PolicyMap& policies,
PrefValueMap* prefs) {
std::unique_ptr<base::Value> value;
if (!CheckAndGetValue(policies, nullptr, &value)) {
LOG_POLICY(ERROR, POLICY_PROCESSING)
<< "Failed to validate bookmarks policy schema.";
return;
}
if (!value || !value->is_list())
return;
prefs->SetString(prefs::kManagedBookmarksFolderName,
GetFolderName(value->GetList()));
base::Value::List filtered(FilterBookmarks(std::move(*value).TakeList()));
prefs->SetValue(prefs::kManagedBookmarks, base::Value(std::move(filtered)));
}
std::string ManagedBookmarksPolicyHandler::GetFolderName(
const base::Value::List& list) {
// Iterate over the list, and try to find the FolderName.
for (const auto& el : list) {
if (!el.is_dict())
continue;
const std::string* name =
el.GetDict().FindString(ManagedBookmarksTracker::kFolderName);
if (name)
return *name;
}
LOG_POLICY(WARNING, POLICY_PROCESSING)
<< "Bookmarks policy has no top_level name";
// FolderName not present.
return std::string();
}
base::Value::List ManagedBookmarksPolicyHandler::FilterBookmarks(
base::Value::List list) {
// Move over conforming values found.
base::Value::List out;
for (base::Value& item : list) {
if (!item.is_dict())
continue;
base::Value::Dict& dict = item.GetDict();
const std::string* name = dict.FindString(ManagedBookmarksTracker::kName);
const std::string* url = dict.FindString(ManagedBookmarksTracker::kUrl);
base::Value::List* children =
dict.FindList(ManagedBookmarksTracker::kChildren);
// Every bookmark must have a name, and then either a URL or a list of
// child bookmarks.
if (!name || (!url && !children)) {
// Do not log error for the {"top_level name": "value"} dictionary
if (!dict.contains(ManagedBookmarksTracker::kFolderName)) {
LOG_POLICY(ERROR, POLICY_PROCESSING)
<< "Error in bookmark policy item: " << dict.DebugString()
<< ". Item must have a name and a URL or a list of child "
"bookmarks.";
}
continue;
}
if (children) {
*children = FilterBookmarks(std::move(*children));
// Ignore the URL if this bookmark has child nodes. Note that this needs
// to be after `children` is overwritten, in case removing an entry from
// the dictionary invalidates its pointers.
dict.Remove(ManagedBookmarksTracker::kUrl);
} else {
// Make sure the URL is valid before passing a bookmark to the pref.
dict.Remove(ManagedBookmarksTracker::kChildren);
GURL gurl = url_formatter::FixupURL(*url, std::string());
if (!gurl.is_valid()) {
LOG_POLICY(ERROR, POLICY_PROCESSING)
<< "Invalid bookmark URL: " << *url;
continue;
}
dict.Set(ManagedBookmarksTracker::kUrl, gurl.spec());
}
out.Append(std::move(item));
}
return out;
}
} // namespace bookmarks