bookmarks_api.cc revision b2df76ea8fec9e32f6f3718986dba0d95315b29c
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" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string16.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_util.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/time.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/utf_string_conversions.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_html_writer.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_model.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_model_factory.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_utils.h" 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/bookmarks/bookmark_api_constants.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/event_router.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_function_dispatcher.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_system.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extensions_quota_service.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/importer/importer_data_types.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/importer/importer_host.h" 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/importer/importer_type.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/chrome_select_file_policy.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_notification_types.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_paths.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/api/bookmarks.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h" 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/user_prefs/user_prefs.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace extensions { 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace keys = bookmark_api_constants; 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace bookmarks = api::bookmarks; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using bookmarks::BookmarkTreeNode; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef QuotaLimitHeuristic::Bucket Bucket; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef QuotaLimitHeuristic::Config Config; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef QuotaLimitHeuristic::BucketList BucketList; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef ExtensionsQuotaService::TimedLimit TimedLimit; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef ExtensionsQuotaService::SustainedLimit SustainedLimit; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef QuotaLimitHeuristic::BucketMapper BucketMapper; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generates a default path (including a default filename) that will be 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// used for pre-populating the "Export Bookmarks" file chooser dialog box. 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetDefaultFilepathForBookmarkExport() { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time time = base::Time::Now(); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Concatenate a date stamp to the filename. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath::StringType filename = 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF8(IDS_EXPORT_BOOKMARKS_DEFAULT_FILENAME, 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeFormatShortDateNumeric(time)); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_WIN) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath::StringType filename = 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringFUTF16(IDS_EXPORT_BOOKMARKS_DEFAULT_FILENAME, 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeFormatShortDateNumeric(time)); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_util::ReplaceIllegalCharactersInPath(&filename, '_'); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath default_path; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PathService::Get(chrome::DIR_USER_DOCUMENTS, &default_path); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return default_path.Append(filename); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarksFunction::Run() { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile()); 93b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!model->loaded()) { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Bookmarks are not ready yet. We'll wait. 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) model->AddObserver(this); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddRef(); // Balanced in Loaded(). 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = RunImpl(); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (success) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationService::current()->Notify( 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome::NOTIFICATION_EXTENSION_BOOKMARKS_API_INVOKED, 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::Source<const Extension>(GetExtension()), 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Details<const BookmarksFunction>(this)); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendResponse(success); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BookmarksFunction::GetBookmarkIdAsInt64(const std::string& id_string, 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64* id) { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::StringToInt64(id_string, id)) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kInvalidIdError; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarksFunction::EditBookmarksEnabled() { 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PrefService* prefs = components::UserPrefs::Get(profile_); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prefs->GetBoolean(prefs::kEditBookmarksEnabled)) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kEditBookmarksDisabled; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksFunction::BookmarkModelChanged() { 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksFunction::Loaded(BookmarkModel* model, bool ids_reassigned) { 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) model->RemoveObserver(this); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Run(); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Release(); // Balanced in Run(). 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BookmarkEventRouter::BookmarkEventRouter(Profile* profile, 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BookmarkModel* model) 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : profile_(profile), 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) model_(model) { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->AddObserver(this); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BookmarkEventRouter::~BookmarkEventRouter() { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (model_) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->RemoveObserver(this); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::DispatchEvent( 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* event_name, 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ListValue> event_args) { 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (extensions::ExtensionSystem::Get(profile_)->event_router()) { 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::ExtensionSystem::Get(profile_)->event_router()->BroadcastEvent( 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) make_scoped_ptr(new extensions::Event(event_name, event_args.Pass()))); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::Loaded(BookmarkModel* model, bool ids_reassigned) { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(erikkay): Perhaps we should send this event down to the extension 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so they know when it's safe to use the API? 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::BookmarkModelBeingDeleted(BookmarkModel* model) { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_ = NULL; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::BookmarkNodeMoved(BookmarkModel* model, 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const BookmarkNode* old_parent, 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int old_index, 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const BookmarkNode* new_parent, 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int new_index) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ListValue> args(new ListValue()); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = new_parent->GetChild(new_index); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->Append(new StringValue(base::Int64ToString(node->id()))); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryValue* object_args = new DictionaryValue(); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object_args->SetString(keys::kParentIdKey, 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Int64ToString(new_parent->id())); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object_args->SetInteger(keys::kIndexKey, new_index); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object_args->SetString(keys::kOldParentIdKey, 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Int64ToString(old_parent->id())); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object_args->SetInteger(keys::kOldIndexKey, old_index); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->Append(object_args); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DispatchEvent(keys::kOnBookmarkMoved, args.Pass()); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::BookmarkNodeAdded(BookmarkModel* model, 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const BookmarkNode* parent, 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int index) { 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ListValue> args(new ListValue()); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = parent->GetChild(index); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->Append(new StringValue(base::Int64ToString(node->id()))); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<BookmarkTreeNode> tree_node( 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bookmark_api_helpers::GetBookmarkTreeNode(node, false, false)); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->Append(tree_node->ToValue().release()); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DispatchEvent(keys::kOnBookmarkCreated, args.Pass()); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::BookmarkNodeRemoved(BookmarkModel* model, 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const BookmarkNode* parent, 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int index, 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const BookmarkNode* node) { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ListValue> args(new ListValue()); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->Append(new StringValue(base::Int64ToString(node->id()))); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryValue* object_args = new DictionaryValue(); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object_args->SetString(keys::kParentIdKey, 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Int64ToString(parent->id())); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object_args->SetInteger(keys::kIndexKey, index); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->Append(object_args); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DispatchEvent(keys::kOnBookmarkRemoved, args.Pass()); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void BookmarkEventRouter::BookmarkAllNodesRemoved(BookmarkModel* model) { 216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NOTREACHED(); 217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // TODO(shashishekhar) Currently this notification is only used on Android, 218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // which does not support extensions. If Desktop needs to support this, add 219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // a new event to the extensions api. 220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::BookmarkNodeChanged(BookmarkModel* model, 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const BookmarkNode* node) { 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ListValue> args(new ListValue()); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->Append(new StringValue(base::Int64ToString(node->id()))); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(erikkay) The only three things that BookmarkModel sends this 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // notification for are title, url and favicon. Since we're currently 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ignoring favicon and since the notification doesn't say which one anyway, 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for now we only include title and url. The ideal thing would be to change 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // BookmarkModel to indicate what changed. 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryValue* object_args = new DictionaryValue(); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object_args->SetString(keys::kTitleKey, node->GetTitle()); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node->is_url()) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object_args->SetString(keys::kUrlKey, node->url().spec()); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->Append(object_args); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DispatchEvent(keys::kOnBookmarkChanged, args.Pass()); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::BookmarkNodeFaviconChanged(BookmarkModel* model, 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const BookmarkNode* node) { 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(erikkay) anything we should do here? 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::BookmarkNodeChildrenReordered( 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BookmarkModel* model, 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const BookmarkNode* node) { 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ListValue> args(new ListValue()); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->Append(new StringValue(base::Int64ToString(node->id()))); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int childCount = node->child_count(); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListValue* children = new ListValue(); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < childCount; ++i) { 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* child = node->GetChild(i); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Value* child_id = new StringValue(base::Int64ToString(child->id())); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) children->Append(child_id); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryValue* reorder_info = new DictionaryValue(); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reorder_info->Set(keys::kChildIdsKey, children); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->Append(reorder_info); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DispatchEvent(keys::kOnBookmarkChildrenReordered, args.Pass()); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::ExtensiveBookmarkChangesBeginning( 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BookmarkModel* model) { 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ListValue> args(new ListValue()); 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DispatchEvent(keys::kOnBookmarkImportBegan, args.Pass()); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarkEventRouter::ExtensiveBookmarkChangesEnded(BookmarkModel* model) { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ListValue> args(new ListValue()); 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DispatchEvent(keys::kOnBookmarkImportEnded, args.Pass()); 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BookmarksAPI::BookmarksAPI(Profile* profile) : profile_(profile) { 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, keys::kOnBookmarkCreated); 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, keys::kOnBookmarkRemoved); 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, keys::kOnBookmarkChanged); 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, keys::kOnBookmarkMoved); 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, keys::kOnBookmarkChildrenReordered); 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, keys::kOnBookmarkImportBegan); 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, keys::kOnBookmarkImportEnded); 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BookmarksAPI::~BookmarksAPI() { 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksAPI::Shutdown() { 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this); 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static base::LazyInstance<ProfileKeyedAPIFactory<BookmarksAPI> > 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)g_factory = LAZY_INSTANCE_INITIALIZER; 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ProfileKeyedAPIFactory<BookmarksAPI>* BookmarksAPI::GetFactoryInstance() { 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return &g_factory.Get(); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksAPI::OnListenerAdded(const EventListenerInfo& details) { 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bookmark_event_router_.reset(new BookmarkEventRouter(profile_, 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BookmarkModelFactory::GetForProfile(profile_))); 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this); 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BookmarksGetFunction::RunImpl() { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<bookmarks::Get::Params> params( 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmarks::Get::Params::Create(*args_)); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(params.get()); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<linked_ptr<BookmarkTreeNode> > nodes; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile()); 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (params->id_or_id_list.as_array) { 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<std::string>* ids = params->id_or_id_list.as_array.get(); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t count = ids->size(); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(count > 0); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < count; ++i) { 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 id; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetBookmarkIdAsInt64(ids->at(i), &id)) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = model->GetNodeByID(id); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node) { 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kNoNodeError; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bookmark_api_helpers::AddNode(node, &nodes, false); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 id; 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!GetBookmarkIdAsInt64(*params->id_or_id_list.as_string, &id)) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = model->GetNodeByID(id); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node) { 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kNoNodeError; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bookmark_api_helpers::AddNode(node, &nodes, false); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results_ = bookmarks::Get::Results::Create(nodes); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BookmarksGetChildrenFunction::RunImpl() { 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<bookmarks::GetChildren::Params> params( 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmarks::GetChildren::Params::Create(*args_)); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(params.get()); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 id; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetBookmarkIdAsInt64(params->id, &id)) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<linked_ptr<BookmarkTreeNode> > nodes; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModelFactory::GetForProfile(profile())->GetNodeByID(id); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node) { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kNoNodeError; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int child_count = node->child_count(); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < child_count; ++i) { 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* child = node->GetChild(i); 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bookmark_api_helpers::AddNode(child, &nodes, false); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results_ = bookmarks::GetChildren::Results::Create(nodes); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BookmarksGetRecentFunction::RunImpl() { 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<bookmarks::GetRecent::Params> params( 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmarks::GetRecent::Params::Create(*args_)); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(params.get()); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (params->number_of_items < 1) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<const BookmarkNode*> nodes; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_utils::GetMostRecentlyAddedEntries( 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModelFactory::GetForProfile(profile()), 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params->number_of_items, 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &nodes); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<linked_ptr<BookmarkTreeNode> > tree_nodes; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<const BookmarkNode*>::iterator i = nodes.begin(); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; i != nodes.end(); ++i) { 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = *i; 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bookmark_api_helpers::AddNode(node, &tree_nodes, false); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results_ = bookmarks::GetRecent::Results::Create(tree_nodes); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BookmarksGetTreeFunction::RunImpl() { 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<linked_ptr<BookmarkTreeNode> > nodes; 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModelFactory::GetForProfile(profile())->root_node(); 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bookmark_api_helpers::AddNode(node, &nodes, true); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results_ = bookmarks::GetTree::Results::Create(nodes); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BookmarksGetSubTreeFunction::RunImpl() { 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<bookmarks::GetSubTree::Params> params( 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmarks::GetSubTree::Params::Create(*args_)); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(params.get()); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 id; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetBookmarkIdAsInt64(params->id, &id)) 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModelFactory::GetForProfile(profile())->GetNodeByID(id); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node) { 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kNoNodeError; 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<linked_ptr<BookmarkTreeNode> > nodes; 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bookmark_api_helpers::AddNode(node, &nodes, true); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results_ = bookmarks::GetSubTree::Results::Create(nodes); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BookmarksSearchFunction::RunImpl() { 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<bookmarks::Search::Params> params( 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmarks::Search::Params::Create(*args_)); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(params.get()); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PrefService* prefs = components::UserPrefs::Get(profile_); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string lang = prefs->GetString(prefs::kAcceptLanguages); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<const BookmarkNode*> nodes; 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_utils::GetBookmarksContainingText( 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModelFactory::GetForProfile(profile()), 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UTF8ToUTF16(params->query), 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::numeric_limits<int>::max(), 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lang, 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &nodes); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<linked_ptr<BookmarkTreeNode> > tree_nodes; 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<const BookmarkNode*>::iterator node_iter = nodes.begin(); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node_iter != nodes.end(); ++node_iter) { 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bookmark_api_helpers::AddNode(*node_iter, &tree_nodes, false); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results_ = bookmarks::Search::Results::Create(tree_nodes); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BookmarksRemoveFunction::ExtractIds(const ListValue* args, 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::list<int64>* ids, 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* invalid_id) { 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string id_string; 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!args->GetString(0, &id_string)) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 id; 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::StringToInt64(id_string, &id)) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ids->push_back(id); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *invalid_id = true; 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BookmarksRemoveFunction::RunImpl() { 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!EditBookmarksEnabled()) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<bookmarks::Remove::Params> params( 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmarks::Remove::Params::Create(*args_)); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(params.get()); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 id; 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!base::StringToInt64(params->id, &id)) { 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kInvalidIdError; 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool recursive = false; 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (name() == BookmarksRemoveTreeFunction::function_name()) 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recursive = true; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile()); 4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!bookmark_api_helpers::RemoveNode(model, id, recursive, &error_)) 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BookmarksCreateFunction::RunImpl() { 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!EditBookmarksEnabled()) 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<bookmarks::Create::Params> params( 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmarks::Create::Params::Create(*args_)); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(params.get()); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile()); 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 parentId; 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!params->bookmark.parent_id.get()) { 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Optional, default to "other bookmarks". 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parentId = model->other_node()->id(); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetBookmarkIdAsInt64(*params->bookmark.parent_id, &parentId)) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* parent = model->GetNodeByID(parentId); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!parent) { 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kNoParentError; 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parent->is_root()) { // Can't create children of the root. 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kModifySpecialError; 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index; 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!params->bookmark.index.get()) { // Optional (defaults to end). 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = parent->child_count(); 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = *params->bookmark.index; 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index > parent->child_count() || index < 0) { 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kInvalidIndexError; 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 title; // Optional. 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (params->bookmark.title.get()) 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) title = UTF8ToUTF16(*params->bookmark.title.get()); 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url_string; // Optional. 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (params->bookmark.url.get()) 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_string = *params->bookmark.url.get(); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url(url_string); 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_string.empty() && !url.is_valid()) { 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kInvalidUrlError; 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node; 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url_string.length()) 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node = model->AddURL(parent, index, title, url); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node = model->AddFolder(parent, index, title); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(node); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node) { 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kNoNodeError; 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<BookmarkTreeNode> ret( 5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bookmark_api_helpers::GetBookmarkTreeNode(node, false, false)); 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results_ = bookmarks::Create::Results::Create(*ret); 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BookmarksMoveFunction::ExtractIds(const ListValue* args, 5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::list<int64>* ids, 5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* invalid_id) { 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For now, Move accepts ID parameters in the same way as an Update. 5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return BookmarksUpdateFunction::ExtractIds(args, ids, invalid_id); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BookmarksMoveFunction::RunImpl() { 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!EditBookmarksEnabled()) 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<bookmarks::Move::Params> params( 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmarks::Move::Params::Create(*args_)); 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(params.get()); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 id; 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!base::StringToInt64(params->id, &id)) { 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kInvalidIdError; 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile()); 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = model->GetNodeByID(id); 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node) { 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kNoNodeError; 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (model->is_permanent_node(node)) { 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kModifySpecialError; 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* parent = NULL; 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!params->destination.parent_id.get()) { 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Optional, defaults to current parent. 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent = node->parent(); 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 parentId; 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetBookmarkIdAsInt64(*params->destination.parent_id, &parentId)) 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent = model->GetNodeByID(parentId); 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!parent) { 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kNoParentError; 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(erikkay) return an error message. 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parent == model->root_node()) { 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kModifySpecialError; 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index; 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (params->destination.index.get()) { // Optional (defaults to end). 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = *params->destination.index; 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index > parent->child_count() || index < 0) { 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kInvalidIndexError; 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = parent->child_count(); 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model->Move(node, parent, index); 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<BookmarkTreeNode> tree_node( 6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bookmark_api_helpers::GetBookmarkTreeNode(node, false, false)); 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results_ = bookmarks::Move::Results::Create(*tree_node); 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BookmarksUpdateFunction::ExtractIds(const ListValue* args, 6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::list<int64>* ids, 6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* invalid_id) { 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For now, Update accepts ID parameters in the same way as an Remove. 6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return BookmarksRemoveFunction::ExtractIds(args, ids, invalid_id); 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BookmarksUpdateFunction::RunImpl() { 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!EditBookmarksEnabled()) 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<bookmarks::Update::Params> params( 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmarks::Update::Params::Create(*args_)); 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXTENSION_FUNCTION_VALIDATE(params.get()); 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 id; 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!base::StringToInt64(params->id, &id)) { 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kInvalidIdError; 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile()); 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Optional but we need to distinguish non present from an empty title. 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 title; 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_title = false; 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (params->changes.title.get()) { 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) title = UTF8ToUTF16(*params->changes.title); 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_title = true; 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Optional. 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url_string; 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (params->changes.url.get()) 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url_string = *params->changes.url; 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL url(url_string); 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url_string.empty() && !url.is_valid()) { 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kInvalidUrlError; 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = model->GetNodeByID(id); 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node) { 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kNoNodeError; 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (model->is_permanent_node(node)) { 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = keys::kModifySpecialError; 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_title) 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model->SetTitle(node, title); 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url.is_empty()) 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model->SetURL(node, url); 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<BookmarkTreeNode> tree_node( 7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bookmark_api_helpers::GetBookmarkTreeNode(node, false, false)); 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results_ = bookmarks::Update::Results::Create(*tree_node); 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Mapper superclass for BookmarkFunctions. 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename BucketIdType> 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BookmarkBucketMapper : public BucketMapper { 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~BookmarkBucketMapper() { STLDeleteValues(&buckets_); } 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Bucket* GetBucket(const BucketIdType& id) { 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Bucket* b = buckets_[id]; 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (b == NULL) { 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) b = new Bucket(); 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buckets_[id] = b; 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return b; 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<BucketIdType, Bucket*> buckets_; 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Mapper for 'bookmarks.create'. Maps "same input to bookmarks.create" to a 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// unique bucket. 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CreateBookmarkBucketMapper : public BookmarkBucketMapper<std::string> { 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit CreateBookmarkBucketMapper(Profile* profile) : profile_(profile) {} 7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(tim): This should share code with BookmarksCreateFunction::RunImpl, 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // but I can't figure out a good way to do that with all the macros. 7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void GetBucketsForArgs(const ListValue* args, 7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BucketList* buckets) OVERRIDE { 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DictionaryValue* json; 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!args->GetDictionary(0, &json)) 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string parent_id; 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (json->HasKey(keys::kParentIdKey)) { 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!json->GetString(keys::kParentIdKey, &parent_id)) 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile_); 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 parent_id_int64; 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringToInt64(parent_id, &parent_id_int64); 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* parent = model->GetNodeByID(parent_id_int64); 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!parent) 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string bucket_id = UTF16ToUTF8(parent->GetTitle()); 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string title; 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json->GetString(keys::kTitleKey, &title); 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string url_string; 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) json->GetString(keys::kUrlKey, &url_string); 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bucket_id += title; 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bucket_id += url_string; 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 20 bytes (SHA1 hash length) is very likely less than most of the 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |bucket_id| strings we construct here, so we hash it to save space. 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buckets->push_back(GetBucket(base::SHA1HashString(bucket_id))); 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile_; 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Mapper for 'bookmarks.remove'. 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RemoveBookmarksBucketMapper : public BookmarkBucketMapper<std::string> { 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit RemoveBookmarksBucketMapper(Profile* profile) : profile_(profile) {} 7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void GetBucketsForArgs(const ListValue* args, 7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BucketList* buckets) OVERRIDE { 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::list<int64> IdList; 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IdList ids; 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool invalid_id = false; 7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!BookmarksRemoveFunction::ExtractIds(args, &ids, &invalid_id) || 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) invalid_id) { 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (IdList::iterator it = ids.begin(); it != ids.end(); ++it) { 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile_); 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = model->GetNodeByID(*it); 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node || node->is_root()) 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string bucket_id; 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bucket_id += UTF16ToUTF8(node->parent()->GetTitle()); 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bucket_id += UTF16ToUTF8(node->GetTitle()); 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bucket_id += node->url().spec(); 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buckets->push_back(GetBucket(base::SHA1HashString(bucket_id))); 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile_; 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Mapper for any bookmark function accepting bookmark IDs as parameters, where 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a distinct ID corresponds to a single item in terms of quota limiting. This 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is inappropriate for bookmarks.remove, for example, since repeated removals 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the same item will actually have a different ID each time. 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class FunctionType> 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BookmarkIdMapper : public BookmarkBucketMapper<int64> { 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::list<int64> IdList; 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void GetBucketsForArgs(const ListValue* args, BucketList* buckets) { 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IdList ids; 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool invalid_id = false; 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!FunctionType::ExtractIds(args, &ids, &invalid_id) || invalid_id) 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (IdList::iterator it = ids.begin(); it != ids.end(); ++it) 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buckets->push_back(GetBucket(*it)); 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Builds heuristics for all BookmarkFunctions using specialized BucketMappers. 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BookmarksQuotaLimitFactory { 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For id-based bookmark functions. 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template <class FunctionType> 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void Build(QuotaLimitHeuristics* heuristics) { 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BuildWithMappers(heuristics, new BookmarkIdMapper<FunctionType>(), 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new BookmarkIdMapper<FunctionType>()); 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For bookmarks.create. 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void BuildForCreate(QuotaLimitHeuristics* heuristics, 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile) { 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BuildWithMappers(heuristics, new CreateBookmarkBucketMapper(profile), 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new CreateBookmarkBucketMapper(profile)); 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For bookmarks.remove. 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void BuildForRemove(QuotaLimitHeuristics* heuristics, 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile) { 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BuildWithMappers(heuristics, new RemoveBookmarksBucketMapper(profile), 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new RemoveBookmarksBucketMapper(profile)); 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void BuildWithMappers(QuotaLimitHeuristics* heuristics, 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BucketMapper* short_mapper, BucketMapper* long_mapper) { 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Config kSustainedLimitConfig = { 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See bookmarks.json for current value. 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmarks::MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE, 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta::FromMinutes(1) 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heuristics->push_back(new SustainedLimit( 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta::FromMinutes(10), 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kSustainedLimitConfig, 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) short_mapper, 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE")); 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Config kTimedLimitConfig = { 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See bookmarks.json for current value. 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmarks::MAX_WRITE_OPERATIONS_PER_HOUR, 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta::FromHours(1) 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heuristics->push_back(new TimedLimit( 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kTimedLimitConfig, 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long_mapper, 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "MAX_WRITE_OPERATIONS_PER_HOUR")); 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_IMPLICIT_CONSTRUCTORS(BookmarksQuotaLimitFactory); 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// And finally, building the individual heuristics for each function. 8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksRemoveFunction::GetQuotaLimitHeuristics( 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QuotaLimitHeuristics* heuristics) const { 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarksQuotaLimitFactory::BuildForRemove(heuristics, profile()); 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksMoveFunction::GetQuotaLimitHeuristics( 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QuotaLimitHeuristics* heuristics) const { 8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BookmarksQuotaLimitFactory::Build<BookmarksMoveFunction>(heuristics); 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksUpdateFunction::GetQuotaLimitHeuristics( 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QuotaLimitHeuristics* heuristics) const { 8802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BookmarksQuotaLimitFactory::Build<BookmarksUpdateFunction>(heuristics); 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksCreateFunction::GetQuotaLimitHeuristics( 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QuotaLimitHeuristics* heuristics) const { 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarksQuotaLimitFactory::BuildForCreate(heuristics, profile()); 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarksIOFunction::BookmarksIOFunction() {} 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarksIOFunction::~BookmarksIOFunction() { 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There may be pending file dialogs, we need to tell them that we've gone 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // away so they don't try and call back to us. 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (select_file_dialog_.get()) 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) select_file_dialog_->ListenerDestroyed(); 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarksIOFunction::SelectFile(ui::SelectFileDialog::Type type) { 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GetDefaultFilepathForBookmarkExport() might have to touch the filesystem 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (stat or access, for example), so this requires a thread with IO allowed. 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) { 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&BookmarksIOFunction::SelectFile, this, type)); 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pre-populating the filename field in case this is a SELECT_SAVEAS_FILE 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dialog. If not, there is no filename field in the dialog box. 9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath default_path; 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == ui::SelectFileDialog::SELECT_SAVEAS_FILE) 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default_path = GetDefaultFilepathForBookmarkExport(); 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(type == ui::SelectFileDialog::SELECT_OPEN_FILE); 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // After getting the |default_path|, ask the UI to display the file dialog. 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&BookmarksIOFunction::ShowSelectFileDialog, this, 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type, default_path)); 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksIOFunction::ShowSelectFileDialog( 9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::SelectFileDialog::Type type, 9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& default_path) { 9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!dispatcher()) 9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; // Extension was unloaded. 9252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Balanced in one of the three callbacks of SelectFileDialog: 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // either FileSelectionCanceled, MultiFilesSelected, or FileSelected 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddRef(); 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* web_contents = dispatcher()->delegate()-> 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetAssociatedWebContents(); 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) select_file_dialog_ = ui::SelectFileDialog::Create( 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, new ChromeSelectFilePolicy(web_contents)); 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::SelectFileDialog::FileTypeInfo file_type_info; 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_type_info.extensions.resize(1); 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("html")); 9382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(kinaba): http://crbug.com/140425. Turn file_type_info.support_drive 9392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // on for saving once Google Drive client on ChromeOS supports it. 9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (type == ui::SelectFileDialog::SELECT_OPEN_FILE) 9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) file_type_info.support_drive = true; 9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |web_contents| can be NULL (for background pages), which is fine. In such 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a case if file-selection dialogs are forbidden by policy, we will not 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // show an InfoBar, which is better than letting one appear out of the blue. 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) select_file_dialog_->SelectFile(type, 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16(), 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default_path, 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &file_type_info, 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 950c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath::StringType(), 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL); 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarksIOFunction::FileSelectionCanceled(void* params) { 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Release(); // Balanced in BookmarksIOFunction::SelectFile() 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BookmarksIOFunction::MultiFilesSelected( 9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<base::FilePath>& files, void* params) { 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Release(); // Balanced in BookmarsIOFunction::SelectFile() 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Should not be able to select multiple files"; 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BookmarksImportFunction::RunImpl() { 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!EditBookmarksEnabled()) 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SelectFile(ui::SelectFileDialog::SELECT_OPEN_FILE); 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksImportFunction::FileSelected(const base::FilePath& path, 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index, 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* params) { 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_ANDROID) 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Android does not have support for the standard importers. 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(jgreenwald): remove ifdef once extensions are no longer built on 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Android. 979c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Deletes itself. 980c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ImporterHost* importer_host = new ImporterHost; 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) importer::SourceProfile source_profile; 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_profile.importer_type = importer::TYPE_BOOKMARKS_FILE; 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_profile.source_path = path; 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) importer_host->StartImportSettings(source_profile, 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile(), 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) importer::FAVORITES, 987c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new ProfileWriter(profile())); 988c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 989c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) importer::LogImporterUseToMetrics("BookmarksAPI", 990c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) importer::TYPE_BOOKMARKS_FILE); 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Release(); // Balanced in BookmarksIOFunction::SelectFile() 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool BookmarksExportFunction::RunImpl() { 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE); 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BookmarksExportFunction::FileSelected(const base::FilePath& path, 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index, 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* params) { 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_ANDROID) 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Android does not have support for the standard exporter. 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(jgreenwald): remove ifdef once extensions are no longer built on 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Android. 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_html_writer::WriteBookmarks(profile(), path, NULL); 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Release(); // Balanced in BookmarksIOFunction::SelectFile() 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace extensions 1013