bookmarks_api.cc revision 010d83a9304c5a91596085d917d248abff47903a
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"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/lazy_instance.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sha1.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
185e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string16.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
205e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_html_writer.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_model_factory.h"
257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.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"
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "components/bookmarks/core/browser/bookmark_model.h"
395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "components/bookmarks/core/browser/bookmark_utils.h"
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/user_prefs/user_prefs.h"
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/public/browser/browser_context.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "content/public/browser/web_contents.h"
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/event_router.h"
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/extension_function_dispatcher.h"
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/quota_service.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.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 base::TimeDelta;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using bookmarks::BookmarkTreeNode;
610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochusing bookmarks::CreateDetails;
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using content::BrowserContext;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef QuotaLimitHeuristic::Bucket Bucket;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef QuotaLimitHeuristic::Config Config;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef QuotaLimitHeuristic::BucketList BucketList;
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)typedef QuotaService::TimedLimit TimedLimit;
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)typedef QuotaService::SustainedLimit SustainedLimit;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef QuotaLimitHeuristic::BucketMapper BucketMapper;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generates a default path (including a default filename) that will be
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// used for pre-populating the "Export Bookmarks" file chooser dialog box.
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetDefaultFilepathForBookmarkExport() {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Time time = base::Time::Now();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Concatenate a date stamp to the filename.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath::StringType filename =
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l10n_util::GetStringFUTF8(IDS_EXPORT_BOOKMARKS_DEFAULT_FILENAME,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                base::TimeFormatShortDateNumeric(time));
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_WIN)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath::StringType filename =
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l10n_util::GetStringFUTF16(IDS_EXPORT_BOOKMARKS_DEFAULT_FILENAME,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 base::TimeFormatShortDateNumeric(time));
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_util::ReplaceIllegalCharactersInPath(&filename, '_');
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath default_path;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PathService::Get(chrome::DIR_USER_DOCUMENTS, &default_path);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return default_path.Append(filename);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool BookmarksFunction::RunAsync() {
1011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
102b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!model->loaded()) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Bookmarks are not ready yet.  We'll wait.
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    model->AddObserver(this);
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AddRef();  // Balanced in Loaded().
1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return true;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bool success = RunOnReady();
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (success) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::NotificationService::current()->Notify(
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        chrome::NOTIFICATION_EXTENSION_BOOKMARKS_API_INVOKED,
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        content::Source<const Extension>(GetExtension()),
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::Details<const BookmarksFunction>(this));
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendResponse(success);
1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return true;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (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)
1350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const BookmarkNode* node = 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  }
1560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const BookmarkNode* parent = GetBookmarkNodeByID(model, parentId);
1570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!parent) {
1580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    error_ = keys::kNoParentError;
1590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return NULL;
1600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
1610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (parent->is_root()) {  // Can't create children of the root.
1620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    error_ = keys::kModifySpecialError;
1630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return NULL;
1640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
1650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  int index;
1670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!details.index.get()) {  // Optional (defaults to end).
1680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    index = parent->child_count();
1690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  } else {
1700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    index = *details.index;
1710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (index > parent->child_count() || index < 0) {
1720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      error_ = keys::kInvalidIndexError;
1730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      return NULL;
1740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
1750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
1760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::string16 title;  // Optional.
1780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (details.title.get())
1790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    title = base::UTF8ToUTF16(*details.title.get());
1800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  std::string url_string;  // Optional.
1820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (details.url.get())
1830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    url_string = *details.url.get();
1840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  GURL url(url_string);
1860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!url_string.empty() && !url.is_valid()) {
1870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    error_ = keys::kInvalidUrlError;
1880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return NULL;
1890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
1900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const BookmarkNode* node;
1920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (url_string.length())
1930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    node = model->AddURLWithCreationTimeAndMetaInfo(
1940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        parent, index, title, url, base::Time::Now(), meta_info);
1950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  else
1960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    node = model->AddFolderWithMetaInfo(parent, index, title, meta_info);
1970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK(node);
1980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!node) {
1990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    error_ = keys::kNoNodeError;
2000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return NULL;
2010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
2020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return node;
2040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarksFunction::EditBookmarksEnabled() {
2071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  PrefService* prefs = user_prefs::UserPrefs::Get(GetProfile());
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (prefs->GetBoolean(prefs::kEditBookmarksEnabled))
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  error_ = keys::kEditBookmarksDisabled;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksFunction::BookmarkModelChanged() {
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BookmarksFunction::BookmarkModelLoaded(BookmarkModel* model,
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                            bool ids_reassigned) {
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  model->RemoveObserver(this);
2205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  RunOnReady();
2215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  Release();  // Balanced in RunOnReady().
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BookmarkEventRouter::BookmarkEventRouter(BrowserContext* context,
225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                         BookmarkModel* model)
226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : browser_context_(context), model_(model) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  model_->AddObserver(this);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BookmarkEventRouter::~BookmarkEventRouter() {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (model_) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    model_->RemoveObserver(this);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::DispatchEvent(
2374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const std::string& event_name,
238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<base::ListValue> event_args) {
2390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EventRouter* event_router = EventRouter::Get(browser_context_);
2400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (event_router) {
2410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    event_router->BroadcastEvent(
2420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        make_scoped_ptr(new extensions::Event(event_name, event_args.Pass())));
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BookmarkEventRouter::BookmarkModelLoaded(BookmarkModel* model,
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                              bool ids_reassigned) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(erikkay): Perhaps we should send this event down to the extension
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so they know when it's safe to use the API?
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::BookmarkModelBeingDeleted(BookmarkModel* model) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  model_ = NULL;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::BookmarkNodeMoved(BookmarkModel* model,
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            const BookmarkNode* old_parent,
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            int old_index,
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            const BookmarkNode* new_parent,
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            int new_index) {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BookmarkNode* node = new_parent->GetChild(new_index);
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bookmarks::OnMoved::MoveInfo move_info;
263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  move_info.parent_id = base::Int64ToString(new_parent->id());
264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  move_info.index = new_index;
265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  move_info.old_parent_id = base::Int64ToString(old_parent->id());
266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  move_info.old_index = old_index;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DispatchEvent(
269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      bookmarks::OnMoved::kEventName,
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      bookmarks::OnMoved::Create(base::Int64ToString(node->id()), move_info));
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::BookmarkNodeAdded(BookmarkModel* model,
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            const BookmarkNode* parent,
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            int index) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BookmarkNode* node = parent->GetChild(index);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<BookmarkTreeNode> tree_node(
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bookmark_api_helpers::GetBookmarkTreeNode(node, false, false));
279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DispatchEvent(bookmarks::OnCreated::kEventName,
280a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                bookmarks::OnCreated::Create(base::Int64ToString(node->id()),
281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                             *tree_node));
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
284010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void BookmarkEventRouter::BookmarkNodeRemoved(
285010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    BookmarkModel* model,
286010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const BookmarkNode* parent,
287010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    int index,
288010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const BookmarkNode* node,
289010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::set<GURL>& removed_urls) {
290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bookmarks::OnRemoved::RemoveInfo remove_info;
291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  remove_info.parent_id = base::Int64ToString(parent->id());
292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  remove_info.index = index;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DispatchEvent(bookmarks::OnRemoved::kEventName,
295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                bookmarks::OnRemoved::Create(base::Int64ToString(node->id()),
296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                             remove_info));
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
299010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void BookmarkEventRouter::BookmarkAllNodesRemoved(
300010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    BookmarkModel* model,
301010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::set<GURL>& removed_urls) {
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NOTREACHED();
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(shashishekhar) Currently this notification is only used on Android,
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // which does not support extensions. If Desktop needs to support this, add
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // a new event to the extensions api.
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::BookmarkNodeChanged(BookmarkModel* model,
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                              const BookmarkNode* node) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(erikkay) The only three things that BookmarkModel sends this
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // notification for are title, url and favicon.  Since we're currently
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ignoring favicon and since the notification doesn't say which one anyway,
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for now we only include title and url.  The ideal thing would be to change
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // BookmarkModel to indicate what changed.
315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bookmarks::OnChanged::ChangeInfo change_info;
316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  change_info.title = base::UTF16ToUTF8(node->GetTitle());
317e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (node->is_url())
318e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    change_info.url.reset(new std::string(node->url().spec()));
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
320a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DispatchEvent(bookmarks::OnChanged::kEventName,
321a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                bookmarks::OnChanged::Create(base::Int64ToString(node->id()),
322a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                             change_info));
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::BookmarkNodeFaviconChanged(BookmarkModel* model,
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                     const BookmarkNode* node) {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(erikkay) anything we should do here?
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::BookmarkNodeChildrenReordered(
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BookmarkModel* model,
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const BookmarkNode* node) {
333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bookmarks::OnChildrenReordered::ReorderInfo reorder_info;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int childCount = node->child_count();
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < childCount; ++i) {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BookmarkNode* child = node->GetChild(i);
337a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    reorder_info.child_ids.push_back(base::Int64ToString(child->id()));
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
340a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DispatchEvent(bookmarks::OnChildrenReordered::kEventName,
341a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                bookmarks::OnChildrenReordered::Create(
342a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    base::Int64ToString(node->id()), reorder_info));
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::ExtensiveBookmarkChangesBeginning(
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BookmarkModel* model) {
347a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DispatchEvent(bookmarks::OnImportBegan::kEventName,
348a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                bookmarks::OnImportBegan::Create());
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::ExtensiveBookmarkChangesEnded(BookmarkModel* model) {
352a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DispatchEvent(bookmarks::OnImportEnded::kEventName,
353a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                bookmarks::OnImportEnded::Create());
354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
355a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
356a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BookmarksAPI::BookmarksAPI(BrowserContext* context)
357a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : browser_context_(context) {
3580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EventRouter* event_router = EventRouter::Get(browser_context_);
359a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  event_router->RegisterObserver(this, bookmarks::OnCreated::kEventName);
360a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  event_router->RegisterObserver(this, bookmarks::OnRemoved::kEventName);
361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  event_router->RegisterObserver(this, bookmarks::OnChanged::kEventName);
362a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  event_router->RegisterObserver(this, bookmarks::OnMoved::kEventName);
363a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  event_router->RegisterObserver(this,
364a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 bookmarks::OnChildrenReordered::kEventName);
365a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  event_router->RegisterObserver(this, bookmarks::OnImportBegan::kEventName);
366a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  event_router->RegisterObserver(this, bookmarks::OnImportEnded::kEventName);
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BookmarksAPI::~BookmarksAPI() {
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksAPI::Shutdown() {
3730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EventRouter::Get(browser_context_)->UnregisterObserver(this);
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static base::LazyInstance<BrowserContextKeyedAPIFactory<BookmarksAPI> >
377a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    g_factory = LAZY_INSTANCE_INITIALIZER;
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
380a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BrowserContextKeyedAPIFactory<BookmarksAPI>*
381a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BookmarksAPI::GetFactoryInstance() {
3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return g_factory.Pointer();
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksAPI::OnListenerAdded(const EventListenerInfo& details) {
386a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bookmark_event_router_.reset(new BookmarkEventRouter(
387a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      browser_context_,
388a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      BookmarkModelFactory::GetForProfile(
389a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          Profile::FromBrowserContext(browser_context_))));
3900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EventRouter::Get(browser_context_)->UnregisterObserver(this);
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksGetFunction::RunOnReady() {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<bookmarks::Get::Params> params(
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks::Get::Params::Create(*args_));
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<linked_ptr<BookmarkTreeNode> > nodes;
3997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (params->id_or_id_list.as_strings) {
4007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    std::vector<std::string>& ids = *params->id_or_id_list.as_strings;
4017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    size_t count = ids.size();
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXTENSION_FUNCTION_VALIDATE(count > 0);
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < count; ++i) {
404f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      const BookmarkNode* node = GetBookmarkNodeFromId(ids[i]);
405f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (!node)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
407f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      bookmark_api_helpers::AddNode(node, &nodes, false);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
410f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const BookmarkNode* node =
411f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        GetBookmarkNodeFromId(*params->id_or_id_list.as_string);
412f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!node)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bookmark_api_helpers::AddNode(node, &nodes, false);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results_ = bookmarks::Get::Results::Create(nodes);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksGetChildrenFunction::RunOnReady() {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<bookmarks::GetChildren::Params> params(
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks::GetChildren::Params::Create(*args_));
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
426f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const BookmarkNode* node = GetBookmarkNodeFromId(params->id);
427f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!node)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<linked_ptr<BookmarkTreeNode> > nodes;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int child_count = node->child_count();
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < child_count; ++i) {
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BookmarkNode* child = node->GetChild(i);
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bookmark_api_helpers::AddNode(child, &nodes, false);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results_ = bookmarks::GetChildren::Results::Create(nodes);
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksGetRecentFunction::RunOnReady() {
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<bookmarks::GetRecent::Params> params(
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks::GetRecent::Params::Create(*args_));
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (params->number_of_items < 1)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const BookmarkNode*> nodes;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bookmark_utils::GetMostRecentlyAddedEntries(
4501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      BookmarkModelFactory::GetForProfile(GetProfile()),
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      params->number_of_items,
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &nodes);
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<linked_ptr<BookmarkTreeNode> > tree_nodes;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const BookmarkNode*>::iterator i = nodes.begin();
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; i != nodes.end(); ++i) {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BookmarkNode* node = *i;
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bookmark_api_helpers::AddNode(node, &tree_nodes, false);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results_ = bookmarks::GetRecent::Results::Create(tree_nodes);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksGetTreeFunction::RunOnReady() {
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<linked_ptr<BookmarkTreeNode> > nodes;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BookmarkNode* node =
4681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      BookmarkModelFactory::GetForProfile(GetProfile())->root_node();
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bookmark_api_helpers::AddNode(node, &nodes, true);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results_ = bookmarks::GetTree::Results::Create(nodes);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksGetSubTreeFunction::RunOnReady() {
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<bookmarks::GetSubTree::Params> params(
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks::GetSubTree::Params::Create(*args_));
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
479f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const BookmarkNode* node = GetBookmarkNodeFromId(params->id);
480f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!node)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<linked_ptr<BookmarkTreeNode> > nodes;
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bookmark_api_helpers::AddNode(node, &nodes, true);
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results_ = bookmarks::GetSubTree::Results::Create(nodes);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksSearchFunction::RunOnReady() {
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<bookmarks::Search::Params> params(
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks::Search::Params::Create(*args_));
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  PrefService* prefs = user_prefs::UserPrefs::Get(GetProfile());
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string lang = prefs->GetString(prefs::kAcceptLanguages);
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const BookmarkNode*> nodes;
4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (params->query.as_string) {
4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bookmark_utils::QueryFields query;
4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    query.word_phrase_query.reset(
5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        new base::string16(base::UTF8ToUTF16(*params->query.as_string)));
5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bookmark_utils::GetBookmarksMatchingProperties(
5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        BookmarkModelFactory::GetForProfile(GetProfile()),
5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        query,
5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        std::numeric_limits<int>::max(),
5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        lang,
5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        &nodes);
5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(params->query.as_object);
5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const bookmarks::Search::Params::Query::Object& object =
5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        *params->query.as_object;
5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bookmark_utils::QueryFields query;
5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (object.query) {
5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      query.word_phrase_query.reset(
5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          new base::string16(base::UTF8ToUTF16(*object.query)));
5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (object.url)
5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      query.url.reset(new base::string16(base::UTF8ToUTF16(*object.url)));
5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (object.title)
5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      query.title.reset(new base::string16(base::UTF8ToUTF16(*object.title)));
5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bookmark_utils::GetBookmarksMatchingProperties(
5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        BookmarkModelFactory::GetForProfile(GetProfile()),
5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        query,
5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        std::numeric_limits<int>::max(),
5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        lang,
5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        &nodes);
5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<linked_ptr<BookmarkTreeNode> > tree_nodes;
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<const BookmarkNode*>::iterator node_iter = nodes.begin();
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       node_iter != nodes.end(); ++node_iter) {
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bookmark_api_helpers::AddNode(*node_iter, &tree_nodes, false);
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results_ = bookmarks::Search::Results::Create(tree_nodes);
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool BookmarksRemoveFunction::ExtractIds(const base::ListValue* args,
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         std::list<int64>* ids,
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         bool* invalid_id) {
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string id_string;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!args->GetString(0, &id_string))
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 id;
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (base::StringToInt64(id_string, &id))
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ids->push_back(id);
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *invalid_id = true;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksRemoveFunction::RunOnReady() {
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!EditBookmarksEnabled())
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<bookmarks::Remove::Params> params(
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks::Remove::Params::Create(*args_));
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 id;
562f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!GetBookmarkIdAsInt64(params->id, &id))
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool recursive = false;
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (name() == BookmarksRemoveTreeFunction::function_name())
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    recursive = true;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!bookmark_api_helpers::RemoveNode(model, id, recursive, &error_))
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksCreateFunction::RunOnReady() {
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!EditBookmarksEnabled())
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<bookmarks::Create::Params> params(
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks::Create::Params::Create(*args_));
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
5850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const BookmarkNode* node = CreateBookmarkNode(model, params->bookmark, NULL);
5860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!node)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<BookmarkTreeNode> ret(
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bookmark_api_helpers::GetBookmarkTreeNode(node, false, false));
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results_ = bookmarks::Create::Results::Create(*ret);
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
597eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool BookmarksMoveFunction::ExtractIds(const base::ListValue* args,
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       std::list<int64>* ids,
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       bool* invalid_id) {
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For now, Move accepts ID parameters in the same way as an Update.
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return BookmarksUpdateFunction::ExtractIds(args, ids, invalid_id);
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksMoveFunction::RunOnReady() {
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!EditBookmarksEnabled())
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<bookmarks::Move::Params> params(
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks::Move::Params::Create(*args_));
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
612f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const BookmarkNode* node = GetBookmarkNodeFromId(params->id);
613f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!node)
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (model->is_permanent_node(node)) {
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = keys::kModifySpecialError;
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const BookmarkNode* parent = NULL;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!params->destination.parent_id.get()) {
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Optional, defaults to current parent.
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parent = node->parent();
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 parentId;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!GetBookmarkIdAsInt64(*params->destination.parent_id, &parentId))
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    parent = GetBookmarkNodeByID(model, parentId);
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!parent) {
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = keys::kNoParentError;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(erikkay) return an error message.
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parent == model->root_node()) {
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = keys::kModifySpecialError;
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int index;
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (params->destination.index.get()) {  // Optional (defaults to end).
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    index = *params->destination.index;
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (index > parent->child_count() || index < 0) {
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error_ = keys::kInvalidIndexError;
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    index = parent->child_count();
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  model->Move(node, parent, index);
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<BookmarkTreeNode> tree_node(
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bookmark_api_helpers::GetBookmarkTreeNode(node, false, false));
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results_ = bookmarks::Move::Results::Create(*tree_node);
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
664eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool BookmarksUpdateFunction::ExtractIds(const base::ListValue* args,
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         std::list<int64>* ids,
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         bool* invalid_id) {
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For now, Update accepts ID parameters in the same way as an Remove.
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return BookmarksRemoveFunction::ExtractIds(args, ids, invalid_id);
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksUpdateFunction::RunOnReady() {
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!EditBookmarksEnabled())
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<bookmarks::Update::Params> params(
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks::Update::Params::Create(*args_));
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Optional but we need to distinguish non present from an empty title.
680a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 title;
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool has_title = false;
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (params->changes.title.get()) {
6835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    title = base::UTF8ToUTF16(*params->changes.title);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    has_title = true;
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Optional.
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string;
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (params->changes.url.get())
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    url_string = *params->changes.url;
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(url_string);
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!url_string.empty() && !url.is_valid()) {
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = keys::kInvalidUrlError;
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
697f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const BookmarkNode* node = GetBookmarkNodeFromId(params->id);
698f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!node)
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
700f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
701f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  BookmarkModel* model = BookmarkModelFactory::GetForProfile(GetProfile());
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (model->is_permanent_node(node)) {
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_ = keys::kModifySpecialError;
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_title)
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    model->SetTitle(node, title);
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!url.is_empty())
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    model->SetURL(node, url);
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<BookmarkTreeNode> tree_node(
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bookmark_api_helpers::GetBookmarkTreeNode(node, false, false));
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results_ = bookmarks::Update::Results::Create(*tree_node);
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Mapper superclass for BookmarkFunctions.
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename BucketIdType>
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BookmarkBucketMapper : public BucketMapper {
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~BookmarkBucketMapper() { STLDeleteValues(&buckets_); }
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Bucket* GetBucket(const BucketIdType& id) {
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Bucket* b = buckets_[id];
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (b == NULL) {
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      b = new Bucket();
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buckets_[id] = b;
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return b;
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<BucketIdType, Bucket*> buckets_;
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Mapper for 'bookmarks.create'.  Maps "same input to bookmarks.create" to a
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// unique bucket.
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CreateBookmarkBucketMapper : public BookmarkBucketMapper<std::string> {
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
739a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  explicit CreateBookmarkBucketMapper(BrowserContext* context)
740a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      : browser_context_(context) {}
7415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // TODO(tim): This should share code with BookmarksCreateFunction::RunOnReady,
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // but I can't figure out a good way to do that with all the macros.
743eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void GetBucketsForArgs(const base::ListValue* args,
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 BucketList* buckets) OVERRIDE {
745eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const base::DictionaryValue* json;
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!args->GetDictionary(0, &json))
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string parent_id;
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (json->HasKey(keys::kParentIdKey)) {
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!json->GetString(keys::kParentIdKey, &parent_id))
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
754a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    BookmarkModel* model = BookmarkModelFactory::GetForProfile(
755a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        Profile::FromBrowserContext(browser_context_));
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 parent_id_int64;
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringToInt64(parent_id, &parent_id_int64);
7590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const BookmarkNode* parent = GetBookmarkNodeByID(model, parent_id_int64);
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!parent)
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string bucket_id = base::UTF16ToUTF8(parent->GetTitle());
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string title;
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    json->GetString(keys::kTitleKey, &title);
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string url_string;
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    json->GetString(keys::kUrlKey, &url_string);
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bucket_id += title;
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bucket_id += url_string;
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // 20 bytes (SHA1 hash length) is very likely less than most of the
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |bucket_id| strings we construct here, so we hash it to save space.
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buckets->push_back(GetBucket(base::SHA1HashString(bucket_id)));
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
776a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  BrowserContext* browser_context_;
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Mapper for 'bookmarks.remove'.
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RemoveBookmarksBucketMapper : public BookmarkBucketMapper<std::string> {
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
782a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  explicit RemoveBookmarksBucketMapper(BrowserContext* context)
783a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      : browser_context_(context) {}
784eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void GetBucketsForArgs(const base::ListValue* args,
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 BucketList* buckets) OVERRIDE {
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef std::list<int64> IdList;
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IdList ids;
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool invalid_id = false;
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!BookmarksRemoveFunction::ExtractIds(args, &ids, &invalid_id) ||
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        invalid_id) {
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (IdList::iterator it = ids.begin(); it != ids.end(); ++it) {
795a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      BookmarkModel* model = BookmarkModelFactory::GetForProfile(
796a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          Profile::FromBrowserContext(browser_context_));
7970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      const BookmarkNode* node = GetBookmarkNodeByID(model, *it);
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!node || node->is_root())
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string bucket_id;
8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bucket_id += base::UTF16ToUTF8(node->parent()->GetTitle());
8035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bucket_id += base::UTF16ToUTF8(node->GetTitle());
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bucket_id += node->url().spec();
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buckets->push_back(GetBucket(base::SHA1HashString(bucket_id)));
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
809a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  BrowserContext* browser_context_;
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Mapper for any bookmark function accepting bookmark IDs as parameters, where
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a distinct ID corresponds to a single item in terms of quota limiting.  This
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is inappropriate for bookmarks.remove, for example, since repeated removals
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the same item will actually have a different ID each time.
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class FunctionType>
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BookmarkIdMapper : public BookmarkBucketMapper<int64> {
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::list<int64> IdList;
820eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void GetBucketsForArgs(const base::ListValue* args,
821eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                 BucketList* buckets) {
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IdList ids;
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool invalid_id = false;
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!FunctionType::ExtractIds(args, &ids, &invalid_id) || invalid_id)
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (IdList::iterator it = ids.begin(); it != ids.end(); ++it)
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buckets->push_back(GetBucket(*it));
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Builds heuristics for all BookmarkFunctions using specialized BucketMappers.
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BookmarksQuotaLimitFactory {
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For id-based bookmark functions.
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <class FunctionType>
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void Build(QuotaLimitHeuristics* heuristics) {
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BuildWithMappers(heuristics, new BookmarkIdMapper<FunctionType>(),
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 new BookmarkIdMapper<FunctionType>());
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For bookmarks.create.
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void BuildForCreate(QuotaLimitHeuristics* heuristics,
843a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             BrowserContext* context) {
844a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    BuildWithMappers(heuristics,
845a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     new CreateBookmarkBucketMapper(context),
846a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     new CreateBookmarkBucketMapper(context));
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For bookmarks.remove.
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void BuildForRemove(QuotaLimitHeuristics* heuristics,
851a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             BrowserContext* context) {
852a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    BuildWithMappers(heuristics,
853a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     new RemoveBookmarksBucketMapper(context),
854a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     new RemoveBookmarksBucketMapper(context));
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void BuildWithMappers(QuotaLimitHeuristics* heuristics,
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BucketMapper* short_mapper, BucketMapper* long_mapper) {
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Config kSustainedLimitConfig = {
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // See bookmarks.json for current value.
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks::MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE,
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TimeDelta::FromMinutes(1)
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    heuristics->push_back(new SustainedLimit(
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TimeDelta::FromMinutes(10),
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kSustainedLimitConfig,
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        short_mapper,
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE"));
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Config kTimedLimitConfig = {
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // See bookmarks.json for current value.
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bookmarks::MAX_WRITE_OPERATIONS_PER_HOUR,
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TimeDelta::FromHours(1)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    heuristics->push_back(new TimedLimit(
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kTimedLimitConfig,
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        long_mapper,
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "MAX_WRITE_OPERATIONS_PER_HOUR"));
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_IMPLICIT_CONSTRUCTORS(BookmarksQuotaLimitFactory);
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// And finally, building the individual heuristics for each function.
8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksRemoveFunction::GetQuotaLimitHeuristics(
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    QuotaLimitHeuristics* heuristics) const {
8881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  BookmarksQuotaLimitFactory::BuildForRemove(heuristics, GetProfile());
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksMoveFunction::GetQuotaLimitHeuristics(
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    QuotaLimitHeuristics* heuristics) const {
8932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BookmarksQuotaLimitFactory::Build<BookmarksMoveFunction>(heuristics);
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksUpdateFunction::GetQuotaLimitHeuristics(
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    QuotaLimitHeuristics* heuristics) const {
8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BookmarksQuotaLimitFactory::Build<BookmarksUpdateFunction>(heuristics);
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksCreateFunction::GetQuotaLimitHeuristics(
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    QuotaLimitHeuristics* heuristics) const {
9031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  BookmarksQuotaLimitFactory::BuildForCreate(heuristics, GetProfile());
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarksIOFunction::BookmarksIOFunction() {}
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarksIOFunction::~BookmarksIOFunction() {
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There may be pending file dialogs, we need to tell them that we've gone
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // away so they don't try and call back to us.
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (select_file_dialog_.get())
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    select_file_dialog_->ListenerDestroyed();
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarksIOFunction::SelectFile(ui::SelectFileDialog::Type type) {
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GetDefaultFilepathForBookmarkExport() might have to touch the filesystem
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (stat or access, for example), so this requires a thread with IO allowed.
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&BookmarksIOFunction::SelectFile, this, type));
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pre-populating the filename field in case this is a SELECT_SAVEAS_FILE
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dialog. If not, there is no filename field in the dialog box.
9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath default_path;
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == ui::SelectFileDialog::SELECT_SAVEAS_FILE)
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default_path = GetDefaultFilepathForBookmarkExport();
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(type == ui::SelectFileDialog::SELECT_OPEN_FILE);
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // After getting the |default_path|, ask the UI to display the file dialog.
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BookmarksIOFunction::ShowSelectFileDialog, this,
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 type, default_path));
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksIOFunction::ShowSelectFileDialog(
9392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ui::SelectFileDialog::Type type,
9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& default_path) {
9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!dispatcher())
9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;  // Extension was unloaded.
9432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Balanced in one of the three callbacks of SelectFileDialog:
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // either FileSelectionCanceled, MultiFilesSelected, or FileSelected
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddRef();
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebContents* web_contents = dispatcher()->delegate()->
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetAssociatedWebContents();
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  select_file_dialog_ = ui::SelectFileDialog::Create(
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this, new ChromeSelectFilePolicy(web_contents));
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::SelectFileDialog::FileTypeInfo file_type_info;
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_type_info.extensions.resize(1);
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("html"));
9567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::NativeWindow owning_window = web_contents ?
957010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      platform_util::GetTopLevel(web_contents->GetNativeView())
9587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          : NULL;
9595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_WIN)
9607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!owning_window &&
9617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      chrome::GetActiveDesktop() == chrome::HOST_DESKTOP_TYPE_ASH)
9625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    owning_window = aura::RemoteWindowTreeHostWin::Instance()->GetAshWindow();
9637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif
9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |web_contents| can be NULL (for background pages), which is fine. In such
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a case if file-selection dialogs are forbidden by policy, we will not
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // show an InfoBar, which is better than letting one appear out of the blue.
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  select_file_dialog_->SelectFile(type,
968a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                  base::string16(),
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  default_path,
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  &file_type_info,
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  0,
972c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  base::FilePath::StringType(),
9737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                  owning_window,
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  NULL);
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarksIOFunction::FileSelectionCanceled(void* params) {
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Release();  // Balanced in BookmarksIOFunction::SelectFile()
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarksIOFunction::MultiFilesSelected(
9822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<base::FilePath>& files, void* params) {
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Release();  // Balanced in BookmarsIOFunction::SelectFile()
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "Should not be able to select multiple files";
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksImportFunction::RunOnReady() {
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!EditBookmarksEnabled())
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectFile(ui::SelectFileDialog::SELECT_OPEN_FILE);
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksImportFunction::FileSelected(const base::FilePath& path,
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           int index,
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           void* params) {
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_ANDROID)
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Android does not have support for the standard importers.
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(jgreenwald): remove ifdef once extensions are no longer built on
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Android.
1001c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Deletes itself.
1002eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ExternalProcessImporterHost* importer_host = new ExternalProcessImporterHost;
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  importer::SourceProfile source_profile;
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source_profile.importer_type = importer::TYPE_BOOKMARKS_FILE;
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source_profile.source_path = path;
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  importer_host->StartImportSettings(source_profile,
10071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                     GetProfile(),
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     importer::FAVORITES,
10091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                     new ProfileWriter(GetProfile()));
1010c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1011c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  importer::LogImporterUseToMetrics("BookmarksAPI",
1012c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                    importer::TYPE_BOOKMARKS_FILE);
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Release();  // Balanced in BookmarksIOFunction::SelectFile()
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool BookmarksExportFunction::RunOnReady() {
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE);
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksExportFunction::FileSelected(const base::FilePath& path,
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           int index,
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           void* params) {
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_ANDROID)
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Android does not have support for the standard exporter.
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(jgreenwald): remove ifdef once extensions are no longer built on
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Android.
10291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bookmark_html_writer::WriteBookmarks(GetProfile(), path, NULL);
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Release();  // Balanced in BookmarksIOFunction::SelectFile()
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace extensions
1035