bookmark_utils.cc revision dc0f95d653279beabeb9817299e2902918ba123e
172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 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 "base/basictypes.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_path.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string16.h"
1272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/string_number_conversions.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/time.h"
143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/bookmarks/bookmark_model.h"
1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/bookmarks/bookmark_node_data.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_MACOSX)
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/bookmarks/bookmark_pasteboard_helper_mac.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_list.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_window.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/query_parser.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/platform_util.h"
243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/prefs/pref_service.h"
2521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h"
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/notification_service.h"
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h"
29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/page_navigator.h"
30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h"
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/app_strings.h"
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/chromium_strings.h"
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_util.h"
3572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/dragdrop/drag_drop_types.h"
3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/models/tree_node_iterator.h"
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(TOOLKIT_VIEWS)
4072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/dragdrop/os_exchange_data.h"
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/drag_utils.h"
4272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "views/events/event.h"
43dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "views/widget/native_widget.h"
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/widget.h"
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(TOOLKIT_GTK)
4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/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;
21372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (ui::DragDropTypes::DRAG_COPY & common_ops)
21472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return ui::DragDropTypes::DRAG_COPY;
21572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (ui::DragDropTypes::DRAG_LINK & common_ops)
21672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return ui::DragDropTypes::DRAG_LINK;
21772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (ui::DragDropTypes::DRAG_MOVE & common_ops)
21872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return ui::DragDropTypes::DRAG_MOVE;
21972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return ui::DragDropTypes::DRAG_NONE;
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BookmarkDragOperation(const BookmarkNode* node) {
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (node->is_url()) {
22472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE |
22572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen           ui::DragDropTypes::DRAG_LINK;
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
22772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE;
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
23072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(TOOLKIT_VIEWS)
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BookmarkDropOperation(Profile* profile,
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          const views::DropTargetEvent& event,
233201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                          const BookmarkNodeData& data,
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          const BookmarkNode* parent,
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          int index) {
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (data.IsFromProfile(profile) && data.size() > 1)
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Currently only accept one dragged node at a time.
23872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return ui::DragDropTypes::DRAG_NONE;
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!bookmark_utils::IsValidDropLocation(profile, data, parent, index))
24172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return ui::DragDropTypes::DRAG_NONE;
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (data.GetFirstNode(profile)) {
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // User is dragging from this profile: move.
24572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return ui::DragDropTypes::DRAG_MOVE;
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // User is dragging from another app, copy.
24872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return PreferredDropOperation(event.source_operations(),
24972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_LINK);
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
25172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif  // defined(TOOLKIT_VIEWS)
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint PerformBookmarkDrop(Profile* profile,
254201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                        const BookmarkNodeData& data,
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        const BookmarkNode* parent_node,
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        int index) {
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BookmarkModel* model = profile->GetBookmarkModel();
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (data.IsFromProfile(profile)) {
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::vector<const BookmarkNode*> dragged_nodes =
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        data.GetNodes(profile);
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!dragged_nodes.empty()) {
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Drag from same profile. Move nodes.
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      for (size_t i = 0; i < dragged_nodes.size(); ++i) {
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        model->Move(dragged_nodes[i], parent_node, index);
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        index = parent_node->IndexOfChild(dragged_nodes[i]) + 1;
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
26772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return ui::DragDropTypes::DRAG_MOVE;
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
26972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return ui::DragDropTypes::DRAG_NONE;
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Dropping a group from different profile. Always accept.
2724a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  bookmark_utils::CloneBookmarkNode(model, data.elements, parent_node, index);
27372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return ui::DragDropTypes::DRAG_COPY;
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool IsValidDropLocation(Profile* profile,
277201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                         const BookmarkNodeData& data,
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         const BookmarkNode* drop_parent,
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         int index) {
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!drop_parent->is_folder()) {
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!data.is_valid())
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (data.IsFromProfile(profile)) {
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<const BookmarkNode*> nodes = data.GetNodes(profile);
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (size_t i = 0; i < nodes.size(); ++i) {
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Don't allow the drop if the user is attempting to drop on one of the
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // nodes being dragged.
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const BookmarkNode* node = nodes[i];
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int node_index = (drop_parent == node->GetParent()) ?
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          drop_parent->IndexOfChild(nodes[i]) : -1;
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (node_index != -1 && (index == node_index || index == node_index + 1))
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return false;
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // drop_parent can't accept a child that is an ancestor.
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (drop_parent->HasAncestor(node))
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return false;
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // From the same profile, always accept.
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid CloneBookmarkNode(BookmarkModel* model,
310201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                       const std::vector<BookmarkNodeData::Element>& elements,
3114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                       const BookmarkNode* parent,
3124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                       int index_to_add_at) {
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!parent->is_folder() || !model) {
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < elements.size(); ++i)
3184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    CloneBookmarkNodeImpl(model, elements[i], parent, index_to_add_at + i);
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Bookmark dragging
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DragBookmarks(Profile* profile,
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   const std::vector<const BookmarkNode*>& nodes,
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   gfx::NativeView view) {
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!nodes.empty());
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(TOOLKIT_VIEWS)
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Set up our OLE machinery
33072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ui::OSExchangeData data;
331201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  BookmarkNodeData drag_data(nodes);
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  drag_data.Write(profile, &data);
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
338dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  views::NativeWidget* native_widget =
339dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      views::NativeWidget::GetNativeWidgetForNativeView(view);
340dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (native_widget) {
341dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    native_widget->GetWidget()->RunShellDrag(NULL, data,
342dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE |
343dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        ui::DragDropTypes::DRAG_LINK);
344dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->SetNestableTasksAllowed(was_nested);
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(OS_MACOSX)
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Allow nested message loop so we get DnD events as we drag this around.
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool was_nested = MessageLoop::current()->IsNested();
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->SetNestableTasksAllowed(true);
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bookmark_pasteboard_helper_mac::StartDrag(profile, nodes, view);
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->SetNestableTasksAllowed(was_nested);
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(TOOLKIT_GTK)
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BookmarkDrag::BeginDrag(profile, nodes);
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid OpenAll(gfx::NativeWindow parent,
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             Profile* profile,
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             PageNavigator* navigator,
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             const std::vector<const BookmarkNode*>& nodes,
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             WindowOpenDisposition initial_disposition) {
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!ShouldOpenAll(parent, nodes))
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NewBrowserPageNavigator navigator_impl(profile);
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!navigator) {
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Browser* browser =
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        BrowserList::FindBrowserWithType(profile, Browser::TYPE_NORMAL, false);
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!browser || !browser->GetSelectedTabContents()) {
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      navigator = &navigator_impl;
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (initial_disposition != NEW_WINDOW &&
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          initial_disposition != OFF_THE_RECORD) {
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        browser->window()->Activate();
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      navigator = browser->GetSelectedTabContents();
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool opened_url = false;
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < nodes.size(); ++i)
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OpenAllImpl(nodes[i], initial_disposition, &navigator, &opened_url);
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid OpenAll(gfx::NativeWindow parent,
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             Profile* profile,
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             PageNavigator* navigator,
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             const BookmarkNode* node,
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             WindowOpenDisposition initial_disposition) {
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<const BookmarkNode*> nodes;
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  nodes.push_back(node);
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  OpenAll(parent, profile, navigator, nodes, initial_disposition);
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CopyToClipboard(BookmarkModel* model,
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     const std::vector<const BookmarkNode*>& nodes,
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     bool remove_nodes) {
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (nodes.empty())
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
402201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  BookmarkNodeData(nodes).WriteToClipboard(NULL);
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (remove_nodes) {
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (size_t i = 0; i < nodes.size(); ++i) {
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      model->Remove(nodes[i]->GetParent(),
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    nodes[i]->GetParent()->IndexOfChild(nodes[i]));
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PasteFromClipboard(BookmarkModel* model,
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        const BookmarkNode* parent,
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        int index) {
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!parent)
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
418201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  BookmarkNodeData bookmark_data;
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!bookmark_data.ReadFromClipboard())
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (index == -1)
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    index = parent->GetChildCount();
4244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  bookmark_utils::CloneBookmarkNode(
4254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      model, bookmark_data.elements, parent, index);
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool CanPasteFromClipboard(const BookmarkNode* node) {
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!node)
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
431201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return BookmarkNodeData::ClipboardContainsBookmarks();
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
43472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstring16 GetNameForURL(const GURL& url) {
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (url.is_valid()) {
43672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return net::GetSuggestedFilename(url, "", "", string16());
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
43872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return l10n_util::GetStringUTF16(IDS_APP_UNTITLED_SHORTCUT_FILE_NAME);
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::vector<const BookmarkNode*> GetMostRecentlyModifiedGroups(
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BookmarkModel* model,
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    size_t max_count) {
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<const BookmarkNode*> nodes;
44672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node());
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (iterator.has_next()) {
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* parent = iterator.Next();
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (parent->is_folder() && parent->date_group_modified() > base::Time()) {
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (max_count == 0) {
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        nodes.push_back(parent);
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        std::vector<const BookmarkNode*>::iterator i =
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            std::upper_bound(nodes.begin(), nodes.end(), parent,
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             &MoreRecentlyModified);
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (nodes.size() < max_count || i != nodes.end()) {
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          nodes.insert(i, parent);
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          while (nodes.size() > max_count)
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            nodes.pop_back();
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }  // else case, the root node, which we don't care about or imported nodes
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       // (which have a time of 0).
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (nodes.size() < max_count) {
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Add the bookmark bar and other nodes if there is space.
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (find(nodes.begin(), nodes.end(), model->GetBookmarkBarNode()) ==
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        nodes.end()) {
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      nodes.push_back(model->GetBookmarkBarNode());
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (nodes.size() < max_count &&
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        find(nodes.begin(), nodes.end(), model->other_node()) == nodes.end()) {
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      nodes.push_back(model->other_node());
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return nodes;
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetMostRecentlyAddedEntries(BookmarkModel* model,
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 size_t count,
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 std::vector<const BookmarkNode*>* nodes) {
48472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node());
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (iterator.has_next()) {
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* node = iterator.Next();
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (node->is_url()) {
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      std::vector<const BookmarkNode*>::iterator insert_position =
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          std::upper_bound(nodes->begin(), nodes->end(), node,
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           &MoreRecentlyAdded);
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (nodes->size() < count || insert_position != nodes->end()) {
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        nodes->insert(insert_position, node);
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        while (nodes->size() > count)
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          nodes->pop_back();
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
50072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTitleMatch::TitleMatch()
50172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    : node(NULL) {
50272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
50372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
50472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTitleMatch::~TitleMatch() {}
50572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool MoreRecentlyAdded(const BookmarkNode* n1, const BookmarkNode* n2) {
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return n1->date_added() > n2->date_added();
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetBookmarksContainingText(BookmarkModel* model,
5113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                const string16& text,
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                size_t max_count,
5133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                const std::string& languages,
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                std::vector<const BookmarkNode*>* nodes) {
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<string16> words;
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  QueryParser parser;
5173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  parser.ExtractQueryWords(l10n_util::ToLower(text), &words);
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (words.empty())
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
52172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node());
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (iterator.has_next()) {
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* node = iterator.Next();
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (node->is_url() && DoesBookmarkContainWords(node, words, languages)) {
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      nodes->push_back(node);
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (nodes->size() == max_count)
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return;
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool DoesBookmarkContainText(const BookmarkNode* node,
5333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                             const string16& text,
5343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                             const std::string& languages) {
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<string16> words;
536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  QueryParser parser;
5373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  parser.ExtractQueryWords(l10n_util::ToLower(text), &words);
538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (words.empty())
539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return (node->is_url() && DoesBookmarkContainWords(node, words, languages));
542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const BookmarkNode* CreateNewNode(BookmarkModel* model,
545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* parent, const BookmarkEditor::EditDetails& details,
5463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const string16& new_title, const GURL& new_url) {
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const BookmarkNode* node;
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (details.type == BookmarkEditor::EditDetails::NEW_URL) {
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    node = model->AddURL(parent, parent->GetChildCount(), new_title, new_url);
550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (details.type == BookmarkEditor::EditDetails::NEW_FOLDER) {
551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    node = model->AddGroup(parent, parent->GetChildCount(), new_title);
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (size_t i = 0; i < details.urls.size(); ++i) {
553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      model->AddURL(node, node->GetChildCount(), details.urls[i].second,
554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    details.urls[i].first);
555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    model->SetDateGroupModified(parent, Time::Now());
557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return node;
563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst BookmarkNode* ApplyEditsWithNoGroupChange(BookmarkModel* model,
566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* parent, const BookmarkEditor::EditDetails& details,
5673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const string16& new_title, const GURL& new_url) {
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (details.type == BookmarkEditor::EditDetails::NEW_URL ||
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      details.type == BookmarkEditor::EditDetails::NEW_FOLDER) {
570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return CreateNewNode(model, parent, details, new_title, new_url);
571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const BookmarkNode* node = details.existing_node;
574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(node);
575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (node->is_url())
577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    model->SetURL(node, new_url);
578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  model->SetTitle(node, new_title);
579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return node;
581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst BookmarkNode* ApplyEditsWithPossibleGroupChange(BookmarkModel* model,
584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* new_parent, const BookmarkEditor::EditDetails& details,
5853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const string16& new_title, const GURL& new_url) {
586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (details.type == BookmarkEditor::EditDetails::NEW_URL ||
587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      details.type == BookmarkEditor::EditDetails::NEW_FOLDER) {
588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return CreateNewNode(model, new_parent, details, new_title, new_url);
589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const BookmarkNode* node = details.existing_node;
592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(node);
593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (new_parent != node->GetParent())
595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    model->Move(node, new_parent, new_parent->GetChildCount());
596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (node->is_url())
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    model->SetURL(node, new_url);
598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  model->SetTitle(node, new_title);
599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return node;
601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Formerly in BookmarkBarView
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ToggleWhenVisible(Profile* profile) {
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PrefService* prefs = profile->GetPrefs();
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const bool always_show = !prefs->GetBoolean(prefs::kShowBookmarkBar);
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The user changed when the bookmark bar is shown, update the preferences.
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  prefs->SetBoolean(prefs::kShowBookmarkBar, always_show);
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  prefs->ScheduleSavePersistentPrefs();
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // And notify the notification service.
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Source<Profile> source(profile);
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NotificationService::current()->Notify(
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NotificationType::BOOKMARK_BAR_VISIBILITY_PREF_CHANGED,
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      source,
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NotificationService::NoDetails());
618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid RegisterUserPrefs(PrefService* prefs) {
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  prefs->RegisterBooleanPref(prefs::kShowBookmarkBar, false);
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetURLAndTitleToBookmark(TabContents* tab_contents,
625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              GURL* url,
6263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                              string16* title) {
627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *url = tab_contents->GetURL();
6283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  *title = tab_contents->GetTitle();
629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetURLsForOpenTabs(Browser* browser,
6323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    std::vector<std::pair<GURL, string16> >* urls) {
633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int i = 0; i < browser->tab_count(); ++i) {
6343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    std::pair<GURL, string16> entry;
635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GetURLAndTitleToBookmark(browser->GetTabContentsAt(i), &(entry.first),
636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             &(entry.second));
637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    urls->push_back(entry);
638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst BookmarkNode* GetParentForNewNodes(
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* parent,
643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::vector<const BookmarkNode*>& selection,
644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int* index) {
645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const BookmarkNode* real_parent = parent;
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (selection.size() == 1 && selection[0]->is_folder())
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    real_parent = selection[0];
649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (index) {
651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (selection.size() == 1 && selection[0]->is_url()) {
652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      *index = real_parent->IndexOfChild(selection[0]) + 1;
653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (*index == 0) {
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // Node doesn't exist in parent, add to end.
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NOTREACHED();
656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        *index = real_parent->GetChildCount();
657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      *index = real_parent->GetChildCount();
660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return real_parent;
664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
666201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool NodeHasURLs(const BookmarkNode* node) {
667201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(node);
668201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
669201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (node->is_url())
670201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return true;
671201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
672201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  for (int i = 0; i < node->GetChildCount(); ++i) {
673201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (NodeHasURLs(node->GetChild(i)))
674201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      return true;
675201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
676201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return false;
677201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
678201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace bookmark_utils
680