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#include "chrome/browser/history/query_parser.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/platform_util.h"
193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/prefs/pref_service.h"
2021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h"
22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_list.h"
23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_window.h"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h"
25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/page_navigator.h"
26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h"
27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h"
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/app_strings.h"
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/chromium_strings.h"
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_util.h"
3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/dragdrop/drag_drop_types.h"
3372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
3472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/models/tree_node_iterator.h"
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_MACOSX)
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/bookmarks/bookmark_pasteboard_helper_mac.h"
38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif
39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(TOOLKIT_VIEWS)
4172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/dragdrop/os_exchange_data.h"
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/drag_utils.h"
4372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "views/events/event.h"
44dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "views/widget/native_widget.h"
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/widget.h"
46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif
47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(TOOLKIT_GTK)
4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/custom_drag.h"
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::Time;
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A PageNavigator implementation that creates a new Browser. This is used when
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// opening a url and there is no Browser open. The Browser is created the first
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// time the PageNavigator method is invoked.
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass NewBrowserPageNavigator : public PageNavigator {
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  explicit NewBrowserPageNavigator(Profile* profile)
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : profile_(profile),
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        browser_(NULL) {}
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual ~NewBrowserPageNavigator() {
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (browser_)
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      browser_->window()->Show();
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Browser* browser() const { return browser_; }
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void OpenURL(const GURL& url,
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       const GURL& referrer,
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       WindowOpenDisposition disposition,
75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                       PageTransition::Type transition) OVERRIDE {
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!browser_) {
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      Profile* profile = (disposition == OFF_THE_RECORD) ?
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          profile_->GetOffTheRecordProfile() : profile_;
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      browser_ = Browser::Create(profile);
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Always open the first tab in the foreground.
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      disposition = NEW_FOREGROUND_TAB;
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    browser_->OpenURL(url, referrer, NEW_FOREGROUND_TAB, transition);
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Profile* profile_;
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Browser* browser_;
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(NewBrowserPageNavigator);
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid CloneBookmarkNodeImpl(BookmarkModel* model,
94201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                           const BookmarkNodeData::Element& element,
954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                           const BookmarkNode* parent,
964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                           int index_to_add_at) {
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (element.is_url) {
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    model->AddURL(parent, index_to_add_at, element.title, element.url);
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const BookmarkNode* new_folder = model->AddFolder(parent,
101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                      index_to_add_at,
102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                                      element.title);
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (int i = 0; i < static_cast<int>(element.children.size()); ++i)
1044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      CloneBookmarkNodeImpl(model, element.children[i], new_folder, i);
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Returns the number of children of |node| that are of type url.
109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint ChildURLCount(const BookmarkNode* node) {
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int result = 0;
111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (int i = 0; i < node->child_count(); ++i) {
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* child = node->GetChild(i);
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (child->is_url())
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      result++;
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return result;
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Implementation of OpenAll. Opens all nodes of type URL and any children of
120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// |node| that are of type URL. |navigator| is the PageNavigator used to open
121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// URLs. After the first url is opened |opened_url| is set to true and
122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// |navigator| is set to the PageNavigator of the last active tab. This is done
123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// to handle a window disposition of new window, in which case we want
124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// subsequent tabs to open in that window.
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid OpenAllImpl(const BookmarkNode* node,
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 WindowOpenDisposition initial_disposition,
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 PageNavigator** navigator,
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 bool* opened_url) {
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (node->is_url()) {
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WindowOpenDisposition disposition;
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (*opened_url)
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      disposition = NEW_BACKGROUND_TAB;
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    else
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      disposition = initial_disposition;
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    (*navigator)->OpenURL(node->GetURL(), GURL(), disposition,
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          PageTransition::AUTO_BOOKMARK);
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!*opened_url) {
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      *opened_url = true;
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // We opened the first URL which may have opened a new window or clobbered
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // the current page, reset the navigator just to be sure.
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      Browser* new_browser = BrowserList::GetLastActive();
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (new_browser) {
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        TabContents* current_tab = new_browser->GetSelectedTabContents();
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        DCHECK(new_browser && current_tab);
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (new_browser && current_tab)
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          *navigator = current_tab;
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }  // else, new_browser == NULL, which happens during testing.
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // For folders only open direct children.
151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    for (int i = 0; i < node->child_count(); ++i) {
152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const BookmarkNode* child_node = node->GetChild(i);
153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (child_node->is_url())
154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        OpenAllImpl(child_node, initial_disposition, navigator, opened_url);
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ShouldOpenAll(gfx::NativeWindow parent,
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   const std::vector<const BookmarkNode*>& nodes) {
161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int child_count = 0;
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < nodes.size(); ++i)
163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    child_count += ChildURLCount(nodes[i]);
164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (child_count < bookmark_utils::num_urls_before_prompting)
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  string16 message = l10n_util::GetStringFUTF16(
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      IDS_BOOKMARK_BAR_SHOULD_OPEN_ALL,
169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      base::IntToString16(child_count));
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  string16 title = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return platform_util::SimpleYesNoBox(parent, title, message);
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Comparison function that compares based on date modified of the two nodes.
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool MoreRecentlyModified(const BookmarkNode* n1, const BookmarkNode* n2) {
176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return n1->date_folder_modified() > n2->date_folder_modified();
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns true if |text| contains each string in |words|. This is used when
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// searching for bookmarks.
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool DoesBookmarkTextContainWords(const string16& text,
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  const std::vector<string16>& words) {
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < words.size(); ++i) {
1843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (text.find(words[i]) == string16::npos)
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns true if |node|s title or url contains the strings in |words|.
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |languages| argument is user's accept-language setting to decode IDN.
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool DoesBookmarkContainWords(const BookmarkNode* node,
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              const std::vector<string16>& words,
1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                              const std::string& languages) {
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      DoesBookmarkTextContainWords(
1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          l10n_util::ToLower(node->GetTitle()), words) ||
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      DoesBookmarkTextContainWords(
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          l10n_util::ToLower(UTF8ToUTF16(node->GetURL().spec())), words) ||
2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      DoesBookmarkTextContainWords(l10n_util::ToLower(
2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          net::FormatUrl(node->GetURL(), languages, net::kFormatUrlOmitNothing,
2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                         UnescapeRule::NORMAL, NULL, NULL, NULL)), words);
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace bookmark_utils {
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint num_urls_before_prompting = 15;
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint PreferredDropOperation(int source_operations, int operations) {
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int common_ops = (source_operations & operations);
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!common_ops)
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
21572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (ui::DragDropTypes::DRAG_COPY & common_ops)
21672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return ui::DragDropTypes::DRAG_COPY;
21772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (ui::DragDropTypes::DRAG_LINK & common_ops)
21872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return ui::DragDropTypes::DRAG_LINK;
21972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (ui::DragDropTypes::DRAG_MOVE & common_ops)
22072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return ui::DragDropTypes::DRAG_MOVE;
22172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return ui::DragDropTypes::DRAG_NONE;
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint BookmarkDragOperation(Profile* profile, const BookmarkNode* node) {
225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int move = ui::DragDropTypes::DRAG_MOVE;
226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!profile->GetPrefs()->GetBoolean(prefs::kEditBookmarksEnabled))
227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    move = 0;
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (node->is_url()) {
229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_LINK | move;
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return ui::DragDropTypes::DRAG_COPY | move;
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
23472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(TOOLKIT_VIEWS)
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint BookmarkDropOperation(Profile* profile,
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          const views::DropTargetEvent& event,
237201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                          const BookmarkNodeData& data,
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          const BookmarkNode* parent,
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          int index) {
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (data.IsFromProfile(profile) && data.size() > 1)
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Currently only accept one dragged node at a time.
24272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return ui::DragDropTypes::DRAG_NONE;
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!bookmark_utils::IsValidDropLocation(profile, data, parent, index))
24572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return ui::DragDropTypes::DRAG_NONE;
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (data.GetFirstNode(profile)) {
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // User is dragging from this profile: move.
24972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return ui::DragDropTypes::DRAG_MOVE;
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // User is dragging from another app, copy.
25272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return PreferredDropOperation(event.source_operations(),
25372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_LINK);
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
25572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif  // defined(TOOLKIT_VIEWS)
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint PerformBookmarkDrop(Profile* profile,
258201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                        const BookmarkNodeData& data,
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        const BookmarkNode* parent_node,
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        int index) {
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BookmarkModel* model = profile->GetBookmarkModel();
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (data.IsFromProfile(profile)) {
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::vector<const BookmarkNode*> dragged_nodes =
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        data.GetNodes(profile);
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!dragged_nodes.empty()) {
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Drag from same profile. Move nodes.
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      for (size_t i = 0; i < dragged_nodes.size(); ++i) {
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        model->Move(dragged_nodes[i], parent_node, index);
269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        index = parent_node->GetIndexOf(dragged_nodes[i]) + 1;
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
27172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return ui::DragDropTypes::DRAG_MOVE;
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
27372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return ui::DragDropTypes::DRAG_NONE;
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Dropping a folder from different profile. Always accept.
2764a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  bookmark_utils::CloneBookmarkNode(model, data.elements, parent_node, index);
27772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return ui::DragDropTypes::DRAG_COPY;
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool IsValidDropLocation(Profile* profile,
281201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                         const BookmarkNodeData& data,
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         const BookmarkNode* drop_parent,
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         int index) {
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!drop_parent->is_folder()) {
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!data.is_valid())
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (data.IsFromProfile(profile)) {
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<const BookmarkNode*> nodes = data.GetNodes(profile);
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (size_t i = 0; i < nodes.size(); ++i) {
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Don't allow the drop if the user is attempting to drop on one of the
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // nodes being dragged.
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const BookmarkNode* node = nodes[i];
298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      int node_index = (drop_parent == node->parent()) ?
299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          drop_parent->GetIndexOf(nodes[i]) : -1;
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (node_index != -1 && (index == node_index || index == node_index + 1))
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return false;
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // drop_parent can't accept a child that is an ancestor.
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (drop_parent->HasAncestor(node))
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return false;
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // From the same profile, always accept.
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid CloneBookmarkNode(BookmarkModel* model,
314201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                       const std::vector<BookmarkNodeData::Element>& elements,
3154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                       const BookmarkNode* parent,
3164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                       int index_to_add_at) {
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!parent->is_folder() || !model) {
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < elements.size(); ++i)
3224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    CloneBookmarkNodeImpl(model, elements[i], parent, index_to_add_at + i);
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Bookmark dragging
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DragBookmarks(Profile* profile,
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   const std::vector<const BookmarkNode*>& nodes,
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   gfx::NativeView view) {
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!nodes.empty());
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(TOOLKIT_VIEWS)
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Set up our OLE machinery
33472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ui::OSExchangeData data;
335201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  BookmarkNodeData drag_data(nodes);
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  drag_data.Write(profile, &data);
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Allow nested message loop so we get DnD events as we drag this around.
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool was_nested = MessageLoop::current()->IsNested();
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->SetNestableTasksAllowed(true);
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
342dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  views::NativeWidget* native_widget =
343dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      views::NativeWidget::GetNativeWidgetForNativeView(view);
344dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (native_widget) {
345dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    native_widget->GetWidget()->RunShellDrag(NULL, data,
346dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE |
347dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        ui::DragDropTypes::DRAG_LINK);
348dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->SetNestableTasksAllowed(was_nested);
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(OS_MACOSX)
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Allow nested message loop so we get DnD events as we drag this around.
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool was_nested = MessageLoop::current()->IsNested();
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->SetNestableTasksAllowed(true);
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bookmark_pasteboard_helper_mac::StartDrag(profile, nodes, view);
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->SetNestableTasksAllowed(was_nested);
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(TOOLKIT_GTK)
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BookmarkDrag::BeginDrag(profile, nodes);
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid OpenAll(gfx::NativeWindow parent,
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             Profile* profile,
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             PageNavigator* navigator,
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             const std::vector<const BookmarkNode*>& nodes,
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             WindowOpenDisposition initial_disposition) {
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!ShouldOpenAll(parent, nodes))
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NewBrowserPageNavigator navigator_impl(profile);
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!navigator) {
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Browser* browser =
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        BrowserList::FindBrowserWithType(profile, Browser::TYPE_NORMAL, false);
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!browser || !browser->GetSelectedTabContents()) {
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      navigator = &navigator_impl;
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (initial_disposition != NEW_WINDOW &&
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          initial_disposition != OFF_THE_RECORD) {
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        browser->window()->Activate();
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      navigator = browser->GetSelectedTabContents();
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool opened_url = false;
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < nodes.size(); ++i)
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OpenAllImpl(nodes[i], initial_disposition, &navigator, &opened_url);
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid OpenAll(gfx::NativeWindow parent,
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             Profile* profile,
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             PageNavigator* navigator,
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             const BookmarkNode* node,
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             WindowOpenDisposition initial_disposition) {
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<const BookmarkNode*> nodes;
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  nodes.push_back(node);
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  OpenAll(parent, profile, navigator, nodes, initial_disposition);
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CopyToClipboard(BookmarkModel* model,
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     const std::vector<const BookmarkNode*>& nodes,
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     bool remove_nodes) {
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (nodes.empty())
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
406201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  BookmarkNodeData(nodes).WriteToClipboard(NULL);
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (remove_nodes) {
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (size_t i = 0; i < nodes.size(); ++i) {
410ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      int index = nodes[i]->parent()->GetIndexOf(nodes[i]);
411ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (index > -1)
412ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        model->Remove(nodes[i]->parent(), index);
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PasteFromClipboard(BookmarkModel* model,
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        const BookmarkNode* parent,
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        int index) {
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!parent)
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
423201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  BookmarkNodeData bookmark_data;
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!bookmark_data.ReadFromClipboard())
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (index == -1)
428ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    index = parent->child_count();
4294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  bookmark_utils::CloneBookmarkNode(
4304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      model, bookmark_data.elements, parent, index);
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool CanPasteFromClipboard(const BookmarkNode* node) {
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!node)
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
436201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return BookmarkNodeData::ClipboardContainsBookmarks();
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
43972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstring16 GetNameForURL(const GURL& url) {
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (url.is_valid()) {
44172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return net::GetSuggestedFilename(url, "", "", string16());
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
44372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return l10n_util::GetStringUTF16(IDS_APP_UNTITLED_SHORTCUT_FILE_NAME);
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
447ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstd::vector<const BookmarkNode*> GetMostRecentlyModifiedFolders(
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BookmarkModel* model,
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    size_t max_count) {
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<const BookmarkNode*> nodes;
45172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node());
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (iterator.has_next()) {
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* parent = iterator.Next();
454ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (parent->is_folder() && parent->date_folder_modified() > base::Time()) {
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (max_count == 0) {
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        nodes.push_back(parent);
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        std::vector<const BookmarkNode*>::iterator i =
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            std::upper_bound(nodes.begin(), nodes.end(), parent,
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             &MoreRecentlyModified);
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (nodes.size() < max_count || i != nodes.end()) {
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          nodes.insert(i, parent);
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          while (nodes.size() > max_count)
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            nodes.pop_back();
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }  // else case, the root node, which we don't care about or imported nodes
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       // (which have a time of 0).
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (nodes.size() < max_count) {
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Add the bookmark bar and other nodes if there is space.
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (find(nodes.begin(), nodes.end(), model->GetBookmarkBarNode()) ==
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        nodes.end()) {
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      nodes.push_back(model->GetBookmarkBarNode());
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (nodes.size() < max_count &&
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        find(nodes.begin(), nodes.end(), model->other_node()) == nodes.end()) {
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      nodes.push_back(model->other_node());
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return nodes;
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetMostRecentlyAddedEntries(BookmarkModel* model,
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 size_t count,
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 std::vector<const BookmarkNode*>* nodes) {
48972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node());
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (iterator.has_next()) {
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* node = iterator.Next();
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (node->is_url()) {
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      std::vector<const BookmarkNode*>::iterator insert_position =
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          std::upper_bound(nodes->begin(), nodes->end(), node,
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           &MoreRecentlyAdded);
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (nodes->size() < count || insert_position != nodes->end()) {
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        nodes->insert(insert_position, node);
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        while (nodes->size() > count)
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          nodes->pop_back();
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
50572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTitleMatch::TitleMatch()
50672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    : node(NULL) {
50772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
50872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
50972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTitleMatch::~TitleMatch() {}
51072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool MoreRecentlyAdded(const BookmarkNode* n1, const BookmarkNode* n2) {
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return n1->date_added() > n2->date_added();
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetBookmarksContainingText(BookmarkModel* model,
5163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                const string16& text,
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                size_t max_count,
5183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                const std::string& languages,
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                std::vector<const BookmarkNode*>* nodes) {
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<string16> words;
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  QueryParser parser;
5223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  parser.ExtractQueryWords(l10n_util::ToLower(text), &words);
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (words.empty())
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
52672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node());
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (iterator.has_next()) {
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* node = iterator.Next();
529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (node->is_url() && DoesBookmarkContainWords(node, words, languages)) {
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      nodes->push_back(node);
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (nodes->size() == max_count)
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return;
533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool DoesBookmarkContainText(const BookmarkNode* node,
5383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                             const string16& text,
5393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                             const std::string& languages) {
540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<string16> words;
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  QueryParser parser;
5423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  parser.ExtractQueryWords(l10n_util::ToLower(text), &words);
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (words.empty())
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return (node->is_url() && DoesBookmarkContainWords(node, words, languages));
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const BookmarkNode* CreateNewNode(BookmarkModel* model,
550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* parent, const BookmarkEditor::EditDetails& details,
5513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const string16& new_title, const GURL& new_url) {
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const BookmarkNode* node;
553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (details.type == BookmarkEditor::EditDetails::NEW_URL) {
554ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    node = model->AddURL(parent, parent->child_count(), new_title, new_url);
555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (details.type == BookmarkEditor::EditDetails::NEW_FOLDER) {
556ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    node = model->AddFolder(parent, parent->child_count(), new_title);
557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (size_t i = 0; i < details.urls.size(); ++i) {
558ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      model->AddURL(node, node->child_count(), details.urls[i].second,
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    details.urls[i].first);
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
561ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    model->SetDateFolderModified(parent, Time::Now());
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return node;
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
570ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst BookmarkNode* ApplyEditsWithNoFolderChange(BookmarkModel* model,
571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* parent, const BookmarkEditor::EditDetails& details,
5723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const string16& new_title, const GURL& new_url) {
573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (details.type == BookmarkEditor::EditDetails::NEW_URL ||
574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      details.type == BookmarkEditor::EditDetails::NEW_FOLDER) {
575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return CreateNewNode(model, parent, details, new_title, new_url);
576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const BookmarkNode* node = details.existing_node;
579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(node);
580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (node->is_url())
582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    model->SetURL(node, new_url);
583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  model->SetTitle(node, new_title);
584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return node;
586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
588ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst BookmarkNode* ApplyEditsWithPossibleFolderChange(BookmarkModel* model,
589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* new_parent, const BookmarkEditor::EditDetails& details,
5903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const string16& new_title, const GURL& new_url) {
591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (details.type == BookmarkEditor::EditDetails::NEW_URL ||
592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      details.type == BookmarkEditor::EditDetails::NEW_FOLDER) {
593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return CreateNewNode(model, new_parent, details, new_title, new_url);
594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const BookmarkNode* node = details.existing_node;
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(node);
598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
599ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (new_parent != node->parent())
600ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    model->Move(node, new_parent, new_parent->child_count());
601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (node->is_url())
602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    model->SetURL(node, new_url);
603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  model->SetTitle(node, new_title);
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return node;
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Formerly in BookmarkBarView
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ToggleWhenVisible(Profile* profile) {
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PrefService* prefs = profile->GetPrefs();
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const bool always_show = !prefs->GetBoolean(prefs::kShowBookmarkBar);
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The user changed when the bookmark bar is shown, update the preferences.
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  prefs->SetBoolean(prefs::kShowBookmarkBar, always_show);
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  prefs->ScheduleSavePersistentPrefs();
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // And notify the notification service.
618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Source<Profile> source(profile);
619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NotificationService::current()->Notify(
620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NotificationType::BOOKMARK_BAR_VISIBILITY_PREF_CHANGED,
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      source,
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NotificationService::NoDetails());
623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid RegisterUserPrefs(PrefService* prefs) {
626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  prefs->RegisterBooleanPref(prefs::kShowBookmarkBar, false);
627ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  prefs->RegisterBooleanPref(prefs::kEditBookmarksEnabled, true);
628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetURLAndTitleToBookmark(TabContents* tab_contents,
631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              GURL* url,
6323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                              string16* title) {
633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *url = tab_contents->GetURL();
6343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  *title = tab_contents->GetTitle();
635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetURLsForOpenTabs(Browser* browser,
6383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    std::vector<std::pair<GURL, string16> >* urls) {
639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int i = 0; i < browser->tab_count(); ++i) {
6403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    std::pair<GURL, string16> entry;
641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GetURLAndTitleToBookmark(browser->GetTabContentsAt(i), &(entry.first),
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             &(entry.second));
643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    urls->push_back(entry);
644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst BookmarkNode* GetParentForNewNodes(
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* parent,
649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::vector<const BookmarkNode*>& selection,
650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int* index) {
651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const BookmarkNode* real_parent = parent;
652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (selection.size() == 1 && selection[0]->is_folder())
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    real_parent = selection[0];
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (index) {
657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (selection.size() == 1 && selection[0]->is_url()) {
658ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      *index = real_parent->GetIndexOf(selection[0]) + 1;
659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (*index == 0) {
660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // Node doesn't exist in parent, add to end.
661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NOTREACHED();
662ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        *index = real_parent->child_count();
663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
665ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      *index = real_parent->child_count();
666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return real_parent;
670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
672201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool NodeHasURLs(const BookmarkNode* node) {
673201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(node);
674201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
675201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (node->is_url())
676201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return true;
677201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
678ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (int i = 0; i < node->child_count(); ++i) {
679201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (NodeHasURLs(node->GetChild(i)))
680201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      return true;
681201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
682201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return false;
683201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
684201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace bookmark_utils
686