bookmark_utils.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/bookmarks/bookmark_utils.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <utility> 821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "app/drag_drop_types.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "app/l10n_util.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "app/tree_node_iterator.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/basictypes.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_path.h" 143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string16.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/time.h" 173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h" 18201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/browser/bookmarks/bookmark_node_data.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/bookmarks/bookmark_model.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_MACOSX) 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/bookmarks/bookmark_pasteboard_helper_mac.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_list.h" 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_window.h" 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/query_parser.h" 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/platform_util.h" 273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/prefs/pref_service.h" 2821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/page_navigator.h" 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/tab_contents.h" 314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h" 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/notification_service.h" 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h" 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/app_strings.h" 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/chromium_strings.h" 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h" 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_util.h" 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/event.h" 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(TOOLKIT_VIEWS) 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "app/os_exchange_data.h" 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/drag_utils.h" 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/root_view.h" 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/widget.h" 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(TOOLKIT_GTK) 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/gtk/custom_drag.h" 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::Time; 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A PageNavigator implementation that creates a new Browser. This is used when 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// opening a url and there is no Browser open. The Browser is created the first 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// time the PageNavigator method is invoked. 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass NewBrowserPageNavigator : public PageNavigator { 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit NewBrowserPageNavigator(Profile* profile) 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : profile_(profile), 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser_(NULL) {} 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual ~NewBrowserPageNavigator() { 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (browser_) 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser_->window()->Show(); 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser() const { return browser_; } 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OpenURL(const GURL& url, 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& referrer, 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WindowOpenDisposition disposition, 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageTransition::Type transition) { 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser_) { 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* profile = (disposition == OFF_THE_RECORD) ? 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_->GetOffTheRecordProfile() : profile_; 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser_ = Browser::Create(profile); 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Always open the first tab in the foreground. 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch disposition = NEW_FOREGROUND_TAB; 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser_->OpenURL(url, referrer, NEW_FOREGROUND_TAB, transition); 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* profile_; 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser_; 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(NewBrowserPageNavigator); 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid CloneBookmarkNodeImpl(BookmarkModel* model, 91201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch const BookmarkNodeData::Element& element, 924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const BookmarkNode* parent, 934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch int index_to_add_at) { 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (element.is_url) { 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model->AddURL(parent, index_to_add_at, element.title, element.url); 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* new_folder = model->AddGroup(parent, 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch index_to_add_at, 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch element.title); 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < static_cast<int>(element.children.size()); ++i) 1014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch CloneBookmarkNodeImpl(model, element.children[i], new_folder, i); 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns the number of descendants of node that are of type url. 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint DescendantURLCount(const BookmarkNode* node) { 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int result = 0; 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < node->GetChildCount(); ++i) { 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* child = node->GetChild(i); 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (child->is_url()) 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result++; 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result += DescendantURLCount(child); 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Implementation of OpenAll. Opens all nodes of type URL and recurses for 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// groups. |navigator| is the PageNavigator used to open URLs. After the first 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// url is opened |opened_url| is set to true and |navigator| is set to the 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// PageNavigator of the last active tab. This is done to handle a window 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// disposition of new window, in which case we want subsequent tabs to open in 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// that window. 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid OpenAllImpl(const BookmarkNode* node, 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WindowOpenDisposition initial_disposition, 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageNavigator** navigator, 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool* opened_url) { 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (node->is_url()) { 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WindowOpenDisposition disposition; 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (*opened_url) 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch disposition = NEW_BACKGROUND_TAB; 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch disposition = initial_disposition; 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (*navigator)->OpenURL(node->GetURL(), GURL(), disposition, 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageTransition::AUTO_BOOKMARK); 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!*opened_url) { 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *opened_url = true; 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We opened the first URL which may have opened a new window or clobbered 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the current page, reset the navigator just to be sure. 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* new_browser = BrowserList::GetLastActive(); 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (new_browser) { 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TabContents* current_tab = new_browser->GetSelectedTabContents(); 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(new_browser && current_tab); 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (new_browser && current_tab) 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *navigator = current_tab; 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } // else, new_browser == NULL, which happens during testing. 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Group, recurse through children. 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < node->GetChildCount(); ++i) { 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OpenAllImpl(node->GetChild(i), initial_disposition, navigator, 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch opened_url); 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ShouldOpenAll(gfx::NativeWindow parent, 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::vector<const BookmarkNode*>& nodes) { 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int descendant_count = 0; 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < nodes.size(); ++i) 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch descendant_count += DescendantURLCount(nodes[i]); 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (descendant_count < bookmark_utils::num_urls_before_prompting) 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch string16 message = l10n_util::GetStringFUTF16( 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IDS_BOOKMARK_BAR_SHOULD_OPEN_ALL, 1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::IntToString16(descendant_count)); 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch string16 title = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return platform_util::SimpleYesNoBox(parent, title, message); 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Comparison function that compares based on date modified of the two nodes. 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool MoreRecentlyModified(const BookmarkNode* n1, const BookmarkNode* n2) { 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return n1->date_group_modified() > n2->date_group_modified(); 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns true if |text| contains each string in |words|. This is used when 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// searching for bookmarks. 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool DoesBookmarkTextContainWords(const string16& text, 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::vector<string16>& words) { 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < words.size(); ++i) { 1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (text.find(words[i]) == string16::npos) 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns true if |node|s title or url contains the strings in |words|. 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |languages| argument is user's accept-language setting to decode IDN. 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool DoesBookmarkContainWords(const BookmarkNode* node, 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::vector<string16>& words, 1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::string& languages) { 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DoesBookmarkTextContainWords( 1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick l10n_util::ToLower(node->GetTitle()), words) || 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DoesBookmarkTextContainWords( 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch l10n_util::ToLower(UTF8ToUTF16(node->GetURL().spec())), words) || 1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DoesBookmarkTextContainWords(l10n_util::ToLower( 1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick net::FormatUrl(node->GetURL(), languages, net::kFormatUrlOmitNothing, 2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UnescapeRule::NORMAL, NULL, NULL, NULL)), words); 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace bookmark_utils { 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint num_urls_before_prompting = 15; 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint PreferredDropOperation(int source_operations, int operations) { 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int common_ops = (source_operations & operations); 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!common_ops) 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return 0; 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (DragDropTypes::DRAG_COPY & common_ops) 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DragDropTypes::DRAG_COPY; 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (DragDropTypes::DRAG_LINK & common_ops) 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DragDropTypes::DRAG_LINK; 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (DragDropTypes::DRAG_MOVE & common_ops) 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DragDropTypes::DRAG_MOVE; 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DragDropTypes::DRAG_NONE; 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BookmarkDragOperation(const BookmarkNode* node) { 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (node->is_url()) { 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_MOVE | 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DragDropTypes::DRAG_LINK; 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_MOVE; 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BookmarkDropOperation(Profile* profile, 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const views::DropTargetEvent& event, 232201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch const BookmarkNodeData& data, 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* parent, 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index) { 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (data.IsFromProfile(profile) && data.size() > 1) 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Currently only accept one dragged node at a time. 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DragDropTypes::DRAG_NONE; 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!bookmark_utils::IsValidDropLocation(profile, data, parent, index)) 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DragDropTypes::DRAG_NONE; 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (data.GetFirstNode(profile)) { 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // User is dragging from this profile: move. 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DragDropTypes::DRAG_MOVE; 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // User is dragging from another app, copy. 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return PreferredDropOperation(event.GetSourceOperations(), 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_LINK); 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint PerformBookmarkDrop(Profile* profile, 252201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch const BookmarkNodeData& data, 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* parent_node, 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index) { 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkModel* model = profile->GetBookmarkModel(); 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (data.IsFromProfile(profile)) { 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::vector<const BookmarkNode*> dragged_nodes = 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data.GetNodes(profile); 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!dragged_nodes.empty()) { 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Drag from same profile. Move nodes. 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < dragged_nodes.size(); ++i) { 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model->Move(dragged_nodes[i], parent_node, index); 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch index = parent_node->IndexOfChild(dragged_nodes[i]) + 1; 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DragDropTypes::DRAG_MOVE; 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DragDropTypes::DRAG_NONE; 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Dropping a group from different profile. Always accept. 2704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch bookmark_utils::CloneBookmarkNode(model, data.elements, parent_node, index); 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DragDropTypes::DRAG_COPY; 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool IsValidDropLocation(Profile* profile, 275201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch const BookmarkNodeData& data, 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* drop_parent, 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index) { 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!drop_parent->is_folder()) { 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!data.is_valid()) 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (data.IsFromProfile(profile)) { 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<const BookmarkNode*> nodes = data.GetNodes(profile); 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < nodes.size(); ++i) { 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't allow the drop if the user is attempting to drop on one of the 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // nodes being dragged. 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node = nodes[i]; 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int node_index = (drop_parent == node->GetParent()) ? 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drop_parent->IndexOfChild(nodes[i]) : -1; 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (node_index != -1 && (index == node_index || index == node_index + 1)) 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // drop_parent can't accept a child that is an ancestor. 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (drop_parent->HasAncestor(node)) 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // From the same profile, always accept. 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid CloneBookmarkNode(BookmarkModel* model, 308201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch const std::vector<BookmarkNodeData::Element>& elements, 3094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const BookmarkNode* parent, 3104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch int index_to_add_at) { 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!parent->is_folder() || !model) { 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < elements.size(); ++i) 3164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch CloneBookmarkNodeImpl(model, elements[i], parent, index_to_add_at + i); 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Bookmark dragging 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DragBookmarks(Profile* profile, 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::vector<const BookmarkNode*>& nodes, 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::NativeView view) { 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!nodes.empty()); 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(TOOLKIT_VIEWS) 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set up our OLE machinery 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OSExchangeData data; 329201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch BookmarkNodeData drag_data(nodes); 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch drag_data.Write(profile, &data); 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch views::RootView* root_view = 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch views::Widget::GetWidgetFromNativeView(view)->GetRootView(); 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Allow nested message loop so we get DnD events as we drag this around. 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool was_nested = MessageLoop::current()->IsNested(); 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->SetNestableTasksAllowed(true); 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch root_view->StartDragForViewFromMouseEvent(NULL, data, 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_MOVE | 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DragDropTypes::DRAG_LINK); 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->SetNestableTasksAllowed(was_nested); 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(OS_MACOSX) 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Allow nested message loop so we get DnD events as we drag this around. 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool was_nested = MessageLoop::current()->IsNested(); 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->SetNestableTasksAllowed(true); 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bookmark_pasteboard_helper_mac::StartDrag(profile, nodes, view); 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->SetNestableTasksAllowed(was_nested); 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(TOOLKIT_GTK) 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkDrag::BeginDrag(profile, nodes); 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid OpenAll(gfx::NativeWindow parent, 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* profile, 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageNavigator* navigator, 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::vector<const BookmarkNode*>& nodes, 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WindowOpenDisposition initial_disposition) { 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ShouldOpenAll(parent, nodes)) 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewBrowserPageNavigator navigator_impl(profile); 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!navigator) { 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Browser* browser = 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BrowserList::FindBrowserWithType(profile, Browser::TYPE_NORMAL, false); 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!browser || !browser->GetSelectedTabContents()) { 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch navigator = &navigator_impl; 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (initial_disposition != NEW_WINDOW && 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch initial_disposition != OFF_THE_RECORD) { 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch browser->window()->Activate(); 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch navigator = browser->GetSelectedTabContents(); 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool opened_url = false; 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < nodes.size(); ++i) 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OpenAllImpl(nodes[i], initial_disposition, &navigator, &opened_url); 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid OpenAll(gfx::NativeWindow parent, 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* profile, 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PageNavigator* navigator, 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node, 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WindowOpenDisposition initial_disposition) { 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<const BookmarkNode*> nodes; 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch nodes.push_back(node); 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OpenAll(parent, profile, navigator, nodes, initial_disposition); 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CopyToClipboard(BookmarkModel* model, 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::vector<const BookmarkNode*>& nodes, 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool remove_nodes) { 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (nodes.empty()) 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 399201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch BookmarkNodeData(nodes).WriteToClipboard(NULL); 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (remove_nodes) { 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < nodes.size(); ++i) { 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model->Remove(nodes[i]->GetParent(), 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch nodes[i]->GetParent()->IndexOfChild(nodes[i])); 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PasteFromClipboard(BookmarkModel* model, 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* parent, 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int index) { 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!parent) 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 415201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch BookmarkNodeData bookmark_data; 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!bookmark_data.ReadFromClipboard()) 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (index == -1) 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch index = parent->GetChildCount(); 4214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch bookmark_utils::CloneBookmarkNode( 4224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch model, bookmark_data.elements, parent, index); 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool CanPasteFromClipboard(const BookmarkNode* node) { 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!node) 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 428201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return BookmarkNodeData::ClipboardContainsBookmarks(); 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string GetNameForURL(const GURL& url) { 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (url.is_valid()) { 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return WideToUTF8(net::GetSuggestedFilename( 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url, std::string(), std::string(), FilePath()).ToWStringHack()); 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return l10n_util::GetStringUTF8(IDS_APP_UNTITLED_SHORTCUT_FILE_NAME); 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::vector<const BookmarkNode*> GetMostRecentlyModifiedGroups( 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BookmarkModel* model, 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t max_count) { 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<const BookmarkNode*> nodes; 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TreeNodeIterator<const BookmarkNode> iterator(model->root_node()); 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (iterator.has_next()) { 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* parent = iterator.Next(); 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (parent->is_folder() && parent->date_group_modified() > base::Time()) { 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (max_count == 0) { 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch nodes.push_back(parent); 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<const BookmarkNode*>::iterator i = 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::upper_bound(nodes.begin(), nodes.end(), parent, 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &MoreRecentlyModified); 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (nodes.size() < max_count || i != nodes.end()) { 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch nodes.insert(i, parent); 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (nodes.size() > max_count) 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch nodes.pop_back(); 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } // else case, the root node, which we don't care about or imported nodes 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (which have a time of 0). 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (nodes.size() < max_count) { 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add the bookmark bar and other nodes if there is space. 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (find(nodes.begin(), nodes.end(), model->GetBookmarkBarNode()) == 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch nodes.end()) { 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch nodes.push_back(model->GetBookmarkBarNode()); 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (nodes.size() < max_count && 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch find(nodes.begin(), nodes.end(), model->other_node()) == nodes.end()) { 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch nodes.push_back(model->other_node()); 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return nodes; 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetMostRecentlyAddedEntries(BookmarkModel* model, 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t count, 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<const BookmarkNode*>* nodes) { 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TreeNodeIterator<const BookmarkNode> iterator(model->root_node()); 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (iterator.has_next()) { 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node = iterator.Next(); 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (node->is_url()) { 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<const BookmarkNode*>::iterator insert_position = 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::upper_bound(nodes->begin(), nodes->end(), node, 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &MoreRecentlyAdded); 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (nodes->size() < count || insert_position != nodes->end()) { 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch nodes->insert(insert_position, node); 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (nodes->size() > count) 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch nodes->pop_back(); 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool MoreRecentlyAdded(const BookmarkNode* n1, const BookmarkNode* n2) { 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return n1->date_added() > n2->date_added(); 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetBookmarksContainingText(BookmarkModel* model, 5033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const string16& text, 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t max_count, 5053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::string& languages, 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<const BookmarkNode*>* nodes) { 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<string16> words; 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch QueryParser parser; 5093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick parser.ExtractQueryWords(l10n_util::ToLower(text), &words); 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (words.empty()) 511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TreeNodeIterator<const BookmarkNode> iterator(model->root_node()); 514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (iterator.has_next()) { 515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node = iterator.Next(); 516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (node->is_url() && DoesBookmarkContainWords(node, words, languages)) { 517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch nodes->push_back(node); 518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (nodes->size() == max_count) 519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool DoesBookmarkContainText(const BookmarkNode* node, 5253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const string16& text, 5263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::string& languages) { 527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<string16> words; 528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch QueryParser parser; 5293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick parser.ExtractQueryWords(l10n_util::ToLower(text), &words); 530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (words.empty()) 531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return (node->is_url() && DoesBookmarkContainWords(node, words, languages)); 534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const BookmarkNode* CreateNewNode(BookmarkModel* model, 537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* parent, const BookmarkEditor::EditDetails& details, 5383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const string16& new_title, const GURL& new_url) { 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node; 540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (details.type == BookmarkEditor::EditDetails::NEW_URL) { 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch node = model->AddURL(parent, parent->GetChildCount(), new_title, new_url); 542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (details.type == BookmarkEditor::EditDetails::NEW_FOLDER) { 543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch node = model->AddGroup(parent, parent->GetChildCount(), new_title); 544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < details.urls.size(); ++i) { 545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model->AddURL(node, node->GetChildCount(), details.urls[i].second, 546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch details.urls[i].first); 547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model->SetDateGroupModified(parent, Time::Now()); 549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return node; 555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst BookmarkNode* ApplyEditsWithNoGroupChange(BookmarkModel* model, 558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* parent, const BookmarkEditor::EditDetails& details, 5593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const string16& new_title, const GURL& new_url) { 560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (details.type == BookmarkEditor::EditDetails::NEW_URL || 561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch details.type == BookmarkEditor::EditDetails::NEW_FOLDER) { 562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return CreateNewNode(model, parent, details, new_title, new_url); 563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node = details.existing_node; 566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(node); 567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (node->is_url()) 569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model->SetURL(node, new_url); 570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model->SetTitle(node, new_title); 571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return node; 573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst BookmarkNode* ApplyEditsWithPossibleGroupChange(BookmarkModel* model, 576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* new_parent, const BookmarkEditor::EditDetails& details, 5773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const string16& new_title, const GURL& new_url) { 578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (details.type == BookmarkEditor::EditDetails::NEW_URL || 579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch details.type == BookmarkEditor::EditDetails::NEW_FOLDER) { 580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return CreateNewNode(model, new_parent, details, new_title, new_url); 581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* node = details.existing_node; 584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(node); 585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (new_parent != node->GetParent()) 587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model->Move(node, new_parent, new_parent->GetChildCount()); 588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (node->is_url()) 589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model->SetURL(node, new_url); 590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model->SetTitle(node, new_title); 591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return node; 593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Formerly in BookmarkBarView 596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ToggleWhenVisible(Profile* profile) { 597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* prefs = profile->GetPrefs(); 598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool always_show = !prefs->GetBoolean(prefs::kShowBookmarkBar); 599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The user changed when the bookmark bar is shown, update the preferences. 601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->SetBoolean(prefs::kShowBookmarkBar, always_show); 602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->ScheduleSavePersistentPrefs(); 603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // And notify the notification service. 605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Source<Profile> source(profile); 606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::current()->Notify( 607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationType::BOOKMARK_BAR_VISIBILITY_PREF_CHANGED, 608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch source, 609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationService::NoDetails()); 610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid RegisterUserPrefs(PrefService* prefs) { 613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->RegisterBooleanPref(prefs::kShowBookmarkBar, false); 614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetURLAndTitleToBookmark(TabContents* tab_contents, 617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL* url, 6183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick string16* title) { 619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *url = tab_contents->GetURL(); 6203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *title = tab_contents->GetTitle(); 621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetURLsForOpenTabs(Browser* browser, 6243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::vector<std::pair<GURL, string16> >* urls) { 625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < browser->tab_count(); ++i) { 6263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::pair<GURL, string16> entry; 627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetURLAndTitleToBookmark(browser->GetTabContentsAt(i), &(entry.first), 628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &(entry.second)); 629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch urls->push_back(entry); 630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst BookmarkNode* GetParentForNewNodes( 634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* parent, 635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::vector<const BookmarkNode*>& selection, 636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int* index) { 637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BookmarkNode* real_parent = parent; 638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (selection.size() == 1 && selection[0]->is_folder()) 640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch real_parent = selection[0]; 641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (index) { 643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (selection.size() == 1 && selection[0]->is_url()) { 644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *index = real_parent->IndexOfChild(selection[0]) + 1; 645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (*index == 0) { 646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Node doesn't exist in parent, add to end. 647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *index = real_parent->GetChildCount(); 649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *index = real_parent->GetChildCount(); 652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return real_parent; 656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 658201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool NodeHasURLs(const BookmarkNode* node) { 659201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DCHECK(node); 660201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 661201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (node->is_url()) 662201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return true; 663201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 664201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch for (int i = 0; i < node->GetChildCount(); ++i) { 665201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (NodeHasURLs(node->GetChild(i))) 666201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return true; 667201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 668201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return false; 669201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} 670201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace bookmark_utils 672