15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/basictypes.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_model_factory.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/extensions/api/commands/command_service.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/search/search.h"
151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/ui/app_list/app_list_util.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/ui/bookmarks/bookmark_editor.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser_navigator.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_window.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/simple_message_box.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/pref_names.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/url_constants.h"
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/grit/chromium_strings.h"
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/grit/generated_resources.h"
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/bookmarks/browser/bookmark_model.h"
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/search/search.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/user_prefs/user_prefs.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_util.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(ENABLE_EXTENSIONS)
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/extension_registry.h"
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/common/extension_set.h"
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chrome {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int num_bookmark_urls_before_prompting = 15;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// The ways in which extensions may customize the bookmark shortcut.
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)enum BookmarkShortcutDisposition {
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  BOOKMARK_SHORTCUT_DISPOSITION_UNCHANGED,
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  BOOKMARK_SHORTCUT_DISPOSITION_REMOVED,
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  BOOKMARK_SHORTCUT_DISPOSITION_OVERRIDDEN
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Iterator that iterates through a set of BookmarkNodes returning the URLs
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// for nodes that are urls, or the URLs for the children of non-url urls.
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This does not recurse through all descendants, only immediate children.
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The following illustrates
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// typical usage:
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// OpenURLIterator iterator(nodes);
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// while (iterator.has_next()) {
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//   const GURL* url = iterator.NextURL();
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//   // do something with |urll|.
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// }
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class OpenURLIterator {
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit OpenURLIterator(const std::vector<const BookmarkNode*>& nodes)
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : child_index_(0),
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        next_(NULL),
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        parent_(nodes.begin()),
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        end_(nodes.end()) {
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FindNext();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool has_next() { return next_ != NULL;}
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const GURL* NextURL() {
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!has_next()) {
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED();
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return NULL;
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL* next = next_;
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FindNext();
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return next;
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Seach next node which has URL.
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void FindNext() {
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (; parent_ < end_; ++parent_, child_index_ = 0) {
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if ((*parent_)->is_url()) {
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        next_ = &(*parent_)->url();
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ++parent_;
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        child_index_ = 0;
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return;
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        for (; child_index_ < (*parent_)->child_count(); ++child_index_) {
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          const BookmarkNode* child = (*parent_)->GetChild(child_index_);
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (child->is_url()) {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            next_ = &child->url();
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            ++child_index_;
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    next_ = NULL;
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int child_index_;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const GURL* next_;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<const BookmarkNode*>::const_iterator parent_;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::vector<const BookmarkNode*>::const_iterator end_;
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OpenURLIterator);
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ShouldOpenAll(gfx::NativeWindow parent,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   const std::vector<const BookmarkNode*>& nodes) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int child_count = 0;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OpenURLIterator iterator(nodes);
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (iterator.has_next()) {
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    iterator.NextURL();
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    child_count++;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (child_count < num_bookmark_urls_before_prompting)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ShowMessageBox(parent,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l10n_util::GetStringFUTF16(IDS_BOOKMARK_BAR_SHOULD_OPEN_ALL,
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 base::IntToString16(child_count)),
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MESSAGE_BOX_TYPE_QUESTION) == MESSAGE_BOX_RESULT_YES;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the total number of descendants nodes.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ChildURLCountTotal(const BookmarkNode* node) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = 0;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < node->child_count(); ++i) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BookmarkNode* child = node->GetChild(i);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result++;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (child->is_folder())
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result += ChildURLCountTotal(child);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns in |urls|, the url and title pairs for each open tab in browser.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetURLsForOpenTabs(Browser* browser,
148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                        std::vector<std::pair<GURL, base::string16> >* urls) {
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < browser->tab_strip_model()->count(); ++i) {
150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    std::pair<GURL, base::string16> entry;
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GetURLAndTitleToBookmark(browser->tab_strip_model()->GetWebContentsAt(i),
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             &(entry.first), &(entry.second));
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    urls->push_back(entry);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Indicates how the bookmark shortcut has been changed by extensions associated
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// with |profile|, if at all.
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BookmarkShortcutDisposition GetBookmarkShortcutDisposition(Profile* profile) {
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(ENABLE_EXTENSIONS)
161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  extensions::CommandService* command_service =
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      extensions::CommandService::Get(profile);
163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  extensions::ExtensionRegistry* registry =
165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      extensions::ExtensionRegistry::Get(profile);
166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!registry)
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return BOOKMARK_SHORTCUT_DISPOSITION_UNCHANGED;
168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const extensions::ExtensionSet& extension_set =
170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      registry->enabled_extensions();
171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // This flag tracks whether any extension wants the disposition to be
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // removed.
174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool removed = false;
175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (extensions::ExtensionSet::const_iterator i = extension_set.begin();
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       i != extension_set.end();
177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       ++i) {
178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Use the overridden disposition if any extension wants it.
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (command_service->OverridesBookmarkShortcut(i->get()))
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return BOOKMARK_SHORTCUT_DISPOSITION_OVERRIDDEN;
181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!removed &&
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        extensions::CommandService::RemovesBookmarkShortcut(i->get())) {
184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      removed = true;
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (removed)
189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return BOOKMARK_SHORTCUT_DISPOSITION_REMOVED;
1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return BOOKMARK_SHORTCUT_DISPOSITION_UNCHANGED;
192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenAll(gfx::NativeWindow parent,
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             content::PageNavigator* navigator,
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             const std::vector<const BookmarkNode*>& nodes,
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             WindowOpenDisposition initial_disposition,
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             content::BrowserContext* browser_context) {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ShouldOpenAll(parent, nodes))
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Opens all |nodes| of type URL and any children of |nodes| that are of type
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // URL. |navigator| is the PageNavigator used to open URLs. After the first
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // url is opened |opened_first_url| is set to true and |navigator| is set to
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the PageNavigator of the last active tab. This is done to handle a window
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // disposition of new window, in which case we want subsequent tabs to open in
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // that window.
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool opened_first_url = false;
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WindowOpenDisposition disposition = initial_disposition;
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OpenURLIterator iterator(nodes);
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (iterator.has_next()) {
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL* url = iterator.NextURL();
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // When |initial_disposition| is OFF_THE_RECORD, a node which can't be
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // opened in incognito window, it is detected using |browser_context|, is
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // not opened.
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (initial_disposition == OFF_THE_RECORD &&
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        !IsURLAllowedInIncognito(*url, browser_context))
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::WebContents* opened_tab = navigator->OpenURL(
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        content::OpenURLParams(*url, content::Referrer(), disposition,
2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               ui::PAGE_TRANSITION_AUTO_BOOKMARK, false));
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!opened_first_url) {
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      opened_first_url = true;
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      disposition = NEW_BACKGROUND_TAB;
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // We opened the first URL which may have opened a new window or clobbered
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // the current page, reset the navigator just to be sure. |opened_tab| may
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // be NULL in tests.
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (opened_tab)
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        navigator = opened_tab;
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OpenAll(gfx::NativeWindow parent,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             content::PageNavigator* navigator,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             const BookmarkNode* node,
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             WindowOpenDisposition initial_disposition,
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             content::BrowserContext* browser_context) {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const BookmarkNode*> nodes;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nodes.push_back(node);
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OpenAll(parent, navigator, nodes, initial_disposition, browser_context);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ConfirmDeleteBookmarkNode(const BookmarkNode* node,
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               gfx::NativeWindow window) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(node && node->is_folder() && !node->empty());
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ShowMessageBox(window,
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l10n_util::GetStringFUTF16Int(IDS_BOOKMARK_EDITOR_CONFIRM_DELETE,
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    ChildURLCountTotal(node)),
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MESSAGE_BOX_TYPE_QUESTION) == MESSAGE_BOX_RESULT_YES;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ShowBookmarkAllTabsDialog(Browser* browser) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile = browser->profile();
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile);
261b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(model && model->loaded());
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const BookmarkNode* parent = model->GetParentForNewNodes();
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BookmarkEditor::EditDetails details =
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      BookmarkEditor::EditDetails::AddFolder(parent, parent->child_count());
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetURLsForOpenTabs(browser, &(details.urls));
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!details.urls.empty());
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BookmarkEditor::Show(browser->window()->GetNativeWindow(), profile, details,
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       BookmarkEditor::SHOW_TREE);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HasBookmarkURLs(const std::vector<const BookmarkNode*>& selection) {
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OpenURLIterator iterator(selection);
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return iterator.has_next();
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool HasBookmarkURLsAllowedInIncognitoMode(
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<const BookmarkNode*>& selection,
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::BrowserContext* browser_context) {
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OpenURLIterator iterator(selection);
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (iterator.has_next()) {
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL* url = iterator.NextURL();
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (IsURLAllowedInIncognito(*url, browser_context))
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL GetURLToBookmark(content::WebContents* web_contents) {
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(web_contents);
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return IsInstantNTP(web_contents) ?
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GURL(kChromeUINewTabURL) : web_contents->GetURL();
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetURLAndTitleToBookmark(content::WebContents* web_contents,
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              GURL* url,
298a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                              base::string16* title) {
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *url = GetURLToBookmark(web_contents);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *title = web_contents->GetTitle();
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ToggleBookmarkBarWhenVisible(content::BrowserContext* browser_context) {
3045e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  PrefService* prefs = user_prefs::UserPrefs::Get(browser_context);
3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const bool always_show =
3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      !prefs->GetBoolean(bookmarks::prefs::kShowBookmarkBar);
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The user changed when the bookmark bar is shown, update the preferences.
3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  prefs->SetBoolean(bookmarks::prefs::kShowBookmarkBar, always_show);
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 FormatBookmarkURLForDisplay(const GURL& url,
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                           const PrefService* prefs) {
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string languages;
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (prefs)
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    languages = prefs->GetString(prefs::kAcceptLanguages);
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Because this gets re-parsed by FixupURL(), it's safe to omit the scheme
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // and trailing slash, and unescape most characters.  However, it's
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // important not to drop any username/password, or unescape anything that
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // changes the URL's meaning.
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return net::FormatUrl(
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url, languages,
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net::kFormatUrlOmitAll & ~net::kFormatUrlOmitUsernamePassword,
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net::UnescapeRule::SPACES, NULL, NULL, NULL);
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool IsAppsShortcutEnabled(Profile* profile,
329f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                           chrome::HostDesktopType host_desktop_type) {
330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Supervised users can not have apps installed currently so there's no need
331f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // to show the apps shortcut.
332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (profile->IsSupervised())
3337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return false;
3347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Don't show the apps shortcut in ash since the app launcher is enabled.
336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (host_desktop_type == chrome::HOST_DESKTOP_TYPE_ASH)
337f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return false;
338f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
339f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return chrome::IsInstantExtendedAPIEnabled() && !profile->IsOffTheRecord();
340f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
341f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool ShouldShowAppsShortcutInBookmarkBar(
343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Profile* profile,
344f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  chrome::HostDesktopType host_desktop_type) {
345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return IsAppsShortcutEnabled(profile, host_desktop_type) &&
3461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci         profile->GetPrefs()->GetBoolean(
3471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci             bookmarks::prefs::kShowAppsShortcutInBookmarkBar);
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
350a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ShouldRemoveBookmarkThisPageUI(Profile* profile) {
351a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return GetBookmarkShortcutDisposition(profile) ==
352a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)         BOOKMARK_SHORTCUT_DISPOSITION_REMOVED;
353a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
355effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool ShouldRemoveBookmarkOpenPagesUI(Profile* profile) {
3561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(ENABLE_EXTENSIONS)
357effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  extensions::ExtensionRegistry* registry =
358effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      extensions::ExtensionRegistry::Get(profile);
359effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!registry)
360effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return false;
361effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
362effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const extensions::ExtensionSet& extension_set =
363effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      registry->enabled_extensions();
364effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
365effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  for (extensions::ExtensionSet::const_iterator i = extension_set.begin();
366effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch       i != extension_set.end();
367effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch       ++i) {
3681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (extensions::CommandService::RemovesBookmarkOpenPagesShortcut(i->get()))
369effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      return true;
370effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
372effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
373effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return false;
374effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
375effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chrome
377