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