1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
|
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_BOOKMARKS_PERMANENT_FOLDER_ORDERING_TRACKER_H_
#define CHROME_BROWSER_BOOKMARKS_PERMANENT_FOLDER_ORDERING_TRACKER_H_
#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "components/bookmarks/browser/bookmark_model_observer.h"
#include "components/bookmarks/browser/bookmark_node.h"
#include "components/bookmarks/browser/bookmark_node_data.h"
namespace bookmarks {
class BookmarkModel;
class BookmarkNode;
} // namespace bookmarks
// Tracks any custom order across child nodes of a particular local and account
// permanent bookmark node of a certain type `bookmarks::BookmarkNode::Type`
// (bookmark bar, other, mobile). Manages operations across children of local
// and account equivalent permanent node e.g. add, move, remove bookmark node.
// It also allows querying their direct children while respecting the custom
// order between the children of the two permanent nodes.
// If only local or syncable node exists, this class just forwards operations to
// the `BookmarkModel`.
class PermanentFolderOrderingTracker : public bookmarks::BookmarkModelObserver {
public:
class Delegate {
public:
// Called every time the ordering of the nodes in
// `PermanentFolderOrderingTracker` changes.
virtual void TrackedOrderingChanged() = 0;
virtual ~Delegate() = default;
};
// `tracked_type` must reflect the type of the permanent node, it must be
// one of the following: BOOKMARK_BAR, OTHER_NODE, MOBILE. Other node types
// are invalid.
// `delegate` must not be null and must outlive this class.
PermanentFolderOrderingTracker(bookmarks::BookmarkModel* model,
bookmarks::BookmarkNode::Type tracked_type,
Delegate* delegate);
~PermanentFolderOrderingTracker() override;
PermanentFolderOrderingTracker(const PermanentFolderOrderingTracker&) =
delete;
PermanentFolderOrderingTracker& operator=(
const PermanentFolderOrderingTracker&) = delete;
// This function must be invoked, and ordering will only be tracked
// afterwards.
void Init(std::vector<int64_t> in_order_node_ids);
// Returns underlying permanent nodes.
// If the bookmark model is not loaded, it returns empty.
std::vector<const bookmarks::BookmarkNode*> GetUnderlyingPermanentNodes()
const;
// Returns default parent node for new nodes created as a child of
// `tracked_type_`.
// This will return the account node if one exists, otherwise it returns the
// local/syncable node.
// `BookmarkModel` must be loaded.
const bookmarks::BookmarkNode* GetDefaultParentForNewNodes() const;
// Returns index of `node`.
// `node` must be a direct child of one of the tracked permanent
// nodes in `this`.
size_t GetIndexOf(const bookmarks::BookmarkNode* node) const;
// Returns node at `index`.
const bookmarks::BookmarkNode* GetNodeAtIndex(size_t index) const;
// Returns children count for nodes tracked in this tracker.
size_t GetChildrenCount() const;
// Moves node from an arbitrary parent to become a child of the permanent
// folder tracked by this at `index`.
// If `node` is local or account bookmark, it will remain local/account after
// the move.
// Note that if node is already being tracked by this, there are two possible
// target indices (index) that result in a no-op. This is similar to what
// `BookmarkModel::Move()` does
// Returns the new index or `std::nullopt` if `MoveToIndex` is no-op.
std::optional<size_t> MoveToIndex(const bookmarks::BookmarkNode* node,
size_t index);
// Copies nodes in `elements` to be new child nodes of the permanent
// folder tracked by this starting at `index`.
// The new nodes will be child nodes of `GetDefaultParentForNewNodes()`.
void AddNodesAsCopiesOfNodeData(
const std::vector<bookmarks::BookmarkNodeData::Element>& elements,
size_t index);
// Helper function for optimization purposes, it returns the same value as
// `GetIndexOf()`.
// Returns `in_storage_index` if ordering is not tracked
// `ShouldTrackOrdering()` is false. Otherwise, returns `GetIndexOf()`
size_t GetIndexAcrossStorage(const bookmarks::BookmarkNode* node,
size_t in_storage_index) const;
// Returns true if `ordering` is not empty and has non-default order.
// Default order is all account child nodes then local child nodes.
bool IsNonDefaultOrderingTracked() const;
// bookmarks::BookmarkModelObserver:
void BookmarkModelLoaded(bool ids_reassigned) override;
void BookmarkNodeMoved(const bookmarks::BookmarkNode* old_parent,
size_t old_index,
const bookmarks::BookmarkNode* new_parent,
size_t new_index) override;
void BookmarkNodeAdded(const bookmarks::BookmarkNode* parent,
size_t index,
bool added_by_user) override;
void BookmarkNodeRemoved(const bookmarks::BookmarkNode* parent,
size_t old_index,
const bookmarks::BookmarkNode* node,
const std::set<GURL>& removed_urls,
const base::Location& location) override;
void OnWillRemoveAllUserBookmarks(const base::Location& location) override;
void BookmarkAllUserNodesRemoved(const std::set<GURL>& removed_urls,
const base::Location& location) override;
void BookmarkNodeChanged(const bookmarks::BookmarkNode* node) override {}
void BookmarkNodeFaviconChanged(
const bookmarks::BookmarkNode* node) override {}
void BookmarkNodeChildrenReordered(
const bookmarks::BookmarkNode* node) override;
private:
void NotifyTrackedOrderingChanged();
void SetTrackedPermanentNodes();
bool IsTrackedPermanentNode(const bookmarks::BookmarkNode* node) const;
void ResetOrderingToDefault();
bool ShouldTrackOrdering() const;
size_t GetExpectedOrderingSize() const;
std::vector<raw_ptr<const bookmarks::BookmarkNode>> GetDefaultOrderIfTracked()
const;
void RemoveBookmarkNodeIfTracked(const bookmarks::BookmarkNode* parent,
size_t old_index,
const bookmarks::BookmarkNode* node);
void AddBookmarkNodeIfTracked(const bookmarks::BookmarkNode* parent,
size_t index);
// This function counts bookmarks within the permanent bookmarks folder
// tracked by this. If account_storage is true, it counts bookmarks whose
// parent is account_node_. Otherwise, it counts bookmarks with a parent of
// local_or_syncable_node_, considering only children indexed from 0 to index
// - 1.
size_t GetInStorageBookmarkCountBeforeIndex(bool account_storage,
size_t index) const;
void ReconcileLoadedNodeIds();
const raw_ptr<bookmarks::BookmarkModel> model_;
const bookmarks::BookmarkNode::Type tracked_type_;
const raw_ptr<Delegate> delegate_;
bool initialized_ = false;
raw_ptr<const bookmarks::BookmarkNode> local_or_syncable_node_ = nullptr;
raw_ptr<const bookmarks::BookmarkNode> account_node_ = nullptr;
// Loaded node Ids from disk.
// Only needed while the bookmark model is being loaded.
std::vector<int64_t> loaded_node_ids_during_model_load_;
// Non-empty if both `local_or_syncable_node_` and
// `account_node_` have children (`ShouldTrackOrdering()` returns true).
// If ordering is tracked, the size of the vector is the sum of direct
// children of the `local_or_syncable_node_` and `account_node_` (as returned
// by `GetExpectedOrderingSize()`).
std::vector<raw_ptr<const bookmarks::BookmarkNode>> ordering_;
bool all_user_bookmarks_remove_in_progress_ = false;
base::ScopedObservation<bookmarks::BookmarkModel,
bookmarks::BookmarkModelObserver>
model_observation_{this};
};
#endif // CHROME_BROWSER_BOOKMARKS_PERMANENT_FOLDER_ORDERING_TRACKER_H_
|