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 "apps/app_launcher.h"
8 #include "base/basictypes.h"
9 #include "base/logging.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "chrome/browser/bookmarks/bookmark_model.h"
13 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/search/search.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 (apps::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