- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / bookmarks / bookmark_utils.cc
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.
4
5 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
6
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"
30
31 namespace chrome {
32
33 int num_bookmark_urls_before_prompting = 15;
34
35 namespace {
36
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
41 // typical usage:
42 // OpenURLIterator iterator(nodes);
43 // while (iterator.has_next()) {
44 //   const GURL* url = iterator.NextURL();
45 //   // do something with |urll|.
46 // }
47 class OpenURLIterator {
48  public:
49   explicit OpenURLIterator(const std::vector<const BookmarkNode*>& nodes)
50       : child_index_(0),
51         next_(NULL),
52         parent_(nodes.begin()),
53         end_(nodes.end()) {
54     FindNext();
55   }
56
57   bool has_next() { return next_ != NULL;}
58
59   const GURL* NextURL() {
60     if (!has_next()) {
61       NOTREACHED();
62       return NULL;
63     }
64
65     const GURL* next = next_;
66     FindNext();
67     return next;
68   }
69
70  private:
71   // Seach next node which has URL.
72   void FindNext() {
73     for (; parent_ < end_; ++parent_, child_index_ = 0) {
74       if ((*parent_)->is_url()) {
75         next_ = &(*parent_)->url();
76         ++parent_;
77         child_index_ = 0;
78         return;
79       } else {
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();
84             ++child_index_;
85             return;
86           }
87         }
88       }
89     }
90     next_ = NULL;
91   }
92
93   int child_index_;
94   const GURL* next_;
95   std::vector<const BookmarkNode*>::const_iterator parent_;
96   const std::vector<const BookmarkNode*>::const_iterator end_;
97
98   DISALLOW_COPY_AND_ASSIGN(OpenURLIterator);
99 };
100
101 bool ShouldOpenAll(gfx::NativeWindow parent,
102                    const std::vector<const BookmarkNode*>& nodes) {
103   int child_count = 0;
104   OpenURLIterator iterator(nodes);
105   while (iterator.has_next()) {
106     iterator.NextURL();
107     child_count++;
108   }
109
110   if (child_count < num_bookmark_urls_before_prompting)
111     return true;
112
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;
118 }
119
120 // Returns the total number of descendants nodes.
121 int ChildURLCountTotal(const BookmarkNode* node) {
122   int result = 0;
123   for (int i = 0; i < node->child_count(); ++i) {
124     const BookmarkNode* child = node->GetChild(i);
125     result++;
126     if (child->is_folder())
127       result += ChildURLCountTotal(child);
128   }
129   return result;
130 }
131
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);
140   }
141 }
142
143 }  // namespace
144
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))
151     return;
152
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
158   // that window.
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
166     // not opened.
167     if (initial_disposition == OFF_THE_RECORD &&
168         !IsURLAllowedInIncognito(*url, browser_context))
169       continue;
170
171     content::WebContents* opened_tab = navigator->OpenURL(
172         content::OpenURLParams(*url, content::Referrer(), disposition,
173                                content::PAGE_TRANSITION_AUTO_BOOKMARK, false));
174
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
180       // be NULL in tests.
181       if (opened_tab)
182         navigator = opened_tab;
183     }
184   }
185 }
186
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);
195 }
196
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;
205 }
206
207 void ShowBookmarkAllTabsDialog(Browser* browser) {
208   Profile* profile = browser->profile();
209   BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile);
210   DCHECK(model && model->loaded());
211
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());
217
218   BookmarkEditor::Show(browser->window()->GetNativeWindow(), profile, details,
219                        BookmarkEditor::SHOW_TREE);
220 }
221
222 bool HasBookmarkURLs(const std::vector<const BookmarkNode*>& selection) {
223   OpenURLIterator iterator(selection);
224   return iterator.has_next();
225 }
226
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))
234       return true;
235   }
236   return false;
237 }
238
239 GURL GetURLToBookmark(content::WebContents* web_contents) {
240   DCHECK(web_contents);
241   return IsInstantNTP(web_contents) ?
242       GURL(kChromeUINewTabURL) : web_contents->GetURL();
243 }
244
245 void GetURLAndTitleToBookmark(content::WebContents* web_contents,
246                               GURL* url,
247                               string16* title) {
248   *url = GetURLToBookmark(web_contents);
249   *title = web_contents->GetTitle();
250 }
251
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);
255
256   // The user changed when the bookmark bar is shown, update the preferences.
257   prefs->SetBoolean(prefs::kShowBookmarkBar, always_show);
258 }
259
260 string16 FormatBookmarkURLForDisplay(const GURL& url,
261                                      const PrefService* prefs) {
262   std::string languages;
263   if (prefs)
264     languages = prefs->GetString(prefs::kAcceptLanguages);
265
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(
271       url, languages,
272       net::kFormatUrlOmitAll & ~net::kFormatUrlOmitUsernamePassword,
273       net::UnescapeRule::SPACES, NULL, NULL, NULL);
274 }
275
276 bool IsAppsShortcutEnabled(const Profile* profile) {
277 #if defined(USE_ASH)
278   // Don't show the apps shortcut in ash when the app launcher is enabled.
279   if (IsAppLauncherEnabled())
280     return false;
281 #endif
282
283   return chrome::IsInstantExtendedAPIEnabled() && !profile->IsOffTheRecord();
284 }
285
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())
290     return false;
291
292   return IsAppsShortcutEnabled(profile) &&
293       profile->GetPrefs()->GetBoolean(prefs::kShowAppsShortcutInBookmarkBar);
294 }
295
296 }  // namespace chrome