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)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/bookmarks/bookmarks_api.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/file_util_icu.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/time_formatting.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/lazy_instance.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sha1.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
175e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string16.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
195e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_html_writer.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_model_factory.h"
2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/bookmarks/chrome_bookmark_client.h"
25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/bookmarks/chrome_bookmark_client_factory.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/bookmarks/bookmark_api_constants.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.h"
28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/importer/external_process_importer_host.h"
297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/importer/importer_uma.h"
307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/platform_util.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/chrome_select_file_policy.h"
337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/ui/host_desktop.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_paths.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/api/bookmarks.h"
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/common/importer/importer_data_types.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/grit/generated_resources.h"
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/bookmarks/browser/bookmark_model.h"
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/bookmarks/browser/bookmark_utils.h"
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/user_prefs/user_prefs.h"
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/public/browser/browser_context.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "content/public/browser/web_contents.h"
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/event_router.h"
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/extension_function_dispatcher.h"
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/notification_types.h"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_WIN)
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/aura/remote_window_tree_host_win.h"
527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif
537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace extensions {
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace keys = bookmark_api_constants;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace bookmarks = api::bookmarks;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using bookmarks::BookmarkTreeNode;
600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochusing bookmarks::CreateDetails;
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using content::BrowserContext;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generates a default path (including a default filename) that will be
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// used for pre-populating the "Export Bookmarks" file chooser dialog box.
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetDefaultFilepathForBookmarkExport() {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time time = base::Time::Now();
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Concatenate a date stamp to the filename.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath::StringType filename =
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l10n_util::GetStringFUTF8(IDS_EXPORT_BOOKMARKS_DEFAULT_FILENAME,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                base::TimeFormatShortDateNumeric(time));
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_WIN)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath::StringType filename =
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l10n_util::GetStringFUTF16(IDS_EXPORT_BOOKMARKS_DEFAULT_FILENAME,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 base::TimeFormatShortDateNumeric(time));
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::i18n::ReplaceIllegalCharactersInPath(&filename, '_');
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath default_path;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PathService::Get(chrome::DIR_USER_DOCUMENTS, &default_path);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return default_path.Append(filename);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool BookmarksFunction::RunAsync() {
931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
94b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!model->loaded()) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Bookmarks are not ready yet.  We'll wait.
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    model->AddObserver(this);
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AddRef();  // Balanced in Loaded().
985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return true;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bool success = RunOnReady();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (success) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::NotificationService::current()->Notify(
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        extensions::NOTIFICATION_EXTENSION_BOOKMARKS_API_INVOKED,
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        content::Source<const Extension>(extension()),
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::Details<const BookmarksFunction>(this));
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendResponse(success);
1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return true;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)BookmarkModel* BookmarksFunction::GetBookmarkModel() {
113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return BookmarkModelFactory::GetForProfile(GetProfile());
114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)ChromeBookmarkClient* BookmarksFunction::GetChromeBookmarkClient() {
117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return ChromeBookmarkClientFactory::GetForProfile(GetProfile());
11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
11946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BookmarksFunction::GetBookmarkIdAsInt64(const std::string& id_string,
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             int64* id) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::StringToInt64(id_string, id))
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  error_ = keys::kInvalidIdError;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const BookmarkNode* BookmarksFunction::GetBookmarkNodeFromId(
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& id_string) {
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int64 id;
132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!GetBookmarkIdAsInt64(id_string, &id))
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return NULL;
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const BookmarkNode* node = ::bookmarks::GetBookmarkNodeByID(
1360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      BookmarkModelFactory::GetForProfile(GetProfile()), id);
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!node)
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    error_ = keys::kNoNodeError;
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return node;
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochconst BookmarkNode* BookmarksFunction::CreateBookmarkNode(
1440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    BookmarkModel* model,
1450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const CreateDetails& details,
1460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const BookmarkNode::MetaInfoMap* meta_info) {
1470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  int64 parentId;
1480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!details.parent_id.get()) {
1500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // Optional, default to "other bookmarks".
1510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    parentId = model->other_node()->id();
1520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  } else {
1530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (!GetBookmarkIdAsInt64(*details.parent_id, &parentId))
1540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      return NULL;
1550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const BookmarkNode* parent =
157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      ::bookmarks::GetBookmarkNodeByID(model, parentId);
15846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!CanBeModified(parent))
1590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return NULL;
1600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  int index;
1620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!details.index.get()) {  // Optional (defaults to end).
1630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    index = parent->child_count();
1640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  } else {
1650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    index = *details.index;
1660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (index > parent->child_count() || index < 0) {
1670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      error_ = keys::kInvalidIndexError;
1680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      return NULL;
1690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
1700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
1710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::string16 title;  // Optional.
1730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (details.title.get())
1740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    title = base::UTF8ToUTF16(*details.title.get());
1750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  std::string url_string;  // Optional.
1770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (details.url.get())
1780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    url_string = *details.url.get();
1790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  GURL url(url_string);
1810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!url_string.empty() && !url.is_valid()) {
1820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    error_ = keys::kInvalidUrlError;
1830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return NULL;
1840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
1850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const BookmarkNode* node;
1870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (url_string.length())
1880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    node = model->AddURLWithCreationTimeAndMetaInfo(
1890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        parent, index, title, url, base::Time::Now(), meta_info);
1900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  else
1910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    node = model->AddFolderWithMetaInfo(parent, index, title, meta_info);
1920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK(node);
1930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!node) {
1940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    error_ = keys::kNoNodeError;
1950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return NULL;
1960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
1970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return node;
1990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarksFunction::EditBookmarksEnabled() {
2021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  PrefService* prefs = user_prefs::UserPrefs::Get(GetProfile());
2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (prefs->GetBoolean(::bookmarks::prefs::kEditBookmarksEnabled))
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  error_ = keys::kEditBookmarksDisabled;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool BookmarksFunction::CanBeModified(const BookmarkNode* node) {
21046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!node) {
21146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    error_ = keys::kNoParentError;
21246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return false;
21346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
21446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (node->is_root()) {
21546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    error_ = keys::kModifySpecialError;
21646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return false;
21746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
21846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ChromeBookmarkClient* client = GetChromeBookmarkClient();
21946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (client->IsDescendantOfManagedNode(node)) {
22046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    error_ = keys::kModifyManagedError;
22146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return false;
22246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
22346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return true;
22446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
22546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksFunction::BookmarkModelChanged() {
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BookmarksFunction::BookmarkModelLoaded(BookmarkModel* model,
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                            bool ids_reassigned) {
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  model->RemoveObserver(this);
2325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  RunOnReady();
2335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  Release();  // Balanced in RunOnReady().
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)BookmarkEventRouter::BookmarkEventRouter(Profile* profile)
23746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : browser_context_(profile),
23846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      model_(BookmarkModelFactory::GetForProfile(profile)),
239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      client_(ChromeBookmarkClientFactory::GetForProfile(profile)) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  model_->AddObserver(this);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BookmarkEventRouter::~BookmarkEventRouter() {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (model_) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    model_->RemoveObserver(this);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::DispatchEvent(
2504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const std::string& event_name,
251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<base::ListValue> event_args) {
2520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EventRouter* event_router = EventRouter::Get(browser_context_);
2530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (event_router) {
2540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    event_router->BroadcastEvent(
2550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        make_scoped_ptr(new extensions::Event(event_name, event_args.Pass())));
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BookmarkEventRouter::BookmarkModelLoaded(BookmarkModel* model,
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                              bool ids_reassigned) {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(erikkay): Perhaps we should send this event down to the extension
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so they know when it's safe to use the API?
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::BookmarkModelBeingDeleted(BookmarkModel* model) {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  model_ = NULL;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::BookmarkNodeMoved(BookmarkModel* model,
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            const BookmarkNode* old_parent,
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            int old_index,
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            const BookmarkNode* new_parent,
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            int new_index) {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BookmarkNode* node = new_parent->GetChild(new_index);
275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bookmarks::OnMoved::MoveInfo move_info;
276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  move_info.parent_id = base::Int64ToString(new_parent->id());
277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  move_info.index = new_index;
278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  move_info.old_parent_id = base::Int64ToString(old_parent->id());
279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  move_info.old_index = old_index;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DispatchEvent(
282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      bookmarks::OnMoved::kEventName,
283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      bookmarks::OnMoved::Create(base::Int64ToString(node->id()), move_info));
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::BookmarkNodeAdded(BookmarkModel* model,
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            const BookmarkNode* parent,
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            int index) {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BookmarkNode* node = parent->GetChild(index);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<BookmarkTreeNode> tree_node(
29146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      bookmark_api_helpers::GetBookmarkTreeNode(client_, node, false, false));
292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DispatchEvent(bookmarks::OnCreated::kEventName,
293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                bookmarks::OnCreated::Create(base::Int64ToString(node->id()),
294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                             *tree_node));
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
297010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void BookmarkEventRouter::BookmarkNodeRemoved(
298010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    BookmarkModel* model,
299010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const BookmarkNode* parent,
300010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int index,
301010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const BookmarkNode* node,
302010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::set<GURL>& removed_urls) {
303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bookmarks::OnRemoved::RemoveInfo remove_info;
304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  remove_info.parent_id = base::Int64ToString(parent->id());
305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  remove_info.index = index;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DispatchEvent(bookmarks::OnRemoved::kEventName,
308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                bookmarks::OnRemoved::Create(base::Int64ToString(node->id()),
309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                             remove_info));
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void BookmarkEventRouter::BookmarkAllUserNodesRemoved(
313010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    BookmarkModel* model,
314010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::set<GURL>& removed_urls) {
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NOTREACHED();
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(shashishekhar) Currently this notification is only used on Android,
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // which does not support extensions. If Desktop needs to support this, add
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // a new event to the extensions api.
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::BookmarkNodeChanged(BookmarkModel* model,
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                              const BookmarkNode* node) {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(erikkay) The only three things that BookmarkModel sends this
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // notification for are title, url and favicon.  Since we're currently
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ignoring favicon and since the notification doesn't say which one anyway,
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for now we only include title and url.  The ideal thing would be to change
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // BookmarkModel to indicate what changed.
328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bookmarks::OnChanged::ChangeInfo change_info;
329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  change_info.title = base::UTF16ToUTF8(node->GetTitle());
330e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (node->is_url())
331e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    change_info.url.reset(new std::string(node->url().spec()));
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DispatchEvent(bookmarks::OnChanged::kEventName,
334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                bookmarks::OnChanged::Create(base::Int64ToString(node->id()),
335a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                             change_info));
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::BookmarkNodeFaviconChanged(BookmarkModel* model,
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                     const BookmarkNode* node) {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(erikkay) anything we should do here?
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::BookmarkNodeChildrenReordered(
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BookmarkModel* model,
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const BookmarkNode* node) {
346a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bookmarks::OnChildrenReordered::ReorderInfo reorder_info;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int childCount = node->child_count();
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < childCount; ++i) {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BookmarkNode* child = node->GetChild(i);
350a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    reorder_info.child_ids.push_back(base::Int64ToString(child->id()));
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
353a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DispatchEvent(bookmarks::OnChildrenReordered::kEventName,
354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                bookmarks::OnChildrenReordered::Create(
355a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    base::Int64ToString(node->id()), reorder_info));
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::ExtensiveBookmarkChangesBeginning(
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BookmarkModel* model) {
360a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DispatchEvent(bookmarks::OnImportBegan::kEventName,
361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                bookmarks::OnImportBegan::Create());
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::ExtensiveBookmarkChangesEnded(BookmarkModel* model) {
365a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DispatchEvent(bookmarks::OnImportEnded::kEventName,
366a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                bookmarks::OnImportEnded::Create());
367a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
368a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
369a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BookmarksAPI::BookmarksAPI(BrowserContext* context)
370a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : browser_context_(context) {
3710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EventRouter* event_router = EventRouter::Get(browser_context_);
372a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  event_router->RegisterObserver(this, bookmarks::OnCreated::kEventName);
373a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  event_router->RegisterObserver(this, bookmarks::OnRemoved::kEventName);
374a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  event_router->RegisterObserver(this, bookmarks::OnChanged::kEventName);
375a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  event_router->RegisterObserver(this, bookmarks::OnMoved::kEventName);
376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  event_router->RegisterObserver(this,
377a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 bookmarks::OnChildrenReordered::kEventName);
378a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  event_router->RegisterObserver(this, bookmarks::OnImportBegan::kEventName);
379a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  event_router->RegisterObserver(this, bookmarks::OnImportEnded::kEventName);
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BookmarksAPI::~BookmarksAPI() {
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksAPI::Shutdown() {
3860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EventRouter::Get(browser_context_)->UnregisterObserver(this);
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
389a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static base::LazyInstance<BrowserContextKeyedAPIFactory<BookmarksAPI> >
390a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    g_factory = LAZY_INSTANCE_INITIALIZER;
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
393a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BrowserContextKeyedAPIFactory<BookmarksAPI>*
394a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BookmarksAPI::GetFactoryInstance() {
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return g_factory.Pointer();
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksAPI::OnListenerAdded(const EventListenerInfo& details) {
39946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  bookmark_event_router_.reset(
40046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      new BookmarkEventRouter(Profile::FromBrowserContext(browser_context_)));
4010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EventRouter::Get(browser_context_)->UnregisterObserver(this);
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksGetFunction::RunOnReady() {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<bookmarks::Get::Params> params(
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks::Get::Params::Create(*args_));
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<linked_ptr<BookmarkTreeNode> > nodes;
41046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ChromeBookmarkClient* client = GetChromeBookmarkClient();
4117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (params->id_or_id_list.as_strings) {
4127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    std::vector<std::string>& ids = *params->id_or_id_list.as_strings;
4137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    size_t count = ids.size();
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXTENSION_FUNCTION_VALIDATE(count > 0);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < count; ++i) {
416f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      const BookmarkNode* node = GetBookmarkNodeFromId(ids[i]);
417f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (!node)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
41946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      bookmark_api_helpers::AddNode(client, node, &nodes, false);
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
422f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const BookmarkNode* node =
423f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        GetBookmarkNodeFromId(*params->id_or_id_list.as_string);
424f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!node)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
42646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    bookmark_api_helpers::AddNode(client, node, &nodes, false);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results_ = bookmarks::Get::Results::Create(nodes);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksGetChildrenFunction::RunOnReady() {
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<bookmarks::GetChildren::Params> params(
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks::GetChildren::Params::Create(*args_));
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
438f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const BookmarkNode* node = GetBookmarkNodeFromId(params->id);
439f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!node)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<linked_ptr<BookmarkTreeNode> > nodes;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int child_count = node->child_count();
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < child_count; ++i) {
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BookmarkNode* child = node->GetChild(i);
44646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    bookmark_api_helpers::AddNode(
44746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        GetChromeBookmarkClient(), child, &nodes, false);
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results_ = bookmarks::GetChildren::Results::Create(nodes);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksGetRecentFunction::RunOnReady() {
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<bookmarks::GetRecent::Params> params(
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks::GetRecent::Params::Create(*args_));
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (params->number_of_items < 1)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const BookmarkNode*> nodes;
462116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ::bookmarks::GetMostRecentlyAddedEntries(
4631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      BookmarkModelFactory::GetForProfile(GetProfile()),
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      params->number_of_items,
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &nodes);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<linked_ptr<BookmarkTreeNode> > tree_nodes;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const BookmarkNode*>::iterator i = nodes.begin();
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; i != nodes.end(); ++i) {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BookmarkNode* node = *i;
47146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    bookmark_api_helpers::AddNode(
47246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        GetChromeBookmarkClient(), node, &tree_nodes, false);
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results_ = bookmarks::GetRecent::Results::Create(tree_nodes);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksGetTreeFunction::RunOnReady() {
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<linked_ptr<BookmarkTreeNode> > nodes;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BookmarkNode* node =
4821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      BookmarkModelFactory::GetForProfile(GetProfile())->root_node();
48346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  bookmark_api_helpers::AddNode(GetChromeBookmarkClient(), node, &nodes, true);
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results_ = bookmarks::GetTree::Results::Create(nodes);
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksGetSubTreeFunction::RunOnReady() {
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<bookmarks::GetSubTree::Params> params(
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks::GetSubTree::Params::Create(*args_));
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
493f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const BookmarkNode* node = GetBookmarkNodeFromId(params->id);
494f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!node)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<linked_ptr<BookmarkTreeNode> > nodes;
49846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  bookmark_api_helpers::AddNode(GetChromeBookmarkClient(), node, &nodes, true);
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results_ = bookmarks::GetSubTree::Results::Create(nodes);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksSearchFunction::RunOnReady() {
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<bookmarks::Search::Params> params(
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks::Search::Params::Create(*args_));
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  PrefService* prefs = user_prefs::UserPrefs::Get(GetProfile());
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string lang = prefs->GetString(prefs::kAcceptLanguages);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const BookmarkNode*> nodes;
5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (params->query.as_string) {
512116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ::bookmarks::QueryFields query;
5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    query.word_phrase_query.reset(
5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        new base::string16(base::UTF8ToUTF16(*params->query.as_string)));
515116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ::bookmarks::GetBookmarksMatchingProperties(
5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        BookmarkModelFactory::GetForProfile(GetProfile()),
5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        query,
5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        std::numeric_limits<int>::max(),
5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        lang,
5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        &nodes);
5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(params->query.as_object);
5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const bookmarks::Search::Params::Query::Object& object =
5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        *params->query.as_object;
525116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ::bookmarks::QueryFields query;
5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (object.query) {
5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      query.word_phrase_query.reset(
5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          new base::string16(base::UTF8ToUTF16(*object.query)));
5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (object.url)
5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      query.url.reset(new base::string16(base::UTF8ToUTF16(*object.url)));
5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (object.title)
5335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      query.title.reset(new base::string16(base::UTF8ToUTF16(*object.title)));
534116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ::bookmarks::GetBookmarksMatchingProperties(
5355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        BookmarkModelFactory::GetForProfile(GetProfile()),
5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        query,
5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        std::numeric_limits<int>::max(),
5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        lang,
5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        &nodes);
5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<linked_ptr<BookmarkTreeNode> > tree_nodes;
54346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ChromeBookmarkClient* client = GetChromeBookmarkClient();
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<const BookmarkNode*>::iterator node_iter = nodes.begin();
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       node_iter != nodes.end(); ++node_iter) {
54646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    bookmark_api_helpers::AddNode(client, *node_iter, &tree_nodes, false);
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results_ = bookmarks::Search::Results::Create(tree_nodes);
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool BookmarksRemoveFunction::ExtractIds(const base::ListValue* args,
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         std::list<int64>* ids,
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         bool* invalid_id) {
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string id_string;
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!args->GetString(0, &id_string))
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 id;
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::StringToInt64(id_string, &id))
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ids->push_back(id);
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *invalid_id = true;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksRemoveFunction::RunOnReady() {
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!EditBookmarksEnabled())
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<bookmarks::Remove::Params> params(
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks::Remove::Params::Create(*args_));
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 id;
577f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!GetBookmarkIdAsInt64(params->id, &id))
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool recursive = false;
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (name() == BookmarksRemoveTreeFunction::function_name())
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    recursive = true;
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
584f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  BookmarkModel* model = GetBookmarkModel();
58546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ChromeBookmarkClient* client = GetChromeBookmarkClient();
586f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!bookmark_api_helpers::RemoveNode(model, client, id, recursive, &error_))
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksCreateFunction::RunOnReady() {
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!EditBookmarksEnabled())
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<bookmarks::Create::Params> params(
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks::Create::Params::Create(*args_));
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
6010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const BookmarkNode* node = CreateBookmarkNode(model, params->bookmark, NULL);
6020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!node)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
60546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<BookmarkTreeNode> ret(bookmark_api_helpers::GetBookmarkTreeNode(
60646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      GetChromeBookmarkClient(), node, false, false));
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results_ = bookmarks::Create::Results::Create(*ret);
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
613eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool BookmarksMoveFunction::ExtractIds(const base::ListValue* args,
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       std::list<int64>* ids,
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       bool* invalid_id) {
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For now, Move accepts ID parameters in the same way as an Update.
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return BookmarksUpdateFunction::ExtractIds(args, ids, invalid_id);
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksMoveFunction::RunOnReady() {
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!EditBookmarksEnabled())
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<bookmarks::Move::Params> params(
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks::Move::Params::Create(*args_));
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
628f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const BookmarkNode* node = GetBookmarkNodeFromId(params->id);
629f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!node)
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (model->is_permanent_node(node)) {
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = keys::kModifySpecialError;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BookmarkNode* parent = NULL;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!params->destination.parent_id.get()) {
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Optional, defaults to current parent.
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parent = node->parent();
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 parentId;
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!GetBookmarkIdAsInt64(*params->destination.parent_id, &parentId))
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
647116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    parent = ::bookmarks::GetBookmarkNodeByID(model, parentId);
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
64946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!CanBeModified(parent) || !CanBeModified(node))
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int index;
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (params->destination.index.get()) {  // Optional (defaults to end).
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    index = *params->destination.index;
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (index > parent->child_count() || index < 0) {
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error_ = keys::kInvalidIndexError;
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    index = parent->child_count();
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  model->Move(node, parent, index);
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<BookmarkTreeNode> tree_node(
66646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      bookmark_api_helpers::GetBookmarkTreeNode(
66746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          GetChromeBookmarkClient(), node, false, false));
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results_ = bookmarks::Move::Results::Create(*tree_node);
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool BookmarksUpdateFunction::ExtractIds(const base::ListValue* args,
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         std::list<int64>* ids,
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         bool* invalid_id) {
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For now, Update accepts ID parameters in the same way as an Remove.
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return BookmarksRemoveFunction::ExtractIds(args, ids, invalid_id);
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksUpdateFunction::RunOnReady() {
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!EditBookmarksEnabled())
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<bookmarks::Update::Params> params(
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks::Update::Params::Create(*args_));
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Optional but we need to distinguish non present from an empty title.
690a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 title;
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool has_title = false;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (params->changes.title.get()) {
6935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    title = base::UTF8ToUTF16(*params->changes.title);
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_title = true;
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Optional.
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (params->changes.url.get())
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    url_string = *params->changes.url;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(url_string);
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!url_string.empty() && !url.is_valid()) {
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = keys::kInvalidUrlError;
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
707f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const BookmarkNode* node = GetBookmarkNodeFromId(params->id);
70846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!CanBeModified(node))
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
710f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
711f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (model->is_permanent_node(node)) {
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = keys::kModifySpecialError;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_title)
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    model->SetTitle(node, title);
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!url.is_empty())
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    model->SetURL(node, url);
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<BookmarkTreeNode> tree_node(
72246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      bookmark_api_helpers::GetBookmarkTreeNode(
72346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          GetChromeBookmarkClient(), node, false, false));
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results_ = bookmarks::Update::Results::Create(*tree_node);
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarksIOFunction::BookmarksIOFunction() {}
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarksIOFunction::~BookmarksIOFunction() {
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There may be pending file dialogs, we need to tell them that we've gone
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // away so they don't try and call back to us.
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (select_file_dialog_.get())
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    select_file_dialog_->ListenerDestroyed();
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarksIOFunction::SelectFile(ui::SelectFileDialog::Type type) {
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GetDefaultFilepathForBookmarkExport() might have to touch the filesystem
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (stat or access, for example), so this requires a thread with IO allowed.
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&BookmarksIOFunction::SelectFile, this, type));
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pre-populating the filename field in case this is a SELECT_SAVEAS_FILE
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dialog. If not, there is no filename field in the dialog box.
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath default_path;
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == ui::SelectFileDialog::SELECT_SAVEAS_FILE)
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default_path = GetDefaultFilepathForBookmarkExport();
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(type == ui::SelectFileDialog::SELECT_OPEN_FILE);
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // After getting the |default_path|, ask the UI to display the file dialog.
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BookmarksIOFunction::ShowSelectFileDialog, this,
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 type, default_path));
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksIOFunction::ShowSelectFileDialog(
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ui::SelectFileDialog::Type type,
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& default_path) {
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!dispatcher())
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;  // Extension was unloaded.
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Balanced in one of the three callbacks of SelectFileDialog:
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // either FileSelectionCanceled, MultiFilesSelected, or FileSelected
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddRef();
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebContents* web_contents = dispatcher()->delegate()->
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetAssociatedWebContents();
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  select_file_dialog_ = ui::SelectFileDialog::Create(
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this, new ChromeSelectFilePolicy(web_contents));
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::SelectFileDialog::FileTypeInfo file_type_info;
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_type_info.extensions.resize(1);
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("html"));
7787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::NativeWindow owning_window = web_contents ?
779010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      platform_util::GetTopLevel(web_contents->GetNativeView())
7807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          : NULL;
7815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_WIN)
7827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!owning_window &&
7837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      chrome::GetActiveDesktop() == chrome::HOST_DESKTOP_TYPE_ASH)
7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    owning_window = aura::RemoteWindowTreeHostWin::Instance()->GetAshWindow();
7857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |web_contents| can be NULL (for background pages), which is fine. In such
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a case if file-selection dialogs are forbidden by policy, we will not
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // show an InfoBar, which is better than letting one appear out of the blue.
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  select_file_dialog_->SelectFile(type,
790a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                  base::string16(),
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  default_path,
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  &file_type_info,
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  0,
794c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  base::FilePath::StringType(),
7957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                  owning_window,
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  NULL);
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarksIOFunction::FileSelectionCanceled(void* params) {
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Release();  // Balanced in BookmarksIOFunction::SelectFile()
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarksIOFunction::MultiFilesSelected(
8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<base::FilePath>& files, void* params) {
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Release();  // Balanced in BookmarsIOFunction::SelectFile()
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "Should not be able to select multiple files";
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksImportFunction::RunOnReady() {
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!EditBookmarksEnabled())
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectFile(ui::SelectFileDialog::SELECT_OPEN_FILE);
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksImportFunction::FileSelected(const base::FilePath& path,
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           int index,
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           void* params) {
819c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Deletes itself.
820eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ExternalProcessImporterHost* importer_host = new ExternalProcessImporterHost;
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  importer::SourceProfile source_profile;
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source_profile.importer_type = importer::TYPE_BOOKMARKS_FILE;
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source_profile.source_path = path;
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  importer_host->StartImportSettings(source_profile,
8251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                     GetProfile(),
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     importer::FAVORITES,
8271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                     new ProfileWriter(GetProfile()));
828c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
829c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  importer::LogImporterUseToMetrics("BookmarksAPI",
830c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                    importer::TYPE_BOOKMARKS_FILE);
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Release();  // Balanced in BookmarksIOFunction::SelectFile()
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksExportFunction::RunOnReady() {
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE);
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksExportFunction::FileSelected(const base::FilePath& path,
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           int index,
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           void* params) {
8421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bookmark_html_writer::WriteBookmarks(GetProfile(), path, NULL);
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Release();  // Balanced in BookmarksIOFunction::SelectFile()
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace extensions
847