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