Home | History | Annotate | Download | only in bookmarks
      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, base::string16> >* urls) {
    135   for (int i = 0; i < browser->tab_strip_model()->count(); ++i) {
    136     std::pair<GURL, base::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                               base::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 base::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(Profile* profile,
    277                            chrome::HostDesktopType host_desktop_type) {
    278   // Managed users can not have apps installed currently so there's no need to
    279   // show the apps shortcut.
    280   if (profile->IsManaged())
    281     return false;
    282 
    283   // Don't show the apps shortcut in ash since the app launcher is enabled.
    284   if (host_desktop_type == chrome::HOST_DESKTOP_TYPE_ASH)
    285     return false;
    286 
    287   return chrome::IsInstantExtendedAPIEnabled() && !profile->IsOffTheRecord();
    288 }
    289 
    290 bool ShouldShowAppsShortcutInBookmarkBar(
    291   Profile* profile,
    292   chrome::HostDesktopType host_desktop_type) {
    293   return IsAppsShortcutEnabled(profile, host_desktop_type) &&
    294       profile->GetPrefs()->GetBoolean(prefs::kShowAppsShortcutInBookmarkBar);
    295 }
    296 
    297 }  // namespace chrome
    298