OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/bookmarks/browser/bookmark_utils.h" | 5 #include "components/bookmarks/browser/bookmark_utils.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
11 #include "base/i18n/case_conversion.h" | 11 #include "base/i18n/case_conversion.h" |
12 #include "base/i18n/string_search.h" | 12 #include "base/i18n/string_search.h" |
13 #include "base/metrics/user_metrics_action.h" | 13 #include "base/metrics/user_metrics_action.h" |
14 #include "base/prefs/pref_service.h" | 14 #include "base/prefs/pref_service.h" |
15 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
16 #include "base/time/time.h" | 16 #include "base/time/time.h" |
| 17 #include "components/bookmarks/browser/bookmark_client.h" |
17 #include "components/bookmarks/browser/bookmark_model.h" | 18 #include "components/bookmarks/browser/bookmark_model.h" |
18 #include "components/bookmarks/browser/scoped_group_bookmark_actions.h" | 19 #include "components/bookmarks/browser/scoped_group_bookmark_actions.h" |
19 #include "components/bookmarks/common/bookmark_pref_names.h" | 20 #include "components/bookmarks/common/bookmark_pref_names.h" |
20 #include "components/pref_registry/pref_registry_syncable.h" | 21 #include "components/pref_registry/pref_registry_syncable.h" |
21 #include "components/query_parser/query_parser.h" | 22 #include "components/query_parser/query_parser.h" |
22 #include "net/base/net_util.h" | 23 #include "net/base/net_util.h" |
23 #include "ui/base/models/tree_node_iterator.h" | 24 #include "ui/base/models/tree_node_iterator.h" |
24 #include "url/gurl.h" | 25 #include "url/gurl.h" |
25 | 26 |
26 using base::Time; | 27 using base::Time; |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 BookmarkNodeData bookmark_data; | 197 BookmarkNodeData bookmark_data; |
197 if (!bookmark_data.ReadFromClipboard(ui::CLIPBOARD_TYPE_COPY_PASTE)) | 198 if (!bookmark_data.ReadFromClipboard(ui::CLIPBOARD_TYPE_COPY_PASTE)) |
198 return; | 199 return; |
199 | 200 |
200 if (index == -1) | 201 if (index == -1) |
201 index = parent->child_count(); | 202 index = parent->child_count(); |
202 bookmarks::ScopedGroupBookmarkActions group_paste(model); | 203 bookmarks::ScopedGroupBookmarkActions group_paste(model); |
203 CloneBookmarkNode(model, bookmark_data.elements, parent, index, true); | 204 CloneBookmarkNode(model, bookmark_data.elements, parent, index, true); |
204 } | 205 } |
205 | 206 |
206 bool CanPasteFromClipboard(const BookmarkNode* node) { | 207 bool CanPasteFromClipboard(BookmarkModel* model, const BookmarkNode* node) { |
207 if (!node) | 208 if (!node || !model->client()->CanBeEditedByUser(node)) |
208 return false; | 209 return false; |
209 return BookmarkNodeData::ClipboardContainsBookmarks(); | 210 return BookmarkNodeData::ClipboardContainsBookmarks(); |
210 } | 211 } |
211 | 212 |
212 std::vector<const BookmarkNode*> GetMostRecentlyModifiedFolders( | 213 std::vector<const BookmarkNode*> GetMostRecentlyModifiedUserFolders( |
213 BookmarkModel* model, | 214 BookmarkModel* model, |
214 size_t max_count) { | 215 size_t max_count) { |
215 std::vector<const BookmarkNode*> nodes; | 216 std::vector<const BookmarkNode*> nodes; |
216 ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node(), | 217 ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node(), |
217 PruneInvisibleFolders); | 218 PruneInvisibleFolders); |
218 | 219 |
219 while (iterator.has_next()) { | 220 while (iterator.has_next()) { |
220 const BookmarkNode* parent = iterator.Next(); | 221 const BookmarkNode* parent = iterator.Next(); |
| 222 if (!model->client()->CanBeEditedByUser(parent)) |
| 223 continue; |
221 if (parent->is_folder() && parent->date_folder_modified() > Time()) { | 224 if (parent->is_folder() && parent->date_folder_modified() > Time()) { |
222 if (max_count == 0) { | 225 if (max_count == 0) { |
223 nodes.push_back(parent); | 226 nodes.push_back(parent); |
224 } else { | 227 } else { |
225 std::vector<const BookmarkNode*>::iterator i = | 228 std::vector<const BookmarkNode*>::iterator i = |
226 std::upper_bound(nodes.begin(), nodes.end(), parent, | 229 std::upper_bound(nodes.begin(), nodes.end(), parent, |
227 &MoreRecentlyModified); | 230 &MoreRecentlyModified); |
228 if (nodes.size() < max_count || i != nodes.end()) { | 231 if (nodes.size() < max_count || i != nodes.end()) { |
229 nodes.insert(i, parent); | 232 nodes.insert(i, parent); |
230 while (nodes.size() > max_count) | 233 while (nodes.size() > max_count) |
231 nodes.pop_back(); | 234 nodes.pop_back(); |
232 } | 235 } |
233 } | 236 } |
234 } // else case, the root node, which we don't care about or imported nodes | 237 } // else case, the root node, which we don't care about or imported nodes |
235 // (which have a time of 0). | 238 // (which have a time of 0). |
236 } | 239 } |
237 | 240 |
238 if (nodes.size() < max_count) { | 241 if (nodes.size() < max_count) { |
239 // Add the permanent nodes if there is space. The permanent nodes are the | 242 // Add the permanent nodes if there is space. The permanent nodes are the |
240 // only children of the root_node. | 243 // only children of the root_node. |
241 const BookmarkNode* root_node = model->root_node(); | 244 const BookmarkNode* root_node = model->root_node(); |
242 | 245 |
243 for (int i = 0; i < root_node->child_count(); ++i) { | 246 for (int i = 0; i < root_node->child_count(); ++i) { |
244 const BookmarkNode* node = root_node->GetChild(i); | 247 const BookmarkNode* node = root_node->GetChild(i); |
245 if (node->IsVisible() && | 248 if (node->IsVisible() && model->client()->CanBeEditedByUser(node) && |
246 std::find(nodes.begin(), nodes.end(), node) == nodes.end()) { | 249 std::find(nodes.begin(), nodes.end(), node) == nodes.end()) { |
247 nodes.push_back(node); | 250 nodes.push_back(node); |
248 | 251 |
249 if (nodes.size() == max_count) | 252 if (nodes.size() == max_count) |
250 break; | 253 break; |
251 } | 254 } |
252 } | 255 } |
253 } | 256 } |
254 return nodes; | 257 return nodes; |
255 } | 258 } |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 if (!node) | 372 if (!node) |
370 continue; | 373 continue; |
371 const BookmarkNode* parent = node->parent(); | 374 const BookmarkNode* parent = node->parent(); |
372 model->Remove(parent, parent->GetIndexOf(node)); | 375 model->Remove(parent, parent->GetIndexOf(node)); |
373 } | 376 } |
374 } | 377 } |
375 | 378 |
376 void AddIfNotBookmarked(BookmarkModel* model, | 379 void AddIfNotBookmarked(BookmarkModel* model, |
377 const GURL& url, | 380 const GURL& url, |
378 const base::string16& title) { | 381 const base::string16& title) { |
379 std::vector<const BookmarkNode*> bookmarks; | 382 if (IsBookmarkedByUser(model, url)) |
380 model->GetNodesByURL(url, &bookmarks); | 383 return; // Nothing to do, a user bookmark with that url already exists. |
381 if (!bookmarks.empty()) | |
382 return; // Nothing to do, a bookmark with that url already exists. | |
383 | |
384 model->client()->RecordAction(base::UserMetricsAction("BookmarkAdded")); | 384 model->client()->RecordAction(base::UserMetricsAction("BookmarkAdded")); |
385 const BookmarkNode* parent = model->GetParentForNewNodes(); | 385 const BookmarkNode* parent = model->GetParentForNewNodes(); |
386 model->AddURL(parent, parent->child_count(), title, url); | 386 model->AddURL(parent, parent->child_count(), title, url); |
387 } | 387 } |
388 | 388 |
389 void RemoveAllBookmarks(BookmarkModel* model, const GURL& url) { | 389 void RemoveAllBookmarks(BookmarkModel* model, const GURL& url) { |
390 std::vector<const BookmarkNode*> bookmarks; | 390 std::vector<const BookmarkNode*> bookmarks; |
391 model->GetNodesByURL(url, &bookmarks); | 391 model->GetNodesByURL(url, &bookmarks); |
392 | 392 |
393 // Remove all the bookmarks. | 393 // Remove all the user bookmarks. |
394 for (size_t i = 0; i < bookmarks.size(); ++i) { | 394 for (size_t i = 0; i < bookmarks.size(); ++i) { |
395 const BookmarkNode* node = bookmarks[i]; | 395 const BookmarkNode* node = bookmarks[i]; |
396 int index = node->parent()->GetIndexOf(node); | 396 int index = node->parent()->GetIndexOf(node); |
397 if (index > -1) | 397 if (index > -1 && model->client()->CanBeEditedByUser(node)) |
398 model->Remove(node->parent(), index); | 398 model->Remove(node->parent(), index); |
399 } | 399 } |
400 } | 400 } |
401 | 401 |
402 base::string16 CleanUpUrlForMatching( | 402 base::string16 CleanUpUrlForMatching( |
403 const GURL& gurl, | 403 const GURL& gurl, |
404 const std::string& languages, | 404 const std::string& languages, |
405 base::OffsetAdjuster::Adjustments* adjustments) { | 405 base::OffsetAdjuster::Adjustments* adjustments) { |
406 base::OffsetAdjuster::Adjustments tmp_adjustments; | 406 base::OffsetAdjuster::Adjustments tmp_adjustments; |
407 return base::i18n::ToLower(net::FormatUrlWithAdjustments( | 407 return base::i18n::ToLower(net::FormatUrlWithAdjustments( |
408 GURL(TruncateUrl(gurl.spec())), languages, | 408 GURL(TruncateUrl(gurl.spec())), languages, |
409 net::kFormatUrlOmitUsernamePassword, | 409 net::kFormatUrlOmitUsernamePassword, |
410 net::UnescapeRule::SPACES | net::UnescapeRule::URL_SPECIAL_CHARS, | 410 net::UnescapeRule::SPACES | net::UnescapeRule::URL_SPECIAL_CHARS, |
411 NULL, NULL, adjustments ? adjustments : &tmp_adjustments)); | 411 NULL, NULL, adjustments ? adjustments : &tmp_adjustments)); |
412 } | 412 } |
413 | 413 |
414 base::string16 CleanUpTitleForMatching(const base::string16& title) { | 414 base::string16 CleanUpTitleForMatching(const base::string16& title) { |
415 return base::i18n::ToLower(title.substr(0u, kCleanedUpTitleMaxLength)); | 415 return base::i18n::ToLower(title.substr(0u, kCleanedUpTitleMaxLength)); |
416 } | 416 } |
417 | 417 |
| 418 bool CanAllBeEditedByUser(BookmarkClient* client, |
| 419 const std::vector<const BookmarkNode*>& list) { |
| 420 for (size_t i = 0; i < list.size(); ++i) { |
| 421 if (!client->CanBeEditedByUser(list[i])) |
| 422 return false; |
| 423 } |
| 424 return true; |
| 425 } |
| 426 |
| 427 bool IsBookmarkedByUser(BookmarkModel* model, const GURL& url) { |
| 428 std::vector<const BookmarkNode*> nodes; |
| 429 model->GetNodesByURL(url, &nodes); |
| 430 for (size_t i = 0; i < nodes.size(); ++i) { |
| 431 if (model->client()->CanBeEditedByUser(nodes[i])) |
| 432 return true; |
| 433 } |
| 434 return false; |
| 435 } |
| 436 |
418 } // namespace bookmark_utils | 437 } // namespace bookmark_utils |
419 | 438 |
420 const BookmarkNode* GetBookmarkNodeByID(const BookmarkModel* model, int64 id) { | 439 const BookmarkNode* GetBookmarkNodeByID(const BookmarkModel* model, int64 id) { |
421 // TODO(sky): TreeNode needs a method that visits all nodes using a predicate. | 440 // TODO(sky): TreeNode needs a method that visits all nodes using a predicate. |
422 return GetNodeByID(model->root_node(), id); | 441 return GetNodeByID(model->root_node(), id); |
423 } | 442 } |
OLD | NEW |