1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
7 #include "base/basictypes.h"
8 #include "base/logging.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "chrome/browser/bookmarks/bookmark_model.h"
12 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/search/search.h"
15 #include "chrome/browser/ui/app_list/app_list_util.h"
16 #include "chrome/browser/ui/bookmarks/bookmark_editor.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/browser_navigator.h"
19 #include "chrome/browser/ui/browser_window.h"
20 #include "chrome/browser/ui/simple_message_box.h"
21 #include "chrome/browser/ui/tabs/tab_strip_model.h"
22 #include "chrome/common/pref_names.h"
23 #include "chrome/common/url_constants.h"
24 #include "components/user_prefs/user_prefs.h"
25 #include "content/public/browser/web_contents.h"
26 #include "grit/chromium_strings.h"
27 #include "grit/generated_resources.h"
28 #include "net/base/net_util.h"
29 #include "ui/base/l10n/l10n_util.h"
33 int num_bookmark_urls_before_prompting = 15;
37 // Iterator that iterates through a set of BookmarkNodes returning the URLs
38 // for nodes that are urls, or the URLs for the children of non-url urls.
39 // This does not recurse through all descendants, only immediate children.
40 // The following illustrates
42 // OpenURLIterator iterator(nodes);
43 // while (iterator.has_next()) {
44 // const GURL* url = iterator.NextURL();
45 // // do something with |urll|.
47 class OpenURLIterator {
49 explicit OpenURLIterator(const std::vector<const BookmarkNode*>& nodes)
52 parent_(nodes.begin()),
57 bool has_next() { return next_ != NULL;}
59 const GURL* NextURL() {
65 const GURL* next = next_;
71 // Seach next node which has URL.
73 for (; parent_ < end_; ++parent_, child_index_ = 0) {
74 if ((*parent_)->is_url()) {
75 next_ = &(*parent_)->url();
80 for (; child_index_ < (*parent_)->child_count(); ++child_index_) {
81 const BookmarkNode* child = (*parent_)->GetChild(child_index_);
82 if (child->is_url()) {
83 next_ = &child->url();
95 std::vector<const BookmarkNode*>::const_iterator parent_;
96 const std::vector<const BookmarkNode*>::const_iterator end_;
98 DISALLOW_COPY_AND_ASSIGN(OpenURLIterator);
101 bool ShouldOpenAll(gfx::NativeWindow parent,
102 const std::vector<const BookmarkNode*>& nodes) {
104 OpenURLIterator iterator(nodes);
105 while (iterator.has_next()) {
110 if (child_count < num_bookmark_urls_before_prompting)
113 return ShowMessageBox(parent,
114 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
115 l10n_util::GetStringFUTF16(IDS_BOOKMARK_BAR_SHOULD_OPEN_ALL,
116 base::IntToString16(child_count)),
117 MESSAGE_BOX_TYPE_QUESTION) == MESSAGE_BOX_RESULT_YES;
120 // Returns the total number of descendants nodes.
121 int ChildURLCountTotal(const BookmarkNode* node) {
123 for (int i = 0; i < node->child_count(); ++i) {
124 const BookmarkNode* child = node->GetChild(i);
126 if (child->is_folder())
127 result += ChildURLCountTotal(child);
132 // Returns in |urls|, the url and title pairs for each open tab in browser.
133 void GetURLsForOpenTabs(Browser* browser,
134 std::vector<std::pair<GURL, string16> >* urls) {
135 for (int i = 0; i < browser->tab_strip_model()->count(); ++i) {
136 std::pair<GURL, string16> entry;
137 GetURLAndTitleToBookmark(browser->tab_strip_model()->GetWebContentsAt(i),
138 &(entry.first), &(entry.second));
139 urls->push_back(entry);
145 void OpenAll(gfx::NativeWindow parent,
146 content::PageNavigator* navigator,
147 const std::vector<const BookmarkNode*>& nodes,
148 WindowOpenDisposition initial_disposition,
149 content::BrowserContext* browser_context) {
150 if (!ShouldOpenAll(parent, nodes))
153 // Opens all |nodes| of type URL and any children of |nodes| that are of type
154 // URL. |navigator| is the PageNavigator used to open URLs. After the first
155 // url is opened |opened_first_url| is set to true and |navigator| is set to
156 // the PageNavigator of the last active tab. This is done to handle a window
157 // disposition of new window, in which case we want subsequent tabs to open in
159 bool opened_first_url = false;
160 WindowOpenDisposition disposition = initial_disposition;
161 OpenURLIterator iterator(nodes);
162 while (iterator.has_next()) {
163 const GURL* url = iterator.NextURL();
164 // When |initial_disposition| is OFF_THE_RECORD, a node which can't be
165 // opened in incognito window, it is detected using |browser_context|, is
167 if (initial_disposition == OFF_THE_RECORD &&
168 !IsURLAllowedInIncognito(*url, browser_context))
171 content::WebContents* opened_tab = navigator->OpenURL(
172 content::OpenURLParams(*url, content::Referrer(), disposition,
173 content::PAGE_TRANSITION_AUTO_BOOKMARK, false));
175 if (!opened_first_url) {
176 opened_first_url = true;
177 disposition = NEW_BACKGROUND_TAB;
178 // We opened the first URL which may have opened a new window or clobbered
179 // the current page, reset the navigator just to be sure. |opened_tab| may
182 navigator = opened_tab;
187 void OpenAll(gfx::NativeWindow parent,
188 content::PageNavigator* navigator,
189 const BookmarkNode* node,
190 WindowOpenDisposition initial_disposition,
191 content::BrowserContext* browser_context) {
192 std::vector<const BookmarkNode*> nodes;
193 nodes.push_back(node);
194 OpenAll(parent, navigator, nodes, initial_disposition, browser_context);
197 bool ConfirmDeleteBookmarkNode(const BookmarkNode* node,
198 gfx::NativeWindow window) {
199 DCHECK(node && node->is_folder() && !node->empty());
200 return ShowMessageBox(window,
201 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
202 l10n_util::GetStringFUTF16Int(IDS_BOOKMARK_EDITOR_CONFIRM_DELETE,
203 ChildURLCountTotal(node)),
204 MESSAGE_BOX_TYPE_QUESTION) == MESSAGE_BOX_RESULT_YES;
207 void ShowBookmarkAllTabsDialog(Browser* browser) {
208 Profile* profile = browser->profile();
209 BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile);
210 DCHECK(model && model->loaded());
212 const BookmarkNode* parent = model->GetParentForNewNodes();
213 BookmarkEditor::EditDetails details =
214 BookmarkEditor::EditDetails::AddFolder(parent, parent->child_count());
215 GetURLsForOpenTabs(browser, &(details.urls));
216 DCHECK(!details.urls.empty());
218 BookmarkEditor::Show(browser->window()->GetNativeWindow(), profile, details,
219 BookmarkEditor::SHOW_TREE);
222 bool HasBookmarkURLs(const std::vector<const BookmarkNode*>& selection) {
223 OpenURLIterator iterator(selection);
224 return iterator.has_next();
227 bool HasBookmarkURLsAllowedInIncognitoMode(
228 const std::vector<const BookmarkNode*>& selection,
229 content::BrowserContext* browser_context) {
230 OpenURLIterator iterator(selection);
231 while (iterator.has_next()) {
232 const GURL* url = iterator.NextURL();
233 if (IsURLAllowedInIncognito(*url, browser_context))
239 GURL GetURLToBookmark(content::WebContents* web_contents) {
240 DCHECK(web_contents);
241 return IsInstantNTP(web_contents) ?
242 GURL(kChromeUINewTabURL) : web_contents->GetURL();
245 void GetURLAndTitleToBookmark(content::WebContents* web_contents,
248 *url = GetURLToBookmark(web_contents);
249 *title = web_contents->GetTitle();
252 void ToggleBookmarkBarWhenVisible(content::BrowserContext* browser_context) {
253 PrefService* prefs = user_prefs::UserPrefs::Get(browser_context);
254 const bool always_show = !prefs->GetBoolean(prefs::kShowBookmarkBar);
256 // The user changed when the bookmark bar is shown, update the preferences.
257 prefs->SetBoolean(prefs::kShowBookmarkBar, always_show);
260 string16 FormatBookmarkURLForDisplay(const GURL& url,
261 const PrefService* prefs) {
262 std::string languages;
264 languages = prefs->GetString(prefs::kAcceptLanguages);
266 // Because this gets re-parsed by FixupURL(), it's safe to omit the scheme
267 // and trailing slash, and unescape most characters. However, it's
268 // important not to drop any username/password, or unescape anything that
269 // changes the URL's meaning.
270 return net::FormatUrl(
272 net::kFormatUrlOmitAll & ~net::kFormatUrlOmitUsernamePassword,
273 net::UnescapeRule::SPACES, NULL, NULL, NULL);
276 bool IsAppsShortcutEnabled(const Profile* profile) {
278 // Don't show the apps shortcut in ash when the app launcher is enabled.
279 if (IsAppLauncherEnabled())
283 return chrome::IsInstantExtendedAPIEnabled() && !profile->IsOffTheRecord();
286 bool ShouldShowAppsShortcutInBookmarkBar(Profile* profile) {
287 // Managed users can not have apps installed currently so there's no need to
288 // show the apps shortcut.
289 if (profile->IsManaged())
292 return IsAppsShortcutEnabled(profile) &&
293 profile->GetPrefs()->GetBoolean(prefs::kShowAppsShortcutInBookmarkBar);
296 } // namespace chrome