bookmark_utils.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
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"
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/page_navigator.h"
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/tab_contents.h"
284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h"
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/notification_service.h"
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.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"
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/root_view.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  views::RootView* root_view =
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      views::Widget::GetWidgetFromNativeView(view)->GetRootView();
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Allow nested message loop so we get DnD events as we drag this around.
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool was_nested = MessageLoop::current()->IsNested();
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->SetNestableTasksAllowed(true);
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  root_view->StartDragForViewFromMouseEvent(NULL, data,
34272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE |
34372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      ui::DragDropTypes::DRAG_LINK);
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->SetNestableTasksAllowed(was_nested);
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(OS_MACOSX)
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Allow nested message loop so we get DnD events as we drag this around.
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool was_nested = MessageLoop::current()->IsNested();
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->SetNestableTasksAllowed(true);
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bookmark_pasteboard_helper_mac::StartDrag(profile, nodes, view);
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->SetNestableTasksAllowed(was_nested);
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(TOOLKIT_GTK)
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BookmarkDrag::BeginDrag(profile, nodes);
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid OpenAll(gfx::NativeWindow parent,
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             Profile* profile,
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             PageNavigator* navigator,
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             const std::vector<const BookmarkNode*>& nodes,
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             WindowOpenDisposition initial_disposition) {
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!ShouldOpenAll(parent, nodes))
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NewBrowserPageNavigator navigator_impl(profile);
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!navigator) {
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Browser* browser =
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        BrowserList::FindBrowserWithType(profile, Browser::TYPE_NORMAL, false);
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!browser || !browser->GetSelectedTabContents()) {
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      navigator = &navigator_impl;
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (initial_disposition != NEW_WINDOW &&
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          initial_disposition != OFF_THE_RECORD) {
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        browser->window()->Activate();
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      navigator = browser->GetSelectedTabContents();
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool opened_url = false;
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < nodes.size(); ++i)
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OpenAllImpl(nodes[i], initial_disposition, &navigator, &opened_url);
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid OpenAll(gfx::NativeWindow parent,
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             Profile* profile,
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             PageNavigator* navigator,
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             const BookmarkNode* node,
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             WindowOpenDisposition initial_disposition) {
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<const BookmarkNode*> nodes;
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  nodes.push_back(node);
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  OpenAll(parent, profile, navigator, nodes, initial_disposition);
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CopyToClipboard(BookmarkModel* model,
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     const std::vector<const BookmarkNode*>& nodes,
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     bool remove_nodes) {
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (nodes.empty())
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
401201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  BookmarkNodeData(nodes).WriteToClipboard(NULL);
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (remove_nodes) {
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (size_t i = 0; i < nodes.size(); ++i) {
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      model->Remove(nodes[i]->GetParent(),
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    nodes[i]->GetParent()->IndexOfChild(nodes[i]));
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PasteFromClipboard(BookmarkModel* model,
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        const BookmarkNode* parent,
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        int index) {
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!parent)
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
417201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  BookmarkNodeData bookmark_data;
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!bookmark_data.ReadFromClipboard())
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (index == -1)
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    index = parent->GetChildCount();
4234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  bookmark_utils::CloneBookmarkNode(
4244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      model, bookmark_data.elements, parent, index);
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool CanPasteFromClipboard(const BookmarkNode* node) {
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!node)
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
430201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return BookmarkNodeData::ClipboardContainsBookmarks();
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
43372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstring16 GetNameForURL(const GURL& url) {
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (url.is_valid()) {
43572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return net::GetSuggestedFilename(url, "", "", string16());
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
43772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return l10n_util::GetStringUTF16(IDS_APP_UNTITLED_SHORTCUT_FILE_NAME);
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::vector<const BookmarkNode*> GetMostRecentlyModifiedGroups(
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BookmarkModel* model,
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    size_t max_count) {
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<const BookmarkNode*> nodes;
44572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node());
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (iterator.has_next()) {
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* parent = iterator.Next();
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (parent->is_folder() && parent->date_group_modified() > base::Time()) {
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (max_count == 0) {
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        nodes.push_back(parent);
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        std::vector<const BookmarkNode*>::iterator i =
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            std::upper_bound(nodes.begin(), nodes.end(), parent,
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             &MoreRecentlyModified);
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (nodes.size() < max_count || i != nodes.end()) {
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          nodes.insert(i, parent);
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          while (nodes.size() > max_count)
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            nodes.pop_back();
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }  // else case, the root node, which we don't care about or imported nodes
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       // (which have a time of 0).
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (nodes.size() < max_count) {
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Add the bookmark bar and other nodes if there is space.
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (find(nodes.begin(), nodes.end(), model->GetBookmarkBarNode()) ==
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        nodes.end()) {
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      nodes.push_back(model->GetBookmarkBarNode());
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (nodes.size() < max_count &&
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        find(nodes.begin(), nodes.end(), model->other_node()) == nodes.end()) {
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      nodes.push_back(model->other_node());
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return nodes;
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetMostRecentlyAddedEntries(BookmarkModel* model,
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 size_t count,
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 std::vector<const BookmarkNode*>* nodes) {
48372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node());
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (iterator.has_next()) {
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* node = iterator.Next();
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (node->is_url()) {
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      std::vector<const BookmarkNode*>::iterator insert_position =
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          std::upper_bound(nodes->begin(), nodes->end(), node,
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           &MoreRecentlyAdded);
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (nodes->size() < count || insert_position != nodes->end()) {
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        nodes->insert(insert_position, node);
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        while (nodes->size() > count)
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          nodes->pop_back();
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
49972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTitleMatch::TitleMatch()
50072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    : node(NULL) {
50172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
50272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
50372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTitleMatch::~TitleMatch() {}
50472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool MoreRecentlyAdded(const BookmarkNode* n1, const BookmarkNode* n2) {
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return n1->date_added() > n2->date_added();
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetBookmarksContainingText(BookmarkModel* model,
5103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                const string16& text,
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                size_t max_count,
5123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                const std::string& languages,
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                std::vector<const BookmarkNode*>* nodes) {
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<string16> words;
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  QueryParser parser;
5163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  parser.ExtractQueryWords(l10n_util::ToLower(text), &words);
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (words.empty())
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
52072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node());
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (iterator.has_next()) {
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* node = iterator.Next();
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (node->is_url() && DoesBookmarkContainWords(node, words, languages)) {
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      nodes->push_back(node);
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (nodes->size() == max_count)
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return;
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool DoesBookmarkContainText(const BookmarkNode* node,
5323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                             const string16& text,
5333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                             const std::string& languages) {
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<string16> words;
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  QueryParser parser;
5363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  parser.ExtractQueryWords(l10n_util::ToLower(text), &words);
537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (words.empty())
538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return (node->is_url() && DoesBookmarkContainWords(node, words, languages));
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const BookmarkNode* CreateNewNode(BookmarkModel* model,
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* parent, const BookmarkEditor::EditDetails& details,
5453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const string16& new_title, const GURL& new_url) {
546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const BookmarkNode* node;
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (details.type == BookmarkEditor::EditDetails::NEW_URL) {
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    node = model->AddURL(parent, parent->GetChildCount(), new_title, new_url);
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (details.type == BookmarkEditor::EditDetails::NEW_FOLDER) {
550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    node = model->AddGroup(parent, parent->GetChildCount(), new_title);
551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (size_t i = 0; i < details.urls.size(); ++i) {
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      model->AddURL(node, node->GetChildCount(), details.urls[i].second,
553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    details.urls[i].first);
554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    model->SetDateGroupModified(parent, Time::Now());
556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();
558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return node;
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst BookmarkNode* ApplyEditsWithNoGroupChange(BookmarkModel* model,
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* parent, const BookmarkEditor::EditDetails& details,
5663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const string16& new_title, const GURL& new_url) {
567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (details.type == BookmarkEditor::EditDetails::NEW_URL ||
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      details.type == BookmarkEditor::EditDetails::NEW_FOLDER) {
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return CreateNewNode(model, parent, details, new_title, new_url);
570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const BookmarkNode* node = details.existing_node;
573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(node);
574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (node->is_url())
576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    model->SetURL(node, new_url);
577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  model->SetTitle(node, new_title);
578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return node;
580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst BookmarkNode* ApplyEditsWithPossibleGroupChange(BookmarkModel* model,
583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* new_parent, const BookmarkEditor::EditDetails& details,
5843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const string16& new_title, const GURL& new_url) {
585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (details.type == BookmarkEditor::EditDetails::NEW_URL ||
586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      details.type == BookmarkEditor::EditDetails::NEW_FOLDER) {
587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return CreateNewNode(model, new_parent, details, new_title, new_url);
588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const BookmarkNode* node = details.existing_node;
591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(node);
592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (new_parent != node->GetParent())
594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    model->Move(node, new_parent, new_parent->GetChildCount());
595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (node->is_url())
596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    model->SetURL(node, new_url);
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  model->SetTitle(node, new_title);
598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return node;
600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Formerly in BookmarkBarView
603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ToggleWhenVisible(Profile* profile) {
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PrefService* prefs = profile->GetPrefs();
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const bool always_show = !prefs->GetBoolean(prefs::kShowBookmarkBar);
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The user changed when the bookmark bar is shown, update the preferences.
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  prefs->SetBoolean(prefs::kShowBookmarkBar, always_show);
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  prefs->ScheduleSavePersistentPrefs();
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // And notify the notification service.
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Source<Profile> source(profile);
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NotificationService::current()->Notify(
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NotificationType::BOOKMARK_BAR_VISIBILITY_PREF_CHANGED,
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      source,
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NotificationService::NoDetails());
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid RegisterUserPrefs(PrefService* prefs) {
620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  prefs->RegisterBooleanPref(prefs::kShowBookmarkBar, false);
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetURLAndTitleToBookmark(TabContents* tab_contents,
624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              GURL* url,
6253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                              string16* title) {
626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *url = tab_contents->GetURL();
6273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  *title = tab_contents->GetTitle();
628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetURLsForOpenTabs(Browser* browser,
6313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    std::vector<std::pair<GURL, string16> >* urls) {
632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int i = 0; i < browser->tab_count(); ++i) {
6333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    std::pair<GURL, string16> entry;
634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GetURLAndTitleToBookmark(browser->GetTabContentsAt(i), &(entry.first),
635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             &(entry.second));
636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    urls->push_back(entry);
637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst BookmarkNode* GetParentForNewNodes(
641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* parent,
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::vector<const BookmarkNode*>& selection,
643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int* index) {
644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const BookmarkNode* real_parent = parent;
645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (selection.size() == 1 && selection[0]->is_folder())
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    real_parent = selection[0];
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (index) {
650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (selection.size() == 1 && selection[0]->is_url()) {
651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      *index = real_parent->IndexOfChild(selection[0]) + 1;
652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (*index == 0) {
653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // Node doesn't exist in parent, add to end.
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NOTREACHED();
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        *index = real_parent->GetChildCount();
656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      *index = real_parent->GetChildCount();
659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return real_parent;
663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
665201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool NodeHasURLs(const BookmarkNode* node) {
666201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(node);
667201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
668201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (node->is_url())
669201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return true;
670201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
671201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  for (int i = 0; i < node->GetChildCount(); ++i) {
672201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (NodeHasURLs(node->GetChild(i)))
673201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      return true;
674201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
675201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return false;
676201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
677201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace bookmark_utils
679