15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/bookmarks/browser/bookmark_utils.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/bind.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/case_conversion.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/string_search.h" 145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/metrics/user_metrics_action.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h" 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "components/bookmarks/browser/bookmark_client.h" 19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/bookmarks/browser/bookmark_model.h" 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/bookmarks/browser/scoped_group_bookmark_actions.h" 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/bookmarks/common/bookmark_pref_names.h" 22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h" 230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "components/query_parser/query_parser.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h" 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/base/clipboard/clipboard.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/models/tree_node_iterator.h" 270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "url/gurl.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 31116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace bookmarks { 32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// The maximum length of URL or title returned by the Cleanup functions. 360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochconst size_t kCleanedUpUrlMaxLength = 1024u; 370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochconst size_t kCleanedUpTitleMaxLength = 1024u; 380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloneBookmarkNodeImpl(BookmarkModel* model, 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNodeData::Element& element, 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* parent, 423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int index_to_add_at, 433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool reset_node_times) { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (element.is_url) { 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Time date_added = reset_node_times ? Time::Now() : element.date_added; 460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(!date_added.is_null()); 470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch model->AddURLWithCreationTimeAndMetaInfo(parent, 490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch index_to_add_at, 500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch element.title, 510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch element.url, 520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch date_added, 530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch &element.meta_info_map); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const BookmarkNode* cloned_node = model->AddFolderWithMetaInfo( 560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent, index_to_add_at, element.title, &element.meta_info_map); 573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!reset_node_times) { 583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(!element.date_folder_modified.is_null()); 59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) model->SetDateFolderModified(cloned_node, element.date_folder_modified); 603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < static_cast<int>(element.children.size()); ++i) 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CloneBookmarkNodeImpl(model, element.children[i], cloned_node, i, 633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) reset_node_times); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Comparison function that compares based on date modified of the two nodes. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MoreRecentlyModified(const BookmarkNode* n1, const BookmarkNode* n2) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return n1->date_folder_modified() > n2->date_folder_modified(); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if |text| contains each string in |words|. This is used when 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// searching for bookmarks. 74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool DoesBookmarkTextContainWords(const base::string16& text, 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::vector<base::string16>& words) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < words.size(); ++i) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!base::i18n::StringSearchIgnoringCaseAndAccents( 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) words[i], text, NULL, NULL)) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if |node|s title or url contains the strings in |words|. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |languages| argument is user's accept-language setting to decode IDN. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DoesBookmarkContainWords(const BookmarkNode* node, 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::vector<base::string16>& words, 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& languages) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoesBookmarkTextContainWords(node->GetTitle(), words) || 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DoesBookmarkTextContainWords( 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::UTF8ToUTF16(node->url().spec()), words) || 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoesBookmarkTextContainWords(net::FormatUrl( 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->url(), languages, net::kFormatUrlOmitNothing, 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::UnescapeRule::NORMAL, NULL, NULL, NULL), words); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// This is used with a tree iterator to skip subtrees which are not visible. 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool PruneInvisibleFolders(const BookmarkNode* node) { 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return !node->IsVisible(); 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This traces parents up to root, determines if node is contained in a 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// selected folder. 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool HasSelectedAncestor(BookmarkModel* model, 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::vector<const BookmarkNode*>& selected_nodes, 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const BookmarkNode* node) { 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!node || model->is_permanent_node(node)) 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (size_t i = 0; i < selected_nodes.size(); ++i) 113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (node->id() == selected_nodes[i]->id()) 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return HasSelectedAncestor(model, selected_nodes, node->parent()); 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochconst BookmarkNode* GetNodeByID(const BookmarkNode* node, int64 id) { 1200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (node->id() == id) 1210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return node; 1220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (int i = 0, child_count = node->child_count(); i < child_count; ++i) { 1240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const BookmarkNode* result = GetNodeByID(node->GetChild(i), id); 1250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (result) 1260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return result; 1270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 1280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return NULL; 1290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Attempts to shorten a URL safely (i.e., by preventing the end of the URL 1320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// from being in the middle of an escape sequence) to no more than 1330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// kCleanedUpUrlMaxLength characters, returning the result. 1340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochstd::string TruncateUrl(const std::string& url) { 1350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (url.length() <= kCleanedUpUrlMaxLength) 1360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return url; 1370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // If we're in the middle of an escape sequence, truncate just before it. 1390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (url[kCleanedUpUrlMaxLength - 1] == '%') 1400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return url.substr(0, kCleanedUpUrlMaxLength - 1); 1410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (url[kCleanedUpUrlMaxLength - 2] == '%') 1420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return url.substr(0, kCleanedUpUrlMaxLength - 2); 1430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return url.substr(0, kCleanedUpUrlMaxLength); 1450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Returns the URL from the clipboard. If there is no URL an empty URL is 1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// returned. 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciGURL GetUrlFromClipboard() { 1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::string16 url_text; 1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if !defined(OS_IOS) 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ui::Clipboard::GetForCurrentThread()->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &url_text); 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return GURL(url_text); 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QueryFields::QueryFields() {} 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QueryFields::~QueryFields() {} 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloneBookmarkNode(BookmarkModel* model, 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<BookmarkNodeData::Element>& elements, 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* parent, 1663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int index_to_add_at, 1673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool reset_node_times) { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!parent->is_folder() || !model) { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (size_t i = 0; i < elements.size(); ++i) { 1735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CloneBookmarkNodeImpl(model, elements[i], parent, 1745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu index_to_add_at + static_cast<int>(i), 1753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) reset_node_times); 1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CopyToClipboard(BookmarkModel* model, 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<const BookmarkNode*>& nodes, 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool remove_nodes) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nodes.empty()) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Create array of selected nodes with descendants filtered out. 186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::vector<const BookmarkNode*> filtered_nodes; 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (size_t i = 0; i < nodes.size(); ++i) 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!HasSelectedAncestor(model, nodes, nodes[i]->parent())) 189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) filtered_nodes.push_back(nodes[i]); 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) BookmarkNodeData(filtered_nodes). 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WriteToClipboard(ui::CLIPBOARD_TYPE_COPY_PASTE); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (remove_nodes) { 1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ScopedGroupBookmarkActions group_cut(model); 196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (size_t i = 0; i < filtered_nodes.size(); ++i) { 197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int index = filtered_nodes[i]->parent()->GetIndexOf(filtered_nodes[i]); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index > -1) 199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) model->Remove(filtered_nodes[i]->parent(), index); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasteFromClipboard(BookmarkModel* model, 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* parent, 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index) { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!parent) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNodeData bookmark_data; 2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!bookmark_data.ReadFromClipboard(ui::CLIPBOARD_TYPE_COPY_PASTE)) { 2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GURL url = GetUrlFromClipboard(); 2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!url.is_valid()) 2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BookmarkNode node(url); 2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci node.SetTitle(base::ASCIIToUTF16(url.spec())); 2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bookmark_data = BookmarkNodeData(&node); 2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index == -1) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = parent->child_count(); 2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ScopedGroupBookmarkActions group_paste(model); 2223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CloneBookmarkNode(model, bookmark_data.elements, parent, index, true); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool CanPasteFromClipboard(BookmarkModel* model, const BookmarkNode* node) { 22646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!node || !model->client()->CanBeEditedByUser(node)) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return (BookmarkNodeData::ClipboardContainsBookmarks() || 2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetUrlFromClipboard().is_valid()); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)std::vector<const BookmarkNode*> GetMostRecentlyModifiedUserFolders( 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModel* model, 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t max_count) { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<const BookmarkNode*> nodes; 2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ui::TreeNodeIterator<const BookmarkNode> iterator( 2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci model->root_node(), base::Bind(&PruneInvisibleFolders)); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (iterator.has_next()) { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* parent = iterator.Next(); 24146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!model->client()->CanBeEditedByUser(parent)) 24246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) continue; 243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (parent->is_folder() && parent->date_folder_modified() > Time()) { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (max_count == 0) { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nodes.push_back(parent); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<const BookmarkNode*>::iterator i = 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::upper_bound(nodes.begin(), nodes.end(), parent, 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &MoreRecentlyModified); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nodes.size() < max_count || i != nodes.end()) { 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nodes.insert(i, parent); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (nodes.size() > max_count) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nodes.pop_back(); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } // else case, the root node, which we don't care about or imported nodes 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (which have a time of 0). 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nodes.size() < max_count) { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the permanent nodes if there is space. The permanent nodes are the 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // only children of the root_node. 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* root_node = model->root_node(); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < root_node->child_count(); ++i) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = root_node->GetChild(i); 26746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (node->IsVisible() && model->client()->CanBeEditedByUser(node) && 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::find(nodes.begin(), nodes.end(), node) == nodes.end()) { 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nodes.push_back(node); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nodes.size() == max_count) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nodes; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetMostRecentlyAddedEntries(BookmarkModel* model, 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t count, 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<const BookmarkNode*>* nodes) { 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node()); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (iterator.has_next()) { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = iterator.Next(); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node->is_url()) { 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<const BookmarkNode*>::iterator insert_position = 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::upper_bound(nodes->begin(), nodes->end(), node, 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &MoreRecentlyAdded); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nodes->size() < count || insert_position != nodes->end()) { 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nodes->insert(insert_position, node); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (nodes->size() > count) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nodes->pop_back(); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MoreRecentlyAdded(const BookmarkNode* n1, const BookmarkNode* n2) { 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return n1->date_added() > n2->date_added(); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GetBookmarksMatchingProperties(BookmarkModel* model, 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const QueryFields& query, 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t max_count, 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& languages, 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<const BookmarkNode*>* nodes) { 3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<base::string16> query_words; 3080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch query_parser::QueryParser parser; 3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (query.word_phrase_query) { 3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) parser.ParseQueryWords(base::i18n::ToLower(*query.word_phrase_query), 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &query_words); 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (query_words.empty()) 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node()); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (iterator.has_next()) { 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = iterator.Next(); 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if ((!query_words.empty() && 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !DoesBookmarkContainWords(node, query_words, languages)) || 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model->is_permanent_node(node)) { 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (query.url) { 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Check against bare url spec and IDN-decoded url. 3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!node->is_url() || 3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !(base::UTF8ToUTF16(node->url().spec()) == *query.url || 3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) net::FormatUrl( 3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) node->url(), languages, net::kFormatUrlOmitNothing, 3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) net::UnescapeRule::NORMAL, NULL, NULL, NULL) == *query.url)) { 3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (query.title && node->GetTitle() != *query.title) 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) nodes->push_back(node); 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (nodes->size() == max_count) 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { 344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) registry->RegisterBooleanPref( 345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) prefs::kShowBookmarkBar, 346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) false, 347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) registry->RegisterBooleanPref( 349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) prefs::kEditBookmarksEnabled, 350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) true, 351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) registry->RegisterBooleanPref( 353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) prefs::kShowAppsShortcutInBookmarkBar, 354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) true, 355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 356f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) registry->RegisterBooleanPref( 357f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) prefs::kShowManagedBookmarksInBookmarkBar, 358f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) true, 359f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BookmarkNode* GetParentForNewNodes( 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* parent, 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<const BookmarkNode*>& selection, 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* index) { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* real_parent = parent; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (selection.size() == 1 && selection[0]->is_folder()) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) real_parent = selection[0]; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index) { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (selection.size() == 1 && selection[0]->is_url()) { 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *index = real_parent->GetIndexOf(selection[0]) + 1; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*index == 0) { 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Node doesn't exist in parent, add to end. 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *index = real_parent->child_count(); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *index = real_parent->child_count(); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return real_parent; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeleteBookmarkFolders(BookmarkModel* model, 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<int64>& ids) { 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove the folders that were removed. This has to be done after all the 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // other changes have been committed. 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<int64>::const_iterator iter = ids.begin(); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != ids.end(); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++iter) { 3940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const BookmarkNode* node = GetBookmarkNodeByID(model, *iter); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* parent = node->parent(); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model->Remove(parent, parent->GetIndexOf(node)); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AddIfNotBookmarked(BookmarkModel* model, 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 404a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& title) { 40546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (IsBookmarkedByUser(model, url)) 40646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; // Nothing to do, a user bookmark with that url already exists. 4075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu model->client()->RecordAction(base::UserMetricsAction("BookmarkAdded")); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* parent = model->GetParentForNewNodes(); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model->AddURL(parent, parent->child_count(), title, url); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RemoveAllBookmarks(BookmarkModel* model, const GURL& url) { 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<const BookmarkNode*> bookmarks; 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model->GetNodesByURL(url, &bookmarks); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 41646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Remove all the user bookmarks. 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < bookmarks.size(); ++i) { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = bookmarks[i]; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index = node->parent()->GetIndexOf(node); 42046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (index > -1 && model->client()->CanBeEditedByUser(node)) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model->Remove(node->parent(), index); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubase::string16 CleanUpUrlForMatching( 4265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const GURL& gurl, 4275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const std::string& languages, 4285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::OffsetAdjuster::Adjustments* adjustments) { 4295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::OffsetAdjuster::Adjustments tmp_adjustments; 4305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return base::i18n::ToLower(net::FormatUrlWithAdjustments( 4310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch GURL(TruncateUrl(gurl.spec())), languages, 4320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch net::kFormatUrlOmitUsernamePassword, 4330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch net::UnescapeRule::SPACES | net::UnescapeRule::URL_SPECIAL_CHARS, 4345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu NULL, NULL, adjustments ? adjustments : &tmp_adjustments)); 4350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 4360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochbase::string16 CleanUpTitleForMatching(const base::string16& title) { 4380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return base::i18n::ToLower(title.substr(0u, kCleanedUpTitleMaxLength)); 4390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 4400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 44146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool CanAllBeEditedByUser(BookmarkClient* client, 44246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::vector<const BookmarkNode*>& nodes) { 44346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (size_t i = 0; i < nodes.size(); ++i) { 44446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!client->CanBeEditedByUser(nodes[i])) 44546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 44646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 44746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return true; 44846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 44946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 45046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool IsBookmarkedByUser(BookmarkModel* model, const GURL& url) { 45146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::vector<const BookmarkNode*> nodes; 45246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) model->GetNodesByURL(url, &nodes); 45346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) for (size_t i = 0; i < nodes.size(); ++i) { 45446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (model->client()->CanBeEditedByUser(nodes[i])) 45546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return true; 45646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 45746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 45846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 45946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 4600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochconst BookmarkNode* GetBookmarkNodeByID(const BookmarkModel* model, int64 id) { 4610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // TODO(sky): TreeNode needs a method that visits all nodes using a predicate. 4620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return GetNodeByID(model->root_node(), id); 4630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 464116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 465116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} // namespace bookmarks 466