blob: 374b94910061c569c3b80a338b2884448e04151f [file] [log] [blame]
[email protected]368f3a72011-03-08 17:17:481// Copyright (c) 2011 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]d8e41ed2008-09-11 15:22:325#include "chrome/browser/bookmarks/bookmark_model.h"
initial.commit09911bf2008-07-26 23:55:296
[email protected]4e425be42011-01-15 06:56:097#include <algorithm>
8#include <functional>
9
[email protected]2041cf342010-02-19 03:15:5910#include "base/callback.h"
[email protected]6892e2e2011-05-26 22:07:1711#include "base/command_line.h"
[email protected]3b63f8f42011-03-28 01:54:1512#include "base/memory/scoped_vector.h"
[email protected]fc3fc452009-02-10 03:25:4013#include "build/build_config.h"
[email protected]01eec882009-05-22 18:13:2814#include "chrome/browser/bookmarks/bookmark_index.h"
[email protected]68de8b72008-09-09 23:08:1315#include "chrome/browser/bookmarks/bookmark_storage.h"
[email protected]368f3a72011-03-08 17:17:4816#include "chrome/browser/bookmarks/bookmark_utils.h"
[email protected]e2f86d92009-02-25 00:22:0117#include "chrome/browser/browser_process.h"
[email protected]9c92d192009-12-02 08:03:1618#include "chrome/browser/history/history_notifications.h"
[email protected]8ecad5e2010-12-02 21:18:3319#include "chrome/browser/profiles/profile.h"
[email protected]6892e2e2011-05-26 22:07:1720#include "chrome/common/chrome_switches.h"
[email protected]f20d7332011-03-08 21:11:5321#include "content/common/notification_service.h"
[email protected]34ac8f32009-02-22 23:03:2722#include "grit/generated_resources.h"
[email protected]c051a1b2011-01-21 23:30:1723#include "ui/base/l10n/l10n_util.h"
24#include "ui/base/l10n/l10n_util_collator.h"
[email protected]08397d52011-02-05 01:53:3825#include "ui/gfx/codec/png_codec.h"
initial.commit09911bf2008-07-26 23:55:2926
[email protected]e1acf6f2008-10-27 20:43:3327using base::Time;
28
[email protected]b3c33d462009-06-26 22:29:2029namespace {
30
31// Helper to get a mutable bookmark node.
32static BookmarkNode* AsMutable(const BookmarkNode* node) {
33 return const_cast<BookmarkNode*>(node);
34}
35
[email protected]e1f76c62011-06-30 20:15:3936} // namespace
[email protected]b3c33d462009-06-26 22:29:2037
[email protected]d8e41ed2008-09-11 15:22:3238// BookmarkNode ---------------------------------------------------------------
initial.commit09911bf2008-07-26 23:55:2939
[email protected]ea2e5aa52009-05-20 18:01:2840BookmarkNode::BookmarkNode(const GURL& url)
[email protected]814a2d32009-04-30 23:09:0141 : url_(url) {
[email protected]ea2e5aa52009-05-20 18:01:2842 Initialize(0);
[email protected]814a2d32009-04-30 23:09:0143}
44
[email protected]367d7072009-07-13 23:27:1345BookmarkNode::BookmarkNode(int64 id, const GURL& url)
[email protected]2c685cc22009-08-28 00:17:4446 : url_(url) {
[email protected]ea2e5aa52009-05-20 18:01:2847 Initialize(id);
[email protected]814a2d32009-04-30 23:09:0148}
49
[email protected]a0835ac2010-09-13 19:40:0850BookmarkNode::~BookmarkNode() {
51}
52
[email protected]367d7072009-07-13 23:27:1353void BookmarkNode::Initialize(int64 id) {
[email protected]4d89f382009-05-12 06:56:4954 id_ = id;
[email protected]814a2d32009-04-30 23:09:0155 loaded_favicon_ = false;
56 favicon_load_handle_ = 0;
[email protected]bd1b96702009-07-08 21:54:1457 type_ = !url_.is_empty() ? URL : BOOKMARK_BAR;
[email protected]814a2d32009-04-30 23:09:0158 date_added_ = Time::Now();
initial.commit09911bf2008-07-26 23:55:2959}
60
[email protected]02d08e02010-10-08 17:50:4661void BookmarkNode::InvalidateFavicon() {
62 loaded_favicon_ = false;
63 favicon_ = SkBitmap();
64}
65
[email protected]6892e2e2011-05-26 22:07:1766bool BookmarkNode::IsVisible() const {
67 // The synced bookmark folder is invisible if the flag isn't set and there are
68 // no bookmarks under it.
69 if (type_ != BookmarkNode::SYNCED ||
70 CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]f23cc7472011-06-08 18:10:2771 switches::kEnableSyncedBookmarksFolder) || !empty()) {
[email protected]6892e2e2011-05-26 22:07:1772 return true;
73 }
74 return false;
75}
76
[email protected]d8e41ed2008-09-11 15:22:3277void BookmarkNode::Reset(const history::StarredEntry& entry) {
[email protected]bd1b96702009-07-08 21:54:1478 DCHECK(entry.type != history::StarredEntry::URL || entry.url == url_);
[email protected]f25387b2008-08-21 15:20:3379
initial.commit09911bf2008-07-26 23:55:2980 favicon_ = SkBitmap();
[email protected]bd1b96702009-07-08 21:54:1481 switch (entry.type) {
82 case history::StarredEntry::URL:
83 type_ = BookmarkNode::URL;
84 break;
[email protected]9fcaee72011-03-21 21:53:4485 case history::StarredEntry::USER_FOLDER:
[email protected]bd1b96702009-07-08 21:54:1486 type_ = BookmarkNode::FOLDER;
87 break;
88 case history::StarredEntry::BOOKMARK_BAR:
89 type_ = BookmarkNode::BOOKMARK_BAR;
90 break;
[email protected]6892e2e2011-05-26 22:07:1791 case history::StarredEntry::SYNCED:
92 type_ = BookmarkNode::SYNCED;
93 break;
[email protected]bd1b96702009-07-08 21:54:1494 case history::StarredEntry::OTHER:
95 type_ = BookmarkNode::OTHER_NODE;
96 break;
97 default:
98 NOTREACHED();
99 }
initial.commit09911bf2008-07-26 23:55:29100 date_added_ = entry.date_added;
[email protected]edb63cc2011-03-11 02:00:41101 date_folder_modified_ = entry.date_folder_modified;
[email protected]23db9f72011-03-11 19:43:24102 set_title(entry.title);
initial.commit09911bf2008-07-26 23:55:29103}
104
[email protected]d8e41ed2008-09-11 15:22:32105// BookmarkModel --------------------------------------------------------------
initial.commit09911bf2008-07-26 23:55:29106
[email protected]ef762642009-03-05 16:30:25107namespace {
108
109// Comparator used when sorting bookmarks. Folders are sorted first, then
[email protected]2c685cc22009-08-28 00:17:44110// bookmarks.
[email protected]b3c33d462009-06-26 22:29:20111class SortComparator : public std::binary_function<const BookmarkNode*,
112 const BookmarkNode*,
[email protected]ef762642009-03-05 16:30:25113 bool> {
114 public:
[email protected]b5b2385a2009-08-18 05:12:29115 explicit SortComparator(icu::Collator* collator) : collator_(collator) { }
[email protected]ef762642009-03-05 16:30:25116
117 // Returns true if lhs preceeds rhs.
[email protected]b3c33d462009-06-26 22:29:20118 bool operator() (const BookmarkNode* n1, const BookmarkNode* n2) {
[email protected]037db002009-10-19 20:06:08119 if (n1->type() == n2->type()) {
[email protected]ef762642009-03-05 16:30:25120 // Types are the same, compare the names.
121 if (!collator_)
[email protected]440b37b22010-08-30 05:31:40122 return n1->GetTitle() < n2->GetTitle();
[email protected]3abebda2011-01-07 20:17:15123 return l10n_util::CompareString16WithCollator(
124 collator_, n1->GetTitle(), n2->GetTitle()) == UCOL_LESS;
[email protected]ef762642009-03-05 16:30:25125 }
126 // Types differ, sort such that folders come first.
127 return n1->is_folder();
128 }
129
130 private:
[email protected]b5b2385a2009-08-18 05:12:29131 icu::Collator* collator_;
[email protected]ef762642009-03-05 16:30:25132};
133
134} // namespace
135
[email protected]d8e41ed2008-09-11 15:22:32136BookmarkModel::BookmarkModel(Profile* profile)
initial.commit09911bf2008-07-26 23:55:29137 : profile_(profile),
138 loaded_(false),
[email protected]fc7c36a22009-05-28 20:23:33139 file_changed_(false),
[email protected]ea2e5aa52009-05-20 18:01:28140 root_(GURL()),
initial.commit09911bf2008-07-26 23:55:29141 bookmark_bar_node_(NULL),
[email protected]90ef13132008-08-27 03:27:46142 other_node_(NULL),
[email protected]6892e2e2011-05-26 22:07:17143 synced_node_(NULL),
[email protected]4d89f382009-05-12 06:56:49144 next_node_id_(1),
[email protected]b3e2fad02008-10-31 03:32:06145 observers_(ObserverList<BookmarkModelObserver>::NOTIFY_EXISTING_ONLY),
[email protected]4d89f382009-05-12 06:56:49146 loaded_signal_(TRUE, FALSE) {
[email protected]f25387b2008-08-21 15:20:33147 if (!profile_) {
148 // Profile is null during testing.
[email protected]01eec882009-05-22 18:13:28149 DoneLoading(CreateLoadDetails());
initial.commit09911bf2008-07-26 23:55:29150 }
initial.commit09911bf2008-07-26 23:55:29151}
152
[email protected]d8e41ed2008-09-11 15:22:32153BookmarkModel::~BookmarkModel() {
[email protected]d8e41ed2008-09-11 15:22:32154 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_,
[email protected]3de6fd342008-09-05 02:44:51155 BookmarkModelBeingDeleted(this));
156
[email protected]f25387b2008-08-21 15:20:33157 if (store_) {
158 // The store maintains a reference back to us. We need to tell it we're gone
159 // so that it doesn't try and invoke a method back on us again.
160 store_->BookmarkModelDeleted();
initial.commit09911bf2008-07-26 23:55:29161 }
162}
163
[email protected]d8e41ed2008-09-11 15:22:32164void BookmarkModel::Load() {
[email protected]90ef13132008-08-27 03:27:46165 if (store_.get()) {
166 // If the store is non-null, it means Load was already invoked. Load should
167 // only be invoked once.
168 NOTREACHED();
169 return;
170 }
171
172 // Listen for changes to favicons so that we can update the favicon of the
173 // node appropriately.
[email protected]40e0486b2009-05-22 01:47:27174 registrar_.Add(this, NotificationType::FAVICON_CHANGED,
175 Source<Profile>(profile_));
[email protected]90ef13132008-08-27 03:27:46176
177 // Load the bookmarks. BookmarkStorage notifies us when done.
178 store_ = new BookmarkStorage(profile_, this);
[email protected]01eec882009-05-22 18:13:28179 store_->LoadBookmarks(CreateLoadDetails());
[email protected]90ef13132008-08-27 03:27:46180}
181
[email protected]b3c33d462009-06-26 22:29:20182const BookmarkNode* BookmarkModel::GetParentForNewNodes() {
183 std::vector<const BookmarkNode*> nodes =
[email protected]9fcaee72011-03-21 21:53:44184 bookmark_utils::GetMostRecentlyModifiedFolders(this, 1);
initial.commit09911bf2008-07-26 23:55:29185 return nodes.empty() ? bookmark_bar_node_ : nodes[0];
186}
187
[email protected]b3c33d462009-06-26 22:29:20188void BookmarkModel::Remove(const BookmarkNode* parent, int index) {
189 if (!loaded_ || !IsValidIndex(parent, index, false) || is_root(parent)) {
[email protected]f25387b2008-08-21 15:20:33190 NOTREACHED();
191 return;
192 }
[email protected]b3c33d462009-06-26 22:29:20193 RemoveAndDeleteNode(AsMutable(parent->GetChild(index)));
[email protected]f25387b2008-08-21 15:20:33194}
195
[email protected]b3c33d462009-06-26 22:29:20196void BookmarkModel::Move(const BookmarkNode* node,
197 const BookmarkNode* new_parent,
[email protected]d8e41ed2008-09-11 15:22:32198 int index) {
[email protected]f25387b2008-08-21 15:20:33199 if (!loaded_ || !node || !IsValidIndex(new_parent, index, true) ||
[email protected]b3c33d462009-06-26 22:29:20200 is_root(new_parent) || is_permanent_node(node)) {
initial.commit09911bf2008-07-26 23:55:29201 NOTREACHED();
202 return;
203 }
204
205 if (new_parent->HasAncestor(node)) {
206 // Can't make an ancestor of the node be a child of the node.
207 NOTREACHED();
208 return;
209 }
210
[email protected]c6a7a3d2011-03-12 01:04:30211 SetDateFolderModified(new_parent, Time::Now());
initial.commit09911bf2008-07-26 23:55:29212
[email protected]2d48ee842011-03-08 23:27:29213 const BookmarkNode* old_parent = node->parent();
[email protected]368f3a72011-03-08 17:17:48214 int old_index = old_parent->GetIndexOf(node);
initial.commit09911bf2008-07-26 23:55:29215
216 if (old_parent == new_parent &&
217 (index == old_index || index == old_index + 1)) {
218 // Node is already in this position, nothing to do.
219 return;
220 }
221
222 if (old_parent == new_parent && index > old_index)
223 index--;
[email protected]b3c33d462009-06-26 22:29:20224 BookmarkNode* mutable_new_parent = AsMutable(new_parent);
[email protected]a0dd6a32011-03-18 17:31:37225 mutable_new_parent->Add(AsMutable(node), index);
initial.commit09911bf2008-07-26 23:55:29226
[email protected]f25387b2008-08-21 15:20:33227 if (store_.get())
228 store_->ScheduleSave();
229
[email protected]d8e41ed2008-09-11 15:22:32230 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_,
initial.commit09911bf2008-07-26 23:55:29231 BookmarkNodeMoved(this, old_parent, old_index,
232 new_parent, index));
233}
234
[email protected]4e187ef652010-03-11 05:21:35235void BookmarkModel::Copy(const BookmarkNode* node,
236 const BookmarkNode* new_parent,
237 int index) {
238 if (!loaded_ || !node || !IsValidIndex(new_parent, index, true) ||
239 is_root(new_parent) || is_permanent_node(node)) {
240 NOTREACHED();
241 return;
242 }
243
244 if (new_parent->HasAncestor(node)) {
245 // Can't make an ancestor of the node be a child of the node.
246 NOTREACHED();
247 return;
248 }
249
[email protected]c6a7a3d2011-03-12 01:04:30250 SetDateFolderModified(new_parent, Time::Now());
[email protected]14eb15af2010-11-20 01:03:26251 BookmarkNodeData drag_data_(node);
252 std::vector<BookmarkNodeData::Element> elements(drag_data_.elements);
[email protected]b1864502010-11-13 00:55:51253 // CloneBookmarkNode will use BookmarkModel methods to do the job, so we
[email protected]1a566fae2010-04-16 01:05:06254 // don't need to send notifications here.
[email protected]b1864502010-11-13 00:55:51255 bookmark_utils::CloneBookmarkNode(this, elements, new_parent, index);
[email protected]4e187ef652010-03-11 05:21:35256
257 if (store_.get())
258 store_->ScheduleSave();
[email protected]4e187ef652010-03-11 05:21:35259}
260
[email protected]9b488bda2011-03-15 14:42:27261const SkBitmap& BookmarkModel::GetFavicon(const BookmarkNode* node) {
[email protected]ea2e5aa52009-05-20 18:01:28262 DCHECK(node);
[email protected]b3c33d462009-06-26 22:29:20263 if (!node->is_favicon_loaded()) {
264 BookmarkNode* mutable_node = AsMutable(node);
265 mutable_node->set_favicon_loaded(true);
[email protected]abc2f262011-03-15 21:15:44266 LoadFavicon(mutable_node);
[email protected]ea2e5aa52009-05-20 18:01:28267 }
268 return node->favicon();
269}
270
[email protected]e64e9012010-01-11 23:10:55271void BookmarkModel::SetTitle(const BookmarkNode* node, const string16& title) {
[email protected]f25387b2008-08-21 15:20:33272 if (!node) {
273 NOTREACHED();
274 return;
275 }
[email protected]440b37b22010-08-30 05:31:40276 if (node->GetTitle() == title)
initial.commit09911bf2008-07-26 23:55:29277 return;
[email protected]f25387b2008-08-21 15:20:33278
[email protected]6892e2e2011-05-26 22:07:17279 if (is_permanent_node(node)) {
[email protected]baf4f922009-10-19 16:44:07280 NOTREACHED();
281 return;
282 }
283
[email protected]85d911c2009-05-19 03:59:42284 // The title index doesn't support changing the title, instead we remove then
285 // add it back.
[email protected]01eec882009-05-22 18:13:28286 index_->Remove(node);
[email protected]23db9f72011-03-11 19:43:24287 AsMutable(node)->set_title(title);
[email protected]01eec882009-05-22 18:13:28288 index_->Add(node);
[email protected]85d911c2009-05-19 03:59:42289
[email protected]f25387b2008-08-21 15:20:33290 if (store_.get())
291 store_->ScheduleSave();
292
[email protected]d8e41ed2008-09-11 15:22:32293 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_,
initial.commit09911bf2008-07-26 23:55:29294 BookmarkNodeChanged(this, node));
295}
296
[email protected]e5486602010-02-09 21:27:55297void BookmarkModel::SetURL(const BookmarkNode* node, const GURL& url) {
298 if (!node) {
299 NOTREACHED();
300 return;
301 }
302
303 // We cannot change the URL of a folder.
304 if (node->is_folder()) {
305 NOTREACHED();
306 return;
307 }
308
309 if (url == node->GetURL())
310 return;
311
312 AsMutable(node)->InvalidateFavicon();
[email protected]abc2f262011-03-15 21:15:44313 CancelPendingFaviconLoadRequests(AsMutable(node));
[email protected]e5486602010-02-09 21:27:55314
315 {
[email protected]20305ec2011-01-21 04:55:52316 base::AutoLock url_lock(url_lock_);
[email protected]e5486602010-02-09 21:27:55317 NodesOrderedByURLSet::iterator i = nodes_ordered_by_url_set_.find(
318 AsMutable(node));
319 DCHECK(i != nodes_ordered_by_url_set_.end());
320 // i points to the first node with the URL, advance until we find the
321 // node we're removing.
322 while (*i != node)
323 ++i;
324 nodes_ordered_by_url_set_.erase(i);
325
326 AsMutable(node)->SetURL(url);
327 nodes_ordered_by_url_set_.insert(AsMutable(node));
328 }
329
330 if (store_.get())
331 store_->ScheduleSave();
332
333 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_,
334 BookmarkNodeChanged(this, node));
335}
336
[email protected]02d08e02010-10-08 17:50:46337bool BookmarkModel::IsLoaded() {
338 return loaded_;
339}
340
[email protected]848cd05e2008-09-19 18:33:48341void BookmarkModel::GetNodesByURL(const GURL& url,
[email protected]b3c33d462009-06-26 22:29:20342 std::vector<const BookmarkNode*>* nodes) {
[email protected]20305ec2011-01-21 04:55:52343 base::AutoLock url_lock(url_lock_);
[email protected]ea2e5aa52009-05-20 18:01:28344 BookmarkNode tmp_node(url);
initial.commit09911bf2008-07-26 23:55:29345 NodesOrderedByURLSet::iterator i = nodes_ordered_by_url_set_.find(&tmp_node);
[email protected]848cd05e2008-09-19 18:33:48346 while (i != nodes_ordered_by_url_set_.end() && (*i)->GetURL() == url) {
347 nodes->push_back(*i);
348 ++i;
349 }
350}
351
[email protected]b3c33d462009-06-26 22:29:20352const BookmarkNode* BookmarkModel::GetMostRecentlyAddedNodeForURL(
353 const GURL& url) {
354 std::vector<const BookmarkNode*> nodes;
[email protected]848cd05e2008-09-19 18:33:48355 GetNodesByURL(url, &nodes);
356 if (nodes.empty())
357 return NULL;
358
[email protected]9333f182008-12-09 17:34:17359 std::sort(nodes.begin(), nodes.end(), &bookmark_utils::MoreRecentlyAdded);
[email protected]848cd05e2008-09-19 18:33:48360 return nodes.front();
initial.commit09911bf2008-07-26 23:55:29361}
362
[email protected]d8e41ed2008-09-11 15:22:32363void BookmarkModel::GetBookmarks(std::vector<GURL>* urls) {
[email protected]20305ec2011-01-21 04:55:52364 base::AutoLock url_lock(url_lock_);
[email protected]848cd05e2008-09-19 18:33:48365 const GURL* last_url = NULL;
[email protected]90ef13132008-08-27 03:27:46366 for (NodesOrderedByURLSet::iterator i = nodes_ordered_by_url_set_.begin();
367 i != nodes_ordered_by_url_set_.end(); ++i) {
[email protected]b3c33d462009-06-26 22:29:20368 const GURL* url = &((*i)->GetURL());
[email protected]848cd05e2008-09-19 18:33:48369 // Only add unique URLs.
370 if (!last_url || *url != *last_url)
371 urls->push_back(*url);
372 last_url = url;
[email protected]90ef13132008-08-27 03:27:46373 }
374}
375
[email protected]4478c652010-08-27 00:08:21376bool BookmarkModel::HasBookmarks() {
[email protected]20305ec2011-01-21 04:55:52377 base::AutoLock url_lock(url_lock_);
[email protected]4478c652010-08-27 00:08:21378 return !nodes_ordered_by_url_set_.empty();
379}
380
[email protected]848cd05e2008-09-19 18:33:48381bool BookmarkModel::IsBookmarked(const GURL& url) {
[email protected]20305ec2011-01-21 04:55:52382 base::AutoLock url_lock(url_lock_);
[email protected]dddc1b42008-10-09 20:56:59383 return IsBookmarkedNoLock(url);
[email protected]848cd05e2008-09-19 18:33:48384}
385
[email protected]367d7072009-07-13 23:27:13386const BookmarkNode* BookmarkModel::GetNodeByID(int64 id) {
initial.commit09911bf2008-07-26 23:55:29387 // TODO(sky): TreeNode needs a method that visits all nodes using a predicate.
[email protected]f25387b2008-08-21 15:20:33388 return GetNodeByID(&root_, id);
initial.commit09911bf2008-07-26 23:55:29389}
390
[email protected]39703292011-03-18 17:03:40391const BookmarkNode* BookmarkModel::AddFolder(const BookmarkNode* parent,
392 int index,
393 const string16& title) {
[email protected]f25387b2008-08-21 15:20:33394 if (!loaded_ || parent == &root_ || !IsValidIndex(parent, index, true)) {
initial.commit09911bf2008-07-26 23:55:29395 // Can't add to the root.
396 NOTREACHED();
397 return NULL;
398 }
399
[email protected]ea2e5aa52009-05-20 18:01:28400 BookmarkNode* new_node = new BookmarkNode(generate_next_node_id(),
[email protected]4d89f382009-05-12 06:56:49401 GURL());
[email protected]edb63cc2011-03-11 02:00:41402 new_node->set_date_folder_modified(Time::Now());
[email protected]23db9f72011-03-11 19:43:24403 new_node->set_title(title);
[email protected]037db002009-10-19 20:06:08404 new_node->set_type(BookmarkNode::FOLDER);
initial.commit09911bf2008-07-26 23:55:29405
[email protected]b3c33d462009-06-26 22:29:20406 return AddNode(AsMutable(parent), index, new_node, false);
initial.commit09911bf2008-07-26 23:55:29407}
408
[email protected]e64e9012010-01-11 23:10:55409const BookmarkNode* BookmarkModel::AddURL(const BookmarkNode* parent,
410 int index,
411 const string16& title,
412 const GURL& url) {
initial.commit09911bf2008-07-26 23:55:29413 return AddURLWithCreationTime(parent, index, title, url, Time::Now());
414}
415
[email protected]e64e9012010-01-11 23:10:55416const BookmarkNode* BookmarkModel::AddURLWithCreationTime(
417 const BookmarkNode* parent,
418 int index,
419 const string16& title,
420 const GURL& url,
421 const Time& creation_time) {
[email protected]b3c33d462009-06-26 22:29:20422 if (!loaded_ || !url.is_valid() || is_root(parent) ||
[email protected]f25387b2008-08-21 15:20:33423 !IsValidIndex(parent, index, true)) {
initial.commit09911bf2008-07-26 23:55:29424 NOTREACHED();
425 return NULL;
426 }
initial.commit09911bf2008-07-26 23:55:29427
[email protected]848cd05e2008-09-19 18:33:48428 bool was_bookmarked = IsBookmarked(url);
initial.commit09911bf2008-07-26 23:55:29429
[email protected]c6a7a3d2011-03-12 01:04:30430 SetDateFolderModified(parent, creation_time);
initial.commit09911bf2008-07-26 23:55:29431
[email protected]ea2e5aa52009-05-20 18:01:28432 BookmarkNode* new_node = new BookmarkNode(generate_next_node_id(), url);
[email protected]23db9f72011-03-11 19:43:24433 new_node->set_title(title);
[email protected]b3c33d462009-06-26 22:29:20434 new_node->set_date_added(creation_time);
[email protected]037db002009-10-19 20:06:08435 new_node->set_type(BookmarkNode::URL);
initial.commit09911bf2008-07-26 23:55:29436
[email protected]776e7492008-10-23 16:47:41437 {
438 // Only hold the lock for the duration of the insert.
[email protected]20305ec2011-01-21 04:55:52439 base::AutoLock url_lock(url_lock_);
[email protected]776e7492008-10-23 16:47:41440 nodes_ordered_by_url_set_.insert(new_node);
441 }
initial.commit09911bf2008-07-26 23:55:29442
[email protected]b3c33d462009-06-26 22:29:20443 return AddNode(AsMutable(parent), index, new_node, was_bookmarked);
initial.commit09911bf2008-07-26 23:55:29444}
445
[email protected]b3c33d462009-06-26 22:29:20446void BookmarkModel::SortChildren(const BookmarkNode* parent) {
447 if (!parent || !parent->is_folder() || is_root(parent) ||
[email protected]9c1a75a2011-03-10 02:38:12448 parent->child_count() <= 1) {
[email protected]e2f86d92009-02-25 00:22:01449 return;
450 }
451
[email protected]ef762642009-03-05 16:30:25452 UErrorCode error = U_ZERO_ERROR;
[email protected]b5b2385a2009-08-18 05:12:29453 scoped_ptr<icu::Collator> collator(
454 icu::Collator::createInstance(
455 icu::Locale(g_browser_process->GetApplicationLocale().c_str()),
[email protected]ef762642009-03-05 16:30:25456 error));
457 if (U_FAILURE(error))
458 collator.reset(NULL);
[email protected]b3c33d462009-06-26 22:29:20459 BookmarkNode* mutable_parent = AsMutable(parent);
460 std::sort(mutable_parent->children().begin(),
461 mutable_parent->children().end(),
[email protected]ef762642009-03-05 16:30:25462 SortComparator(collator.get()));
[email protected]e2f86d92009-02-25 00:22:01463
[email protected]997a0362009-03-12 03:10:51464 if (store_.get())
465 store_->ScheduleSave();
466
[email protected]e2f86d92009-02-25 00:22:01467 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_,
468 BookmarkNodeChildrenReordered(this, parent));
469}
470
[email protected]e64e9012010-01-11 23:10:55471void BookmarkModel::SetURLStarred(const GURL& url,
472 const string16& title,
473 bool is_starred) {
[email protected]b3c33d462009-06-26 22:29:20474 std::vector<const BookmarkNode*> bookmarks;
[email protected]848cd05e2008-09-19 18:33:48475 GetNodesByURL(url, &bookmarks);
476 bool bookmarks_exist = !bookmarks.empty();
477 if (is_starred == bookmarks_exist)
478 return; // Nothing to do, state already matches.
479
480 if (is_starred) {
481 // Create a bookmark.
[email protected]b3c33d462009-06-26 22:29:20482 const BookmarkNode* parent = GetParentForNewNodes();
[email protected]9c1a75a2011-03-10 02:38:12483 AddURL(parent, parent->child_count(), title, url);
[email protected]848cd05e2008-09-19 18:33:48484 } else {
485 // Remove all the bookmarks.
486 for (size_t i = 0; i < bookmarks.size(); ++i) {
[email protected]b3c33d462009-06-26 22:29:20487 const BookmarkNode* node = bookmarks[i];
[email protected]3417cb72011-03-11 17:38:09488 int index = node->parent()->GetIndexOf(node);
489 if (index > -1)
490 Remove(node->parent(), index);
[email protected]848cd05e2008-09-19 18:33:48491 }
initial.commit09911bf2008-07-26 23:55:29492 }
493}
494
[email protected]c6a7a3d2011-03-12 01:04:30495void BookmarkModel::SetDateFolderModified(const BookmarkNode* parent,
496 const Time time) {
[email protected]eea8fd5532009-12-16 00:08:10497 DCHECK(parent);
[email protected]edb63cc2011-03-11 02:00:41498 AsMutable(parent)->set_date_folder_modified(time);
[email protected]eea8fd5532009-12-16 00:08:10499
500 if (store_.get())
501 store_->ScheduleSave();
502}
503
[email protected]c6a7a3d2011-03-12 01:04:30504void BookmarkModel::ResetDateFolderModified(const BookmarkNode* node) {
505 SetDateFolderModified(node, Time());
initial.commit09911bf2008-07-26 23:55:29506}
507
[email protected]e64e9012010-01-11 23:10:55508void BookmarkModel::GetBookmarksWithTitlesMatching(
509 const string16& text,
510 size_t max_count,
511 std::vector<bookmark_utils::TitleMatch>* matches) {
[email protected]01eec882009-05-22 18:13:28512 if (!loaded_)
513 return;
514
[email protected]d0195a62010-08-22 04:40:20515 index_->GetBookmarksWithTitlesMatching(text, max_count, matches);
[email protected]85d911c2009-05-19 03:59:42516}
517
[email protected]9876bb1c2008-12-16 20:42:25518void BookmarkModel::ClearStore() {
[email protected]40e0486b2009-05-22 01:47:27519 registrar_.RemoveAll();
[email protected]9876bb1c2008-12-16 20:42:25520 store_ = NULL;
521}
522
[email protected]dddc1b42008-10-09 20:56:59523bool BookmarkModel::IsBookmarkedNoLock(const GURL& url) {
[email protected]ea2e5aa52009-05-20 18:01:28524 BookmarkNode tmp_node(url);
[email protected]dddc1b42008-10-09 20:56:59525 return (nodes_ordered_by_url_set_.find(&tmp_node) !=
526 nodes_ordered_by_url_set_.end());
527}
528
[email protected]abc2f262011-03-15 21:15:44529void BookmarkModel::FaviconLoaded(const BookmarkNode* node) {
initial.commit09911bf2008-07-26 23:55:29530 // Send out notification to the observer.
[email protected]d8e41ed2008-09-11 15:22:32531 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_,
[email protected]f12de8302011-05-23 16:12:30532 BookmarkNodeFaviconChanged(this, node));
initial.commit09911bf2008-07-26 23:55:29533}
534
[email protected]d8e41ed2008-09-11 15:22:32535void BookmarkModel::RemoveNode(BookmarkNode* node,
536 std::set<GURL>* removed_urls) {
[email protected]b3c33d462009-06-26 22:29:20537 if (!loaded_ || !node || is_permanent_node(node)) {
[email protected]f25387b2008-08-21 15:20:33538 NOTREACHED();
539 return;
540 }
541
[email protected]0890e60e2011-06-27 14:55:21542 if (node->is_url()) {
[email protected]90ef13132008-08-27 03:27:46543 // NOTE: this is called in such a way that url_lock_ is already held. As
544 // such, this doesn't explicitly grab the lock.
initial.commit09911bf2008-07-26 23:55:29545 NodesOrderedByURLSet::iterator i = nodes_ordered_by_url_set_.find(node);
546 DCHECK(i != nodes_ordered_by_url_set_.end());
[email protected]848cd05e2008-09-19 18:33:48547 // i points to the first node with the URL, advance until we find the
548 // node we're removing.
549 while (*i != node)
550 ++i;
initial.commit09911bf2008-07-26 23:55:29551 nodes_ordered_by_url_set_.erase(i);
[email protected]f25387b2008-08-21 15:20:33552 removed_urls->insert(node->GetURL());
[email protected]85d911c2009-05-19 03:59:42553
[email protected]01eec882009-05-22 18:13:28554 index_->Remove(node);
initial.commit09911bf2008-07-26 23:55:29555 }
556
[email protected]abc2f262011-03-15 21:15:44557 CancelPendingFaviconLoadRequests(node);
initial.commit09911bf2008-07-26 23:55:29558
559 // Recurse through children.
[email protected]9c1a75a2011-03-10 02:38:12560 for (int i = node->child_count() - 1; i >= 0; --i)
[email protected]f25387b2008-08-21 15:20:33561 RemoveNode(node->GetChild(i), removed_urls);
initial.commit09911bf2008-07-26 23:55:29562}
563
[email protected]01eec882009-05-22 18:13:28564void BookmarkModel::DoneLoading(
[email protected]9c92d192009-12-02 08:03:16565 BookmarkLoadDetails* details_delete_me) {
[email protected]01eec882009-05-22 18:13:28566 DCHECK(details_delete_me);
[email protected]9c92d192009-12-02 08:03:16567 scoped_ptr<BookmarkLoadDetails> details(details_delete_me);
[email protected]01eec882009-05-22 18:13:28568 if (loaded_) {
569 // We should only ever be loaded once.
570 NOTREACHED();
571 return;
572 }
573
[email protected]01eec882009-05-22 18:13:28574 next_node_id_ = details->max_id();
[email protected]fc7c36a22009-05-28 20:23:33575 if (details->computed_checksum() != details->stored_checksum())
576 SetFileChanged();
[email protected]367d7072009-07-13 23:27:13577 if (details->computed_checksum() != details->stored_checksum() ||
578 details->ids_reassigned()) {
579 // If bookmarks file changed externally, the IDs may have changed
580 // externally. In that case, the decoder may have reassigned IDs to make
581 // them unique. So when the file has changed externally, we should save the
582 // bookmarks file to persist new IDs.
583 if (store_.get())
584 store_->ScheduleSave();
585 }
[email protected]d22d8732010-05-04 19:24:42586 bookmark_bar_node_ = details->release_bb_node();
587 other_node_ = details->release_other_folder_node();
[email protected]6892e2e2011-05-26 22:07:17588 synced_node_ = details->release_synced_folder_node();
[email protected]d22d8732010-05-04 19:24:42589 index_.reset(details->release_index());
[email protected]01eec882009-05-22 18:13:28590
591 // WARNING: order is important here, various places assume bookmark bar then
592 // other node.
[email protected]a0dd6a32011-03-18 17:31:37593 root_.Add(bookmark_bar_node_, 0);
594 root_.Add(other_node_, 1);
[email protected]6892e2e2011-05-26 22:07:17595 root_.Add(synced_node_, 2);
[email protected]6c1164042009-05-08 14:41:08596
[email protected]90ef13132008-08-27 03:27:46597 {
[email protected]20305ec2011-01-21 04:55:52598 base::AutoLock url_lock(url_lock_);
[email protected]90ef13132008-08-27 03:27:46599 // Update nodes_ordered_by_url_set_ from the nodes.
600 PopulateNodesByURL(&root_);
601 }
[email protected]f25387b2008-08-21 15:20:33602
initial.commit09911bf2008-07-26 23:55:29603 loaded_ = true;
604
[email protected]cbcd6412009-03-09 22:31:39605 loaded_signal_.Signal();
[email protected]90ef13132008-08-27 03:27:46606
[email protected]f25387b2008-08-21 15:20:33607 // Notify our direct observers.
[email protected]d8e41ed2008-09-11 15:22:32608 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_, Loaded(this));
initial.commit09911bf2008-07-26 23:55:29609
[email protected]f25387b2008-08-21 15:20:33610 // And generic notification.
initial.commit09911bf2008-07-26 23:55:29611 NotificationService::current()->Notify(
[email protected]bfd04a62009-02-01 18:16:56612 NotificationType::BOOKMARK_MODEL_LOADED,
initial.commit09911bf2008-07-26 23:55:29613 Source<Profile>(profile_),
614 NotificationService::NoDetails());
615}
616
[email protected]d8e41ed2008-09-11 15:22:32617void BookmarkModel::RemoveAndDeleteNode(BookmarkNode* delete_me) {
618 scoped_ptr<BookmarkNode> node(delete_me);
initial.commit09911bf2008-07-26 23:55:29619
[email protected]2d48ee842011-03-08 23:27:29620 BookmarkNode* parent = AsMutable(node->parent());
initial.commit09911bf2008-07-26 23:55:29621 DCHECK(parent);
[email protected]368f3a72011-03-08 17:17:48622 int index = parent->GetIndexOf(node.get());
[email protected]18cc5ff2011-03-22 01:05:23623 parent->Remove(node.get());
[email protected]f25387b2008-08-21 15:20:33624 history::URLsStarredDetails details(false);
[email protected]90ef13132008-08-27 03:27:46625 {
[email protected]20305ec2011-01-21 04:55:52626 base::AutoLock url_lock(url_lock_);
[email protected]90ef13132008-08-27 03:27:46627 RemoveNode(node.get(), &details.changed_urls);
[email protected]848cd05e2008-09-19 18:33:48628
629 // RemoveNode adds an entry to changed_urls for each node of type URL. As we
630 // allow duplicates we need to remove any entries that are still bookmarked.
631 for (std::set<GURL>::iterator i = details.changed_urls.begin();
[email protected]2c685cc22009-08-28 00:17:44632 i != details.changed_urls.end(); ) {
[email protected]fc3fc452009-02-10 03:25:40633 if (IsBookmarkedNoLock(*i)) {
634 // When we erase the iterator pointing at the erasee is
635 // invalidated, so using i++ here within the "erase" call is
636 // important as it advances the iterator before passing the
637 // old value through to erase.
638 details.changed_urls.erase(i++);
639 } else {
[email protected]848cd05e2008-09-19 18:33:48640 ++i;
[email protected]fc3fc452009-02-10 03:25:40641 }
[email protected]848cd05e2008-09-19 18:33:48642 }
[email protected]90ef13132008-08-27 03:27:46643 }
initial.commit09911bf2008-07-26 23:55:29644
[email protected]f25387b2008-08-21 15:20:33645 if (store_.get())
646 store_->ScheduleSave();
647
[email protected]d8e41ed2008-09-11 15:22:32648 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_,
[email protected]776e7492008-10-23 16:47:41649 BookmarkNodeRemoved(this, parent, index, node.get()));
[email protected]f25387b2008-08-21 15:20:33650
[email protected]848cd05e2008-09-19 18:33:48651 if (details.changed_urls.empty()) {
652 // No point in sending out notification if the starred state didn't change.
653 return;
654 }
655
[email protected]90ef13132008-08-27 03:27:46656 if (profile_) {
657 HistoryService* history =
658 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
659 if (history)
660 history->URLsNoLongerBookmarked(details.changed_urls);
661 }
662
[email protected]bfd04a62009-02-01 18:16:56663 NotificationService::current()->Notify(
664 NotificationType::URLS_STARRED,
[email protected]f25387b2008-08-21 15:20:33665 Source<Profile>(profile_),
666 Details<history::URLsStarredDetails>(&details));
initial.commit09911bf2008-07-26 23:55:29667}
668
[email protected]cb6cf792010-01-28 00:04:56669void BookmarkModel::BeginImportMode() {
670 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_,
671 BookmarkImportBeginning(this));
672}
673
674void BookmarkModel::EndImportMode() {
675 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_,
676 BookmarkImportEnding(this));
677}
678
[email protected]d8e41ed2008-09-11 15:22:32679BookmarkNode* BookmarkModel::AddNode(BookmarkNode* parent,
680 int index,
[email protected]848cd05e2008-09-19 18:33:48681 BookmarkNode* node,
682 bool was_bookmarked) {
[email protected]a0dd6a32011-03-18 17:31:37683 parent->Add(node, index);
initial.commit09911bf2008-07-26 23:55:29684
[email protected]f25387b2008-08-21 15:20:33685 if (store_.get())
686 store_->ScheduleSave();
687
[email protected]d8e41ed2008-09-11 15:22:32688 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_,
initial.commit09911bf2008-07-26 23:55:29689 BookmarkNodeAdded(this, parent, index));
[email protected]f25387b2008-08-21 15:20:33690
[email protected]01eec882009-05-22 18:13:28691 index_->Add(node);
[email protected]85d911c2009-05-19 03:59:42692
[email protected]0890e60e2011-06-27 14:55:21693 if (node->is_url() && !was_bookmarked) {
[email protected]f25387b2008-08-21 15:20:33694 history::URLsStarredDetails details(true);
695 details.changed_urls.insert(node->GetURL());
[email protected]bfd04a62009-02-01 18:16:56696 NotificationService::current()->Notify(
697 NotificationType::URLS_STARRED,
[email protected]f25387b2008-08-21 15:20:33698 Source<Profile>(profile_),
699 Details<history::URLsStarredDetails>(&details));
700 }
initial.commit09911bf2008-07-26 23:55:29701 return node;
702}
703
[email protected]d8e41ed2008-09-11 15:22:32704void BookmarkModel::BlockTillLoaded() {
[email protected]cbcd6412009-03-09 22:31:39705 loaded_signal_.Wait();
[email protected]90ef13132008-08-27 03:27:46706}
707
[email protected]b3c33d462009-06-26 22:29:20708const BookmarkNode* BookmarkModel::GetNodeByID(const BookmarkNode* node,
[email protected]367d7072009-07-13 23:27:13709 int64 id) {
[email protected]f25387b2008-08-21 15:20:33710 if (node->id() == id)
initial.commit09911bf2008-07-26 23:55:29711 return node;
[email protected]f25387b2008-08-21 15:20:33712
[email protected]9c1a75a2011-03-10 02:38:12713 for (int i = 0, child_count = node->child_count(); i < child_count; ++i) {
[email protected]b3c33d462009-06-26 22:29:20714 const BookmarkNode* result = GetNodeByID(node->GetChild(i), id);
initial.commit09911bf2008-07-26 23:55:29715 if (result)
716 return result;
717 }
718 return NULL;
719}
720
[email protected]b3c33d462009-06-26 22:29:20721bool BookmarkModel::IsValidIndex(const BookmarkNode* parent,
[email protected]d8e41ed2008-09-11 15:22:32722 int index,
723 bool allow_end) {
[email protected]776e7492008-10-23 16:47:41724 return (parent && parent->is_folder() &&
[email protected]9c1a75a2011-03-10 02:38:12725 (index >= 0 && (index < parent->child_count() ||
726 (allow_end && index == parent->child_count()))));
[email protected]bd1b96702009-07-08 21:54:14727}
[email protected]f25387b2008-08-21 15:20:33728
[email protected]e1f76c62011-06-30 20:15:39729BookmarkNode* BookmarkModel::CreatePermanentNode(BookmarkNode::Type type) {
730 DCHECK(type == BookmarkNode::BOOKMARK_BAR ||
731 type == BookmarkNode::OTHER_NODE ||
732 type == BookmarkNode::SYNCED);
[email protected]ea2e5aa52009-05-20 18:01:28733 BookmarkNode* node = new BookmarkNode(generate_next_node_id(), GURL());
[email protected]e1f76c62011-06-30 20:15:39734 node->set_type(type);
735 if (type == BookmarkNode::BOOKMARK_BAR) {
[email protected]23db9f72011-03-11 19:43:24736 node->set_title(l10n_util::GetStringUTF16(IDS_BOOMARK_BAR_FOLDER_NAME));
[email protected]e1f76c62011-06-30 20:15:39737 } else if (type == BookmarkNode::OTHER_NODE) {
[email protected]23db9f72011-03-11 19:43:24738 node->set_title(
[email protected]7caca8a22010-08-21 18:25:31739 l10n_util::GetStringUTF16(IDS_BOOMARK_BAR_OTHER_FOLDER_NAME));
[email protected]e1f76c62011-06-30 20:15:39740 } else {
741 node->set_title(
742 l10n_util::GetStringUTF16(IDS_BOOMARK_BAR_SYNCED_FOLDER_NAME));
[email protected]7caca8a22010-08-21 18:25:31743 }
initial.commit09911bf2008-07-26 23:55:29744 return node;
745}
746
[email protected]abc2f262011-03-15 21:15:44747void BookmarkModel::OnFaviconDataAvailable(
[email protected]0189bc722009-08-28 21:56:48748 FaviconService::Handle handle,
[email protected]849ccee2011-03-16 17:05:30749 history::FaviconData favicon) {
[email protected]f16039d22011-03-16 18:54:05750 SkBitmap favicon_bitmap;
[email protected]d8e41ed2008-09-11 15:22:32751 BookmarkNode* node =
[email protected]4167c3a2008-08-21 18:12:20752 load_consumer_.GetClientData(
[email protected]0189bc722009-08-28 21:56:48753 profile_->GetFaviconService(Profile::EXPLICIT_ACCESS), handle);
[email protected]4167c3a2008-08-21 18:12:20754 DCHECK(node);
[email protected]b3c33d462009-06-26 22:29:20755 node->set_favicon_load_handle(0);
[email protected]849ccee2011-03-16 17:05:30756 if (favicon.is_valid() && gfx::PNGCodec::Decode(favicon.image_data->front(),
757 favicon.image_data->size(),
[email protected]f16039d22011-03-16 18:54:05758 &favicon_bitmap)) {
759 node->set_favicon(favicon_bitmap);
[email protected]abc2f262011-03-15 21:15:44760 FaviconLoaded(node);
initial.commit09911bf2008-07-26 23:55:29761 }
762}
763
[email protected]abc2f262011-03-15 21:15:44764void BookmarkModel::LoadFavicon(BookmarkNode* node) {
[email protected]0890e60e2011-06-27 14:55:21765 if (node->is_folder())
initial.commit09911bf2008-07-26 23:55:29766 return;
767
768 DCHECK(node->GetURL().is_valid());
[email protected]0189bc722009-08-28 21:56:48769 FaviconService* favicon_service =
770 profile_->GetFaviconService(Profile::EXPLICIT_ACCESS);
771 if (!favicon_service)
initial.commit09911bf2008-07-26 23:55:29772 return;
[email protected]0189bc722009-08-28 21:56:48773 FaviconService::Handle handle = favicon_service->GetFaviconForURL(
[email protected]849ccee2011-03-16 17:05:30774 node->GetURL(), history::FAVICON, &load_consumer_,
[email protected]abc2f262011-03-15 21:15:44775 NewCallback(this, &BookmarkModel::OnFaviconDataAvailable));
[email protected]0189bc722009-08-28 21:56:48776 load_consumer_.SetClientData(favicon_service, handle, node);
[email protected]b3c33d462009-06-26 22:29:20777 node->set_favicon_load_handle(handle);
initial.commit09911bf2008-07-26 23:55:29778}
779
[email protected]abc2f262011-03-15 21:15:44780void BookmarkModel::CancelPendingFaviconLoadRequests(BookmarkNode* node) {
[email protected]b3c33d462009-06-26 22:29:20781 if (node->favicon_load_handle()) {
[email protected]0189bc722009-08-28 21:56:48782 FaviconService* favicon_service =
783 profile_->GetFaviconService(Profile::EXPLICIT_ACCESS);
784 if (favicon_service)
785 favicon_service->CancelRequest(node->favicon_load_handle());
[email protected]b3c33d462009-06-26 22:29:20786 node->set_favicon_load_handle(0);
initial.commit09911bf2008-07-26 23:55:29787 }
788}
789
[email protected]d8e41ed2008-09-11 15:22:32790void BookmarkModel::Observe(NotificationType type,
791 const NotificationSource& source,
792 const NotificationDetails& details) {
[email protected]bfd04a62009-02-01 18:16:56793 switch (type.value) {
794 case NotificationType::FAVICON_CHANGED: {
initial.commit09911bf2008-07-26 23:55:29795 // Prevent the observers from getting confused for multiple favicon loads.
[email protected]a9458412011-03-15 19:41:09796 Details<history::FaviconChangeDetails> favicon_details(details);
initial.commit09911bf2008-07-26 23:55:29797 for (std::set<GURL>::const_iterator i = favicon_details->urls.begin();
798 i != favicon_details->urls.end(); ++i) {
[email protected]b3c33d462009-06-26 22:29:20799 std::vector<const BookmarkNode*> nodes;
[email protected]848cd05e2008-09-19 18:33:48800 GetNodesByURL(*i, &nodes);
801 for (size_t i = 0; i < nodes.size(); ++i) {
initial.commit09911bf2008-07-26 23:55:29802 // Got an updated favicon, for a URL, do a new request.
[email protected]b3c33d462009-06-26 22:29:20803 BookmarkNode* node = AsMutable(nodes[i]);
initial.commit09911bf2008-07-26 23:55:29804 node->InvalidateFavicon();
[email protected]abc2f262011-03-15 21:15:44805 CancelPendingFaviconLoadRequests(node);
[email protected]d8e41ed2008-09-11 15:22:32806 FOR_EACH_OBSERVER(BookmarkModelObserver, observers_,
[email protected]f12de8302011-05-23 16:12:30807 BookmarkNodeFaviconChanged(this, node));
initial.commit09911bf2008-07-26 23:55:29808 }
809 }
810 break;
811 }
812
813 default:
814 NOTREACHED();
815 break;
816 }
817}
[email protected]f25387b2008-08-21 15:20:33818
[email protected]d8e41ed2008-09-11 15:22:32819void BookmarkModel::PopulateNodesByURL(BookmarkNode* node) {
[email protected]90ef13132008-08-27 03:27:46820 // NOTE: this is called with url_lock_ already held. As such, this doesn't
821 // explicitly grab the lock.
[email protected]f25387b2008-08-21 15:20:33822 if (node->is_url())
823 nodes_ordered_by_url_set_.insert(node);
[email protected]9c1a75a2011-03-10 02:38:12824 for (int i = 0; i < node->child_count(); ++i)
[email protected]f25387b2008-08-21 15:20:33825 PopulateNodesByURL(node->GetChild(i));
826}
[email protected]4d89f382009-05-12 06:56:49827
[email protected]367d7072009-07-13 23:27:13828int64 BookmarkModel::generate_next_node_id() {
[email protected]4d89f382009-05-12 06:56:49829 return next_node_id_++;
830}
[email protected]01eec882009-05-22 18:13:28831
[email protected]fc7c36a22009-05-28 20:23:33832void BookmarkModel::SetFileChanged() {
833 file_changed_ = true;
[email protected]fc7c36a22009-05-28 20:23:33834}
835
[email protected]9c92d192009-12-02 08:03:16836BookmarkLoadDetails* BookmarkModel::CreateLoadDetails() {
[email protected]e1f76c62011-06-30 20:15:39837 BookmarkNode* bb_node = CreatePermanentNode(BookmarkNode::BOOKMARK_BAR);
838 BookmarkNode* other_node = CreatePermanentNode(BookmarkNode::OTHER_NODE);
839 BookmarkNode* synced_node = CreatePermanentNode(BookmarkNode::SYNCED);
840 return new BookmarkLoadDetails(bb_node, other_node, synced_node,
841 new BookmarkIndex(profile()), next_node_id_);
[email protected]01eec882009-05-22 18:13:28842}