| 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" | |
| 18 #include "components/bookmarks/browser/bookmark_model.h" | 17 #include "components/bookmarks/browser/bookmark_model.h" |
| 19 #include "components/bookmarks/browser/scoped_group_bookmark_actions.h" | 18 #include "components/bookmarks/browser/scoped_group_bookmark_actions.h" |
| 20 #include "components/bookmarks/common/bookmark_pref_names.h" | 19 #include "components/bookmarks/common/bookmark_pref_names.h" |
| 21 #include "components/pref_registry/pref_registry_syncable.h" | 20 #include "components/pref_registry/pref_registry_syncable.h" |
| 22 #include "components/query_parser/query_parser.h" | 21 #include "components/query_parser/query_parser.h" |
| 23 #include "net/base/net_util.h" | 22 #include "net/base/net_util.h" |
| 24 #include "ui/base/models/tree_node_iterator.h" | 23 #include "ui/base/models/tree_node_iterator.h" |
| 25 #include "url/gurl.h" | 24 #include "url/gurl.h" |
| 26 | 25 |
| 27 using base::Time; | 26 using base::Time; |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 BookmarkNodeData bookmark_data; | 196 BookmarkNodeData bookmark_data; |
| 198 if (!bookmark_data.ReadFromClipboard(ui::CLIPBOARD_TYPE_COPY_PASTE)) | 197 if (!bookmark_data.ReadFromClipboard(ui::CLIPBOARD_TYPE_COPY_PASTE)) |
| 199 return; | 198 return; |
| 200 | 199 |
| 201 if (index == -1) | 200 if (index == -1) |
| 202 index = parent->child_count(); | 201 index = parent->child_count(); |
| 203 bookmarks::ScopedGroupBookmarkActions group_paste(model); | 202 bookmarks::ScopedGroupBookmarkActions group_paste(model); |
| 204 CloneBookmarkNode(model, bookmark_data.elements, parent, index, true); | 203 CloneBookmarkNode(model, bookmark_data.elements, parent, index, true); |
| 205 } | 204 } |
| 206 | 205 |
| 207 bool CanPasteFromClipboard(BookmarkModel* model, const BookmarkNode* node) { | 206 bool CanPasteFromClipboard(const BookmarkNode* node) { |
| 208 if (!node || !model->client()->CanBeEditedByUser(node)) | 207 if (!node) |
| 209 return false; | 208 return false; |
| 210 return BookmarkNodeData::ClipboardContainsBookmarks(); | 209 return BookmarkNodeData::ClipboardContainsBookmarks(); |
| 211 } | 210 } |
| 212 | 211 |
| 213 std::vector<const BookmarkNode*> GetMostRecentlyModifiedUserFolders( | 212 std::vector<const BookmarkNode*> GetMostRecentlyModifiedFolders( |
| 214 BookmarkModel* model, | 213 BookmarkModel* model, |
| 215 size_t max_count) { | 214 size_t max_count) { |
| 216 std::vector<const BookmarkNode*> nodes; | 215 std::vector<const BookmarkNode*> nodes; |
| 217 ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node(), | 216 ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node(), |
| 218 PruneInvisibleFolders); | 217 PruneInvisibleFolders); |
| 219 | 218 |
| 220 while (iterator.has_next()) { | 219 while (iterator.has_next()) { |
| 221 const BookmarkNode* parent = iterator.Next(); | 220 const BookmarkNode* parent = iterator.Next(); |
| 222 if (!model->client()->CanBeEditedByUser(parent)) | |
| 223 continue; | |
| 224 if (parent->is_folder() && parent->date_folder_modified() > Time()) { | 221 if (parent->is_folder() && parent->date_folder_modified() > Time()) { |
| 225 if (max_count == 0) { | 222 if (max_count == 0) { |
| 226 nodes.push_back(parent); | 223 nodes.push_back(parent); |
| 227 } else { | 224 } else { |
| 228 std::vector<const BookmarkNode*>::iterator i = | 225 std::vector<const BookmarkNode*>::iterator i = |
| 229 std::upper_bound(nodes.begin(), nodes.end(), parent, | 226 std::upper_bound(nodes.begin(), nodes.end(), parent, |
| 230 &MoreRecentlyModified); | 227 &MoreRecentlyModified); |
| 231 if (nodes.size() < max_count || i != nodes.end()) { | 228 if (nodes.size() < max_count || i != nodes.end()) { |
| 232 nodes.insert(i, parent); | 229 nodes.insert(i, parent); |
| 233 while (nodes.size() > max_count) | 230 while (nodes.size() > max_count) |
| 234 nodes.pop_back(); | 231 nodes.pop_back(); |
| 235 } | 232 } |
| 236 } | 233 } |
| 237 } // else case, the root node, which we don't care about or imported nodes | 234 } // else case, the root node, which we don't care about or imported nodes |
| 238 // (which have a time of 0). | 235 // (which have a time of 0). |
| 239 } | 236 } |
| 240 | 237 |
| 241 if (nodes.size() < max_count) { | 238 if (nodes.size() < max_count) { |
| 242 // Add the permanent nodes if there is space. The permanent nodes are the | 239 // Add the permanent nodes if there is space. The permanent nodes are the |
| 243 // only children of the root_node. | 240 // only children of the root_node. |
| 244 const BookmarkNode* root_node = model->root_node(); | 241 const BookmarkNode* root_node = model->root_node(); |
| 245 | 242 |
| 246 for (int i = 0; i < root_node->child_count(); ++i) { | 243 for (int i = 0; i < root_node->child_count(); ++i) { |
| 247 const BookmarkNode* node = root_node->GetChild(i); | 244 const BookmarkNode* node = root_node->GetChild(i); |
| 248 if (node->IsVisible() && model->client()->CanBeEditedByUser(node) && | 245 if (node->IsVisible() && |
| 249 std::find(nodes.begin(), nodes.end(), node) == nodes.end()) { | 246 std::find(nodes.begin(), nodes.end(), node) == nodes.end()) { |
| 250 nodes.push_back(node); | 247 nodes.push_back(node); |
| 251 | 248 |
| 252 if (nodes.size() == max_count) | 249 if (nodes.size() == max_count) |
| 253 break; | 250 break; |
| 254 } | 251 } |
| 255 } | 252 } |
| 256 } | 253 } |
| 257 return nodes; | 254 return nodes; |
| 258 } | 255 } |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 372 if (!node) | 369 if (!node) |
| 373 continue; | 370 continue; |
| 374 const BookmarkNode* parent = node->parent(); | 371 const BookmarkNode* parent = node->parent(); |
| 375 model->Remove(parent, parent->GetIndexOf(node)); | 372 model->Remove(parent, parent->GetIndexOf(node)); |
| 376 } | 373 } |
| 377 } | 374 } |
| 378 | 375 |
| 379 void AddIfNotBookmarked(BookmarkModel* model, | 376 void AddIfNotBookmarked(BookmarkModel* model, |
| 380 const GURL& url, | 377 const GURL& url, |
| 381 const base::string16& title) { | 378 const base::string16& title) { |
| 382 if (IsBookmarkedByUser(model, url)) | 379 std::vector<const BookmarkNode*> bookmarks; |
| 383 return; // Nothing to do, a user bookmark with that url already exists. | 380 model->GetNodesByURL(url, &bookmarks); |
| 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 user bookmarks. | 393 // Remove all the 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 && model->client()->CanBeEditedByUser(node)) | 397 if (index > -1) |
| 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*>& nodes) { | |
| 420 for (size_t i = 0; i < nodes.size(); ++i) { | |
| 421 if (!client->CanBeEditedByUser(nodes[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 | |
| 437 } // namespace bookmark_utils | 418 } // namespace bookmark_utils |
| 438 | 419 |
| 439 const BookmarkNode* GetBookmarkNodeByID(const BookmarkModel* model, int64 id) { | 420 const BookmarkNode* GetBookmarkNodeByID(const BookmarkModel* model, int64 id) { |
| 440 // TODO(sky): TreeNode needs a method that visits all nodes using a predicate. | 421 // TODO(sky): TreeNode needs a method that visits all nodes using a predicate. |
| 441 return GetNodeByID(model->root_node(), id); | 422 return GetNodeByID(model->root_node(), id); |
| 442 } | 423 } |
| OLD | NEW |